From f58c80e2909301aec085e7ceaa813af3e29720d2 Mon Sep 17 00:00:00 2001 From: gitlost Date: Mon, 9 May 2022 19:50:50 +0100 Subject: [PATCH] Add multiple segments support for AZTEC, CODEONE, DATAMATRIX, DOTCODE, GRIDMATRIX, HANXIN, MAXICODE, MICROPDF417, PDF417, QRCODE, RMQR, ULTRA RMQR: fix ECI encoding (wrong bit length for indicator) MICROQR: check versions M1 and M2 for allowed characters so as to give better error messages DOTCODE: some small optimizations common.c: add is_chr(), segs_length(), segs_cpy() CODEONE/CODE128/DOTCODE/GRIDMATRIX/HANXIN/MAXICODE/QRCODE/ULTRA: add namespace prefixes to static funcs/data includes: use Z_ prefix, unuse double underscore prefixes (guard defines) manual.txt: compress some tables using double/treble column sets --- ChangeLog | 6 + backend/aztec.c | 216 +- backend/aztec.h | 13 +- backend/code1.c | 724 +++-- backend/code128.c | 17 +- backend/common.c | 100 +- backend/common.h | 47 +- backend/dmatrix.c | 301 +- backend/dotcode.c | 1365 ++++---- backend/eci.c | 57 + backend/eci.h | 16 +- backend/gb18030.c | 36 +- backend/gb18030.h | 9 +- backend/gb2312.c | 39 +- backend/gb2312.h | 19 +- backend/general_field.c | 7 +- backend/general_field.h | 10 +- backend/gridmtx.c | 279 +- backend/gridmtx.h | 36 +- backend/gs1.h | 10 +- backend/hanxin.c | 313 +- backend/hanxin.h | 20 +- backend/large.h | 10 +- backend/library.c | 423 ++- backend/maxicode.c | 344 ++- backend/pdf417.c | 135 +- backend/pdf417.h | 10 +- backend/pdf417_tabs.h | 10 +- backend/qr.c | 746 ++--- backend/qr.h | 45 +- backend/sjis.c | 37 +- backend/sjis.h | 19 +- backend/tests/test_2of5.c | 2 +- backend/tests/test_auspost.c | 7 +- backend/tests/test_aztec.c | 287 +- backend/tests/test_channel.c | 7 +- backend/tests/test_codablock.c | 7 +- backend/tests/test_code.c | 2 +- backend/tests/test_code1.c | 625 +++- backend/tests/test_code128.c | 6 +- backend/tests/test_code16k.c | 7 +- backend/tests/test_code49.c | 7 +- backend/tests/test_common.c | 174 +- backend/tests/test_composite.c | 19 +- backend/tests/test_dmatrix.c | 330 +- backend/tests/test_dotcode.c | 603 +++- backend/tests/test_eci.c | 194 +- backend/tests/test_gridmtx.c | 385 ++- backend/tests/test_gs1.c | 7 +- backend/tests/test_hanxin.c | 574 +++- backend/tests/test_imail.c | 7 +- backend/tests/test_library.c | 258 +- backend/tests/test_maxicode.c | 577 +++- backend/tests/test_medical.c | 2 +- backend/tests/test_pdf417.c | 379 ++- backend/tests/test_plessey.c | 7 +- backend/tests/test_postal.c | 7 +- backend/tests/test_qr.c | 2751 +++++++++++++---- backend/tests/test_rss.c | 4 +- backend/tests/test_telepen.c | 7 +- backend/tests/test_ultra.c | 265 +- backend/tests/test_upcean.c | 4 +- backend/tests/testcommon.c | 300 +- backend/tests/testcommon.h | 10 +- .../tests/tools/bwipp_dump-barcode.ps.diff | 56 +- backend/tests/tools/bwipp_dump.ps.tar.xz | Bin 124268 -> 124608 bytes backend/tests/tools/run_bwipp_tests.sh | 12 +- backend/tests/tools/run_zxingcpp_tests.sh | 12 + backend/ultra.c | 556 ++-- backend/zint.h | 37 +- backend_qt/qzint.cpp | 170 +- backend_qt/qzint.h | 46 +- backend_qt/tests/test_qzint.cpp | 81 +- backend_tcl/zint.c | 113 +- docs/manual.txt | 683 ++-- frontend/main.c | 102 +- frontend/tests/test_args.c | 80 + frontend_qt/main.cpp | 5 +- frontend_qt/mainWindow.ui | 1342 ++++++-- frontend_qt/mainwindow.cpp | 185 +- frontend_qt/mainwindow.h | 7 + 81 files changed, 12026 insertions(+), 4701 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2b77bd8e..1a62a730 100644 --- a/ChangeLog +++ b/ChangeLog @@ -61,6 +61,10 @@ Changes - HANXIN: removed alternating filler in function information - GRIDMATRIX/HANXIN/QRCODE/RMQR: warn if auto-conversion (i.e. no ECI given) occurs to resp. specialized char sets (GB 2312/GB 18030/Shift JIS) +- Add multiple segments support for AZTEC, CODEONE, DATAMATRIX, DOTCODE, + GRIDMATRIX, HANXIN, MAXICODE, MICROPDF417, PDF417, QRCODE, RMQR, ULTRA +- MICROQR: check versions M1 and M2 for allowed characters so as to give better + error messages Bugs ---- @@ -85,6 +89,8 @@ Bugs - DATAMATRIX: fix mis-encoding of FNC1/GS in EDIFACT in GS1 mode - Allow for dot overspill in height of vertical box sides (dotty mode) - HANXIN: fix gate-posts on codeword limits +- GUI: cater for HiDPI display, props bitaround (#257) +- RMQR: fix ECI encoding (wrong bit length for indicator) Version 2.10.0 2021-08-14 diff --git a/backend/aztec.c b/backend/aztec.c index 6729b2fb..d5466852 100644 --- a/backend/aztec.c +++ b/backend/aztec.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2009-2021 Robin Stuart + Copyright (C) 2009-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,7 +29,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include #include @@ -100,9 +99,10 @@ static int az_bin_append_posn(const int arg, const int length, char *binary, con } static int aztec_text_process(const unsigned char source[], int src_len, int bp, char binary_string[], const int gs1, - const int eci, int *data_length, const int debug_print) { + const int eci, char *p_current_mode, int *data_length, const int debug_print) { int i, j; + const char initial_mode = p_current_mode ? *p_current_mode : 'U'; char current_mode; int count; char next_mode; @@ -129,7 +129,7 @@ static int aztec_text_process(const unsigned char source[], int src_len, int bp, // Deal first with letter combinations which can be combined to one codeword // Combinations are (CR LF) (. SP) (, SP) (: SP) in Punct mode - current_mode = 'U'; + current_mode = initial_mode; for (i = 0; i + 1 < src_len; i++) { // Combination (CR LF) should always be in Punct mode if ((source[i] == 13) && (source[i + 1] == 10)) { @@ -230,7 +230,7 @@ static int aztec_text_process(const unsigned char source[], int src_len, int bp, reduced_length = j; - current_mode = 'U'; + current_mode = initial_mode; for (i = 0; i < reduced_length; i++) { // Resolve Carriage Return (CR) which can be Punct or Mixed mode if (reduced_source[i] == 13) { @@ -386,7 +386,7 @@ static int aztec_text_process(const unsigned char source[], int src_len, int bp, } // Decide when to use P/S instead of P/L and U/S instead of U/L - current_mode = 'U'; + current_mode = initial_mode; for (i = 0; i < reduced_length; i++) { if (reduced_encode_mode[i] != current_mode) { @@ -459,14 +459,14 @@ static int aztec_text_process(const unsigned char source[], int src_len, int bp, printf("%.*s\n", reduced_length, reduced_encode_mode); } - if (gs1) { + if (bp == 0 && gs1) { bp = bin_append_posn(0, 5, binary_string, bp); // P/S bp = bin_append_posn(0, 5, binary_string, bp); // FLG(n) bp = bin_append_posn(0, 3, binary_string, bp); // FLG(0) } if (eci != 0) { - bp = bin_append_posn(0, 5, binary_string, bp); // P/S + bp = bin_append_posn(0, initial_mode == 'D' ? 4 : 5, binary_string, bp); // P/S bp = bin_append_posn(0, 5, binary_string, bp); // FLG(n) if (eci < 10) { bp = bin_append_posn(1, 3, binary_string, bp); // FLG(1) @@ -504,7 +504,7 @@ static int aztec_text_process(const unsigned char source[], int src_len, int bp, } } - current_mode = 'U'; + current_mode = initial_mode; for (i = 0; i < reduced_length; i++) { if (reduced_encode_mode[i] != 'B') { @@ -516,124 +516,124 @@ static int aztec_text_process(const unsigned char source[], int src_len, int bp, if (current_mode == 'U') { switch (reduced_encode_mode[i]) { case 'L': - if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // L/L + if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return 0; // L/L break; case 'M': - if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // M/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return 0; // M/L break; case 'P': - if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // M/L - if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return 0; // M/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return 0; // P/L break; case 'p': - if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/S + if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return 0; // P/S break; case 'D': - if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // D/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return 0; // D/L break; case 'B': - if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // B/S + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return 0; // B/S break; } } else if (current_mode == 'L') { switch (reduced_encode_mode[i]) { case 'U': - if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // D/L - if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return 0; // D/L + if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return 0; // U/L break; case 'u': - if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/S + if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return 0; // U/S break; case 'M': - if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // M/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return 0; // M/L break; case 'P': - if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // M/L - if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return 0; // M/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return 0; // P/L break; case 'p': - if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/S + if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return 0; // P/S break; case 'D': - if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // D/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return 0; // D/L break; case 'B': - if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // B/S + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return 0; // B/S break; } } else if (current_mode == 'M') { switch (reduced_encode_mode[i]) { case 'U': - if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return 0; // U/L break; case 'L': - if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // L/L + if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return 0; // L/L break; case 'P': - if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return 0; // P/L break; case 'p': - if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/S + if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return 0; // P/S break; case 'D': - if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L - if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // D/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return 0; // U/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return 0; // D/L break; case 'B': - if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // B/S + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return 0; // B/S break; } } else if (current_mode == 'P') { switch (reduced_encode_mode[i]) { case 'U': - if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return 0; // U/L break; case 'L': - if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L - if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // L/L + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return 0; // U/L + if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return 0; // L/L break; case 'M': - if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L - if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // M/L + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return 0; // U/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return 0; // M/L break; case 'D': - if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L - if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // D/L + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return 0; // U/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return 0; // D/L break; case 'B': - if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return 0; // U/L current_mode = 'U'; - if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // B/S + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return 0; // B/S break; } } else if (current_mode == 'D') { switch (reduced_encode_mode[i]) { case 'U': - if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return 0; // U/L break; case 'u': - if (!(bp = az_bin_append_posn(15, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/S + if (!(bp = az_bin_append_posn(15, 4, binary_string, bp))) return 0; // U/S break; case 'L': - if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L - if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // L/L + if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return 0; // U/L + if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return 0; // L/L break; case 'M': - if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L - if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // M/L + if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return 0; // U/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return 0; // M/L break; case 'P': - if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L - if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // M/L - if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/L + if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return 0; // U/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return 0; // M/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return 0; // P/L break; case 'p': - if (!(bp = az_bin_append_posn(0, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/S + if (!(bp = az_bin_append_posn(0, 4, binary_string, bp))) return 0; // P/S break; case 'B': - if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return 0; // U/L current_mode = 'U'; - if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // B/S + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return 0; // B/S break; } } @@ -643,16 +643,16 @@ static int aztec_text_process(const unsigned char source[], int src_len, int bp, for (count = 0; ((i + count) < reduced_length) && (reduced_encode_mode[i + count] == 'B'); count++); if (count > 2079) { - return ZINT_ERROR_TOO_LONG; + return 0; } if (count > 31) { /* Put 00000 followed by 11-bit number of bytes less 31 */ - if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; - if (!(bp = az_bin_append_posn(count - 31, 11, binary_string, bp))) return ZINT_ERROR_TOO_LONG; + if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return 0; + if (!(bp = az_bin_append_posn(count - 31, 11, binary_string, bp))) return 0; } else { /* Put 5-bit number of bytes */ - if (!(bp = az_bin_append_posn(count, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; + if (!(bp = az_bin_append_posn(count, 5, binary_string, bp))) return 0; } byte_mode = 1; } @@ -665,73 +665,94 @@ static int aztec_text_process(const unsigned char source[], int src_len, int bp, if ((reduced_encode_mode[i] == 'U') || (reduced_encode_mode[i] == 'u')) { if (reduced_source[i] == ' ') { - if (!(bp = az_bin_append_posn(1, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // SP + if (!(bp = az_bin_append_posn(1, 5, binary_string, bp))) return 0; // SP } else { if (!(bp = az_bin_append_posn(AztecSymbolChar[(int) reduced_source[i]], 5, binary_string, bp))) - return ZINT_ERROR_TOO_LONG; + return 0; } } else if (reduced_encode_mode[i] == 'L') { if (reduced_source[i] == ' ') { - if (!(bp = az_bin_append_posn(1, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // SP + if (!(bp = az_bin_append_posn(1, 5, binary_string, bp))) return 0; // SP } else { if (!(bp = az_bin_append_posn(AztecSymbolChar[(int) reduced_source[i]], 5, binary_string, bp))) - return ZINT_ERROR_TOO_LONG; + return 0; } } else if (reduced_encode_mode[i] == 'M') { if (reduced_source[i] == ' ') { - if (!(bp = az_bin_append_posn(1, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // SP + if (!(bp = az_bin_append_posn(1, 5, binary_string, bp))) return 0; // SP } else if (reduced_source[i] == 13) { - if (!(bp = az_bin_append_posn(14, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // CR + if (!(bp = az_bin_append_posn(14, 5, binary_string, bp))) return 0; // CR } else { if (!(bp = az_bin_append_posn(AztecSymbolChar[(int) reduced_source[i]], 5, binary_string, bp))) - return ZINT_ERROR_TOO_LONG; + return 0; } } else if ((reduced_encode_mode[i] == 'P') || (reduced_encode_mode[i] == 'p')) { if (gs1 && (reduced_source[i] == '[')) { - if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // FLG(n) - if (!(bp = az_bin_append_posn(0, 3, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // FLG(0) = FNC1 + if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return 0; // FLG(n) + if (!(bp = az_bin_append_posn(0, 3, binary_string, bp))) return 0; // FLG(0) = FNC1 } else if (reduced_source[i] == 13) { - if (!(bp = az_bin_append_posn(1, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // CR + if (!(bp = az_bin_append_posn(1, 5, binary_string, bp))) return 0; // CR } else if (reduced_source[i] == 'a') { - if (!(bp = az_bin_append_posn(2, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // CR LF + if (!(bp = az_bin_append_posn(2, 5, binary_string, bp))) return 0; // CR LF } else if (reduced_source[i] == 'b') { - if (!(bp = az_bin_append_posn(3, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // . SP + if (!(bp = az_bin_append_posn(3, 5, binary_string, bp))) return 0; // . SP } else if (reduced_source[i] == 'c') { - if (!(bp = az_bin_append_posn(4, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // , SP + if (!(bp = az_bin_append_posn(4, 5, binary_string, bp))) return 0; // , SP } else if (reduced_source[i] == 'd') { - if (!(bp = az_bin_append_posn(5, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // : SP + if (!(bp = az_bin_append_posn(5, 5, binary_string, bp))) return 0; // : SP } else if (reduced_source[i] == ',') { - if (!(bp = az_bin_append_posn(17, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // Comma + if (!(bp = az_bin_append_posn(17, 5, binary_string, bp))) return 0; // Comma } else if (reduced_source[i] == '.') { - if (!(bp = az_bin_append_posn(19, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // Full stop + if (!(bp = az_bin_append_posn(19, 5, binary_string, bp))) return 0; // Full stop } else { if (!(bp = az_bin_append_posn(AztecSymbolChar[(int) reduced_source[i]], 5, binary_string, bp))) - return ZINT_ERROR_TOO_LONG; + return 0; } } else if (reduced_encode_mode[i] == 'D') { if (reduced_source[i] == ' ') { - if (!(bp = az_bin_append_posn(1, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // SP + if (!(bp = az_bin_append_posn(1, 4, binary_string, bp))) return 0; // SP } else if (reduced_source[i] == ',') { - if (!(bp = az_bin_append_posn(12, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // Comma + if (!(bp = az_bin_append_posn(12, 4, binary_string, bp))) return 0; // Comma } else if (reduced_source[i] == '.') { - if (!(bp = az_bin_append_posn(13, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // Full stop + if (!(bp = az_bin_append_posn(13, 4, binary_string, bp))) return 0; // Full stop } else { if (!(bp = az_bin_append_posn(AztecSymbolChar[(int) reduced_source[i]], 4, binary_string, bp))) - return ZINT_ERROR_TOO_LONG; + return 0; } } else if (reduced_encode_mode[i] == 'B') { - if (!(bp = az_bin_append_posn(reduced_source[i], 8, binary_string, bp))) return ZINT_ERROR_TOO_LONG; + if (!(bp = az_bin_append_posn(reduced_source[i], 8, binary_string, bp))) return 0; } } if (debug_print) { - printf("Binary String:\n"); - printf("%.*s\n", bp, binary_string); + printf("Binary String (%d): %.*s\n", bp, bp, binary_string); + } + + *data_length = bp; + if (p_current_mode) { + *p_current_mode = current_mode; + } + + return 1; +} + +/* Call `aztec_text_process()` for each segment */ +static int aztec_text_process_segs(struct zint_seg segs[], const int seg_count, int bp, char binary_string[], + const int gs1, int *data_length, const int debug_print) { + int i; + + char current_mode = 'U'; + + for (i = 0; i < seg_count; i++) { + if (!aztec_text_process(segs[i].source, segs[i].length, bp, binary_string, gs1, segs[i].eci, ¤t_mode, + &bp, debug_print)) { + return 0; + } } *data_length = bp; - return 0; + return 1; } /* Prevent data from obscuring reference grid */ @@ -819,7 +840,7 @@ static void az_populate_map(short AztecMap[], const int layers) { } } -INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], int length) { +INTERNAL int aztec(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { int x, y, i, j, p, data_blocks, ecc_blocks, layers, total_bits; char bit_pattern[AZTEC_MAP_POSN_MAX + 1]; /* Note AZTEC_MAP_POSN_MAX > AZTEC_BIN_CAPACITY */ /* To lessen stack usage, share binary_string buffer with bit_pattern, as accessed separately */ @@ -828,11 +849,13 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], int lengt char adjusted_string[AZTEC_MAX_CAPACITY]; short AztecMap[AZTEC_MAP_SIZE]; unsigned char desc_data[4], desc_ecc[6]; - int error_number, compact, data_length, data_maxsize, codeword_size, adjusted_length; - int remainder, padbits, count, gs1, adjustment_size; + int error_number = 0; + int compact, data_length, data_maxsize, codeword_size, adjusted_length; + int remainder, padbits, count, adjustment_size; int reader = 0; int comp_loop = 4; int bp = 0; + const int gs1 = (symbol->input_mode & 0x07) == GS1_MODE; const int debug_print = (symbol->debug & ZINT_DEBUG_PRINT); rs_t rs; rs_uint_t rs_uint; @@ -842,11 +865,6 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], int lengt unsigned int *ecc_part; #endif - if ((symbol->input_mode & 0x07) == GS1_MODE) { - gs1 = 1; - } else { - gs1 = 0; - } if (symbol->output_options & READER_INIT) { reader = 1; comp_loop = 1; @@ -895,16 +913,14 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], int lengt symbol->structapp.count, symbol->structapp.count, symbol->structapp.id, sa_src); } - (void) aztec_text_process(sa_src, sa_len, bp, binary_string, 0 /*gs1*/, 0 /*eci*/, &bp, debug_print); + (void) aztec_text_process(sa_src, sa_len, bp, binary_string, 0 /*gs1*/, 0 /*eci*/, NULL /*p_current_mode*/, + &bp, debug_print); /* Will be in U/L due to uppercase A-Z index/count indicators at end */ } - error_number = aztec_text_process(source, length, bp, binary_string, gs1, symbol->eci, &data_length, - debug_print); - - if (error_number != 0) { + if (!aztec_text_process_segs(segs, seg_count, bp, binary_string, gs1, &data_length, debug_print)) { strcpy(symbol->errtxt, "502: Input too long or too many extended ASCII characters"); - return error_number; + return ZINT_ERROR_TOO_LONG; } assert(data_length > 0); /* Suppress clang-tidy warning: clang-analyzer-core.UndefinedBinaryOperatorResult */ @@ -1409,7 +1425,7 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], int lengt for (y = offset; y < end_offset; y++) { int y_map = y * 27; for (x = offset; x < end_offset; x++) { - int map = CompactAztecMap[y_map + x]; + int map = AztecCompactMap[y_map + x]; if (map == 1) { set_module(symbol, y - offset, x - offset); } else if (map >= 2 && bit_pattern[map - 2] == '1') { @@ -1509,9 +1525,9 @@ INTERNAL int azrune(struct zint_symbol *symbol, unsigned char source[], int leng for (y = 8; y < 19; y++) { r = y * 27; for (x = 8; x < 19; x++) { - if (CompactAztecMap[r + x] == 1) { + if (AztecCompactMap[r + x] == 1) { set_module(symbol, y - 8, x - 8); - } else if (CompactAztecMap[r + x] && binary_string[CompactAztecMap[r + x] - 2000] == '1') { + } else if (AztecCompactMap[r + x] && binary_string[AztecCompactMap[r + x] - 2000] == '1') { set_module(symbol, y - 8, x - 8); } } @@ -1523,3 +1539,5 @@ INTERNAL int azrune(struct zint_symbol *symbol, unsigned char source[], int leng return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/aztec.h b/backend/aztec.h index 488f6a02..f791e089 100644 --- a/backend/aztec.h +++ b/backend/aztec.h @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2008-2021 Robin Stuart + Copyright (C) 2008-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,11 +29,11 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ -#ifndef __AZTEC_H -#define __AZTEC_H -static const short CompactAztecMap[] = { +#ifndef Z_AZTEC_H +#define Z_AZTEC_H + +static const short AztecCompactMap[] = { /* 27 x 27 data grid */ 609, 608, 411, 413, 415, 417, 419, 421, 423, 425, 427, 429, 431, 433, 435, 437, 439, 441, 443, 445, 447, 449, 451, 453, 455, 457, 459, // 0 607, 606, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458, // 1 @@ -164,4 +164,5 @@ static const short AztecMapGridYOffsets[] = { 27, 43, 59, 75, 91, 107, 123, 139 }; -#endif /* __AZTEC_H */ +/* vim: set ts=4 sw=4 et : */ +#endif /* Z_AZTEC_H */ diff --git a/backend/code1.c b/backend/code1.c index 6e36c067..057e6b7a 100644 --- a/backend/code1.c +++ b/backend/code1.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2009-2021 Robin Stuart + Copyright (C) 2009-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,7 +29,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "common.h" #include "code1.h" @@ -42,7 +41,7 @@ #endif /* Add solid bar */ -static void horiz(struct zint_symbol *symbol, const int row_no, const int full) { +static void c1_horiz(struct zint_symbol *symbol, const int row_no, const int full) { int i; if (full) { @@ -57,15 +56,15 @@ static void horiz(struct zint_symbol *symbol, const int row_no, const int full) } /* Central recognition pattern for Versions A-H */ -static void central_finder(struct zint_symbol *symbol, const int start_row, const int row_count, +static void c1_central_finder(struct zint_symbol *symbol, const int start_row, const int row_count, const int full_rows) { int i; for (i = 0; i < row_count; i++) { if (i < full_rows) { - horiz(symbol, start_row + (i * 2), 1); + c1_horiz(symbol, start_row + (i * 2), 1); } else { - horiz(symbol, start_row + (i * 2), 0); + c1_horiz(symbol, start_row + (i * 2), 0); if (i != row_count - 1) { set_module(symbol, start_row + (i * 2) + 1, 1); set_module(symbol, start_row + (i * 2) + 1, symbol->width - 2); @@ -75,7 +74,7 @@ static void central_finder(struct zint_symbol *symbol, const int start_row, cons } /* Add solid column */ -static void vert(struct zint_symbol *symbol, const int column, const int height, const int top) { +static void c1_vert(struct zint_symbol *symbol, const int column, const int height, const int top) { int i; if (top) { @@ -90,7 +89,7 @@ static void vert(struct zint_symbol *symbol, const int column, const int height, } /* Add bump to the right of the vertical recognition pattern column (Versions A-H) */ -static void spigot(struct zint_symbol *symbol, const int row_no) { +static void c1_spigot(struct zint_symbol *symbol, const int row_no) { int i; for (i = symbol->width - 1; i > 0; i--) { @@ -101,7 +100,7 @@ static void spigot(struct zint_symbol *symbol, const int row_no) { } /* Is basic (non-shifted) C40? */ -static int isc40(const unsigned char input) { +static int c1_isc40(const unsigned char input) { if ((input >= '0' && input <= '9') || (input >= 'A' && input <= 'Z') || input == ' ') { return 1; } @@ -109,7 +108,7 @@ static int isc40(const unsigned char input) { } /* Is basic (non-shifted) TEXT? */ -static int istext(const unsigned char input) { +static int c1_istext(const unsigned char input) { if ((input >= '0' && input <= '9') || (input >= 'a' && input <= 'z') || input == ' ') { return 1; } @@ -117,14 +116,14 @@ static int istext(const unsigned char input) { } /* Is basic (non-shifted) C40/TEXT? */ -static int isc40text(const int current_mode, const unsigned char input) { - return current_mode == C1_C40 ? isc40(input) : istext(input); +static int c1_isc40text(const int current_mode, const unsigned char input) { + return current_mode == C1_C40 ? c1_isc40(input) : c1_istext(input); } /* EDI characters are uppercase alphanumerics plus space plus EDI terminator (CR) plus 2 EDI separator chars */ -static int isedi(const unsigned char input) { +static int c1_isedi(const unsigned char input) { - if (isc40(input)) { + if (c1_isc40(input)) { return 1; } if (input == 13 || input == '*' || input == '>') { @@ -135,10 +134,10 @@ static int isedi(const unsigned char input) { } /* Whether Step Q4bi applies, i.e. if one of the 3 EDI terminator/separator chars appears before a non-EDI char */ -static int is_step_Q4bi_applicable(const unsigned char source[], const int sourcelen, const int position) { +static int c1_is_step_Q4bi_applicable(const unsigned char source[], const int length, const int position) { int i; - for (i = position; i < sourcelen && isedi(source[i]); i++) { + for (i = position; i < length && c1_isedi(source[i]); i++) { if (source[i] == 13 || source[i] == '*' || source[i] == '>') { return 1; } @@ -164,7 +163,7 @@ static int is_step_Q4bi_applicable(const unsigned char source[], const int sourc #define C1_MULT_CEIL(n) ((((n) + C1_MULT_MINUS_1) / C1_MULT) * C1_MULT) /* AIM USS Code One Annex D Steps J-R */ -static int c1_look_ahead_test(const unsigned char source[], const int sourcelen, const int position, +static int c1_look_ahead_test(const unsigned char source[], const int length, const int position, const int current_mode, const int gs1) { int ascii_count, c40_count, text_count, edi_count, byte_count; int ascii_rnded, c40_rnded, text_rnded, edi_rnded, byte_rnded; @@ -197,9 +196,9 @@ static int c1_look_ahead_test(const unsigned char source[], const int sourcelen, break; } - for (sp = position; sp < sourcelen; sp++) { - unsigned char c = source[sp]; - int is_extended = c & 0x80; + for (sp = position; sp < length; sp++) { + const unsigned char c = source[sp]; + const int is_extended = c & 0x80; /* Step L */ if ((c >= '0') && (c <= '9')) { @@ -213,7 +212,7 @@ static int c1_look_ahead_test(const unsigned char source[], const int sourcelen, } /* Step M */ - if (isc40(c)) { + if (c1_isc40(c)) { c40_count += C1_MULT_2_DIV_3; /* Step M1 */ } else if (is_extended) { c40_count += C1_MULT_8_DIV_3; /* Step M2 */ @@ -222,7 +221,7 @@ static int c1_look_ahead_test(const unsigned char source[], const int sourcelen, } /* Step N */ - if (istext(c)) { + if (c1_istext(c)) { text_count += C1_MULT_2_DIV_3; /* Step N1 */ } else if (is_extended) { text_count += C1_MULT_8_DIV_3; /* Step N2 */ @@ -231,7 +230,7 @@ static int c1_look_ahead_test(const unsigned char source[], const int sourcelen, } /* Step O */ - if (isedi(c)) { + if (c1_isedi(c)) { edi_count += C1_MULT_2_DIV_3; /* Step O1 */ } else if (is_extended) { edi_count += C1_MULT_13_DIV_3; /* Step O2 */ @@ -277,7 +276,7 @@ static int c1_look_ahead_test(const unsigned char source[], const int sourcelen, } if (c40_rnded == edi_rnded) { /* Step Q4b */ - if (is_step_Q4bi_applicable(source, sourcelen, sp + 1)) { + if (c1_is_step_Q4bi_applicable(source, length, sp + 1)) { return C1_EDI; /* Step Q4bi */ } return C1_C40; /* Step Q4bii */ @@ -315,18 +314,18 @@ static int c1_look_ahead_test(const unsigned char source[], const int sourcelen, } /* Whether can fit last character or characters in a single ASCII codeword */ -static int is_last_single_ascii(const unsigned char string[], const int length, const int sp) { - if (length - sp == 1 && string[sp] <= 127) { +static int c1_is_last_single_ascii(const unsigned char source[], const int length, const int sp) { + if (length - sp == 1 && source[sp] <= 127) { return 1; } - if (length - sp == 2 && is_twodigits(string, length, sp)) { + if (length - sp == 2 && is_twodigits(source, length, sp)) { return 1; } return 0; } /* Initialize number of digits array (taken from BWIPP) */ -static void set_num_digits(const unsigned char source[], const int length, int *num_digits) { +static void c1_set_num_digits(const unsigned char source[], const int length, int num_digits[]) { int i; for (i = length - 1; i >= 0; i--) { if (source[i] >= '0' && source[i] <= '9') { @@ -335,8 +334,8 @@ static void set_num_digits(const unsigned char source[], const int length, int * } } -/* Copy C40/TEXT/EDI triplets from buffer to target. Returns elements left in buffer (< 3) */ -static int cte_buffer_transfer(int cte_buffer[6], int cte_p, unsigned target[], int *p_tp) { +/* Copy C40/TEXT/EDI triplets from buffer to `target`. Returns elements left in buffer (< 3) */ +static int c1_cte_buffer_transfer(int cte_buffer[6], int cte_p, unsigned target[], int *p_tp) { int cte_i, cte_e; int tp = *p_tp; @@ -359,8 +358,8 @@ static int cte_buffer_transfer(int cte_buffer[6], int cte_p, unsigned target[], return cte_p; } -/* Copy DECIMAL bytes to target. Returns bits left in buffer (< 8) */ -static int decimal_binary_transfer(char decimal_binary[24], int db_p, unsigned int target[], int *p_tp) { +/* Copy DECIMAL bytes to `target`. Returns bits left in buffer (< 8) */ +static int c1_decimal_binary_transfer(char decimal_binary[24], int db_p, unsigned int target[], int *p_tp) { int b_i, b_e, p; int tp = *p_tp; @@ -388,14 +387,14 @@ static int decimal_binary_transfer(char decimal_binary[24], int db_p, unsigned i } /* Unlatch to ASCII from DECIMAL mode using 6 ones flag. DECIMAL binary buffer will be empty */ -static int decimal_unlatch(char decimal_binary[24], int db_p, unsigned int target[], int *p_tp, - const int decimal_count, const unsigned char *source, int *p_sp) { +static int c1_decimal_unlatch(char decimal_binary[24], int db_p, unsigned int target[], int *p_tp, + const int decimal_count, const unsigned char source[], int *p_sp) { int sp = *p_sp; int bits_left; db_p = bin_append_posn(63, 6, decimal_binary, db_p); /* Unlatch */ if (db_p >= 8) { - db_p = decimal_binary_transfer(decimal_binary, db_p, target, p_tp); + db_p = c1_decimal_binary_transfer(decimal_binary, db_p, target, p_tp); } bits_left = (8 - db_p) & 0x07; if (decimal_count >= 1 && bits_left >= 4) { @@ -404,7 +403,7 @@ static int decimal_unlatch(char decimal_binary[24], int db_p, unsigned int targe if (bits_left == 6) { db_p = bin_append_posn(1, 2, decimal_binary, db_p); } - (void) decimal_binary_transfer(decimal_binary, db_p, target, p_tp); + (void) c1_decimal_binary_transfer(decimal_binary, db_p, target, p_tp); } else if (bits_left) { if (bits_left >= 4) { @@ -413,7 +412,7 @@ static int decimal_unlatch(char decimal_binary[24], int db_p, unsigned int targe if (bits_left == 2 || bits_left == 6) { db_p = bin_append_posn(1, 2, decimal_binary, db_p); } - (void) decimal_binary_transfer(decimal_binary, db_p, target, p_tp); + (void) c1_decimal_binary_transfer(decimal_binary, db_p, target, p_tp); } *p_sp = sp; @@ -422,7 +421,7 @@ static int decimal_unlatch(char decimal_binary[24], int db_p, unsigned int targe } /* Number of codewords remaining in a particular version (may be negative) */ -static int codewords_remaining(struct zint_symbol *symbol, const int tp) { +static int c1_codewords_remaining(struct zint_symbol *symbol, const int tp) { int i; if (symbol->option_2 == 10) { /* Version T */ @@ -444,7 +443,7 @@ static int codewords_remaining(struct zint_symbol *symbol, const int tp) { } /* Number of C40/TEXT elements needed to encode `input` */ -static int c40text_cnt(const int current_mode, const int gs1, unsigned char input) { +static int c1_c40text_cnt(const int current_mode, const int gs1, unsigned char input) { int cnt; if (gs1 && input == '[') { @@ -459,7 +458,7 @@ static int c40text_cnt(const int current_mode, const int gs1, unsigned char inpu } /* Copy `source` to `eci_buf` with "\NNNNNN" ECI indicator at start and backslashes escaped */ -static void eci_escape(const int eci, unsigned char *source, const int length, unsigned char *eci_buf, +static void c1_eci_escape(const int eci, unsigned char source[], const int length, unsigned char eci_buf[], const int eci_length) { int i, j; @@ -475,10 +474,12 @@ static void eci_escape(const int eci, unsigned char *source, const int length, u } /* Convert to codewords */ -static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigned int target[], int length, - int *p_last_mode) { +static int c1_encode(struct zint_symbol *symbol, unsigned char source[], int length, const int eci, + const int seg_count, const int gs1, unsigned int target[], int *p_tp, int *p_last_mode) { int current_mode, next_mode; - int sp, tp, gs1, i; + int sp = 0; + int tp = *p_tp; + int i; int cte_buffer[6], cte_p = 0; /* C1_C40/TEXT/EDI buffer and index */ char decimal_binary[24]; /* C1_DECIMAL buffer */ int db_p = 0; @@ -493,69 +494,76 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne int *num_digits = (int *) _alloca(sizeof(int) * (eci_length + 1)); #endif - sp = 0; - tp = 0; memset(num_digits, 0, sizeof(int) * (eci_length + 1)); /* Step A */ current_mode = C1_ASCII; next_mode = C1_ASCII; - if ((symbol->input_mode & 0x07) == GS1_MODE) { - gs1 = 1; - } else { - gs1 = 0; - } - if (gs1) { - set_num_digits(source, length, num_digits); + if (gs1 && tp == 0) { + c1_set_num_digits(source, length, num_digits); if (length >= 15 && num_digits[0] >= 15) { target[tp++] = 236; /* FNC1 and change to Decimal */ next_mode = C1_DECIMAL; + if (debug_print) printf("FNC1Dec "); } else if (length >= 7 && num_digits[0] == length) { target[tp++] = 236; /* FNC1 and change to Decimal */ next_mode = C1_DECIMAL; + if (debug_print) printf("FNC1Dec "); } else { target[tp++] = 232; /* FNC1 */ + if (debug_print) printf("FNC1 "); } /* Note ignoring Structured Append and ECI if GS1 mode (up to caller to warn/error) */ } else { - if (symbol->structapp.count) { + if (symbol->structapp.count && tp == 0) { if (symbol->structapp.count < 16) { /* Group mode */ - if (symbol->eci && symbol->structapp.index == 1) { /* Initial pad indicator for 1st symbol only */ + if ((eci || seg_count > 1) && symbol->structapp.index == 1) { + /* Initial pad indicator for 1st symbol only */ target[tp++] = 129; /* Pad */ target[tp++] = 233; /* FNC2 */ target[tp++] = (symbol->structapp.index - 1) * 15 + (symbol->structapp.count - 1); target[tp++] = '\\' + 1; /* Escape char */ + if (debug_print) printf("SAGrp "); } else { target[tp++] = (symbol->structapp.index - 1) * 15 + (symbol->structapp.count - 1); target[tp++] = 233; /* FNC2 */ + if (debug_print) printf("FNC2 "); } } else { /* Extended Group mode */ - if (symbol->eci && symbol->structapp.index == 1) { /* Initial pad indicator for 1st symbol only */ + if ((eci || seg_count > 1) && symbol->structapp.index == 1) { + /* Initial pad indicator for 1st symbol only */ target[tp++] = 129; /* Pad */ target[tp++] = '\\' + 1; /* Escape char */ target[tp++] = 233; /* FNC2 */ target[tp++] = symbol->structapp.index; target[tp++] = symbol->structapp.count; + if (debug_print) printf("SAExGrp "); } else { target[tp++] = symbol->structapp.index; target[tp++] = symbol->structapp.count; target[tp++] = 233; /* FNC2 */ + if (debug_print) printf("FNC2 "); } } - if (symbol->eci) { - eci_escape(symbol->eci, source, length, eci_buf, eci_length); + if (eci) { + c1_eci_escape(eci, source, length, eci_buf, eci_length); + source = eci_buf; + length = eci_length; + } + } else if (eci || seg_count > 1) { + if (tp == 0) { + target[tp++] = 129; /* Pad */ + target[tp++] = '\\' + 1; /* Escape char */ + if (debug_print) printf("PADEsc "); + } + if (eci) { + c1_eci_escape(eci, source, length, eci_buf, eci_length); source = eci_buf; length = eci_length; } - } else if (symbol->eci) { - target[tp++] = 129; /* Pad */ - target[tp++] = '\\' + 1; /* Escape char */ - eci_escape(symbol->eci, source, length, eci_buf, eci_length); - source = eci_buf; - length = eci_length; } - set_num_digits(source, length, num_digits); + c1_set_num_digits(source, length, num_digits); } do { @@ -563,12 +571,16 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne /* Change mode */ switch (next_mode) { case C1_C40: target[tp++] = 230; + if (debug_print) printf("->C40 "); break; case C1_TEXT: target[tp++] = 239; + if (debug_print) printf("->Text "); break; case C1_EDI: target[tp++] = 238; + if (debug_print) printf("->EDI "); break; case C1_BYTE: target[tp++] = 231; + if (debug_print) printf("->Byte "); byte_start = tp; target[tp++] = 0; /* Byte count holder (may be expanded to 2 codewords) */ break; @@ -592,21 +604,22 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne if (next_mode == C1_ASCII) { if (is_twodigits(source, length, sp)) { - if (debug_print) printf("ASCII double-digits "); - /* Step B3 */ target[tp++] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130; + if (debug_print) printf("ASCDD(%.2s) ", source + sp); sp += 2; } else { if ((gs1) && (source[sp] == '[')) { if (length - (sp + 1) >= 15 && num_digits[sp + 1] >= 15) { /* Step B4 */ target[tp++] = 236; /* FNC1 and change to Decimal */ + if (debug_print) printf("FNC1 "); sp++; next_mode = C1_DECIMAL; } else if (length - (sp + 1) >= 7 && num_digits[sp + 1] == length - (sp + 1)) { /* Step B5 */ target[tp++] = 236; /* FNC1 and change to Decimal */ + if (debug_print) printf("FNC1 "); sp++; next_mode = C1_DECIMAL; } @@ -618,18 +631,21 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne next_mode = c1_look_ahead_test(source, length, sp, current_mode, gs1); if (next_mode == C1_ASCII) { - if (debug_print) printf("ASCII "); + if (debug_print) printf("ASC(%d) ", source[sp]); if (source[sp] & 0x80) { /* Step B7 */ target[tp++] = 235; /* FNC4 (Upper Shift) */ target[tp++] = (source[sp] - 128) + 1; + if (debug_print) printf("UpSh(%d) ", source[sp]); } else if ((gs1) && (source[sp] == '[')) { /* Step B8 */ target[tp++] = 232; /* FNC1 */ + if (debug_print) printf("FNC1 "); } else { /* Step B8 */ target[tp++] = source[sp] + 1; + if (debug_print) printf("ASC(%d) ", source[sp]); } sp++; } @@ -657,6 +673,7 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne if (next_mode != current_mode) { /* Step C/D1c */ target[tp++] = 255; /* Unlatch */ + if (debug_print) printf("Unlatch "); } else { /* Step C/D2 */ const char *ct_shift, *ct_value; @@ -688,7 +705,7 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne } if (cte_p >= 3) { - cte_p = cte_buffer_transfer(cte_buffer, cte_p, target, &tp); + cte_p = c1_cte_buffer_transfer(cte_buffer, cte_p, target, &tp); } sp++; } @@ -705,8 +722,8 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne } else if ((length - sp) >= 8 && num_digits[sp] == (length - sp)) { /* Step E1b */ next_mode = C1_ASCII; - } else if ((length - sp) < 3 || !isedi(source[sp]) || !isedi(source[sp + 1]) - || !isedi(source[sp + 2])) { + } else if ((length - sp) < 3 || !c1_isedi(source[sp]) || !c1_isedi(source[sp + 1]) + || !c1_isedi(source[sp + 2])) { /* Step E1c */ /* This ensures ASCII switch if don't have EDI triplet, so cte_p will be zero on loop exit */ next_mode = C1_ASCII; @@ -714,10 +731,11 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne } if (next_mode != C1_EDI) { - if (is_last_single_ascii(source, length, sp) && codewords_remaining(symbol, tp) == 1) { + if (c1_is_last_single_ascii(source, length, sp) && c1_codewords_remaining(symbol, tp) == 1) { /* No unlatch needed if data fits as ASCII in last data codeword */ } else { target[tp++] = 255; /* Unlatch */ + if (debug_print) printf("Unlatch "); } } else { /* Step E2 */ @@ -734,7 +752,7 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne } if (cte_p >= 3) { - cte_p = cte_buffer_transfer(cte_buffer, cte_p, target, &tp); + cte_p = c1_cte_buffer_transfer(cte_buffer, cte_p, target, &tp); } sp++; } @@ -742,22 +760,25 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne } else if (current_mode == C1_DECIMAL) { /* Step F - Decimal encodation */ - if (debug_print) printf("DECIMAL "); + if (debug_print) printf("DEC "); next_mode = C1_DECIMAL; if (length - sp < 3) { /* Step F1 */ - int bits_left = 8 - db_p; - int can_ascii = bits_left == 8 && is_last_single_ascii(source, length, sp); - if (codewords_remaining(symbol, tp) == 1 && (can_ascii || (num_digits[sp] == 1 && bits_left >= 4))) { + const int bits_left = 8 - db_p; + const int can_ascii = bits_left == 8 && c1_is_last_single_ascii(source, length, sp); + if (c1_codewords_remaining(symbol, tp) == 1 + && (can_ascii || (num_digits[sp] == 1 && bits_left >= 4))) { if (can_ascii) { /* Encode last character or last 2 digits as ASCII */ if (is_twodigits(source, length, sp)) { target[tp++] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130; + if (debug_print) printf("ASCDD(%.2s) ", source + sp); sp += 2; } else { target[tp++] = source[sp] + 1; + if (debug_print) printf("ASC(%d) ", source[sp]); sp++; } } else { @@ -767,10 +788,10 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne if (bits_left == 6) { db_p = bin_append_posn(1, 2, decimal_binary, db_p); } - db_p = decimal_binary_transfer(decimal_binary, db_p, target, &tp); + db_p = c1_decimal_binary_transfer(decimal_binary, db_p, target, &tp); } } else { - db_p = decimal_unlatch(decimal_binary, db_p, target, &tp, num_digits[sp], source, &sp); + db_p = c1_decimal_unlatch(decimal_binary, db_p, target, &tp, num_digits[sp], source, &sp); current_mode = C1_ASCII; /* Note need to set current_mode also in case exit loop */ } next_mode = C1_ASCII; @@ -778,7 +799,7 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne } else { if (num_digits[sp] < 3) { /* Step F2 */ - db_p = decimal_unlatch(decimal_binary, db_p, target, &tp, num_digits[sp], source, &sp); + db_p = c1_decimal_unlatch(decimal_binary, db_p, target, &tp, num_digits[sp], source, &sp); current_mode = next_mode = C1_ASCII; /* Note need to set current_mode also in case exit loop */ } else { /* Step F3 */ @@ -786,7 +807,7 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne int value = (100 * ctoi(source[sp])) + (10 * ctoi(source[sp + 1])) + ctoi(source[sp + 2]) + 1; db_p = bin_append_posn(value, 10, decimal_binary, db_p); if (db_p >= 8) { - db_p = decimal_binary_transfer(decimal_binary, db_p, target, &tp); + db_p = c1_decimal_binary_transfer(decimal_binary, db_p, target, &tp); } sp += 3; } @@ -816,7 +837,7 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne tp++; } } else { - if (debug_print) printf("BYTE "); + if (debug_print) printf("BYTE(%d) ", source[sp]); target[tp++] = source[sp]; sp++; @@ -837,10 +858,10 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne /* Empty buffers (note cte_buffer will be empty if current_mode C1_EDI) */ if (current_mode == C1_C40 || current_mode == C1_TEXT) { if (cte_p >= 1) { - int cws_remaining = codewords_remaining(symbol, tp); + const int cws_remaining = c1_codewords_remaining(symbol, tp); /* Note doing strict interpretation of spec here (same as BWIPP), as now also done in Data Matrix case */ - if (cws_remaining == 1 && cte_p == 1 && isc40text(current_mode, source[sp - 1])) { + if (cws_remaining == 1 && cte_p == 1 && c1_isc40text(current_mode, source[sp - 1])) { /* 2.2.2.2 "...except when a single symbol character is left at the end before the first error correction character. This single character is encoded in the ASCII code set." */ target[tp++] = source[sp - 1] + 1; /* As ASCII */ @@ -849,14 +870,14 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne /* 2.2.2.2 "Two characters may be encoded in C40 mode in the last two data symbol characters of the symbol as two C40 values followed by one of the C40 shift characters." */ cte_buffer[cte_p++] = 0; /* Shift 0 */ - cte_p = cte_buffer_transfer(cte_buffer, cte_p, target, &tp); + cte_p = c1_cte_buffer_transfer(cte_buffer, cte_p, target, &tp); } if (cte_p >= 1) { int cnt, total_cnt = 0; /* Backtrack to last complete triplet (same technique as BWIPP) */ while (sp > 0 && cte_p % 3) { sp--; - cnt = c40text_cnt(current_mode, gs1, source[sp]); + cnt = c1_c40text_cnt(current_mode, gs1, source[sp]); total_cnt += cnt; cte_p -= cnt; } @@ -884,12 +905,12 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne int bits_left; /* Finish Decimal mode and go back to ASCII unless only one codeword remaining */ - if (codewords_remaining(symbol, tp) > 1) { + if (c1_codewords_remaining(symbol, tp) > 1) { db_p = bin_append_posn(63, 6, decimal_binary, db_p); /* Unlatch */ } if (db_p >= 8) { - db_p = decimal_binary_transfer(decimal_binary, db_p, target, &tp); + db_p = c1_decimal_binary_transfer(decimal_binary, db_p, target, &tp); } bits_left = (8 - db_p) & 0x07; @@ -904,13 +925,13 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne db_p = bin_append_posn(1, 2, decimal_binary, db_p); } - (void) decimal_binary_transfer(decimal_binary, db_p, target, &tp); + (void) c1_decimal_binary_transfer(decimal_binary, db_p, target, &tp); } current_mode = C1_ASCII; } else if (current_mode == C1_BYTE) { /* Update byte field length unless no codewords remaining */ - if (codewords_remaining(symbol, tp) > 0) { + if (c1_codewords_remaining(symbol, tp) > 0) { int byte_count = tp - (byte_start + 1); if (byte_count <= 249) { target[byte_start] = byte_count; @@ -943,9 +964,22 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne return tp; } +/* Call `c1_encode()` for each segment */ +static int c1_encode_segs(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count, const int gs1, + unsigned int target[], int *p_last_mode) { + int i; + int tp = 0; + + for (i = 0; i < seg_count; i++) { + tp = c1_encode(symbol, segs[i].source, segs[i].length, segs[i].eci, seg_count, gs1, target, &tp, p_last_mode); + } + + return tp; +} + /* Set symbol from datagrid */ -static void block_copy(struct zint_symbol *symbol, char datagrid[136][120], const int start_row, const int start_col, - const int height, const int width, const int row_offset, const int col_offset) { +static void c1_block_copy(struct zint_symbol *symbol, char datagrid[136][120], const int start_row, + const int start_col, const int height, const int width, const int row_offset, const int col_offset) { int i, j; for (i = start_row; i < (start_row + height); i++) { @@ -957,14 +991,30 @@ static void block_copy(struct zint_symbol *symbol, char datagrid[136][120], cons } } -INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int length) { - int size = 1, i, j; +/* Get total length allowing for ECIs and escaping backslashes */ +static int c1_total_length_segs(struct zint_seg segs[], const int seg_count) { + int total_len = 0; + int i; + if (segs[0].eci || seg_count > 1) { + for (i = 0; i < seg_count; i++) { + total_len += segs[i].length + 7 + chr_cnt(segs[i].source, segs[i].length, '\\'); + } + } else { + total_len = segs[0].length; + } + + return total_len; +} + +INTERNAL int codeone(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { + int size = 1, i, j; char datagrid[136][120]; int row, col; int sub_version = 0; rs_t rs; int error_number = 0; + const int gs1 = (symbol->input_mode & 0x07) == GS1_MODE; const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; if ((symbol->option_2 < 0) || (symbol->option_2 > 10)) { @@ -977,7 +1027,7 @@ INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int len strcpy(symbol->errtxt, "714: Structured Append not available for Version S"); return ZINT_ERROR_INVALID_OPTION; } - if ((symbol->input_mode & 0x07) == GS1_MODE) { + if (gs1) { strcpy(symbol->errtxt, "710: Cannot have Structured Append and GS1 mode at the same time"); return ZINT_ERROR_INVALID_OPTION; } @@ -999,25 +1049,29 @@ INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int len /* Version S */ int codewords; large_int elreg; - unsigned int data[30], ecc[15]; + unsigned int target[30], ecc[15]; int block_width; - if (length > 18) { + if (seg_count > 1) { + strcpy(symbol->errtxt, "715: Multiple segments not supported for Version S"); + return ZINT_ERROR_INVALID_OPTION; + } + if (segs[0].length > 18) { strcpy(symbol->errtxt, "514: Input data too long for Version S"); return ZINT_ERROR_TOO_LONG; } - if (!is_sane(NEON_F, source, length)) { + if (!is_sane(NEON_F, segs[0].source, segs[0].length)) { strcpy(symbol->errtxt, "515: Invalid input data (Version S encodes numeric input only)"); return ZINT_ERROR_INVALID_DATA; } size = 9; - if (length <= 6) { + if (segs[0].length <= 6) { /* Version S-10 */ sub_version = 1; codewords = 4; block_width = 2; - } else if (length <= 12) { + } else if (segs[0].length <= 12) { /* Version S-20 */ sub_version = 2; codewords = 8; @@ -1034,37 +1088,37 @@ INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int len } /* Convert value plus one to binary */ - large_load_str_u64(&elreg, source, length); + large_load_str_u64(&elreg, segs[0].source, segs[0].length); large_add_u64(&elreg, 1); - large_uint_array(&elreg, data, codewords, 5 /*bits*/); + large_uint_array(&elreg, target, codewords, 5 /*bits*/); rs_init_gf(&rs, 0x25); rs_init_code(&rs, codewords, 0); - rs_encode_uint(&rs, codewords, data, ecc); + rs_encode_uint(&rs, codewords, target, ecc); for (i = 0; i < codewords; i++) { - data[i + codewords] = ecc[codewords - i - 1]; + target[i + codewords] = ecc[codewords - i - 1]; } if (debug_print) { printf("Codewords (%d): ", codewords); - for (i = 0; i < codewords * 2; i++) printf(" %d", (int) data[i]); + for (i = 0; i < codewords * 2; i++) printf(" %d", (int) target[i]); printf("\n"); } i = 0; for (row = 0; row < 2; row++) { for (col = 0; col < block_width; col++) { - datagrid[row * 2][col * 5] = data[i] & 0x10; - datagrid[row * 2][(col * 5) + 1] = data[i] & 0x08; - datagrid[row * 2][(col * 5) + 2] = data[i] & 0x04; - datagrid[(row * 2) + 1][col * 5] = data[i] & 0x02; - datagrid[(row * 2) + 1][(col * 5) + 1] = data[i] & 0x01; - datagrid[row * 2][(col * 5) + 3] = data[i + 1] & 0x10; - datagrid[row * 2][(col * 5) + 4] = data[i + 1] & 0x08; - datagrid[(row * 2) + 1][(col * 5) + 2] = data[i + 1] & 0x04; - datagrid[(row * 2) + 1][(col * 5) + 3] = data[i + 1] & 0x02; - datagrid[(row * 2) + 1][(col * 5) + 4] = data[i + 1] & 0x01; + datagrid[row * 2][col * 5] = target[i] & 0x10; + datagrid[row * 2][(col * 5) + 1] = target[i] & 0x08; + datagrid[row * 2][(col * 5) + 2] = target[i] & 0x04; + datagrid[(row * 2) + 1][col * 5] = target[i] & 0x02; + datagrid[(row * 2) + 1][(col * 5) + 1] = target[i] & 0x01; + datagrid[row * 2][(col * 5) + 3] = target[i + 1] & 0x10; + datagrid[row * 2][(col * 5) + 4] = target[i + 1] & 0x08; + datagrid[(row * 2) + 1][(col * 5) + 2] = target[i + 1] & 0x04; + datagrid[(row * 2) + 1][(col * 5) + 3] = target[i + 1] & 0x02; + datagrid[(row * 2) + 1][(col * 5) + 4] = target[i + 1] & 0x01; i += 2; } } @@ -1074,18 +1128,18 @@ INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int len } else if (symbol->option_2 == 10) { /* Version T */ - unsigned int data[90 + 2]; /* Allow for 90 BYTE mode (+ latch and byte count) */ + unsigned int target[90 + 2]; /* Allow for 90 BYTE mode (+ latch and byte count) */ unsigned int ecc[22]; int data_length; int data_cw, ecc_cw, block_width; int last_mode; - if (length > 90 || (symbol->eci && length + 7 + chr_cnt(source, length, '\\') > 90)) { + if (c1_total_length_segs(segs, seg_count) > 90) { strcpy(symbol->errtxt, "519: Input data too long for Version T"); return ZINT_ERROR_TOO_LONG; } - data_length = c1_encode(symbol, source, data, length, &last_mode); + data_length = c1_encode_segs(symbol, segs, seg_count, gs1, target, &last_mode); if (data_length == 0 || data_length > 38) { strcpy(symbol->errtxt, "516: Input data too long for Version T"); @@ -1118,39 +1172,39 @@ INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int len if (data_cw > data_length) { /* If did not finish in ASCII or BYTE mode, switch to ASCII */ if (last_mode != C1_ASCII && last_mode != C1_BYTE) { - data[data_length++] = 255; /* Unlatch */ + target[data_length++] = 255; /* Unlatch */ } for (i = data_length; i < data_cw; i++) { - data[i] = 129; /* Pad */ + target[i] = 129; /* Pad */ } } /* Calculate error correction data */ rs_init_gf(&rs, 0x12d); rs_init_code(&rs, ecc_cw, 0); - rs_encode_uint(&rs, data_cw, data, ecc); + rs_encode_uint(&rs, data_cw, target, ecc); for (i = 0; i < ecc_cw; i++) { - data[data_cw + i] = ecc[ecc_cw - i - 1]; + target[data_cw + i] = ecc[ecc_cw - i - 1]; } if (debug_print) { printf("Codewords (%d):", data_cw + ecc_cw); - for (i = 0; i < data_cw + ecc_cw; i++) printf(" %d", (int) data[i]); + for (i = 0; i < data_cw + ecc_cw; i++) printf(" %d", (int) target[i]); printf("\n"); } i = 0; for (row = 0; row < 5; row++) { for (col = 0; col < block_width; col++) { - datagrid[row * 2][col * 4] = data[i] & 0x80; - datagrid[row * 2][(col * 4) + 1] = data[i] & 0x40; - datagrid[row * 2][(col * 4) + 2] = data[i] & 0x20; - datagrid[row * 2][(col * 4) + 3] = data[i] & 0x10; - datagrid[(row * 2) + 1][col * 4] = data[i] & 0x08; - datagrid[(row * 2) + 1][(col * 4) + 1] = data[i] & 0x04; - datagrid[(row * 2) + 1][(col * 4) + 2] = data[i] & 0x02; - datagrid[(row * 2) + 1][(col * 4) + 3] = data[i] & 0x01; + datagrid[row * 2][col * 4] = target[i] & 0x80; + datagrid[row * 2][(col * 4) + 1] = target[i] & 0x40; + datagrid[row * 2][(col * 4) + 2] = target[i] & 0x20; + datagrid[row * 2][(col * 4) + 3] = target[i] & 0x10; + datagrid[(row * 2) + 1][col * 4] = target[i] & 0x08; + datagrid[(row * 2) + 1][(col * 4) + 1] = target[i] & 0x04; + datagrid[(row * 2) + 1][(col * 4) + 2] = target[i] & 0x02; + datagrid[(row * 2) + 1][(col * 4) + 3] = target[i] & 0x01; i++; } } @@ -1160,14 +1214,14 @@ INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int len } else { /* Versions A to H */ - unsigned int data[1480 + 560]; + unsigned int target[1480 + 560]; unsigned int sub_data[185], sub_ecc[70]; int data_length; int data_cw; int blocks, data_blocks, ecc_blocks, ecc_length; int last_mode; - data_length = c1_encode(symbol, source, data, length, &last_mode); + data_length = c1_encode_segs(symbol, segs, seg_count, gs1, target, &last_mode); if (data_length == 0) { strcpy(symbol->errtxt, "517: Input data is too long"); @@ -1194,13 +1248,13 @@ INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int len if (data_cw > data_length) { /* If did not finish in ASCII or BYTE mode, switch to ASCII */ if (last_mode != C1_ASCII && last_mode != C1_BYTE) { - data[data_length++] = 255; /* Unlatch */ + target[data_length++] = 255; /* Unlatch */ } if (debug_print) { printf("Padding: %d\n", data_cw - data_length); } for (i = data_length; i < data_cw; i++) { - data[i] = 129; /* Pad */ + target[i] = 129; /* Pad */ } } else if (debug_print) { printf("No padding\n"); @@ -1216,31 +1270,31 @@ INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int len rs_init_code(&rs, ecc_blocks, 0); for (i = 0; i < blocks; i++) { for (j = 0; j < data_blocks; j++) { - sub_data[j] = data[j * blocks + i]; + sub_data[j] = target[j * blocks + i]; } rs_encode_uint(&rs, data_blocks, sub_data, sub_ecc); for (j = 0; j < ecc_blocks; j++) { - data[data_cw + j * blocks + i] = sub_ecc[ecc_blocks - 1 - j]; + target[data_cw + j * blocks + i] = sub_ecc[ecc_blocks - 1 - j]; } } if (debug_print) { printf("Codewords (%d):", data_cw + ecc_length); - for (i = 0; i < data_cw + ecc_length; i++) printf(" %d", (int) data[i]); + for (i = 0; i < data_cw + ecc_length; i++) printf(" %d", (int) target[i]); printf("\n"); } i = 0; for (row = 0; row < c1_grid_height[size - 1]; row++) { for (col = 0; col < c1_grid_width[size - 1]; col++) { - datagrid[row * 2][col * 4] = data[i] & 0x80; - datagrid[row * 2][(col * 4) + 1] = data[i] & 0x40; - datagrid[row * 2][(col * 4) + 2] = data[i] & 0x20; - datagrid[row * 2][(col * 4) + 3] = data[i] & 0x10; - datagrid[(row * 2) + 1][col * 4] = data[i] & 0x08; - datagrid[(row * 2) + 1][(col * 4) + 1] = data[i] & 0x04; - datagrid[(row * 2) + 1][(col * 4) + 2] = data[i] & 0x02; - datagrid[(row * 2) + 1][(col * 4) + 3] = data[i] & 0x01; + datagrid[row * 2][col * 4] = target[i] & 0x80; + datagrid[row * 2][(col * 4) + 1] = target[i] & 0x40; + datagrid[row * 2][(col * 4) + 2] = target[i] & 0x20; + datagrid[row * 2][(col * 4) + 3] = target[i] & 0x10; + datagrid[(row * 2) + 1][col * 4] = target[i] & 0x08; + datagrid[(row * 2) + 1][(col * 4) + 1] = target[i] & 0x04; + datagrid[(row * 2) + 1][(col * 4) + 2] = target[i] & 0x02; + datagrid[(row * 2) + 1][(col * 4) + 3] = target[i] & 0x01; i++; } } @@ -1255,194 +1309,194 @@ INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int len switch (size) { case 1: /* Version A */ - central_finder(symbol, 6, 3, 1); - vert(symbol, 4, 6, 1); - vert(symbol, 12, 5, 0); + c1_central_finder(symbol, 6, 3, 1); + c1_vert(symbol, 4, 6, 1); + c1_vert(symbol, 12, 5, 0); set_module(symbol, 5, 12); - spigot(symbol, 0); - spigot(symbol, 15); - block_copy(symbol, datagrid, 0, 0, 5, 4, 0, 0); - block_copy(symbol, datagrid, 0, 4, 5, 12, 0, 2); - block_copy(symbol, datagrid, 5, 0, 5, 12, 6, 0); - block_copy(symbol, datagrid, 5, 12, 5, 4, 6, 2); + c1_spigot(symbol, 0); + c1_spigot(symbol, 15); + c1_block_copy(symbol, datagrid, 0, 0, 5, 4, 0, 0); + c1_block_copy(symbol, datagrid, 0, 4, 5, 12, 0, 2); + c1_block_copy(symbol, datagrid, 5, 0, 5, 12, 6, 0); + c1_block_copy(symbol, datagrid, 5, 12, 5, 4, 6, 2); break; case 2: /* Version B */ - central_finder(symbol, 8, 4, 1); - vert(symbol, 4, 8, 1); - vert(symbol, 16, 7, 0); + c1_central_finder(symbol, 8, 4, 1); + c1_vert(symbol, 4, 8, 1); + c1_vert(symbol, 16, 7, 0); set_module(symbol, 7, 16); - spigot(symbol, 0); - spigot(symbol, 21); - block_copy(symbol, datagrid, 0, 0, 7, 4, 0, 0); - block_copy(symbol, datagrid, 0, 4, 7, 16, 0, 2); - block_copy(symbol, datagrid, 7, 0, 7, 16, 8, 0); - block_copy(symbol, datagrid, 7, 16, 7, 4, 8, 2); + c1_spigot(symbol, 0); + c1_spigot(symbol, 21); + c1_block_copy(symbol, datagrid, 0, 0, 7, 4, 0, 0); + c1_block_copy(symbol, datagrid, 0, 4, 7, 16, 0, 2); + c1_block_copy(symbol, datagrid, 7, 0, 7, 16, 8, 0); + c1_block_copy(symbol, datagrid, 7, 16, 7, 4, 8, 2); break; case 3: /* Version C */ - central_finder(symbol, 11, 4, 2); - vert(symbol, 4, 11, 1); - vert(symbol, 26, 13, 1); - vert(symbol, 4, 10, 0); - vert(symbol, 26, 10, 0); - spigot(symbol, 0); - spigot(symbol, 27); - block_copy(symbol, datagrid, 0, 0, 10, 4, 0, 0); - block_copy(symbol, datagrid, 0, 4, 10, 20, 0, 2); - block_copy(symbol, datagrid, 0, 24, 10, 4, 0, 4); - block_copy(symbol, datagrid, 10, 0, 10, 4, 8, 0); - block_copy(symbol, datagrid, 10, 4, 10, 20, 8, 2); - block_copy(symbol, datagrid, 10, 24, 10, 4, 8, 4); + c1_central_finder(symbol, 11, 4, 2); + c1_vert(symbol, 4, 11, 1); + c1_vert(symbol, 26, 13, 1); + c1_vert(symbol, 4, 10, 0); + c1_vert(symbol, 26, 10, 0); + c1_spigot(symbol, 0); + c1_spigot(symbol, 27); + c1_block_copy(symbol, datagrid, 0, 0, 10, 4, 0, 0); + c1_block_copy(symbol, datagrid, 0, 4, 10, 20, 0, 2); + c1_block_copy(symbol, datagrid, 0, 24, 10, 4, 0, 4); + c1_block_copy(symbol, datagrid, 10, 0, 10, 4, 8, 0); + c1_block_copy(symbol, datagrid, 10, 4, 10, 20, 8, 2); + c1_block_copy(symbol, datagrid, 10, 24, 10, 4, 8, 4); break; case 4: /* Version D */ - central_finder(symbol, 16, 5, 1); - vert(symbol, 4, 16, 1); - vert(symbol, 20, 16, 1); - vert(symbol, 36, 16, 1); - vert(symbol, 4, 15, 0); - vert(symbol, 20, 15, 0); - vert(symbol, 36, 15, 0); - spigot(symbol, 0); - spigot(symbol, 12); - spigot(symbol, 27); - spigot(symbol, 39); - block_copy(symbol, datagrid, 0, 0, 15, 4, 0, 0); - block_copy(symbol, datagrid, 0, 4, 15, 14, 0, 2); - block_copy(symbol, datagrid, 0, 18, 15, 14, 0, 4); - block_copy(symbol, datagrid, 0, 32, 15, 4, 0, 6); - block_copy(symbol, datagrid, 15, 0, 15, 4, 10, 0); - block_copy(symbol, datagrid, 15, 4, 15, 14, 10, 2); - block_copy(symbol, datagrid, 15, 18, 15, 14, 10, 4); - block_copy(symbol, datagrid, 15, 32, 15, 4, 10, 6); + c1_central_finder(symbol, 16, 5, 1); + c1_vert(symbol, 4, 16, 1); + c1_vert(symbol, 20, 16, 1); + c1_vert(symbol, 36, 16, 1); + c1_vert(symbol, 4, 15, 0); + c1_vert(symbol, 20, 15, 0); + c1_vert(symbol, 36, 15, 0); + c1_spigot(symbol, 0); + c1_spigot(symbol, 12); + c1_spigot(symbol, 27); + c1_spigot(symbol, 39); + c1_block_copy(symbol, datagrid, 0, 0, 15, 4, 0, 0); + c1_block_copy(symbol, datagrid, 0, 4, 15, 14, 0, 2); + c1_block_copy(symbol, datagrid, 0, 18, 15, 14, 0, 4); + c1_block_copy(symbol, datagrid, 0, 32, 15, 4, 0, 6); + c1_block_copy(symbol, datagrid, 15, 0, 15, 4, 10, 0); + c1_block_copy(symbol, datagrid, 15, 4, 15, 14, 10, 2); + c1_block_copy(symbol, datagrid, 15, 18, 15, 14, 10, 4); + c1_block_copy(symbol, datagrid, 15, 32, 15, 4, 10, 6); break; case 5: /* Version E */ - central_finder(symbol, 22, 5, 2); - vert(symbol, 4, 22, 1); - vert(symbol, 26, 24, 1); - vert(symbol, 48, 22, 1); - vert(symbol, 4, 21, 0); - vert(symbol, 26, 21, 0); - vert(symbol, 48, 21, 0); - spigot(symbol, 0); - spigot(symbol, 12); - spigot(symbol, 39); - spigot(symbol, 51); - block_copy(symbol, datagrid, 0, 0, 21, 4, 0, 0); - block_copy(symbol, datagrid, 0, 4, 21, 20, 0, 2); - block_copy(symbol, datagrid, 0, 24, 21, 20, 0, 4); - block_copy(symbol, datagrid, 0, 44, 21, 4, 0, 6); - block_copy(symbol, datagrid, 21, 0, 21, 4, 10, 0); - block_copy(symbol, datagrid, 21, 4, 21, 20, 10, 2); - block_copy(symbol, datagrid, 21, 24, 21, 20, 10, 4); - block_copy(symbol, datagrid, 21, 44, 21, 4, 10, 6); + c1_central_finder(symbol, 22, 5, 2); + c1_vert(symbol, 4, 22, 1); + c1_vert(symbol, 26, 24, 1); + c1_vert(symbol, 48, 22, 1); + c1_vert(symbol, 4, 21, 0); + c1_vert(symbol, 26, 21, 0); + c1_vert(symbol, 48, 21, 0); + c1_spigot(symbol, 0); + c1_spigot(symbol, 12); + c1_spigot(symbol, 39); + c1_spigot(symbol, 51); + c1_block_copy(symbol, datagrid, 0, 0, 21, 4, 0, 0); + c1_block_copy(symbol, datagrid, 0, 4, 21, 20, 0, 2); + c1_block_copy(symbol, datagrid, 0, 24, 21, 20, 0, 4); + c1_block_copy(symbol, datagrid, 0, 44, 21, 4, 0, 6); + c1_block_copy(symbol, datagrid, 21, 0, 21, 4, 10, 0); + c1_block_copy(symbol, datagrid, 21, 4, 21, 20, 10, 2); + c1_block_copy(symbol, datagrid, 21, 24, 21, 20, 10, 4); + c1_block_copy(symbol, datagrid, 21, 44, 21, 4, 10, 6); break; case 6: /* Version F */ - central_finder(symbol, 31, 5, 3); - vert(symbol, 4, 31, 1); - vert(symbol, 26, 35, 1); - vert(symbol, 48, 31, 1); - vert(symbol, 70, 35, 1); - vert(symbol, 4, 30, 0); - vert(symbol, 26, 30, 0); - vert(symbol, 48, 30, 0); - vert(symbol, 70, 30, 0); - spigot(symbol, 0); - spigot(symbol, 12); - spigot(symbol, 24); - spigot(symbol, 45); - spigot(symbol, 57); - spigot(symbol, 69); - block_copy(symbol, datagrid, 0, 0, 30, 4, 0, 0); - block_copy(symbol, datagrid, 0, 4, 30, 20, 0, 2); - block_copy(symbol, datagrid, 0, 24, 30, 20, 0, 4); - block_copy(symbol, datagrid, 0, 44, 30, 20, 0, 6); - block_copy(symbol, datagrid, 0, 64, 30, 4, 0, 8); - block_copy(symbol, datagrid, 30, 0, 30, 4, 10, 0); - block_copy(symbol, datagrid, 30, 4, 30, 20, 10, 2); - block_copy(symbol, datagrid, 30, 24, 30, 20, 10, 4); - block_copy(symbol, datagrid, 30, 44, 30, 20, 10, 6); - block_copy(symbol, datagrid, 30, 64, 30, 4, 10, 8); + c1_central_finder(symbol, 31, 5, 3); + c1_vert(symbol, 4, 31, 1); + c1_vert(symbol, 26, 35, 1); + c1_vert(symbol, 48, 31, 1); + c1_vert(symbol, 70, 35, 1); + c1_vert(symbol, 4, 30, 0); + c1_vert(symbol, 26, 30, 0); + c1_vert(symbol, 48, 30, 0); + c1_vert(symbol, 70, 30, 0); + c1_spigot(symbol, 0); + c1_spigot(symbol, 12); + c1_spigot(symbol, 24); + c1_spigot(symbol, 45); + c1_spigot(symbol, 57); + c1_spigot(symbol, 69); + c1_block_copy(symbol, datagrid, 0, 0, 30, 4, 0, 0); + c1_block_copy(symbol, datagrid, 0, 4, 30, 20, 0, 2); + c1_block_copy(symbol, datagrid, 0, 24, 30, 20, 0, 4); + c1_block_copy(symbol, datagrid, 0, 44, 30, 20, 0, 6); + c1_block_copy(symbol, datagrid, 0, 64, 30, 4, 0, 8); + c1_block_copy(symbol, datagrid, 30, 0, 30, 4, 10, 0); + c1_block_copy(symbol, datagrid, 30, 4, 30, 20, 10, 2); + c1_block_copy(symbol, datagrid, 30, 24, 30, 20, 10, 4); + c1_block_copy(symbol, datagrid, 30, 44, 30, 20, 10, 6); + c1_block_copy(symbol, datagrid, 30, 64, 30, 4, 10, 8); break; case 7: /* Version G */ - central_finder(symbol, 47, 6, 2); - vert(symbol, 6, 47, 1); - vert(symbol, 27, 49, 1); - vert(symbol, 48, 47, 1); - vert(symbol, 69, 49, 1); - vert(symbol, 90, 47, 1); - vert(symbol, 6, 46, 0); - vert(symbol, 27, 46, 0); - vert(symbol, 48, 46, 0); - vert(symbol, 69, 46, 0); - vert(symbol, 90, 46, 0); - spigot(symbol, 0); - spigot(symbol, 12); - spigot(symbol, 24); - spigot(symbol, 36); - spigot(symbol, 67); - spigot(symbol, 79); - spigot(symbol, 91); - spigot(symbol, 103); - block_copy(symbol, datagrid, 0, 0, 46, 6, 0, 0); - block_copy(symbol, datagrid, 0, 6, 46, 19, 0, 2); - block_copy(symbol, datagrid, 0, 25, 46, 19, 0, 4); - block_copy(symbol, datagrid, 0, 44, 46, 19, 0, 6); - block_copy(symbol, datagrid, 0, 63, 46, 19, 0, 8); - block_copy(symbol, datagrid, 0, 82, 46, 6, 0, 10); - block_copy(symbol, datagrid, 46, 0, 46, 6, 12, 0); - block_copy(symbol, datagrid, 46, 6, 46, 19, 12, 2); - block_copy(symbol, datagrid, 46, 25, 46, 19, 12, 4); - block_copy(symbol, datagrid, 46, 44, 46, 19, 12, 6); - block_copy(symbol, datagrid, 46, 63, 46, 19, 12, 8); - block_copy(symbol, datagrid, 46, 82, 46, 6, 12, 10); + c1_central_finder(symbol, 47, 6, 2); + c1_vert(symbol, 6, 47, 1); + c1_vert(symbol, 27, 49, 1); + c1_vert(symbol, 48, 47, 1); + c1_vert(symbol, 69, 49, 1); + c1_vert(symbol, 90, 47, 1); + c1_vert(symbol, 6, 46, 0); + c1_vert(symbol, 27, 46, 0); + c1_vert(symbol, 48, 46, 0); + c1_vert(symbol, 69, 46, 0); + c1_vert(symbol, 90, 46, 0); + c1_spigot(symbol, 0); + c1_spigot(symbol, 12); + c1_spigot(symbol, 24); + c1_spigot(symbol, 36); + c1_spigot(symbol, 67); + c1_spigot(symbol, 79); + c1_spigot(symbol, 91); + c1_spigot(symbol, 103); + c1_block_copy(symbol, datagrid, 0, 0, 46, 6, 0, 0); + c1_block_copy(symbol, datagrid, 0, 6, 46, 19, 0, 2); + c1_block_copy(symbol, datagrid, 0, 25, 46, 19, 0, 4); + c1_block_copy(symbol, datagrid, 0, 44, 46, 19, 0, 6); + c1_block_copy(symbol, datagrid, 0, 63, 46, 19, 0, 8); + c1_block_copy(symbol, datagrid, 0, 82, 46, 6, 0, 10); + c1_block_copy(symbol, datagrid, 46, 0, 46, 6, 12, 0); + c1_block_copy(symbol, datagrid, 46, 6, 46, 19, 12, 2); + c1_block_copy(symbol, datagrid, 46, 25, 46, 19, 12, 4); + c1_block_copy(symbol, datagrid, 46, 44, 46, 19, 12, 6); + c1_block_copy(symbol, datagrid, 46, 63, 46, 19, 12, 8); + c1_block_copy(symbol, datagrid, 46, 82, 46, 6, 12, 10); break; case 8: /* Version H */ - central_finder(symbol, 69, 6, 3); - vert(symbol, 6, 69, 1); - vert(symbol, 26, 73, 1); - vert(symbol, 46, 69, 1); - vert(symbol, 66, 73, 1); - vert(symbol, 86, 69, 1); - vert(symbol, 106, 73, 1); - vert(symbol, 126, 69, 1); - vert(symbol, 6, 68, 0); - vert(symbol, 26, 68, 0); - vert(symbol, 46, 68, 0); - vert(symbol, 66, 68, 0); - vert(symbol, 86, 68, 0); - vert(symbol, 106, 68, 0); - vert(symbol, 126, 68, 0); - spigot(symbol, 0); - spigot(symbol, 12); - spigot(symbol, 24); - spigot(symbol, 36); - spigot(symbol, 48); - spigot(symbol, 60); - spigot(symbol, 87); - spigot(symbol, 99); - spigot(symbol, 111); - spigot(symbol, 123); - spigot(symbol, 135); - spigot(symbol, 147); - block_copy(symbol, datagrid, 0, 0, 68, 6, 0, 0); - block_copy(symbol, datagrid, 0, 6, 68, 18, 0, 2); - block_copy(symbol, datagrid, 0, 24, 68, 18, 0, 4); - block_copy(symbol, datagrid, 0, 42, 68, 18, 0, 6); - block_copy(symbol, datagrid, 0, 60, 68, 18, 0, 8); - block_copy(symbol, datagrid, 0, 78, 68, 18, 0, 10); - block_copy(symbol, datagrid, 0, 96, 68, 18, 0, 12); - block_copy(symbol, datagrid, 0, 114, 68, 6, 0, 14); - block_copy(symbol, datagrid, 68, 0, 68, 6, 12, 0); - block_copy(symbol, datagrid, 68, 6, 68, 18, 12, 2); - block_copy(symbol, datagrid, 68, 24, 68, 18, 12, 4); - block_copy(symbol, datagrid, 68, 42, 68, 18, 12, 6); - block_copy(symbol, datagrid, 68, 60, 68, 18, 12, 8); - block_copy(symbol, datagrid, 68, 78, 68, 18, 12, 10); - block_copy(symbol, datagrid, 68, 96, 68, 18, 12, 12); - block_copy(symbol, datagrid, 68, 114, 68, 6, 12, 14); + c1_central_finder(symbol, 69, 6, 3); + c1_vert(symbol, 6, 69, 1); + c1_vert(symbol, 26, 73, 1); + c1_vert(symbol, 46, 69, 1); + c1_vert(symbol, 66, 73, 1); + c1_vert(symbol, 86, 69, 1); + c1_vert(symbol, 106, 73, 1); + c1_vert(symbol, 126, 69, 1); + c1_vert(symbol, 6, 68, 0); + c1_vert(symbol, 26, 68, 0); + c1_vert(symbol, 46, 68, 0); + c1_vert(symbol, 66, 68, 0); + c1_vert(symbol, 86, 68, 0); + c1_vert(symbol, 106, 68, 0); + c1_vert(symbol, 126, 68, 0); + c1_spigot(symbol, 0); + c1_spigot(symbol, 12); + c1_spigot(symbol, 24); + c1_spigot(symbol, 36); + c1_spigot(symbol, 48); + c1_spigot(symbol, 60); + c1_spigot(symbol, 87); + c1_spigot(symbol, 99); + c1_spigot(symbol, 111); + c1_spigot(symbol, 123); + c1_spigot(symbol, 135); + c1_spigot(symbol, 147); + c1_block_copy(symbol, datagrid, 0, 0, 68, 6, 0, 0); + c1_block_copy(symbol, datagrid, 0, 6, 68, 18, 0, 2); + c1_block_copy(symbol, datagrid, 0, 24, 68, 18, 0, 4); + c1_block_copy(symbol, datagrid, 0, 42, 68, 18, 0, 6); + c1_block_copy(symbol, datagrid, 0, 60, 68, 18, 0, 8); + c1_block_copy(symbol, datagrid, 0, 78, 68, 18, 0, 10); + c1_block_copy(symbol, datagrid, 0, 96, 68, 18, 0, 12); + c1_block_copy(symbol, datagrid, 0, 114, 68, 6, 0, 14); + c1_block_copy(symbol, datagrid, 68, 0, 68, 6, 12, 0); + c1_block_copy(symbol, datagrid, 68, 6, 68, 18, 12, 2); + c1_block_copy(symbol, datagrid, 68, 24, 68, 18, 12, 4); + c1_block_copy(symbol, datagrid, 68, 42, 68, 18, 12, 6); + c1_block_copy(symbol, datagrid, 68, 60, 68, 18, 12, 8); + c1_block_copy(symbol, datagrid, 68, 78, 68, 18, 12, 10); + c1_block_copy(symbol, datagrid, 68, 96, 68, 18, 12, 12); + c1_block_copy(symbol, datagrid, 68, 114, 68, 6, 12, 14); break; case 9: /* Version S */ - horiz(symbol, 5, 1); - horiz(symbol, 7, 1); + c1_horiz(symbol, 5, 1); + c1_horiz(symbol, 7, 1); set_module(symbol, 6, 0); set_module(symbol, 6, symbol->width - 1); unset_module(symbol, 7, 1); @@ -1450,28 +1504,28 @@ INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int len switch (sub_version) { case 1: /* Version S-10 */ set_module(symbol, 0, 5); - block_copy(symbol, datagrid, 0, 0, 4, 5, 0, 0); - block_copy(symbol, datagrid, 0, 5, 4, 5, 0, 1); + c1_block_copy(symbol, datagrid, 0, 0, 4, 5, 0, 0); + c1_block_copy(symbol, datagrid, 0, 5, 4, 5, 0, 1); break; case 2: /* Version S-20 */ set_module(symbol, 0, 10); set_module(symbol, 4, 10); - block_copy(symbol, datagrid, 0, 0, 4, 10, 0, 0); - block_copy(symbol, datagrid, 0, 10, 4, 10, 0, 1); + c1_block_copy(symbol, datagrid, 0, 0, 4, 10, 0, 0); + c1_block_copy(symbol, datagrid, 0, 10, 4, 10, 0, 1); break; case 3: /* Version S-30 */ set_module(symbol, 0, 15); set_module(symbol, 4, 15); set_module(symbol, 6, 15); - block_copy(symbol, datagrid, 0, 0, 4, 15, 0, 0); - block_copy(symbol, datagrid, 0, 15, 4, 15, 0, 1); + c1_block_copy(symbol, datagrid, 0, 0, 4, 15, 0, 0); + c1_block_copy(symbol, datagrid, 0, 15, 4, 15, 0, 1); break; } break; case 10: /* Version T */ - horiz(symbol, 11, 1); - horiz(symbol, 13, 1); - horiz(symbol, 15, 1); + c1_horiz(symbol, 11, 1); + c1_horiz(symbol, 13, 1); + c1_horiz(symbol, 15, 1); set_module(symbol, 12, 0); set_module(symbol, 12, symbol->width - 1); set_module(symbol, 14, 0); @@ -1484,23 +1538,23 @@ INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int len case 1: /* Version T-16 */ set_module(symbol, 0, 8); set_module(symbol, 10, 8); - block_copy(symbol, datagrid, 0, 0, 10, 8, 0, 0); - block_copy(symbol, datagrid, 0, 8, 10, 8, 0, 1); + c1_block_copy(symbol, datagrid, 0, 0, 10, 8, 0, 0); + c1_block_copy(symbol, datagrid, 0, 8, 10, 8, 0, 1); break; case 2: /* Version T-32 */ set_module(symbol, 0, 16); set_module(symbol, 10, 16); set_module(symbol, 12, 16); - block_copy(symbol, datagrid, 0, 0, 10, 16, 0, 0); - block_copy(symbol, datagrid, 0, 16, 10, 16, 0, 1); + c1_block_copy(symbol, datagrid, 0, 0, 10, 16, 0, 0); + c1_block_copy(symbol, datagrid, 0, 16, 10, 16, 0, 1); break; case 3: /* Verion T-48 */ set_module(symbol, 0, 24); set_module(symbol, 10, 24); set_module(symbol, 12, 24); set_module(symbol, 14, 24); - block_copy(symbol, datagrid, 0, 0, 10, 24, 0, 0); - block_copy(symbol, datagrid, 0, 24, 10, 24, 0, 1); + c1_block_copy(symbol, datagrid, 0, 0, 10, 24, 0, 0); + c1_block_copy(symbol, datagrid, 0, 24, 10, 24, 0, 1); break; } break; @@ -1512,17 +1566,17 @@ INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int len symbol->height = symbol->rows; if (symbol->option_2 == 9) { /* Version S */ - if (symbol->eci || (symbol->input_mode & 0x07) == GS1_MODE) { + if (symbol->eci || gs1) { sprintf(symbol->errtxt, "511: %s ignored for Version S", - symbol->eci && (symbol->input_mode & 0x07) == GS1_MODE - ? "ECI and GS1 mode" - : symbol->eci ? "ECI" : "GS1 mode"); + symbol->eci && gs1 ? "ECI and GS1 mode" : symbol->eci ? "ECI" : "GS1 mode"); error_number = ZINT_WARN_INVALID_OPTION; } - } else if (symbol->eci && (symbol->input_mode & 0x07) == GS1_MODE) { + } else if (symbol->eci && gs1) { strcpy(symbol->errtxt, "512: ECI ignored for GS1 mode"); error_number = ZINT_WARN_INVALID_OPTION; } return error_number; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/code128.c b/backend/code128.c index 716f846e..38103bdf 100644 --- a/backend/code128.c +++ b/backend/code128.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2008-2021 Robin Stuart + Copyright (C) 2008-2022 Robin Stuart Bugfixes thanks to Christian Sakowski and BogDan Vatra Redistribution and use in source and binary forms, with or without @@ -30,7 +30,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include #ifdef _MSC_VER @@ -103,7 +102,7 @@ INTERNAL int c128_parunmodd(const unsigned char llyth) { /** * bring together same type blocks */ -static void grwp(int list[2][C128_MAX], int *indexliste) { +static void c128_grwp(int list[2][C128_MAX], int *indexliste) { /* bring together same type blocks */ if (*(indexliste) > 1) { @@ -220,7 +219,7 @@ INTERNAL void c128_dxsmooth(int list[2][C128_MAX], int *indexliste) { } /* Rule 2 is implemented elsewhere, Rule 6 is implied */ } - grwp(list, indexliste); + c128_grwp(list, indexliste); } /** @@ -342,11 +341,11 @@ INTERNAL void c128_put_in_set(int list[2][C128_MAX], const int indexliste, char } /* Treats source as ISO 8859-1 and copies into symbol->text, converting to UTF-8. Returns length of symbol->text */ -STATIC_UNLESS_ZINT_TEST int hrt_cpy_iso8859_1(struct zint_symbol *symbol, const unsigned char *source, - const int source_len) { +STATIC_UNLESS_ZINT_TEST int c128_hrt_cpy_iso8859_1(struct zint_symbol *symbol, const unsigned char source[], + const int length) { int i, j; - for (i = 0, j = 0; i < source_len && j < (int) sizeof(symbol->text); i++) { + for (i = 0, j = 0; i < length && j < (int) sizeof(symbol->text); i++) { if (source[i] < 0x80) { symbol->text[j++] = source[i] >= ' ' && source[i] != 0x7F ? source[i] : ' '; } else if (source[i] < 0xC0) { @@ -724,7 +723,7 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len /* ISO/IEC 15417:2007 leaves dimensions/height as application specification */ - hrt_cpy_iso8859_1(symbol, source, length); + c128_hrt_cpy_iso8859_1(symbol, source, length); return error_number; } @@ -1146,3 +1145,5 @@ INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length) return error_number; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/common.c b/backend/common.c index 2d1ae2cb..0ae41434 100644 --- a/backend/common.c +++ b/backend/common.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2008 - 2021 Robin Stuart + Copyright (C) 2008-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,7 +29,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include #ifdef ZINT_TEST #include @@ -98,36 +97,47 @@ INTERNAL int chr_cnt(const unsigned char string[], const int length, const unsig return count; } +/* Flag table for `is_chr()` and `is_sane()` */ +#define IS_CLS_F (IS_CLI_F | IS_SIL_F) +static const unsigned short flgs[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*00-1F*/ + IS_SPC_F, IS_C82_F, IS_C82_F, IS_HSH_F, /*20-23*/ /* !"# */ + IS_CLS_F, IS_SIL_F | IS_C82_F, IS_C82_F, IS_C82_F, /*24-27*/ /* $%&' */ + IS_C82_F, IS_C82_F, IS_AST_F, IS_PLS_F, /*28-2B*/ /* ()*+ */ + IS_C82_F, IS_MNS_F, IS_CLS_F | IS_C82_F, IS_CLS_F | IS_C82_F, /*2B-2F*/ /* ,-./ */ + IS_NUM_F, IS_NUM_F, IS_NUM_F, IS_NUM_F, /*30-33*/ /* 0123 */ + IS_NUM_F, IS_NUM_F, IS_NUM_F, IS_NUM_F, /*34-37*/ /* 4567 */ + IS_NUM_F, IS_NUM_F, IS_CLI_F | IS_C82_F, IS_C82_F, /*38-3B*/ /* 89:; */ + IS_C82_F, IS_C82_F, IS_C82_F, IS_C82_F, /*3B-3F*/ /* <=>? */ + 0, IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, /*40-43*/ /* @ABC */ + IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*44-47*/ /* DEFG */ + IS_UPO_F | IS_ARS_F, IS_UPO_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*48-4B*/ /* HIJK */ + IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F, /*4B-4F*/ /* LMNO */ + IS_UPO_F | IS_ARS_F, IS_UPO_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*50-53*/ /* PQRS */ + IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*53-57*/ /* TUVW */ + IS_UX__F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, 0, /*58-5B*/ /* XYZ[ */ + 0, 0, 0, IS_C82_F, /*5B-5F*/ /* \]^_ */ + 0, IS_LHX_F, IS_LHX_F, IS_LHX_F, /*60-63*/ /* `abc */ + IS_LHX_F, IS_LHX_F, IS_LHX_F, IS_LWO_F, /*64-67*/ /* defg */ + IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*68-6B*/ /* hijk */ + IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*6B-6F*/ /* lmno */ + IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*70-73*/ /* pqrs */ + IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*74-77*/ /* tuvw */ + IS_LX__F, IS_LWO_F, IS_LWO_F, 0, /*78-7B*/ /* xyz{ */ + 0, 0, 0, 0, /*7B-7F*/ /* |}~D */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80-9F*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*A0-BF*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*C0-DF*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*E0-FF*/ +}; + +/* Whether a character matches `flg` */ +INTERNAL int is_chr(const unsigned int flg, const unsigned int c) { + return c < 0x80 && (flgs[c] & flg) != 0; +} + /* Verifies that a string only uses valid characters */ INTERNAL int is_sane(const unsigned int flg, const unsigned char source[], const int length) { - #define IS_CLS_F (IS_CLI_F | IS_SIL_F) - static const unsigned short flgs[256] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*00-1F*/ - IS_SPC_F, IS_C82_F, IS_C82_F, IS_HSH_F, /*20-23*/ /* !"# */ - IS_CLS_F, IS_SIL_F | IS_C82_F, IS_C82_F, IS_C82_F, /*24-27*/ /* $%&' */ - IS_C82_F, IS_C82_F, IS_C82_F, IS_PLS_F, /*28-2B*/ /* ()*+ */ - IS_C82_F, IS_MNS_F, IS_CLS_F | IS_C82_F, IS_CLS_F | IS_C82_F, /*2B-2F*/ /* ,-./ */ - IS_NUM_F, IS_NUM_F, IS_NUM_F, IS_NUM_F, /*30-33*/ /* 0123 */ - IS_NUM_F, IS_NUM_F, IS_NUM_F, IS_NUM_F, /*34-37*/ /* 4567 */ - IS_NUM_F, IS_NUM_F, IS_CLI_F | IS_C82_F, IS_C82_F, /*38-3B*/ /* 89:; */ - IS_C82_F, IS_C82_F, IS_C82_F, IS_C82_F, /*3B-3F*/ /* <=>? */ - 0, IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, /*40-43*/ /* @ABC */ - IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*44-47*/ /* DEFG */ - IS_UPO_F | IS_ARS_F, IS_UPO_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*48-4B*/ /* HIJK */ - IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F, /*4B-4F*/ /* LMNO */ - IS_UPO_F | IS_ARS_F, IS_UPO_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*50-53*/ /* PQRS */ - IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*53-57*/ /* TUVW */ - IS_UX__F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, 0, /*58-5B*/ /* XYZ[ */ - 0, 0, 0, IS_C82_F, /*5B-5F*/ /* \]^_ */ - 0, IS_LHX_F, IS_LHX_F, IS_LHX_F, /*60-63*/ /* `abc */ - IS_LHX_F, IS_LHX_F, IS_LHX_F, IS_LWO_F, /*64-67*/ /* defg */ - IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*68-6B*/ /* hijk */ - IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*6B-6F*/ /* lmno */ - IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*70-73*/ /* pqrs */ - IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*74-77*/ /* tuvw */ - IS_LX__F, IS_LWO_F, IS_LWO_F, 0, /*78-7B*/ /* xyz{ */ - 0, 0, 0, 0, /*7B-7F*/ /* |}~D */ - }; int i; for (i = 0; i < length; i++) { @@ -189,7 +199,7 @@ INTERNAL int bin_append_posn(const int arg, const int length, char *binary, cons return bin_posn + length; } -#ifndef COMMON_INLINE +#ifndef Z_COMMON_INLINE /* Return true (1) if a module is dark/black, otherwise false (0) */ INTERNAL int module_is_set(const struct zint_symbol *symbol, const int y_coord, const int x_coord) { return (symbol->encoded_data[y_coord][x_coord >> 3] >> (x_coord & 0x07)) & 1; @@ -505,6 +515,32 @@ INTERNAL float stripf(const float arg) { return *((volatile const float *) &arg); } +/* Returns total length of segments */ +INTERNAL int segs_length(const struct zint_seg segs[], const int seg_count) { + int total_len = 0; + int i; + + for (i = 0; i < seg_count; i++) { + total_len += segs[i].length == -1 ? (int) ustrlen(segs[i].source) : segs[i].length; + } + + return total_len; +} + +/* Shallow copy segments, adjusting default ECIs */ +INTERNAL void segs_cpy(const struct zint_seg segs[], const int seg_count, struct zint_seg local_segs[]) { + int i; + + local_segs[0] = segs[0]; + for (i = 1; i < seg_count; i++) { + local_segs[i] = segs[i]; + /* Ensure default ECI set if follows non-default ECI */ + if (local_segs[i].eci == 0 && local_segs[i - 1].eci > 3) { + local_segs[i].eci = 3; + } + } +} + /* Returns red component if any of ultra colour indexing "0CBMRYGKW" */ INTERNAL int colour_to_red(const int colour) { int return_val = 0; @@ -586,3 +622,5 @@ void debug_test_codeword_dump_int(struct zint_symbol *symbol, const int *codewor symbol->errtxt[strlen(symbol->errtxt) - 1] = '\0'; /* Zap last space */ } #endif + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/common.h b/backend/common.h index 724f2a08..59646d44 100644 --- a/backend/common.h +++ b/backend/common.h @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2009 - 2021 Robin Stuart + Copyright (C) 2009-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,10 +29,9 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ -#ifndef __COMMON_H -#define __COMMON_H +#ifndef Z_COMMON_H +#define Z_COMMON_H #ifndef FALSE #define FALSE 0 @@ -49,19 +48,20 @@ /* `is_sane()` flags */ #define IS_SPC_F 0x0001 /* Space */ #define IS_HSH_F 0x0002 /* Hash sign # */ -#define IS_PLS_F 0x0004 /* Plus sign + */ -#define IS_MNS_F 0x0008 /* Minus sign - */ -#define IS_NUM_F 0x0010 /* Number 0-9 */ -#define IS_UPO_F 0x0020 /* Uppercase letter, apart from A-F and X */ -#define IS_UHX_F 0x0040 /* Uppercase hex A-F */ -#define IS_UX__F 0x0080 /* Uppercase X */ -#define IS_LWO_F 0x0100 /* Lowercase letter, apart from a-f and x */ -#define IS_LHX_F 0x0200 /* Lowercase hex a-f */ -#define IS_LX__F 0x0400 /* Lowercase x */ -#define IS_C82_F 0x0800 /* CSET82 punctuation (apart from - and +) */ -#define IS_SIL_F 0x1000 /* SILVER/TECHNETIUM punctuation .$/% (apart from space, - and +) */ -#define IS_CLI_F 0x2000 /* CALCIUM INNER punctuation $:/. (apart from - and +) (Codabar) */ -#define IS_ARS_F 0x4000 /* ARSENIC uppercase subset (VIN) */ +#define IS_AST_F 0x0004 /* Asterisk sign * */ +#define IS_PLS_F 0x0008 /* Plus sign + */ +#define IS_MNS_F 0x0010 /* Minus sign - */ +#define IS_NUM_F 0x0020 /* Number 0-9 */ +#define IS_UPO_F 0x0040 /* Uppercase letter, apart from A-F and X */ +#define IS_UHX_F 0x0080 /* Uppercase hex A-F */ +#define IS_UX__F 0x0100 /* Uppercase X */ +#define IS_LWO_F 0x0200 /* Lowercase letter, apart from a-f and x */ +#define IS_LHX_F 0x0400 /* Lowercase hex a-f */ +#define IS_LX__F 0x0800 /* Lowercase x */ +#define IS_C82_F 0x1000 /* CSET82 punctuation (apart from *, + and -) */ +#define IS_SIL_F 0x2000 /* SILVER/TECHNETIUM punctuation .$/% (apart from space, + and -) */ +#define IS_CLI_F 0x4000 /* CALCIUM INNER punctuation $:/. (apart from + and -) (Codabar) */ +#define IS_ARS_F 0x8000 /* ARSENIC uppercase subset (VIN) */ #define IS_UPR_F (IS_UPO_F | IS_UHX_F | IS_UX__F) /* Uppercase letters */ #define IS_LWR_F (IS_LWO_F | IS_LHX_F | IS_LX__F) /* Lowercase letters */ @@ -121,9 +121,9 @@ #define STATIC_UNLESS_ZINT_TEST static #endif -#define COMMON_INLINE 1 +#define Z_COMMON_INLINE 1 -#ifdef COMMON_INLINE +#ifdef Z_COMMON_INLINE /* Return true (1) if a module is dark/black, otherwise false (0) */ # define module_is_set(s, y, x) (((s)->encoded_data[(y)][(x) >> 3] >> ((x) & 0x07)) & 1) @@ -147,6 +147,7 @@ extern "C" { INTERNAL void to_upper(unsigned char source[], const int length); INTERNAL int chr_cnt(const unsigned char string[], const int length, const unsigned char c); + INTERNAL int is_chr(const unsigned int flg, const unsigned int c); INTERNAL int is_sane(const unsigned int flg, const unsigned char source[], const int length); INTERNAL int is_sane_lookup(const char test_string[], const int test_length, const unsigned char source[], const int length, int *posns); @@ -154,7 +155,7 @@ extern "C" { INTERNAL int bin_append_posn(const int arg, const int length, char *binary, const int bin_posn); - #ifndef COMMON_INLINE + #ifndef Z_COMMON_INLINE INTERNAL int module_is_set(const struct zint_symbol *symbol, const int y_coord, const int x_coord); INTERNAL void set_module(struct zint_symbol *symbol, const int y_coord, const int x_coord); INTERNAL int module_colour_is_set(const struct zint_symbol *symbol, const int y_coord, const int x_coord); @@ -183,6 +184,9 @@ extern "C" { INTERNAL float stripf(const float arg); + INTERNAL int segs_length(const struct zint_seg segs[], const int seg_count); + INTERNAL void segs_cpy(const struct zint_seg segs[], const int seg_count, struct zint_seg local_segs[]); + INTERNAL int colour_to_red(const int colour); INTERNAL int colour_to_green(const int colour); INTERNAL int colour_to_blue(const int colour); @@ -197,4 +201,5 @@ extern "C" { } #endif /* __cplusplus */ -#endif /* __COMMON_H */ +/* vim: set ts=4 sw=4 et : */ +#endif /* Z_COMMON_H */ diff --git a/backend/dmatrix.c b/backend/dmatrix.c index 7209eec6..aba1da82 100644 --- a/backend/dmatrix.c +++ b/backend/dmatrix.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2009 - 2021 Robin Stuart + Copyright (C) 2009-2022 Robin Stuart developed from and including some functions from: IEC16022 bar code generation @@ -37,7 +37,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include #include @@ -1485,12 +1484,11 @@ 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_UNLESS_ZINT_TEST int dm_encode(struct zint_symbol *symbol, const unsigned char source[], - unsigned char target[], int *p_length, int *p_binlen) { + const int length, const int eci, const int gs1, unsigned char target[], int *p_tp) { int sp = 0; - int tp = 0; + int tp = *p_tp; int current_mode = DM_ASCII; - int i, gs1; - int length = *p_length; + int i; int process_buffer[8]; /* holds remaining data to finalised */ int process_p = 0; /* number of characters left to finalise */ int b256_start = 0; @@ -1498,134 +1496,20 @@ STATIC_UNLESS_ZINT_TEST int dm_encode(struct zint_symbol *symbol, const unsigned int error_number; const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; - if (length > 3116) { /* Max is 3166 digits */ - strcpy(symbol->errtxt, "760: Data too long to fit in symbol"); - return ZINT_ERROR_TOO_LONG; - } - - if (symbol->structapp.count) { - int id1, id2; - - if (symbol->structapp.count < 2 || symbol->structapp.count > 16) { - strcpy(symbol->errtxt, "720: Structured Append count out of range (2-16)"); - return ZINT_ERROR_INVALID_OPTION; - } - if (symbol->structapp.index < 1 || symbol->structapp.index > symbol->structapp.count) { - sprintf(symbol->errtxt, "721: Structured Append index out of range (1-%d)", symbol->structapp.count); - return ZINT_ERROR_INVALID_OPTION; - } - if (symbol->structapp.id[0]) { - int id, id_len, id1_err, id2_err; - - for (id_len = 0; id_len < 32 && symbol->structapp.id[id_len]; id_len++); - - if (id_len > 6) { /* ID1 * 1000 + ID2 */ - strcpy(symbol->errtxt, "722: Structured Append ID too long (6 digit maximum)"); - return ZINT_ERROR_INVALID_OPTION; - } - - id = to_int((const unsigned char *) symbol->structapp.id, id_len); - if (id == -1) { - strcpy(symbol->errtxt, "723: Invalid Structured Append ID (digits only)"); - return ZINT_ERROR_INVALID_OPTION; - } - id1 = id / 1000; - id2 = id % 1000; - id1_err = id1 < 1 || id1 > 254; - id2_err = id2 < 1 || id2 > 254; - if (id1_err || id2_err) { - if (id1_err && id2_err) { - sprintf(symbol->errtxt, - "724: Structured Append ID1 '%03d' and ID2 '%03d' out of range (001-254) (ID '%03d%03d')", - id1, id2, id1, id2); - } else if (id1_err) { - sprintf(symbol->errtxt, - "725: Structured Append ID1 '%03d' out of range (001-254) (ID '%03d%03d')", - id1, id1, id2); - } else { - sprintf(symbol->errtxt, - "726: Structured Append ID2 '%03d' out of range (001-254) (ID '%03d%03d')", - id2, id1, id2); - } - return ZINT_ERROR_INVALID_OPTION; - } - } else { - id1 = id2 = 1; - } - - target[tp++] = 233; - target[tp++] = (17 - symbol->structapp.count) | ((symbol->structapp.index - 1) << 4); - target[tp++] = id1; - target[tp++] = id2; - } - - /* gs1 flag values: 0: no gs1, 1: gs1 with FNC1 serparator, 2: GS separator */ - if ((symbol->input_mode & 0x07) == GS1_MODE) { - if (symbol->output_options & GS1_GS_SEPARATOR) { - gs1 = 2; - } else { - gs1 = 1; - } - } else { - gs1 = 0; - } - - if (gs1) { - target[tp++] = 232; - if (debug_print) printf("FN1 "); - } /* FNC1 */ - - if (symbol->output_options & READER_INIT) { - if (gs1) { - strcpy(symbol->errtxt, "521: Cannot encode in GS1 mode and Reader Initialisation at the same time"); - return ZINT_ERROR_INVALID_OPTION; - } - if (symbol->structapp.count) { - strcpy(symbol->errtxt, "727: Cannot have Structured Append and Reader Initialisation at the same time"); - return ZINT_ERROR_INVALID_OPTION; - } - target[tp++] = 234; /* Reader Programming */ - if (debug_print) printf("RP "); - } - - if (symbol->eci > 0) { + if (eci > 0) { /* Encode ECI numbers according to Table 6 */ target[tp++] = 241; /* ECI Character */ - if (symbol->eci <= 126) { - target[tp++] = (unsigned char) (symbol->eci + 1); - } else if (symbol->eci <= 16382) { - target[tp++] = (unsigned char) ((symbol->eci - 127) / 254 + 128); - target[tp++] = (unsigned char) ((symbol->eci - 127) % 254 + 1); + if (eci <= 126) { + target[tp++] = (unsigned char) (eci + 1); + } else if (eci <= 16382) { + target[tp++] = (unsigned char) ((eci - 127) / 254 + 128); + target[tp++] = (unsigned char) ((eci - 127) % 254 + 1); } else { - target[tp++] = (unsigned char) ((symbol->eci - 16383) / 64516 + 192); - target[tp++] = (unsigned char) (((symbol->eci - 16383) / 254) % 254 + 1); - target[tp++] = (unsigned char) ((symbol->eci - 16383) % 254 + 1); + target[tp++] = (unsigned char) ((eci - 16383) / 64516 + 192); + target[tp++] = (unsigned char) (((eci - 16383) / 254) % 254 + 1); + target[tp++] = (unsigned char) ((eci - 16383) % 254 + 1); } - if (debug_print) printf("ECI %d ", symbol->eci + 1); - } - - /* Check for Macro05/Macro06 */ - /* "[)>[RS]05[GS]...[RS][EOT]" -> CW 236 */ - /* "[)>[RS]06[GS]...[RS][EOT]" -> CW 237 */ - if (tp == 0 && sp == 0 && length >= 9 - && source[0] == '[' && source[1] == ')' && source[2] == '>' - && source[3] == '\x1e' && source[4] == '0' - && (source[5] == '5' || source[5] == '6') - && source[6] == '\x1d' - && source[length - 2] == '\x1e' && source[length - 1] == '\x04') { - - /* Output macro Codeword */ - if (source[5] == '5') { - target[tp++] = 236; - if (debug_print) printf("Macro05 "); - } else { - target[tp++] = 237; - if (debug_print) printf("Macro06 "); - } - /* Remove macro characters from input string */ - sp = 7; - length -= 2; - *p_length -= 2; + if (debug_print) printf("ECI %d ", eci + 1); } if (symbol->input_mode & FAST_MODE) { /* If FAST_MODE, do Annex J-based encodation */ @@ -1769,6 +1653,153 @@ STATIC_UNLESS_ZINT_TEST int dm_encode(struct zint_symbol *symbol, const unsigned printf("\n"); } + *p_tp = tp; + + return 0; +} + +/* Call `dm_encode()` for each segment, dealing with Structured Append, GS1, READER_INIT and macro headers + beforehand */ +static int dm_encode_segs(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count, + unsigned char target[], int *p_binlen) { + int error_number; + int i; + int tp = 0; + int gs1; + int in_macro = 0; + const struct zint_seg *last_seg = &segs[seg_count - 1]; + const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; + + if (segs_length(segs, seg_count) > 3116) { /* Max is 3166 digits */ + strcpy(symbol->errtxt, "760: Data too long to fit in symbol"); + return ZINT_ERROR_TOO_LONG; + } + + if (symbol->structapp.count) { + int id1, id2; + + if (symbol->structapp.count < 2 || symbol->structapp.count > 16) { + strcpy(symbol->errtxt, "720: Structured Append count out of range (2-16)"); + return ZINT_ERROR_INVALID_OPTION; + } + if (symbol->structapp.index < 1 || symbol->structapp.index > symbol->structapp.count) { + sprintf(symbol->errtxt, "721: Structured Append index out of range (1-%d)", symbol->structapp.count); + return ZINT_ERROR_INVALID_OPTION; + } + if (symbol->structapp.id[0]) { + int id, id_len, id1_err, id2_err; + + for (id_len = 0; id_len < 32 && symbol->structapp.id[id_len]; id_len++); + + if (id_len > 6) { /* ID1 * 1000 + ID2 */ + strcpy(symbol->errtxt, "722: Structured Append ID too long (6 digit maximum)"); + return ZINT_ERROR_INVALID_OPTION; + } + + id = to_int((const unsigned char *) symbol->structapp.id, id_len); + if (id == -1) { + strcpy(symbol->errtxt, "723: Invalid Structured Append ID (digits only)"); + return ZINT_ERROR_INVALID_OPTION; + } + id1 = id / 1000; + id2 = id % 1000; + id1_err = id1 < 1 || id1 > 254; + id2_err = id2 < 1 || id2 > 254; + if (id1_err || id2_err) { + if (id1_err && id2_err) { + sprintf(symbol->errtxt, + "724: Structured Append ID1 '%03d' and ID2 '%03d' out of range (001-254) (ID '%03d%03d')", + id1, id2, id1, id2); + } else if (id1_err) { + sprintf(symbol->errtxt, + "725: Structured Append ID1 '%03d' out of range (001-254) (ID '%03d%03d')", + id1, id1, id2); + } else { + sprintf(symbol->errtxt, + "726: Structured Append ID2 '%03d' out of range (001-254) (ID '%03d%03d')", + id2, id1, id2); + } + return ZINT_ERROR_INVALID_OPTION; + } + } else { + id1 = id2 = 1; + } + + target[tp++] = 233; + target[tp++] = (17 - symbol->structapp.count) | ((symbol->structapp.index - 1) << 4); + target[tp++] = id1; + target[tp++] = id2; + } + + /* gs1 flag values: 0: no gs1, 1: gs1 with FNC1 serparator, 2: GS separator */ + if ((symbol->input_mode & 0x07) == GS1_MODE) { + if (symbol->output_options & GS1_GS_SEPARATOR) { + gs1 = 2; + } else { + gs1 = 1; + } + } else { + gs1 = 0; + } + + if (gs1) { + target[tp++] = 232; + if (debug_print) printf("FN1 "); + } /* FNC1 */ + + if (symbol->output_options & READER_INIT) { + if (gs1) { + strcpy(symbol->errtxt, "521: Cannot encode in GS1 mode and Reader Initialisation at the same time"); + return ZINT_ERROR_INVALID_OPTION; + } + if (symbol->structapp.count) { + strcpy(symbol->errtxt, "727: Cannot have Structured Append and Reader Initialisation at the same time"); + return ZINT_ERROR_INVALID_OPTION; + } + target[tp++] = 234; /* Reader Programming */ + if (debug_print) printf("RP "); + } + + /* Check for Macro05/Macro06 */ + /* "[)>[RS]05[GS]...[RS][EOT]" -> CW 236 */ + /* "[)>[RS]06[GS]...[RS][EOT]" -> CW 237 */ + if (tp == 0 && segs[0].length >= 9 && last_seg->length >= 2 + && segs[0].source[0] == '[' && segs[0].source[1] == ')' && segs[0].source[2] == '>' + && segs[0].source[3] == '\x1e' /*RS*/ && segs[0].source[4] == '0' + && (segs[0].source[5] == '5' || segs[0].source[5] == '6') + && segs[0].source[6] == '\x1d' /*GS*/ + && last_seg->source[last_seg->length - 1] == '\x04' /*EOT*/ + && last_seg->source[last_seg->length - 2] == '\x1e' /*RS*/) { + + /* Output macro Codeword */ + if (segs[0].source[5] == '5') { + target[tp++] = 236; + if (debug_print) printf("Macro05 "); + } else { + target[tp++] = 237; + if (debug_print) printf("Macro06 "); + } + /* Remove macro characters from input string */ + in_macro = 1; + } + + for (i = 0; i < seg_count; i++) { + int src_inc = 0, len_dec = 0; + if (in_macro) { + if (i == 0) { + src_inc = len_dec = 7; /* Skip over macro characters at beginning */ + } + if (i + 1 == seg_count) { + 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); + if (error_number != 0) { + return error_number; + } + } + *p_binlen = tp; return 0; @@ -1791,7 +1822,7 @@ static void dm_add_tail(unsigned char target[], int tp, const int tail_length) { } } -static int dm_ecc200(struct zint_symbol *symbol, const unsigned char source[], int length) { +static int dm_ecc200(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { int i, skew = 0; unsigned char binary[2200]; int binlen; @@ -1801,7 +1832,7 @@ static int dm_ecc200(struct zint_symbol *symbol, const unsigned char source[], i const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; /* `length` may be decremented by 2 if macro character is used */ - error_number = dm_encode(symbol, source, binary, &length, &binlen); + error_number = dm_encode_segs(symbol, segs, seg_count, binary, &binlen); if (error_number != 0) { return error_number; } @@ -1906,12 +1937,12 @@ static int dm_ecc200(struct zint_symbol *symbol, const unsigned char source[], i return error_number; } -INTERNAL int datamatrix(struct zint_symbol *symbol, unsigned char source[], int length) { +INTERNAL int datamatrix(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { int error_number; if (symbol->option_1 <= 1) { /* ECC 200 */ - error_number = dm_ecc200(symbol, source, length); + error_number = dm_ecc200(symbol, segs, seg_count); } else { /* ECC 000 - 140 */ strcpy(symbol->errtxt, "524: Older Data Matrix standards are no longer supported"); @@ -1920,3 +1951,5 @@ INTERNAL int datamatrix(struct zint_symbol *symbol, unsigned char source[], int return error_number; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/dotcode.c b/backend/dotcode.c index 21d5226e..a9683269 100644 --- a/backend/dotcode.c +++ b/backend/dotcode.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2017-2020 Robin Stuart + Copyright (C) 2017-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,7 +29,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ /* * Attempts to encode DotCode according to (AIMD013) ISS DotCode Rev. 4.0, DRAFT 0.15, TSC Pre-PR #5, @@ -54,7 +53,7 @@ #define SCORE_UNLIT_EDGE -99999 /* DotCode symbol character dot patterns, from Annex C */ -static const unsigned short int dot_patterns[113] = { +static const unsigned short dc_dot_patterns[113] = { 0x155, 0x0ab, 0x0ad, 0x0b5, 0x0d5, 0x156, 0x15a, 0x16a, 0x1aa, 0x0ae, 0x0b6, 0x0ba, 0x0d6, 0x0da, 0x0ea, 0x12b, 0x12d, 0x135, 0x14b, 0x14d, 0x153, 0x159, 0x165, 0x169, 0x195, 0x1a5, 0x1a9, 0x057, 0x05b, 0x05d, @@ -70,22 +69,21 @@ static const unsigned short int dot_patterns[113] = { }; // Printed() routine from Annex A adapted to char array of ASCII 1's and 0's -static int get_dot(const char Dots[], const int Hgt, const int Wid, const int x, const int y) { - int retval = 0; +static int dc_get_dot(const char Dots[], const int Hgt, const int Wid, const int x, const int y) { if ((x >= 0) && (x < Wid) && (y >= 0) && (y < Hgt)) { if (Dots[(y * Wid) + x] == '1') { - retval = 1; + return 1; } } - return retval; + return 0; } -static int clr_col(const char *Dots, const int Hgt, const int Wid, const int x) { +static int dc_clr_col(const char *Dots, const int Hgt, const int Wid, const int x) { int y; for (y = x & 1; y < Hgt; y += 2) { - if (get_dot(Dots, Hgt, Wid, x, y)) { + if (dc_get_dot(Dots, Hgt, Wid, x, y)) { return 0; } } @@ -93,10 +91,10 @@ static int clr_col(const char *Dots, const int Hgt, const int Wid, const int x) return 1; } -static int clr_row(const char *Dots, const int Hgt, const int Wid, const int y) { +static int dc_clr_row(const char *Dots, const int Hgt, const int Wid, const int y) { int x; for (x = y & 1; x < Wid; x += 2) { - if (get_dot(Dots, Hgt, Wid, x, y)) { + if (dc_get_dot(Dots, Hgt, Wid, x, y)) { return 0; } } @@ -105,11 +103,11 @@ static int clr_row(const char *Dots, const int Hgt, const int Wid, const int y) } // calc penalty for empty interior columns -static int col_penalty(const char *Dots, const int Hgt, const int Wid) { +static int dc_col_penalty(const char *Dots, const int Hgt, const int Wid) { int x, penalty = 0, penalty_local = 0; for (x = 1; x < Wid - 1; x++) { - if (clr_col(Dots, Hgt, Wid, x)) { + if (dc_clr_col(Dots, Hgt, Wid, x)) { if (penalty_local == 0) { penalty_local = Hgt; } else { @@ -127,11 +125,11 @@ static int col_penalty(const char *Dots, const int Hgt, const int Wid) { } // calc penalty for empty interior rows -static int row_penalty(const char *Dots, const int Hgt, const int Wid) { +static int dc_row_penalty(const char *Dots, const int Hgt, const int Wid) { int y, penalty = 0, penalty_local = 0; for (y = 1; y < Hgt - 1; y++) { - if (clr_row(Dots, Hgt, Wid, y)) { + if (dc_clr_row(Dots, Hgt, Wid, y)) { if (penalty_local == 0) { penalty_local = Wid; } else { @@ -149,7 +147,7 @@ static int row_penalty(const char *Dots, const int Hgt, const int Wid) { } /* Dot pattern scoring routine from Annex A */ -static int score_array(const char Dots[], const int Hgt, const int Wid) { +static int dc_score_array(const char Dots[], const int Hgt, const int Wid) { int x, y, worstedge, first, last, sum; int penalty = 0; @@ -157,7 +155,7 @@ static int score_array(const char Dots[], const int Hgt, const int Wid) { // subtract a penalty score for empty rows/columns from total code score for each mask, // where the penalty is Sum(N ^ n), where N is the number of positions in a column/row, // and n is the number of consecutive empty rows/columns - penalty = row_penalty(Dots, Hgt, Wid) + col_penalty(Dots, Hgt, Wid); + penalty = dc_row_penalty(Dots, Hgt, Wid) + dc_col_penalty(Dots, Hgt, Wid); sum = 0; first = -1; @@ -165,7 +163,7 @@ static int score_array(const char Dots[], const int Hgt, const int Wid) { // across the top edge, count printed dots and measure their extent for (x = 0; x < Wid; x += 2) { - if (get_dot(Dots, Hgt, Wid, x, 0)) { + if (dc_get_dot(Dots, Hgt, Wid, x, 0)) { if (first < 0) { first = x; } @@ -186,7 +184,7 @@ static int score_array(const char Dots[], const int Hgt, const int Wid) { // across the bottom edge, ditto for (x = Wid & 1; x < Wid; x += 2) { - if (get_dot(Dots, Hgt, Wid, x, Hgt - 1)) { + if (dc_get_dot(Dots, Hgt, Wid, x, Hgt - 1)) { if (first < 0) { first = x; } @@ -210,7 +208,7 @@ static int score_array(const char Dots[], const int Hgt, const int Wid) { // down the left edge, ditto for (y = 0; y < Hgt; y += 2) { - if (get_dot(Dots, Hgt, Wid, 0, y)) { + if (dc_get_dot(Dots, Hgt, Wid, 0, y)) { if (first < 0) { first = y; } @@ -234,7 +232,7 @@ static int score_array(const char Dots[], const int Hgt, const int Wid) { // down the right edge, ditto for (y = Hgt & 1; y < Hgt; y += 2) { - if (get_dot(Dots, Hgt, Wid, Wid - 1, y)) { + if (dc_get_dot(Dots, Hgt, Wid, Wid - 1, y)) { if (first < 0) { first = y; } @@ -257,15 +255,11 @@ static int score_array(const char Dots[], const int Hgt, const int Wid) { sum = 0; for (y = 0; y < Hgt; y++) { for (x = y & 1; x < Wid; x += 2) { - if ((!get_dot(Dots, Hgt, Wid, x - 1, y - 1)) - && (!get_dot(Dots, Hgt, Wid, x + 1, y - 1)) - && (!get_dot(Dots, Hgt, Wid, x - 1, y + 1)) - && (!get_dot(Dots, Hgt, Wid, x + 1, y + 1)) - && ((!get_dot(Dots, Hgt, Wid, x, y)) - || ((!get_dot(Dots, Hgt, Wid, x - 2, y)) - && (!get_dot(Dots, Hgt, Wid, x, y - 2)) - && (!get_dot(Dots, Hgt, Wid, x + 2, y)) - && (!get_dot(Dots, Hgt, Wid, x, y + 2))))) { + if (!dc_get_dot(Dots, Hgt, Wid, x - 1, y - 1) && !dc_get_dot(Dots, Hgt, Wid, x + 1, y - 1) + && !dc_get_dot(Dots, Hgt, Wid, x - 1, y + 1) && !dc_get_dot(Dots, Hgt, Wid, x + 1, y + 1) + && (!dc_get_dot(Dots, Hgt, Wid, x, y) + || (!dc_get_dot(Dots, Hgt, Wid, x - 2, y) && !dc_get_dot(Dots, Hgt, Wid, x, y - 2) + && !dc_get_dot(Dots, Hgt, Wid, x + 2, y) && !dc_get_dot(Dots, Hgt, Wid, x, y + 2)))) { sum++; } } @@ -279,7 +273,7 @@ static int score_array(const char Dots[], const int Hgt, const int Wid) { // employing Galois Field GF, where GF is prime, with a prime modulus of PM //------------------------------------------------------------------------- -static void rsencode(const int nd, const int nc, unsigned char *wd) { +static void dc_rsencode(const int nd, const int nc, unsigned char *wd) { /* Pre-calculated coefficients for GF(113) of generator polys of degree 3 to 39. To generate run "backend/tests/test_dotcode -f generate -g" and place result below */ static const char coefs[820 - 5] = { /* 40*(41 + 1)/2 == 820 less 2 + 3 (degrees 1 and 2) */ @@ -381,26 +375,22 @@ static void rsencode(const int nd, const int nc, unsigned char *wd) { } /* Check if the next character is directly encodable in code set A (Annex F.II.D) */ -static int datum_a(const unsigned char source[], const int position, const int length) { - int retval = 0; +static int dc_datum_a(const unsigned char source[], const int length, const int position) { - if (position < length) { - if (source[position] <= 95) { - retval = 1; - } + if (position < length && source[position] <= 95) { + return 1; } - return retval; + return 0; } /* Check if the next character is directly encodable in code set B (Annex F.II.D). * Note changed to return 2 if CR/LF */ -static int datum_b(const unsigned char source[], const int position, const int length) { - int retval = 0; +static int dc_datum_b(const unsigned char source[], const int length, const int position) { if (position < length) { if ((source[position] >= 32) && (source[position] <= 127)) { - retval = 1; + return 1; } switch (source[position]) { @@ -408,63 +398,52 @@ static int datum_b(const unsigned char source[], const int position, const int l case 28: // FS case 29: // GS case 30: // RS - retval = 1; + return 1; + break; } - if (position + 1 < length) { - if ((source[position] == 13) && (source[position + 1] == 10)) { // CRLF - retval = 2; - } + if ((position + 1 < length) && (source[position] == 13) && (source[position + 1] == 10)) { // CRLF + return 2; } } - return retval; + return 0; } /* Check if the next characters are directly encodable in code set C (Annex F.II.D) */ -static int datum_c(const unsigned char source[], const int position, const int length) { - int retval = 0; - - if (position + 1 < length) { - if (((source[position] >= '0') && (source[position] <= '9')) - && ((source[position + 1] >= '0') && (source[position + 1] <= '9'))) - retval = 1; - } - - return retval; +static int dc_datum_c(const unsigned char source[], const int length, const int position) { + return is_twodigits(source, length, position); } /* Returns how many consecutive digits lie immediately ahead (Annex F.II.A) */ -static int n_digits(const unsigned char source[], const int position, const int length) { +static int dc_n_digits(const unsigned char source[], const int length, const int position, const int max) { int i; - for (i = position; (i < length) && ((source[i] >= '0') && (source[i] <= '9')); i++); + for (i = position; (i < length) && ((source[i] >= '0') && (source[i] <= '9') && i < position + max); i++); return i - position; } -/* checks ahead for 10 or more digits starting "17xxxxxx10..." (Annex F.II.B) */ -static int seventeen_ten(const unsigned char source[], const int position, const int length) { - int found = 0; +/* Checks ahead for 10 or more digits starting "17xxxxxx10..." (Annex F.II.B) */ +static int dc_seventeen_ten(const unsigned char source[], const int length, const int position) { - if (n_digits(source, position, length) >= 10) { - if (((source[position] == '1') && (source[position + 1] == '7')) - && ((source[position + 8] == '1') && (source[position + 9] == '0'))) { - found = 1; - } + if (position + 9 < length && source[position] == '1' && source[position + 1] == '7' + && source[position + 8] == '1' && source[position + 9] == '0' + && dc_n_digits(source, length, position + 2, 6) >= 6) { + return 1; } - return found; + return 0; } -/* checks how many characters ahead can be reached while datum_c is true, +/* Checks how many characters ahead can be reached while dc_datum_c is true, * returning the resulting number of codewords (Annex F.II.E) */ -static int ahead_c(const unsigned char source[], const int position, const int length) { +static int dc_ahead_c(const unsigned char source[], const int length, const int position) { int count = 0; int i; - for (i = position; (i < length) && datum_c(source, i, length); i += 2) { + for (i = position; (i < length) && dc_datum_c(source, length, i); i += 2) { count++; } @@ -472,25 +451,24 @@ static int ahead_c(const unsigned char source[], const int position, const int l } /* Annex F.II.F */ -static int try_c(const unsigned char source[], const int position, const int length) { - int retval = 0; +static int dc_try_c(const unsigned char source[], const int length, const int position) { - if (n_digits(source, position, length) > 0) { - if (ahead_c(source, position, length) > ahead_c(source, position + 1, length)) { - retval = ahead_c(source, position, length); + if (position < length && source[position] >= '0' && source[position] <= '9') { /* dc_n_digits(position) > 0 */ + const int ahead_c_position = dc_ahead_c(source, length, position); + if (ahead_c_position > dc_ahead_c(source, length, position + 1)) { + return ahead_c_position; } } - return retval; + return 0; } /* Annex F.II.G */ -static int ahead_a(const unsigned char source[], const int position, const int length) { +static int dc_ahead_a(const unsigned char source[], const int length, const int position) { int count = 0; int i; - for (i = position; ((i < length) && datum_a(source, i, length)) - && (try_c(source, i, length) < 2); i++) { + for (i = position; i < length && dc_datum_a(source, length, i) && dc_try_c(source, length, i) < 2; i++) { count++; } @@ -498,12 +476,12 @@ static int ahead_a(const unsigned char source[], const int position, const int l } /* Annex F.II.H Note: changed to return number of chars encodable. Number of codewords returned in *p_nx. */ -static int ahead_b(const unsigned char source[], const int position, const int length, int *p_nx) { +static int dc_ahead_b(const unsigned char source[], const int length, const int position, int *p_nx) { int count = 0; int i, incr; - for (i = position; (i < length) && (incr = datum_b(source, i, length)) - && (try_c(source, i, length) < 2); i += incr) { + for (i = position; i < length && (incr = dc_datum_b(source, length, i)) + && dc_try_c(source, length, i) < 2; i += incr) { count++; } @@ -514,680 +492,561 @@ static int ahead_b(const unsigned char source[], const int position, const int l return i - position; } -/* checks if the next character is in the range 128 to 255 (Annex F.II.I) */ -static int binary(const unsigned char source[], const int length, const int position) { - int retval = 0; +/* Checks if the next character is in the range 128 to 255 (Annex F.II.I) */ +static int dc_binary(const unsigned char source[], const int length, const int position) { if (position < length && source[position] >= 128) { - retval = 1; + return 1; } - return retval; + return 0; +} + +/* Empty binary buffer */ +static int dc_empty_bin_buf(unsigned char *codeword_array, int ap, uint64_t *p_bin_buf, int *p_bin_buf_size) { + int i; + int lawrencium[6]; // Reversed radix 103 values + uint64_t bin_buf = *p_bin_buf; + int bin_buf_size = *p_bin_buf_size; + + if (bin_buf_size) { + for (i = 0; i < bin_buf_size + 1; i++) { + lawrencium[i] = (int) (bin_buf % 103); + bin_buf /= 103; + } + + for (i = 0; i < bin_buf_size + 1; i++) { + codeword_array[ap++] = lawrencium[bin_buf_size - i]; + } + } + + *p_bin_buf = 0; + *p_bin_buf_size = 0; + + return ap; +} + +/* Add value to binary buffer, emptying if full */ +static int dc_append_to_bin_buf(unsigned char *codeword_array, int ap, unsigned int val, uint64_t *p_bin_buf, + int *p_bin_buf_size) { + + *p_bin_buf *= 259; + *p_bin_buf += val; + (*p_bin_buf_size)++; + + if (*p_bin_buf_size == 5) { + ap = dc_empty_bin_buf(codeword_array, ap, p_bin_buf, p_bin_buf_size); + } + + return ap; } /* Analyse input data stream and encode using algorithm from Annex F */ -static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned char source[], const int length, - unsigned char *codeword_array, int *binary_finish) { +static int dc_encode_message(struct zint_symbol *symbol, const unsigned char source[], const int length, + const int eci, const int last_seg, const int last_EOT, const int last_RSEOT, + int ap, unsigned char *codeword_array, char *p_encoding_mode, int *p_inside_macro, + uint64_t *p_bin_buf, int *p_bin_buf_size, unsigned char structapp_array[], int *p_structapp_size) { static const char lead_specials[] = "\x09\x1C\x1D\x1E"; // HT, FS, GS, RS - int input_position, array_length, i; - char encoding_mode; - int inside_macro; - const int debug_print = (symbol->debug & ZINT_DEBUG_PRINT); - int binary_buffer_size = 0; - int lawrencium[6]; // Reversed radix 103 values + int i; + int position = 0; + char encoding_mode = *p_encoding_mode; + int inside_macro = *p_inside_macro; + uint64_t bin_buf = *p_bin_buf; + int bin_buf_size = *p_bin_buf_size; int nx; - uint64_t binary_buffer = 0; + const int first_seg = ap == 0; + const int gs1 = (symbol->input_mode & 0x07) == GS1_MODE; + const int debug_print = (symbol->debug & ZINT_DEBUG_PRINT); - input_position = 0; - array_length = 0; - encoding_mode = 'C'; - inside_macro = 0; + if (first_seg) { + if (symbol->output_options & READER_INIT) { + codeword_array[ap++] = 109; // FNC3 - if (symbol->output_options & READER_INIT) { - codeword_array[array_length] = 109; // FNC3 - array_length++; - } + } else if (!gs1 && eci == 0 && length > 2 && is_twodigits(source, length, 0)) { + codeword_array[ap++] = 107; // FNC1 - if ((symbol->input_mode & 0x07) != GS1_MODE) { - if (length > 2) { - if (((source[input_position] >= '0') && (source[input_position] <= '9')) && - ((source[input_position + 1] >= '0') && (source[input_position + 1] <= '9'))) { - codeword_array[array_length] = 107; // FNC1 - array_length++; + } else if (posn(lead_specials, source[0]) != -1) { + // Prevent encodation as a macro if a special character is in first position + codeword_array[ap++] = 101; // Latch A + codeword_array[ap++] = source[0] + 64; + encoding_mode = 'A'; + position++; + + } else if (length > 5) { // Note assuming macro headers don't straddle segments + /* Step C1 */ + if (source[0] == '[' && source[1] == ')' && source[2] == '>' && source[3] == 30 /*RS*/ && last_EOT) { + int format_050612 = (source[4] == '0' && (source[5] == '5' || source[5] == '6')) + || (source[4] == '1' && source[5] == '2'); + inside_macro = 0; + if (length > 6 && format_050612 && source[6] == 29 /*GS*/ && last_RSEOT) { + if (source[5] == '5') { + inside_macro = 97; + } else if (source[5] == '6') { + inside_macro = 98; + } else { + inside_macro = 99; + } + } else if (!format_050612 && is_twodigits(source, length, 4) ) { + inside_macro = 100; /* Note no longer using for malformed 05/06/12 */ + } + if (inside_macro) { + codeword_array[ap++] = 106; // Latch B + encoding_mode = 'B'; + codeword_array[ap++] = inside_macro; // Macro + if (inside_macro == 100) { + codeword_array[ap++] = ctoi(source[4]) + 16; + codeword_array[ap++] = ctoi(source[5]) + 16; + position += 6; + } else { + position += 7; + } + if (debug_print) printf("C1/%d ", inside_macro - 96); + } } } } - if (symbol->eci > 0) { - codeword_array[array_length] = 108; // FNC2 - array_length++; - if (symbol->eci <= 39) { - codeword_array[array_length] = symbol->eci; - array_length++; + if (eci > 0) { + if (encoding_mode == 'X') { + if (eci <= 0xFF) { + ap = dc_append_to_bin_buf(codeword_array, ap, 256, &bin_buf, &bin_buf_size); + ap = dc_append_to_bin_buf(codeword_array, ap, eci, &bin_buf, &bin_buf_size); + /* Following BWIPP, assuming big-endian byte order */ + } else if (eci <= 0xFFFF) { + ap = dc_append_to_bin_buf(codeword_array, ap, 257, &bin_buf, &bin_buf_size); + ap = dc_append_to_bin_buf(codeword_array, ap, eci >> 8, &bin_buf, &bin_buf_size); + ap = dc_append_to_bin_buf(codeword_array, ap, eci & 0xFF, &bin_buf, &bin_buf_size); + } else { + ap = dc_append_to_bin_buf(codeword_array, ap, 258, &bin_buf, &bin_buf_size); + ap = dc_append_to_bin_buf(codeword_array, ap, eci >> 16, &bin_buf, &bin_buf_size); + ap = dc_append_to_bin_buf(codeword_array, ap, (eci >> 8) & 0xFF, &bin_buf, &bin_buf_size); + ap = dc_append_to_bin_buf(codeword_array, ap, eci & 0xFF, &bin_buf, &bin_buf_size); + } } else { - // the next three codewords valued A, B & C encode the ECI value of - // (A - 40) * 12769 + B * 113 + C + 40 (Section 5.2.1) - int a, b, c; - a = (symbol->eci - 40) / 12769; - b = ((symbol->eci - 40) - (12769 * a)) / 113; - c = (symbol->eci - 40) - (12769 * a) - (113 * b); + codeword_array[ap++] = 108; // FNC2 + if (eci <= 39) { + codeword_array[ap++] = eci; + } else { + // the next three codewords valued A, B & C encode the ECI value of + // (A - 40) * 12769 + B * 113 + C + 40 (Section 5.2.1) + int a, b, c; + a = (eci - 40) / 12769; + b = ((eci - 40) - (12769 * a)) / 113; + c = (eci - 40) - (12769 * a) - (113 * b); - codeword_array[array_length] = a + 40; - array_length++; - codeword_array[array_length] = b; - array_length++; - codeword_array[array_length] = c; - array_length++; + codeword_array[ap++] = a + 40; + codeword_array[ap++] = b; + codeword_array[ap++] = c; + } } } - // Prevent encodation as a macro if a special character is in first position - if (posn(lead_specials, source[input_position]) != -1) { - codeword_array[array_length] = 101; // Latch A - array_length++; - codeword_array[array_length] = source[input_position] + 64; - array_length++; - encoding_mode = 'A'; - input_position++; - } - - while (input_position < length) { - int done = 0; + while (position < length) { /* Step A */ - if ((input_position == length - 2) && (inside_macro != 0) && (inside_macro != 100)) { + if (last_seg && (position == length - 2) && (inside_macro != 0) && (inside_macro != 100)) { // inside_macro only gets set to 97, 98 or 99 if the last two characters are RS/EOT - input_position += 2; - done = 1; - if (debug_print) { - printf("A "); - } + position += 2; + if (debug_print) printf("A "); + continue; } /* Step B */ - if ((input_position == length - 1) && (inside_macro == 100)) { + if (last_seg && (position == length - 1) && (inside_macro == 100)) { // inside_macro only gets set to 100 if the last character is EOT - input_position++; - done = 1; - if (debug_print) { - printf("B "); - } + position++; + if (debug_print) printf("B "); + continue; } - /* Step C1 */ - if ((!done) && (encoding_mode == 'C')) { - if ((array_length == 0) && (length > 6)) { - if ((source[input_position] == '[') - && (source[input_position + 1] == ')') - && (source[input_position + 2] == '>') - && (source[input_position + 3] == 30) // RS - && (source[length - 1] == 4)) { // EOT + if (encoding_mode == 'C') { + /* Step C2 */ + if (dc_seventeen_ten(source, length, position)) { + codeword_array[ap++] = 100; // (17)...(10) + codeword_array[ap++] = to_int(source + position + 2, 2); + codeword_array[ap++] = to_int(source + position + 4, 2); + codeword_array[ap++] = to_int(source + position + 6, 2); + position += 10; + if (debug_print) printf("C2/1 "); + continue; + } - if ((source[input_position + 6] == 29) && (source[length - 2] == 30)) { // GS/RS - if ((source[input_position + 4] == '0') && (source[input_position + 5] == '5')) { - codeword_array[array_length] = 106; // Latch B - array_length++; - encoding_mode = 'B'; - codeword_array[array_length] = 97; // Macro - array_length++; - input_position += 7; - inside_macro = 97; - done = 1; - if (debug_print) { - printf("C1/1 "); - } - } + if (dc_datum_c(source, length, position) || (source[position] == '[' && gs1)) { + if (source[position] == '[') { + codeword_array[ap++] = 107; // FNC1 + position++; + } else { + codeword_array[ap++] = to_int(source + position, 2); + position += 2; + } + if (debug_print) printf("C2/2 "); + continue; + } - if ((!done) && (source[input_position + 4] == '0') && (source[input_position + 5] == '6')) { - codeword_array[array_length] = 106; // Latch B - array_length++; - encoding_mode = 'B'; - codeword_array[array_length] = 98; // Macro - array_length++; - input_position += 7; - inside_macro = 98; - done = 1; - if (debug_print) { - printf("C1/2 "); - } - } - - if ((!done) && (source[input_position + 4] == '1') && (source[input_position + 5] == '2')) { - codeword_array[array_length] = 106; // Latch B - array_length++; - encoding_mode = 'B'; - codeword_array[array_length] = 99; // Macro - array_length++; - input_position += 7; - inside_macro = 99; - done = 1; - if (debug_print) { - printf("C1/3 "); - } - } + /* Step C3 */ + if (dc_binary(source, length, position)) { + /* dc_n_digits(position + 1) > 0 */ + if (position + 1 < length && source[position + 1] >= '0' && source[position + 1] <= '9') { + if ((source[position] - 128) < 32) { + codeword_array[ap++] = 110; // Upper Shift A + codeword_array[ap++] = source[position] - 128 + 64; + } else { + codeword_array[ap++] = 111; // Upper Shift B + codeword_array[ap++] = source[position] - 128 - 32; } + position++; + } else { + codeword_array[ap++] = 112; // Bin Latch + encoding_mode = 'X'; + } + if (debug_print) printf("C3 "); + continue; + } - if ((!done) && (source[input_position + 4] >= '0') && (source[input_position + 4] <= '9') && - (source[input_position + 5] >= '0') && (source[input_position + 5] <= '9')) { - codeword_array[array_length] = 106; // Latch B - array_length++; + /* Step C4 */ + { + const int m = dc_ahead_a(source, length, position); + const int n = dc_ahead_b(source, length, position, &nx); + if (m > n) { + codeword_array[ap++] = 101; // Latch A + encoding_mode = 'A'; + } else { + if (nx >= 1 && nx <= 4) { + codeword_array[ap++] = 101 + nx; // nx Shift B + + for (i = 0; i < nx; i++) { + if (source[position] >= 32) { + codeword_array[ap++] = source[position] - 32; + } else if (source[position] == 13) { // CR/LF + codeword_array[ap++] = 96; + position++; + } else { + switch (source[position]) { + case 9: codeword_array[ap++] = 97; break; // HT + case 28: codeword_array[ap++] = 98; break; // FS + case 29: codeword_array[ap++] = 99; break; // GS + case 30: codeword_array[ap++] = 100; break; // RS + } + } + position++; + } + } else { + codeword_array[ap++] = 106; // Latch B encoding_mode = 'B'; - codeword_array[array_length] = 100; // Macro - array_length++; - input_position += 4; - inside_macro = 100; - done = 1; - if (debug_print) { - printf("C1/4 "); - } } } + if (debug_print) printf("C4 "); + continue; } - } + } /* encoding_mode == 'C' */ - /* Step C2 */ - if ((!done) && (encoding_mode == 'C')) { - if (seventeen_ten(source, input_position, length)) { - codeword_array[array_length] = 100; // (17)...(10) - array_length++; - codeword_array[array_length] = to_int(source + input_position + 2, 2); - array_length++; - codeword_array[array_length] = to_int(source + input_position + 4, 2); - array_length++; - codeword_array[array_length] = to_int(source + input_position + 6, 2); - array_length++; - input_position += 10; - done = 1; - if (debug_print) { - printf("C2/1 "); - } - } - } - - if ((!done) && (encoding_mode == 'C')) { - if (datum_c(source, input_position, length) - || ((source[input_position] == '[') && ((symbol->input_mode & 0x07) == GS1_MODE))) { - if (source[input_position] == '[') { - codeword_array[array_length] = 107; // FNC1 - input_position++; - } else { - codeword_array[array_length] = to_int(source + input_position, 2); - input_position += 2; - } - array_length++; - done = 1; - if (debug_print) { - printf("C2/2 "); - } - } - } - - /* Step C3 */ - if ((!done) && (encoding_mode == 'C')) { - if (binary(source, length, input_position)) { - if (n_digits(source, input_position + 1, length) > 0) { - if ((source[input_position] - 128) < 32) { - codeword_array[array_length] = 110; // Upper Shift A - array_length++; - codeword_array[array_length] = source[input_position] - 128 + 64; - array_length++; - } else { - codeword_array[array_length] = 111; // Upper Shift B - array_length++; - codeword_array[array_length] = source[input_position] - 128 - 32; - array_length++; - } - input_position++; - } else { - codeword_array[array_length] = 112; // Bin Latch - array_length++; - encoding_mode = 'X'; - } - done = 1; - if (debug_print) { - printf("C3 "); - } - } - } - - /* Step C4 */ - if ((!done) && (encoding_mode == 'C')) { - const int m = ahead_a(source, input_position, length); - const int n = ahead_b(source, input_position, length, &nx); - if (m > n) { - codeword_array[array_length] = 101; // Latch A - array_length++; - encoding_mode = 'A'; - } else { - if (nx >= 1 && nx <= 4) { - codeword_array[array_length] = 101 + nx; // nx Shift B - array_length++; - - for (i = 0; i < nx; i++) { - if (source[input_position] >= 32) { - codeword_array[array_length] = source[input_position] - 32; - } else if (source[input_position] == 13) { // CR/LF - codeword_array[array_length] = 96; - input_position++; - } else { - switch (source[input_position]) { - case 9: codeword_array[array_length] = 97; break; // HT - case 28: codeword_array[array_length] = 98; break; // FS - case 29: codeword_array[array_length] = 99; break; // GS - case 30: codeword_array[array_length] = 100; break; // RS - } - } - array_length++; - input_position++; - } - } else { - codeword_array[array_length] = 106; // Latch B - array_length++; - encoding_mode = 'B'; - } - } - done = 1; - if (debug_print) { - printf("C4 "); - } - } - - /* Step D1 */ - if ((!done) && (encoding_mode == 'B')) { - const int n = try_c(source, input_position, length); + if (encoding_mode == 'B') { + /* Step D1 */ + const int n = dc_try_c(source, length, position); if (n >= 2) { if (n <= 4) { - codeword_array[array_length] = 103 + (n - 2); // nx Shift C - array_length++; + codeword_array[ap++] = 103 + (n - 2); // nx Shift C for (i = 0; i < n; i++) { - codeword_array[array_length] = to_int(source + input_position, 2); - array_length++; - input_position += 2; + codeword_array[ap++] = to_int(source + position, 2); + position += 2; } } else { - codeword_array[array_length] = 106; // Latch C - array_length++; + codeword_array[ap++] = 106; // Latch C encoding_mode = 'C'; } - done = 1; - if (debug_print) { - printf("D1 "); - } + if (debug_print) printf("D1 "); + continue; } - } - /* Step D2 */ - if ((!done) && (encoding_mode == 'B')) { - if ((source[input_position] == '[') && ((symbol->input_mode & 0x07) == GS1_MODE)) { - codeword_array[array_length] = 107; // FNC1 - array_length++; - input_position++; - done = 1; - if (debug_print) { - printf("D2/1 "); - } - } else { - if (datum_b(source, input_position, length)) { - - if ((source[input_position] >= 32) && (source[input_position] <= 127)) { - codeword_array[array_length] = source[input_position] - 32; - done = 1; - - } else if (source[input_position] == 13) { - /* CR/LF */ - codeword_array[array_length] = 96; - input_position++; - done = 1; - - } else if (input_position != 0) { - /* HT, FS, GS and RS in the first data position would be interpreted as a macro - * (see table 2) */ - switch (source[input_position]) { - case 9: // HT - codeword_array[array_length] = 97; - break; - case 28: // FS - codeword_array[array_length] = 98; - break; - case 29: // GS - codeword_array[array_length] = 99; - break; - case 30: // RS - codeword_array[array_length] = 100; - break; - } - done = 1; - } - - if (done == 1) { - array_length++; - input_position++; - if (debug_print) { - printf("D2/2 "); - } - } - } + /* Step D2 */ + if ((source[position] == '[') && gs1) { + codeword_array[ap++] = 107; // FNC1 + position++; + if (debug_print) printf("D2/1 "); + continue; } - } - /* Step D3 */ - if ((!done) && (encoding_mode == 'B')) { - if (binary(source, length, input_position)) { - if (datum_b(source, input_position + 1, length)) { - if ((source[input_position] - 128) < 32) { - codeword_array[array_length] = 110; // Bin Shift A - array_length++; - codeword_array[array_length] = source[input_position] - 128 + 64; - array_length++; - } else { - codeword_array[array_length] = 111; // Bin Shift B - array_length++; - codeword_array[array_length] = source[input_position] - 128 - 32; - array_length++; - } - input_position++; - } else { - codeword_array[array_length] = 112; // Bin Latch - array_length++; - encoding_mode = 'X'; - } - done = 1; - if (debug_print) { - printf("D3 "); - } - } - } + if (dc_datum_b(source, length, position)) { + int done = 0; - /* Step D4 */ - if ((!done) && (encoding_mode == 'B')) { - if (ahead_a(source, input_position, length) == 1) { - codeword_array[array_length] = 101; // Shift A - array_length++; - if (source[input_position] < 32) { - codeword_array[array_length] = source[input_position] + 64; - } else { - codeword_array[array_length] = source[input_position] - 32; - } - array_length++; - input_position++; - } else { - codeword_array[array_length] = 102; // Latch A - array_length++; - encoding_mode = 'A'; - } - done = 1; - if (debug_print) { - printf("D4 "); - } - } - - /* Step E1 */ - if ((!done) && (encoding_mode == 'A')) { - const int n = try_c(source, input_position, length); - if (n >= 2) { - if (n <= 4) { - codeword_array[array_length] = 103 + (n - 2); // nx Shift C - array_length++; - for (i = 0; i < n; i++) { - codeword_array[array_length] = to_int(source + input_position, 2); - array_length++; - input_position += 2; - } - } else { - codeword_array[array_length] = 106; // Latch C - array_length++; - encoding_mode = 'C'; - } - done = 1; - if (debug_print) { - printf("E1 "); - } - } - } - - /* Step E2 */ - if ((!done) && (encoding_mode == 'A')) { - if ((source[input_position] == '[') && ((symbol->input_mode & 0x07) == GS1_MODE)) { - // Note: this branch probably never reached as no reason to be in Code Set A for GS1 data - codeword_array[array_length] = 107; // FNC1 - array_length++; - input_position++; - done = 1; - if (debug_print) { - printf("E2/1 "); - } - } else { - if (datum_a(source, input_position, length)) { - if (source[input_position] < 32) { - codeword_array[array_length] = source[input_position] + 64; - } else { - codeword_array[array_length] = source[input_position] - 32; - } - array_length++; - input_position++; + if ((source[position] >= 32) && (source[position] <= 127)) { + codeword_array[ap++] = source[position] - 32; done = 1; - if (debug_print) { - printf("E2/2 "); + + } else if (source[position] == 13) { + /* CR/LF */ + codeword_array[ap++] = 96; + position++; + done = 1; + + } else if (!first_seg || position != 0) { + /* HT, FS, GS and RS in the first data position would be interpreted as a macro + * (see table 2) */ + switch (source[position]) { + case 9: codeword_array[ap++] = 97; break; // HT + case 28: codeword_array[ap++] = 98; break; // FS + case 29: codeword_array[ap++] = 99; break; // GS + case 30: codeword_array[ap++] = 100; break; // RS } + done = 1; + } + + if (done == 1) { + position++; + if (debug_print) printf("D2/2 "); + continue; } } - } - /* Step E3 */ - if ((!done) && (encoding_mode == 'A')) { - if (binary(source, length, input_position)) { - if (datum_a(source, input_position + 1, length)) { - if ((source[input_position] - 128) < 32) { - codeword_array[array_length] = 110; // Bin Shift A - array_length++; - codeword_array[array_length] = source[input_position] - 128 + 64; - array_length++; + /* Step D3 */ + if (dc_binary(source, length, position)) { + if (dc_datum_b(source, length, position + 1)) { + if ((source[position] - 128) < 32) { + codeword_array[ap++] = 110; // Bin Shift A + codeword_array[ap++] = source[position] - 128 + 64; } else { - codeword_array[array_length] = 111; // Bin Shift B - array_length++; - codeword_array[array_length] = source[input_position] - 128 - 32; - array_length++; + codeword_array[ap++] = 111; // Bin Shift B + codeword_array[ap++] = source[position] - 128 - 32; } - input_position++; + position++; } else { - codeword_array[array_length] = 112; // Bin Latch - array_length++; + codeword_array[ap++] = 112; // Bin Latch encoding_mode = 'X'; } - done = 1; - if (debug_print) { - printf("E3 "); - } + if (debug_print) printf("D3 "); + continue; } - } - /* Step E4 */ - if ((!done) && (encoding_mode == 'A')) { - ahead_b(source, input_position, length, &nx); + /* Step D4 */ + if (dc_ahead_a(source, length, position) == 1) { + codeword_array[ap++] = 101; // Shift A + if (source[position] < 32) { + codeword_array[ap++] = source[position] + 64; + } else { + codeword_array[ap++] = source[position] - 32; + } + position++; + } else { + codeword_array[ap++] = 102; // Latch A + encoding_mode = 'A'; + } + if (debug_print) printf("D4 "); + continue; + } /* encoding_mode == 'B' */ + + if (encoding_mode == 'A') { + /* Step E1 */ + const int n = dc_try_c(source, length, position); + if (n >= 2) { + if (n <= 4) { + codeword_array[ap++] = 103 + (n - 2); // nx Shift C + for (i = 0; i < n; i++) { + codeword_array[ap++] = to_int(source + position, 2); + position += 2; + } + } else { + codeword_array[ap++] = 106; // Latch C + encoding_mode = 'C'; + } + if (debug_print) printf("E1 "); + continue; + } + + /* Step E2 */ + if ((source[position] == '[') && gs1) { + // Note: this branch probably never reached as no reason to be in Code Set A for GS1 data + codeword_array[ap++] = 107; // FNC1 + position++; + if (debug_print) printf("E2/1 "); + continue; + } + if (dc_datum_a(source, length, position)) { + if (source[position] < 32) { + codeword_array[ap++] = source[position] + 64; + } else { + codeword_array[ap++] = source[position] - 32; + } + position++; + if (debug_print) printf("E2/2 "); + continue; + } + + /* Step E3 */ + if (dc_binary(source, length, position)) { + if (dc_datum_a(source, length, position + 1)) { + if ((source[position] - 128) < 32) { + codeword_array[ap++] = 110; // Bin Shift A + codeword_array[ap++] = source[position] - 128 + 64; + } else { + codeword_array[ap++] = 111; // Bin Shift B + codeword_array[ap++] = source[position] - 128 - 32; + } + position++; + } else { + codeword_array[ap++] = 112; // Bin Latch + encoding_mode = 'X'; + } + if (debug_print) printf("E3 "); + continue; + } + + /* Step E4 */ + dc_ahead_b(source, length, position, &nx); if (nx >= 1 && nx <= 6) { - codeword_array[array_length] = 95 + nx; // nx Shift B - array_length++; + codeword_array[ap++] = 95 + nx; // nx Shift B for (i = 0; i < nx; i++) { - if (source[input_position] >= 32) { - codeword_array[array_length] = source[input_position] - 32; - } else if (source[input_position] == 13) { // CR/LF - codeword_array[array_length] = 96; - input_position++; + if (source[position] >= 32) { + codeword_array[ap++] = source[position] - 32; + } else if (source[position] == 13) { // CR/LF + codeword_array[ap++] = 96; + position++; } else { - switch (source[input_position]) { - case 9: codeword_array[array_length] = 97; break; // HT - case 28: codeword_array[array_length] = 98; break; // FS - case 29: codeword_array[array_length] = 99; break; // GS - case 30: codeword_array[array_length] = 100; break; // RS + switch (source[position]) { + case 9: codeword_array[ap++] = 97; break; // HT + case 28: codeword_array[ap++] = 98; break; // FS + case 29: codeword_array[ap++] = 99; break; // GS + case 30: codeword_array[ap++] = 100; break; // RS } } - array_length++; - input_position++; + position++; } } else { - codeword_array[array_length] = 102; // Latch B - array_length++; + codeword_array[ap++] = 102; // Latch B encoding_mode = 'B'; } - done = 1; - if (debug_print) { - printf("E4 "); - } - } + if (debug_print) printf("E4 "); + continue; + } /* encoding_mode == 'A' */ /* Step F1 */ - if ((!done) && (encoding_mode == 'X')) { - const int n = try_c(source, input_position, length); + if (encoding_mode == 'X') { + const int n = dc_try_c(source, length, position); if (n >= 2) { - /* Empty binary buffer */ - for (i = 0; i < (binary_buffer_size + 1); i++) { - lawrencium[i] = (int) (binary_buffer % 103); - binary_buffer /= 103; - } - - for (i = 0; i < (binary_buffer_size + 1); i++) { - codeword_array[array_length] = lawrencium[binary_buffer_size - i]; - array_length++; - } - binary_buffer = 0; - binary_buffer_size = 0; + ap = dc_empty_bin_buf(codeword_array, ap, &bin_buf, &bin_buf_size); if (n <= 7) { - codeword_array[array_length] = 101 + n; // Interrupt for nx Shift C - array_length++; + codeword_array[ap++] = 101 + n; // Interrupt for nx Shift C for (i = 0; i < n; i++) { - codeword_array[array_length] = to_int(source + input_position, 2); - array_length++; - input_position += 2; + codeword_array[ap++] = to_int(source + position, 2); + position += 2; } } else { - codeword_array[array_length] = 111; // Terminate with Latch to C - array_length++; + codeword_array[ap++] = 111; // Terminate with Latch to C encoding_mode = 'C'; } - done = 1; - if (debug_print) { - printf("F1 "); - } - } - } - - /* Step F2 */ - /* Section 5.2.1.1 para D.2.i states: - * "Groups of six codewords, each valued between 0 and 102, are radix converted from - * base 103 into five base 259 values..." - */ - if ((!done) && (encoding_mode == 'X')) { - if (binary(source, length, input_position) - || binary(source, length, input_position + 1) - || binary(source, length, input_position + 2) - || binary(source, length, input_position + 3)) { - binary_buffer *= 259; - binary_buffer += source[input_position]; - binary_buffer_size++; - - if (binary_buffer_size == 5) { - for (i = 0; i < 6; i++) { - lawrencium[i] = (int) (binary_buffer % 103); - binary_buffer /= 103; - } - - for (i = 0; i < 6; i++) { - codeword_array[array_length] = lawrencium[5 - i]; - array_length++; - } - binary_buffer = 0; - binary_buffer_size = 0; - } - input_position++; - done = 1; - if (debug_print) { - printf("F2 "); - } - } - } - - /* Step F3 */ - if ((!done) && (encoding_mode == 'X')) { - /* Empty binary buffer */ - for (i = 0; i < (binary_buffer_size + 1); i++) { - lawrencium[i] = (int) (binary_buffer % 103); - binary_buffer /= 103; + if (debug_print) printf("F1 "); + continue; } - for (i = 0; i < (binary_buffer_size + 1); i++) { - codeword_array[array_length] = lawrencium[binary_buffer_size - i]; - array_length++; + /* Step F2 */ + /* Section 5.2.1.1 para D.2.i states: + * "Groups of six codewords, each valued between 0 and 102, are radix converted from + * base 103 into five base 259 values..." + */ + if (dc_binary(source, length, position) + || dc_binary(source, length, position + 1) + || dc_binary(source, length, position + 2) + || dc_binary(source, length, position + 3)) { + ap = dc_append_to_bin_buf(codeword_array, ap, source[position], &bin_buf, &bin_buf_size); + position++; + if (debug_print) printf("F2 "); + continue; } - binary_buffer = 0; - binary_buffer_size = 0; - if (ahead_a(source, input_position, length) > ahead_b(source, input_position, length, NULL)) { - codeword_array[array_length] = 109; // Terminate with Latch to A + /* Step F3 */ + ap = dc_empty_bin_buf(codeword_array, ap, &bin_buf, &bin_buf_size); /* Empty binary buffer */ + + if (dc_ahead_a(source, length, position) > dc_ahead_b(source, length, position, NULL)) { + codeword_array[ap++] = 109; // Terminate with Latch to A encoding_mode = 'A'; } else { - codeword_array[array_length] = 110; // Terminate with Latch to B + codeword_array[ap++] = 110; // Terminate with Latch to B encoding_mode = 'B'; } - array_length++; - // done = 1 // As long as last branch not needed - if (debug_print) { - printf("F3 "); - } - } + if (debug_print) printf("F3 "); + } /* encoding_mode == 'X' */ } - if (encoding_mode == 'X') { - if (binary_buffer_size != 0) { + if (last_seg) { + if (encoding_mode == 'X' && bin_buf_size != 0) { /* Empty binary buffer */ - for (i = 0; i < (binary_buffer_size + 1); i++) { - lawrencium[i] = (int) (binary_buffer % 103); - binary_buffer /= 103; - } + ap = dc_empty_bin_buf(codeword_array, ap, &bin_buf, &bin_buf_size); + } - for (i = 0; i < (binary_buffer_size + 1); i++) { - codeword_array[array_length] = lawrencium[binary_buffer_size - i]; - array_length++; + if (symbol->structapp.count) { + int sp = 0; + /* Need Code Set A or B - choosing A here (TEC-IT chooses B) */ + if (encoding_mode == 'C') { + structapp_array[sp++] = 101; /* Latch A */ + } else if (encoding_mode == 'X') { + structapp_array[sp++] = 109; /* Terminate with Latch A */ } + if (symbol->structapp.index < 10) { + structapp_array[sp++] = 16 + symbol->structapp.index; /* '0' + index for 1-9 */ + } else { + structapp_array[sp++] = 33 + symbol->structapp.index - 10; /* 'A' + index for A-Z */ + } + if (symbol->structapp.count < 10) { + structapp_array[sp++] = 16 + symbol->structapp.count; /* '0' + count for 1-9 */ + } else { + structapp_array[sp++] = 33 + symbol->structapp.count - 10; /* 'A' + count for A-Z */ + } + structapp_array[sp++] = 108; /* FNC2 as last codeword */ + *p_structapp_size = sp; } - *(binary_finish) = 1; - } - - if (symbol->structapp.count) { - /* Need Code Set A or B - choosing A here (TEC-IT chooses B) */ - if (encoding_mode == 'C') { - codeword_array[array_length++] = 101; /* Latch A */ - } else if (encoding_mode == 'X') { - codeword_array[array_length++] = 109; /* Terminate with Latch A */ - *binary_finish = 0; - } - if (symbol->structapp.index < 10) { - codeword_array[array_length++] = 16 + symbol->structapp.index; /* '0' + index for 1-9 */ - } else { - codeword_array[array_length++] = 33 + symbol->structapp.index - 10; /* 'A' + index for A-Z */ - } - if (symbol->structapp.count < 10) { - codeword_array[array_length++] = 16 + symbol->structapp.count; /* '0' + count for 1-9 */ - } else { - codeword_array[array_length++] = 33 + symbol->structapp.count - 10; /* 'A' + count for A-Z */ - } - codeword_array[array_length++] = 108; /* FNC2 as last codeword */ } if (debug_print) { printf("\n"); } - return array_length; + *p_encoding_mode = encoding_mode; + *p_inside_macro = inside_macro; + *p_bin_buf = bin_buf; + *p_bin_buf_size = bin_buf_size; + + return ap; +} + +/* Call `dc_encode_message()` for each segment */ +static int dc_encode_message_segs(struct zint_symbol *symbol, const struct zint_seg segs[], const int seg_count, + unsigned char *codeword_array, int *p_binary_finish, unsigned char structapp_array[], + int *p_structapp_size) { + int i; + + int last_EOT = 0; + int last_RSEOT = 0; + int ap = 0; + char encoding_mode = 'C'; + int inside_macro = 0; + uint64_t bin_buf = 0; + int bin_buf_size = 0; + + const struct zint_seg *last_seg = &segs[seg_count - 1]; + + last_EOT = last_seg->source[last_seg->length - 1] == 4; // EOT + if (last_EOT && last_seg->length > 1) { + last_RSEOT = last_seg->source[last_seg->length - 2] == 30; // RS + } + + for (i = 0; i < seg_count; i++) { + ap = dc_encode_message(symbol, segs[i].source, segs[i].length, segs[i].eci, i == seg_count - 1 /*last_seg*/, + last_EOT, last_RSEOT, ap, codeword_array, &encoding_mode, &inside_macro, &bin_buf, &bin_buf_size, + structapp_array, p_structapp_size); + } + + *p_binary_finish = encoding_mode == 'X'; + + return ap + *p_structapp_size; } /* Convert codewords to binary data stream */ -static int make_dotstream(const unsigned char masked_array[], const int array_length, char dot_stream[]) { +static int dc_make_dotstream(const unsigned char masked_array[], const int array_length, char dot_stream[]) { int i; int bp = 0; @@ -1196,7 +1055,7 @@ static int make_dotstream(const unsigned char masked_array[], const int array_le /* The rest of the data uses 9-bit dot patterns from Annex C */ for (i = 1; i < array_length; i++) { - bp = bin_append_posn(dot_patterns[masked_array[i]], 9, dot_stream, bp); + bp = bin_append_posn(dc_dot_patterns[masked_array[i]], 9, dot_stream, bp); } return bp; @@ -1205,62 +1064,60 @@ static int make_dotstream(const unsigned char masked_array[], const int array_le /* Determines if a given dot is a reserved corner dot * to be used by one of the last six bits */ -static int is_corner(const int column, const int row, const int width, const int height) { - int corner = 0; +static int dc_is_corner(const int column, const int row, const int width, const int height) { /* Top Left */ if ((column == 0) && (row == 0)) { - corner = 1; + return 1; } /* Top Right */ - if (height % 2) { + if (height & 1) { if (((column == width - 2) && (row == 0)) || ((column == width - 1) && (row == 1))) { - corner = 1; + return 1; } } else { if ((column == width - 1) && (row == 0)) { - corner = 1; + return 1; } } /* Bottom Left */ - if (height % 2) { + if (height & 1) { if ((column == 0) && (row == height - 1)) { - corner = 1; + return 1; } } else { if (((column == 0) && (row == height - 2)) || ((column == 1) && (row == height - 1))) { - corner = 1; + return 1; } } /* Bottom Right */ if (((column == width - 2) && (row == height - 1)) || ((column == width - 1) && (row == height - 2))) { - corner = 1; + return 1; } - return corner; + return 0; } /* Place the dots in the symbol*/ -static void fold_dotstream(const char dot_stream[], const int width, const int height, char dot_array[]) { +static void dc_fold_dotstream(const char dot_stream[], const int width, const int height, char dot_array[]) { int column, row; - int input_position = 0; + int position = 0; - if (height % 2) { + if (height & 1) { /* Horizontal folding */ for (row = 0; row < height; row++) { for (column = 0; column < width; column++) { - if (!((column + row) % 2)) { - if (is_corner(column, row, width, height)) { + if (!((column + row) & 1)) { + if (dc_is_corner(column, row, width, height)) { dot_array[(row * width) + column] = 'C'; } else { - dot_array[((height - row - 1) * width) + column] = dot_stream[input_position]; - input_position++; + dot_array[((height - row - 1) * width) + column] = dot_stream[position++]; } } else { dot_array[((height - row - 1) * width) + column] = ' '; // Non-data position @@ -1269,27 +1126,21 @@ static void fold_dotstream(const char dot_stream[], const int width, const int h } /* Corners */ - dot_array[width - 2] = dot_stream[input_position]; - input_position++; - dot_array[(height * width) - 2] = dot_stream[input_position]; - input_position++; - dot_array[(width * 2) - 1] = dot_stream[input_position]; - input_position++; - dot_array[((height - 1) * width) - 1] = dot_stream[input_position]; - input_position++; - dot_array[0] = dot_stream[input_position]; - input_position++; - dot_array[(height - 1) * width] = dot_stream[input_position]; + dot_array[width - 2] = dot_stream[position++]; + dot_array[(height * width) - 2] = dot_stream[position++]; + dot_array[(width * 2) - 1] = dot_stream[position++]; + dot_array[((height - 1) * width) - 1] = dot_stream[position++]; + dot_array[0] = dot_stream[position++]; + dot_array[(height - 1) * width] = dot_stream[position]; } else { /* Vertical folding */ for (column = 0; column < width; column++) { for (row = 0; row < height; row++) { - if (!((column + row) % 2)) { - if (is_corner(column, row, width, height)) { + if (!((column + row) & 1)) { + if (dc_is_corner(column, row, width, height)) { dot_array[(row * width) + column] = 'C'; } else { - dot_array[(row * width) + column] = dot_stream[input_position]; - input_position++; + dot_array[(row * width) + column] = dot_stream[position++]; } } else { dot_array[(row * width) + column] = ' '; // Non-data position @@ -1298,26 +1149,22 @@ static void fold_dotstream(const char dot_stream[], const int width, const int h } /* Corners */ - dot_array[((height - 1) * width) - 1] = dot_stream[input_position]; - input_position++; - dot_array[(height - 2) * width] = dot_stream[input_position]; - input_position++; - dot_array[(height * width) - 2] = dot_stream[input_position]; - input_position++; - dot_array[((height - 1) * width) + 1] = dot_stream[input_position]; - input_position++; - dot_array[width - 1] = dot_stream[input_position]; - input_position++; - dot_array[0] = dot_stream[input_position]; + dot_array[((height - 1) * width) - 1] = dot_stream[position++]; + dot_array[(height - 2) * width] = dot_stream[position++]; + dot_array[(height * width) - 2] = dot_stream[position++]; + dot_array[((height - 1) * width) + 1] = dot_stream[position++]; + dot_array[width - 1] = dot_stream[position++]; + dot_array[0] = dot_stream[position]; } } -static void apply_mask(const int mask, const int data_length, unsigned char *masked_codeword_array, +static void dc_apply_mask(const int mask, const int data_length, unsigned char *masked_codeword_array, const unsigned char *codeword_array, const int ecc_length) { int weight = 0; int j; assert(mask >= 0 && mask <= 3); /* Suppress clang-analyzer taking default branch */ + assert(data_length > 0); /* Suppress clang-analyzer-core.UndefinedBinaryOperatorResult */ switch (mask) { case 0: masked_codeword_array[0] = 0; @@ -1348,11 +1195,11 @@ static void apply_mask(const int mask, const int data_length, unsigned char *mas break; } - rsencode(data_length + 1, ecc_length, masked_codeword_array); + dc_rsencode(data_length + 1, ecc_length, masked_codeword_array); } -static void force_corners(const int width, const int height, char *dot_array) { - if (width % 2) { +static void dc_force_corners(const int width, const int height, char *dot_array) { + if (width & 1) { // "Vertical" symbol dot_array[0] = '1'; dot_array[width - 1] = '1'; @@ -1371,7 +1218,7 @@ static void force_corners(const int width, const int height, char *dot_array) { } } -INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int length) { +INTERNAL int dotcode(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { int i, j, k; int jc, n_dots; int data_length, ecc_length; @@ -1382,10 +1229,13 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len int dot_stream_length; int high_score, best_mask; int binary_finish = 0; + unsigned char structapp_array[5]; + int structapp_size = 0; + int padding_dots; const int debug_print = (symbol->debug & ZINT_DEBUG_PRINT); - int padding_dots, is_first; - /* Allow 4 codewords per input + 2 (FNC) + 4 (ECI) + 2 (special char 1st position) + 4 (Structured Append) */ - const int codeword_array_len = length * 4 + 2 + 4 + 2 + 4; + /* Allow 4 codewords per input + 2 (FNC) + seg_count * 4 (ECI) + 2 (special char 1st position) + + 5 (Structured Append) + 10 (PAD) */ + const int codeword_array_len = segs_length(segs, seg_count) * 4 + 2 + seg_count * 4 + 2 + 5 + 10; #ifndef _MSC_VER unsigned char codeword_array[codeword_array_len]; @@ -1421,7 +1271,8 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len } } - data_length = dotcode_encode_message(symbol, source, length, codeword_array, &binary_finish); + data_length = dc_encode_message_segs(symbol, segs, seg_count, codeword_array, &binary_finish, structapp_array, + &structapp_size); /* Suppresses clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult/uninitialized.ArraySubscript * warnings */ @@ -1429,20 +1280,6 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len ecc_length = 3 + (data_length / 2); - if (debug_print) { - printf("Codeword length = %d, ECC length = %d\n", data_length, ecc_length); - printf("Codewords: "); - for (i = 0; i < data_length; i++) { - printf("[%d] ",codeword_array[i]); - } - printf("\n"); - } -#ifdef ZINT_TEST - if (symbol->debug & ZINT_DEBUG_TEST) { - debug_test_codeword_dump(symbol, codeword_array, data_length); - } -#endif - min_dots = 9 * (data_length + 3 + (data_length / 2)) + 2; min_area = min_dots * 2; @@ -1491,7 +1328,7 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len width = symbol->option_2; height = (min_area + (width - 1)) / width; - if (!((width + height) % 2)) { + if (!((width + height) & 1)) { height++; } } @@ -1532,29 +1369,60 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len /* Add pad characters */ padding_dots = n_dots - min_dots; /* get the number of free dots available for padding */ - is_first = 1; /* first padding character flag */ - while (padding_dots >= 9) { - if (padding_dots < 18 && ((data_length % 2) == 0)) - padding_dots -= 9; - - else if (padding_dots >= 18) { - if ((data_length % 2) == 0) + if (padding_dots >= 9) { + int is_first = 1; /* first padding character flag */ + int padp = data_length - structapp_size; + while (padding_dots >= 9) { + if (padding_dots < 18 && (data_length & 1) == 0) { padding_dots -= 9; - else - padding_dots -= 18; - } else - break; /* not enough padding dots left for padding */ + } else if (padding_dots >= 18) { + if ((data_length & 1) == 0) { + padding_dots -= 9; + } else { + padding_dots -= 18; + } + } else { + break; /* not enough padding dots left for padding */ + } + if (is_first && binary_finish) { + codeword_array[padp++] = 109; + } else { + codeword_array[padp++] = 106; + } - if ((is_first == 1) && (binary_finish == 1)) - codeword_array[data_length] = 109; - else - codeword_array[data_length] = 106; - - data_length++; - is_first = 0; + data_length++; + is_first = 0; + } + if (structapp_size) { + if (structapp_array[0] == 109) { /* Binary latch no longer valid */ + structapp_array[0] = 106; + } + for (i = 0; i < structapp_size; i++) { + codeword_array[padp++] = structapp_array[i]; + } + } + } else if (structapp_size) { + data_length -= structapp_size; + for (i = 0; i < structapp_size; i++) { + codeword_array[data_length++] = structapp_array[i]; + } } + if (debug_print) { + printf("Codeword length = %d, ECC length = %d\n", data_length, ecc_length); + printf("Codewords:"); + for (i = 0; i < data_length; i++) { + printf(" %d", codeword_array[i]); + } + printf("\n"); + } +#ifdef ZINT_TEST + if (symbol->debug & ZINT_DEBUG_TEST) { + debug_test_codeword_dump(symbol, codeword_array, data_length); + } +#endif + ecc_length = 3 + (data_length / 2); #ifndef _MSC_VER @@ -1572,18 +1440,18 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len /* Evaluate data mask options */ for (i = 0; i < 4; i++) { - apply_mask(i, data_length, masked_codeword_array, codeword_array, ecc_length); + dc_apply_mask(i, data_length, masked_codeword_array, codeword_array, ecc_length); - dot_stream_length = make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream); + dot_stream_length = dc_make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream); /* Add pad bits */ for (jc = dot_stream_length; jc < n_dots; jc++) { dot_stream[dot_stream_length++] = '1'; } - fold_dotstream(dot_stream, width, height, dot_array); + dc_fold_dotstream(dot_stream, width, height, dot_array); - mask_score[i] = score_array(dot_array, height, width); + mask_score[i] = dc_score_array(dot_array, height, width); if (debug_print) { printf("Mask %d score is %d\n", i, mask_score[i]); @@ -1608,20 +1476,21 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len for (i = 0; i < 4; i++) { - apply_mask(i, data_length, masked_codeword_array, codeword_array, ecc_length); + dc_apply_mask(i, data_length, masked_codeword_array, codeword_array, ecc_length); - dot_stream_length = make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream); + dot_stream_length = dc_make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), + dot_stream); /* Add pad bits */ for (jc = dot_stream_length; jc < n_dots; jc++) { dot_stream[dot_stream_length++] = '1'; } - fold_dotstream(dot_stream, width, height, dot_array); + dc_fold_dotstream(dot_stream, width, height, dot_array); - force_corners(width, height, dot_array); + dc_force_corners(width, height, dot_array); - mask_score[i + 4] = score_array(dot_array, height, width); + mask_score[i + 4] = dc_score_array(dot_array, height, width); if (debug_print) { printf("Mask %d score is %d\n", i + 4, mask_score[i + 4]); @@ -1642,7 +1511,7 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len } /* Apply best mask */ - apply_mask(best_mask % 4, data_length, masked_codeword_array, codeword_array, ecc_length); + dc_apply_mask(best_mask % 4, data_length, masked_codeword_array, codeword_array, ecc_length); if (debug_print) { printf("Masked codewords (%d):", data_length); @@ -1657,7 +1526,7 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len printf("\n"); } - dot_stream_length = make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream); + dot_stream_length = dc_make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream); /* Add pad bits */ for (jc = dot_stream_length; jc < n_dots; jc++) { @@ -1665,10 +1534,10 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len } if (debug_print) printf("Binary (%d): %.*s\n", dot_stream_length, dot_stream_length, dot_stream); - fold_dotstream(dot_stream, width, height, dot_array); + dc_fold_dotstream(dot_stream, width, height, dot_array); if (best_mask >= 4) { - force_corners(width, height, dot_array); + dc_force_corners(width, height, dot_array); } /* Copy values to symbol */ @@ -1689,3 +1558,5 @@ INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int len return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/eci.c b/backend/eci.c index eb9b434b..2502c40a 100644 --- a/backend/eci.c +++ b/backend/eci.c @@ -197,6 +197,18 @@ INTERNAL int is_eci_convertible(const int eci) { return 1; } +/* Are any of the ECIs in the segments convertible from UTF-8? + Sets `convertible[]` for each, which must be at least `seg_count` in size */ +INTERNAL int is_eci_convertible_segs(const struct zint_seg segs[], const int seg_count, int convertible[]) { + int ret = 0; + int i; + for (i = 0; i < seg_count; i++) { + convertible[i] = is_eci_convertible(segs[i].eci); + ret |= convertible[i]; + } + return ret; +} + /* Calculate length required to convert UTF-8 to (double-byte) encoding */ INTERNAL int get_eci_length(const int eci, const unsigned char source[], int length) { if (eci == 20) { /* Shift JIS */ @@ -222,6 +234,18 @@ INTERNAL int get_eci_length(const int eci, const unsigned char source[], int len return length; } +/* Call `get_eci_length()` for each segment, returning total */ +INTERNAL int get_eci_length_segs(const struct zint_seg segs[], const int seg_count) { + int length = 0; + int i; + + for (i = 0; i < seg_count; i++) { + length += get_eci_length(segs[i].eci, segs[i].source, segs[i].length); + } + + return length; +} + /* Convert UTF-8 Unicode to other character encodings */ INTERNAL int utf8_to_eci(const int eci, const unsigned char source[], unsigned char dest[], int *p_length) { @@ -325,4 +349,37 @@ INTERNAL int get_best_eci(const unsigned char source[], int length) { return 26; // If all of these fail, use Unicode! } +/* Return 0 on failure, first ECI set on success */ +INTERNAL int get_best_eci_segs(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { + int first_eci_set = 0; + int i; + + for (i = 0; i < seg_count; i++) { + if (segs[i].eci == 0) { + int eci = get_best_eci(segs[i].source, segs[i].length); + if (eci == 0) { + return 0; + } + if (eci == 3) { + if (i != 0 && segs[i - 1].eci > 3) { + segs[i].eci = eci; + if (first_eci_set == 0) { + first_eci_set = eci; + } + } + } else { + segs[i].eci = eci; + if (first_eci_set == 0) { + first_eci_set = eci; + if (i == 0) { + symbol->eci = eci; + } + } + } + } + } + + return first_eci_set; +} + /* vim: set ts=4 sw=4 et : */ diff --git a/backend/eci.h b/backend/eci.h index f1f6596f..ed9bb9f6 100644 --- a/backend/eci.h +++ b/backend/eci.h @@ -1,7 +1,7 @@ /* eci.c - Extended Channel Interpretations to Unicode tables libzint - the open source barcode library - Copyright (C) 2009-2021 Robin Stuart + Copyright (C) 2009-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -28,22 +28,28 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ -#ifndef ECI_H -#define ECI_H +#ifndef Z_ECI_H +#define Z_ECI_H #ifdef __cplusplus extern "C" { #endif INTERNAL int is_eci_convertible(const int eci); +INTERNAL int is_eci_convertible_segs(const struct zint_seg segs[], const int seg_count, int convertible[]); + INTERNAL int get_eci_length(const int eci, const unsigned char source[], int length); +INTERNAL int get_eci_length_segs(const struct zint_seg segs[], const int seg_count); + INTERNAL int utf8_to_eci(const int eci, const unsigned char source[], unsigned char dest[], int *p_length); + INTERNAL int get_best_eci(const unsigned char source[], int length); +INTERNAL int get_best_eci_segs(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); #ifdef __cplusplus } #endif -#endif /* ECI_H */ +/* vim: set ts=4 sw=4 et : */ +#endif /* Z_ECI_H */ diff --git a/backend/gb18030.c b/backend/gb18030.c index 411dc4a9..3d5aa7f4 100644 --- a/backend/gb18030.c +++ b/backend/gb18030.c @@ -2868,7 +2868,7 @@ INTERNAL int gb18030_wctomb_zint(unsigned int *r1, unsigned int *r2, const unsig /* Convert UTF-8 string to GB 18030 and place in array of ints */ INTERNAL int gb18030_utf8(struct zint_symbol *symbol, const unsigned char source[], int *p_length, - unsigned int *gbdata) { + unsigned int *ddata) { int error_number, ret; unsigned int i, j, length; #ifndef _MSC_VER @@ -2884,9 +2884,9 @@ INTERNAL int gb18030_utf8(struct zint_symbol *symbol, const unsigned char source for (i = 0, j = 0, length = *p_length; i < length; i++, j++) { if (utfdata[i] < 0x80) { - gbdata[j] = utfdata[i]; + ddata[j] = utfdata[i]; } else { - ret = gb18030_wctomb_zint(gbdata + j, gbdata + j + 1, utfdata[i]); + ret = gb18030_wctomb_zint(ddata + j, ddata + j + 1, utfdata[i]); if (ret == 0) { /* Should never happen, as GB 18030 is a UTF i.e. maps all Unicode codepoints */ strcpy(symbol->errtxt, "820: Invalid character in input data"); /* Not reached */ return ZINT_ERROR_INVALID_DATA; @@ -2903,7 +2903,7 @@ INTERNAL int gb18030_utf8(struct zint_symbol *symbol, const unsigned char source } /* Convert UTF-8 string to ECI and place in array of ints */ -INTERNAL int gb18030_utf8_to_eci(const int eci, const unsigned char source[], int *p_length, unsigned int *gbdata, +INTERNAL int gb18030_utf8_to_eci(const int eci, const unsigned char source[], int *p_length, unsigned int *ddata, const int full_multibyte) { if (is_eci_convertible(eci)) { @@ -2921,9 +2921,9 @@ INTERNAL int gb18030_utf8_to_eci(const int eci, const unsigned char source[], in return error_number; } - gb18030_cpy(converted, p_length, gbdata, full_multibyte); + gb18030_cpy(converted, p_length, ddata, full_multibyte); } else { - gb18030_cpy(source, p_length, gbdata, full_multibyte); + gb18030_cpy(source, p_length, ddata, full_multibyte); } return 0; @@ -2931,7 +2931,7 @@ INTERNAL int gb18030_utf8_to_eci(const int eci, const unsigned char source[], in /* If `full_multibyte` set, copy byte input stream to array of ints, putting double-bytes that match HANXIN * Chinese mode in single entry, and quad-bytes in 2 entries. If `full_multibyte` not set, do a straight copy */ -INTERNAL void gb18030_cpy(const unsigned char source[], int *p_length, unsigned int *gbdata, +INTERNAL void gb18030_cpy(const unsigned char source[], int *p_length, unsigned int *ddata, const int full_multibyte) { unsigned int i, j, length; int done; @@ -2945,15 +2945,15 @@ INTERNAL void gb18030_cpy(const unsigned char source[], int *p_length, unsigned if (c1 >= 0x81 && c1 <= 0xFE) { c2 = source[i + 1]; if ((c2 >= 0x40 && c2 <= 0x7E) || (c2 >= 0x80 && c2 <= 0xFE)) { - gbdata[j] = (c1 << 8) | c2; + ddata[j] = (c1 << 8) | c2; i++; done = 1; } else if (length - i >= 4 && (c2 >= 0x30 && c2 <= 0x39)) { c3 = source[i + 2]; c4 = source[i + 3]; if ((c3 >= 0x81 && c3 <= 0xFE) && (c4 >= 0x30 && c4 <= 0x39)) { - gbdata[j++] = (c1 << 8) | c2; - gbdata[j] = (c3 << 8) | c4; + ddata[j++] = (c1 << 8) | c2; + ddata[j] = (c3 << 8) | c4; i += 3; done = 1; } @@ -2961,16 +2961,28 @@ INTERNAL void gb18030_cpy(const unsigned char source[], int *p_length, unsigned } } if (!done) { - gbdata[j] = c1; + ddata[j] = c1; } } *p_length = j; } else { /* Straight copy */ for (i = 0, length = *p_length; i < length; i++) { - gbdata[i] = source[i]; + ddata[i] = source[i]; } } } +/* Call `gb18030_cpy()` for each segment */ +INTERNAL void gb18030_cpy_segs(struct zint_seg segs[], const int seg_count, unsigned int *ddata, + const int full_multibyte) { + int i; + unsigned int *dd = ddata; + + for (i = 0; i < seg_count; i++) { + gb18030_cpy(segs[i].source, &segs[i].length, dd, full_multibyte); + dd += segs[i].length; + } +} + /* vim: set ts=4 sw=4 et : */ diff --git a/backend/gb18030.h b/backend/gb18030.h index d6d0dbba..8769c2d3 100644 --- a/backend/gb18030.h +++ b/backend/gb18030.h @@ -39,10 +39,13 @@ extern "C" { INTERNAL int gbk_wctomb_zint(unsigned int *r, const unsigned int wc); INTERNAL int gb18030_wctomb_zint(unsigned int *r1, unsigned int *r2, const unsigned int wc); INTERNAL int gb18030_utf8(struct zint_symbol *symbol, const unsigned char source[], int *p_length, - unsigned int *gbdata); -INTERNAL int gb18030_utf8_to_eci(const int eci, const unsigned char source[], int *p_length, unsigned int *gbdata, + unsigned int *ddata); +INTERNAL int gb18030_utf8_to_eci(const int eci, const unsigned char source[], int *p_length, unsigned int *ddata, const int full_multibyte); -INTERNAL void gb18030_cpy(const unsigned char source[], int *p_length, unsigned int *gbdata, + +INTERNAL void gb18030_cpy(const unsigned char source[], int *p_length, unsigned int *ddata, + const int full_multibyte); +INTERNAL void gb18030_cpy_segs(struct zint_seg segs[], const int seg_count, unsigned int *ddata, const int full_multibyte); #ifdef __cplusplus diff --git a/backend/gb2312.c b/backend/gb2312.c index 55e9cc39..a81befb8 100644 --- a/backend/gb2312.c +++ b/backend/gb2312.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2019-2021 Robin Stuart + Copyright (C) 2019-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ /* * Adapted from GNU LIBICONV library and patched to add 2 duplicate mappings * for compatibility with GB 18030 subset: @@ -1543,7 +1542,7 @@ INTERNAL int gb2312_wctomb_zint(unsigned int *r, const unsigned int wc) { /* Convert UTF-8 string to GB 2312 (EUC-CN) and place in array of ints */ INTERNAL int gb2312_utf8(struct zint_symbol *symbol, const unsigned char source[], int *p_length, - unsigned int *gbdata) { + unsigned int *ddata) { int error_number; unsigned int i, length; #ifndef _MSC_VER @@ -1559,9 +1558,9 @@ INTERNAL int gb2312_utf8(struct zint_symbol *symbol, const unsigned char source[ for (i = 0, length = *p_length; i < length; i++) { if (utfdata[i] < 0x80) { - gbdata[i] = utfdata[i]; + ddata[i] = utfdata[i]; } else { - if (!gb2312_wctomb_zint(gbdata + i, utfdata[i])) { + if (!gb2312_wctomb_zint(ddata + i, utfdata[i])) { strcpy(symbol->errtxt, "810: Invalid character in input data"); return ZINT_ERROR_INVALID_DATA; } @@ -1572,7 +1571,7 @@ INTERNAL int gb2312_utf8(struct zint_symbol *symbol, const unsigned char source[ } /* Convert UTF-8 string to ECI and place in array of ints */ -INTERNAL int gb2312_utf8_to_eci(const int eci, const unsigned char source[], int *p_length, unsigned int *gbdata, +INTERNAL int gb2312_utf8_to_eci(const int eci, const unsigned char source[], int *p_length, unsigned int *ddata, const int full_multibyte) { if (is_eci_convertible(eci)) { @@ -1590,9 +1589,9 @@ INTERNAL int gb2312_utf8_to_eci(const int eci, const unsigned char source[], int return error_number; } - gb2312_cpy(converted, p_length, gbdata, full_multibyte); + gb2312_cpy(converted, p_length, ddata, full_multibyte); } else { - gb2312_cpy(source, p_length, gbdata, full_multibyte); + gb2312_cpy(source, p_length, ddata, full_multibyte); } return 0; @@ -1600,7 +1599,7 @@ INTERNAL int gb2312_utf8_to_eci(const int eci, const unsigned char source[], int /* If `full_multibyte` set, copy byte input stream to array of ints, putting double-bytes that match GRIDMATRIX * Chinese mode in a single entry. If `full_multibyte` not set, do a straight copy */ -INTERNAL void gb2312_cpy(const unsigned char source[], int *p_length, unsigned int *gbdata, +INTERNAL void gb2312_cpy(const unsigned char source[], int *p_length, unsigned int *ddata, const int full_multibyte) { unsigned int i, j, length; unsigned char c1, c2; @@ -1613,20 +1612,34 @@ INTERNAL void gb2312_cpy(const unsigned char source[], int *p_length, unsigned i if (((c1 >= 0xA1 && c1 <= 0xA9) || (c1 >= 0xB0 && c1 <= 0xF7)) && c2 >= 0xA1 && c2 <= 0xFE) { /* This may or may not be valid GB 2312 (EUC-CN), but don't care as long as it can be encoded in * GRIDMATRIX Chinese mode */ - gbdata[j] = (c1 << 8) | c2; + ddata[j] = (c1 << 8) | c2; i++; } else { - gbdata[j] = c1; + ddata[j] = c1; } } else { - gbdata[j] = source[i]; + ddata[j] = source[i]; } } *p_length = j; } else { /* Straight copy */ for (i = 0, length = *p_length; i < length; i++) { - gbdata[i] = source[i]; + ddata[i] = source[i]; } } } + +/* Call `gb2312_cpy()` for each segment */ +INTERNAL void gb2312_cpy_segs(struct zint_seg segs[], const int seg_count, unsigned int *ddata, + const int full_multibyte) { + int i; + unsigned int *dd = ddata; + + for (i = 0; i < seg_count; i++) { + gb2312_cpy(segs[i].source, &segs[i].length, dd, full_multibyte); + dd += segs[i].length; + } +} + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/gb2312.h b/backend/gb2312.h index 63e264b1..42b6d2aa 100644 --- a/backend/gb2312.h +++ b/backend/gb2312.h @@ -1,7 +1,7 @@ /* gb2312.h - Unicode to GB 2312-1980 (EUC-CN) libzint - the open source barcode library - Copyright (C) 2009-2021 Robin Stuart + Copyright (C) 2009-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -28,10 +28,9 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ -#ifndef GB2312_H -#define GB2312_H +#ifndef Z_GB2312_H +#define Z_GB2312_H #ifdef __cplusplus extern "C" { @@ -39,14 +38,18 @@ extern "C" { INTERNAL int gb2312_wctomb_zint(unsigned int *r, const unsigned int wc); INTERNAL int gb2312_utf8(struct zint_symbol *symbol, const unsigned char source[], int *p_length, - unsigned int *gbdata); -INTERNAL int gb2312_utf8_to_eci(const int eci, const unsigned char source[], int *p_length, unsigned int *gbdata, + unsigned int *ddata); +INTERNAL int gb2312_utf8_to_eci(const int eci, const unsigned char source[], int *p_length, unsigned int *ddata, const int full_multibyte); -INTERNAL void gb2312_cpy(const unsigned char source[], int *p_length, unsigned int *gbdata, + +INTERNAL void gb2312_cpy(const unsigned char source[], int *p_length, unsigned int *ddata, + const int full_multibyte); +INTERNAL void gb2312_cpy_segs(struct zint_seg segs[], const int seg_count, unsigned int *ddata, const int full_multibyte); #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* GB2312_H */ +/* vim: set ts=4 sw=4 et : */ +#endif /* Z_GB2312_H */ diff --git a/backend/general_field.c b/backend/general_field.c index d8a85069..cb4cd0b3 100644 --- a/backend/general_field.c +++ b/backend/general_field.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2019 - 2021 Robin Stuart + Copyright (C) 2019-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,14 +29,13 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "common.h" #include "general_field.h" static const char alphanum_puncs[] = "*,-./"; static const char isoiec_puncs[] = "!\"%&'()*+,-./:;<=>?_ "; /* Note contains space, not in cset82 */ -#define IS_ISOIEC_F (IS_LWR_F | IS_C82_F | IS_PLS_F | IS_MNS_F | IS_SPC_F) +#define IS_ISOIEC_F (IS_LWR_F | IS_C82_F | IS_AST_F | IS_PLS_F | IS_MNS_F | IS_SPC_F) /* Returns type of char at `i`. FNC1 counted as NUMERIC. Returns 0 if invalid char */ static int general_field_type(const char *general_field, const int i) { @@ -205,3 +204,5 @@ INTERNAL int general_field_encode(const char *general_field, const int general_f return 1; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/general_field.h b/backend/general_field.h index 5ab8847c..b43ac588 100644 --- a/backend/general_field.h +++ b/backend/general_field.h @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2019 - 2020 Robin Stuart + Copyright (C) 2019-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,10 +27,9 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ -#ifndef __GENERAL_FIELD_H -#define __GENERAL_FIELD_H +#ifndef Z_GENERAL_FIELD_H +#define Z_GENERAL_FIELD_H #define NUMERIC 110 #define ALPHANUMERIC 97 @@ -47,4 +46,5 @@ INTERNAL int general_field_encode(const char *general_field, const int general_f } #endif /* __cplusplus */ -#endif /* __GENERAL_FIELD_H */ +/* vim: set ts=4 sw=4 et : */ +#endif /* Z_GENERAL_FIELD_H */ diff --git a/backend/gridmtx.c b/backend/gridmtx.c index aadf1372..b907a22e 100644 --- a/backend/gridmtx.c +++ b/backend/gridmtx.c @@ -46,16 +46,17 @@ static const char EUROPIUM[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijkl static const char EUROPIUM_UPR[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ "; static const char EUROPIUM_LWR[] = "abcdefghijklmnopqrstuvwxyz "; -/* define_mode() stuff */ +/* gm_define_mode() stuff */ /* Bits multiplied by this for costs, so as to be whole integer divisible by 2 and 3 */ #define GM_MULT 6 -static const char numeral_nondigits[] = " +-.,"; /* Non-digit numeral set, excluding EOL (carriage return/linefeed) */ +/* Non-digit numeral set, excluding EOL (carriage return/linefeed) */ +static const char gm_numeral_nondigits[] = " +-.,"; /* Whether in numeral or not. If in numeral, *p_numeral_end is set to position after numeral, * and *p_numeral_cost is set to per-numeral cost */ -static int in_numeral(const unsigned int gbdata[], const int length, const int in_posn, +static int gm_in_numeral(const unsigned int ddata[], const int length, const int in_posn, unsigned int *p_numeral_end, unsigned int *p_numeral_cost) { int i, digit_cnt, nondigit, nondigit_posn; @@ -69,15 +70,15 @@ static int in_numeral(const unsigned int gbdata[], const int length, const int i block of three numeric characters) */ for (i = in_posn, digit_cnt = 0, nondigit = 0, nondigit_posn = 0; i < length && i < in_posn + 4 && digit_cnt < 3; i++) { - if (gbdata[i] >= '0' && gbdata[i] <= '9') { + if (ddata[i] >= '0' && ddata[i] <= '9') { digit_cnt++; - } else if (posn(numeral_nondigits, (const char) gbdata[i]) != -1) { + } else if (posn(gm_numeral_nondigits, (const char) ddata[i]) != -1) { if (nondigit) { break; } nondigit = 1; nondigit_posn = i; - } else if (i < length - 1 && gbdata[i] == 13 && gbdata[i + 1] == 10) { + } else if (i < length - 1 && ddata[i] == 13 && ddata[i + 1] == 10) { if (nondigit) { break; } @@ -128,7 +129,7 @@ static int in_numeral(const unsigned int gbdata[], const int length, const int i /* Calculate optimized encoding modes. Adapted from Project Nayuki */ /* Copyright (c) Project Nayuki. (MIT License) See qr.c for detailed notice */ -static void define_mode(char *mode, const unsigned int gbdata[], const int length, const int debug) { +static void gm_define_mode(char *mode, const unsigned int ddata[], const int length, const int debug_print) { /* Must be in same order as GM_H etc */ static const char mode_types[] = { GM_CHINESE, GM_NUMBER, GM_LOWER, GM_UPPER, GM_MIXED, GM_BYTE, '\0' }; @@ -183,24 +184,24 @@ static void define_mode(char *mode, const unsigned int gbdata[], const int lengt space = numeric = lower = upper = control = double_digit = eol = 0; - double_byte = gbdata[i] > 0xFF; + double_byte = ddata[i] > 0xFF; if (!double_byte) { - space = gbdata[i] == ' '; + space = ddata[i] == ' '; if (!space) { - numeric = gbdata[i] >= '0' && gbdata[i] <= '9'; + numeric = ddata[i] >= '0' && ddata[i] <= '9'; if (!numeric) { - lower = gbdata[i] >= 'a' && gbdata[i] <= 'z'; + lower = ddata[i] >= 'a' && ddata[i] <= 'z'; if (!lower) { - upper = gbdata[i] >= 'A' && gbdata[i] <= 'Z'; + upper = ddata[i] >= 'A' && ddata[i] <= 'Z'; if (!upper) { - control = gbdata[i] < 0x7F; /* Exclude DEL */ + control = ddata[i] < 0x7F; /* Exclude DEL */ if (control && i + 1 < length) { - eol = gbdata[i] == 13 && gbdata[i + 1] == 10; + eol = ddata[i] == 13 && ddata[i + 1] == 10; } } } } else if (i + 1 < length) { - double_digit = gbdata[i + 1] >= '0' && gbdata[i + 1] <= '9'; + double_digit = ddata[i + 1] >= '0' && ddata[i + 1] <= '9'; } } } @@ -222,7 +223,7 @@ static void define_mode(char *mode, const unsigned int gbdata[], const int lengt char_modes[cm_i + GM_B] = GM_BYTE; byte_count += double_byte ? 2 : 1; - if (in_numeral(gbdata, length, i, &numeral_end, &numeral_cost)) { + if (gm_in_numeral(ddata, length, i, &numeral_end, &numeral_cost)) { cur_costs[GM_N] = prev_costs[GM_N] + numeral_cost; char_modes[cm_i + GM_N] = GM_NUMBER; } @@ -290,20 +291,20 @@ static void define_mode(char *mode, const unsigned int gbdata[], const int lengt mode[i] = cur_mode; } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf(" Mode: %.*s\n", length, mode); } } /* Add the length indicator for byte encoded blocks */ -static void add_byte_count(char binary[], const int byte_count_posn, const int byte_count) { +static void gm_add_byte_count(char binary[], const int byte_count_posn, const int byte_count) { /* AIMD014 6.3.7: "Let L be the number of bytes of input data to be encoded in the 8-bit binary data set. * First output (L-1) as a 9-bit binary prefix to record the number of bytes..." */ bin_append_posn(byte_count - 1, 9, binary, byte_count_posn); } /* Add a control character to the data stream */ -static int add_shift_char(char binary[], int bp, int shifty, int debug) { +static int gm_add_shift_char(char binary[], int bp, int shifty, const int debug_print) { int i; int glyph = 0; @@ -318,7 +319,7 @@ static int add_shift_char(char binary[], int bp, int shifty, int debug) { } } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("SHIFT [%d] ", glyph); } @@ -327,46 +328,29 @@ static int add_shift_char(char binary[], int bp, int shifty, int debug) { return bp; } -static int gm_encode(unsigned int gbdata[], const int length, char binary[], const int reader, - const struct zint_structapp *p_structapp, const int eci, int *bin_len, int debug) { +static int gm_encode(unsigned int ddata[], const int length, char binary[], const int eci, int *p_bp, + const int debug_print) { /* Create a binary stream representation of the input data. 7 sets are defined - Chinese characters, Numerals, Lower case letters, Upper case letters, Mixed numerals and latters, Control characters and 8-bit binary data */ - int sp; - int current_mode, last_mode; + int sp = 0; + int current_mode = 0; + int last_mode; unsigned int glyph = 0; int c1, c2, done; int p = 0, ppos; int numbuf[3], punt = 0; - int number_pad_posn, byte_count_posn = 0; + int number_pad_posn = 0; + int byte_count_posn = 0; int byte_count = 0; int shift; - int bp; + int bp = *p_bp; #ifndef _MSC_VER char mode[length]; #else char *mode = (char *) _alloca(length); #endif - *binary = '\0'; - bp = 0; - - sp = 0; - current_mode = 0; - number_pad_posn = 0; - - if (reader && (!p_structapp || p_structapp->index == 1)) { /* Appears only in 1st symbol if Structured Append */ - bp = bin_append_posn(10, 4, binary, bp); /* FNC3 - Reader Initialisation */ - } - - if (p_structapp) { - bp = bin_append_posn(9, 4, binary, bp); /* FNC2 - Structured Append */ - bp = bin_append_posn(to_int((const unsigned char *) p_structapp->id, (int) strlen(p_structapp->id)), 8, - binary, bp); /* File signature */ - bp = bin_append_posn(p_structapp->count - 1, 4, binary, bp); - bp = bin_append_posn(p_structapp->index - 1, 4, binary, bp); - } - if (eci != 0) { /* ECI assignment according to Table 8 */ bp = bin_append_posn(12, 4, binary, bp); /* ECI */ @@ -381,7 +365,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con } } - define_mode(mode, gbdata, length, debug); + gm_define_mode(mode, ddata, length, debug_print); do { const int next_mode = mode[sp]; @@ -476,7 +460,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con break; case GM_BYTE: /* add byte block length indicator */ - add_byte_count(binary, byte_count_posn, byte_count); + gm_add_byte_count(binary, byte_count_posn, byte_count); byte_count = 0; switch (next_mode) { case GM_CHINESE: bp = bin_append_posn(1, 4, binary, bp); @@ -492,7 +476,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con } break; } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { switch (next_mode) { case GM_CHINESE: printf("CHIN "); break; @@ -515,10 +499,10 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con switch (current_mode) { case GM_CHINESE: done = 0; - if (gbdata[sp] > 0xff) { + if (ddata[sp] > 0xff) { /* GB2312 character */ - c1 = (gbdata[sp] & 0xff00) >> 8; - c2 = gbdata[sp] & 0xff; + c1 = (ddata[sp] & 0xff00) >> 8; + c2 = ddata[sp] & 0xff; if ((c1 >= 0xa1) && (c1 <= 0xa9)) { glyph = (0x60 * (c1 - 0xa1)) + (c2 - 0xa0); @@ -529,7 +513,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con } if (!(done)) { if (sp != (length - 1)) { - if ((gbdata[sp] == 13) && (gbdata[sp + 1] == 10)) { + if ((ddata[sp] == 13) && (ddata[sp + 1] == 10)) { /* End of Line */ glyph = 7776; sp++; @@ -539,10 +523,10 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con } if (!(done)) { if (sp != (length - 1)) { - if (((gbdata[sp] >= '0') && (gbdata[sp] <= '9')) && - ((gbdata[sp + 1] >= '0') && (gbdata[sp + 1] <= '9'))) { + if (((ddata[sp] >= '0') && (ddata[sp] <= '9')) && + ((ddata[sp + 1] >= '0') && (ddata[sp + 1] <= '9'))) { /* Two digits */ - glyph = 8033 + (10 * (gbdata[sp] - '0')) + (gbdata[sp + 1] - '0'); + glyph = 8033 + (10 * (ddata[sp] - '0')) + (ddata[sp + 1] - '0'); sp++; done = 1; } @@ -550,10 +534,10 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con } if (!(done)) { /* Byte value */ - glyph = 7777 + gbdata[sp]; + glyph = 7777 + ddata[sp]; } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("[%d] ", (int) glyph); } @@ -577,21 +561,21 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con numbuf[1] = '0'; numbuf[2] = '0'; do { - if ((gbdata[sp] >= '0') && (gbdata[sp] <= '9')) { - numbuf[p] = gbdata[sp]; + if ((ddata[sp] >= '0') && (ddata[sp] <= '9')) { + numbuf[p] = ddata[sp]; p++; - } else if (posn(numeral_nondigits, (const char) gbdata[sp]) != -1) { + } else if (posn(gm_numeral_nondigits, (const char) ddata[sp]) != -1) { if (ppos != -1) { break; } - punt = gbdata[sp]; + punt = ddata[sp]; ppos = p; - } else if (sp < (length - 1) && (gbdata[sp] == 13) && (gbdata[sp + 1] == 10)) { + } else if (sp < (length - 1) && (ddata[sp] == 13) && (ddata[sp + 1] == 10)) { /* */ if (ppos != -1) { break; } - punt = gbdata[sp]; + punt = ddata[sp]; sp++; ppos = p; } else { @@ -618,7 +602,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con glyph += ppos; glyph += 1000; - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("[%d] ", (int) glyph); } @@ -626,7 +610,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con } glyph = (100 * (numbuf[0] - '0')) + (10 * (numbuf[1] - '0')) + (numbuf[2] - '0'); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("[%d] ", (int) glyph); } @@ -639,7 +623,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con byte_count_posn = bp; bp = bin_append_posn(0, 9, binary, bp); } - glyph = gbdata[sp]; + glyph = ddata[sp]; if (byte_count == 512 || (glyph > 0xFF && byte_count == 511)) { /* Maximum byte block size is 512 bytes. If longer is needed then start a new block */ if (glyph > 0xFF && byte_count == 511) { /* Split double-byte */ @@ -647,14 +631,14 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con glyph &= 0xFF; byte_count++; } - add_byte_count(binary, byte_count_posn, byte_count); + gm_add_byte_count(binary, byte_count_posn, byte_count); bp = bin_append_posn(7, 4, binary, bp); byte_count_posn = bp; bp = bin_append_posn(0, 9, binary, bp); byte_count = 0; } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("[%d] ", (int) glyph); } bp = bin_append_posn(glyph, glyph > 0xFF ? 16 : 8, binary, bp); @@ -667,20 +651,20 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con case GM_MIXED: shift = 1; - if ((gbdata[sp] >= '0') && (gbdata[sp] <= '9')) { + if ((ddata[sp] >= '0') && (ddata[sp] <= '9')) { shift = 0; - } else if ((gbdata[sp] >= 'A') && (gbdata[sp] <= 'Z')) { + } else if ((ddata[sp] >= 'A') && (ddata[sp] <= 'Z')) { shift = 0; - } else if ((gbdata[sp] >= 'a') && (gbdata[sp] <= 'z')) { + } else if ((ddata[sp] >= 'a') && (ddata[sp] <= 'z')) { shift = 0; - } else if (gbdata[sp] == ' ') { + } else if (ddata[sp] == ' ') { shift = 0; } if (shift == 0) { /* Mixed Mode character */ - glyph = posn(EUROPIUM, (const char) gbdata[sp]); - if (debug & ZINT_DEBUG_PRINT) { + glyph = posn(EUROPIUM, (const char) ddata[sp]); + if (debug_print) { printf("[%d] ", (int) glyph); } @@ -688,7 +672,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con } else { /* Shift Mode character */ bp = bin_append_posn(1014, 10, binary, bp); /* shift indicator */ - bp = add_shift_char(binary, bp, gbdata[sp], debug); + bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print); } sp++; @@ -696,16 +680,16 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con case GM_UPPER: shift = 1; - if ((gbdata[sp] >= 'A') && (gbdata[sp] <= 'Z')) { + if ((ddata[sp] >= 'A') && (ddata[sp] <= 'Z')) { shift = 0; - } else if (gbdata[sp] == ' ') { + } else if (ddata[sp] == ' ') { shift = 0; } if (shift == 0) { /* Upper Case character */ - glyph = posn(EUROPIUM_UPR, (const char) gbdata[sp]); - if (debug & ZINT_DEBUG_PRINT) { + glyph = posn(EUROPIUM_UPR, (const char) ddata[sp]); + if (debug_print) { printf("[%d] ", (int) glyph); } @@ -713,7 +697,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con } else { /* Shift Mode character */ bp = bin_append_posn(125, 7, binary, bp); /* shift indicator */ - bp = add_shift_char(binary, bp, gbdata[sp], debug); + bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print); } sp++; @@ -721,16 +705,16 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con case GM_LOWER: shift = 1; - if ((gbdata[sp] >= 'a') && (gbdata[sp] <= 'z')) { + if ((ddata[sp] >= 'a') && (ddata[sp] <= 'z')) { shift = 0; - } else if (gbdata[sp] == ' ') { + } else if (ddata[sp] == ' ') { shift = 0; } if (shift == 0) { /* Lower Case character */ - glyph = posn(EUROPIUM_LWR, (const char) gbdata[sp]); - if (debug & ZINT_DEBUG_PRINT) { + glyph = posn(EUROPIUM_LWR, (const char) ddata[sp]); + if (debug_print) { printf("[%d] ", (int) glyph); } @@ -738,7 +722,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con } else { /* Shift Mode character */ bp = bin_append_posn(125, 7, binary, bp); /* shift indicator */ - bp = add_shift_char(binary, bp, gbdata[sp], debug); + bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print); } sp++; @@ -767,7 +751,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con if (current_mode == GM_BYTE) { /* Add byte block length indicator */ - add_byte_count(binary, byte_count_posn, byte_count); + gm_add_byte_count(binary, byte_count_posn, byte_count); } /* Add "end of data" character */ @@ -785,21 +769,58 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con break; } + if (bp > 9191) { + return ZINT_ERROR_TOO_LONG; + } + + *p_bp = bp; + + if (debug_print) { + printf("\nBinary (%d): %.*s\n", bp, bp, binary); + } + + return 0; +} + +static int gm_encode_segs(unsigned int ddata[], const struct zint_seg segs[], const int seg_count, char binary[], + const int reader, const struct zint_structapp *p_structapp, int *p_bin_len, const int debug_print) { + int i; + unsigned int *dd = ddata; + int bp = 0; + int p; + + if (reader && (!p_structapp || p_structapp->index == 1)) { /* Appears only in 1st symbol if Structured Append */ + bp = bin_append_posn(10, 4, binary, bp); /* FNC3 - Reader Initialisation */ + } + + if (p_structapp) { + bp = bin_append_posn(9, 4, binary, bp); /* FNC2 - Structured Append */ + bp = bin_append_posn(to_int((const unsigned char *) p_structapp->id, (int) strlen(p_structapp->id)), 8, + binary, bp); /* File signature */ + bp = bin_append_posn(p_structapp->count - 1, 4, binary, bp); + bp = bin_append_posn(p_structapp->index - 1, 4, binary, bp); + } + + for (i = 0; i < seg_count; i++) { + int error_number = gm_encode(dd, segs[i].length, binary, segs[i].eci, &bp, debug_print); + if (error_number != 0) { + return error_number; + } + dd += segs[i].length; + } + /* Add padding bits if required */ p = 7 - (bp % 7); if (p % 7) { bp = bin_append_posn(0, p, binary, bp); } + /* Note bit-padding can't tip `bp` over max 9191 (1313 * 7) */ - if (bp > 9191) { - return ZINT_ERROR_TOO_LONG; + if (debug_print) { + printf("\nBinary (%d): %.*s\n", bp, bp, binary); } - binary[bp] = '\0'; - *bin_len = bp; - if (debug & ZINT_DEBUG_PRINT) { - printf("\nBinary (%d): %s\n", bp, binary); - } + *p_bin_len = bp; return 0; } @@ -893,7 +914,7 @@ static void gm_add_ecc(const char binary[], const int data_posn, const int layer } } -static void place_macromodule(char grid[], int x, int y, int word1, int word2, int size) { +static void gm_place_macromodule(char grid[], int x, int y, int word1, int word2, int size) { int i, j; i = (x * 6) + 1; @@ -943,20 +964,20 @@ static void place_macromodule(char grid[], int x, int y, int word1, int word2, i } } -static void place_data_in_grid(unsigned char word[], char grid[], int modules, int size) { +static void gm_place_data_in_grid(unsigned char word[], char grid[], int modules, int size) { int x, y, macromodule, offset; offset = 13 - ((modules - 1) / 2); for (y = 0; y < modules; y++) { for (x = 0; x < modules; x++) { macromodule = gm_macro_matrix[((y + offset) * 27) + (x + offset)]; - place_macromodule(grid, x, y, word[macromodule * 2], word[(macromodule * 2) + 1], size); + gm_place_macromodule(grid, x, y, word[macromodule * 2], word[(macromodule * 2) + 1], size); } } } /* Place the layer ID into each macromodule */ -static void place_layer_id(char *grid, int size, int layers, int modules, int ecc_level) { +static void gm_place_layer_id(char *grid, int size, int layers, int modules, int ecc_level) { int i, j, layer, start, stop; #ifndef _MSC_VER @@ -1009,7 +1030,7 @@ static void place_layer_id(char *grid, int size, int layers, int modules, int ec } } -INTERNAL int gridmatrix(struct zint_symbol *symbol, unsigned char source[], int length) { +INTERNAL int gridmatrix(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { int warn_number = 0; int size, modules, error_number; int auto_layers, min_layers, layers, auto_ecc_level, min_ecc_level, ecc_level; @@ -1022,42 +1043,52 @@ INTERNAL int gridmatrix(struct zint_symbol *symbol, unsigned char source[], int const struct zint_structapp *p_structapp = NULL; int size_squared; int bin_len; - const int eci_length = get_eci_length(symbol->eci, source, length); + const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; + const int eci_length_segs = get_eci_length_segs(segs, seg_count); #ifndef _MSC_VER - unsigned int gbdata[eci_length + 1]; + struct zint_seg local_segs[seg_count]; + unsigned int ddata[eci_length_segs]; #else + struct zint_seg *local_segs = (struct zint_seg *) _alloca(sizeof(struct zint_seg) * seg_count); + unsigned int *ddata = (unsigned int *) _alloca(sizeof(unsigned int) * eci_length_segs); char *grid; - unsigned int *gbdata = (unsigned int *) _alloca((eci_length + 1) * sizeof(unsigned int)); #endif + segs_cpy(segs, seg_count, local_segs); /* Shallow copy (needed to set default ECIs & protect lengths) */ + /* If ZINT_FULL_MULTIBYTE set use Hanzi mode in DATA_MODE or for non-GB 2312 in UNICODE_MODE */ full_multibyte = (symbol->option_3 & 0xFF) == ZINT_FULL_MULTIBYTE; if ((symbol->input_mode & 0x07) == DATA_MODE) { - gb2312_cpy(source, &length, gbdata, full_multibyte); + gb2312_cpy_segs(local_segs, seg_count, ddata, full_multibyte); } else { - int done = 0; - if (symbol->eci != 29) { /* Unless ECI 29 (GB 2312) */ - /* Try other conversions (ECI 0 defaults to ISO/IEC 8859-1) */ - error_number = gb2312_utf8_to_eci(symbol->eci, source, &length, gbdata, full_multibyte); - if (error_number == 0) { - done = 1; - } else if (symbol->eci) { - sprintf(symbol->errtxt, "535: Invalid character in input data for ECI %d", symbol->eci); - return error_number; + unsigned int *dd = ddata; + for (i = 0; i < seg_count; i++) { + int done = 0; + if (local_segs[i].eci != 29 || seg_count > 1) { /* Unless ECI 29 (GB 2312) or have multiple segments */ + /* Try other conversions (ECI 0 defaults to ISO/IEC 8859-1) */ + error_number = gb2312_utf8_to_eci(local_segs[i].eci, local_segs[i].source, &local_segs[i].length, + dd, full_multibyte); + if (error_number == 0) { + done = 1; + } else if (local_segs[i].eci || seg_count > 1) { + sprintf(symbol->errtxt, "535: Invalid character in input data for ECI %d", local_segs[i].eci); + return error_number; + } } - } - if (!done) { - /* Try GB 2312 (EUC-CN) */ - error_number = gb2312_utf8(symbol, source, &length, gbdata); - if (error_number != 0) { - return error_number; - } - if (symbol->eci != 29) { - strcpy(symbol->errtxt, "540: Converted to GB 2312 but no ECI specified"); - warn_number = ZINT_WARN_NONCOMPLIANT; + if (!done) { + /* Try GB 2312 (EUC-CN) */ + error_number = gb2312_utf8(symbol, local_segs[i].source, &local_segs[i].length, dd); + if (error_number != 0) { + return error_number; + } + if (local_segs[i].eci != 29) { + strcpy(symbol->errtxt, "540: Converted to GB 2312 but no ECI specified"); + warn_number = ZINT_WARN_NONCOMPLIANT; + } } + dd += local_segs[i].length; } } @@ -1100,7 +1131,7 @@ INTERNAL int gridmatrix(struct zint_symbol *symbol, unsigned char source[], int return ZINT_ERROR_INVALID_OPTION; } - error_number = gm_encode(gbdata, length, binary, reader, p_structapp, symbol->eci, &bin_len, symbol->debug); + error_number = gm_encode_segs(ddata, local_segs, seg_count, binary, reader, p_structapp, &bin_len, debug_print); if (error_number != 0) { strcpy(symbol->errtxt, "531: Input data too long"); return error_number; @@ -1205,8 +1236,8 @@ INTERNAL int gridmatrix(struct zint_symbol *symbol, unsigned char source[], int memset(grid, '0', size_squared); - place_data_in_grid(word, grid, modules, size); - place_layer_id(grid, size, layers, modules, ecc_level); + gm_place_data_in_grid(word, grid, modules, size); + gm_place_layer_id(grid, size, layers, modules, ecc_level); /* Add macromodule frames */ for (x = 0; x < modules; x++) { diff --git a/backend/gridmtx.h b/backend/gridmtx.h index 65b99a48..f8011c23 100644 --- a/backend/gridmtx.h +++ b/backend/gridmtx.h @@ -1,7 +1,7 @@ /* gridmtx.h - definitions for Grid Matrix libzint - the open source barcode library - Copyright (C) 2009-2021 Robin Stuart + Copyright (C) 2009-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -28,7 +28,9 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ + +#ifndef Z_GRIDMTX_H +#define Z_GRIDMTX_H static const char gm_shift_set[] = { /* From Table 7 - Encoding of control characters */ @@ -38,15 +40,15 @@ static const char gm_shift_set[] = { ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~' }; -static const unsigned short int gm_recommend_cw[] = { +static const unsigned short gm_recommend_cw[] = { 9, 30, 59, 114, 170, 237, 315, 405, 506, 618, 741, 875, 1021 }; -static const unsigned short int gm_max_cw[] = { +static const unsigned short gm_max_cw[] = { 11, 40, 79, 146, 218, 305, 405, 521, 650, 794, 953, 1125, 1313 }; -static const unsigned short int gm_data_codewords[] = { +static const unsigned short gm_data_codewords[] = { 0, 15, 13, 11, 9, 45, 40, 35, 30, 25, 89, 79, 69, 59, 49, @@ -144,7 +146,7 @@ static const char gm_ebeb[] = { 61, 9, 60, 3 }; -static const unsigned short int gm_macro_matrix[] = { +static const unsigned short gm_macro_matrix[] = { 728, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 727, 624, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 651, 726, 623, 528, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 553, 652, @@ -153,16 +155,16 @@ static const unsigned short int gm_macro_matrix[] = { 723, 620, 525, 438, 359, 288, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 307, 382, 465, 556, 655, 722, 619, 524, 437, 358, 287, 224, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 241, 308, 383, 466, 557, 656, 721, 618, 523, 436, 357, 286, 223, 168, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 183, 242, 309, 384, 467, 558, 657, - 720, 617, 522, 435, 356, 285, 222, 167, 120, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 133, 184, 243, 310, 385, 468, 559, 658, - 719, 616, 521, 434, 355, 284, 221, 166, 119, 80, 49, 50, 51, 52, 53, 54, 55, 56, 91, 134, 185, 244, 311, 386, 469, 560, 659, - 718, 615, 520, 433, 354, 283, 220, 165, 118, 79, 48, 25, 26, 27, 28, 29, 30, 57, 92, 135, 186, 245, 312, 387, 470, 561, 660, - 717, 614, 519, 432, 353, 282, 219, 164, 117, 78, 47, 24, 9, 10, 11, 12, 31, 58, 93, 136, 187, 246, 313, 388, 471, 562, 661, - 716, 613, 518, 431, 352, 281, 218, 163, 116, 77, 46, 23, 8, 1, 2, 13, 32, 59, 94, 137, 188, 247, 314, 389, 472, 563, 662, - 715, 612, 517, 430, 351, 280, 217, 162, 115, 76, 45, 22, 7, 0, 3, 14, 33, 60, 95, 138, 189, 248, 315, 390, 473, 564, 663, - 714, 611, 516, 429, 350, 279, 216, 161, 114, 75, 44, 21, 6, 5, 4, 15, 34, 61, 96, 139, 190, 249, 316, 391, 474, 565, 664, - 713, 610, 515, 428, 349, 278, 215, 160, 113, 74, 43, 20, 19, 18, 17, 16, 35, 62, 97, 140, 191, 250, 317, 392, 475, 566, 665, - 712, 609, 514, 427, 348, 277, 214, 159, 112, 73, 42, 41, 40, 39, 38, 37, 36, 63, 98, 141, 192, 251, 318, 393, 476, 567, 666, - 711, 608, 513, 426, 347, 276, 213, 158, 111, 72, 71, 70, 69, 68, 67, 66, 65, 64, 99, 142, 193, 252, 319, 394, 477, 568, 667, + 720, 617, 522, 435, 356, 285, 222, 167, 120, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 133, 184, 243, 310, 385, 468, 559, 658, + 719, 616, 521, 434, 355, 284, 221, 166, 119, 80, 49, 50, 51, 52, 53, 54, 55, 56, 91, 134, 185, 244, 311, 386, 469, 560, 659, + 718, 615, 520, 433, 354, 283, 220, 165, 118, 79, 48, 25, 26, 27, 28, 29, 30, 57, 92, 135, 186, 245, 312, 387, 470, 561, 660, + 717, 614, 519, 432, 353, 282, 219, 164, 117, 78, 47, 24, 9, 10, 11, 12, 31, 58, 93, 136, 187, 246, 313, 388, 471, 562, 661, + 716, 613, 518, 431, 352, 281, 218, 163, 116, 77, 46, 23, 8, 1, 2, 13, 32, 59, 94, 137, 188, 247, 314, 389, 472, 563, 662, + 715, 612, 517, 430, 351, 280, 217, 162, 115, 76, 45, 22, 7, 0, 3, 14, 33, 60, 95, 138, 189, 248, 315, 390, 473, 564, 663, + 714, 611, 516, 429, 350, 279, 216, 161, 114, 75, 44, 21, 6, 5, 4, 15, 34, 61, 96, 139, 190, 249, 316, 391, 474, 565, 664, + 713, 610, 515, 428, 349, 278, 215, 160, 113, 74, 43, 20, 19, 18, 17, 16, 35, 62, 97, 140, 191, 250, 317, 392, 475, 566, 665, + 712, 609, 514, 427, 348, 277, 214, 159, 112, 73, 42, 41, 40, 39, 38, 37, 36, 63, 98, 141, 192, 251, 318, 393, 476, 567, 666, + 711, 608, 513, 426, 347, 276, 213, 158, 111, 72, 71, 70, 69, 68, 67, 66, 65, 64, 99, 142, 193, 252, 319, 394, 477, 568, 667, 710, 607, 512, 425, 346, 275, 212, 157, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 143, 194, 253, 320, 395, 478, 569, 668, 709, 606, 511, 424, 345, 274, 211, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 195, 254, 321, 396, 479, 570, 669, 708, 605, 510, 423, 344, 273, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 255, 322, 397, 480, 571, 670, @@ -174,3 +176,5 @@ static const unsigned short int gm_macro_matrix[] = { 702, 701, 700, 699, 698, 697, 696, 695, 694, 693, 692, 691, 690, 689, 688, 687, 686, 685, 684, 683, 682, 681, 680, 679, 678, 677, 676, }; +/* vim: set ts=4 sw=4 et : */ +#endif /* Z_GRIDMTX_H */ diff --git a/backend/gs1.h b/backend/gs1.h index d7f2c658..dfa7c539 100644 --- a/backend/gs1.h +++ b/backend/gs1.h @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2009 - 2020 Robin Stuart + Copyright (C) 2009-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,9 +29,8 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ -#ifndef __GS1_H -#define __GS1_H +#ifndef Z_GS1_H +#define Z_GS1_H #ifdef __cplusplus extern "C" { @@ -45,4 +44,5 @@ INTERNAL char gs1_check_digit(const unsigned char source[], const int src_len); } #endif /* __cplusplus */ -#endif /* __GS1_H */ +/* vim: set ts=4 sw=4 et : */ +#endif /* Z_GS1_H */ diff --git a/backend/hanxin.c b/backend/hanxin.c index 9720bd30..5fcccfe8 100644 --- a/backend/hanxin.c +++ b/backend/hanxin.c @@ -45,7 +45,7 @@ #include /* Find which submode to use for a text character */ -static int getsubmode(const unsigned int input) { +static int hx_getsubmode(const unsigned int input) { if ((input >= '0') && (input <= '9')) { return 1; @@ -63,7 +63,7 @@ static int getsubmode(const unsigned int input) { } /* Return length of terminator for encoding mode */ -static int terminator_length(const char mode) { +static int hx_terminator_length(const char mode) { int result = 0; switch (mode) { @@ -86,7 +86,7 @@ static int terminator_length(const char mode) { } /* Calculate the length of the binary string */ -static int calculate_binlength(const char mode[], const unsigned int source[], const int length, const int eci) { +static int hx_calc_binlen(const char mode[], const unsigned int ddata[], const int length, const int eci) { int i; char lastmode = '\0'; int est_binlen = 0; @@ -108,7 +108,7 @@ static int calculate_binlength(const char mode[], const unsigned int source[], c do { if (mode[i] != lastmode) { if (i > 0) { - est_binlen += terminator_length(lastmode); + est_binlen += hx_terminator_length(lastmode); } /* GB 4-byte has indicator for each character (and no terminator) so not included here */ /* Region1/Region2 have special terminator to go directly into each other's mode so not included here */ @@ -130,14 +130,14 @@ static int calculate_binlength(const char mode[], const unsigned int source[], c numeric_run++; break; case 't': - if (getsubmode(source[i]) != submode) { + if (hx_getsubmode(ddata[i]) != submode) { est_binlen += 6; - submode = getsubmode(source[i]); + submode = hx_getsubmode(ddata[i]); } est_binlen += 6; break; case 'b': - est_binlen += source[i] > 0xFF ? 16 : 8; + est_binlen += ddata[i] > 0xFF ? 16 : 8; break; case '1': case '2': @@ -154,12 +154,29 @@ static int calculate_binlength(const char mode[], const unsigned int source[], c i++; } while (i < length); - est_binlen += terminator_length(lastmode); + est_binlen += hx_terminator_length(lastmode); return est_binlen; } -static int isRegion1(const unsigned int glyph) { +/* Call `hx_calc_binlen()` for each segment */ +static int hx_calc_binlen_segs(const char mode[], const unsigned int ddata[], const struct zint_seg segs[], + const int seg_count) { + int i; + int count = 0; + const unsigned int *dd = ddata; + const char *m = mode; + + for (i = 0; i < seg_count; i++) { + count += hx_calc_binlen(m, dd, segs[i].length, segs[i].eci); + m += segs[i].length; + dd += segs[i].length; + } + + return count; +} + +static int hx_isRegion1(const unsigned int glyph) { unsigned int byte; byte = glyph >> 8; @@ -181,7 +198,7 @@ static int isRegion1(const unsigned int glyph) { return 0; } -static int isRegion2(const unsigned int glyph) { +static int hx_isRegion2(const unsigned int glyph) { unsigned int byte; byte = glyph >> 8; @@ -196,7 +213,7 @@ static int isRegion2(const unsigned int glyph) { return 0; } -static int isDoubleByte(const unsigned int glyph) { +static int hx_isDoubleByte(const unsigned int glyph) { unsigned int byte; byte = glyph >> 8; @@ -214,7 +231,7 @@ static int isDoubleByte(const unsigned int glyph) { return 0; } -static int isFourByte(const unsigned int glyph, const unsigned int glyph2) { +static int hx_isFourByte(const unsigned int glyph, const unsigned int glyph2) { unsigned int byte; byte = glyph >> 8; @@ -236,7 +253,7 @@ static int isFourByte(const unsigned int glyph, const unsigned int glyph2) { } /* Convert Text 1 sub-mode character to encoding value, as given in table 3 */ -static int lookup_text1(const unsigned int input) { +static int hx_lookup_text1(const unsigned int input) { if ((input >= '0') && (input <= '9')) { return input - '0'; @@ -254,7 +271,7 @@ static int lookup_text1(const unsigned int input) { } /* Convert Text 2 sub-mode character to encoding value, as given in table 4 */ -static int lookup_text2(const unsigned int input) { +static int hx_lookup_text2(const unsigned int input) { if (input <= 27) { return input; @@ -286,7 +303,7 @@ static int lookup_text2(const unsigned int input) { /* Whether in numeric or not. If in numeric, *p_end is set to position after numeric, * and *p_cost is set to per-numeric cost */ -static int in_numeric(const unsigned int gbdata[], const int length, const int in_posn, +static int hx_in_numeric(const unsigned int ddata[], const int length, const int in_posn, unsigned int *p_end, unsigned int *p_cost) { int i, digit_cnt; @@ -295,7 +312,7 @@ static int in_numeric(const unsigned int gbdata[], const int length, const int i } /* Attempt to calculate the average 'cost' of using numeric mode in number of bits (times HX_MULT) */ - for (i = in_posn; i < length && i < in_posn + 4 && gbdata[i] >= '0' && gbdata[i] <= '9'; i++); + for (i = in_posn; i < length && i < in_posn + 4 && ddata[i] >= '0' && ddata[i] <= '9'; i++); digit_cnt = i - in_posn; @@ -311,13 +328,13 @@ static int in_numeric(const unsigned int gbdata[], const int length, const int i /* Whether in four-byte or not. If in four-byte, *p_fourbyte is set to position after four-byte, * and *p_fourbyte_cost is set to per-position cost */ -static int in_fourbyte(const unsigned int gbdata[], const int length, const int in_posn, +static int hx_in_fourbyte(const unsigned int ddata[], const int length, const int in_posn, unsigned int *p_end, unsigned int *p_cost) { if (in_posn < (int) *p_end) { return 1; } - if (in_posn == length - 1 || !isFourByte(gbdata[in_posn], gbdata[in_posn + 1])) { + if (in_posn == length - 1 || !hx_isFourByte(ddata[in_posn], ddata[in_posn + 1])) { *p_end = 0; return 0; } @@ -340,7 +357,7 @@ static int in_fourbyte(const unsigned int gbdata[], const int length, const int /* Calculate optimized encoding modes. Adapted from Project Nayuki */ /* Copyright (c) Project Nayuki. (MIT License) See qr.c for detailed notice */ -static void hx_define_mode(char *mode, const unsigned int gbdata[], const int length, const int debug) { +static void hx_define_mode(char *mode, const unsigned int ddata[], const int length, const int debug_print) { /* Must be in same order as HX_N etc */ static const char mode_types[] = { 'n', 't', 'b', '1', '2', 'd', 'f', '\0' }; @@ -394,14 +411,14 @@ static void hx_define_mode(char *mode, const unsigned int gbdata[], const int le for (i = 0, cm_i = 0; i < length; i++, cm_i += HX_NUM_MODES) { memset(cur_costs, 0, HX_NUM_MODES * sizeof(unsigned int)); - if (in_numeric(gbdata, length, i, &numeric_end, &numeric_cost)) { + if (hx_in_numeric(ddata, length, i, &numeric_end, &numeric_cost)) { cur_costs[HX_N] = prev_costs[HX_N] + numeric_cost; char_modes[cm_i + HX_N] = 'n'; text1 = 1; text2 = 0; } else { - text1 = lookup_text1(gbdata[i]) != -1; - text2 = lookup_text2(gbdata[i]) != -1; + text1 = hx_lookup_text1(ddata[i]) != -1; + text2 = hx_lookup_text2(ddata[i]) != -1; } if (text1 || text2) { @@ -417,20 +434,20 @@ static void hx_define_mode(char *mode, const unsigned int gbdata[], const int le } /* Binary mode can encode anything */ - cur_costs[HX_B] = prev_costs[HX_B] + (gbdata[i] > 0xFF ? 96 : 48); /* (16 : 8) * HX_MULT */ + cur_costs[HX_B] = prev_costs[HX_B] + (ddata[i] > 0xFF ? 96 : 48); /* (16 : 8) * HX_MULT */ char_modes[cm_i + HX_B] = 'b'; - if (in_fourbyte(gbdata, length, i, &fourbyte_end, &fourbyte_cost)) { + if (hx_in_fourbyte(ddata, length, i, &fourbyte_end, &fourbyte_cost)) { cur_costs[HX_F] = prev_costs[HX_F] + fourbyte_cost; char_modes[cm_i + HX_F] = 'f'; } else { - if (isDoubleByte(gbdata[i])) { + if (hx_isDoubleByte(ddata[i])) { cur_costs[HX_D] = prev_costs[HX_D] + 90; /* 15 * HX_MULT */ char_modes[cm_i + HX_D] = 'd'; - if (isRegion1(gbdata[i])) { /* Subset */ + if (hx_isRegion1(ddata[i])) { /* Subset */ cur_costs[HX_1] = prev_costs[HX_1] + 72; /* 12 * HX_MULT */ char_modes[cm_i + HX_1] = '1'; - } else if (isRegion2(gbdata[i])) { /* Subset */ + } else if (hx_isRegion2(ddata[i])) { /* Subset */ cur_costs[HX_2] = prev_costs[HX_2] + 72; /* 12 * HX_MULT */ char_modes[cm_i + HX_2] = '2'; } @@ -478,21 +495,35 @@ static void hx_define_mode(char *mode, const unsigned int gbdata[], const int le mode[i] = cur_mode; } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf(" Mode: %.*s\n", length, mode); } } +/* Call `hx_define_mode()` for each segment */ +static void hx_define_mode_segs(char mode[], const unsigned int ddata[], const struct zint_seg segs[], + const int seg_count, const int debug_print) { + int i; + const unsigned int *dd = ddata; + char *m = mode; + + for (i = 0; i < seg_count; i++) { + hx_define_mode(m, dd, segs[i].length, debug_print); + m += segs[i].length; + dd += segs[i].length; + } +} + /* Convert input data to binary stream */ -static void calculate_binary(char binary[], const char mode[], unsigned int source[], const int length, const int eci, - int *bin_len, const int debug) { +static void hx_calculate_binary(char binary[], const char mode[], const unsigned int ddata[], const int length, + const int eci, int *p_bp, const int debug_print) { int position = 0; int i, count, encoding_value; int first_byte, second_byte; int third_byte, fourth_byte; int glyph; int submode; - int bp = 0; + int bp = *p_bp; if (eci != 0) { /* Encoding ECI assignment number, according to Table 5 */ @@ -512,7 +543,7 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour int block_length = 0; int double_byte = 0; do { - if (mode[position] == 'b' && source[position + block_length] > 0xFF) { + if (mode[position] == 'b' && ddata[position + block_length] > 0xFF) { double_byte++; } block_length++; @@ -524,7 +555,7 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour /* Mode indicator */ bp = bin_append_posn(1, 4, binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Numeric\n"); } @@ -532,17 +563,17 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour i = 0; while (i < block_length) { - const int first = ctoi((const char) source[position + i]); + const int first = ctoi((const char) ddata[position + i]); count = 1; encoding_value = first; if (i + 1 < block_length && mode[position + i + 1] == 'n') { - const int second = ctoi((const char) source[position + i + 1]); + const int second = ctoi((const char) ddata[position + i + 1]); count = 2; encoding_value = (encoding_value * 10) + second; if (i + 2 < block_length && mode[position + i + 2] == 'n') { - const int third = ctoi((const char) source[position + i + 2]); + const int third = ctoi((const char) ddata[position + i + 2]); count = 3; encoding_value = (encoding_value * 10) + third; } @@ -550,7 +581,7 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour bp = bin_append_posn(encoding_value, 10, binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("0x%3x (%d)", encoding_value, encoding_value); } @@ -570,7 +601,7 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour break; } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf(" (TERM %d)\n", count); } @@ -580,7 +611,7 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour /* Mode indicator */ bp = bin_append_posn(2, 4, binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Text\n"); } @@ -590,25 +621,25 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour while (i < block_length) { - if (getsubmode(source[i + position]) != submode) { + if (hx_getsubmode(ddata[i + position]) != submode) { /* Change submode */ bp = bin_append_posn(62, 6, binary, bp); - submode = getsubmode(source[i + position]); - if (debug & ZINT_DEBUG_PRINT) { + submode = hx_getsubmode(ddata[i + position]); + if (debug_print) { printf("SWITCH "); } } if (submode == 1) { - encoding_value = lookup_text1(source[i + position]); + encoding_value = hx_lookup_text1(ddata[i + position]); } else { - encoding_value = lookup_text2(source[i + position]); + encoding_value = hx_lookup_text2(ddata[i + position]); } bp = bin_append_posn(encoding_value, 6, binary, bp); - if (debug & ZINT_DEBUG_PRINT) { - printf("%.2x [ASC %.2x] ", encoding_value, source[i + position]); + if (debug_print) { + printf("%.2x [ASC %.2x] ", encoding_value, ddata[i + position]); } i++; } @@ -616,7 +647,7 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour /* Terminator */ bp = bin_append_posn(63, 6, binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("\n"); } break; @@ -628,7 +659,7 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour /* Count indicator */ bp = bin_append_posn(block_length + double_byte, 13, binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Binary Mode (%d):", block_length + double_byte); } @@ -637,35 +668,35 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour while (i < block_length) { /* 8-bit bytes with no conversion */ - bp = bin_append_posn(source[i + position], source[i + position] > 0xFF ? 16 : 8, binary, bp); + bp = bin_append_posn(ddata[i + position], ddata[i + position] > 0xFF ? 16 : 8, binary, bp); - if (debug & ZINT_DEBUG_PRINT) { - printf(" %02x", (int) source[i + position]); + if (debug_print) { + printf(" %02x", (int) ddata[i + position]); } i++; } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("\n"); } break; case '1': - /* Region 1 encoding */ + /* Region One encoding */ /* Mode indicator */ - if (position == 0 || mode[position - 1] != '2') { /* Unless previous mode Region 2 */ + if (position == 0 || mode[position - 1] != '2') { /* Unless previous mode Region Two */ bp = bin_append_posn(4, 4, binary, bp); } - if (debug & ZINT_DEBUG_PRINT) { - printf("Region 1%s\n", position == 0 || mode[position - 1] != '2' ? "" : " (NO indicator)" ); + if (debug_print) { + printf("Region One%s\n", position == 0 || mode[position - 1] != '2' ? "" : " (NO indicator)" ); } i = 0; while (i < block_length) { - first_byte = (source[i + position] & 0xff00) >> 8; - second_byte = source[i + position] & 0xff; + first_byte = (ddata[i + position] & 0xff00) >> 8; + second_byte = ddata[i + position] & 0xff; /* Subset 1 */ glyph = (0x5e * (first_byte - 0xb0)) + (second_byte - 0xa1); @@ -678,12 +709,12 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour } /* Subset 3 */ - if ((source[i + position] >= 0xa8a1) && (source[i + position] <= 0xa8c0)) { + if ((ddata[i + position] >= 0xa8a1) && (ddata[i + position] <= 0xa8c0)) { glyph = (second_byte - 0xa1) + 0xfca; } - if (debug & ZINT_DEBUG_PRINT) { - printf("%.3x [GB %.4x] ", glyph, source[i + position]); + if (debug_print) { + printf("%.3x [GB %.4x] ", glyph, ddata[i + position]); } bp = bin_append_posn(glyph, 12, binary, bp); @@ -694,33 +725,33 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour bp = bin_append_posn(position + block_length == length || mode[position + block_length] != '2' ? 4095 : 4094, 12, binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("(TERM %x)\n", position + block_length == length || mode[position + block_length] != '2' ? 4095 : 4094); } break; case '2': - /* Region 2 encoding */ + /* Region Two encoding */ /* Mode indicator */ - if (position == 0 || mode[position - 1] != '1') { /* Unless previous mode Region 1 */ + if (position == 0 || mode[position - 1] != '1') { /* Unless previous mode Region One */ bp = bin_append_posn(5, 4, binary, bp); } - if (debug & ZINT_DEBUG_PRINT) { - printf("Region 2%s\n", position == 0 || mode[position - 1] != '1' ? "" : " (NO indicator)" ); + if (debug_print) { + printf("Region Two%s\n", position == 0 || mode[position - 1] != '1' ? "" : " (NO indicator)" ); } i = 0; while (i < block_length) { - first_byte = (source[i + position] & 0xff00) >> 8; - second_byte = source[i + position] & 0xff; + first_byte = (ddata[i + position] & 0xff00) >> 8; + second_byte = ddata[i + position] & 0xff; glyph = (0x5e * (first_byte - 0xd8)) + (second_byte - 0xa1); - if (debug & ZINT_DEBUG_PRINT) { - printf("%.3x [GB %.4x] ", glyph, source[i + position]); + if (debug_print) { + printf("%.3x [GB %.4x] ", glyph, ddata[i + position]); } bp = bin_append_posn(glyph, 12, binary, bp); @@ -731,7 +762,7 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour bp = bin_append_posn(position + block_length == length || mode[position + block_length] != '1' ? 4095 : 4094, 12, binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("(TERM %x)\n", position + block_length == length || mode[position + block_length] != '1' ? 4095 : 4094); } @@ -742,15 +773,15 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour /* Mode indicator */ bp = bin_append_posn(6, 4, binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Double byte\n"); } i = 0; while (i < block_length) { - first_byte = (source[i + position] & 0xff00) >> 8; - second_byte = source[i + position] & 0xff; + first_byte = (ddata[i + position] & 0xff00) >> 8; + second_byte = ddata[i + position] & 0xff; if (second_byte <= 0x7e) { glyph = (0xbe * (first_byte - 0x81)) + (second_byte - 0x40); @@ -758,7 +789,7 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour glyph = (0xbe * (first_byte - 0x81)) + (second_byte - 0x41); } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("%.4x ", glyph); } @@ -771,13 +802,13 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour /* Terminator sequence of length 12 is a mistake - confirmed by Wang Yi */ - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("\n"); } break; case 'f': /* Four-byte encoding */ - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Four byte\n"); } @@ -788,15 +819,15 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour /* Mode indicator */ bp = bin_append_posn(7, 4, binary, bp); - first_byte = (source[i + position] & 0xff00) >> 8; - second_byte = source[i + position] & 0xff; - third_byte = (source[i + position + 1] & 0xff00) >> 8; - fourth_byte = source[i + position + 1] & 0xff; + first_byte = (ddata[i + position] & 0xff00) >> 8; + second_byte = ddata[i + position] & 0xff; + third_byte = (ddata[i + position + 1] & 0xff00) >> 8; + fourth_byte = ddata[i + position + 1] & 0xff; glyph = (0x3138 * (first_byte - 0x81)) + (0x04ec * (second_byte - 0x30)) + (0x0a * (third_byte - 0x81)) + (fourth_byte - 0x30); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("%d ", glyph); } @@ -806,7 +837,7 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour /* No terminator */ - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("\n"); } break; @@ -816,11 +847,26 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour } while (position < length); - binary[bp] = '\0'; + if (debug_print) printf("Binary (%d): %.*s\n", bp, bp, binary); - if (debug & ZINT_DEBUG_PRINT) printf("Binary (%d): %s\n", bp, binary); + *p_bp = bp; +} - *bin_len = bp; +/* Call `hx_calculate_binary()` for each segment */ +static void hx_calculate_binary_segs(char binary[], const char mode[], const unsigned int ddata[], + const struct zint_seg segs[], const int seg_count, int *p_bin_len, const int debug_print) { + int i; + const unsigned int *dd = ddata; + const char *m = mode; + int bp = 0; + + for (i = 0; i < seg_count; i++) { + hx_calculate_binary(binary, m, dd, segs[i].length, segs[i].eci, &bp, debug_print); + m += segs[i].length; + dd += segs[i].length; + } + + *p_bin_len = bp; } /* Finder pattern for top left of symbol */ @@ -1111,7 +1157,7 @@ static void hx_add_ecc(unsigned char fullstream[], const unsigned char datastrea } static void hx_set_function_info(unsigned char *grid, const int size, const int version, const int ecc_level, - const int bitmask, const int debug) { + const int bitmask, const int debug_print) { int i, j; char function_information[34]; unsigned char fi_cw[3] = {0}; @@ -1148,7 +1194,7 @@ static void hx_set_function_info(unsigned char *grid, const int size, const int function_information[i] = '0'; } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Version: %d, ECC: %d, Mask: %d, Structural Info: %.34s\n", version, ecc_level, bitmask, function_information); } @@ -1175,7 +1221,8 @@ static void hx_set_function_info(unsigned char *grid, const int size, const int } /* Rearrange data in batches of 13 codewords (section 5.8.2) */ -static void make_picket_fence(const unsigned char fullstream[], unsigned char picket_fence[], const int streamsize) { +static void hx_make_picket_fence(const unsigned char fullstream[], unsigned char picket_fence[], + const int streamsize) { int i, start; int output_position = 0; @@ -1340,7 +1387,7 @@ static int hx_evaluate(const unsigned char *local, const int size) { /* TODO: Haven't been able to replicate (or even get close to) the penalty scores in ISO/IEC 20830:2021 * Annex K examples */ static void hx_apply_bitmask(unsigned char *grid, const int size, const int version, const int ecc_level, - const int user_mask, const int debug) { + const int user_mask, const int debug_print) { int x, y; int i, j, r, k; int pattern, penalty[4] = {0}; @@ -1390,7 +1437,7 @@ static void hx_apply_bitmask(unsigned char *grid, const int size, const int vers local[k] = grid[k] & 0x0f; } /* Set the Structural Info */ - hx_set_function_info(local, size, version, ecc_level, pattern, 0 /*debug*/); + hx_set_function_info(local, size, version, ecc_level, pattern, 0 /*debug_print*/); /* Evaluate result */ penalty[pattern] = hx_evaluate(local, size); @@ -1406,7 +1453,7 @@ static void hx_apply_bitmask(unsigned char *grid, const int size, const int vers } } /* Set the Structural Info */ - hx_set_function_info(local, size, version, ecc_level, pattern, 0 /*debug*/); + hx_set_function_info(local, size, version, ecc_level, pattern, 0 /*debug_print*/); /* Evaluate result */ penalty[pattern] = hx_evaluate(local, size); @@ -1416,7 +1463,7 @@ static void hx_apply_bitmask(unsigned char *grid, const int size, const int vers } } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Mask: %d (%s)", best_pattern, user_mask ? "specified" : "automatic"); if (!user_mask) { for (pattern = 0; pattern < 4; pattern++) printf(" %d:%d", pattern, penalty[pattern]); @@ -1438,11 +1485,11 @@ static void hx_apply_bitmask(unsigned char *grid, const int size, const int vers } } /* Set the Structural Info */ - hx_set_function_info(grid, size, version, ecc_level, best_pattern, debug); + hx_set_function_info(grid, size, version, ecc_level, best_pattern, debug_print); } /* Han Xin Code - main */ -INTERNAL int hanxin(struct zint_symbol *symbol, unsigned char source[], int length) { +INTERNAL int hanxin(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { int warn_number = 0; int est_binlen; int ecc_level = symbol->option_1; @@ -1453,14 +1500,17 @@ INTERNAL int hanxin(struct zint_symbol *symbol, unsigned char source[], int leng int size_squared; int codewords; int bin_len; - const int eci_length = get_eci_length(symbol->eci, source, length); + const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; + const int eci_length_segs = get_eci_length_segs(segs, seg_count); #ifndef _MSC_VER - unsigned int gbdata[eci_length + 1]; - char mode[eci_length]; + struct zint_seg local_segs[seg_count]; + unsigned int ddata[eci_length_segs]; + char mode[eci_length_segs]; #else - unsigned int *gbdata = (unsigned int *) _alloca((eci_length + 1) * sizeof(unsigned int)); - char *mode = (char *) _alloca(eci_length); + struct zint_seg *local_segs = (struct zint_seg *) _alloca(sizeof(struct zint_seg) * seg_count); + unsigned int *ddata = (unsigned int *) _alloca(sizeof(unsigned int) * eci_length_segs); + char *mode = (char *) _alloca(eci_length_segs); char *binary; unsigned char *datastream; unsigned char *fullstream; @@ -1468,6 +1518,8 @@ INTERNAL int hanxin(struct zint_symbol *symbol, unsigned char source[], int leng unsigned char *grid; #endif + segs_cpy(segs, seg_count, local_segs); /* Shallow copy (needed to set default ECI & protect lengths) */ + /* If ZINT_FULL_MULTIBYTE set use Hanzi mode in DATA_MODE or for non-GB 18030 in UNICODE_MODE */ full_multibyte = (symbol->option_3 & 0xFF) == ZINT_FULL_MULTIBYTE; user_mask = (symbol->option_3 >> 8) & 0x0F; /* User mask is pattern + 1, so >= 1 and <= 4 */ @@ -1476,35 +1528,40 @@ INTERNAL int hanxin(struct zint_symbol *symbol, unsigned char source[], int leng } if ((symbol->input_mode & 0x07) == DATA_MODE) { - gb18030_cpy(source, &length, gbdata, full_multibyte); + gb18030_cpy_segs(local_segs, seg_count, ddata, full_multibyte); } else { - int done = 0; - if (symbol->eci != 32) { /* Unless ECI 32 (GB 18030) */ - /* Try other conversions (ECI 0 defaults to ISO/IEC 8859-1) */ - int error_number = gb18030_utf8_to_eci(symbol->eci, source, &length, gbdata, full_multibyte); - if (error_number == 0) { - done = 1; - } else if (symbol->eci) { - sprintf(symbol->errtxt, "545: Invalid character in input data for ECI %d", symbol->eci); - return error_number; + unsigned int *dd = ddata; + for (i = 0; i < seg_count; i++) { + int done = 0; + if (local_segs[i].eci != 32 || seg_count > 1) { /* Unless ECI 32 (GB 18030) or have multiple segments */ + /* Try other conversions (ECI 0 defaults to ISO/IEC 8859-1) */ + int error_number = gb18030_utf8_to_eci(local_segs[i].eci, local_segs[i].source, &local_segs[i].length, + dd, full_multibyte); + if (error_number == 0) { + done = 1; + } else if (local_segs[i].eci || seg_count > 1) { + sprintf(symbol->errtxt, "545: Invalid character in input data for ECI %d", local_segs[i].eci); + return error_number; + } } - } - if (!done) { - /* Try GB 18030 */ - int error_number = gb18030_utf8(symbol, source, &length, gbdata); - if (error_number != 0) { - return error_number; - } - if (symbol->eci != 32) { - strcpy(symbol->errtxt, "543: Converted to GB 18030 but no ECI specified"); - warn_number = ZINT_WARN_NONCOMPLIANT; + if (!done) { + /* Try GB 18030 */ + int error_number = gb18030_utf8(symbol, local_segs[i].source, &local_segs[i].length, dd); + if (error_number != 0) { + return error_number; + } + if (local_segs[i].eci != 32) { + strcpy(symbol->errtxt, "543: Converted to GB 18030 but no ECI specified"); + warn_number = ZINT_WARN_NONCOMPLIANT; + } } + dd += local_segs[i].length; } } - hx_define_mode(mode, gbdata, length, symbol->debug); + hx_define_mode_segs(mode, ddata, local_segs, seg_count, debug_print); - est_binlen = calculate_binlength(mode, gbdata, length, symbol->eci); + est_binlen = hx_calc_binlen_segs(mode, ddata, local_segs, seg_count); #ifndef _MSC_VER char binary[est_binlen + 1]; @@ -1516,12 +1573,12 @@ INTERNAL int hanxin(struct zint_symbol *symbol, unsigned char source[], int leng ecc_level = 1; } - calculate_binary(binary, mode, gbdata, length, symbol->eci, &bin_len, symbol->debug); + hx_calculate_binary_segs(binary, mode, ddata, local_segs, seg_count, &bin_len, debug_print); codewords = bin_len >> 3; if (bin_len & 0x07) { codewords++; } - if (symbol->debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Num. of codewords: %d\n", codewords); } @@ -1619,7 +1676,7 @@ INTERNAL int hanxin(struct zint_symbol *symbol, unsigned char source[], int leng } } - if (symbol->debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Datastream (%d): ", data_codewords); for (i = 0; i < data_codewords; i++) { printf("%.2x ", datastream[i]); @@ -1634,7 +1691,7 @@ INTERNAL int hanxin(struct zint_symbol *symbol, unsigned char source[], int leng hx_add_ecc(fullstream, datastream, data_codewords, version, ecc_level); - if (symbol->debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Fullstream (%d): ", hx_total_codewords[version - 1]); for (i = 0; i < hx_total_codewords[version - 1]; i++) { printf("%.2x ", fullstream[i]); @@ -1642,7 +1699,7 @@ INTERNAL int hanxin(struct zint_symbol *symbol, unsigned char source[], int leng printf("\n"); } - make_picket_fence(fullstream, picket_fence, hx_total_codewords[version - 1]); + hx_make_picket_fence(fullstream, picket_fence, hx_total_codewords[version - 1]); /* Populate grid */ j = 0; @@ -1660,7 +1717,7 @@ INTERNAL int hanxin(struct zint_symbol *symbol, unsigned char source[], int leng } } - hx_apply_bitmask(grid, size, version, ecc_level, user_mask, symbol->debug); + hx_apply_bitmask(grid, size, version, ecc_level, user_mask, debug_print); symbol->width = size; symbol->rows = size; diff --git a/backend/hanxin.h b/backend/hanxin.h index a5258d7a..4ebaa72f 100644 --- a/backend/hanxin.h +++ b/backend/hanxin.h @@ -1,7 +1,7 @@ /* hanxin.h - definitions for Han Xin code libzint - the open source barcode library - Copyright (C) 2009-2017 Robin Stuart + Copyright (C) 2009-2022 Robin Stuart Copyright (C) 2016 Zoe Stuart Redistribution and use in source and binary forms, with or without @@ -30,8 +30,11 @@ SUCH DAMAGE. */ +#ifndef Z_HANXIN_H +#define Z_HANXIN_H + /* Data from table B1: Data capacity of Han Xin Code */ -static const unsigned short int hx_total_codewords[] = { +static const unsigned short hx_total_codewords[] = { 25, 37, 50, 54, 69, 84, 100, 117, 136, 155, 161, 181, 203, 225, 249, 273, 299, 325, 353, 381, 411, 422, 453, 485, 518, 552, 587, 623, 660, 698, 737, 754, 794, 836, 878, 922, 966, 1011, 1058, 1105, 1126, 1175, @@ -41,7 +44,7 @@ static const unsigned short int hx_total_codewords[] = { 3500, 3585, 3671, 3758, 3798, 3886 }; -static const unsigned short int hx_data_codewords_L1[] = { +static const unsigned short hx_data_codewords_L1[] = { 21, 31, 42, 46, 57, 70, 84, 99, 114, 131, 135, 153, 171, 189, 209, 229, 251, 273, 297, 321, 345, 354, 381, 407, 436, 464, 493, 523, 554, 586, 619, 634, 666, 702, 738, 774, 812, 849, 888, 929, 946, 987, 1028, 1071, 1115, @@ -51,7 +54,7 @@ static const unsigned short int hx_data_codewords_L1[] = { 3083, 3156, 3190, 3264 }; -static const unsigned short int hx_data_codewords_L2[] = { +static const unsigned short hx_data_codewords_L2[] = { 17, 25, 34, 38, 49, 58, 70, 81, 96, 109, 113, 127, 143, 157, 175, 191, 209, 227, 247, 267, 287, 296, 317, 339, 362, 386, 411, 437, 462, 488, 515, 528, 556, 586, 614, 646, 676, 707, 740, 773, 788, 823, 856, 893, 929, 966, 1004, @@ -61,7 +64,7 @@ static const unsigned short int hx_data_codewords_L2[] = { 2720 }; -static const unsigned short int hx_data_codewords_L3[] = { +static const unsigned short hx_data_codewords_L3[] = { 13, 19, 26, 30, 37, 46, 54, 63, 74, 83, 87, 97, 109, 121, 135, 147, 161, 175, 191, 205, 221, 228, 245, 261, 280, 298, 317, 337, 358, 376, 397, 408, 428, 452, 474, 498, 522, 545, 572, 597, 608, 635, 660, 689, 717, 746, 774, @@ -70,7 +73,7 @@ static const unsigned short int hx_data_codewords_L3[] = { 1713, 1756, 1800, 1844, 1890, 1935, 1983, 2030, 2050, 2098 }; -static const unsigned short int hx_data_codewords_L4[] = { +static const unsigned short hx_data_codewords_L4[] = { 9, 15, 20, 22, 27, 34, 40, 47, 54, 61, 65, 73, 81, 89, 99, 109, 119, 129, 141, 153, 165, 168, 181, 195, 208, 220, 235, 251, 264, 280, 295, 302, 318, 334, 352, 368, 386, 405, 424, 441, 450, 469, 490, 509, 531, 552, 574, 595, 605, @@ -119,7 +122,7 @@ static const char hx_module_m[] = { }; /* Error correction block sizes from Table D1 */ -static const unsigned short int hx_table_d1[] = { +static const unsigned short hx_table_d1[] = { /* #blocks, k, 2t, #blocks, k, 2t, #blocks, k, 2t */ 1, 21, 4, 0, 0, 0, 0, 0, 0, // version 1 1, 17, 8, 0, 0, 0, 0, 0, 0, @@ -458,3 +461,6 @@ static const unsigned short int hx_table_d1[] = { 2, 26, 26, 62, 33, 28, 0, 0, 0, 79, 18, 28, 4, 33, 30, 0, 0, 0 }; + +/* vim: set ts=4 sw=4 et : */ +#endif /* Z_HANXIN_H */ diff --git a/backend/large.h b/backend/large.h index cd7f7f2c..89188847 100644 --- a/backend/large.h +++ b/backend/large.h @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2008 - 2021 Robin Stuart + Copyright (C) 2008-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,9 +29,8 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ -#ifndef __LARGE_H -#define __LARGE_H +#ifndef Z_LARGE_H +#define Z_LARGE_H #ifndef _MSC_VER #include @@ -77,4 +76,5 @@ INTERNAL char *large_dump(const large_int *t, char *buf); } #endif /* __cplusplus */ -#endif /* __LARGE_H */ +/* vim: set ts=4 sw=4 et : */ +#endif /* Z_LARGE_H */ diff --git a/backend/library.c b/backend/library.c index e4f87103..ebc4da69 100644 --- a/backend/library.c +++ b/backend/library.c @@ -1,7 +1,7 @@ /* library.c - external functions of libzint libzint - the open source barcode library - Copyright (C) 2009 - 2021 Robin Stuart + Copyright (C) 2009-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -28,7 +28,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include #include @@ -162,15 +161,15 @@ INTERNAL int usps_imail(struct zint_symbol *symbol, unsigned char source[], int INTERNAL int rm4scc(struct zint_symbol *symbol, unsigned char source[], int length); /* RM4SCC */ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int length); /* Australia Post 4-state */ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 16k */ -INTERNAL int pdf417(struct zint_symbol *symbol, unsigned char source[], int length); /* PDF417 */ -INTERNAL int micropdf417(struct zint_symbol *symbol, unsigned char chaine[], int length); /* Micro PDF417 */ -INTERNAL int maxicode(struct zint_symbol *symbol, unsigned char source[], int length); /* Maxicode */ -INTERNAL int dbar_omn(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS-14 */ -INTERNAL int dbar_ltd(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS Limited */ -INTERNAL int dbar_exp(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS Expanded */ +INTERNAL int pdf417(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* PDF417 */ +INTERNAL int micropdf417(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Micro PDF417 */ +INTERNAL int maxicode(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Maxicode */ +INTERNAL int dbar_omn(struct zint_symbol *symbol, unsigned char source[], int length); /* DataBar Omnidirectional */ +INTERNAL int dbar_ltd(struct zint_symbol *symbol, unsigned char source[], int length); /* DataBar Limited */ +INTERNAL int dbar_exp(struct zint_symbol *symbol, unsigned char source[], int length); /* DataBar Expanded */ INTERNAL int composite(struct zint_symbol *symbol, unsigned char source[], int length); /* Composite Symbology */ INTERNAL int kix(struct zint_symbol *symbol, unsigned char source[], int length); /* TNT KIX Code */ -INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], int length); /* Aztec Code */ +INTERNAL int aztec(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Aztec Code */ INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int length); /* Italian Pharmacode */ INTERNAL int daft(struct zint_symbol *symbol, unsigned char source[], int length); /* DAFT Code */ INTERNAL int ean14(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN-14 */ @@ -181,20 +180,21 @@ INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int l INTERNAL int japanpost(struct zint_symbol *symbol, unsigned char source[], int length); /* Japanese Post */ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 49 */ INTERNAL int channel(struct zint_symbol *symbol, unsigned char source[], int length); /* Channel Code */ -INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int length); /* Code One */ -INTERNAL int gridmatrix(struct zint_symbol *symbol, unsigned char source[], int length); /* Grid Matrix */ -INTERNAL int hanxin(struct zint_symbol *symbol, unsigned char source[], int length); /* Han Xin */ -INTERNAL int dotcode(struct zint_symbol *symbol, unsigned char source[], int length); /* DotCode */ +INTERNAL int codeone(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Code One */ +INTERNAL int gridmatrix(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Grid Matrix */ +INTERNAL int hanxin(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Han Xin */ +INTERNAL int dotcode(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* DotCode */ INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int length); /* Codablock */ INTERNAL int upnqr(struct zint_symbol *symbol, unsigned char source[], int length); /* UPNQR */ -INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int length); /* QR Code */ -INTERNAL int datamatrix(struct zint_symbol *symbol, unsigned char source[], int length); /* Data Matrix (IEC16022) */ +INTERNAL int qrcode(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* QR Code */ +/* Data Matrix (IEC16022) */ +INTERNAL int datamatrix(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* VIN Code (Vehicle Identification Number) */ INTERNAL int vin(struct zint_symbol *symbol, unsigned char source[], int length); /* Royal Mail 4-state Mailmark */ INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int length); -INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int length); /* Ultracode */ -INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length); /* rMQR */ +INTERNAL int ultra(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* Ultracode */ +INTERNAL int rmqr(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); /* rMQR */ INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length); /* DPD Code */ INTERNAL int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to PNG/BMP/PCX */ @@ -289,7 +289,10 @@ static int dump_plot(struct zint_symbol *symbol) { static const char TECHNETIUM[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"; /* Same as SILVER (CODE39) */ /* Process health industry bar code data */ -static int hibc(struct zint_symbol *symbol, unsigned char source[], int length) { +static int hibc(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { + unsigned char *source = segs[0].source; + int length = segs[0].length; + int i; int counter, error_number = 0; char to_process[110 + 2 + 1]; @@ -317,45 +320,48 @@ static int hibc(struct zint_symbol *symbol, unsigned char source[], int length) to_process[++length] = TECHNETIUM[counter]; to_process[++length] = '\0'; + segs[0].source = (unsigned char *) to_process; + segs[0].length = length; + switch (symbol->symbology) { case BARCODE_HIBC_128: - error_number = code128(symbol, (unsigned char *) to_process, length); + error_number = code128(symbol, segs[0].source, segs[0].length); ustrcpy(symbol->text, "*"); ustrcat(symbol->text, to_process); ustrcat(symbol->text, "*"); break; case BARCODE_HIBC_39: symbol->option_2 = 0; - error_number = code39(symbol, (unsigned char *) to_process, length); + error_number = code39(symbol, segs[0].source, segs[0].length); ustrcpy(symbol->text, "*"); ustrcat(symbol->text, to_process); ustrcat(symbol->text, "*"); break; case BARCODE_HIBC_DM: - error_number = datamatrix(symbol, (unsigned char *) to_process, length); + error_number = datamatrix(symbol, segs, seg_count); break; case BARCODE_HIBC_QR: - error_number = qrcode(symbol, (unsigned char *) to_process, length); + error_number = qrcode(symbol, segs, seg_count); break; case BARCODE_HIBC_PDF: - error_number = pdf417(symbol, (unsigned char *) to_process, length); + error_number = pdf417(symbol, segs, seg_count); break; case BARCODE_HIBC_MICPDF: - error_number = micropdf417(symbol, (unsigned char *) to_process, length); + error_number = micropdf417(symbol, segs, seg_count); break; case BARCODE_HIBC_AZTEC: - error_number = aztec(symbol, (unsigned char *) to_process, length); + error_number = aztec(symbol, segs, seg_count); break; case BARCODE_HIBC_BLOCKF: - error_number = codablockf(symbol, (unsigned char *) to_process, length); + error_number = codablockf(symbol, segs[0].source, segs[0].length); break; } return error_number; } +/* Returns 1 if symbology MUST have GS1 data */ static int check_force_gs1(const int symbology) { - /* Returns 1 if symbology MUST have GS1 data */ switch (symbology) { case BARCODE_GS1_128: @@ -370,8 +376,8 @@ static int check_force_gs1(const int symbology) { return is_composite(symbology); } +/* Returns 1 if symbology supports GS1 data */ static int gs1_compliant(const int symbology) { - /* Returns 1 if symbology supports GS1 data */ switch (symbology) { case BARCODE_CODE16K: @@ -393,8 +399,8 @@ static int gs1_compliant(const int symbology) { return check_force_gs1(symbology); } +/* Returns 1 if symbology can encode the ECI character */ static int supports_eci(const int symbology) { - /* Returns 1 if symbology can encode the ECI character */ switch (symbology) { case BARCODE_AZTEC: @@ -417,8 +423,27 @@ static int supports_eci(const int symbology) { return 0; } +/* Returns 1 if symbology is Health Industry Bar Code */ +static int is_hibc(const int symbology) { + + switch (symbology) { + case BARCODE_HIBC_128: + case BARCODE_HIBC_39: + case BARCODE_HIBC_DM: + case BARCODE_HIBC_QR: + case BARCODE_HIBC_PDF: + case BARCODE_HIBC_MICPDF: + case BARCODE_HIBC_BLOCKF: + case BARCODE_HIBC_AZTEC: + return 1; + break; + } + + return 0; +} + +/* Returns 1 if symbology supports HRT */ static int has_hrt(const int symbology) { - /* Returns 1 if symbology supports HRT */ if (is_fixed_ratio(symbology)) { return 0; @@ -463,9 +488,16 @@ static int has_hrt(const int symbology) { return 1; } +/* Suppress warning ISO C forbids initialization between function pointer and ‘void *’ */ +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" +#endif + /* Used for dispatching barcodes and for whether symbol id valid */ -typedef int (*barcode_func_t)(struct zint_symbol *, unsigned char *, int); -static const barcode_func_t barcode_funcs[BARCODE_LAST + 1] = { +typedef int (*barcode_segs_func_t)(struct zint_symbol *, struct zint_seg[], const int); +typedef int (*barcode_func_t)(struct zint_symbol *, unsigned char[], int); +static const void *barcode_funcs[BARCODE_LAST + 1] = { NULL, code11, c25standard, c25inter, c25iata, /*0-4*/ NULL, c25logic, c25ind, code39, excode39, /*5-9*/ NULL, NULL, NULL, eanx, eanx, /*10-14*/ @@ -498,22 +530,26 @@ static const barcode_func_t barcode_funcs[BARCODE_LAST + 1] = { rmqr, }; -static int reduced_charset(struct zint_symbol *symbol, unsigned char *source, int length); +static int reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count); -static int extended_or_reduced_charset(struct zint_symbol *symbol, unsigned char *source, const int length) { +static int extended_or_reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { int error_number = 0; switch (symbol->symbology) { - /* These are the "elite" standards which have support for specific character sets */ + /* These are the "elite" standards which have support for specific character sets + ECI */ case BARCODE_QRCODE: - case BARCODE_MICROQR: case BARCODE_GRIDMATRIX: case BARCODE_HANXIN: - case BARCODE_UPNQR: case BARCODE_RMQR: - error_number = (*barcode_funcs[symbol->symbology])(symbol, source, length); + error_number = (*(barcode_segs_func_t)barcode_funcs[symbol->symbology])(symbol, segs, seg_count); break; - default: error_number = reduced_charset(symbol, source, length); + /* These are the standards which have support for specific character sets but not ECI */ + case BARCODE_MICROQR: + case BARCODE_UPNQR: + error_number = (*(barcode_func_t)barcode_funcs[symbol->symbology])(symbol, segs[0].source, + segs[0].length); + break; + default: error_number = reduced_charset(symbol, segs, seg_count); break; } @@ -521,36 +557,69 @@ static int extended_or_reduced_charset(struct zint_symbol *symbol, unsigned char } /* These are the "norm" standards which only support Latin-1 at most, though a few support ECI */ -static int reduced_charset(struct zint_symbol *symbol, unsigned char *source, int length) { +static int reduced_charset(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { int error_number = 0; - unsigned char *preprocessed = source; + int i; - const int eci_length = get_eci_length(symbol->eci, source, length); #ifndef _MSC_VER - unsigned char preprocessed_buf[eci_length + 1]; + struct zint_seg local_segs[seg_count]; + int convertible[seg_count]; #else - unsigned char *preprocessed_buf = (unsigned char *) _alloca(eci_length + 1); + struct zint_seg *local_segs = (struct zint_seg *) _alloca(sizeof(struct zint_seg) * seg_count); + int *convertible = (int *) _alloca(sizeof(int) * seg_count); +#endif + + if ((symbol->input_mode & 0x07) == UNICODE_MODE && is_eci_convertible_segs(segs, seg_count, convertible)) { + unsigned char *preprocessed; + const int eci_length_segs = get_eci_length_segs(segs, seg_count); +#ifndef _MSC_VER + unsigned char preprocessed_buf[eci_length_segs + seg_count]; +#else + unsigned char *preprocessed_buf = (unsigned char *) _alloca(eci_length_segs + seg_count); #endif - if ((symbol->input_mode & 0x07) == UNICODE_MODE && is_eci_convertible(symbol->eci)) { /* Prior check ensures ECI only set for those that support it */ + segs_cpy(segs, seg_count, local_segs); /* Shallow copy (needed to set default ECIs) */ preprocessed = preprocessed_buf; - error_number = utf8_to_eci(symbol->eci, source, preprocessed, &length); - if (error_number != 0) { - if (symbol->eci) { - sprintf(symbol->errtxt, "244: Invalid character in input data for ECI %d", symbol->eci); - } else { - strcpy(symbol->errtxt, "204: Invalid character in input data (ISO/IEC 8859-1 only)"); + for (i = 0; i < seg_count; i++) { + if (convertible[i]) { + error_number = utf8_to_eci(local_segs[i].eci, local_segs[i].source, preprocessed, + &local_segs[i].length); + if (error_number != 0) { + if (local_segs[i].eci) { + sprintf(symbol->errtxt, "244: Invalid character in input data for ECI %d", local_segs[i].eci); + } else { + strcpy(symbol->errtxt, "204: Invalid character in input data (ISO/IEC 8859-1 only)"); + } + return error_number; + } + local_segs[i].source = preprocessed; + preprocessed += local_segs[i].length + 1; } - return error_number; + } + if (supports_eci(symbol->symbology) || is_hibc(symbol->symbology)) { + error_number = (*(barcode_segs_func_t)barcode_funcs[symbol->symbology])(symbol, local_segs, seg_count); + } else { + error_number = (*(barcode_func_t)barcode_funcs[symbol->symbology])(symbol, local_segs[0].source, + local_segs[0].length); + } + } else { + if (supports_eci(symbol->symbology) || is_hibc(symbol->symbology)) { + segs_cpy(segs, seg_count, local_segs); /* Shallow copy (needed to set default ECIs) */ + error_number = (*(barcode_segs_func_t)barcode_funcs[symbol->symbology])(symbol, local_segs, seg_count); + } else { + error_number = (*(barcode_func_t)barcode_funcs[symbol->symbology])(symbol, segs[0].source, + segs[0].length); } } - error_number = (*barcode_funcs[symbol->symbology])(symbol, preprocessed, length); - return error_number; } +#if defined(__GNUC__) || defined(__clang__) +#pragma GCC diagnostic pop +#endif + STATIC_UNLESS_ZINT_TEST void strip_bom(unsigned char *source, int *input_length) { int i; @@ -693,38 +762,93 @@ STATIC_UNLESS_ZINT_TEST int escape_char_process(struct zint_symbol *symbol, unsi /* Encode a barcode. If `length` is 0, `source` must be NUL-terminated. */ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int length) { - int error_number, warn_number; -#ifdef _MSC_VER + struct zint_seg segs[1]; + + if (!symbol) return ZINT_ERROR_INVALID_DATA; + + segs[0].eci = symbol->eci; + segs[0].source = (unsigned char *) source; + segs[0].length = length; + + return ZBarcode_Encode_Segs(symbol, segs, 1); +} + +/* Encode a barcode with multiple ECI segments. */ +int ZBarcode_Encode_Segs(struct zint_symbol *symbol, const struct zint_seg segs[], const int seg_count) { + int error_number, warn_number = 0; + int total_len = 0; + int have_zero_eci = 0; + int i; unsigned char *local_source; +#ifndef _MSC_VER + struct zint_seg local_segs[seg_count > 0 ? seg_count : 1]; +#else + struct zint_seg *local_segs; + unsigned char *local_sources; + local_segs = (struct zint_seg *) _alloca(sizeof(struct zint_seg) * (seg_count > 0 ? seg_count : 1)); #endif if (!symbol) return ZINT_ERROR_INVALID_DATA; + if (segs == NULL) { + return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "200: Input segments NULL"); + } + if (seg_count <= 0) { + return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "205: Input segment count 0"); + } + if (seg_count > ZINT_MAX_SEG_COUNT) { + return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "771: Too many input segments (max 256)"); + } + + /* Check segment lengths */ + for (i = 0; i < seg_count; i++) { + local_segs[i] = segs[i]; + if (local_segs[i].source == NULL) { + sprintf(symbol->errtxt, "772: Input segment %d source NULL", i); + return error_tag(symbol, ZINT_ERROR_INVALID_DATA, NULL); + } + if (local_segs[i].length <= 0) { + local_segs[i].length = (int) ustrlen(local_segs[i].source); + } + if (local_segs[i].length <= 0) { + sprintf(symbol->errtxt, "773: Input segment %d length zero", i); + return error_tag(symbol, ZINT_ERROR_INVALID_DATA, NULL); + } + if (local_segs[i].length > ZINT_MAX_DATA_LEN) { + return error_tag(symbol, ZINT_ERROR_TOO_LONG, "777: Input data too long"); + } + total_len += local_segs[i].length; + } + if (symbol->debug & ZINT_DEBUG_PRINT) { - printf("ZBarcode_Encode: symbology: %d, input_mode: 0x%X, ECI: %d, option_1: %d, option_2: %d," + printf("ZBarcode_Encode_Segs: symbology: %d, input_mode: 0x%X, ECI: %d, option_1: %d, option_2: %d," " option_3: %d, scale: %g\n output_options: 0x%X, fg: %s, bg: %s," - " length: %d, First 10 source: \"%.*s\", First 10 primary: \"%.10s\"\n", + " seg_count: %d, length[0] %d," " First 10 source[0] \"%.*s\", First 10 primary: \"%.10s\"\n", symbol->symbology, symbol->input_mode, symbol->eci, symbol->option_1, symbol->option_2, symbol->option_3, symbol->scale, symbol->output_options, symbol->fgcolour, symbol->bgcolour, - length, length < 10 ? length : 10, source ? (const char *) source : "", symbol->primary); + seg_count, local_segs[0].length, local_segs[0].length < 10 ? local_segs[0].length : 10, + local_segs[0].source, symbol->primary); } - warn_number = 0; - - if (source == NULL) { - return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "200: Input data NULL"); - } - if (length <= 0) { - length = (int) ustrlen(source); - } - if (length <= 0) { - return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "205: No input data"); - } - if (length > ZINT_MAX_DATA_LEN) { + if (total_len > ZINT_MAX_DATA_LEN) { return error_tag(symbol, ZINT_ERROR_TOO_LONG, "243: Input data too long"); } - /* First check the symbology field */ + /* Reconcile symbol ECI and first segment ECI if both set */ + if (symbol->eci != local_segs[0].eci) { + if (symbol->eci && local_segs[0].eci) { + sprintf(symbol->errtxt, "774: Symbol ECI %d must match segment zero ECI %d", symbol->eci, + local_segs[0].eci); + return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, NULL); + } + if (symbol->eci) { + local_segs[0].eci = symbol->eci; + } else { + symbol->eci = local_segs[0].eci; + } + } + + /* Check the symbology field */ if (!ZBarcode_ValidID(symbol->symbology)) { int orig_symbology = symbol->symbology; /* For self-check */ if (symbol->symbology < 1) { @@ -835,15 +959,27 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int } } - if (symbol->eci != 0) { - if (!(supports_eci(symbol->symbology))) { - return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "217: Symbology does not support ECI switching"); - } - if ((symbol->eci < 0) || (symbol->eci == 1) || (symbol->eci == 2) || (symbol->eci > 999999)) { - return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "218: Invalid ECI mode"); + if (seg_count > 1 && !supports_eci(symbol->symbology)) { + return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "775: Symbology does not support multiple segments"); + } + + /* Check ECI(s) */ + for (i = 0; i < seg_count; i++) { + if (local_segs[i].eci) { + if (!supports_eci(symbol->symbology)) { + return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "217: Symbology does not support ECI switching"); + } + if (local_segs[i].eci < 0 || local_segs[i].eci == 1 || local_segs[i].eci == 2 || local_segs[i].eci == 14 + || local_segs[i].eci == 19 || local_segs[i].eci > 999999) { + sprintf(symbol->errtxt, "218: Invalid ECI code %d", local_segs[i].eci); + return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, NULL); + } + } else { + have_zero_eci = 1; } } + /* Check other symbol fields */ if ((symbol->scale < 0.01f) || (symbol->scale > 100.0f)) { return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "227: Scale out of range (0.01 to 100)"); } @@ -875,29 +1011,50 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int symbol->input_mode = DATA_MODE; /* Reset completely TODO: in future, warn/error */ } - if ((symbol->input_mode & 0x07) == UNICODE_MODE && !is_valid_utf8(source, length)) { - return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "245: Invalid UTF-8 in input data"); + if ((symbol->input_mode & 0x07) == GS1_MODE && !gs1_compliant(symbol->symbology)) { + return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "220: Selected symbology does not support GS1 mode"); } - -#ifndef _MSC_VER - unsigned char local_source[length + 1]; -#else - local_source = (unsigned char *) _alloca(length + 1); -#endif - - memcpy(local_source, source, length); - local_source[length] = '\0'; - - /* Start acting on input mode */ - if (symbol->input_mode & ESCAPE_MODE) { - error_number = escape_char_process(symbol, local_source, &length); /* Only returns errors, not warnings */ - if (error_number != 0) { - return error_tag(symbol, error_number, NULL); + if (seg_count > 1) { + /* Note: GS1_MODE not currently supported when using multiple segments */ + if ((symbol->input_mode & 0x07) == GS1_MODE) { + return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "776: GS1_MODE not supported for multiple segments"); } } if ((symbol->input_mode & 0x07) == UNICODE_MODE) { - strip_bom(local_source, &length); + for (i = 0; i < seg_count; i++) { + if (!is_valid_utf8(local_segs[i].source, local_segs[i].length)) { + return error_tag(symbol, ZINT_ERROR_INVALID_DATA, "245: Invalid UTF-8 in input data"); + } + } + } + +#ifndef _MSC_VER + unsigned char local_sources[total_len + seg_count]; +#else + local_sources = (unsigned char *) _alloca(total_len + seg_count); +#endif + + for (i = 0, local_source = local_sources; i < seg_count; i++) { + local_segs[i].source = local_source; + memcpy(local_segs[i].source, segs[i].source, local_segs[i].length); + local_segs[i].source[local_segs[i].length] = '\0'; + local_source += local_segs[i].length + 1; + } + + /* Start acting on input mode */ + if (symbol->input_mode & ESCAPE_MODE) { + for (i = 0; i < seg_count; i++) { + error_number = escape_char_process(symbol, local_segs[i].source, &local_segs[i].length); + if (error_number != 0) { /* Only returns errors, not warnings */ + return error_tag(symbol, error_number, NULL); + } + } + } + + if ((symbol->input_mode & 0x07) == UNICODE_MODE) { + /* Only strip BOM on first segment */ + strip_bom(local_segs[0].source, &local_segs[0].length); } if (((symbol->input_mode & 0x07) == GS1_MODE) || (check_force_gs1(symbol->symbology))) { @@ -906,11 +1063,11 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int // handle it themselves if (is_composite(symbol->symbology) || !check_force_gs1(symbol->symbology)) { #ifndef _MSC_VER - unsigned char reduced[length + 1]; + unsigned char reduced[local_segs[0].length + 1]; #else - unsigned char *reduced = (unsigned char *) _alloca(length + 1); + unsigned char *reduced = (unsigned char *) _alloca(local_segs[0].length + 1); #endif - error_number = gs1_verify(symbol, local_source, length, reduced); + error_number = gs1_verify(symbol, local_segs[0].source, local_segs[0].length, reduced); if (error_number) { static const char in_2d_comp[] = " in 2D component"; if (is_composite(symbol->symbology) @@ -923,29 +1080,29 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int } warn_number = error_number; /* Override any previous warning (errtxt has been overwritten) */ } - ustrcpy(local_source, reduced); // Cannot contain NUL char - length = (int) ustrlen(local_source); + ustrcpy(local_segs[0].source, reduced); // Cannot contain NUL char + local_segs[0].length = (int) ustrlen(reduced); } } else { return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "220: Selected symbology does not support GS1 mode"); } } - error_number = extended_or_reduced_charset(symbol, local_source, length); + error_number = extended_or_reduced_charset(symbol, local_segs, seg_count); - if ((error_number == ZINT_ERROR_INVALID_DATA) && symbol->eci == 0 && supports_eci(symbol->symbology) + if ((error_number == ZINT_ERROR_INVALID_DATA) && have_zero_eci && supports_eci(symbol->symbology) && (symbol->input_mode & 0x07) == UNICODE_MODE) { /* Try another ECI mode */ - symbol->eci = get_best_eci(local_source, length); - if (symbol->eci != 0) { - error_number = extended_or_reduced_charset(symbol, local_source, length); + const int first_eci_set = get_best_eci_segs(symbol, local_segs, seg_count); + if (first_eci_set != 0) { + error_number = extended_or_reduced_charset(symbol, local_segs, seg_count); /* Inclusion of ECI more noteworthy than other warnings, so overwrite (if any) */ if (error_number < ZINT_ERROR) { error_number = ZINT_WARN_USES_ECI; if (!(symbol->debug & ZINT_DEBUG_TEST)) { - sprintf(symbol->errtxt, "222: Encoded data includes ECI %d", symbol->eci); + sprintf(symbol->errtxt, "222: Encoded data includes ECI %d", first_eci_set); } - if (symbol->debug & ZINT_DEBUG_PRINT) printf("Added ECI %d\n", symbol->eci); + if (symbol->debug & ZINT_DEBUG_PRINT) printf("Added ECI %d\n", first_eci_set); } } } @@ -1069,10 +1226,24 @@ int ZBarcode_Buffer_Vector(struct zint_symbol *symbol, int rotate_angle) { /* Encode and output a symbol to file `symbol->outfile` */ int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, const unsigned char *source, int length, int rotate_angle) { + struct zint_seg segs[1]; + + if (!symbol) return ZINT_ERROR_INVALID_DATA; + + segs[0].eci = symbol->eci; + segs[0].source = (unsigned char *) source; + segs[0].length = length; + + return ZBarcode_Encode_Segs_and_Print(symbol, segs, 1, rotate_angle); +} + +/* Encode a symbol with multiple ECI segments and output to file `symbol->outfile` */ +int ZBarcode_Encode_Segs_and_Print(struct zint_symbol *symbol, const struct zint_seg segs[], const int seg_count, + int rotate_angle) { int error_number; int first_err; - error_number = ZBarcode_Encode(symbol, source, length); + error_number = ZBarcode_Encode_Segs(symbol, segs, seg_count); if (error_number >= ZINT_ERROR) { return error_number; } @@ -1088,10 +1259,24 @@ int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, const unsigned char *s /* Encode and output a symbol to memory as raster (`symbol->bitmap`) */ int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, const unsigned char *source, int length, int rotate_angle) { + struct zint_seg segs[1]; + + if (!symbol) return ZINT_ERROR_INVALID_DATA; + + segs[0].eci = symbol->eci; + segs[0].source = (unsigned char *) source; + segs[0].length = length; + + return ZBarcode_Encode_Segs_and_Buffer(symbol, segs, 1, rotate_angle); +} + +/* Encode a symbol with multiple ECI segments and output to memory as raster (`symbol->bitmap`) */ +int ZBarcode_Encode_Segs_and_Buffer(struct zint_symbol *symbol, const struct zint_seg segs[], + const int seg_count, int rotate_angle) { int error_number; int first_err; - error_number = ZBarcode_Encode(symbol, source, length); + error_number = ZBarcode_Encode_Segs(symbol, segs, seg_count); if (error_number >= ZINT_ERROR) { return error_number; } @@ -1108,10 +1293,24 @@ int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, const unsigned char * /* Encode and output a symbol to memory as vector (`symbol->vector`) */ int ZBarcode_Encode_and_Buffer_Vector(struct zint_symbol *symbol, const unsigned char *source, int length, int rotate_angle) { + struct zint_seg segs[1]; + + if (!symbol) return ZINT_ERROR_INVALID_DATA; + + segs[0].eci = symbol->eci; + segs[0].source = (unsigned char *) source; + segs[0].length = length; + + return ZBarcode_Encode_Segs_and_Buffer_Vector(symbol, segs, 1, rotate_angle); +} + +/* Encode a symbol with multiple ECI segments and output to memory as vector (`symbol->vector`) */ +int ZBarcode_Encode_Segs_and_Buffer_Vector(struct zint_symbol *symbol, const struct zint_seg segs[], + const int seg_count, int rotate_angle) { int error_number; int first_err; - error_number = ZBarcode_Encode(symbol, source, length); + error_number = ZBarcode_Encode_Segs(symbol, segs, seg_count); if (error_number >= ZINT_ERROR) { return error_number; } @@ -1601,3 +1800,5 @@ int ZBarcode_Version(void) { } return (ZINT_VERSION_MAJOR * 10000) + (ZINT_VERSION_MINOR * 100) + ZINT_VERSION_RELEASE; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/maxicode.c b/backend/maxicode.c index 48072c25..d87bd157 100644 --- a/backend/maxicode.c +++ b/backend/maxicode.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2010-2021 Robin Stuart + Copyright (C) 2010-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -29,7 +29,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ /* Includes corrections thanks to Monica Swanson @ Source Technologies */ #include @@ -114,7 +113,7 @@ static void maxi_bump(unsigned char set[], unsigned char character[], const int } /* If the value is present in array, return the value, else return badvalue */ -static int value_in_array(const unsigned char val, const unsigned char arr[], const int badvalue, +static int maxi_value_in_array(const unsigned char val, const unsigned char arr[], const int badvalue, const int arrLength) { int i; for (i = 0; i < arrLength; i++) { @@ -125,13 +124,13 @@ static int value_in_array(const unsigned char val, const unsigned char arr[], co /* Choose the best set from previous and next set in the range of the setval array, if no value can be found we * return setval[0] */ -static int bestSurroundingSet(const int index, const int length, const unsigned char set[], +static int maxi_bestSurroundingSet(const int index, const int length, const unsigned char set[], const int sp, const unsigned char setval[], const int setLength) { int badValue = -1; - int option1 = value_in_array(set[index - 1], setval, badValue, setLength); + int option1 = maxi_value_in_array(set[sp + index - 1], setval, badValue, setLength); if (index + 1 < length) { // we have two options to check (previous & next) - int option2 = value_in_array(set[index + 1], setval, badValue, setLength); + int option2 = maxi_value_in_array(set[sp + index + 1], setval, badValue, setLength); if (option2 != badValue && option1 > option2) { return option2; } @@ -144,10 +143,11 @@ static int bestSurroundingSet(const int index, const int length, const unsigned } /* Format text according to Appendix A */ -static int maxi_text_process(unsigned char maxi_codeword[144], const int mode, const unsigned char in_source[], - int length, const int structapp_cw, const int eci, const int scm_vv, const int debug_print) { +static int maxi_text_process(unsigned char set[144], unsigned char character[144], const int mode, + const unsigned char in_source[], int length, const int eci, const int scm_vv, int *p_sp, + const int debug_print) { - unsigned char set[144], character[144] = {0}; + int sp = *p_sp; int i, count, current_set, padding_set; static const unsigned char set15[2] = { 1, 5 }; @@ -161,12 +161,38 @@ static int maxi_text_process(unsigned char maxi_codeword[144], const int mode, c unsigned char *source_buf = (unsigned char *) _alloca(length + 9); #endif - if (length > 144) { + if (sp + length > 144) { return ZINT_ERROR_TOO_LONG; } + /* Insert ECI at the beginning of message if needed */ + /* Encode ECI assignment numbers according to table 3 */ + if (eci != 0) { + if (sp + 1 + length > 144) return ZINT_ERROR_TOO_LONG; + character[sp++] = 27; // ECI + if (eci <= 31) { + if (sp + 1 + length > 144) return ZINT_ERROR_TOO_LONG; + character[sp++] = eci; + } else if (eci <= 1023) { + if (sp + 2 + length > 144) return ZINT_ERROR_TOO_LONG; + character[sp++] = 0x20 | ((eci >> 6) & 0x0F); + character[sp++] = eci & 0x3F; + } else if (eci <= 32767) { + if (sp + 3 + length > 144) return ZINT_ERROR_TOO_LONG; + character[sp++] = 0x30 | ((eci >> 12) & 0x07); + character[sp++] = (eci >> 6) & 0x3F; + character[sp++] = eci & 0x3F; + } else { + if (sp + 4 + length > 144) return ZINT_ERROR_TOO_LONG; + character[sp++] = 0x38 | ((eci >> 18) & 0x03); + character[sp++] = (eci >> 12) & 0x3F; + character[sp++] = (eci >> 6) & 0x3F; + character[sp++] = eci & 0x3F; + } + } + if (scm_vv != -1) { /* Add SCM prefix */ - if (length > 135) { + if (sp + length > 135) { return ZINT_ERROR_TOO_LONG; } sprintf((char *) source_buf, "[)>\03601\035%02d", scm_vv); /* [)>\R01\Gvv */ @@ -175,117 +201,115 @@ static int maxi_text_process(unsigned char maxi_codeword[144], const int mode, c length += 9; } - memset(set, 255, 144); - for (i = 0; i < length; i++) { /* Look up characters in table from Appendix A - this gives value and code set for most characters */ - set[i] = maxiCodeSet[source[i]]; - character[i] = maxiSymbolChar[source[i]]; + set[sp + i] = maxiCodeSet[source[i]]; + character[sp + i] = maxiSymbolChar[source[i]]; } /* If a character can be represented in more than one code set, pick which version to use */ - if (set[0] == 0) { - if (character[0] == 13) { - character[0] = 0; + if (set[sp + 0] == 0) { + if (character[sp + 0] == 13) { + character[sp + 0] = 0; } - set[0] = 1; + set[sp + 0] = 1; } for (i = 1; i < length; i++) { - if (set[i] == 0) { + if (set[sp + i] == 0) { /* Special character */ - if (character[i] == 13) { + if (character[sp + i] == 13) { /* Carriage Return */ - set[i] = bestSurroundingSet(i, length, set, set15, 2); - if (set[i] == 5) { - character[i] = 13; + set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set15, 2); + if (set[sp + i] == 5) { + character[sp + i] = 13; } else { - character[i] = 0; + character[sp + i] = 0; } - } else if (character[i] == 28) { + } else if (character[sp + i] == 28) { /* FS */ - set[i] = bestSurroundingSet(i, length, set, set12345, 5); - if (set[i] == 5) { - character[i] = 32; + set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12345, 5); + if (set[sp + i] == 5) { + character[sp + i] = 32; } - } else if (character[i] == 29) { + } else if (character[sp + i] == 29) { /* GS */ - set[i] = bestSurroundingSet(i, length, set, set12345, 5); - if (set[i] == 5) { - character[i] = 33; + set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12345, 5); + if (set[sp + i] == 5) { + character[sp + i] = 33; } - } else if (character[i] == 30) { + } else if (character[sp + i] == 30) { /* RS */ - set[i] = bestSurroundingSet(i, length, set, set12345, 5); - if (set[i] == 5) { - character[i] = 34; + set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12345, 5); + if (set[sp + i] == 5) { + character[sp + i] = 34; } - } else if (character[i] == 32) { + } else if (character[sp + i] == 32) { /* Space */ - set[i] = bestSurroundingSet(i, length, set, set12345, 5); - if (set[i] == 1) { - character[i] = 32; - } else if (set[i] == 2) { - character[i] = 47; + set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12345, 5); + if (set[sp + i] == 1) { + character[sp + i] = 32; + } else if (set[sp + i] == 2) { + character[sp + i] = 47; } else { - character[i] = 59; + character[sp + i] = 59; } - } else if (character[i] == 44) { + } else if (character[sp + i] == 44) { /* Comma */ - set[i] = bestSurroundingSet(i, length, set, set12, 2); - if (set[i] == 2) { - character[i] = 48; + set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12, 2); + if (set[sp + i] == 2) { + character[sp + i] = 48; } - } else if (character[i] == 46) { + } else if (character[sp + i] == 46) { /* Full Stop */ - set[i] = bestSurroundingSet(i, length, set, set12, 2); - if (set[i] == 2) { - character[i] = 49; + set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12, 2); + if (set[sp + i] == 2) { + character[sp + i] = 49; } - } else if (character[i] == 47) { + } else if (character[sp + i] == 47) { /* Slash */ - set[i] = bestSurroundingSet(i, length, set, set12, 2); - if (set[i] == 2) { - character[i] = 50; + set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12, 2); + if (set[sp + i] == 2) { + character[sp + i] = 50; } - } else if (character[i] == 58) { + } else if (character[sp + i] == 58) { /* Colon */ - set[i] = bestSurroundingSet(i, length, set, set12, 2); - if (set[i] == 2) { - character[i] = 51; + set[sp + i] = maxi_bestSurroundingSet(i, length, set, sp, set12, 2); + if (set[sp + i] == 2) { + character[sp + i] = 51; } } } } - padding_set = set[length - 1] == 2 ? 2 : 1; - for (i = length; i < 144; i++) { + padding_set = set[sp + length - 1] == 2 ? 2 : 1; + for (i = length; sp + i < 144; i++) { /* Add the padding */ - set[i] = padding_set; - character[i] = 33; + set[sp + i] = padding_set; + character[sp + i] = 33; } /* Find candidates for number compression */ /* Note the prohibition on number compression in the primary message in ISO/IEC 16023:2000 B.1 (1) applies to modes 2 & 3 only */ count = 0; - for (i = 0; i < 144; i++) { - if ((set[i] == 1) && ((character[i] >= 48) && (character[i] <= 57))) { + for (i = 0; sp + i < 144; i++) { + if ((set[sp + i] == 1) && ((character[sp + i] >= 48) && (character[sp + i] <= 57))) { /* Character is a number */ count++; if (count == 9) { /* Nine digits in a row can be compressed */ - memset(set + i - 8, 6, 9); /* Set set of nine digits to 6 */ + memset(set + sp + i - 8, 6, 9); /* Set set of nine digits to 6 */ count = 0; } } else { @@ -298,58 +322,59 @@ static int maxi_text_process(unsigned char maxi_codeword[144], const int mode, c i = 0; do { - if ((set[i] != current_set) && (set[i] != 6)) { - switch (set[i]) { + if ((set[sp + i] != current_set) && (set[sp + i] != 6)) { + switch (set[sp + i]) { case 1: if (current_set == 2) { /* Set B */ - if (i + 1 < 144 && set[i + 1] == 1) { - if (i + 2 < 144 && set[i + 2] == 1) { - if (i + 3 < 144 && set[i + 3] == 1) { + if (sp + i + 1 < 144 && set[sp + i + 1] == 1) { + if (sp + i + 2 < 144 && set[sp + i + 2] == 1) { + if (sp + i + 3 < 144 && set[sp + i + 3] == 1) { /* Latch A */ - maxi_bump(set, character, i, &length); - character[i] = 63; /* Set B Latch A */ + maxi_bump(set, character, sp + i, &length); + character[sp + i] = 63; /* Set B Latch A */ current_set = 1; i += 3; /* Next 3 Set A so skip over */ if (debug_print) printf("LCHA "); } else { /* 3 Shift A */ - maxi_bump(set, character, i, &length); - character[i] = 57; /* Set B triple shift A */ + maxi_bump(set, character, sp + i, &length); + character[sp + i] = 57; /* Set B triple shift A */ i += 2; /* Next 2 Set A so skip over */ if (debug_print) printf("3SHA "); } } else { /* 2 Shift A */ - maxi_bump(set, character, i, &length); - character[i] = 56; /* Set B double shift A */ + maxi_bump(set, character, sp + i, &length); + character[sp + i] = 56; /* Set B double shift A */ i++; /* Next Set A so skip over */ if (debug_print) printf("2SHA "); } } else { /* Shift A */ - maxi_bump(set, character, i, &length); - character[i] = 59; /* Set A Shift B */ + maxi_bump(set, character, sp + i, &length); + character[sp + i] = 59; /* Set A Shift B */ if (debug_print) printf("SHA "); } } else { /* All sets other than B only have latch */ /* Latch A */ - maxi_bump(set, character, i, &length); - character[i] = 58; /* Sets C,D,E Latch A */ + maxi_bump(set, character, sp + i, &length); + character[sp + i] = 58; /* Sets C,D,E Latch A */ current_set = 1; if (debug_print) printf("LCHA "); } break; case 2: /* Set B */ - if (current_set != 1 || (i + 1 < 144 && set[i + 1] == 2)) { /* If not Set A or next Set B */ + /* If not Set A or next Set B */ + if (current_set != 1 || (sp + i + 1 < 144 && set[sp + i + 1] == 2)) { /* Latch B */ - maxi_bump(set, character, i, &length); - character[i] = 63; /* Sets A,C,D,E Latch B */ + maxi_bump(set, character, sp + i, &length); + character[sp + i] = 63; /* Sets A,C,D,E Latch B */ current_set = 2; if (debug_print) printf("LCHB "); } else { /* Only available from Set A */ /* Shift B */ - maxi_bump(set, character, i, &length); - character[i] = 59; /* Set B Shift A */ + maxi_bump(set, character, sp + i, &length); + character[sp + i] = 59; /* Set B Shift A */ if (debug_print) printf("SHB "); } break; @@ -357,116 +382,107 @@ static int maxi_text_process(unsigned char maxi_codeword[144], const int mode, c case 4: /* Set D */ case 5: /* Set E */ /* If first and next 3 same set, or not first and previous and next 2 same set */ - if ((i == 0 && i + 3 < 144 && set[i + 1] == set[i] && set[i + 2] == set[i] - && set[i + 3] == set[i]) - || (i > 0 && set[i - 1] == set[i] && i + 2 < 144 && set[i + 1] == set[i] - && set[i + 2] == set[i])) { + if ((sp + i == 0 && sp + i + 3 < 144 && set[sp + i + 1] == set[sp + i] + && set[sp + i + 2] == set[sp + i] && set[sp + i + 3] == set[sp + i]) + || (sp + i > 0 && set[sp + i - 1] == set[sp + i] && sp + i + 2 < 144 + && set[sp + i + 1] == set[sp + i] && set[sp + i + 2] == set[sp + i])) { /* Lock in C/D/E */ - if (i == 0) { - maxi_bump(set, character, i, &length); - character[i] = 60 + set[i] - 3; + if (sp + i == 0) { + maxi_bump(set, character, sp + i, &length); + character[sp + i] = 60 + set[sp + i] - 3; i++; /* Extra bump */ - maxi_bump(set, character, i, &length); - character[i] = 60 + set[i] - 3; + maxi_bump(set, character, sp + i, &length); + character[sp + i] = 60 + set[sp + i] - 3; i += 3; /* Next 3 same set so skip over */ } else { /* Add single Shift to previous Shift */ - maxi_bump(set, character, i - 1, &length); - character[i - 1] = 60 + set[i] - 3; + maxi_bump(set, character, sp + i - 1, &length); + character[sp + i - 1] = 60 + set[sp + i] - 3; i += 2; /* Next 2 same set so skip over */ } - current_set = set[i]; - if (debug_print) printf("LCK%c ", 'C' + set[i] - 3); + current_set = set[sp + i]; + if (debug_print) printf("LCK%c ", 'C' + set[sp + i] - 3); } else { /* Shift C/D/E */ - maxi_bump(set, character, i, &length); - character[i] = 60 + set[i] - 3; - if (debug_print) printf("SH%c ", 'C' + set[i] - 3); + maxi_bump(set, character, sp + i, &length); + character[sp + i] = 60 + set[sp + i] - 3; + if (debug_print) printf("SH%c ", 'C' + set[sp + i] - 3); } break; } i++; /* Allow for bump */ } i++; - } while (i < 144); + } while (sp + i < 144); if (debug_print) printf("\n"); /* Number compression has not been forgotten! - It's handled below */ i = 0; do { - if (set[i] == 6) { + if (set[sp + i] == 6) { /* Number compression */ - int value = to_int(character + i, 9); + int value = to_int(character + sp + i, 9); - character[i] = 31; /* NS */ - character[i + 1] = (value & 0x3f000000) >> 24; - character[i + 2] = (value & 0xfc0000) >> 18; - character[i + 3] = (value & 0x3f000) >> 12; - character[i + 4] = (value & 0xfc0) >> 6; - character[i + 5] = (value & 0x3f); + character[sp + i] = 31; /* NS */ + character[sp + i + 1] = (value & 0x3f000000) >> 24; + character[sp + i + 2] = (value & 0xfc0000) >> 18; + character[sp + i + 3] = (value & 0x3f000) >> 12; + character[sp + i + 4] = (value & 0xfc0) >> 6; + character[sp + i + 5] = (value & 0x3f); i += 6; - memmove(set + i, set + i + 3, 141 - i); - memmove(character + i, character + i + 3, 141 - i); + memmove(set + sp + i, set + sp + i + 3, 141 - (sp + i)); + memmove(character + sp + i, character + sp + i + 3, 141 - (sp + i)); length -= 3; } else { i++; } - } while (i <= 135); /* 144 - 9 */ - - /* Insert ECI at the beginning of message if needed */ - /* Encode ECI assignment numbers according to table 3 */ - if (eci != 0) { - maxi_bump(set, character, 0, &length); - character[0] = 27; // ECI - if (eci <= 31) { - maxi_bump(set, character, 1, &length); - character[1] = eci; - } else if (eci <= 1023) { - maxi_bump(set, character, 1, &length); - maxi_bump(set, character, 1, &length); - character[1] = 0x20 | ((eci >> 6) & 0x0F); - character[2] = eci & 0x3F; - } else if (eci <= 32767) { - maxi_bump(set, character, 1, &length); - maxi_bump(set, character, 1, &length); - maxi_bump(set, character, 1, &length); - character[1] = 0x30 | ((eci >> 12) & 0x07); - character[2] = (eci >> 6) & 0x3F; - character[3] = eci & 0x3F; - } else { - maxi_bump(set, character, 1, &length); - maxi_bump(set, character, 1, &length); - maxi_bump(set, character, 1, &length); - maxi_bump(set, character, 1, &length); - character[1] = 0x38 | ((eci >> 18) & 0x03); - character[2] = (eci >> 12) & 0x3F; - character[3] = (eci >> 6) & 0x3F; - character[4] = eci & 0x3F; - } - } - - /* Insert Structured Append at beginning if needed */ - if (structapp_cw) { - maxi_bump(set, character, 0, &length); - character[0] = 33; // PAD - maxi_bump(set, character, 1, &length); - character[1] = structapp_cw; - } + } while (sp + i <= 135); /* 144 - 9 */ if (debug_print) printf("Length: %d\n", length); - if (((mode == 2) || (mode == 3)) && (length > 84)) { + if (((mode == 2) || (mode == 3)) && (sp + length > 84)) { return ZINT_ERROR_TOO_LONG; - } else if (((mode == 4) || (mode == 6)) && (length > 93)) { + } else if (((mode == 4) || (mode == 6)) && (sp + length > 93)) { return ZINT_ERROR_TOO_LONG; - } else if ((mode == 5) && (length > 77)) { + } else if ((mode == 5) && (sp + length > 77)) { return ZINT_ERROR_TOO_LONG; } + *p_sp = sp + length; + + return 0; +} + +/* Call `maxi_text_process()` for each segment, dealing with Structured Append beforehand and populating + `maxi_codeword` afterwards */ +static int maxi_text_process_segs(unsigned char maxi_codeword[144], const int mode, const struct zint_seg segs[], + const int seg_count, const int structapp_cw, int scm_vv, const int debug_print) { + unsigned char set[144], character[144] = {0}; + int i; + int error_number; + int sp = 0; + + memset(set, 255, 144); + + /* Insert Structured Append at beginning if needed */ + if (structapp_cw) { + character[sp++] = 33; // PAD + character[sp++] = structapp_cw; + } + + for (i = 0; i < seg_count; i++) { + error_number = maxi_text_process(set, character, mode, segs[i].source, segs[i].length, segs[i].eci, scm_vv, + &sp, debug_print); + if (error_number != 0) { + return error_number; + } + scm_vv = -1; + } + /* Copy the encoded text into the codeword array */ if ((mode == 2) || (mode == 3)) { for (i = 0; i < 84; i++) { /* secondary only */ @@ -534,9 +550,9 @@ static void maxi_do_primary_3(unsigned char maxi_codeword[144], unsigned char po maxi_codeword[9] = ((service & 0x3f0) >> 4); } -INTERNAL int maxicode(struct zint_symbol *symbol, unsigned char source[], int length) { +INTERNAL int maxicode(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { int i, j, block, shift, mode, lp = 0; - int error_number = 0, eclen; + int error_number, eclen; unsigned char maxi_codeword[144] = {0}; int scm_vv = -1; int structapp_cw = 0; @@ -658,10 +674,10 @@ INTERNAL int maxicode(struct zint_symbol *symbol, unsigned char source[], int le structapp_cw = (symbol->structapp.count - 1) | ((symbol->structapp.index - 1) << 3); } - i = maxi_text_process(maxi_codeword, mode, source, length, structapp_cw, symbol->eci, scm_vv, debug_print); - if (i == ZINT_ERROR_TOO_LONG) { + error_number = maxi_text_process_segs(maxi_codeword, mode, segs, seg_count, structapp_cw, scm_vv, debug_print); + if (error_number == ZINT_ERROR_TOO_LONG) { strcpy(symbol->errtxt, "553: Input data too long"); - return i; + return error_number; } /* All the data is sorted - now do error correction */ @@ -724,3 +740,5 @@ INTERNAL int maxicode(struct zint_symbol *symbol, unsigned char source[], int le return error_number; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/pdf417.c b/backend/pdf417.c index fbc0bb4c..77edbab1 100644 --- a/backend/pdf417.c +++ b/backend/pdf417.c @@ -1,7 +1,7 @@ /* pdf417.c - Handles PDF417 stacked symbology */ /* Zint - A barcode generating program using libpng - Copyright (C) 2008-2021 Robin Stuart + Copyright (C) 2008-2022 Robin Stuart Portions Copyright (C) 2004 Grandzebu Bug Fixes thanks to KL Chin @@ -30,7 +30,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ /* This code is adapted from "Code barre PDF 417 / PDF 417 barcode" v2.5.0 which is Copyright (C) 2004 (Grandzebu). @@ -461,11 +460,11 @@ static void pdf_numbprocess(int *chainemc, int *mclength, const unsigned char ch } /* Initial processing of data, shared by `pdf417()` and `micropdf417()` */ -static int pdf_initial(struct zint_symbol *symbol, unsigned char chaine[], const int length, const int is_micro, - int chainemc[PDF_MAX_LEN], int *p_mclength, int structapp_cws[18], int *p_structapp_cp) { +static int pdf_initial(struct zint_symbol *symbol, unsigned char chaine[], const int length, const int eci, + const int is_micro, int chainemc[PDF_MAX_LEN], int *p_mclength) { int i, indexchaine, indexliste, mode; int liste[2][PDF_MAX_LEN] = {{0}}; - int mclength, structapp_cp = 0; + int mclength; const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; /* 456 */ @@ -507,7 +506,63 @@ static int pdf_initial(struct zint_symbol *symbol, unsigned char chaine[], const /* 541 - now compress the data */ indexchaine = 0; - mclength = is_micro ? 0 : 1; /* Allow for length descriptor for full symbol */ + mclength = *p_mclength; + if (mclength == 0 && !is_micro) { + mclength++; /* Allow for length descriptor for full symbol */ + } + + if (*p_mclength == 0 && (symbol->output_options & READER_INIT)) { + chainemc[mclength++] = 921; /* Reader Initialisation */ + } + + if (eci != 0) { + if (eci > 811799) { + strcpy(symbol->errtxt, "472: Invalid ECI"); + return ZINT_ERROR_INVALID_OPTION; + } + /* Encoding ECI assignment number, according to Table 8 */ + if (eci <= 899) { + chainemc[mclength++] = 927; /* ECI */ + chainemc[mclength++] = eci; + } else if (eci <= 810899) { + chainemc[mclength++] = 926; /* ECI */ + chainemc[mclength++] = (eci / 900) - 1; + chainemc[mclength++] = eci % 900; + } else { + chainemc[mclength++] = 925; /* ECI */ + chainemc[mclength++] = eci - 810900; + } + } + + for (i = 0; i < indexliste; i++) { + switch (liste[1][i]) { + case TEX: /* 547 - text mode */ + pdf_textprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i], is_micro); + break; + case BYT: /* 670 - octet stream mode */ + pdf_byteprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i], debug_print); + break; + case NUM: /* 712 - numeric mode */ + pdf_numbprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i]); + break; + } + indexchaine = indexchaine + liste[0][i]; + } + + *p_mclength = mclength; + + return 0; +} + +/* Call `pdf_initial()` for each segment, dealing with Structured Append beforehand */ +static int pdf_initial_segs(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count, + const int is_micro, int chainemc[PDF_MAX_LEN], int *p_mclength, int structapp_cws[18], + int *p_structapp_cp) { + int i; + int error_number = 0; + int structapp_cp = 0; + + *p_mclength = 0; if (symbol->structapp.count) { int id_cnt = 0, ids[10]; @@ -558,53 +613,21 @@ static int pdf_initial(struct zint_symbol *symbol, unsigned char chaine[], const structapp_cws[structapp_cp++] = 922; /* Special last segment terminator */ } } - - if (symbol->output_options & READER_INIT) { - chainemc[mclength++] = 921; /* Reader Initialisation */ - } - - if (symbol->eci != 0) { - if (symbol->eci > 811799) { - strcpy(symbol->errtxt, "472: Invalid ECI"); - return ZINT_ERROR_INVALID_OPTION; - } - /* Encoding ECI assignment number, according to Table 8 */ - if (symbol->eci <= 899) { - chainemc[mclength++] = 927; /* ECI */ - chainemc[mclength++] = symbol->eci; - } else if (symbol->eci <= 810899) { - chainemc[mclength++] = 926; /* ECI */ - chainemc[mclength++] = (symbol->eci / 900) - 1; - chainemc[mclength++] = symbol->eci % 900; - } else { - chainemc[mclength++] = 925; /* ECI */ - chainemc[mclength++] = symbol->eci - 810900; - } - } - - for (i = 0; i < indexliste; i++) { - switch (liste[1][i]) { - case TEX: /* 547 - text mode */ - pdf_textprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i], is_micro); - break; - case BYT: /* 670 - octet stream mode */ - pdf_byteprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i], debug_print); - break; - case NUM: /* 712 - numeric mode */ - pdf_numbprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i]); - break; - } - indexchaine = indexchaine + liste[0][i]; - } - - *p_mclength = mclength; *p_structapp_cp = structapp_cp; - return 0; + for (i = 0; i < seg_count; i++) { + error_number = pdf_initial(symbol, segs[i].source, segs[i].length, segs[i].eci, is_micro, chainemc, + p_mclength); + if (error_number) { /* Only errors return >= ZINT_ERROR */ + return error_number; + } + } + + return error_number; } /* 366 */ -static int pdf_enc(struct zint_symbol *symbol, unsigned char chaine[], const int length) { +static int pdf_enc(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { int i, j, longueur, loop, mccorrection[520] = {0}, offset; int total, chainemc[PDF_MAX_LEN], mclength, c1, c2, c3, dummy[35]; int rows, cols, ecc, ecc_cws, padding; @@ -616,12 +639,12 @@ static int pdf_enc(struct zint_symbol *symbol, unsigned char chaine[], const int const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; static const int ecc_num_cws[] = { 2, 4, 8, 16, 32, 64, 128, 256, 512 }; - if (length > PDF_MAX_LEN) { + if (segs_length(segs, seg_count) > PDF_MAX_LEN) { strcpy(symbol->errtxt, "463: Input string too long"); return ZINT_ERROR_TOO_LONG; } - error_number = pdf_initial(symbol, chaine, length, 0 /*is_micro*/, chainemc, &mclength, structapp_cws, + error_number = pdf_initial_segs(symbol, segs, seg_count, 0 /*is_micro*/, chainemc, &mclength, structapp_cws, &structapp_cp); if (error_number) { /* Only errors return >= ZINT_ERROR */ return error_number; @@ -856,7 +879,7 @@ static int pdf_enc(struct zint_symbol *symbol, unsigned char chaine[], const int } /* 345 */ -INTERNAL int pdf417(struct zint_symbol *symbol, unsigned char source[], int length) { +INTERNAL int pdf417(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { int codeerr, error_number; error_number = 0; @@ -887,7 +910,7 @@ INTERNAL int pdf417(struct zint_symbol *symbol, unsigned char source[], int leng } /* 349 */ - codeerr = pdf_enc(symbol, source, length); + codeerr = pdf_enc(symbol, segs, seg_count); /* 352 */ if (codeerr != 0) { @@ -899,7 +922,7 @@ INTERNAL int pdf417(struct zint_symbol *symbol, unsigned char source[], int leng } /* like PDF417 only much smaller! */ -INTERNAL int micropdf417(struct zint_symbol *symbol, unsigned char chaine[], int length) { +INTERNAL int micropdf417(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { int i, k, j, longueur, mccorrection[50] = {0}, offset; int total, chainemc[PDF_MAX_LEN], mclength, error_number = 0; char pattern[580]; @@ -910,7 +933,7 @@ INTERNAL int micropdf417(struct zint_symbol *symbol, unsigned char chaine[], int int LeftRAP, CentreRAP, RightRAP, Cluster, loop; const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; - if (length > MICRO_PDF_MAX_LEN) { + if (segs_length(segs, seg_count) > MICRO_PDF_MAX_LEN) { strcpy(symbol->errtxt, "474: Input data too long"); return ZINT_ERROR_TOO_LONG; } @@ -921,7 +944,7 @@ INTERNAL int micropdf417(struct zint_symbol *symbol, unsigned char chaine[], int /* Encoding starts out the same as PDF417, so use the same code */ - error_number = pdf_initial(symbol, chaine, length, 1 /*is_micro*/, chainemc, &mclength, structapp_cws, + error_number = pdf_initial_segs(symbol, segs, seg_count, 1 /*is_micro*/, chainemc, &mclength, structapp_cws, &structapp_cp); if (error_number) { /* Only errors return >= ZINT_ERROR */ return error_number; @@ -1230,3 +1253,5 @@ INTERNAL int micropdf417(struct zint_symbol *symbol, unsigned char chaine[], int #undef TEX #undef BYT #undef NUM + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/pdf417.h b/backend/pdf417.h index 19b8e650..1f22734e 100644 --- a/backend/pdf417.h +++ b/backend/pdf417.h @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2008-2021 Robin Stuart + Copyright (C) 2008-2022 Robin Stuart Portions Copyright (C) 2004 Grandzebu Redistribution and use in source and binary forms, with or without @@ -30,12 +30,11 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ /* See "pdf417_tabs.h" for table definitions */ -#ifndef __PDF417_H -#define __PDF417_H +#ifndef Z_PDF417_H +#define Z_PDF417_H /* PDF417 error correction coefficients from Grand Zebu */ INTERNAL_DATA_EXTERN const unsigned short pdf_coefrs[1022]; @@ -60,4 +59,5 @@ INTERNAL_DATA_EXTERN const unsigned short pdf_rap_centre[52]; INTERNAL void pdf_byteprocess(int *chainemc, int *mclength, const unsigned char chaine[], int start, const int length, const int debug); -#endif /* __PDF417_H */ +/* vim: set ts=4 sw=4 et : */ +#endif /* Z_PDF417_H */ diff --git a/backend/pdf417_tabs.h b/backend/pdf417_tabs.h index 362568cc..bf85a3da 100644 --- a/backend/pdf417_tabs.h +++ b/backend/pdf417_tabs.h @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2008-2021 Robin Stuart + Copyright (C) 2008-2022 Robin Stuart Portions Copyright (C) 2004 Grandzebu Redistribution and use in source and binary forms, with or without @@ -30,15 +30,14 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ /* this file contains the character table, the pre-calculated coefficients and the codeword patterns taken from lines 416 to 454 of pdf417.frm */ /* See "pdf417.h" for declarations */ -#ifndef __PDF417_TABS_H -#define __PDF417_TABS_H +#ifndef Z_PDF417_TABS_H +#define Z_PDF417_TABS_H /* PDF417 error correction coefficients from Grand Zebu */ INTERNAL_DATA const unsigned short pdf_coefrs[1022] = { @@ -511,4 +510,5 @@ INTERNAL_DATA const unsigned short pdf_rap_centre[52] = { 0x2DC, 0x2DE }; -#endif /* __PDF417_TABS_H */ +/* vim: set ts=4 sw=4 et : */ +#endif /* Z_PDF417_TABS_H */ diff --git a/backend/qr.c b/backend/qr.c index 0f88869b..109949b8 100644 --- a/backend/qr.c +++ b/backend/qr.c @@ -41,45 +41,29 @@ #include "reedsol.h" #include -#define LEVEL_L 1 -#define LEVEL_M 2 -#define LEVEL_Q 3 -#define LEVEL_H 4 +#define QR_ALPHA (IS_NUM_F | IS_UPR_F | IS_SPC_F | IS_AST_F | IS_PLS_F | IS_MNS_F | IS_SIL_F | IS_CLI_F) -static const char ecc_level_names[] = { 'L', 'M', 'Q', 'H' }; +#define QR_LEVEL_L 1 +#define QR_LEVEL_M 2 +#define QR_LEVEL_Q 3 +#define QR_LEVEL_H 4 + +static const char qr_ecc_level_names[] = { 'L', 'M', 'Q', 'H' }; #define QR_PERCENT 38 /* Alphanumeric mode % */ #define RMQR_VERSION 41 #define MICROQR_VERSION 73 -/* Returns true if input glyph is in the Alphanumeric set */ -static int is_alpha(const unsigned int glyph, const int gs1) { - int retval = 0; - - if ((glyph >= '0') && (glyph <= '9')) { - retval = 1; - } else if ((glyph >= 'A') && (glyph <= 'Z')) { - retval = 1; - } else if (gs1 && glyph == '[') { - retval = 1; - } else { - switch (glyph) { - case ' ': - case '$': - case '%': - case '*': - case '+': - case '-': - case '.': - case '/': - case ':': - retval = 1; - break; - } +/* Returns true if input glyph is in the Alphanumeric set or is GS1 FNC1 */ +static int qr_is_alpha(const unsigned int glyph, const int gs1) { + if (is_chr(QR_ALPHA, glyph)) { + return 1; } - - return retval; + if (gs1 && glyph == '[') { + return 1; + } + return 0; } /* Bits multiplied by this for costs, so as to be whole integer divisible by 2 and 3 */ @@ -87,7 +71,7 @@ static int is_alpha(const unsigned int glyph, const int gs1) { /* Whether in numeric or not. If in numeric, *p_end is set to position after numeric, and *p_cost is set to * per-numeric cost */ -static int in_numeric(const unsigned int jisdata[], const int length, const int in_posn, +static int qr_in_numeric(const unsigned int ddata[], const int length, const int in_posn, unsigned int *p_end, unsigned int *p_cost) { int i, digit_cnt; @@ -96,7 +80,7 @@ static int in_numeric(const unsigned int jisdata[], const int length, const int } /* Attempt to calculate the average 'cost' of using numeric mode in number of bits (times QR_MULT) */ - for (i = in_posn; i < length && i < in_posn + 4 && jisdata[i] >= '0' && jisdata[i] <= '9'; i++); + for (i = in_posn; i < length && i < in_posn + 4 && ddata[i] >= '0' && ddata[i] <= '9'; i++); digit_cnt = i - in_posn; @@ -112,14 +96,14 @@ static int in_numeric(const unsigned int jisdata[], const int length, const int /* Whether in alpha or not. If in alpha, *p_end is set to position after alpha, and *p_cost is set to per-alpha cost. * For GS1, *p_pcent set if 2nd char percent */ -static int in_alpha(const unsigned int jisdata[], const int length, const int in_posn, +static int qr_in_alpha(const unsigned int ddata[], const int length, const int in_posn, unsigned int *p_end, unsigned int *p_cost, unsigned int *p_pcent, unsigned int gs1) { int two_alphas; if (in_posn < (int) *p_end) { if (gs1 && *p_pcent) { /* Previous 2nd char was a percent, so allow for second half of doubled-up percent here */ - two_alphas = in_posn < length - 1 && is_alpha(jisdata[in_posn + 1], gs1); + two_alphas = in_posn < length - 1 && qr_is_alpha(ddata[in_posn + 1], gs1); *p_cost = two_alphas ? 33 /* (11 / 2) * QR_MULT */ : 36 /* 6 * QR_MULT */; *p_pcent = 0; } @@ -127,34 +111,34 @@ static int in_alpha(const unsigned int jisdata[], const int length, const int in } /* Attempt to calculate the average 'cost' of using alphanumeric mode in number of bits (times QR_MULT) */ - if (!is_alpha(jisdata[in_posn], gs1)) { + if (!qr_is_alpha(ddata[in_posn], gs1)) { *p_end = 0; *p_pcent = 0; return 0; } - if (gs1 && jisdata[in_posn] == '%') { /* Must double-up so counts as 2 chars */ + if (gs1 && ddata[in_posn] == '%') { /* Must double-up so counts as 2 chars */ *p_end = in_posn + 1; *p_cost = 66; /* 11 * QR_MULT */ *p_pcent = 0; return 1; } - two_alphas = in_posn < length - 1 && is_alpha(jisdata[in_posn + 1], gs1); + two_alphas = in_posn < length - 1 && qr_is_alpha(ddata[in_posn + 1], gs1); *p_end = two_alphas ? in_posn + 2 : in_posn + 1; *p_cost = two_alphas ? 33 /* (11 / 2) * QR_MULT */ : 36 /* 6 * QR_MULT */; - *p_pcent = two_alphas && gs1 && jisdata[in_posn + 1] == '%'; /* 2nd char is percent */ + *p_pcent = two_alphas && gs1 && ddata[in_posn + 1] == '%'; /* 2nd char is percent */ return 1; } -/* Indexes into mode_types array (and state array) */ +/* Indexes into qr_mode_types array (and state array) */ #define QR_N 0 /* Numeric */ #define QR_A 1 /* Alphanumeric */ #define QR_B 2 /* Byte */ #define QR_K 3 /* Kanji */ -static const char mode_types[] = { 'N', 'A', 'B', 'K', '\0' }; /* Must be in same order as QR_N etc */ +static const char qr_mode_types[] = { 'N', 'A', 'B', 'K', '\0' }; /* Must be in same order as QR_N etc */ #define QR_NUM_MODES 4 @@ -210,7 +194,7 @@ static unsigned int *qr_head_costs(unsigned int state[10]) { } /* Calculate optimized encoding modes. Adapted from Project Nayuki */ -static void qr_define_mode(char mode[], const unsigned int jisdata[], const int length, const int gs1, +static void qr_define_mode(char mode[], const unsigned int ddata[], const int length, const int gs1, const int version, const int debug_print) { /* * Copyright (c) Project Nayuki. (MIT License) @@ -244,11 +228,11 @@ static void qr_define_mode(char mode[], const unsigned int jisdata[], const int #endif /* char_modes[i * QR_NUM_MODES + j] represents the mode to encode the code point at index i such that the final - * segment ends in mode_types[j] and the total number of bits is minimized over all possible choices */ + * segment ends in qr_mode_types[j] and the total number of bits is minimized over all possible choices */ memset(char_modes, 0, length * QR_NUM_MODES); /* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/QR_MULT) - * bits needed to encode the entire string prefix of length i, and end in mode_types[j] */ + * bits needed to encode the entire string prefix of length i, and end in qr_mode_types[j] */ memcpy(prev_costs, qr_head_costs(state), QR_NUM_MODES * sizeof(unsigned int)); /* Calculate costs using dynamic programming */ @@ -258,17 +242,17 @@ static void qr_define_mode(char mode[], const unsigned int jisdata[], const int m1 = version == MICROQR_VERSION; m2 = version == MICROQR_VERSION + 1; - if (jisdata[i] > 0xFF) { + if (ddata[i] > 0xFF) { cur_costs[QR_B] = prev_costs[QR_B] + ((m1 || m2) ? QR_MICROQR_MAX : 96); /* 16 * QR_MULT */ char_modes[cm_i + QR_B] = 'B'; cur_costs[QR_K] = prev_costs[QR_K] + ((m1 || m2) ? QR_MICROQR_MAX : 78); /* 13 * QR_MULT */ char_modes[cm_i + QR_K] = 'K'; } else { - if (in_numeric(jisdata, length, i, &state[QR_N_END], &state[QR_N_COST])) { + if (qr_in_numeric(ddata, length, i, &state[QR_N_END], &state[QR_N_COST])) { cur_costs[QR_N] = prev_costs[QR_N] + state[QR_N_COST]; char_modes[cm_i + QR_N] = 'N'; } - if (in_alpha(jisdata, length, i, &state[QR_A_END], &state[QR_A_COST], &state[QR_A_PCENT], gs1)) { + if (qr_in_alpha(ddata, length, i, &state[QR_A_END], &state[QR_A_COST], &state[QR_A_PCENT], gs1)) { cur_costs[QR_A] = prev_costs[QR_A] + (m1 ? QR_MICROQR_MAX : state[QR_A_COST]); char_modes[cm_i + QR_A] = 'A'; } @@ -283,7 +267,7 @@ static void qr_define_mode(char mode[], const unsigned int jisdata[], const int const unsigned int new_cost = cur_costs[k] + state[j]; /* Switch costs same as head costs */ if (!char_modes[cm_i + j] || new_cost < cur_costs[j]) { cur_costs[j] = new_cost; - char_modes[cm_i + j] = mode_types[k]; + char_modes[cm_i + j] = qr_mode_types[k]; } } } @@ -294,17 +278,17 @@ static void qr_define_mode(char mode[], const unsigned int jisdata[], const int /* Find optimal ending mode */ min_cost = prev_costs[0]; - cur_mode = mode_types[0]; + cur_mode = qr_mode_types[0]; for (i = 1; i < QR_NUM_MODES; i++) { if (prev_costs[i] < min_cost) { min_cost = prev_costs[i]; - cur_mode = mode_types[i]; + cur_mode = qr_mode_types[i]; } } /* Get optimal mode for each code point by tracing backwards */ for (i = length - 1, cm_i = i * QR_NUM_MODES; i >= 0; i--, cm_i -= QR_NUM_MODES) { - j = posn(mode_types, cur_mode); + j = posn(qr_mode_types, cur_mode); cur_mode = char_modes[cm_i + j]; mode[i] = cur_mode; } @@ -315,7 +299,7 @@ static void qr_define_mode(char mode[], const unsigned int jisdata[], const int } /* Returns mode indicator based on version and mode */ -static int mode_indicator(const int version, const int mode) { +static int qr_mode_indicator(const int version, const int mode) { static const int mode_indicators[6][QR_NUM_MODES] = { /*N A B K */ { 1, 2, 4, 8, }, /* QRCODE */ @@ -326,7 +310,7 @@ static int mode_indicator(const int version, const int mode) { { 0, 1, 2, 3, }, }; - int mode_index = posn(mode_types, (const char) mode); + int mode_index = posn(qr_mode_types, (const char) mode); if (version < RMQR_VERSION) { return mode_indicators[0][mode_index]; /* QRCODE */ @@ -338,7 +322,7 @@ static int mode_indicator(const int version, const int mode) { } /* Return mode indicator bits based on version */ -static int mode_bits(const int version) { +static int qr_mode_bits(const int version) { if (version < RMQR_VERSION) { return 4; /* QRCODE */ } @@ -349,7 +333,7 @@ static int mode_bits(const int version) { } /* Return character count indicator bits based on version and mode */ -static int cci_bits(const int version, const int mode) { +static int qr_cci_bits(const int version, const int mode) { static const int cci_bits[7][QR_NUM_MODES] = { /* N A B K */ { 10, 9, 8, 8, }, /* QRCODE */ @@ -360,10 +344,10 @@ static int cci_bits(const int version, const int mode) { { 5, 4, 4, 3, }, { 6, 5, 5, 4, } }; - static const unsigned short int *rmqr_ccis[QR_NUM_MODES] = { + static const unsigned short *rmqr_ccis[QR_NUM_MODES] = { rmqr_numeric_cci, rmqr_alphanum_cci, rmqr_byte_cci, rmqr_kanji_cci, }; - int mode_index = posn(mode_types, (const char) mode); + int mode_index = posn(qr_mode_types, (const char) mode); if (version < RMQR_VERSION) { /* QRCODE */ if (version < 10) { @@ -381,7 +365,7 @@ static int cci_bits(const int version, const int mode) { } /* Returns terminator bits based on version */ -static int terminator_bits(const int version) { +static int qr_terminator_bits(const int version) { if (version < RMQR_VERSION) { return 4; /* QRCODE */ } @@ -392,43 +376,17 @@ static int terminator_bits(const int version) { } /* Convert input data to a binary stream and add padding */ -static int qr_binary(unsigned char datastream[], const int version, const int target_codewords, const char mode[], - const unsigned int jisdata[], const int length, const struct zint_structapp *p_structapp, const int gs1, - const int eci, const int est_binlen, const int debug_print) { +static int qr_binary(char binary[], int bp, const int version, const char mode[], + const unsigned int ddata[], const int length, const int gs1, + const int eci, const int debug_print) { int position = 0; - int i, j, bp; - int termbits, padbits, modebits; - int current_bytes; - int toggle, percent; + int i; + int modebits; + int percent = 0; int percent_count; -#ifndef _MSC_VER - char binary[est_binlen + 12]; -#else - char *binary= (char *) _alloca(est_binlen + 12); -#endif - - *binary = '\0'; - bp = 0; - - if (p_structapp) { - bp = bin_append_posn(3, 4, binary, bp); /* Structured Append indicator */ - bp = bin_append_posn(p_structapp->index - 1, 4, binary, bp); - bp = bin_append_posn(p_structapp->count - 1, 4, binary, bp); - bp = bin_append_posn(to_int((const unsigned char *) p_structapp->id, (int) strlen(p_structapp->id)), 8, - binary, bp); /* Parity */ - } - - if (gs1) { /* Not applicable to MICROQR */ - if (version < RMQR_VERSION) { - bp = bin_append_posn(5, 4, binary, bp); /* FNC1 */ - } else { - bp = bin_append_posn(5, 3, binary, bp); - } - } - if (eci != 0) { /* Not applicable to MICROQR */ - bp = bin_append_posn(7, 4, binary, bp); /* ECI (Table 4) */ + bp = bin_append_posn(7, version < RMQR_VERSION ? 4 : 3, binary, bp); /* ECI (Table 4) */ if (eci <= 127) { bp = bin_append_posn(eci, 8, binary, bp); /* 000000 to 000127 */ } else if (eci <= 16383) { @@ -438,16 +396,14 @@ static int qr_binary(unsigned char datastream[], const int version, const int ta } } - percent = 0; - - modebits = mode_bits(version); + modebits = qr_mode_bits(version); do { char data_block = mode[position]; int short_data_block_length = 0; int double_byte = 0; do { - if (data_block == 'B' && jisdata[position + short_data_block_length] > 0xFF) { + if (data_block == 'B' && ddata[position + short_data_block_length] > 0xFF) { double_byte++; } short_data_block_length++; @@ -456,7 +412,7 @@ static int qr_binary(unsigned char datastream[], const int version, const int ta /* Mode indicator */ if (modebits) { - bp = bin_append_posn(mode_indicator(version, data_block), modebits, binary, bp); + bp = bin_append_posn(qr_mode_indicator(version, data_block), modebits, binary, bp); } switch (data_block) { @@ -464,7 +420,7 @@ static int qr_binary(unsigned char datastream[], const int version, const int ta /* Kanji mode */ /* Character count indicator */ - bp = bin_append_posn(short_data_block_length, cci_bits(version, data_block), binary, bp); + bp = bin_append_posn(short_data_block_length, qr_cci_bits(version, data_block), binary, bp); if (debug_print) { printf("Kanji block (length %d)\n\t", short_data_block_length); @@ -472,7 +428,7 @@ static int qr_binary(unsigned char datastream[], const int version, const int ta /* Character representation */ for (i = 0; i < short_data_block_length; i++) { - unsigned int jis = jisdata[position + i]; + unsigned int jis = ddata[position + i]; int prod; if (jis >= 0x8140 && jis <= 0x9ffc) @@ -499,7 +455,7 @@ static int qr_binary(unsigned char datastream[], const int version, const int ta /* Byte mode */ /* Character count indicator */ - bp = bin_append_posn(short_data_block_length + double_byte, cci_bits(version, data_block), binary, + bp = bin_append_posn(short_data_block_length + double_byte, qr_cci_bits(version, data_block), binary, bp); if (debug_print) { @@ -508,7 +464,7 @@ static int qr_binary(unsigned char datastream[], const int version, const int ta /* Character representation */ for (i = 0; i < short_data_block_length; i++) { - unsigned int byte = jisdata[position + i]; + unsigned int byte = ddata[position + i]; if (gs1 && (byte == '[')) { byte = 0x1d; /* FNC1 */ @@ -532,15 +488,15 @@ static int qr_binary(unsigned char datastream[], const int version, const int ta percent_count = 0; if (gs1) { for (i = 0; i < short_data_block_length; i++) { - if (jisdata[position + i] == '%') { + if (ddata[position + i] == '%') { percent_count++; } } } /* Character count indicator */ - bp = bin_append_posn(short_data_block_length + percent_count, cci_bits(version, data_block), binary, - bp); + bp = bin_append_posn(short_data_block_length + percent_count, qr_cci_bits(version, data_block), + binary, bp); if (debug_print) { printf("Alpha block (length %d)\n\t", short_data_block_length + percent_count); @@ -553,33 +509,33 @@ static int qr_binary(unsigned char datastream[], const int version, const int ta int first = 0, second = 0, prod; if (percent == 0) { - if (gs1 && (jisdata[position + i] == '%')) { + if (gs1 && (ddata[position + i] == '%')) { first = QR_PERCENT; second = QR_PERCENT; count = 2; prod = (first * 45) + second; i++; } else { - if (gs1 && (jisdata[position + i] == '[')) { + if (gs1 && (ddata[position + i] == '[')) { first = QR_PERCENT; /* FNC1 */ } else { - first = qr_alphanumeric[jisdata[position + i] - 32]; + first = qr_alphanumeric[ddata[position + i] - 32]; } count = 1; i++; prod = first; if (i < short_data_block_length && mode[position + i] == 'A') { - if (gs1 && (jisdata[position + i] == '%')) { + if (gs1 && (ddata[position + i] == '%')) { second = QR_PERCENT; count = 2; prod = (first * 45) + second; percent = 1; } else { - if (gs1 && (jisdata[position + i] == '[')) { + if (gs1 && (ddata[position + i] == '[')) { second = QR_PERCENT; /* FNC1 */ } else { - second = qr_alphanumeric[jisdata[position + i] - 32]; + second = qr_alphanumeric[ddata[position + i] - 32]; } count = 2; i++; @@ -595,16 +551,16 @@ static int qr_binary(unsigned char datastream[], const int version, const int ta percent = 0; if (i < short_data_block_length && mode[position + i] == 'A') { - if (gs1 && (jisdata[position + i] == '%')) { + if (gs1 && (ddata[position + i] == '%')) { second = QR_PERCENT; count = 2; prod = (first * 45) + second; percent = 1; } else { - if (gs1 && (jisdata[position + i] == '[')) { + if (gs1 && (ddata[position + i] == '[')) { second = QR_PERCENT; /* FNC1 */ } else { - second = qr_alphanumeric[jisdata[position + i] - 32]; + second = qr_alphanumeric[ddata[position + i] - 32]; } count = 2; i++; @@ -629,7 +585,7 @@ static int qr_binary(unsigned char datastream[], const int version, const int ta /* Numeric mode */ /* Character count indicator */ - bp = bin_append_posn(short_data_block_length, cci_bits(version, data_block), binary, bp); + bp = bin_append_posn(short_data_block_length, qr_cci_bits(version, data_block), binary, bp); if (debug_print) { printf("Number block (length %d)\n\t", short_data_block_length); @@ -641,17 +597,17 @@ static int qr_binary(unsigned char datastream[], const int version, const int ta int count; int first = 0, prod; - first = ctoi((const char) jisdata[position + i]); + first = ctoi((const char) ddata[position + i]); count = 1; prod = first; if (i + 1 < short_data_block_length && mode[position + i + 1] == 'N') { - int second = ctoi((const char) jisdata[position + i + 1]); + int second = ctoi((const char) ddata[position + i + 1]); count = 2; prod = (prod * 10) + second; if (i + 2 < short_data_block_length && mode[position + i + 2] == 'N') { - int third = ctoi((const char) jisdata[position + i + 2]); + int third = ctoi((const char) ddata[position + i + 2]); count = 3; prod = (prod * 10) + third; } @@ -676,6 +632,50 @@ static int qr_binary(unsigned char datastream[], const int version, const int ta position += short_data_block_length; } while (position < length); + return bp; +} + +/* Call `qr_binary()` for each segment, dealing with Structured Append and GS1 beforehand and padding afterwards */ +static int qr_binary_segs(unsigned char datastream[], const int version, const int target_codewords, + const char mode[], const unsigned int ddata[], const struct zint_seg segs[], const int seg_count, + const struct zint_structapp *p_structapp, const int gs1, const int est_binlen, const int debug_print) { + int i, j; + const unsigned int *dd = ddata; + const char *m = mode; + int bp = 0; + int termbits, padbits; + int current_bytes; + int toggle; +#ifndef _MSC_VER + char binary[est_binlen + 12]; +#else + char *binary = (char *) _alloca(est_binlen + 12); +#endif + + *binary = '\0'; + + if (p_structapp) { + bp = bin_append_posn(3, 4, binary, bp); /* Structured Append indicator */ + bp = bin_append_posn(p_structapp->index - 1, 4, binary, bp); + bp = bin_append_posn(p_structapp->count - 1, 4, binary, bp); + bp = bin_append_posn(to_int((const unsigned char *) p_structapp->id, (int) strlen(p_structapp->id)), 8, + binary, bp); /* Parity */ + } + + if (gs1) { /* Not applicable to MICROQR */ + if (version < RMQR_VERSION) { + bp = bin_append_posn(5, 4, binary, bp); /* FNC1 */ + } else { + bp = bin_append_posn(5, 3, binary, bp); + } + } + + for (i = 0; i < seg_count; i++) { + bp = qr_binary(binary, bp, version, m, dd, segs[i].length, gs1, segs[i].eci, debug_print); + m += segs[i].length; + dd += segs[i].length; + } + if (version >= MICROQR_VERSION && version < MICROQR_VERSION + 4) { /* MICROQR does its own terminating/padding */ memcpy(datastream, binary, bp); @@ -689,7 +689,7 @@ static int qr_binary(unsigned char datastream[], const int version, const int ta } current_bytes = (bp + termbits) / 8; if (termbits || current_bytes < target_codewords) { - int max_termbits = terminator_bits(version); + int max_termbits = qr_terminator_bits(version); termbits = termbits < max_termbits && current_bytes == target_codewords ? termbits : max_termbits; bp = bin_append_posn(0, termbits, binary, bp); } @@ -742,7 +742,7 @@ static int qr_binary(unsigned char datastream[], const int version, const int ta } /* Split data into blocks, add error correction and then interleave the blocks and error correction data */ -static void add_ecc(unsigned char fullstream[], const unsigned char datastream[], const int version, +static void qr_add_ecc(unsigned char fullstream[], const unsigned char datastream[], const int version, const int data_cw, const int blocks, const int debug_print) { int ecc_cw; int short_data_block_length; @@ -804,7 +804,7 @@ static void add_ecc(unsigned char fullstream[], const unsigned char datastream[] } for (j = 0; j < length_this_block; j++) { - data_block[j] = datastream[in_posn + j]; + data_block[j] = datastream[in_posn + j]; // NOLINT false-positive popped up with clang-tidy 14.0.1 } rs_encode(&rs, length_this_block, data_block, ecc_block); @@ -856,7 +856,7 @@ static void add_ecc(unsigned char fullstream[], const unsigned char datastream[] } } -static void place_finder(unsigned char grid[], const int size, const int x, const int y) { +static void qr_place_finder(unsigned char grid[], const int size, const int x, const int y) { int xp, yp; char finder[] = {0x7F, 0x41, 0x5D, 0x5D, 0x5D, 0x41, 0x7F}; @@ -871,7 +871,7 @@ static void place_finder(unsigned char grid[], const int size, const int x, cons } } -static void place_align(unsigned char grid[], const int size, int x, int y) { +static void qr_place_align(unsigned char grid[], const int size, int x, int y) { int xp, yp; char alignment[] = {0x1F, 0x11, 0x15, 0x11, 0x1F}; @@ -889,7 +889,7 @@ static void place_align(unsigned char grid[], const int size, int x, int y) { } } -static void setup_grid(unsigned char *grid, const int size, const int version) { +static void qr_setup_grid(unsigned char *grid, const int size, const int version) { int i, toggle = 1; /* Add timing patterns */ @@ -906,9 +906,9 @@ static void setup_grid(unsigned char *grid, const int size, const int version) { } /* Add finder patterns */ - place_finder(grid, size, 0, 0); - place_finder(grid, size, 0, size - 7); - place_finder(grid, size, size - 7, 0); + qr_place_finder(grid, size, 0, 0); + qr_place_finder(grid, size, 0, size - 7); + qr_place_finder(grid, size, size - 7, 0); /* Add separators */ for (i = 0; i < 7; i++) { @@ -935,7 +935,7 @@ static void setup_grid(unsigned char *grid, const int size, const int version) { int ycoord = qr_table_e1[((version - 2) * 7) + y]; if (!(grid[(ycoord * size) + xcoord] & 0x10)) { - place_align(grid, size, xcoord, ycoord); + qr_place_align(grid, size, xcoord, ycoord); } } } @@ -964,7 +964,7 @@ static void setup_grid(unsigned char *grid, const int size, const int version) { } } -static int cwbit(const unsigned char *fullstream, const int i) { +static int qr_cwbit(const unsigned char *fullstream, const int i) { if (fullstream[(i >> 3)] & (0x80 >> (i & 0x07))) { return 1; @@ -973,7 +973,7 @@ static int cwbit(const unsigned char *fullstream, const int i) { return 0; } -static void populate_grid(unsigned char *grid, const int h_size, const int v_size, const unsigned char *fullstream, +static void qr_populate_grid(unsigned char *grid, const int h_size, const int v_size, const unsigned char *fullstream, const int cw) { const int not_rmqr = v_size == h_size; const int x_start = h_size - (not_rmqr ? 2 : 3); /* For rMQR allow for righthand vertical timing pattern */ @@ -993,13 +993,13 @@ static void populate_grid(unsigned char *grid, const int h_size, const int v_siz x--; /* skip over vertical timing pattern */ if (!(grid[r + (x + 1)] & 0xf0)) { - grid[r + (x + 1)] = cwbit(fullstream, i); + grid[r + (x + 1)] = qr_cwbit(fullstream, i); i++; } if (i < n) { if (!(grid[r + x] & 0xf0)) { - grid[r + x] = cwbit(fullstream, i); + grid[r + x] = qr_cwbit(fullstream, i); i++; } } @@ -1046,7 +1046,7 @@ static int write_log(char log[]) { } #endif -static int evaluate(unsigned char *local, const int size) { +static int qr_evaluate(unsigned char *local, const int size) { static const unsigned char h1011101[7] = { 1, 0, 1, 1, 1, 0, 1 }; int x, y, r, k, block; @@ -1261,17 +1261,17 @@ static int evaluate(unsigned char *local, const int size) { } /* Add format information to grid */ -static void add_format_info(unsigned char *grid, const int size, const int ecc_level, const int pattern) { +static void qr_add_format_info(unsigned char *grid, const int size, const int ecc_level, const int pattern) { int format = pattern; unsigned int seq; int i; switch (ecc_level) { - case LEVEL_L: format |= 0x08; + case QR_LEVEL_L: format |= 0x08; break; - case LEVEL_Q: format |= 0x18; + case QR_LEVEL_Q: format |= 0x18; break; - case LEVEL_H: format |= 0x10; + case QR_LEVEL_H: format |= 0x10; break; } @@ -1298,7 +1298,7 @@ static void add_format_info(unsigned char *grid, const int size, const int ecc_l grid[(8 * size) + 7] |= (seq >> 8) & 0x01; } -static int apply_bitmask(unsigned char *grid, const int size, const int ecc_level, const int user_mask, +static int qr_apply_bitmask(unsigned char *grid, const int size, const int ecc_level, const int user_mask, const int debug_print) { int x, y; int r, k; @@ -1368,9 +1368,9 @@ static int apply_bitmask(unsigned char *grid, const int size, const int ecc_leve local[k] = grid[k] & 0x0f; } } - add_format_info(local, size, ecc_level, pattern); + qr_add_format_info(local, size, ecc_level, pattern); - penalty[pattern] = evaluate(local, size); + penalty[pattern] = qr_evaluate(local, size); if (penalty[pattern] < penalty[best_pattern]) { best_pattern = pattern; @@ -1409,7 +1409,7 @@ static int apply_bitmask(unsigned char *grid, const int size, const int ecc_leve } /* Add version information */ -static void add_version_info(unsigned char *grid, const int size, const int version) { +static void qr_add_version_info(unsigned char *grid, const int size, const int version) { int i; long int version_data = qr_annex_d[version - 7]; @@ -1423,47 +1423,34 @@ static void add_version_info(unsigned char *grid, const int size, const int vers } } -static int blockLength(const int start, const char inputMode[], const int inputLength) { - /* Find the length of the block starting from 'start' */ +/* Find the length of the block starting from 'start' */ +static int qr_blockLength(const int start, const char mode[], const int length) { int i; - int count; - char mode = inputMode[start]; + int count = 0; + char start_mode = mode[start]; - count = 0; i = start; do { count++; - } while (((i + count) < inputLength) && (inputMode[i + count] == mode)); + } while (((i + count) < length) && (mode[i + count] == start_mode)); return count; } -static int getBinaryLength(const int version, char inputMode[], const unsigned int inputData[], const int inputLength, - const struct zint_structapp *p_structapp, const int gs1, const int eci, const int debug_print) { - /* Calculate the actual bitlength of the proposed binary string */ +/* Calculate the actual bitlength of the proposed binary string */ +static int qr_calc_binlen(const int version, char mode[], const unsigned int ddata[], const int length, const int gs1, + const int eci, const int debug_print) { int i, j; char currentMode; int count = 0; int alphalength; int blocklength; - qr_define_mode(inputMode, inputData, inputLength, gs1, version, debug_print); + qr_define_mode(mode, ddata, length, gs1, version, debug_print); currentMode = ' '; // Null - if (p_structapp) { - count += 4 + 8 + 8; - } - - if (gs1 == 1) { /* Not applicable to MICROQR */ - if (version < RMQR_VERSION) { - count += 4; - } else { - count += 3; - } - } - if (eci != 0) { // RMQR and MICROQR do not support ECI count += 4; if (eci <= 127) { @@ -1475,17 +1462,17 @@ static int getBinaryLength(const int version, char inputMode[], const unsigned i } } - for (i = 0; i < inputLength; i++) { - if (inputMode[i] != currentMode) { - count += mode_bits(version) + cci_bits(version, inputMode[i]); - blocklength = blockLength(i, inputMode, inputLength); - switch (inputMode[i]) { + for (i = 0; i < length; i++) { + if (mode[i] != currentMode) { + count += qr_mode_bits(version) + qr_cci_bits(version, mode[i]); + blocklength = qr_blockLength(i, mode, length); + switch (mode[i]) { case 'K': count += (blocklength * 13); break; case 'B': for (j = i; j < (i + blocklength); j++) { - if (inputData[j] > 0xff) { + if (ddata[j] > 0xff) { count += 16; } else { count += 8; @@ -1497,7 +1484,7 @@ static int getBinaryLength(const int version, char inputMode[], const unsigned i if (gs1) { // In alphanumeric mode % becomes %% for (j = i; j < (i + blocklength); j++) { - if (inputData[j] == '%') { + if (ddata[j] == '%') { alphalength++; } } @@ -1528,76 +1515,128 @@ static int getBinaryLength(const int version, char inputMode[], const unsigned i } break; } - currentMode = inputMode[i]; + currentMode = mode[i]; } } - if (debug_print) { - printf("Estimated Binary Length: %d (version %d, eci %d, gs1 %d)\n", count, version, eci, gs1); - } - return count; } -INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int length) { +/* Call `qr_calc_binlen()` on each segment */ +static int qr_calc_binlen_segs(const int version, char mode[], const unsigned int ddata[], + const struct zint_seg segs[], const int seg_count, const struct zint_structapp *p_structapp, + const int gs1, const int debug_print) { + int i; + int count = 0; + const unsigned int *dd = ddata; + char *m = mode; + + if (p_structapp) { + count += 4 + 8 + 8; + } + + if (gs1 == 1) { /* Not applicable to MICROQR */ + if (version < RMQR_VERSION) { + count += 4; + } else { + count += 3; + } + } + + for (i = 0; i < seg_count; i++) { + count += qr_calc_binlen(version, m, dd, segs[i].length, gs1, segs[i].eci, debug_print); + m += segs[i].length; + dd += segs[i].length; + } + + if (debug_print) { + printf("Estimated Binary Length: %d (version %d, gs1 %d)\n", count, version, gs1); + } + + return count; +} + +/* Helper to process source data into `ddata` array */ +static int qr_prep_data(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count, + unsigned int ddata[]) { int warn_number = 0; + int i; + /* If ZINT_FULL_MULTIBYTE use Kanji mode in DATA_MODE or for non-Shift JIS in UNICODE_MODE */ + const int full_multibyte = (symbol->option_3 & 0xFF) == ZINT_FULL_MULTIBYTE; + + if ((symbol->input_mode & 0x07) == DATA_MODE) { + sjis_cpy_segs(segs, seg_count, ddata, full_multibyte); + } else { + unsigned int *dd = ddata; + for (i = 0; i < seg_count; i++) { + int done = 0; + if (segs[i].eci != 20 || seg_count > 1) { /* Unless ECI 20 (Shift JIS) or have multiple segments */ + /* Try other encodings (ECI 0 defaults to ISO/IEC 8859-1) */ + int error_number = sjis_utf8_to_eci(segs[i].eci, segs[i].source, &segs[i].length, dd, full_multibyte); + if (error_number == 0) { + done = 1; + } else if (segs[i].eci || seg_count > 1) { + sprintf(symbol->errtxt, "575: Invalid character in input data for ECI %d", segs[i].eci); + return error_number; + } + } + if (!done) { + /* Try Shift-JIS */ + int error_number = sjis_utf8(symbol, segs[i].source, &segs[i].length, dd); + if (error_number != 0) { + return error_number; + } + if (segs[i].eci != 20) { + strcpy(symbol->errtxt, "543: Converted to Shift JIS but no ECI specified"); + warn_number = ZINT_WARN_NONCOMPLIANT; + } + } + dd += segs[i].length; + } + } + + return warn_number; +} + +INTERNAL int qrcode(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { + int warn_number; int i, j, est_binlen, prev_est_binlen; int ecc_level, autosize, version, max_cw, target_codewords, blocks, size; int bitmask, gs1; - int full_multibyte; int user_mask; int canShrink; int size_squared; const struct zint_structapp *p_structapp = NULL; const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; - const int eci_length = get_eci_length(symbol->eci, source, length); + const int eci_length_segs = get_eci_length_segs(segs, seg_count); #ifndef _MSC_VER - unsigned int jisdata[eci_length + 1]; - char mode[eci_length]; - char prev_mode[eci_length]; + struct zint_seg local_segs[seg_count]; + unsigned int ddata[eci_length_segs]; + char mode[eci_length_segs]; + char prev_mode[eci_length_segs]; #else + struct zint_seg *local_segs = (struct zint_seg *) _alloca(sizeof(struct zint_seg) * seg_count); + unsigned int *ddata = (unsigned int *) _alloca(sizeof(unsigned int) * eci_length_segs); + char *mode = (char *) _alloca(eci_length_segs); + char *prev_mode = (char *) _alloca(eci_length_segs); unsigned char *datastream; unsigned char *fullstream; unsigned char *grid; - unsigned int *jisdata = (unsigned int *) _alloca((eci_length + 1) * sizeof(unsigned int)); - char *mode = (char *) _alloca(eci_length); - char *prev_mode = (char *) _alloca(eci_length); #endif gs1 = ((symbol->input_mode & 0x07) == GS1_MODE); - /* If ZINT_FULL_MULTIBYTE use Kanji mode in DATA_MODE or for non-Shift JIS in UNICODE_MODE */ - full_multibyte = (symbol->option_3 & 0xFF) == ZINT_FULL_MULTIBYTE; + user_mask = (symbol->option_3 >> 8) & 0x0F; /* User mask is pattern + 1, so >= 1 and <= 8 */ if (user_mask > 8) { user_mask = 0; /* Ignore */ } - if ((symbol->input_mode & 0x07) == DATA_MODE) { - sjis_cpy(source, &length, jisdata, full_multibyte); - } else { - int done = 0; - if (symbol->eci != 20) { /* Unless ECI 20 (Shift JIS) */ - /* Try other encodings (ECI 0 defaults to ISO/IEC 8859-1) */ - int error_number = sjis_utf8_to_eci(symbol->eci, source, &length, jisdata, full_multibyte); - if (error_number == 0) { - done = 1; - } else if (symbol->eci) { - sprintf(symbol->errtxt, "575: Invalid character in input data for ECI %d", symbol->eci); - return error_number; - } - } - if (!done) { - /* Try Shift-JIS */ - int error_number = sjis_utf8(symbol, source, &length, jisdata); - if (error_number != 0) { - return error_number; - } - if (symbol->eci != 20) { - strcpy(symbol->errtxt, "543: Converted to Shift JIS but no ECI specified"); - warn_number = ZINT_WARN_NONCOMPLIANT; - } - } + segs_cpy(segs, seg_count, local_segs); /* Shallow copy (needed to set default ECIs & protect lengths) */ + + warn_number = qr_prep_data(symbol, local_segs, seg_count, ddata); + if (warn_number >= ZINT_ERROR) { + return warn_number; } if (symbol->structapp.count) { @@ -1632,21 +1671,21 @@ INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int leng p_structapp = &symbol->structapp; } - est_binlen = getBinaryLength(40, mode, jisdata, length, p_structapp, gs1, symbol->eci, debug_print); + est_binlen = qr_calc_binlen_segs(40, mode, ddata, local_segs, seg_count, p_structapp, gs1, debug_print); - ecc_level = LEVEL_L; + ecc_level = QR_LEVEL_L; max_cw = 2956; if ((symbol->option_1 >= 1) && (symbol->option_1 <= 4)) { switch (symbol->option_1) { case 1: break; - case 2: ecc_level = LEVEL_M; + case 2: ecc_level = QR_LEVEL_M; max_cw = 2334; break; - case 3: ecc_level = LEVEL_Q; + case 3: ecc_level = QR_LEVEL_Q; max_cw = 1666; break; - case 4: ecc_level = LEVEL_H; + case 4: ecc_level = QR_LEVEL_H; max_cw = 1276; break; } @@ -1660,22 +1699,22 @@ INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int leng autosize = 40; for (i = 39; i >= 0; i--) { switch (ecc_level) { - case LEVEL_L: + case QR_LEVEL_L: if ((8 * qr_data_codewords_L[i]) >= est_binlen) { autosize = i + 1; } break; - case LEVEL_M: + case QR_LEVEL_M: if ((8 * qr_data_codewords_M[i]) >= est_binlen) { autosize = i + 1; } break; - case LEVEL_Q: + case QR_LEVEL_Q: if ((8 * qr_data_codewords_Q[i]) >= est_binlen) { autosize = i + 1; } break; - case LEVEL_H: + case QR_LEVEL_H: if ((8 * qr_data_codewords_H[i]) >= est_binlen) { autosize = i + 1; } @@ -1683,7 +1722,7 @@ INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int leng } } if (autosize != 40) { - est_binlen = getBinaryLength(autosize, mode, jisdata, length, p_structapp, gs1, symbol->eci, debug_print); + est_binlen = qr_calc_binlen_segs(autosize, mode, ddata, local_segs, seg_count, p_structapp, gs1, debug_print); } // Now see if the optimised binary will fit in a smaller symbol. @@ -1694,27 +1733,27 @@ INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int leng canShrink = 0; } else { prev_est_binlen = est_binlen; - memcpy(prev_mode, mode, length); - est_binlen = getBinaryLength(autosize - 1, mode, jisdata, length, p_structapp, gs1, symbol->eci, + memcpy(prev_mode, mode, eci_length_segs); + est_binlen = qr_calc_binlen_segs(autosize - 1, mode, ddata, local_segs, seg_count, p_structapp, gs1, debug_print); switch (ecc_level) { - case LEVEL_L: + case QR_LEVEL_L: if ((8 * qr_data_codewords_L[autosize - 2]) < est_binlen) { canShrink = 0; } break; - case LEVEL_M: + case QR_LEVEL_M: if ((8 * qr_data_codewords_M[autosize - 2]) < est_binlen) { canShrink = 0; } break; - case LEVEL_Q: + case QR_LEVEL_Q: if ((8 * qr_data_codewords_Q[autosize - 2]) < est_binlen) { canShrink = 0; } break; - case LEVEL_H: + case QR_LEVEL_H: if ((8 * qr_data_codewords_H[autosize - 2]) < est_binlen) { canShrink = 0; } @@ -1727,7 +1766,7 @@ INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int leng } else { // Data did not fit in the smaller symbol, revert to original size est_binlen = prev_est_binlen; - memcpy(mode, prev_mode, length); + memcpy(mode, prev_mode, eci_length_segs); } } } while (canShrink == 1); @@ -1741,7 +1780,7 @@ INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int leng */ if (symbol->option_2 > version) { version = symbol->option_2; - est_binlen = getBinaryLength(symbol->option_2, mode, jisdata, length, p_structapp, gs1, symbol->eci, + est_binlen = qr_calc_binlen_segs(symbol->option_2, mode, ddata, local_segs, seg_count, p_structapp, gs1, debug_print); } @@ -1754,26 +1793,26 @@ INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int leng /* Ensure maxium error correction capacity unless user-specified */ if (symbol->option_1 == -1 || symbol->option_1 != ecc_level) { if (est_binlen <= qr_data_codewords_M[version - 1] * 8) { - ecc_level = LEVEL_M; + ecc_level = QR_LEVEL_M; } if (est_binlen <= qr_data_codewords_Q[version - 1] * 8) { - ecc_level = LEVEL_Q; + ecc_level = QR_LEVEL_Q; } if (est_binlen <= qr_data_codewords_H[version - 1] * 8) { - ecc_level = LEVEL_H; + ecc_level = QR_LEVEL_H; } } target_codewords = qr_data_codewords_L[version - 1]; blocks = qr_blocks_L[version - 1]; switch (ecc_level) { - case LEVEL_M: target_codewords = qr_data_codewords_M[version - 1]; + case QR_LEVEL_M: target_codewords = qr_data_codewords_M[version - 1]; blocks = qr_blocks_M[version - 1]; break; - case LEVEL_Q: target_codewords = qr_data_codewords_Q[version - 1]; + case QR_LEVEL_Q: target_codewords = qr_data_codewords_Q[version - 1]; blocks = qr_blocks_Q[version - 1]; break; - case LEVEL_H: target_codewords = qr_data_codewords_H[version - 1]; + case QR_LEVEL_H: target_codewords = qr_data_codewords_H[version - 1]; blocks = qr_blocks_H[version - 1]; break; } @@ -1781,7 +1820,7 @@ INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int leng if (debug_print) { printf("Minimum codewords: %d\n", (est_binlen + 7) / 8); printf("Selected version: %d-%c (%dx%d)\n", - version, ecc_level_names[ecc_level - 1], qr_sizes[version - 1], qr_sizes[version - 1]); + version, qr_ecc_level_names[ecc_level - 1], qr_sizes[version - 1], qr_sizes[version - 1]); printf("Number of data codewords in symbol: %d\n", target_codewords); printf("Number of ECC blocks: %d\n", blocks); } @@ -1794,12 +1833,12 @@ INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int leng fullstream = (unsigned char *) _alloca(qr_total_codewords[version - 1] + 1); #endif - (void) qr_binary(datastream, version, target_codewords, mode, jisdata, length, p_structapp, gs1, symbol->eci, + (void) qr_binary_segs(datastream, version, target_codewords, mode, ddata, local_segs, seg_count, p_structapp, gs1, est_binlen, debug_print); #ifdef ZINT_TEST if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); #endif - add_ecc(fullstream, datastream, version, target_codewords, blocks, debug_print); + qr_add_ecc(fullstream, datastream, version, target_codewords, blocks, debug_print); size = qr_sizes[version - 1]; size_squared = size * size; @@ -1811,16 +1850,16 @@ INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int leng memset(grid, 0, size_squared); - setup_grid(grid, size, version); - populate_grid(grid, size, size, fullstream, qr_total_codewords[version - 1]); + qr_setup_grid(grid, size, version); + qr_populate_grid(grid, size, size, fullstream, qr_total_codewords[version - 1]); if (version >= 7) { - add_version_info(grid, size, version); + qr_add_version_info(grid, size, version); } - bitmask = apply_bitmask(grid, size, ecc_level, user_mask, debug_print); + bitmask = qr_apply_bitmask(grid, size, ecc_level, user_mask, debug_print); - add_format_info(grid, size, ecc_level, bitmask); + qr_add_format_info(grid, size, ecc_level, bitmask); symbol->width = size; symbol->rows = size; @@ -1937,10 +1976,10 @@ static int micro_qr_m2(struct zint_symbol *symbol, char binary_data[], int bp, c latch = 0; - if (ecc_mode == LEVEL_L) { + if (ecc_mode == QR_LEVEL_L) { bits_total = 40; } - else if (ecc_mode == LEVEL_M) { + else if (ecc_mode == QR_LEVEL_M) { bits_total = 32; } else assert(0); @@ -1975,11 +2014,11 @@ static int micro_qr_m2(struct zint_symbol *symbol, char binary_data[], int bp, c } } - if (ecc_mode == LEVEL_L) { + if (ecc_mode == QR_LEVEL_L) { data_codewords = 5; ecc_codewords = 5; } - else if (ecc_mode == LEVEL_M) { + else if (ecc_mode == QR_LEVEL_M) { data_codewords = 4; ecc_codewords = 6; } @@ -2021,10 +2060,10 @@ static int micro_qr_m3(struct zint_symbol *symbol, char binary_data[], int bp, c latch = 0; - if (ecc_mode == LEVEL_L) { + if (ecc_mode == QR_LEVEL_L) { bits_total = 84; } - else if (ecc_mode == LEVEL_M) { + else if (ecc_mode == QR_LEVEL_M) { bits_total = 68; } else assert(0); @@ -2073,11 +2112,11 @@ static int micro_qr_m3(struct zint_symbol *symbol, char binary_data[], int bp, c bp = bin_append_posn(0, 4, binary_data, bp); } - if (ecc_mode == LEVEL_L) { + if (ecc_mode == QR_LEVEL_L) { data_codewords = 11; ecc_codewords = 6; } - else if (ecc_mode == LEVEL_M) { + else if (ecc_mode == QR_LEVEL_M) { data_codewords = 9; ecc_codewords = 8; } @@ -2094,7 +2133,7 @@ static int micro_qr_m3(struct zint_symbol *symbol, char binary_data[], int bp, c } } - if (ecc_mode == LEVEL_L) { + if (ecc_mode == QR_LEVEL_L) { data_blocks[10] = 0; for (j = 0; j < 4; j++) { if (binary_data[80 + j] == '1') { @@ -2103,7 +2142,7 @@ static int micro_qr_m3(struct zint_symbol *symbol, char binary_data[], int bp, c } } - if (ecc_mode == LEVEL_M) { + if (ecc_mode == QR_LEVEL_M) { data_blocks[8] = 0; for (j = 0; j < 4; j++) { if (binary_data[64 + j] == '1') { @@ -2137,13 +2176,13 @@ static int micro_qr_m4(struct zint_symbol *symbol, char binary_data[], int bp, c latch = 0; - if (ecc_mode == LEVEL_L) { + if (ecc_mode == QR_LEVEL_L) { bits_total = 128; } - else if (ecc_mode == LEVEL_M) { + else if (ecc_mode == QR_LEVEL_M) { bits_total = 112; } - else if (ecc_mode == LEVEL_Q) { + else if (ecc_mode == QR_LEVEL_Q) { bits_total = 80; } else assert(0); @@ -2178,15 +2217,15 @@ static int micro_qr_m4(struct zint_symbol *symbol, char binary_data[], int bp, c } } - if (ecc_mode == LEVEL_L) { + if (ecc_mode == QR_LEVEL_L) { data_codewords = 16; ecc_codewords = 8; } - else if (ecc_mode == LEVEL_M) { + else if (ecc_mode == QR_LEVEL_M) { data_codewords = 14; ecc_codewords = 10; } - else if (ecc_mode == LEVEL_Q) { + else if (ecc_mode == QR_LEVEL_Q) { data_codewords = 10; ecc_codewords = 14; } @@ -2236,7 +2275,7 @@ static void micro_setup_grid(unsigned char *grid, const int size) { } /* Add finder patterns */ - place_finder(grid, size, 0, 0); + qr_place_finder(grid, size, 0, 0); /* Add separators */ for (i = 0; i < 7; i++) { @@ -2433,7 +2472,7 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len int full_multibyte; int user_mask; - unsigned int jisdata[40]; + unsigned int ddata[40]; char mode[40]; int alpha_used = 0, byte_or_kanji_used = 0; int version_valid[4]; @@ -2441,6 +2480,8 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len int ecc_level, autoversion, version; int bitmask, format, format_full; int size_squared; + struct zint_seg segs[1]; + const int seg_count = 1; const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; #ifdef _MSC_VER unsigned char *grid; @@ -2452,7 +2493,7 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len } /* Check option 1 in combination with option 2 */ - ecc_level = LEVEL_L; + ecc_level = QR_LEVEL_L; if (symbol->option_1 >= 1 && symbol->option_1 <= 4) { if (symbol->option_1 == 4) { strcpy(symbol->errtxt, "566: Error correction level H not available"); @@ -2479,13 +2520,13 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len } if ((symbol->input_mode & 0x07) == DATA_MODE) { - sjis_cpy(source, &length, jisdata, full_multibyte); + sjis_cpy(source, &length, ddata, full_multibyte); } else { /* Try ISO 8859-1 conversion first */ - int error_number = sjis_utf8_to_eci(3, source, &length, jisdata, full_multibyte); + int error_number = sjis_utf8_to_eci(3, source, &length, ddata, full_multibyte); if (error_number != 0) { /* Try Shift-JIS */ - error_number = sjis_utf8(symbol, source, &length, jisdata); + error_number = sjis_utf8(symbol, source, &length, ddata); if (error_number != 0) { return error_number; } @@ -2494,8 +2535,8 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len /* Determine if alpha (excluding numerics), byte or kanji used */ for (i = 0; i < length && (alpha_used == 0 || byte_or_kanji_used == 0); i++) { - if (jisdata[i] < '0' || jisdata[i] > '9') { - if (is_alpha(jisdata[i], 0 /*gs1*/)) { + if (ddata[i] < '0' || ddata[i] > '9') { + if (qr_is_alpha(ddata[i], 0 /*gs1*/)) { alpha_used = 1; } else { byte_or_kanji_used = 1; @@ -2516,19 +2557,23 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len } /* Eliminate possible versions depending on error correction level specified */ - if (ecc_level == LEVEL_Q) { + if (ecc_level == QR_LEVEL_Q) { version_valid[0] = 0; version_valid[1] = 0; version_valid[2] = 0; - } else if (ecc_level == LEVEL_M) { + } else if (ecc_level == QR_LEVEL_M) { version_valid[0] = 0; } + segs[0].source = source; + segs[0].length = length; + segs[0].eci = 0; + /* Determine length of binary data */ for (i = 0; i < 4; i++) { if (version_valid[i]) { - binary_count[i] = getBinaryLength(MICROQR_VERSION + i, mode, jisdata, length, NULL /*p_structapp*/, - 0 /*gs1*/, 0 /*eci*/, debug_print); + binary_count[i] = qr_calc_binlen_segs(MICROQR_VERSION + i, mode, ddata, segs, seg_count, + NULL /*p_structapp*/, 0 /*gs1*/, debug_print); } else { binary_count[i] = 128 + 1; } @@ -2550,12 +2595,12 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len } /* Eliminate possible versions depending on binary length and error correction level specified */ - if (ecc_level == LEVEL_Q) { + if (ecc_level == QR_LEVEL_Q) { if (binary_count[3] > 80) { strcpy(symbol->errtxt, "567: Input data too long"); return ZINT_ERROR_TOO_LONG; } - } else if (ecc_level == LEVEL_M) { + } else if (ecc_level == QR_LEVEL_M) { if (binary_count[1] > 32) { version_valid[1] = 0; } @@ -2582,6 +2627,14 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len version = autoversion; /* Get version from user */ if ((symbol->option_2 >= 1) && (symbol->option_2 <= 4)) { + if (symbol->option_2 == 1 && !is_sane(NEON_F, source, length)) { + strcpy(symbol->errtxt, "775: Invalid character in data for Version M1 (digits only)"); + return ZINT_ERROR_INVALID_DATA; + } else if (symbol->option_2 == 2 && !is_sane(QR_ALPHA, source, length)) { + strcpy(symbol->errtxt, + "776: Invalid character in data for Version M2 (digits, A-Z, space and \"$%*+-./:\" only)"); + return ZINT_ERROR_INVALID_DATA; + } if (symbol->option_2 - 1 >= autoversion) { version = symbol->option_2 - 1; } else { @@ -2594,26 +2647,26 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len if (symbol->option_1 == -1 || symbol->option_1 != ecc_level) { if (version == 3) { if (binary_count[3] <= 112) { - ecc_level = LEVEL_M; + ecc_level = QR_LEVEL_M; } if (binary_count[3] <= 80) { - ecc_level = LEVEL_Q; + ecc_level = QR_LEVEL_Q; } } else if (version == 2) { if (binary_count[2] <= 68) { - ecc_level = LEVEL_M; + ecc_level = QR_LEVEL_M; } } else if (version == 1) { if (binary_count[1] <= 32) { - ecc_level = LEVEL_M; + ecc_level = QR_LEVEL_M; } } } - qr_define_mode(mode, jisdata, length, 0 /*gs1*/, MICROQR_VERSION + version, debug_print); + qr_define_mode(mode, ddata, length, 0 /*gs1*/, MICROQR_VERSION + version, debug_print); - bp = qr_binary((unsigned char *) full_stream, MICROQR_VERSION + version, 0 /*target_codewords*/, mode, jisdata, - length, NULL /*p_structapp*/, 0 /*gs1*/, 0 /*eci*/, binary_count[version], debug_print); + bp = qr_binary_segs((unsigned char *) full_stream, MICROQR_VERSION + version, 0 /*target_codewords*/, mode, ddata, + segs, seg_count, NULL /*p_structapp*/, 0 /*gs1*/, binary_count[version], debug_print); if (debug_print) printf("Binary (%d): %.*s\n", bp, bp, full_stream); @@ -2672,7 +2725,7 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len if (debug_print) { printf("Version: M%d-%c, Size: %dx%d, Format: %d\n", - version + 1, ecc_level_names[ecc_level - 1], size, size, format); + version + 1, qr_ecc_level_names[ecc_level - 1], size, size, format); } format_full = qr_annex_c1[(format << 2) + bitmask]; @@ -2745,16 +2798,18 @@ INTERNAL int upnqr(struct zint_symbol *symbol, unsigned char source[], int lengt int ecc_level, version, target_codewords, blocks, size; int bitmask, error_number; int size_squared; + struct zint_seg segs[1]; + const int seg_count = 1; const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; #ifndef _MSC_VER - unsigned int jisdata[length + 1]; + unsigned int ddata[length + 1]; char mode[length + 1]; #else unsigned char *datastream; unsigned char *fullstream; unsigned char *grid; - unsigned int *jisdata = (unsigned int *) _alloca((length + 1) * sizeof(unsigned int)); + unsigned int *ddata = (unsigned int *) _alloca(sizeof(unsigned int) * length); char *mode = (char *) _alloca(length + 1); #endif @@ -2770,7 +2825,7 @@ INTERNAL int upnqr(struct zint_symbol *symbol, unsigned char source[], int lengt case DATA_MODE: /* Input is already in ISO-8859-2 format */ for (i = 0; i < length; i++) { - jisdata[i] = source[i]; + ddata[i] = source[i]; mode[i] = 'B'; } break; @@ -2785,15 +2840,19 @@ INTERNAL int upnqr(struct zint_symbol *symbol, unsigned char source[], int lengt return error_number; } for (i = 0; i < length; i++) { - jisdata[i] = preprocessed[i]; + ddata[i] = preprocessed[i]; mode[i] = 'B'; } break; } - est_binlen = getBinaryLength(15, mode, jisdata, length, NULL /*p_structapp*/, 0, symbol->eci, debug_print); + segs[0].source = source; + segs[0].length = length; + segs[0].eci = 4; - ecc_level = LEVEL_M; + est_binlen = qr_calc_binlen_segs(15, mode, ddata, segs, seg_count, NULL /*p_structapp*/, 0, debug_print); + + ecc_level = QR_LEVEL_M; if (est_binlen > 3320) { strcpy(symbol->errtxt, "573: Input too long for selected symbol"); @@ -2812,12 +2871,12 @@ INTERNAL int upnqr(struct zint_symbol *symbol, unsigned char source[], int lengt fullstream = (unsigned char *) _alloca(qr_total_codewords[version - 1] + 1); #endif - (void) qr_binary(datastream, version, target_codewords, mode, jisdata, length, NULL /*p_structapp*/, 0 /*gs1*/, - symbol->eci, est_binlen, debug_print); + (void) qr_binary_segs(datastream, version, target_codewords, mode, ddata, segs, seg_count, NULL /*p_structapp*/, + 0 /*gs1*/, est_binlen, debug_print); #ifdef ZINT_TEST if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); #endif - add_ecc(fullstream, datastream, version, target_codewords, blocks, debug_print); + qr_add_ecc(fullstream, datastream, version, target_codewords, blocks, debug_print); size = qr_sizes[version - 1]; size_squared = size * size; @@ -2829,14 +2888,14 @@ INTERNAL int upnqr(struct zint_symbol *symbol, unsigned char source[], int lengt memset(grid, 0, size_squared); - setup_grid(grid, size, version); - populate_grid(grid, size, size, fullstream, qr_total_codewords[version - 1]); + qr_setup_grid(grid, size, version); + qr_populate_grid(grid, size, size, fullstream, qr_total_codewords[version - 1]); - add_version_info(grid, size, version); + qr_add_version_info(grid, size, version); - bitmask = apply_bitmask(grid, size, ecc_level, 0 /*user_mask*/, debug_print); + bitmask = qr_apply_bitmask(grid, size, ecc_level, 0 /*user_mask*/, debug_print); - add_format_info(grid, size, ecc_level, bitmask); + qr_add_format_info(grid, size, ecc_level, bitmask); symbol->width = size; symbol->rows = size; @@ -2855,7 +2914,7 @@ INTERNAL int upnqr(struct zint_symbol *symbol, unsigned char source[], int lengt return 0; } -static void setup_rmqr_grid(unsigned char *grid, const int h_size, const int v_size) { +static void rmqr_setup_grid(unsigned char *grid, const int h_size, const int v_size) { int i, j; char alignment[] = {0x1F, 0x11, 0x15, 0x11, 0x1F}; int h_version, finder_position; @@ -2883,7 +2942,7 @@ static void setup_rmqr_grid(unsigned char *grid, const int h_size, const int v_s } /* Add finder pattern */ - place_finder(grid, h_size, 0, 0); // This works because finder is always top left + qr_place_finder(grid, h_size, 0, 0); // This works because finder is always top left /* Add finder sub-pattern to bottom right */ for (i = 0; i < 5; i++) { @@ -2970,63 +3029,42 @@ static void setup_rmqr_grid(unsigned char *grid, const int h_size, const int v_s } /* rMQR according to 2018 draft standard */ -INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length) { - int warn_number = 0; +INTERNAL int rmqr(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { + int warn_number; int i, j, est_binlen; int ecc_level, autosize, version, max_cw, target_codewords, blocks, h_size, v_size; int gs1; - int full_multibyte; int footprint, best_footprint, format_data; unsigned int left_format_info, right_format_info; const int debug_print = symbol->debug & ZINT_DEBUG_PRINT; - const int eci_length = get_eci_length(symbol->eci, source, length); + const int eci_length_segs = get_eci_length_segs(segs, seg_count); #ifndef _MSC_VER - unsigned int jisdata[eci_length + 1]; - char mode[eci_length + 1]; + struct zint_seg local_segs[seg_count]; + unsigned int ddata[eci_length_segs]; + char mode[eci_length_segs]; #else + struct zint_seg *local_segs = (struct zint_seg *) _alloca(sizeof(struct zint_seg) * seg_count); + unsigned int *ddata = (unsigned int *) _alloca(sizeof(unsigned int) * eci_length_segs); + char *mode = (char *) _alloca(eci_length_segs); unsigned char *datastream; unsigned char *fullstream; unsigned char *grid; - unsigned int *jisdata = (unsigned int *) _alloca((eci_length + 1) * sizeof(unsigned int)); - char *mode = (char *) _alloca(eci_length + 1); #endif gs1 = ((symbol->input_mode & 0x07) == GS1_MODE); - /* If ZINT_FULL_MULTIBYTE use Kanji mode in DATA_MODE or for non-Shift JIS in UNICODE_MODE */ - full_multibyte = (symbol->option_3 & 0xFF) == ZINT_FULL_MULTIBYTE; - if ((symbol->input_mode & 0x07) == DATA_MODE) { - sjis_cpy(source, &length, jisdata, full_multibyte); - } else { - int done = 0; - if (symbol->eci != 20) { /* Unless ECI 20 (Shift JIS) */ - /* Try other encodings (ECI 0 defaults to ISO/IEC 8859-1) */ - int error_number = sjis_utf8_to_eci(symbol->eci, source, &length, jisdata, full_multibyte); - if (error_number == 0) { - done = 1; - } else if (symbol->eci) { - sprintf(symbol->errtxt, "564: Invalid character in input data for ECI %d", symbol->eci); - return error_number; - } - } - if (!done) { - /* Try Shift-JIS */ - int error_number = sjis_utf8(symbol, source, &length, jisdata); - if (error_number != 0) { - return error_number; - } - if (symbol->eci != 20) { - strcpy(symbol->errtxt, "544: Converted to Shift JIS but no ECI specified"); - warn_number = ZINT_WARN_NONCOMPLIANT; - } - } + segs_cpy(segs, seg_count, local_segs); + + warn_number = qr_prep_data(symbol, local_segs, seg_count, ddata); + if (warn_number >= ZINT_ERROR) { + return warn_number; } - est_binlen = getBinaryLength(RMQR_VERSION + 31, mode, jisdata, length, NULL /*p_structapp*/, gs1, symbol->eci, + est_binlen = qr_calc_binlen_segs(RMQR_VERSION + 31, mode, ddata, local_segs, seg_count, NULL /*p_structapp*/, gs1, debug_print); - ecc_level = LEVEL_M; + ecc_level = QR_LEVEL_M; max_cw = 152; if (symbol->option_1 == 1) { strcpy(symbol->errtxt, "576: Error correction level L not available in rMQR"); @@ -3039,7 +3077,7 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length } if (symbol->option_1 == 4) { - ecc_level = LEVEL_H; + ecc_level = QR_LEVEL_H; max_cw = 76; } @@ -3060,10 +3098,10 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length autosize = 31; best_footprint = rmqr_height[31] * rmqr_width[31]; for (version = 30; version >= 0; version--) { - est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, NULL /*p_structapp*/, gs1, - symbol->eci, debug_print); + est_binlen = qr_calc_binlen_segs(RMQR_VERSION + version, mode, ddata, local_segs, seg_count, + NULL /*p_structapp*/, gs1, debug_print); footprint = rmqr_height[version] * rmqr_width[version]; - if (ecc_level == LEVEL_M) { + if (ecc_level == QR_LEVEL_M) { if (8 * rmqr_data_codewords_M[version] >= est_binlen) { if (footprint < best_footprint) { autosize = version; @@ -3080,24 +3118,24 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length } } version = autosize; - est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, NULL /*p_structapp*/, gs1, - symbol->eci, debug_print); + est_binlen = qr_calc_binlen_segs(RMQR_VERSION + version, mode, ddata, local_segs, seg_count, + NULL /*p_structapp*/, gs1, debug_print); } if ((symbol->option_2 >= 1) && (symbol->option_2 <= 32)) { // User specified symbol size version = symbol->option_2 - 1; - est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, NULL /*p_structapp*/, gs1, - symbol->eci, debug_print); + est_binlen = qr_calc_binlen_segs(RMQR_VERSION + version, mode, ddata, local_segs, seg_count, + NULL /*p_structapp*/, gs1, debug_print); } if (symbol->option_2 >= 33) { // User has specified symbol height only version = rmqr_fixed_height_upper_bound[symbol->option_2 - 32]; for (i = version - 1; i > rmqr_fixed_height_upper_bound[symbol->option_2 - 33]; i--) { - est_binlen = getBinaryLength(RMQR_VERSION + i, mode, jisdata, length, NULL /*p_structapp*/, gs1, - symbol->eci, debug_print); - if (ecc_level == LEVEL_M) { + est_binlen = qr_calc_binlen_segs(RMQR_VERSION + i, mode, ddata, local_segs, seg_count, + NULL /*p_structapp*/, gs1, debug_print); + if (ecc_level == QR_LEVEL_M) { if (8 * rmqr_data_codewords_M[i] >= est_binlen) { version = i; } @@ -3107,18 +3145,18 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length } } } - est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, NULL /*p_structapp*/, gs1, - symbol->eci, debug_print); + est_binlen = qr_calc_binlen_segs(RMQR_VERSION + version, mode, ddata, local_segs, seg_count, + NULL /*p_structapp*/, gs1, debug_print); } if (symbol->option_1 == -1) { // Detect if there is enough free space to increase ECC level if (est_binlen < (rmqr_data_codewords_H[version] * 8)) { - ecc_level = LEVEL_H; + ecc_level = QR_LEVEL_H; } } - if (ecc_level == LEVEL_M) { + if (ecc_level == QR_LEVEL_M) { target_codewords = rmqr_data_codewords_M[version]; blocks = rmqr_blocks_M[version]; } else { @@ -3135,7 +3173,7 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length if (debug_print) { printf("Minimum codewords: %d\n", (est_binlen + 7) / 8); printf("Selected version: %d = R%dx%d-%c\n", - (version + 1), rmqr_height[version], rmqr_width[version], ecc_level_names[ecc_level - 1]); + (version + 1), rmqr_height[version], rmqr_width[version], qr_ecc_level_names[ecc_level - 1]); printf("Number of data codewords in symbol: %d\n", target_codewords); printf("Number of ECC blocks: %d\n", blocks); } @@ -3148,12 +3186,12 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length fullstream = (unsigned char *) _alloca(rmqr_total_codewords[version] + 1); #endif - (void) qr_binary(datastream, RMQR_VERSION + version, target_codewords, mode, jisdata, length, - NULL /*p_structapp*/, gs1, symbol->eci, est_binlen, debug_print); + (void) qr_binary_segs(datastream, RMQR_VERSION + version, target_codewords, mode, ddata, local_segs, seg_count, + NULL /*p_structapp*/, gs1, est_binlen, debug_print); #ifdef ZINT_TEST if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); #endif - add_ecc(fullstream, datastream, RMQR_VERSION + version, target_codewords, blocks, debug_print); + qr_add_ecc(fullstream, datastream, RMQR_VERSION + version, target_codewords, blocks, debug_print); h_size = rmqr_width[version]; v_size = rmqr_height[version]; @@ -3166,8 +3204,8 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length memset(grid, 0, h_size * v_size); - setup_rmqr_grid(grid, h_size, v_size); - populate_grid(grid, h_size, v_size, fullstream, rmqr_total_codewords[version]); + rmqr_setup_grid(grid, h_size, v_size); + qr_populate_grid(grid, h_size, v_size, fullstream, rmqr_total_codewords[version]); /* apply bitmask */ for (i = 0; i < v_size; i++) { @@ -3189,7 +3227,7 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length /* add format information */ format_data = version; - if (ecc_level == LEVEL_H) { + if (ecc_level == QR_LEVEL_H) { format_data += 32; } left_format_info = rmqr_format_info_left[format_data]; diff --git a/backend/qr.h b/backend/qr.h index 21fd42f7..3c88d0c8 100644 --- a/backend/qr.h +++ b/backend/qr.h @@ -1,7 +1,7 @@ /* qr.h Data for QR Code, Micro QR Code and rMQR libzint - the open source barcode library - Copyright (C) 2008 - 2021 Robin Stuart + Copyright (C) 2008-2022 Robin Stuart Copyright (C) 2006 Kentaro Fukuchi Redistribution and use in source and binary forms, with or without @@ -29,7 +29,9 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ + +#ifndef Z_QR_H +#define Z_QR_H /* From ISO/IEC 18004:2015 Table 5 Encoding/decoding table for Alphanumeric mode */ static const char qr_alphanumeric[59] = { @@ -40,37 +42,37 @@ static const char qr_alphanumeric[59] = { }; /* From ISO/IEC 18004:2015 Table 7 */ -static const unsigned short int qr_data_codewords_L[] = { +static const unsigned short qr_data_codewords_L[] = { 19, 34, 55, 80, 108, 136, 156, 194, 232, 274, 324, 370, 428, 461, 523, 589, 647, 721, 795, 861, 932, 1006, 1094, 1174, 1276, 1370, 1468, 1531, 1631, 1735, 1843, 1955, 2071, 2191, 2306, 2434, 2566, 2702, 2812, 2956 }; -static const unsigned short int qr_data_codewords_M[] = { +static const unsigned short qr_data_codewords_M[] = { 16, 28, 44, 64, 86, 108, 124, 154, 182, 216, 254, 290, 334, 365, 415, 453, 507, 563, 627, 669, 714, 782, 860, 914, 1000, 1062, 1128, 1193, 1267, 1373, 1455, 1541, 1631, 1725, 1812, 1914, 1992, 2102, 2216, 2334 }; -static const unsigned short int qr_data_codewords_Q[] = { +static const unsigned short qr_data_codewords_Q[] = { 13, 22, 34, 48, 62, 76, 88, 110, 132, 154, 180, 206, 244, 261, 295, 325, 367, 397, 445, 485, 512, 568, 614, 664, 718, 754, 808, 871, 911, 985, 1033, 1115, 1171, 1231, 1286, 1354, 1426, 1502, 1582, 1666 }; -static const unsigned short int qr_data_codewords_H[] = { +static const unsigned short qr_data_codewords_H[] = { 9, 16, 26, 36, 46, 60, 66, 86, 100, 122, 140, 158, 180, 197, 223, 253, 283, 313, 341, 385, 406, 442, 464, 514, 538, 596, 628, 661, 701, 745, 793, 845, 901, 961, 986, 1054, 1096, 1142, 1222, 1276 }; -static const unsigned short int qr_total_codewords[] = { +static const unsigned short qr_total_codewords[] = { 26, 44, 70, 100, 134, 172, 196, 242, 292, 346, 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085, 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185, 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706 }; -static const unsigned short int rmqr_height[] = { +static const unsigned short rmqr_height[] = { 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11, 11, @@ -79,7 +81,7 @@ static const unsigned short int rmqr_height[] = { 17, 17, 17, 17, 17 }; -static const unsigned short int rmqr_width[] = { +static const unsigned short rmqr_width[] = { 43, 59, 77, 99, 139, 43, 59, 77, 99, 139, 27, 43, 59, 77, 99, 139, @@ -88,7 +90,7 @@ static const unsigned short int rmqr_width[] = { 43, 59, 77, 99, 139 }; -static const unsigned short int rmqr_data_codewords_M[] = { +static const unsigned short rmqr_data_codewords_M[] = { 6, 12, 20, 28, 44, // R7x 12, 21, 31, 42, 63, // R9x 7, 19, 31, 43, 57, 84, // R11x @@ -97,7 +99,7 @@ static const unsigned short int rmqr_data_codewords_M[] = { 39, 56, 78, 100, 152 // R17x }; -static const unsigned short int rmqr_data_codewords_H[] = { +static const unsigned short rmqr_data_codewords_H[] = { 3, 7, 10, 14, 24, // R7x 7, 11, 17, 22, 33, // R9x 5, 11, 15, 23, 29, 42, // R11x @@ -106,11 +108,11 @@ static const unsigned short int rmqr_data_codewords_H[] = { 21, 28, 38, 56, 76 // R17x }; -static const short int rmqr_fixed_height_upper_bound[] = { +static const short rmqr_fixed_height_upper_bound[] = { -1, 4, 9, 15, 21, 26, 31 }; -static const unsigned short int rmqr_total_codewords[] = { +static const unsigned short rmqr_total_codewords[] = { 13, 21, 32, 44, 68, // R7x 21, 33, 49, 66, 99, // R9x 15, 31, 47, 67, 89, 132, // R11x @@ -120,7 +122,7 @@ static const unsigned short int rmqr_total_codewords[] = { }; -static const unsigned short int rmqr_numeric_cci[] = { +static const unsigned short rmqr_numeric_cci[] = { 4, 5, 6, 7, 7, 5, 6, 7, 7, 8, 4, 6, 7, 7, 8, 8, @@ -129,7 +131,7 @@ static const unsigned short int rmqr_numeric_cci[] = { 7, 8, 8, 8, 9 }; -static const unsigned short int rmqr_alphanum_cci[] = { +static const unsigned short rmqr_alphanum_cci[] = { 3, 5, 5, 6, 6, 5, 5, 6, 6, 7, 4, 5, 6, 6, 7, 7, @@ -138,7 +140,7 @@ static const unsigned short int rmqr_alphanum_cci[] = { 6, 7, 7, 8, 8 }; -static const unsigned short int rmqr_byte_cci[] = { +static const unsigned short rmqr_byte_cci[] = { 3, 4, 5, 5, 6, 4, 5, 5, 6, 6, 3, 5, 5, 6, 6, 7, @@ -147,7 +149,7 @@ static const unsigned short int rmqr_byte_cci[] = { 6, 6, 7, 7, 8 }; -static const unsigned short int rmqr_kanji_cci[] = { +static const unsigned short rmqr_kanji_cci[] = { 2, 3, 4, 5, 5, 3, 4, 5, 5, 6, 2, 4, 5, 5, 6, 6, @@ -194,7 +196,7 @@ static const char rmqr_blocks_H[] = { 2, 2, 3, 4, 6 // R17x }; -static const unsigned short int qr_sizes[] = { +static const unsigned short qr_sizes[] = { 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177 }; @@ -208,7 +210,7 @@ static const char qr_align_loopsize[] = { }; // Table E1 - Row/column coordinates of center module of alignment patterns -static const unsigned short int qr_table_e1[] = { +static const unsigned short qr_table_e1[] = { 6, 18, 0, 0, 0, 0, 0, 6, 22, 0, 0, 0, 0, 0, 6, 26, 0, 0, 0, 0, 0, @@ -251,7 +253,7 @@ static const unsigned short int qr_table_e1[] = { }; // Table D1 - Column coordinates of centre module of alignment patterns -static const unsigned short int rmqr_table_d1[] = { +static const unsigned short rmqr_table_d1[] = { 21, 0, 0, 0, 19, 39, 0, 0, 25, 51, 0, 0, @@ -302,3 +304,6 @@ static const unsigned int rmqr_format_info_right[] = { 0x129B9, 0x1369C, 0x14A08, 0x1552D, 0x16B67, 0x17442, 0x18D6A, 0x1924F, 0x1AC05, 0x1B320, 0x1CFB4, 0x1D091, 0x1EEDB, 0x1F1FE }; + +/* vim: set ts=4 sw=4 et : */ +#endif /* Z_QR_H */ diff --git a/backend/sjis.c b/backend/sjis.c index 1b0effe6..753363c3 100644 --- a/backend/sjis.c +++ b/backend/sjis.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2019-2021 Robin Stuart + Copyright (C) 2019-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ /* * Adapted from the GNU LIBICONV library and patched to make compatible with * https://www.unicode.org/Public/MAPPINGS/OBSOLETE/EASTASIA/JIS/SHIFTJIS.TXT @@ -1516,7 +1515,7 @@ INTERNAL int sjis_wctomb_zint(unsigned int *r, const unsigned int wc) { /* Convert UTF-8 string to Shift JIS and place in array of ints */ INTERNAL int sjis_utf8(struct zint_symbol *symbol, const unsigned char source[], int *p_length, - unsigned int *jisdata) { + unsigned int *ddata) { int error_number; unsigned int i, length; #ifndef _MSC_VER @@ -1531,7 +1530,7 @@ INTERNAL int sjis_utf8(struct zint_symbol *symbol, const unsigned char source[], } for (i = 0, length = *p_length; i < length; i++) { - if (!sjis_wctomb_zint(jisdata + i, utfdata[i])) { + if (!sjis_wctomb_zint(ddata + i, utfdata[i])) { strcpy(symbol->errtxt, "800: Invalid character in input data"); return ZINT_ERROR_INVALID_DATA; } @@ -1541,7 +1540,7 @@ INTERNAL int sjis_utf8(struct zint_symbol *symbol, const unsigned char source[], } /* Convert UTF-8 string to ECI and place in array of ints */ -INTERNAL int sjis_utf8_to_eci(const int eci, const unsigned char source[], int *p_length, unsigned int *jisdata, +INTERNAL int sjis_utf8_to_eci(const int eci, const unsigned char source[], int *p_length, unsigned int *ddata, const int full_multibyte) { if (is_eci_convertible(eci)) { @@ -1559,9 +1558,9 @@ INTERNAL int sjis_utf8_to_eci(const int eci, const unsigned char source[], int * return error_number; } - sjis_cpy(converted, p_length, jisdata, full_multibyte); + sjis_cpy(converted, p_length, ddata, full_multibyte); } else { - sjis_cpy(source, p_length, jisdata, full_multibyte); + sjis_cpy(source, p_length, ddata, full_multibyte); } return 0; @@ -1569,7 +1568,7 @@ INTERNAL int sjis_utf8_to_eci(const int eci, const unsigned char source[], int * /* If `full_multibyte` set, copy byte input stream to array of ints, putting double-bytes that match QR Kanji mode in * a single entry. If `full_multibyte` not set, do a straight copy */ -INTERNAL void sjis_cpy(const unsigned char source[], int *p_length, unsigned int *jisdata, const int full_multibyte) { +INTERNAL void sjis_cpy(const unsigned char source[], int *p_length, unsigned int *ddata, const int full_multibyte) { unsigned int i, j, jis, length; unsigned char c; @@ -1581,20 +1580,34 @@ INTERNAL void sjis_cpy(const unsigned char source[], int *p_length, unsigned int if ((jis >= 0x8140 && jis <= 0x9FFC) || (jis >= 0xE040 && jis <= 0xEBBF)) { /* This may or may not be valid Shift JIS, but don't care as long as it can be encoded in * QR Kanji mode */ - jisdata[j] = jis; + ddata[j] = jis; i++; } else { - jisdata[j] = c; + ddata[j] = c; } } else { - jisdata[j] = c; + ddata[j] = c; } } *p_length = j; } else { /* Straight copy */ for (i = 0, length = *p_length; i < length; i++) { - jisdata[i] = source[i]; + ddata[i] = source[i]; } } } + +/* Call `sjis_cpy()` for each segment */ +INTERNAL void sjis_cpy_segs(struct zint_seg segs[], const int seg_count, unsigned int *ddata, + const int full_multibyte) { + int i; + unsigned int *dd = ddata; + + for (i = 0; i < seg_count; i++) { + sjis_cpy(segs[i].source, &segs[i].length, dd, full_multibyte); + dd += segs[i].length; + } +} + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/sjis.h b/backend/sjis.h index 8eba69e7..2d6af812 100644 --- a/backend/sjis.h +++ b/backend/sjis.h @@ -1,7 +1,7 @@ /* sjis.h - Unicode to Shift JIS libzint - the open source barcode library - Copyright (C) 2009-2021 Robin Stuart + Copyright (C) 2009-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -28,10 +28,9 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ -#ifndef SJIS_H -#define SJIS_H +#ifndef Z_SJIS_H +#define Z_SJIS_H #ifdef __cplusplus extern "C" { @@ -39,13 +38,17 @@ extern "C" { INTERNAL int sjis_wctomb_zint(unsigned int *r, const unsigned int wc); INTERNAL int sjis_utf8(struct zint_symbol *symbol, const unsigned char source[], int *p_length, - unsigned int *jisdata); -INTERNAL int sjis_utf8_to_eci(const int eci, const unsigned char source[], int *p_length, unsigned int *jisdata, + unsigned int *ddata); +INTERNAL int sjis_utf8_to_eci(const int eci, const unsigned char source[], int *p_length, unsigned int *ddata, + const int full_multibyte); + +INTERNAL void sjis_cpy(const unsigned char source[], int *p_length, unsigned int *ddata, const int full_multibyte); +INTERNAL void sjis_cpy_segs(struct zint_seg segs[], const int seg_count, unsigned int *ddata, const int full_multibyte); -INTERNAL void sjis_cpy(const unsigned char source[], int *p_length, unsigned int *jisdata, const int full_multibyte); #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* SJIS_H */ +/* vim: set ts=4 sw=4 et : */ +#endif /* Z_SJIS_H */ diff --git a/backend/tests/test_2of5.c b/backend/tests/test_2of5.c index fa66e4f5..8351bed1 100644 --- a/backend/tests/test_2of5.c +++ b/backend/tests/test_2of5.c @@ -341,7 +341,7 @@ static void test_encode(int index, int generate, int debug) { assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, -1, debug)) { - ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf)); + ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -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, data[i].expected); diff --git a/backend/tests/test_auspost.c b/backend/tests/test_auspost.c index e0674aa1..e21a6029 100644 --- a/backend/tests/test_auspost.c +++ b/backend/tests/test_auspost.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2020 - 2021 Robin Stuart + Copyright (C) 2020-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "testcommon.h" @@ -318,7 +317,7 @@ static void test_encode(int index, int generate, int debug) { assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) { - ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -392,3 +391,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_aztec.c b/backend/tests/test_aztec.c index 851ceeda..83dfcfde 100644 --- a/backend/tests/test_aztec.c +++ b/backend/tests/test_aztec.c @@ -2431,7 +2431,7 @@ static void test_encode(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, -1, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, -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, data[i].expected); @@ -2459,6 +2459,290 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +static void test_encode_segs(int index, int generate, int debug) { + + struct item { + int input_mode; + int output_options; + int option_1; + int option_2; + struct zint_seg segs[3]; + int ret; + + int expected_rows; + int expected_width; + int bwipp_cmp; + char *comment; + char *expected; + }; + struct item data[] = { + /* 0*/ { UNICODE_MODE, -1, -1, -1, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 7 }, { TU(""), 0, 0 } }, 0, 15, 15, 1, "ISO/IEC 24778:2008 16.5 example", + "001111000011111" + "110111100100011" + "111100001000111" + "101111111111111" + "001100000001111" + "000101111101101" + "110101000101101" + "011101010101001" + "101101000101010" + "110101111101001" + "000100000001011" + "000111111111111" + "010001100010001" + "001010111001010" + "000001011100111" + }, + /* 1*/ { UNICODE_MODE, -1, -1, -1, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 15, 15, 1, "ISO/IEC 24778:2008 16.5 example auto-ECI", + "001111000011111" + "110111100100011" + "111100001000111" + "101111111111111" + "001100000001111" + "000101111101101" + "110101000101101" + "011101010101001" + "101101000101010" + "110101111101001" + "000100000001011" + "000111111111111" + "010001100010001" + "001010111001010" + "000001011100111" + }, + /* 2*/ { UNICODE_MODE, -1, -1, 2, { { TU("Ж"), -1, 7 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, 0, 19, 19, 1, "ISO/IEC 24778:2008 16.5 example inverted", + "0000011010000000000" + "0000001101101010000" + "0111000110100011110" + "0010011111100001110" + "0001110100110010000" + "0110111111111111110" + "0000010000000100011" + "1100110111110110000" + "0011110100010110101" + "1100010101010100001" + "1110010100010100000" + "1001010111110100000" + "1001010000000100011" + "0011011111111110001" + "0100001111100000111" + "1011111010011010111" + "1111010101011010101" + "1000001011111001010" + "0100000000011100111" + }, + /* 3*/ { UNICODE_MODE, -1, -1, 2, { { TU("Ж"), -1, 0 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 19, 19, 1, "ISO/IEC 24778:2008 16.5 example inverted auto-ECI", + "0000011010000000000" + "0000001101101010000" + "0111000110100011110" + "0010011111100001110" + "0001110100110010000" + "0110111111111111110" + "0000010000000100011" + "1100110111110110000" + "0011110100010110101" + "1100010101010100001" + "1110010100010100000" + "1001010111110100000" + "1001010000000100011" + "0011011111111110001" + "0100001111100000111" + "1011111010011010111" + "1111010101011010101" + "1000001011111001010" + "0100000000011100111" + }, + /* 4*/ { UNICODE_MODE, -1, -1, -1, { { TU("product:Google Pixel 4a - 128 GB of Storage - Black;price:$439.97"), -1, 3 }, { TU("品名:Google 谷歌 Pixel 4a -128 GB的存储空间-黑色;零售价:¥3149.79"), -1, 29 }, { TU("Produkt:Google Pixel 4a - 128 GB Speicher - Schwarz;Preis:444,90 €"), -1, 17 } }, 0, 49, 49, 0, "AIM ITS/04-023:2022 Annex A example; BWIPP different encodation (better)", + "0000110010100000001100011100010010010010100010101" + "0001100000010101011010010100011100000001000100010" + "0001110011110000000000101101100110101001100000000" + "0110001001100100100100110111000111101010011110100" + "0001011110100011010010001000111110010110111010111" + "0010010001101101100111010110111000001101001111101" + "0110001110110010010000111001100100011001100101001" + "0110001101010110010001010100001101001110000110000" + "1010101010101010101010101010101010101010101010101" + "0100110100001010010110010100111110010110001010010" + "1110111010111110101110101010011011000100100100010" + "1000000100001011101010010110010011101011000101001" + "0101101011110000011100001001000011010101101101111" + "0010001100010010110111110101101001011110000011010" + "0100000011001011111011111011111010001101100110000" + "1000010001011000100111100100010100101010001101101" + "0101110010010100010110101010010100011001111001011" + "1101110001010101111001110000100101000010001111000" + "0001110110000111111111111111111101110001111110000" + "0000010101001010011000000000001110111111001001000" + "0000010010100111111011111111101101100011110000110" + "1000010100010111101010000000101011000001010011101" + "1110011111100110111010111110101000110101100100011" + "0101100000101101001010100010101011101000001111110" + "1010101010101010101010101010101010101010101010101" + "1011101100001100011010100010101111011100011001000" + "0011111111100111101010111110101111011100111111001" + "1000100100011010001010000000101010000101001110110" + "0111000010011110111011111111101000101101110100000" + "0100100101000110001000000000001010101001001111100" + "0110011110001110101111111111111111101101110011101" + "0011011000010110000010110100110010001000001001100" + "0001100111010000001111001101101000000111100000011" + "0111100000100011110011100001000110110000011010011" + "0110011110111110100010011001001011111111101100100" + "0111111001101011000101000001010010110100001101000" + "1101000010001010010001101010001111110111101100110" + "1011110000000110111001010011000110001000000110110" + "0000010110110000101010001110111000011101101001001" + "1010010100110110000011000000110100110100000100001" + "1010101010101010101010101010101010101010101010101" + "0000100100100000000110100100000001001000011010110" + "1000101110101110011110001000100100110100111100001" + "0000110101111100011101100000001111001111010100000" + "0101000010011111110110101100010011010010101110100" + "0000100101011010101001110100111010000000001010011" + "0001001111111100100111011100111101001111101100011" + "1001101000110101111010100111100011111001000100101" + "0001001010011000000100101101100110101000100000000" + }, + /* 5*/ { DATA_MODE, -1, -1, -1, { { TU("\357"), 1, 0 }, { TU("\357"), 1, 7 }, { TU("\357"), 1, 0 } }, 0, 19, 19, 1, "Standard example + extra seg, data mode", + "1110011101010111000" + "1100010001011100011" + "1001110101000010110" + "0001000011101001111" + "0001110100111011000" + "1111111111111110101" + "1100110000000111011" + "0110010111110100111" + "1110110100010101011" + "1010010101010110001" + "0010010100010100111" + "0001110111110111010" + "0011110000000111100" + "0000011111111110001" + "0111001101000000011" + "0011000000111110111" + "1111111001101000010" + "0110001101100001010" + "0111100111100000010" + }, + /* 6*/ { UNICODE_MODE, -1, -1, -1, { { TU("12345678"), -1, 3 }, { TU("ABCDEFGH"), -1, 4 }, { TU("123456789"), -1, 5 } }, 0, 23, 23, 0, "Mode change between segs; BWIPP different encodation", + "00100011011101100111000" + "00101011010000010111111" + "00011001010101011010100" + "01011001100000101110000" + "00011000100010011101100" + "00110000100011111111000" + "01001111100101001111000" + "01000111111111111000110" + "01010111000000011000101" + "11010101011111011111000" + "11111101010001011100100" + "00100011010101011101010" + "01000001010001010001111" + "10111101011111010110010" + "10001001000000010111000" + "00001001111111111011111" + "10101100101001000010000" + "10110011100001111000110" + "11101000100001111011010" + "00010010100111001011100" + "11111111000010000100001" + "10101100001011010010000" + "10001000000000111000011" + }, + }; + int data_size = ARRAY_SIZE(data); + int i, j, seg_count, ret; + struct zint_symbol *symbol; + + char escaped[1024]; + 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 + + testStart("test_encode_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + testUtilSetSymbol(symbol, BARCODE_AZTEC, data[i].input_mode, -1 /*eci*/, + data[i].option_1, data[i].option_2, -1, data[i].output_options, NULL, 0, debug); + for (j = 0, seg_count = 0; j < 3 && data[i].segs[j].length; j++, seg_count++); + + ret = ZBarcode_Encode_Segs(symbol, data[i].segs, seg_count); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode_Segs ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + char escaped1[4096]; + char escaped2[4096]; + int length = data[i].segs[0].length == -1 ? (int) ustrlen(data[i].segs[0].source) : data[i].segs[0].length; + int length1 = data[i].segs[1].length == -1 ? (int) ustrlen(data[i].segs[1].source) : data[i].segs[1].length; + int length2 = data[i].segs[2].length == -1 ? (int) ustrlen(data[i].segs[2].source) : data[i].segs[2].length; + printf(" /*%3d*/ { %s, %s, %d, %d, { { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d } }, %s, %d, %d, %d, \"%s\",\n", + i, testUtilInputModeName(data[i].input_mode), testUtilOutputOptionsName(data[i].output_options), + data[i].option_1, data[i].option_2, + testUtilEscape((const char *) data[i].segs[0].source, length, escaped, sizeof(escaped)), data[i].segs[0].length, data[i].segs[0].eci, + testUtilEscape((const char *) data[i].segs[1].source, length1, escaped1, sizeof(escaped1)), data[i].segs[1].length, data[i].segs[1].eci, + testUtilEscape((const char *) data[i].segs[2].source, length2, escaped2, sizeof(escaped2)), data[i].segs[2].length, data[i].segs[2].eci, + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].bwipp_cmp, data[i].comment); + testUtilModulesPrint(symbol, " ", "\n"); + printf(" },\n"); + } else { + if (ret < ZINT_ERROR) { + int width, row; + + 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); + + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d\n", i, ret, width, row); + + if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, data[i].option_2, -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 { + ret = testUtilBwippSegs(i, symbol, data[i].option_1, data[i].option_2, -1, 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); + 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, data[i].expected); + } + } + if (do_zxingcpp && testUtilCanZXingCPP(i, symbol, (const char *) data[i].segs[0].source, data[i].segs[0].length, debug)) { + if (data[i].input_mode == DATA_MODE) { + if (debug & ZINT_DEBUG_TEST_PRINT) { + printf("i:%d multiple segments in DATA_MODE not currently supported for ZXing-C++ testing (%s)\n", + i, testUtilBarcodeName(symbol->symbology)); + } + } else { + int cmp_len, ret_len; + char modules_dump[22801 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilZXingCPP(i, symbol, (const char *) data[i].segs[0].source, data[i].segs[0].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 = testUtilZXingCPPCmpSegs(symbol, cmp_msg, cmp_buf, cmp_len, data[i].segs, seg_count, + NULL /*primary*/, escaped, &ret_len); + assert_zero(ret, "i:%d %s testUtilZXingCPPCmpSegs %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); + } + + testFinish(); +} + // #181 Nico Gunkel OSS-Fuzz static void test_fuzz(int index, int debug) { @@ -3011,6 +3295,7 @@ int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ { "test_options", test_options, 1, 0, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_encode_segs", test_encode_segs, 1, 1, 1 }, { "test_fuzz", test_fuzz, 1, 0, 1 }, { "test_perf", test_perf, 1, 0, 1 }, }; diff --git a/backend/tests/test_channel.c b/backend/tests/test_channel.c index 917abc85..0a41f439 100644 --- a/backend/tests/test_channel.c +++ b/backend/tests/test_channel.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2019 - 2021 Robin Stuart + Copyright (C) 2019-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "testcommon.h" @@ -448,7 +447,7 @@ static void test_encode(int index, int generate, int debug) { assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, -1, debug)) { - ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -507,3 +506,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_codablock.c b/backend/tests/test_codablock.c index 2cf653ee..2a88d5a5 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 - 2021 Robin Stuart + Copyright (C) 2019-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "testcommon.h" @@ -497,7 +496,7 @@ static void test_encode(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -567,3 +566,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_code.c b/backend/tests/test_code.c index d7fe073a..0c323f54 100644 --- a/backend/tests/test_code.c +++ b/backend/tests/test_code.c @@ -456,7 +456,7 @@ static void test_encode(int index, int generate, int debug) { assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, -1, debug)) { - ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf)); + ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -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, data[i].expected); diff --git a/backend/tests/test_code1.c b/backend/tests/test_code1.c index f315436c..d13285ce 100644 --- a/backend/tests/test_code1.c +++ b/backend/tests/test_code1.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2020 - 2021 Robin Stuart + Copyright (C) 2020-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "testcommon.h" @@ -74,112 +73,118 @@ static void test_large(int index, int debug) { /* 25*/ { -1, 1, { 0, 0, "" }, "A", 14, ZINT_ERROR_TOO_LONG, -1, -1 }, /* 26*/ { 3, 1, { 0, 0, "" }, "A", 4, 0, 16, 18 }, /* With ECI */ /* 27*/ { 3, 1, { 0, 0, "" }, "A", 5, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 26*/ { -1, 1, { 1, 2, "" }, "A", 10, 0, 16, 18 }, /* With Structured Append */ - /* 27*/ { -1, 1, { 1, 2, "" }, "A", 11, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 28*/ { 3, 1, { 1, 2, "" }, "A", 2, 0, 16, 18 }, /* With ECI and Structured Append 1st symbol */ - /* 29*/ { 3, 1, { 1, 2, "" }, "A", 3, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 30*/ { 3, 1, { 2, 2, "" }, "A", 4, 0, 16, 18 }, /* With ECI and Structured Append subsequent symbol */ - /* 31*/ { 3, 1, { 2, 2, "" }, "A", 5, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 32*/ { -1, 1, { 0, 0, "" }, "\001", 10, 0, 16, 18 }, - /* 33*/ { -1, 1, { 0, 0, "" }, "\001", 11, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 34*/ { -1, 1, { 0, 0, "" }, "\200", 8, 0, 16, 18 }, - /* 35*/ { -1, 1, { 0, 0, "" }, "\200", 9, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 36*/ { -1, 2, { 0, 0, "" }, "1", 44, 0, 22, 22 }, /* Version B */ - /* 37*/ { -1, 2, { 0, 0, "" }, "1", 45, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 38*/ { -1, 2, { 0, 0, "" }, "A", 27, 0, 22, 22 }, - /* 39*/ { -1, 2, { 0, 0, "" }, "A", 28, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 40*/ { -1, 2, { 0, 0, "" }, "A", 26, 0, 22, 22 }, - /* 41*/ { -1, 2, { 0, 0, "" }, "\001", 19, 0, 22, 22 }, - /* 42*/ { -1, 2, { 0, 0, "" }, "\001", 20, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 43*/ { -1, 2, { 0, 0, "" }, "\200", 17, 0, 22, 22 }, - /* 44*/ { -1, 2, { 0, 0, "" }, "\200", 18, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 45*/ { -1, 3, { 0, 0, "" }, "1", 104, 0, 28, 32 }, /* Version C */ - /* 46*/ { -1, 3, { 0, 0, "" }, "1", 105, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 47*/ { -1, 3, { 0, 0, "" }, "A", 64, 0, 28, 32 }, - /* 48*/ { -1, 3, { 0, 0, "" }, "A", 65, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 49*/ { -1, 3, { 0, 0, "" }, "\001", 44, 0, 28, 32 }, - /* 50*/ { -1, 3, { 0, 0, "" }, "\001", 45, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 51*/ { -1, 3, { 0, 0, "" }, "\200", 42, 0, 28, 32 }, - /* 52*/ { -1, 3, { 0, 0, "" }, "\200", 43, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 53*/ { -1, 4, { 0, 0, "" }, "1", 217, 0, 40, 42 }, /* Version D */ - /* 54*/ { -1, 4, { 0, 0, "" }, "1", 218, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 55*/ { -1, 4, { 0, 0, "" }, "A", 135, 0, 40, 42 }, - /* 56*/ { -1, 4, { 0, 0, "" }, "A", 136, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 57*/ { -1, 4, { 0, 0, "" }, "\001", 91, 0, 40, 42 }, - /* 58*/ { -1, 4, { 0, 0, "" }, "\001", 92, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 59*/ { -1, 4, { 0, 0, "" }, "\200", 89, 0, 40, 42 }, - /* 60*/ { -1, 4, { 0, 0, "" }, "\200", 90, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 61*/ { -1, 5, { 0, 0, "" }, "1", 435, 0, 52, 54 }, /* Version E (note 435 multiple of 3) */ - /* 62*/ { -1, 5, { 0, 0, "" }, "1", 436, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 63*/ { -1, 5, { 0, 0, "" }, "1", 434, ZINT_ERROR_TOO_LONG, -1, -1 }, /* NOTE: a quirk of decimal end-of-data processing is existence of "lower maxs" if digits are not a multiple of 3 */ - /* 64*/ { -1, 5, { 0, 0, "" }, "1", 433, 0, 52, 54 }, - /* 65*/ { -1, 5, { 0, 0, "" }, "A", 271, 0, 52, 54 }, - /* 66*/ { -1, 5, { 0, 0, "" }, "A", 272, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 67*/ { -1, 5, { 0, 0, "" }, "\001", 182, 0, 52, 54 }, - /* 68*/ { -1, 5, { 0, 0, "" }, "\001", 183, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 69*/ { -1, 5, { 0, 0, "" }, "\200", 180, 0, 52, 54 }, - /* 70*/ { -1, 5, { 0, 0, "" }, "\200", 181, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 71*/ { -1, 6, { 0, 0, "" }, "1", 886, 0, 70, 76 }, /* Version F */ - /* 72*/ { -1, 6, { 0, 0, "" }, "1", 887, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 73*/ { -1, 6, { 0, 0, "" }, "A", 553, 0, 70, 76 }, - /* 74*/ { -1, 6, { 0, 0, "" }, "A", 554, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 75*/ { -1, 6, { 0, 0, "" }, "\001", 370, 0, 70, 76 }, - /* 76*/ { -1, 6, { 0, 0, "" }, "\001", 371, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 77*/ { -1, 6, { 0, 0, "" }, "\200", 368, 0, 70, 76 }, - /* 78*/ { -1, 6, { 0, 0, "" }, "\200", 369, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 79*/ { -1, 7, { 0, 0, "" }, "1", 1755, 0, 104, 98 }, /* Version G (note 1755 multiple of 3) */ - /* 80*/ { -1, 7, { 0, 0, "" }, "1", 1756, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 81*/ { -1, 7, { 0, 0, "" }, "1", 1754, ZINT_ERROR_TOO_LONG, -1, -1 }, /* NOTE: a quirk of decimal end-of-data processing is existence of "lower maxs" if digits are not a multiple of 3 */ - /* 82*/ { -1, 7, { 0, 0, "" }, "1", 1753, 0, 104, 98 }, - /* 83*/ { -1, 7, { 0, 0, "" }, "A", 1096, 0, 104, 98 }, - /* 84*/ { -1, 7, { 0, 0, "" }, "A", 1097, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 85*/ { -1, 7, { 0, 0, "" }, "\001", 732, 0, 104, 98 }, - /* 86*/ { -1, 7, { 0, 0, "" }, "\001", 733, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 87*/ { -1, 7, { 0, 0, "" }, "\200", 730, 0, 104, 98 }, - /* 88*/ { -1, 7, { 0, 0, "" }, "\200", 731, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 89*/ { -1, 8, { 0, 0, "" }, "1", 3550, 0, 148, 134 }, /* Version H */ - /* 90*/ { -1, 8, { 0, 0, "" }, "1", 3551, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 91*/ { -1, 8, { 0, 0, "" }, "A", 2218, 0, 148, 134 }, - /* 92*/ { -1, 8, { 0, 0, "" }, "A", 2219, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 93*/ { -1, 8, { 0, 0, "" }, "\001", 1480, 0, 148, 134 }, - /* 94*/ { -1, 8, { 0, 0, "" }, "\001", 1481, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 95*/ { -1, 8, { 0, 0, "" }, "\200", 1478, 0, 148, 134 }, - /* 96*/ { -1, 8, { 0, 0, "" }, "\200", 1479, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 97*/ { -1, 9, { 0, 0, "" }, "1", 6, 0, 8, 11 }, /* Version S-10 */ - /* 98*/ { -1, 9, { 0, 0, "" }, "1", 7, 0, 8, 21 }, /* -> S-20 */ - /* 99*/ { -1, 9, { 0, 0, "" }, "1", 12, 0, 8, 21 }, /* Version S-20 */ - /*100*/ { -1, 9, { 0, 0, "" }, "1", 13, 0, 8, 31 }, /* -> S-30 */ - /*101*/ { -1, 9, { 0, 0, "" }, "1", 18, 0, 8, 31 }, /* Version S-30 */ - /*102*/ { -1, 9, { 0, 0, "" }, "1", 19, ZINT_ERROR_TOO_LONG, -1, -1 }, - /*103*/ { -1, 9, { 0, 0, "" }, "1", 17, 0, 8, 31 }, - /*104*/ { -1, 10, { 0, 0, "" }, "1", 22, 0, 16, 17 }, /* Version T-16 */ - /*105*/ { -1, 10, { 0, 0, "" }, "1", 23, 0, 16, 33 }, /* -> T-32 */ - /*106*/ { -1, 10, { 0, 0, "" }, "A", 13, 0, 16, 17 }, - /*107*/ { -1, 10, { 0, 0, "" }, "A", 14, 0, 16, 33 }, /* -> T-32 */ - /*108*/ { -1, 10, { 0, 0, "" }, "\001", 10, 0, 16, 17 }, - /*109*/ { -1, 10, { 0, 0, "" }, "\001", 11, 0, 16, 33 }, /* -> T-32 */ - /*110*/ { -1, 10, { 0, 0, "" }, "\200", 8, 0, 16, 17 }, - /*111*/ { -1, 10, { 0, 0, "" }, "\200", 9, 0, 16, 33 }, /* -> T-32 */ - /*112*/ { -1, 10, { 0, 0, "" }, "1", 56, 0, 16, 33 }, /* Version T-32 */ - /*113*/ { -1, 10, { 0, 0, "" }, "1", 57, 0, 16, 49 }, /* -> T-48 */ - /*114*/ { -1, 10, { 0, 0, "" }, "A", 34, 0, 16, 33 }, - /*115*/ { -1, 10, { 0, 0, "" }, "A", 35, 0, 16, 49 }, /* -> T-48 */ - /*116*/ { -1, 10, { 0, 0, "" }, "\001", 24, 0, 16, 33 }, - /*117*/ { -1, 10, { 0, 0, "" }, "\001", 25, 0, 16, 49 }, /* -> T-48 */ - /*118*/ { -1, 10, { 0, 0, "" }, "\200", 22, 0, 16, 33 }, - /*119*/ { -1, 10, { 0, 0, "" }, "\200", 23, 0, 16, 49 }, /* -> T-48 */ - /*120*/ { -1, 10, { 0, 0, "" }, "1", 90, 0, 16, 49 }, /* Version T-48 (note 90 multiple of 3) */ - /*121*/ { -1, 10, { 0, 0, "" }, "1", 91, ZINT_ERROR_TOO_LONG, -1, -1 }, - /*122*/ { -1, 10, { 0, 0, "" }, "1", 89, ZINT_ERROR_TOO_LONG, -1, -1 }, /* NOTE: a quirk of decimal end-of-data processing is existence of "lower maxs" if digits are not a multiple of 3 */ - /*123*/ { -1, 10, { 0, 0, "" }, "1", 88, 0, 16, 49 }, - /*124*/ { -1, 10, { 0, 0, "" }, "A", 55, 0, 16, 49 }, - /*125*/ { -1, 10, { 0, 0, "" }, "A", 56, ZINT_ERROR_TOO_LONG, -1, -1 }, - /*126*/ { -1, 10, { 0, 0, "" }, "A", 90, ZINT_ERROR_TOO_LONG, -1, -1 }, - /*127*/ { -1, 10, { 0, 0, "" }, "\001", 38, 0, 16, 49 }, - /*128*/ { -1, 10, { 0, 0, "" }, "\001", 39, ZINT_ERROR_TOO_LONG, -1, -1 }, - /*129*/ { -1, 10, { 0, 0, "" }, "\001", 90, ZINT_ERROR_TOO_LONG, -1, -1 }, - /*130*/ { -1, 10, { 0, 0, "" }, "\200", 36, 0, 16, 49 }, - /*131*/ { -1, 10, { 0, 0, "" }, "\200", 37, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 28*/ { -1, 1, { 1, 2, "" }, "A", 10, 0, 16, 18 }, /* With Structured Append */ + /* 29*/ { -1, 1, { 1, 2, "" }, "A", 11, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 30*/ { 3, 1, { 1, 2, "" }, "A", 2, 0, 16, 18 }, /* With ECI and Structured Append 1st symbol */ + /* 31*/ { 3, 1, { 1, 2, "" }, "A", 3, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 32*/ { 3, 1, { 2, 2, "" }, "A", 4, 0, 16, 18 }, /* With ECI and Structured Append subsequent symbol */ + /* 33*/ { 3, 1, { 2, 2, "" }, "A", 5, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 34*/ { -1, 1, { 0, 0, "" }, "\001", 10, 0, 16, 18 }, + /* 35*/ { -1, 1, { 0, 0, "" }, "\001", 11, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 36*/ { -1, 1, { 0, 0, "" }, "\200", 8, 0, 16, 18 }, + /* 37*/ { -1, 1, { 0, 0, "" }, "\200", 9, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 38*/ { -1, 2, { 0, 0, "" }, "1", 44, 0, 22, 22 }, /* Version B */ + /* 39*/ { -1, 2, { 0, 0, "" }, "1", 45, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 40*/ { -1, 2, { 0, 0, "" }, "A", 27, 0, 22, 22 }, + /* 41*/ { -1, 2, { 0, 0, "" }, "A", 28, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 42*/ { -1, 2, { 0, 0, "" }, "A", 26, 0, 22, 22 }, + /* 43*/ { -1, 2, { 0, 0, "" }, "\001", 19, 0, 22, 22 }, + /* 44*/ { -1, 2, { 0, 0, "" }, "\001", 20, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 45*/ { -1, 2, { 0, 0, "" }, "\200", 17, 0, 22, 22 }, + /* 46*/ { -1, 2, { 0, 0, "" }, "\200", 18, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 47*/ { -1, 3, { 0, 0, "" }, "1", 104, 0, 28, 32 }, /* Version C */ + /* 48*/ { -1, 3, { 0, 0, "" }, "1", 105, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 49*/ { -1, 3, { 0, 0, "" }, "A", 64, 0, 28, 32 }, + /* 50*/ { -1, 3, { 0, 0, "" }, "A", 65, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 51*/ { -1, 3, { 0, 0, "" }, "\001", 44, 0, 28, 32 }, + /* 52*/ { -1, 3, { 0, 0, "" }, "\001", 45, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 53*/ { -1, 3, { 0, 0, "" }, "\200", 42, 0, 28, 32 }, + /* 54*/ { -1, 3, { 0, 0, "" }, "\200", 43, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 55*/ { -1, 4, { 0, 0, "" }, "1", 217, 0, 40, 42 }, /* Version D */ + /* 56*/ { -1, 4, { 0, 0, "" }, "1", 218, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 57*/ { -1, 4, { 0, 0, "" }, "A", 135, 0, 40, 42 }, + /* 58*/ { -1, 4, { 0, 0, "" }, "A", 136, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 59*/ { -1, 4, { 0, 0, "" }, "\001", 91, 0, 40, 42 }, + /* 60*/ { -1, 4, { 0, 0, "" }, "\001", 92, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 61*/ { -1, 4, { 0, 0, "" }, "\200", 89, 0, 40, 42 }, + /* 62*/ { -1, 4, { 0, 0, "" }, "\200", 90, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 63*/ { -1, 5, { 0, 0, "" }, "1", 435, 0, 52, 54 }, /* Version E (note 435 multiple of 3) */ + /* 64*/ { -1, 5, { 0, 0, "" }, "1", 436, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 65*/ { -1, 5, { 0, 0, "" }, "1", 434, ZINT_ERROR_TOO_LONG, -1, -1 }, /* NOTE: a quirk of decimal end-of-data processing is existence of "lower maxs" if digits are not a multiple of 3 */ + /* 66*/ { -1, 5, { 0, 0, "" }, "1", 433, 0, 52, 54 }, + /* 67*/ { -1, 5, { 0, 0, "" }, "A", 271, 0, 52, 54 }, + /* 68*/ { -1, 5, { 0, 0, "" }, "A", 272, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 69*/ { -1, 5, { 0, 0, "" }, "\001", 182, 0, 52, 54 }, + /* 70*/ { -1, 5, { 0, 0, "" }, "\001", 183, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 71*/ { -1, 5, { 0, 0, "" }, "\200", 180, 0, 52, 54 }, + /* 72*/ { -1, 5, { 0, 0, "" }, "\200", 181, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 73*/ { -1, 6, { 0, 0, "" }, "1", 886, 0, 70, 76 }, /* Version F */ + /* 74*/ { -1, 6, { 0, 0, "" }, "1", 887, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 75*/ { -1, 6, { 0, 0, "" }, "A", 553, 0, 70, 76 }, + /* 76*/ { -1, 6, { 0, 0, "" }, "A", 554, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 77*/ { -1, 6, { 0, 0, "" }, "\001", 370, 0, 70, 76 }, + /* 78*/ { -1, 6, { 0, 0, "" }, "\001", 371, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 79*/ { -1, 6, { 0, 0, "" }, "\200", 368, 0, 70, 76 }, + /* 80*/ { -1, 6, { 0, 0, "" }, "\200", 369, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 81*/ { -1, 7, { 0, 0, "" }, "1", 1755, 0, 104, 98 }, /* Version G (note 1755 multiple of 3) */ + /* 82*/ { -1, 7, { 0, 0, "" }, "1", 1756, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 83*/ { -1, 7, { 0, 0, "" }, "1", 1754, ZINT_ERROR_TOO_LONG, -1, -1 }, /* NOTE: a quirk of decimal end-of-data processing is existence of "lower maxs" if digits are not a multiple of 3 */ + /* 84*/ { -1, 7, { 0, 0, "" }, "1", 1753, 0, 104, 98 }, + /* 85*/ { -1, 7, { 0, 0, "" }, "A", 1096, 0, 104, 98 }, + /* 86*/ { -1, 7, { 0, 0, "" }, "A", 1097, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 87*/ { -1, 7, { 0, 0, "" }, "\001", 732, 0, 104, 98 }, + /* 88*/ { -1, 7, { 0, 0, "" }, "\001", 733, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 89*/ { -1, 7, { 0, 0, "" }, "\200", 730, 0, 104, 98 }, + /* 90*/ { -1, 7, { 0, 0, "" }, "\200", 731, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 91*/ { -1, 8, { 0, 0, "" }, "1", 3550, 0, 148, 134 }, /* Version H */ + /* 92*/ { -1, 8, { 0, 0, "" }, "1", 3551, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 93*/ { -1, 8, { 0, 0, "" }, "A", 2218, 0, 148, 134 }, + /* 94*/ { -1, 8, { 0, 0, "" }, "A", 2219, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 95*/ { -1, 8, { 0, 0, "" }, "\001", 1480, 0, 148, 134 }, + /* 96*/ { -1, 8, { 0, 0, "" }, "\001", 1481, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 97*/ { -1, 8, { 0, 0, "" }, "\200", 1478, 0, 148, 134 }, + /* 98*/ { -1, 8, { 0, 0, "" }, "\200", 1479, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 99*/ { -1, 9, { 0, 0, "" }, "1", 6, 0, 8, 11 }, /* Version S-10 */ + /*100*/ { -1, 9, { 0, 0, "" }, "1", 7, 0, 8, 21 }, /* -> S-20 */ + /*101*/ { -1, 9, { 0, 0, "" }, "1", 12, 0, 8, 21 }, /* Version S-20 */ + /*102*/ { -1, 9, { 0, 0, "" }, "1", 13, 0, 8, 31 }, /* -> S-30 */ + /*103*/ { -1, 9, { 0, 0, "" }, "1", 18, 0, 8, 31 }, /* Version S-30 */ + /*104*/ { -1, 9, { 0, 0, "" }, "1", 19, ZINT_ERROR_TOO_LONG, -1, -1 }, + /*105*/ { -1, 9, { 0, 0, "" }, "1", 17, 0, 8, 31 }, + /*106*/ { -1, 10, { 0, 0, "" }, "1", 22, 0, 16, 17 }, /* Version T-16 */ + /*107*/ { -1, 10, { 0, 0, "" }, "1", 23, 0, 16, 33 }, /* -> T-32 */ + /*108*/ { -1, 10, { 0, 0, "" }, "A", 13, 0, 16, 17 }, + /*109*/ { -1, 10, { 0, 0, "" }, "A", 14, 0, 16, 33 }, /* -> T-32 */ + /*110*/ { -1, 10, { 0, 0, "" }, "\001", 10, 0, 16, 17 }, + /*111*/ { -1, 10, { 0, 0, "" }, "\001", 11, 0, 16, 33 }, /* -> T-32 */ + /*112*/ { -1, 10, { 0, 0, "" }, "\200", 8, 0, 16, 17 }, + /*113*/ { -1, 10, { 0, 0, "" }, "\200", 9, 0, 16, 33 }, /* -> T-32 */ + /*114*/ { -1, 10, { 0, 0, "" }, "1", 56, 0, 16, 33 }, /* Version T-32 */ + /*115*/ { -1, 10, { 0, 0, "" }, "1", 57, 0, 16, 49 }, /* -> T-48 */ + /*116*/ { -1, 10, { 0, 0, "" }, "A", 34, 0, 16, 33 }, + /*117*/ { -1, 10, { 0, 0, "" }, "A", 35, 0, 16, 49 }, /* -> T-48 */ + /*118*/ { -1, 10, { 0, 0, "" }, "\001", 24, 0, 16, 33 }, + /*119*/ { -1, 10, { 0, 0, "" }, "\001", 25, 0, 16, 49 }, /* -> T-48 */ + /*120*/ { -1, 10, { 0, 0, "" }, "\200", 22, 0, 16, 33 }, + /*121*/ { -1, 10, { 0, 0, "" }, "\200", 23, 0, 16, 49 }, /* -> T-48 */ + /*122*/ { -1, 10, { 0, 0, "" }, "1", 90, 0, 16, 49 }, /* Version T-48 (note 90 multiple of 3) */ + /*123*/ { -1, 10, { 0, 0, "" }, "1", 91, ZINT_ERROR_TOO_LONG, -1, -1 }, + /*124*/ { -1, 10, { 0, 0, "" }, "1", 89, ZINT_ERROR_TOO_LONG, -1, -1 }, /* NOTE: a quirk of decimal end-of-data processing is existence of "lower maxs" if digits are not a multiple of 3 */ + /*125*/ { -1, 10, { 0, 0, "" }, "1", 88, 0, 16, 49 }, + /*126*/ { -1, 10, { 0, 0, "" }, "A", 55, 0, 16, 49 }, + /*127*/ { -1, 10, { 0, 0, "" }, "A", 56, ZINT_ERROR_TOO_LONG, -1, -1 }, + /*128*/ { -1, 10, { 0, 0, "" }, "A", 90, ZINT_ERROR_TOO_LONG, -1, -1 }, + /*129*/ { -1, 10, { 0, 0, "" }, "\001", 38, 0, 16, 49 }, + /*130*/ { -1, 10, { 0, 0, "" }, "\001", 39, ZINT_ERROR_TOO_LONG, -1, -1 }, + /*131*/ { -1, 10, { 0, 0, "" }, "\001", 90, ZINT_ERROR_TOO_LONG, -1, -1 }, + /*132*/ { -1, 10, { 0, 0, "" }, "\\", 38, 0, 16, 49 }, + /*133*/ { -1, 10, { 0, 0, "" }, "\\", 39, ZINT_ERROR_TOO_LONG, -1, -1 }, + /*134*/ { -1, 10, { 0, 0, "" }, "\200", 36, 0, 16, 49 }, + /*135*/ { -1, 10, { 0, 0, "" }, "\200", 37, ZINT_ERROR_TOO_LONG, -1, -1 }, + /*136*/ { 3, 10, { 0, 0, "" }, "A", 46, 0, 16, 49 }, /* Version T-48 with ECI (9 less as PAD escape char + "\123456") */ + /*137*/ { 3, 10, { 0, 0, "" }, "A", 47, ZINT_ERROR_TOO_LONG, -1, -1 }, + /*138*/ { 3, 10, { 0, 0, "" }, "\001", 32, 0, 16, 49 }, + /*139*/ { 3, 10, { 0, 0, "" }, "\001", 33, ZINT_ERROR_TOO_LONG, -1, -1 }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -2927,7 +2932,7 @@ static void test_encode(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -2944,6 +2949,405 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +static void test_encode_segs(int index, int generate, int debug) { + + struct item { + int input_mode; + int option_2; + struct zint_structapp structapp; + struct zint_seg segs[3]; + int ret; + + int expected_rows; + int expected_width; + int bwipp_cmp; + char *comment; + char *expected; + }; + // Figure examples AIM USS Code One (USSCO) Revision March 3, 2000 + struct item data[] = { + /* 0*/ { UNICODE_MODE, -1, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 7 }, { TU(""), 0, 0 } }, 0, 16, 18, 1, "Standard example", + "100011010111100011" + "000110110110110111" + "010110100010001000" + "110110001000101001" + "111010001111111011" + "000010000000100000" + "111111111111111111" + "000000000000000000" + "011111111111111110" + "010000000000000010" + "011111111111111110" + "101101111011100110" + "100001001111100110" + "010110111000101011" + "001010010011101001" + "010100101110110001" + }, + /* 1*/ { UNICODE_MODE, -1, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 16, 18, 1, "Standard example auto-ECI", + "100011010111100011" + "000110110110110111" + "010110100010001000" + "110110001000101001" + "111010001111111011" + "000010000000100000" + "111111111111111111" + "000000000000000000" + "011111111111111110" + "010000000000000010" + "011111111111111110" + "101101111011100110" + "100001001111100110" + "010110111000101011" + "001010010011101001" + "010100101110110001" + }, + /* 2*/ { UNICODE_MODE, -1, { 0, 0, "" }, { { TU("Ж"), -1, 7 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, 0, 22, 22, 1, "Standard example inverted", + "1000110101010110001000" + "0001101101110100100010" + "1000101110001101011000" + "1001101011011111010010" + "1000101000111000111000" + "0010100101101101110001" + "1000101000100010001101" + "0000100000000000100000" + "1111111111111111111111" + "0000000000000000000000" + "0111111111111111111110" + "0100000000000000000010" + "0111111111111111111110" + "0100000000000000000010" + "0111111111111111111110" + "0001000100010001101111" + "1010110111011111100100" + "1100011010110110101000" + "1111001110101001101101" + "1011101010111001100100" + "0010011101100011101011" + "0011010111000001111101" + }, + /* 3*/ { UNICODE_MODE, -1, { 0, 0, "" }, { { TU("Ж"), -1, 0 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 22, 22, 1, "Standard example inverted auto-ECI", + "1000110101010110001000" + "0001101101110100100010" + "1000101110001101011000" + "1001101011011111010010" + "1000101000111000111000" + "0010100101101101110001" + "1000101000100010001101" + "0000100000000000100000" + "1111111111111111111111" + "0000000000000000000000" + "0111111111111111111110" + "0100000000000000000010" + "0111111111111111111110" + "0100000000000000000010" + "0111111111111111111110" + "0001000100010001101111" + "1010110111011111100100" + "1100011010110110101000" + "1111001110101001101101" + "1011101010111001100100" + "0010011101100011101011" + "0011010111000001111101" + }, + /* 4*/ { UNICODE_MODE, -1, { 0, 0, "" }, { { TU("product:Google Pixel 4a - 128 GB of Storage - Black;price:$439.97"), -1, 3 }, { TU("品名:Google 谷歌 Pixel 4a -128 GB的存储空间-黑色;零售价:¥3149.79"), -1, 29 }, { TU("Produkt:Google Pixel 4a - 128 GB Speicher - Schwarz;Preis:444,90 €"), -1, 17 } }, 0, 70, 76, 0, "AIM ITS/04-023:2022 Annex A example; BWIPP different encodation", + "1000110101010110001000100011111010110011011010101111000111000010111011110011" + "0001101101110100100010010110111110100101111100011011101000110101010010101010" + "0111101111011010010111011010001100110000001000101000110001000100001101101011" + "0000101011011101100100110010010001001000010000001011010011100011000100100001" + "1111100000100110111110011110110100000010000011101001010001000011011100100100" + "1100101111101000110111111110010010000100110010101010101001100011100101100001" + "0111101011111100101010001110001011100101100010001010011110001111001011101100" + "0000101000111101011101101010111100111101001000101011110111101001100111100011" + "1111100011010001100110011010011001100010101111001010111110001001010110100111" + "1011101010011111111111011110110001010000100110001010001000000000001001101000" + "0110100110001000110110001010001000110011001100101001000100101111001011101110" + "0101101100000001000001000010110100010010100000001001110010010101000100100110" + "1011111010101111011011111011001010111101110010101100111100111011001101111011" + "0100100010111101011100010010110110101010100110111010110001001110101011101100" + "1101100011101010101010101110001011010101100010001010010101111011000011101101" + "1011101010001101000001001110111100011101001000101000110001111101100010101000" + "0110100000100100110011100010111100010010100001011010011100010111110100100111" + "0010101000101100001101000010101100110001111110111011000001011110101011101110" + "0010100110000010010000111110011101011000000101111001010000001000001000101000" + "0111100100110110111100101110101110111100011001011011001000010011111001101000" + "1110101100110101100110110010101011000011111110101000110010110100101110100010" + "1111100111101001000001010010011110001000111111101001011101110000011011100101" + "1000101000100010001000100010100010001000100010001010001000100010001000101000" + "0001100001000100010001000110000100010001000100011000010001000100010001100001" + "1000111000100010001000100011100010001000100010001110001000100010001000111000" + "0001100001000100010001000110000100010001000100011000010001000100010001100001" + "1000101000100010001000100010100010001000100010001010001000100010001000101000" + "0001100001000100010001000110000100010001000100011000010001000100010001100001" + "1000101000100010001000100010100010001000100010001010001000100010001000101000" + "0001100001000100010001000110000100010001000100011000010001000100010001100001" + "0000100000000000000000000010000000000000000000001000000000000000000000100000" + "1111111111111111111111111111111111111111111111111111111111111111111111111111" + "0000000000000000000000000010000000000000000000000000000000000000000000100000" + "1111111111111111111111111111111111111111111111111111111111111111111111111111" + "0000000000000000000000000010000000000000000000000000000000000000000000100000" + "1111111111111111111111111111111111111111111111111111111111111111111111111111" + "0000000000000000000000000000000000000000000000000000000000000000000000000000" + "0111111111111111111111111111111111111111111111111111111111111111111111111110" + "0100000000000000000000000000000000000000000000000000000000000000000000000010" + "0111111111111111111111111111111111111111111111111111111111111111111111111110" + "1000101000100010001000100010100010001000100010001010001000100010001000101000" + "0001100001000100010001000110000100010001000100011000010001000100010001100001" + "1000101000100010001000100010100010001000100010001010001000100010001000101000" + "0001100001000100010001000110000100010001000100011000010001000100010001100001" + "1000101000100010001000100010100010001000100010001010001000100010001000101000" + "0001110001000100010001000111000100010001000100011100010001000100010001110001" + "1000101000100010001000100010100010001000100010001010001000100010001000101000" + "0001100001000100010001000110000100010001000100011000010001000100010001100001" + "1000101000100010001000100010100010001000100010001010001000100010001000101000" + "0001100001000100010001000110000100010001000100011000010001000100010001100001" + "1000101000100010001000100010100010001000100010001010001000100010001000101000" + "0001100001000100010001000110000100010001000100011000010001000100010001100001" + "1000101000100010001000100010100010001000100010001010001000111001101111100110" + "0001100001000100010001000110000100010001000100011000010001000110100010100101" + "0101101000101000110010110110001110100100110101001000001100000010011101100010" + "0100101100111011100101111110111100100011111000111010110101000110001000100111" + "1011100010000010011110111110111011110111001100111000101011101100001101100001" + "0011111101010101000010110011010000101111001101011101101100000011001101111110" + "1001101110000000010100100110001000011000010000001001100010100101011001100000" + "1010100110110100010001001110110010011100001101001000000010100010111111100101" + "0001101110111011011001101110001100010010110101111000101011101001111000100000" + "0100100011110110101101100110010110110100101011001011011000011001000111100011" + "1010101111011001001000100110010011010011110100101010010111000101001001100110" + "1011100010101101111110010010001011100010010101111001001111010100011111100001" + "0110101001011011001101100110110001100100010000101011010010101001110100100110" + "1101101000100011101100101110100110011111100111111001010100100101111101100010" + "1100100010111011001011100010100100011110001000101011000010100011101011101111" + "1110100101000010010101100010010111010111001110011010010101111110100000100011" + "0110101011010011001101110110100011011101001011011001000100000001110011101110" + "1110110001111000110010010111100110011010101100011101011011100000011001110111" + }, + /* 5*/ { UNICODE_MODE, -1, { 0, 0, "" }, { { TU("price:$439.97"), -1, 3 }, { TU("零售价:¥3149.79"), -1, 29 }, { TU("Preis:444,90 €"), -1, 17 } }, 0, 40, 42, 1, "AIM ITS/04-023:2022 Annex A example price only", + "100011010101011000101100100001110111110110" + "000110110111010010001010010100010011101010" + "011010011000110010101010001100101110100101" + "010010011010110101111001101011110011101101" + "100010100010011110001000110011101100101101" + "001010001011110111101001000100111010101011" + "101110110100111010101010101010110010101101" + "110010101110100011011000000100111111100001" + "010110100010001001011001011101100110100111" + "110110001000100011001001001101101010100100" + "001110101000110010111001001011100010101000" + "101110111001011101111000000110110101100001" + "100011100010001000101100100010001000111000" + "000110000100010001001001000100010001100001" + "100010100010001000101000100010001000101000" + "000010000000000000001000000000000000100000" + "111111111111111111111111111111111111111111" + "000000000000000000000000000000000000000000" + "011111111111111111111111111111111111111110" + "010000000000000000000000000000000000000010" + "011111111111111111111111111111111111111110" + "010000000000000000000000000000000000000010" + "011111111111111111111111111111111111111110" + "010000000000000000000000000000000000000010" + "011111111111111111111111111111111111111110" + "000110000100010001001001000100010001100001" + "100010100010001000101000100010001000101000" + "000111000100010001001101000100010001110001" + "100010100010001000101000100010001000101000" + "000110000100010001001001000100010001100001" + "100010101101011000011000010110000000101110" + "000110111010101011001011011010010011100010" + "100010000110000101101011111101110001100010" + "010110010000111010111000101011000010101010" + "111010111101001011001010101000001111100000" + "011110101101000001001001011001010000100111" + "110110011011111111111000000001111100101100" + "110110001001101110101011000011000000101111" + "100110111001001100101001010010001011100111" + "111011100100101100101111011011100100111101" + }, + /* 6*/ { DATA_MODE, -1, { 0, 0, "" }, { { TU("\266"), 1, 0 }, { TU("\266"), 1, 7 }, { TU("\266"), 1, 0 } }, 0, 22, 22, 1, "Standard example + extra seg, data mode", + "1000110101111000110101" + "0001101101101101111101" + "1000101000100011100011" + "0010100010100110110111" + "0101101000100010001110" + "1101100010001001011011" + "0011101000100010000010" + "0000100000000000100000" + "1111111111111111111111" + "0000000000000000000000" + "0111111111111111111110" + "0100000000000000000010" + "0111111111111111111110" + "0100000000000000000010" + "0111111111111111111110" + "0111000100010001100011" + "1100010110011101101111" + "1100000111010111101001" + "0010000001001111101110" + "1100100101010100100110" + "1110101101100111101011" + "1001101001111010111100" + }, + /* 7*/ { UNICODE_MODE, -1, { 1, 15, "" }, { { TU("A"), -1, 3 }, { TU("B"), -1, 4 }, { TU("C"), -1, 5 } }, 0, 22, 22, 1, "Structured Append (Group mode) 1st symbol, with ECI", + "1000111110000001010101" + "0001101001111011011101" + "1000101000100001000101" + "0010100010010100101101" + "1000101000100001000101" + "0010100010011000111101" + "1000101000100001000111" + "0000100000000000100000" + "1111111111111111111111" + "0000000000000000000000" + "0111111111111111111110" + "0100000000000000000010" + "0111111111111111111110" + "0100000000000000000010" + "0111111111111111111110" + "0010001001110100100100" + "0010010011001111101011" + "1101000100011110101010" + "0000000001000101101000" + "1101010110111101101011" + "0011010110111100101011" + "1111101011110000110101" + }, + /* 8*/ { UNICODE_MODE, -1, { 3, 15, "" }, { { TU("A"), -1, 3 }, { TU("B"), -1, 4 }, { TU("C"), -1, 5 } }, 0, 22, 22, 1, "Structured Append (Group mode) subsequent symbol, with ECI", + "0010111110010110001000" + "1100101001110100100010" + "1000100100010110001000" + "0101100010110100100010" + "1000100100010110001000" + "0110100011110100100010" + "1000100100100010001100" + "0000100000000000100000" + "1111111111111111111111" + "0000000000000000000000" + "0111111111111111111110" + "0100000000000000000010" + "0111111111111111111110" + "0100000000000000000010" + "0111111111111111111110" + "0111010000010001101101" + "0001110000100010101101" + "0101011110011000101110" + "1111110110000110100111" + "0100001100101001100010" + "1111010111000111100011" + "0010100111110110110101" + }, + /* 9*/ { UNICODE_MODE, -1, { 128, 128, "" }, { { TU("A"), -1, 3 }, { TU("B"), -1, 4 }, { TU("C"), -1, 5 } }, 0, 22, 22, 1, "Structured Append (Extended Group mode)", + "1000111000111001011000" + "0000100000100111010010" + "1000101000010001011000" + "0010100101001011010010" + "1000101000010001011000" + "0010100110001111010010" + "1000101000010010000001" + "0000100000000000100000" + "1111111111111111111111" + "0000000000000000000000" + "0111111111111111111110" + "0100000000000000000010" + "0111111111111111111110" + "0100000000000000000010" + "0111111111111111111110" + "0010011101000001101001" + "1111101010101110101001" + "0111011000100101100010" + "1111010000001010101101" + "0010001100101010101111" + "0000110101011010101000" + "0110000110100100110110" + }, + /* 10*/ { UNICODE_MODE, 9, { 0, 0, "" }, { { TU("A"), -1, 3 }, { TU("B"), -1, 4 }, { TU("C"), -1, 5 } }, ZINT_ERROR_INVALID_OPTION, 0, 0, 1, "Multiple segments not suppoted for Version S", + "" + }, + }; + int data_size = ARRAY_SIZE(data); + int i, j, seg_count, ret; + struct zint_symbol *symbol; + + char escaped[8192]; + char bwipp_buf[32768]; + char bwipp_msg[1024]; + + int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); // Only do BWIPP test if asked, too slow otherwise + + testStart("test_encode_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + if ((debug & ZINT_DEBUG_TEST_PRINT) && !(debug & ZINT_DEBUG_TEST_LESS_NOISY)) printf("i:%d\n", i); + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + testUtilSetSymbol(symbol, BARCODE_CODEONE, data[i].input_mode, -1 /*eci*/, + -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, + NULL, 0, debug); + if (data[i].structapp.count) { + symbol->structapp = data[i].structapp; + } + for (j = 0, seg_count = 0; j < 3 && data[i].segs[j].length; j++, seg_count++); + + ret = ZBarcode_Encode_Segs(symbol, data[i].segs, seg_count); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode_Segs ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + char escaped1[4096]; + char escaped2[4096]; + int length = data[i].segs[0].length == -1 ? (int) ustrlen(data[i].segs[0].source) : data[i].segs[0].length; + int length1 = data[i].segs[1].length == -1 ? (int) ustrlen(data[i].segs[1].source) : data[i].segs[1].length; + int length2 = data[i].segs[2].length == -1 ? (int) ustrlen(data[i].segs[2].source) : data[i].segs[2].length; + printf(" /*%3d*/ { %s, %d, { %d, %d, \"%s\" }, { { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d } }, %s, %d, %d, %d, \"%s\",\n", + i, testUtilInputModeName(data[i].input_mode), data[i].option_2, + data[i].structapp.index, data[i].structapp.count, data[i].structapp.id, + testUtilEscape((const char *) data[i].segs[0].source, length, escaped, sizeof(escaped)), data[i].segs[0].length, data[i].segs[0].eci, + testUtilEscape((const char *) data[i].segs[1].source, length1, escaped1, sizeof(escaped1)), data[i].segs[1].length, data[i].segs[1].eci, + testUtilEscape((const char *) data[i].segs[2].source, length2, escaped2, sizeof(escaped2)), data[i].segs[2].length, data[i].segs[2].eci, + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].bwipp_cmp, data[i].comment); + if (ret < ZINT_ERROR) { + testUtilModulesPrint(symbol, " ", "\n"); + } else { + printf(" \"\"\n"); + } + printf(" },\n"); + } else { + if (ret < ZINT_ERROR) { + int width, row; + + 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); + + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d\n", + i, ret, width, row); + + if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, -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 { + ret = testUtilBwippSegs(i, symbol, -1, data[i].option_2, -1, data[i].segs, seg_count, NULL, bwipp_buf, sizeof(bwipp_buf)); + assert_zero(ret, "i:%d %s testUtilBwippSegs ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); + + ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); + assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n actual: %s\nexpected: %s\n", + i, testUtilBarcodeName(symbol->symbology), ret, bwipp_msg, bwipp_buf, data[i].expected); + } + } + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + static void test_fuzz(int index, int debug) { struct item { @@ -2990,6 +3394,7 @@ int main(int argc, char *argv[]) { { "test_large", test_large, 1, 0, 1 }, { "test_input", test_input, 1, 0, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_encode_segs", test_encode_segs, 1, 1, 1 }, { "test_fuzz", test_fuzz, 1, 0, 1 }, }; @@ -2999,3 +3404,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_code128.c b/backend/tests/test_code128.c index e2da4079..1c6d4d91 100644 --- a/backend/tests/test_code128.c +++ b/backend/tests/test_code128.c @@ -102,7 +102,7 @@ static void test_large(int index, int debug) { testFinish(); } -int hrt_cpy_iso8859_1(struct zint_symbol *symbol, const unsigned char *source, int source_len); +int c128_hrt_cpy_iso8859_1(struct zint_symbol *symbol, const unsigned char source[], const int length); static void test_hrt_cpy_iso8859_1(int index, int debug) { @@ -157,7 +157,7 @@ static void test_hrt_cpy_iso8859_1(int index, int debug) { length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; - ret = hrt_cpy_iso8859_1(&symbol, (unsigned char *) data[i].data, length); + ret = c128_hrt_cpy_iso8859_1(&symbol, (unsigned char *) data[i].data, length); if (index != -1 && (debug & ZINT_DEBUG_TEST_PRINT)) { for (j = 0; j < ret; j++) { fprintf(stderr, "symbol.text[%d] %2X\n", j, symbol.text[j]); @@ -822,7 +822,7 @@ static void test_encode(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf)); + 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, data[i].expected); diff --git a/backend/tests/test_code16k.c b/backend/tests/test_code16k.c index 2d8c4dba..9022625a 100644 --- a/backend/tests/test_code16k.c +++ b/backend/tests/test_code16k.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2020 - 2021 Robin Stuart + Copyright (C) 2020-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "testcommon.h" @@ -333,7 +332,7 @@ static void test_encode(int index, int generate, int debug) { assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, -1, -1, debug)) { - ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -364,3 +363,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_code49.c b/backend/tests/test_code49.c index bc473540..ccd23ace 100644 --- a/backend/tests/test_code49.c +++ b/backend/tests/test_code49.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2020 - 2021 Robin Stuart + Copyright (C) 2020-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "testcommon.h" @@ -247,7 +246,7 @@ static void test_encode(int index, int generate, int debug) { assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, -1, -1, debug)) { - ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -277,3 +276,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_common.c b/backend/tests/test_common.c index e874d49e..e124bdcf 100644 --- a/backend/tests/test_common.c +++ b/backend/tests/test_common.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2019 - 2021 Robin Stuart + Copyright (C) 2019-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "testcommon.h" @@ -67,86 +66,90 @@ static void test_is_sane(int index) { /* 1*/ { IS_SPC_F, "\000", 1, 0, " " }, /* 2*/ { IS_HSH_F, "#", -1, 1, "#" }, /* 3*/ { IS_HSH_F, " ", -1, 0, "#" }, - /* 4*/ { IS_PLS_F, "+", -1, 1, "+" }, - /* 5*/ { IS_PLS_F, " ", -1, 0, "+" }, - /* 6*/ { IS_MNS_F, "-", -1, 1, "-" }, - /* 7*/ { IS_MNS_F, " ", -1, 0, "-" }, - /* 8*/ { IS_NUM_F, "0123456789", -1, 1, "0123456789" }, // NEON - /* 9*/ { IS_NUM_F, "0123456789 ", -1, 0, "0123456789" }, - /* 10*/ { IS_NUM_F, "012345678A9", -1, 0, "0123456789" }, - /* 11*/ { IS_UPO_F, "GHIJKLMNOPQRSTUVWYZ", -1, 1, "GHIJKLMNOPQRSTUVWYZ" }, - /* 12*/ { IS_UPO_F, "FGHIJKLMNOPQRSTUVWYZ", -1, 0, "GHIJKLMNOPQRSTUVWYZ" }, - /* 13*/ { IS_LWO_F, "ghijklmnopqrstuvwyz", -1, 1, "ghijklmnopqrstuvwyz" }, - /* 14*/ { IS_LWO_F, "fghijklmnopqrstuvwyz", -1, 0, "ghijklmnopqrstuvwyz" }, - /* 15*/ { IS_UHX_F, "ABCDEF", -1, 1, "ABCDEF" }, - /* 16*/ { IS_UHX_F, "ABCDEf", -1, 0, "ABCDEF" }, - /* 17*/ { IS_LHX_F, "abcdef", -1, 1, "abcdef" }, - /* 18*/ { IS_LHX_F, "abcdeF", -1, 0, "abcdef" }, - /* 19*/ { IS_UPR_F, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", -1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, - /* 20*/ { IS_UPR_F, "ABCDEFGHIJKLMNOPQRSTUVWXYZ ", -1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, - /* 21*/ { IS_UPR_F, "X", -1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, - /* 22*/ { IS_UPR_F, "x", -1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, - /* 23*/ { IS_LWR_F, "abcdefghijklmnopqrstuvwxyz", -1, 1, "abcdefghijklmnopqrstuvwxyz" }, - /* 24*/ { IS_LWR_F, "abcdefghijklmnopqrstuvwxyz ", -1, 0, "abcdefghijklmnopqrstuvwxyz" }, - /* 25*/ { IS_LWR_F, "x", -1, 1, "abcdefghijklmnopqrstuvwxyz" }, - /* 26*/ { IS_LWR_F, "X", -1, 0, "abcdefghijklmnopqrstuvwxyz" }, - /* 27*/ { IS_UX__F, "X", -1, 1, "X" }, - /* 28*/ { IS_UX__F, "x", -1, 0, "X" }, - /* 29*/ { IS_LX__F, "x", -1, 1, "x" }, - /* 30*/ { IS_LX__F, "X", -1, 0, "x" }, - /* 31*/ { IS_C82_F, "!\"%&'()*,./:;<=>?_", -1, 1, "!\"%&'()*,./:;<=>?_" }, // CSET82 punctuation less "-+" - /* 32*/ { IS_C82_F, "!\"%&'()*,./:;<=>?_ ", -1, 0, "!\"%&'()*,./:;<=>?_" }, - /* 33*/ { IS_C82_F, "-", -1, 0, "!\"%&'()*,./:;<=>?_" }, - /* 34*/ { IS_C82_F, "$", -1, 0, "!\"%&'()*,./:;<=>?_" }, - /* 35*/ { IS_SIL_F, ".$/%", -1, 1, ".$/%" }, // SILVER punctuation less " -+" - /* 36*/ { IS_SIL_F, ".$/% " , -1, 0, ".$/%" }, - /* 37*/ { IS_SIL_F, "-", -1, 0, ".$/%" }, - /* 38*/ { IS_CLI_F, "$:/.", -1, 1, "$:/." }, // CALCIUM INNER punctuation less "-+" - /* 39*/ { IS_CLI_F, "$:/. ", -1, 0, "$:/." }, - /* 40*/ { IS_CLI_F, "+", -1, 0, "$:/." }, - /* 41*/ { IS_ARS_F, "ABCDEFGHJKLMNPRSTUVWXYZ", -1, 1, "ABCDEFGHJKLMNPRSTUVWXYZ" }, // ARSENIC uppercase - /* 42*/ { IS_ARS_F, "ABCDEFGHJKLMNPRSTUVWXYZ ", -1, 0, "ABCDEFGHJKLMNPRSTUVWXYZ" }, - /* 43*/ { IS_ARS_F, "I", -1, 0, "ABCDEFGHJKLMNPRSTUVWXYZ" }, - /* 44*/ { IS_ARS_F, "O", -1, 0, "ABCDEFGHJKLMNPRSTUVWXYZ" }, - /* 45*/ { IS_NUM_F | IS_UHX_F, "0123456789ABCDEF", -1, 1, "0123456789ABCDEF" }, // SSET - /* 46*/ { IS_NUM_F | IS_UHX_F, "0123456789ABCDEf", -1, 0, "0123456789ABCDEF" }, - /* 47*/ { IS_NUM_F | IS_PLS_F, "0123456789+", -1, 1, "0123456789+" }, // SODIUM_PLS - /* 48*/ { IS_NUM_F | IS_PLS_F, "0123456789+-", -1, 0, "0123456789+" }, - /* 49*/ { IS_NUM_F | IS_UX__F, "0123456789X", -1, 1, "0123456789X" }, // ISBNX_SANE - /* 50*/ { IS_NUM_F | IS_UX__F, "0123456789x", -1, 0, "0123456789X" }, - /* 51*/ { IS_NUM_F | IS_UX__F | IS_LX__F | IS_PLS_F, "0123456789Xx+", -1, 1, "0123456789Xx+" }, // ISBNX_ADDON_SANE - /* 52*/ { IS_NUM_F | IS_UX__F | IS_LX__F | IS_PLS_F, "0123456789Xx+Y", -1, 0, "0123456789Xx+" }, - /* 53*/ { IS_NUM_F | IS_MNS_F, "0123456789-", -1, 1, "0123456789-" }, // SODIUM_MNS - /* 54*/ { IS_NUM_F | IS_MNS_F, "0123456789-+", -1, 0, "0123456789-" }, - /* 55*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz", -1, 1, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, // CSET82 - /* 56*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, " ", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, - /* 57*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "#", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, - /* 58*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "$", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, - /* 59*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "@", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, - /* 60*/ { IS_LWR_F | IS_C82_F | IS_PLS_F | IS_MNS_F | IS_SPC_F, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ ", -1, 1, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ " }, // IS_ISOIEC_F - /* 61*/ { IS_LWR_F | IS_C82_F | IS_PLS_F | IS_MNS_F | IS_SPC_F, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ #", -1, 0, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ " }, - /* 62*/ { IS_LWR_F | IS_C82_F | IS_PLS_F | IS_MNS_F | IS_SPC_F, "$", -1, 0, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ " }, - /* 63*/ { IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "-. $/+%", -1, 1, "" }, - /* 64*/ { IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "-. $/!+%", -1, 0, "" }, - /* 65*/ { IS_NUM_F | IS_UPR_F | IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%" }, // SILVER - /* 66*/ { IS_NUM_F | IS_UPR_F | IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%a", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%" }, - /* 67*/ { IS_NUM_F | IS_ARS_F, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ", -1, 1, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" }, // ARSENIC - /* 68*/ { IS_NUM_F | IS_ARS_F, "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ", -1, 0, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" }, - /* 69*/ { IS_NUM_F | IS_ARS_F, "0123456789ABCDEFGHJKLMNPRSTUVWXYz", -1, 0, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" }, - /* 70*/ { IS_NUM_F | IS_UPR_F | IS_LWR_F | IS_SPC_F | IS_HSH_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #" }, // GDSET - /* 71*/ { IS_NUM_F | IS_UPR_F | IS_LWR_F | IS_SPC_F | IS_HSH_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #!", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #" }, - /* 72*/ { IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F, "0123456789-$:/.+", -1, 1, "0123456789-$:/.+" }, // CALCIUM_INNER - /* 73*/ { IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F, "0123456789-$:/.+ ", -1, 0, "0123456789-$:/.+" }, - /* 74*/ { IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F, "0123456789-$:/.+!", -1, 0, "0123456789-$:/.+" }, - /* 75*/ { IS_NUM_F | IS_UPR_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, // KRSET - /* 76*/ { IS_NUM_F | IS_UPR_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYz", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, - /* 77*/ { IS_NUM_F | IS_UPR_F | IS_SPC_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " }, // RUBIDIUM - /* 78*/ { IS_NUM_F | IS_UPR_F | IS_SPC_F, "0123456789aBCDEFGHIJKLMNOPQRSTUVWXYZ ", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " }, - /* 79*/ { IS_NUM_F | IS_MNS_F | IS_UPR_F, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ", -1, 1, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, // SHKASUTSET - /* 80*/ { IS_NUM_F | IS_MNS_F | IS_UPR_F, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYz", -1, 0, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, + /* 4*/ { IS_AST_F, "*", -1, 1, "*" }, + /* 5*/ { IS_AST_F, " ", -1, 0, "*" }, + /* 6*/ { IS_PLS_F, "+", -1, 1, "+" }, + /* 7*/ { IS_PLS_F, " ", -1, 0, "+" }, + /* 8*/ { IS_MNS_F, "-", -1, 1, "-" }, + /* 9*/ { IS_MNS_F, " ", -1, 0, "-" }, + /* 10*/ { IS_NUM_F, "0123456789", -1, 1, "0123456789" }, // NEON + /* 11*/ { IS_NUM_F, "0123456789 ", -1, 0, "0123456789" }, + /* 12*/ { IS_NUM_F, "012345678A9", -1, 0, "0123456789" }, + /* 13*/ { IS_UPO_F, "GHIJKLMNOPQRSTUVWYZ", -1, 1, "GHIJKLMNOPQRSTUVWYZ" }, + /* 14*/ { IS_UPO_F, "FGHIJKLMNOPQRSTUVWYZ", -1, 0, "GHIJKLMNOPQRSTUVWYZ" }, + /* 15*/ { IS_LWO_F, "ghijklmnopqrstuvwyz", -1, 1, "ghijklmnopqrstuvwyz" }, + /* 16*/ { IS_LWO_F, "fghijklmnopqrstuvwyz", -1, 0, "ghijklmnopqrstuvwyz" }, + /* 17*/ { IS_UHX_F, "ABCDEF", -1, 1, "ABCDEF" }, + /* 18*/ { IS_UHX_F, "ABCDEf", -1, 0, "ABCDEF" }, + /* 19*/ { IS_LHX_F, "abcdef", -1, 1, "abcdef" }, + /* 20*/ { IS_LHX_F, "abcdeF", -1, 0, "abcdef" }, + /* 21*/ { IS_UPR_F, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", -1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, + /* 22*/ { IS_UPR_F, "ABCDEFGHIJKLMNOPQRSTUVWXYZ ", -1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, + /* 23*/ { IS_UPR_F, "X", -1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, + /* 24*/ { IS_UPR_F, "x", -1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, + /* 25*/ { IS_LWR_F, "abcdefghijklmnopqrstuvwxyz", -1, 1, "abcdefghijklmnopqrstuvwxyz" }, + /* 26*/ { IS_LWR_F, "abcdefghijklmnopqrstuvwxyz ", -1, 0, "abcdefghijklmnopqrstuvwxyz" }, + /* 27*/ { IS_LWR_F, "x", -1, 1, "abcdefghijklmnopqrstuvwxyz" }, + /* 28*/ { IS_LWR_F, "X", -1, 0, "abcdefghijklmnopqrstuvwxyz" }, + /* 29*/ { IS_UX__F, "X", -1, 1, "X" }, + /* 30*/ { IS_UX__F, "x", -1, 0, "X" }, + /* 31*/ { IS_LX__F, "x", -1, 1, "x" }, + /* 32*/ { IS_LX__F, "X", -1, 0, "x" }, + /* 33*/ { IS_C82_F, "!\"%&'(),./:;<=>?_", -1, 1, "!\"%&'(),./:;<=>?_" }, // CSET82 punctuation less "*+-" + /* 34*/ { IS_C82_F, "!\"%&'(),./:;<=>?_ ", -1, 0, "!\"%&'(),./:;<=>?_" }, + /* 35*/ { IS_C82_F, "-", -1, 0, "!\"%&'(),./:;<=>?_" }, + /* 36*/ { IS_C82_F, "$", -1, 0, "!\"%&'(),./:;<=>?_" }, + /* 37*/ { IS_SIL_F, ".$/%", -1, 1, ".$/%" }, // SILVER punctuation less " +-" + /* 38*/ { IS_SIL_F, ".$/% " , -1, 0, ".$/%" }, + /* 39*/ { IS_SIL_F, "-", -1, 0, ".$/%" }, + /* 40*/ { IS_CLI_F, "$:/.", -1, 1, "$:/." }, // CALCIUM INNER punctuation less "+-" + /* 41*/ { IS_CLI_F, "$:/. ", -1, 0, "$:/." }, + /* 42*/ { IS_CLI_F, "+", -1, 0, "$:/." }, + /* 43*/ { IS_ARS_F, "ABCDEFGHJKLMNPRSTUVWXYZ", -1, 1, "ABCDEFGHJKLMNPRSTUVWXYZ" }, // ARSENIC uppercase + /* 44*/ { IS_ARS_F, "ABCDEFGHJKLMNPRSTUVWXYZ ", -1, 0, "ABCDEFGHJKLMNPRSTUVWXYZ" }, + /* 45*/ { IS_ARS_F, "I", -1, 0, "ABCDEFGHJKLMNPRSTUVWXYZ" }, + /* 46*/ { IS_ARS_F, "O", -1, 0, "ABCDEFGHJKLMNPRSTUVWXYZ" }, + /* 47*/ { IS_NUM_F | IS_UHX_F, "0123456789ABCDEF", -1, 1, "0123456789ABCDEF" }, // SSET + /* 48*/ { IS_NUM_F | IS_UHX_F, "0123456789ABCDEf", -1, 0, "0123456789ABCDEF" }, + /* 49*/ { IS_NUM_F | IS_PLS_F, "0123456789+", -1, 1, "0123456789+" }, // SODIUM_PLS + /* 50*/ { IS_NUM_F | IS_PLS_F, "0123456789+-", -1, 0, "0123456789+" }, + /* 51*/ { IS_NUM_F | IS_UX__F, "0123456789X", -1, 1, "0123456789X" }, // ISBNX_SANE + /* 52*/ { IS_NUM_F | IS_UX__F, "0123456789x", -1, 0, "0123456789X" }, + /* 53*/ { IS_NUM_F | IS_UX__F | IS_LX__F | IS_PLS_F, "0123456789Xx+", -1, 1, "0123456789Xx+" }, // ISBNX_ADDON_SANE + /* 54*/ { IS_NUM_F | IS_UX__F | IS_LX__F | IS_PLS_F, "0123456789Xx+Y", -1, 0, "0123456789Xx+" }, + /* 55*/ { IS_NUM_F | IS_MNS_F, "0123456789-", -1, 1, "0123456789-" }, // SODIUM_MNS + /* 56*/ { IS_NUM_F | IS_MNS_F, "0123456789-+", -1, 0, "0123456789-" }, + /* 57*/ { IS_C82_F | IS_AST_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz", -1, 1, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, // CSET82 + /* 58*/ { IS_C82_F | IS_AST_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, " ", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, + /* 59*/ { IS_C82_F | IS_AST_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "#", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, + /* 60*/ { IS_C82_F | IS_AST_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "$", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, + /* 61*/ { IS_C82_F | IS_AST_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "@", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, + /* 62*/ { IS_LWR_F | IS_C82_F | IS_AST_F | IS_PLS_F | IS_MNS_F | IS_SPC_F, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ ", -1, 1, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ " }, // IS_ISOIEC_F + /* 63*/ { IS_LWR_F | IS_C82_F | IS_AST_F | IS_PLS_F | IS_MNS_F | IS_SPC_F, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ #", -1, 0, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ " }, + /* 64*/ { IS_LWR_F | IS_C82_F | IS_AST_F | IS_PLS_F | IS_MNS_F | IS_SPC_F, "$", -1, 0, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ " }, + /* 65*/ { IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "-. $/+%", -1, 1, "" }, + /* 66*/ { IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "-. $/!+%", -1, 0, "" }, + /* 67*/ { IS_NUM_F | IS_UPR_F | IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%" }, // SILVER + /* 68*/ { IS_NUM_F | IS_UPR_F | IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%a", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%" }, + /* 69*/ { IS_NUM_F | IS_ARS_F, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ", -1, 1, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" }, // ARSENIC + /* 70*/ { IS_NUM_F | IS_ARS_F, "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ", -1, 0, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" }, + /* 71*/ { IS_NUM_F | IS_ARS_F, "0123456789ABCDEFGHJKLMNPRSTUVWXYz", -1, 0, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" }, + /* 72*/ { IS_NUM_F | IS_UPR_F | IS_LWR_F | IS_SPC_F | IS_HSH_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #" }, // GDSET + /* 73*/ { IS_NUM_F | IS_UPR_F | IS_LWR_F | IS_SPC_F | IS_HSH_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #!", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #" }, + /* 74*/ { IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F, "0123456789-$:/.+", -1, 1, "0123456789-$:/.+" }, // CALCIUM_INNER + /* 75*/ { IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F, "0123456789-$:/.+ ", -1, 0, "0123456789-$:/.+" }, + /* 76*/ { IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F, "0123456789-$:/.+!", -1, 0, "0123456789-$:/.+" }, + /* 77*/ { IS_NUM_F | IS_UPR_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, // KRSET + /* 78*/ { IS_NUM_F | IS_UPR_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYz", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, + /* 79*/ { IS_NUM_F | IS_UPR_F | IS_SPC_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " }, // RUBIDIUM + /* 80*/ { IS_NUM_F | IS_UPR_F | IS_SPC_F, "0123456789aBCDEFGHIJKLMNOPQRSTUVWXYZ ", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " }, + /* 81*/ { IS_NUM_F | IS_MNS_F | IS_UPR_F, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ", -1, 1, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, // SHKASUTSET + /* 82*/ { IS_NUM_F | IS_MNS_F | IS_UPR_F, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYz", -1, 0, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, + /* 83*/ { IS_NUM_F | IS_UPR_F | IS_SPC_F | IS_AST_F | IS_PLS_F | IS_MNS_F | IS_SIL_F | IS_CLI_F, "1234567890 $%*+-./:ABCDEFGHIJKLMNOPQRSTUVWXYZ", -1, 1, "1234567890 $%*+-./:ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, // QR_ALPHA + /* 84*/ { IS_NUM_F | IS_UPR_F | IS_SPC_F | IS_AST_F | IS_PLS_F | IS_MNS_F | IS_SIL_F | IS_CLI_F, "1234567890 $%*+-./:ABCDEFGHIJKLMNOPQRSTUVWXYz", -1, 0, "1234567890 $%*+-./:ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, }; int data_size = ARRAY_SIZE(data); - int i, length, ret; + int i, j, length, ret; testStart("test_is_sane"); @@ -167,6 +170,15 @@ static void test_is_sane(int index) { assert_zero(ret, "i:%d orig_ret %d, ret %d != 0\n", i, orig_ret, ret); } } + + ret = 1; + for (j = 0; j < length; j++) { + if (!is_chr(data[i].flg, data[i].data[j])) { + ret = 0; + break; + } + } + assert_equal(ret, data[i].ret, "i:%d is_chr() ret %d != %d\n", i, ret, data[i].ret); } testFinish(); @@ -416,3 +428,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_composite.c b/backend/tests/test_composite.c index e4a06138..581d007e 100644 --- a/backend/tests/test_composite.c +++ b/backend/tests/test_composite.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2019 - 2021 Robin Stuart + Copyright (C) 2019-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "testcommon.h" @@ -1570,7 +1569,7 @@ static void test_examples(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -1735,7 +1734,7 @@ static void test_odd_numbered_numeric(int index, int generate, int debug) { assert_zero(ret, "i:%d %s testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, testUtilBarcodeName(data[i].symbology), ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, -1, -1, debug)) { - ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -1866,7 +1865,7 @@ static void test_ean128_cc_shift(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -2409,7 +2408,7 @@ static void test_encodation_0(int index, int generate, int debug) { assert_zero(ret, "i:%d %s testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, testUtilBarcodeName(data[i].symbology), ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, -1, -1, debug)) { - ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -2546,7 +2545,7 @@ static void test_encodation_10(int index, int generate, int debug) { assert_zero(ret, "i:%d %s testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, testUtilBarcodeName(data[i].symbology), ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, -1, -1, debug)) { - ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -2962,7 +2961,7 @@ static void test_encodation_11(int index, int generate, int debug) { assert_zero(ret, "i:%d %s testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, testUtilBarcodeName(data[i].symbology), ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, -1, -1, debug)) { - ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_1, -1, -1, data[i].composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -3118,7 +3117,7 @@ static void test_addongap(int index, int generate, int debug) { assert_zero(ret, "i:%d %s testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, testUtilBarcodeName(data[i].symbology), ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, data[i].option_2, -1, debug)) { - ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, -1, composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, -1, composite, composite_length, symbol->primary, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -3608,3 +3607,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_dmatrix.c b/backend/tests/test_dmatrix.c index 2775d2cb..ce2121ee 100644 --- a/backend/tests/test_dmatrix.c +++ b/backend/tests/test_dmatrix.c @@ -653,8 +653,11 @@ static void test_reader_init(int index, int generate, int debug) { testFinish(); } +#define ZINT_TEST_ENCODING +#ifdef ZINT_TEST_ENCODING STATIC_UNLESS_ZINT_TEST int dm_encode(struct zint_symbol *symbol, const unsigned char source[], - unsigned char target[], int *p_length, int *p_binlen); + const int length, const int eci, const int gs1, unsigned char target[], int *p_tp); +#endif static void test_input(int index, int generate, int debug) { @@ -967,7 +970,7 @@ static void test_input(int index, int generate, int debug) { } 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)); + 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); @@ -988,13 +991,14 @@ static void test_input(int index, int generate, int debug) { } } +#ifdef ZINT_TEST_ENCODING if (ret < ZINT_ERROR) { if (i && (data[i].input_mode & 0x07) == (data[i - 1].input_mode & 0x07) && !(data[i].input_mode & FAST_MODE) && (data[i - 1].input_mode & FAST_MODE) && data[i].eci == data[i - 1].eci && data[i].option_2 == data[i - 1].option_2 && data[i].option_3 == data[i - 1].option_3 && data[i].output_options == data[i - 1].output_options && strcmp(data[i].data, data[i - 1].data) == 0) { unsigned char binary[2][2200]; - int inputlen; + int gs1; int binlen; int binlens[2] = {0}; unsigned char reduced[1000]; @@ -1012,18 +1016,18 @@ static void test_input(int index, int generate, int debug) { } else { text = (unsigned char *) data[i].data; } - inputlen = length; binlen = 0; symbol->input_mode = data[i - 1].input_mode; - ret = dm_encode(symbol, text, binary[0], &inputlen, &binlen); + gs1 = (symbol->input_mode & 0x07) != GS1_MODE ? 0 : (symbol->output_options & GS1_GS_SEPARATOR) ? 2 : 1; + ret = dm_encode(symbol, text, length, symbol->eci, 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; - inputlen = length; binlen = 0; symbol->input_mode = data[i].input_mode; - ret = dm_encode(symbol, text, binary[1], &inputlen, &binlen); + gs1 = (symbol->input_mode & 0x07) != GS1_MODE ? 0 : (symbol->output_options & GS1_GS_SEPARATOR) ? 2 : 1; + ret = dm_encode(symbol, text, length, symbol->eci, gs1, binary[1], &binlen); assert_zero(ret, "i:%d dm_encode() minimal ret %d != 0 (%s)\n", i, ret, symbol->errtxt); binlens[1] = binlen; @@ -1035,6 +1039,7 @@ static void test_input(int index, int generate, int debug) { } } } +#endif } ZBarcode_Delete(symbol); @@ -1736,7 +1741,7 @@ static void test_encode(int index, int generate, int debug) { "11110110001001001010110111010110" "11111111111111111111111111111111" }, - /* 33*/ { BARCODE_DATAMATRIX, GS1_MODE, -1, -1, -1, -1, "[01]00012345678905[17]180401[21]ABCDEFGHIJKL12345678[91]ABCDEFGHI123456789[92]abcdefghi", -1, 0, 32, 32, 0, "GGS Figure 5.6.3.2-3 (left) **NOT SAME** different encodation; BWIPP different encodation", 1, + /* 33*/ { BARCODE_DATAMATRIX, GS1_MODE, -1, -1, -1, -1, "[01]00012345678905[17]180401[21]ABCDEFGHIJKL12345678[91]ABCDEFGHI123456789[92]abcdefghi", -1, 0, 32, 32, 0, "GGS Figure 5.6.3.2-3 (left) **NOT SAME** different encodation; BWIPP different encodation", 2, "10101010101010101010101010101010" "11001000010111111001100001001011" "10001001100001101101000101000010" @@ -5219,7 +5224,7 @@ static void test_encode(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, -1, data[i].option_2, data[i].option_3, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf)); + 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, data[i].expected); @@ -5239,12 +5244,13 @@ static void test_encode(int index, int generate, int debug) { i, testUtilBarcodeName(symbol->symbology), ret, cmp_msg, cmp_len, cmp_buf, ret_len, escaped); } +#ifdef ZINT_TEST_ENCODING if (i && (data[i].input_mode & 0x07) == (data[i - 1].input_mode & 0x07) && !(data[i].input_mode & FAST_MODE) && (data[i - 1].input_mode & FAST_MODE) && data[i].eci == data[i - 1].eci && data[i].option_2 == data[i - 1].option_2 && data[i].option_3 == data[i - 1].option_3 && data[i].output_options == data[i - 1].output_options && strcmp(data[i].data, data[i - 1].data) == 0) { unsigned char binary[2][2200]; - int inputlen; + int gs1; int binlen; int binlens[2] = {0}; @@ -5252,18 +5258,18 @@ static void test_encode(int index, int generate, int debug) { "i:%d data[i].expected_rows * data[i].expected_width %d > data[i - 1].expected_rows * data[i - 1].expected_width %d\n", i, data[i].expected_rows * data[i].expected_width, data[i - 1].expected_rows * data[i - 1].expected_width); - inputlen = length; binlen = 0; symbol->input_mode = data[i - 1].input_mode; - ret = dm_encode(symbol, (unsigned char *) data[i].data, binary[0], &inputlen, &binlen); + gs1 = (symbol->input_mode & 0x07) != GS1_MODE ? 0 : (symbol->output_options & GS1_GS_SEPARATOR) ? 2 : 1; + ret = dm_encode(symbol, (unsigned char *) data[i].data, length, symbol->eci, 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; - inputlen = length; binlen = 0; symbol->input_mode = data[i].input_mode; - ret = dm_encode(symbol, (unsigned char *) data[i].data, binary[1], &inputlen, &binlen); + gs1 = (symbol->input_mode & 0x07) != GS1_MODE ? 0 : (symbol->output_options & GS1_GS_SEPARATOR) ? 2 : 1; + ret = dm_encode(symbol, (unsigned char *) data[i].data, length, symbol->eci, gs1, binary[1], &binlen); assert_zero(ret, "i:%d dm_encode() minimal ret %d != 0 (%s)\n", i, ret, symbol->errtxt); binlens[1] = binlen; @@ -5272,6 +5278,287 @@ static void test_encode(int index, int generate, int debug) { 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 + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_encode_segs(int index, int generate, int debug) { + + struct item { + int symbology; + int input_mode; + int output_options; + int option_2; + int option_3; + struct zint_structapp structapp; + struct zint_seg segs[3]; + int ret; + + int expected_rows; + int expected_width; + int bwipp_cmp; + char *comment; + char *expected; + }; + struct item data[] = { + /* 0*/ { BARCODE_DATAMATRIX, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 7 }, { TU(""), 0, 0 } }, 0, 14, 14, 1, "ISO 16022:2006 11.6 example", + "10101010101010" + "10000100111111" + "11101100000000" + "11111010010001" + "11000110001000" + "11110110011111" + "10111101000000" + "10010010000111" + "10100110111100" + "11011111011011" + "10101001101110" + "10001001101001" + "10011111100000" + "11111111111111" + }, + /* 1*/ { BARCODE_DATAMATRIX, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 14, 14, 1, "ISO 16022:2006 11.6 example auto-ECI", + "10101010101010" + "10000100111111" + "11101100000000" + "11111010010001" + "11000110001000" + "11110110011111" + "10111101000000" + "10010010000111" + "10100110111100" + "11011111011011" + "10101001101110" + "10001001101001" + "10011111100000" + "11111111111111" + }, + /* 2*/ { BARCODE_DATAMATRIX, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("Ж"), -1, 7 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, 0, 14, 14, 1, "ISO 16022:2006 11.6 example auto-ECI inverted", + "10101010101010" + "10001111001101" + "10011111110110" + "10001100000111" + "10000011111010" + "11000001100101" + "11100001111110" + "10101101000111" + "11101101001110" + "11100001000001" + "11110100111010" + "10010111100111" + "10011001010000" + "11111111111111" + }, + /* 3*/ { BARCODE_DATAMATRIX, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("Ж"), -1, 0 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 14, 14, 1, "ISO 16022:2006 11.6 example inverted auto-ECI", + "10101010101010" + "10001111001101" + "10011111110110" + "10001100000111" + "10000011111010" + "11000001100101" + "11100001111110" + "10101101000111" + "11101101001110" + "11100001000001" + "11110100111010" + "10010111100111" + "10011001010000" + "11111111111111" + }, + /* 4*/ { BARCODE_DATAMATRIX, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("product:Google Pixel 4a - 128 GB of Storage - Black;price:$439.97"), -1, 3 }, { TU("品名:Google 谷歌 Pixel 4a -128 GB的存储空间-黑色;零售价:¥3149.79"), -1, 29 }, { TU("Produkt:Google Pixel 4a - 128 GB Speicher - Schwarz;Preis:444,90 €"), -1, 17 } }, 0, 52, 52, 0, "AIM ITS/04-023:2022 Annex A example **NOT SAME** example corrupt??; BWIPP different encodation", + "1010101010101010101010101010101010101010101010101010" + "1001111110000011100010110111011001110111111001111011" + "1000000101110101100111011011101110011001111001000100" + "1100110100101001111110011111001110000110000111101111" + "1001101110101111110111110010111100011101001000010110" + "1110110010010101001110011111001001011001010001001001" + "1011111001110110111110111010011000101100110010000110" + "1000010111011001010111101110001100011011110011000011" + "1010010110001000100110010010011001000110001111101100" + "1011011010010000111001000111010000010101010000010111" + "1111001000010000010000010011101110011011010011011100" + "1000110001001000001100000111110000001111010011110111" + "1100100011001001011000011011010010110010100000101000" + "1011000000001101110101001110111010000100000100111111" + "1010001011100101001100110011110011100111001010100000" + "1010001110111001100001100111100110001111011001011101" + "1001110101011110011000011010110101111101000110000000" + "1001010111111011101111111111001000100011111111011001" + "1100000100000111010100111010110101110011010011100000" + "1000011000010011111011011110111111100101010110011001" + "1000001000101000011010100011000110110100000100011100" + "1000110110011010111111001111101001001001110000000101" + "1100011111101110000011100010100101111110100101100010" + "1110100000110111110110010111010101111110111110111001" + "1101100110011001001101000011110110101011001001101110" + "1111111111111111111111111111111111111111111111111111" + "1010101010101010101010101010101010101010101010101010" + "1010001100010001001111010111111001010101000110010101" + "1000110000010111111000011011110010101010101000011100" + "1001110110101100101110010111101010011011011011110111" + "1010110000000100101010010010111000010101100001001000" + "1111100001101000011110000111000100111111010100001101" + "1001110010010010000000010011010110010001101101111110" + "1011010010011010100000000111110110010101000100100001" + "1011000111011001111010110010101101100100010010100000" + "1110100011100110001001101111110010111100010010001101" + "1111111010100111111010111010000011100111111010111110" + "1101000000010110010000000110000001010011000001000011" + "1101100101110111000011111011100101000100110001101000" + "1011110111000000000110111111000110000011001101110111" + "1100011000010001101101011011010011100011000010001100" + "1011001111111111110011100111001000001000101001000111" + "1011000101011101100001111010011101011000000000100110" + "1000010011100100111000010110010110010111100010100011" + "1000010111101101110100000010001110000111110010111000" + "1010111010111001011110010111000010010001010111101011" + "1101011010010010011000011010110111000101111000011100" + "1111111000111101110111011111011110101111100100010011" + "1100110000000100110000111011100110101110101011011000" + "1101101101001110001100100111011110110000000010010101" + "1101011000011011100011100010001001010110110010101110" + "1111111111111111111111111111111111111111111111111111" + }, + /* 5*/ { BARCODE_DATAMATRIX, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("price:$439.97"), -1, 3 }, { TU("零售价:¥3149.79"), -1, 29 }, { TU("Preis:444,90 €"), -1, 17 } }, 0, 16, 48, 1, "AIM ITS/04-023:2022 Annex A example price only", + "101010101010101010101010101010101010101010101010" + "100001110110010111001111101001001000110101101111" + "100001011100111101001110111101110011001101011100" + "110010100011100110010101100101101010001101110111" + "100101010111111010110010111000011000011000001110" + "111000011111100110110101110110010001000000001001" + "111001110100011100001100111010100000001100101100" + "100100100000111101000111100000111111000101110111" + "110101111100000101011100100010011101010101001110" + "100101111010010100101111110011010011011010100001" + "110001110001010011101100100000100001010111000000" + "110111110100110011000001110000000100010011100011" + "100001001001011101011100110101010101100000100010" + "101000111110011010011101111110111000001110011011" + "110011100111011000101110100011101100000110010010" + "111111111111111111111111111111111111111111111111" + }, + /* 6*/ { BARCODE_DATAMATRIX, DATA_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("\266"), 1, 0 }, { TU("\266"), 1, 7 }, { TU("\266"), 1, 0 } }, 0, 8, 32, 1, "Standard example + extra seg, data mode", + "10101010101010101010101010101010" + "10000100100011111101000010000011" + "11101100000000101110100001010100" + "11111011110010011011000100011111" + "11000111100111101101010111010110" + "11110110010001111100110110010101" + "11111110000111001100101011000000" + "11111111111111111111111111111111" + }, + /* 7*/ { BARCODE_DATAMATRIX, UNICODE_MODE, -1, -1, -1, { 1, 2, "001001" }, { { TU("A"), -1, 3 }, { TU("B"), -1, 4 }, { TU("C"), -1, 5 } }, 0, 12, 26, 1, "", + "10101010101010101010101010" + "10000100011110000011000101" + "10011100111010100100011000" + "11111100100100001110011111" + "11000010000100110011010100" + "11000000110100010011001001" + "11100000111111010111000000" + "10011101101010000100011101" + "11011000101010010101011000" + "10000100000010000011010001" + "10000011000001110111011000" + "11111111111111111111111111" + }, + }; + int data_size = ARRAY_SIZE(data); + int i, j, seg_count, ret; + struct zint_symbol *symbol; + + 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 + + testStart("test_encode_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + if ((debug & ZINT_DEBUG_TEST_PRINT) && !(debug & ZINT_DEBUG_TEST_LESS_NOISY)) printf("i:%d\n", i); + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, + -1 /*option_1*/, data[i].option_2, data[i].option_3, data[i].output_options, + NULL, 0, debug); + if (data[i].structapp.count) { + symbol->structapp = data[i].structapp; + } + for (j = 0, seg_count = 0; j < 3 && data[i].segs[j].length; j++, seg_count++); + + ret = ZBarcode_Encode_Segs(symbol, data[i].segs, seg_count); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode_Segs ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + char escaped1[4096]; + char escaped2[4096]; + int length = data[i].segs[0].length == -1 ? (int) ustrlen(data[i].segs[0].source) : data[i].segs[0].length; + int length1 = data[i].segs[1].length == -1 ? (int) ustrlen(data[i].segs[1].source) : data[i].segs[1].length; + int length2 = data[i].segs[2].length == -1 ? (int) ustrlen(data[i].segs[2].source) : data[i].segs[2].length; + printf(" /*%3d*/ { %s, %s, %s, %d, %s, { %d, %d, \"%s\" }, { { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d } }, %s, %d, %d, %d, \"%s\",\n", + i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), + testUtilOutputOptionsName(data[i].output_options), + data[i].option_2, testUtilOption3Name(data[i].option_3), + data[i].structapp.index, data[i].structapp.count, data[i].structapp.id, + testUtilEscape((const char *) data[i].segs[0].source, length, escaped, sizeof(escaped)), data[i].segs[0].length, data[i].segs[0].eci, + testUtilEscape((const char *) data[i].segs[1].source, length1, escaped1, sizeof(escaped1)), data[i].segs[1].length, data[i].segs[1].eci, + testUtilEscape((const char *) data[i].segs[2].source, length2, escaped2, sizeof(escaped2)), data[i].segs[2].length, data[i].segs[2].eci, + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].bwipp_cmp, data[i].comment); + testUtilModulesPrint(symbol, " ", "\n"); + printf(" },\n"); + } else { + if (ret < ZINT_ERROR) { + int width, row; + + 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); + + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d\n", i, ret, width, row); + + 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 { + ret = testUtilBwippSegs(i, symbol, -1, data[i].option_2, -1, 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); + 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, data[i].expected); + } + } + if (do_zxingcpp && testUtilCanZXingCPP(i, symbol, (const char *) data[i].segs[0].source, data[i].segs[0].length, debug)) { + if (data[i].input_mode == DATA_MODE) { + if (debug & ZINT_DEBUG_TEST_PRINT) { + printf("i:%d multiple segments in DATA_MODE not currently supported for ZXing-C++ testing (%s)\n", + i, testUtilBarcodeName(symbol->symbology)); + } + } else { + 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, (const char *) data[i].segs[0].source, data[i].segs[0].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 = testUtilZXingCPPCmpSegs(symbol, cmp_msg, cmp_buf, cmp_len, data[i].segs, seg_count, + NULL /*primary*/, escaped, &ret_len); + assert_zero(ret, "i:%d %s testUtilZXingCPPCmpSegs %d != 0 %s\n actual: %.*s\nexpected: %.*s\n", + i, testUtilBarcodeName(symbol->symbology), ret, cmp_msg, cmp_len, cmp_buf, ret_len, escaped); + } + } } } @@ -5281,6 +5568,7 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +#ifdef ZINT_TEST_ENCODING static void test_minimalenc(int index, int debug) { struct item { @@ -6320,7 +6608,7 @@ static void test_minimalenc(int index, int debug) { struct zint_symbol *symbol; unsigned char binary[2][2200]; - int inputlen; + int gs1; int binlen; int binlens[2] = {0}; @@ -6336,18 +6624,18 @@ static void test_minimalenc(int index, int debug) { length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, data[i].output_options, data[i].data, data[i].length, debug); - inputlen = length; binlen = 0; symbol->input_mode |= FAST_MODE; - ret = dm_encode(symbol, (unsigned char *) data[i].data, binary[0], &inputlen, &binlen); + gs1 = (symbol->input_mode & 0x07) != GS1_MODE ? 0 : (symbol->output_options & GS1_GS_SEPARATOR) ? 2 : 1; + ret = dm_encode(symbol, (unsigned char *) data[i].data, length, symbol->eci, 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; - inputlen = length; binlen = 0; symbol->input_mode &= ~FAST_MODE; - ret = dm_encode(symbol, (unsigned char *) data[i].data, binary[1], &inputlen, &binlen); + gs1 = (symbol->input_mode & 0x07) != GS1_MODE ? 0 : (symbol->output_options & GS1_GS_SEPARATOR) ? 2 : 1; + ret = dm_encode(symbol, (unsigned char *) data[i].data, length, symbol->eci, 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; @@ -6371,6 +6659,7 @@ static void test_minimalenc(int index, int debug) { testFinish(); } +#endif #include @@ -6554,7 +6843,10 @@ int main(int argc, char *argv[]) { { "test_reader_init", test_reader_init, 1, 1, 1 }, { "test_input", test_input, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_encode_segs", test_encode_segs, 1, 1, 1 }, +#ifdef ZINT_TEST_ENCODING { "test_minimalenc", test_minimalenc, 1, 0, 1 }, +#endif { "test_perf", test_perf, 1, 0, 1 }, }; diff --git a/backend/tests/test_dotcode.c b/backend/tests/test_dotcode.c index 6f1bbf56..1e93499b 100644 --- a/backend/tests/test_dotcode.c +++ b/backend/tests/test_dotcode.c @@ -148,62 +148,70 @@ static void test_input(int index, int generate, int debug) { struct item { int input_mode; int eci; + int option_2; + int option_3; struct zint_structapp structapp; char *data; int length; int ret; char *expected; + int bwipp_cmp; char *comment; }; struct item data[] = { - /* 0*/ { UNICODE_MODE, -1, { 0, 0, "" }, "A", -1, 0, "66 21", "" }, - /* 1*/ { UNICODE_MODE, 3, { 0, 0, "" }, "A", -1, 0, "6C 03 66 21", "" }, - /* 2*/ { UNICODE_MODE, 40, { 0, 0, "" }, "A", -1, 0, "6C 28 00 00 66 21", "" }, - /* 3*/ { UNICODE_MODE, 113, { 0, 0, "" }, "A", -1, 0, "6C 28 00 49 66 21", "" }, - /* 4*/ { UNICODE_MODE, 899, { 0, 0, "" }, "A", -1, 0, "6C 28 07 44 66 21", "" }, - /* 5*/ { UNICODE_MODE, 12769, { 0, 0, "" }, "A", -1, 0, "6C 28 70 49 66 21", "" }, - /* 6*/ { UNICODE_MODE, 811799, { 0, 0, "" }, "A", -1, 0, "6C 67 40 50 66 21", "" }, - /* 7*/ { UNICODE_MODE, 811800, { 0, 0, "" }, "A", -1, ZINT_ERROR_INVALID_OPTION, "Error 525: Invalid ECI", "" }, - /* 8*/ { UNICODE_MODE, -1, { 0, 0, "" }, "\000", 1, 0, "65 40", "LatchA (0x65) NUL" }, - /* 9*/ { UNICODE_MODE, -1, { 0, 0, "" }, "\010", -1, 0, "65 48", "LatchA (0x65) BS" }, - /* 10*/ { UNICODE_MODE, -1, { 0, 0, "" }, "\011", -1, 0, "65 49", "Lead special; LatchA (0x65) HT" }, - /* 11*/ { UNICODE_MODE, -1, { 0, 0, "" }, "\034", -1, 0, "65 5C", "Lead special; LatchA (0x65) FS" }, - /* 12*/ { UNICODE_MODE, -1, { 0, 0, "" }, "\035", -1, 0, "65 5D", "Lead special; LatchA (0x65) GS" }, - /* 13*/ { UNICODE_MODE, -1, { 0, 0, "" }, "\036", -1, 0, "65 5E", "Lead special; LatchA (0x65) RS" }, - /* 14*/ { UNICODE_MODE, -1, { 0, 0, "" }, "\037", -1, 0, "65 5F", "LatchA (0x65) US" }, - /* 15*/ { UNICODE_MODE, -1, { 0, 0, "" }, "\177", -1, 0, "66 5F", "ShiftB (0x66) DEL" }, - /* 16*/ { UNICODE_MODE, -1, { 0, 0, "" }, "[)>\03605\035A\036\004", -1, 0, "6A 61 21", "[)>RS 05 GS A RS EOT; LatchB (0x6A) Macro97 (0x61) A" }, - /* 17*/ { UNICODE_MODE, -1, { 0, 0, "" }, "[)>\03606\035\011\034\035\036\036\004", -1, 0, "6A 62 61 62 63 64", "[)>RS 06 GS HT FS GS RS RS EOT; LatchB (0x6A) Macro98 (0x62) HT FS GS RS" }, - /* 18*/ { UNICODE_MODE, -1, { 0, 0, "" }, "[)>\03612\03512345\036\004", -1, 0, "6A 63 11 67 17 2D", "[)>RS 12 GS A RS EOT; LatchB (0x6A) Macro99 (0x63) 1 2xShiftC (0x67) 23 45" }, - /* 19*/ { UNICODE_MODE, -1, { 0, 0, "" }, "[)>\03601Blah\004", -1, 0, "6A 64 10 11 22 4C 41 48", "[)>RS 01 Blah EOT; LatchB (0x6A) Macro100 (0x64) 0 1 B l a h" }, - /* 20*/ { UNICODE_MODE, -1, { 0, 0, "" }, "[)>\03605\035A\004", -1, 0, "6A 64 10 15 63 21", "[)>RS 05 GS A EOT; LatchB (0x6A) Macro100 (0x64) 0 5 HT A" }, - /* 21*/ { UNICODE_MODE, -1, { 0, 0, "" }, "[)>\03606A\004", -1, 0, "6A 64 10 16 21", "[)>RS 06 A EOT; LatchB (0x6A) Macro100 (0x64) 0 6 A" }, - /* 22*/ { UNICODE_MODE, -1, { 0, 0, "" }, "[)>\036991\036\004", -1, 0, "6A 64 19 19 11 64", "[)>RS 99 1 RS EOT; LatchB (0x6A) Macro100 (0x64) 9 9 1 RS" }, - /* 23*/ { UNICODE_MODE, -1, { 0, 0, "" }, "1712345610", -1, 0, "6B 64 0C 22 38", "FNC1 (0x6B) 17..10 12 34 56" }, - /* 24*/ { GS1_MODE, -1, { 0, 0, "" }, "[17]123456[10]123", -1, ZINT_WARN_NONCOMPLIANT, "64 0C 22 38 0C 66 13", "17..10 12 34 56 12 ShiftB (0x66) 3" }, - /* 25*/ { GS1_MODE, -1, { 0, 0, "" }, "[90]ABC[90]abc[90]123", -1, 0, "5A 6A 21 22 23 6B 19 10 41 42 43 6B 19 67 01 17", "90 LatchB (0x6A) A B C FNC1 (0x6B) 9 0 a b c FNC1 (0x6B) 9 2xShitfC (0x67) 01 23" }, - /* 26*/ { GS1_MODE | GS1PARENS_MODE, -1, { 0, 0, "" }, "(90)ABC(90)abc(90)123", -1, 0, "5A 6A 21 22 23 6B 19 10 41 42 43 6B 19 67 01 17", "90 LatchB (0x6A) A B C FNC1 (0x6B) 9 0 a b c FNC1 (0x6B) 9 2xShitfC (0x67) 01 23" }, - /* 27*/ { UNICODE_MODE, -1, { 0, 0, "" }, "99aA[{00\000", 9, 0, "6B 63 6A 41 21 3B 5B 10 10 65 40", "FNC1 (0x6B) 99 LatchB (0x6A) a A [ { 0 0 ShiftA (0x65) NUL" }, - /* 28*/ { UNICODE_MODE, -1, { 0, 0, "" }, "\015\012", -1, 0, "66 60", "ShiftB (0x66) CR/LF" }, - /* 29*/ { UNICODE_MODE, -1, { 0, 0, "" }, "A\015\012", -1, 0, "67 21 60", "2xShiftB (0x67) A CR/LF" }, - /* 30*/ { UNICODE_MODE, -1, { 0, 0, "" }, "\015\015\012", -1, 0, "65 4D 4D 4A", "LatchA (0x65) CR CR LF" }, - /* 31*/ { UNICODE_MODE, -1, { 0, 0, "" }, "ABCDE12345678", -1, 0, "6A 21 22 23 24 25 69 0C 22 38 4E", "LatchB (0x6A) A B C D 4xShiftC 12 34 56 78" }, - /* 32*/ { UNICODE_MODE, -1, { 0, 0, "" }, "\000ABCD1234567890", 15, 0, "65 40 21 22 23 24 6A 0C 22 38 4E 5A", "LatchA (0x65) NULL A B C D LatchC (0x6A) 12 34 56 78 90" }, - /* 33*/ { DATA_MODE, -1, { 0, 0, "" }, "\141\142\143\144\145\200\201\202\203\204\377", -1, 0, "6A 41 42 43 44 45 70 31 5A 35 21 5A 5F 02 31", "LatchB (0x6A) a b c d e BinaryLatch (0x70) 0x80 0x81 0x82 0x83 0x84 0xFF" }, - /* 34*/ { DATA_MODE, -1, { 0, 0, "" }, "\200\061\062\240\063\064\201\202\065\066", -1, 0, "6E 40 0C 6F 00 22 70 03 10 42 6E 15 16", "UpperShiftA (0x6E) NUL 12 UpperShiftB (0x6F) SP 34 BinaryLatch (0x70) 0x81 0x82 TermB (0x6E) 5 6" }, - /* 35*/ { DATA_MODE, -1, { 0, 0, "" }, "\200\201\202\203\061\062\063\064", -1, 0, "70 13 56 0A 59 2C 67 0C 22", "BinaryLatch (0x70) 0x80 0x81 0x82 0x83 Intr2xShiftC (0x67) 12 3" }, - /* 36*/ { DATA_MODE, -1, { 0, 0, "" }, "\001\200\201\202\203\204\200\201\202\203\204", -1, 0, "65 41 70 31 5A 35 21 5A 5F 31 5A 35 21 5A 5F", "LatchA (0x65) SOH BinaryLatch (0x70) 0x80 0x81 0x82 0x83 0x80 0x81 0x82 0x83" }, - /* 37*/ { UNICODE_MODE, -1, { 0, 0, "" }, "\001abc\011\015\012\036", -1, 0, "65 41 65 41 42 43 61 60 64", "LatchA (0x65) SOH 6xShiftB (0x65) a b c HT CR/LF RS" }, - /* 38*/ { UNICODE_MODE, -1, { 35, 35, "" }, "ABCDE", -1, 0, "6A 21 22 23 24 25 3A 3A 6C", "LatchB (0x6A) A B C D E Z Z FNC2" }, - /* 39*/ { UNICODE_MODE, -1, { 9, 10, "" }, "1234567890", -1, 0, "6B 0C 22 38 4E 5A 65 19 21 6C", "FNC1 (0x6B) 12 34 56 78 90 LatchA (0x65) 9 A FNC2" }, - /* 40*/ { UNICODE_MODE, -1, { 2, 3, "" }, "\001\002\003\004", -1, 0, "65 41 42 43 44 12 13 6C", "LatchA (0x65) 2 3 FNC2" }, - /* 41*/ { DATA_MODE, -1, { 1, 34, "" }, "\200\201\202\203", -1, 0, "70 13 56 0A 59 2C 6D 11 39 6C", "BinaryLatch (0x70) (...) TermA (0x6D) 1 Y FNC2" }, + /* 0*/ { UNICODE_MODE, -1, 13, -1, { 0, 0, "" }, "A", -1, 0, "66 21 6A", 1, "" }, + /* 1*/ { UNICODE_MODE, 3, -1, -1, { 0, 0, "" }, "A", -1, 0, "6C 03 66 21", 1, "" }, + /* 2*/ { UNICODE_MODE, 40, 18, -1, { 0, 0, "" }, "A", -1, 0, "6C 28 00 00 66 21", 1, "" }, + /* 3*/ { UNICODE_MODE, 113, 18, -1, { 0, 0, "" }, "A", -1, 0, "6C 28 00 49 66 21", 1, "" }, + /* 4*/ { UNICODE_MODE, 899, 18, -1, { 0, 0, "" }, "A", -1, 0, "6C 28 07 44 66 21", 1, "" }, + /* 5*/ { UNICODE_MODE, 12769, 18, 8 << 8, { 0, 0, "" }, "A", -1, 0, "6C 28 70 49 66 21", 1, "" }, + /* 6*/ { UNICODE_MODE, 811799, 18, -1, { 0, 0, "" }, "A", -1, 0, "6C 67 40 50 66 21", 1, "" }, + /* 7*/ { UNICODE_MODE, 811800, -1, -1, { 0, 0, "" }, "A", -1, ZINT_ERROR_INVALID_OPTION, "Error 525: Invalid ECI", 1, "" }, + /* 8*/ { UNICODE_MODE, -1, 13, -1, { 0, 0, "" }, "\000", 1, 0, "65 40 6A", 1, "LatchA (0x65) NUL PAD" }, + /* 9*/ { UNICODE_MODE, -1, 13, -1, { 0, 0, "" }, "\010", -1, 0, "65 48 6A", 1, "LatchA (0x65) BS PAD" }, + /* 10*/ { UNICODE_MODE, -1, 13, -1, { 0, 0, "" }, "\011", -1, 0, "65 49 6A", 1, "Lead special; LatchA (0x65) HT PAD" }, + /* 11*/ { UNICODE_MODE, -1, 13, -1, { 0, 0, "" }, "\034", -1, 0, "65 5C 6A", 1, "Lead special; LatchA (0x65) FS PAD" }, + /* 12*/ { UNICODE_MODE, -1, 13, -1, { 0, 0, "" }, "\035", -1, 0, "65 5D 6A", 1, "Lead special; LatchA (0x65) GS PAD" }, + /* 13*/ { UNICODE_MODE, -1, 13, -1, { 0, 0, "" }, "\036", -1, 0, "65 5E 6A", 1, "Lead special; LatchA (0x65) RS PAD" }, + /* 14*/ { UNICODE_MODE, -1, 13, -1, { 0, 0, "" }, "\037", -1, 0, "65 5F 6A", 1, "LatchA (0x65) US PAD" }, + /* 15*/ { UNICODE_MODE, -1, 13, -1, { 0, 0, "" }, "\177", -1, 0, "66 5F 6A", 1, "ShiftB (0x66) DEL PAD" }, + /* 16*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "[)>\03605\035A\036\004", -1, 0, "6A 61 21", 1, "[)>RS 05 GS A RS EOT; LatchB (0x6A) Macro97 (0x61) A" }, + /* 17*/ { UNICODE_MODE, -1, 17, -1, { 0, 0, "" }, "[)>\03606\035\011\034\035\036\036\004", -1, 0, "6A 62 61 62 63 64 6A", 1, "[)>RS 06 GS HT FS GS RS RS EOT; LatchB (0x6A) Macro98 (0x62) HT FS GS RS PAD" }, + /* 18*/ { UNICODE_MODE, -1, 17, -1, { 0, 0, "" }, "[)>\03612\03512345\036\004", -1, 0, "6A 63 11 67 17 2D 6A", 1, "[)>RS 12 GS A RS EOT; LatchB (0x6A) Macro99 (0x63) 1 2xShiftC (0x67) 23 45 PAD" }, + /* 19*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "[)>\03601Blah\004", -1, 0, "6A 64 10 11 22 4C 41 48 6A", 1, "[)>RS 01 Blah EOT; LatchB (0x6A) Macro100 (0x64) 0 1 B l a h PAD" }, + /* 20*/ { UNICODE_MODE, -1, 22, -1, { 0, 0, "" }, "[)>\03605\035A\004", -1, 0, "65 3B 09 1E 5E 10 15 5D 21 44", 1, "NOTE: no longer using Macro for malformed 05/06/12" }, + /* 21*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "[)>\03606A\004", -1, 0, "65 3B 09 1E 5E 10 16 21 44", 1, "NOTE: no longer using Macro for malformed 05/06/12" }, + /* 22*/ { UNICODE_MODE, -1, 13, -1, { 0, 0, "" }, "[)>\036991\036\004", -1, 0, "6A 64 19 19 11 64", 1, "[)>RS 99 1 RS EOT; LatchB (0x6A) Macro100 (0x64) 9 9 1 RS" }, + /* 23*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "1712345610", -1, 0, "6B 64 0C 22 38", 1, "FNC1 (0x6B) 17..10 12 34 56" }, + /* 24*/ { GS1_MODE, -1, -1, -1, { 0, 0, "" }, "[17]123456[10]123", -1, ZINT_WARN_NONCOMPLIANT, "64 0C 22 38 0C 66 13", 0, "17..10 12 34 56 12 ShiftB (0x66) 3; BWIPP does not allow bad month" }, + /* 25*/ { GS1_MODE, -1, -1, -1, { 0, 0, "" }, "[90]ABC[90]abc[90]123", -1, 0, "5A 6A 21 22 23 6B 19 10 41 42 43 6B 19 67 01 17 6A", 1, "90 LatchB (0x6A) A B C FNC1 (0x6B) 9 0 a b c FNC1 (0x6B) 9 2xShitfC (0x67) 01 23 PAD" }, + /* 26*/ { GS1_MODE | GS1PARENS_MODE, -1, -1, -1, { 0, 0, "" }, "(90)ABC(90)abc(90)123", -1, 0, "5A 6A 21 22 23 6B 19 10 41 42 43 6B 19 67 01 17 6A", 1, "90 LatchB (0x6A) A B C FNC1 (0x6B) 9 0 a b c FNC1 (0x6B) 9 2xShitfC (0x67) 01 23 PAD" }, + /* 27*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "99aA[{00\000", 9, 0, "6B 63 6A 41 21 3B 5B 10 10 65 40", 1, "FNC1 (0x6B) 99 LatchB (0x6A) a A [ { 0 0 ShiftA (0x65) NUL" }, + /* 28*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "\015\012", -1, 0, "66 60", 0, "ShiftB (0x66) CR/LF; BWIPP different encodation" }, + /* 29*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A\015\012", -1, 0, "67 21 60", 0, "2xShiftB (0x67) A CR/LF; BWIPP different encodation" }, + /* 30*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "\015\015\012", -1, 0, "65 4D 4D 4A", 1, "LatchA (0x65) CR CR LF" }, + /* 31*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "ABCDE12345678", -1, 0, "6A 21 22 23 24 25 69 0C 22 38 4E", 1, "LatchB (0x6A) A B C D 4xShiftC 12 34 56 78" }, + /* 32*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "\000ABCD1234567890", 15, 0, "65 40 21 22 23 24 6A 0C 22 38 4E 5A 6A", 1, "LatchA (0x65) NULL A B C D LatchC (0x6A) 12 34 56 78 90 PAD" }, + /* 33*/ { DATA_MODE, -1, -1, 2 << 8, { 0, 0, "" }, "\141\142\143\144\145\200\201\202\203\204\377", -1, 0, "6A 41 42 43 44 45 70 31 5A 35 21 5A 5F 02 31", 1, "LatchB (0x6A) a b c d e BinaryLatch (0x70) 0x80 0x81 0x82 0x83 0x84 0xFF" }, + /* 34*/ { DATA_MODE, -1, -1, -1, { 0, 0, "" }, "\200\061\062\240\063\064\201\202\065\066", -1, 0, "6E 40 0C 6F 00 22 70 03 10 42 6E 15 16", 1, "UpperShiftA (0x6E) NUL 12 UpperShiftB (0x6F) SP 34 BinaryLatch (0x70) 0x81 0x82 TermB (0x6E) 5 6" }, + /* 35*/ { DATA_MODE, -1, -1, -1, { 0, 0, "" }, "\200\201\202\203\061\062\063\064", -1, 0, "70 13 56 0A 59 2C 67 0C 22", 1, "BinaryLatch (0x70) 0x80 0x81 0x82 0x83 Intr2xShiftC (0x67) 12 3" }, + /* 36*/ { DATA_MODE, -1, -1, -1, { 0, 0, "" }, "\001\200\201\202\203\204\200\201\202\203\204", -1, 0, "65 41 70 31 5A 35 21 5A 5F 31 5A 35 21 5A 5F", 1, "LatchA (0x65) SOH BinaryLatch (0x70) 0x80 0x81 0x82 0x83 0x80 0x81 0x82 0x83" }, + /* 37*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "\001abc\011\015\012\036", -1, 0, "65 41 65 41 42 43 61 60 64", 1, "LatchA (0x65) SOH 6xShiftB (0x65) a b c HT CR/LF RS" }, + /* 38*/ { UNICODE_MODE, -1, -1, -1, { 35, 35, "" }, "ABCDE", -1, 0, "6A 21 22 23 24 25 3A 3A 6C", 1, "LatchB (0x6A) A B C D E Z Z FNC2" }, + /* 39*/ { UNICODE_MODE, -1, -1, -1, { 9, 10, "" }, "1234567890", -1, 0, "6B 0C 22 38 4E 5A 65 19 21 6C", 1, "FNC1 (0x6B) 12 34 56 78 90 LatchA (0x65) 9 A FNC2" }, + /* 40*/ { UNICODE_MODE, -1, -1, -1, { 2, 3, "" }, "\001\002\003\004", -1, 0, "65 41 42 43 44 6A 12 13 6C", 1, "LatchA (0x65) PAD 2 3 FNC2" }, + /* 41*/ { DATA_MODE, -1, -1, -1, { 1, 34, "" }, "\200\201\202\203", -1, 0, "70 13 56 0A 59 2C 6D 11 39 6C", 1, "BinaryLatch (0x70) (...) TermA (0x6D) 1 Y FNC2" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol; char escaped[1024]; + 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 testStart("test_input"); @@ -216,7 +224,9 @@ static void test_input(int index, int generate, int debug) { debug |= ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - length = testUtilSetSymbol(symbol, BARCODE_DOTCODE, data[i].input_mode, data[i].eci, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + length = testUtilSetSymbol(symbol, BARCODE_DOTCODE, data[i].input_mode, data[i].eci, + -1 /*option_1*/, data[i].option_2, data[i].option_3, -1 /*output_options*/, + data[i].data, data[i].length, debug); if (data[i].structapp.count) { symbol->structapp = data[i].structapp; } @@ -225,13 +235,41 @@ static void test_input(int index, int generate, int debug) { assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, %d, { %d, %d, \"%s\" }, \"%s\", %d, %s, \"%s\", \"%s\" },\n", - i, testUtilInputModeName(data[i].input_mode), data[i].eci, + printf(" /*%3d*/ { %s, %d, %d, %d, { %d, %d, \"%s\" }, \"%s\", %d, %s, \"%s\", %d, \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), data[i].eci, data[i].option_2, data[i].option_3, data[i].structapp.index, data[i].structapp.count, data[i].structapp.id, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), - data[i].length, testUtilErrorName(data[i].ret), symbol->errtxt, data[i].comment); + data[i].length, testUtilErrorName(data[i].ret), symbol->errtxt, data[i].bwipp_cmp, data[i].comment); } else { assert_zero(strcmp((char *) symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + + if (ret < ZINT_ERROR) { + 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[200 * 200 + 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[200 * 200 + 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); @@ -955,6 +993,80 @@ static void test_encode(int index, int generate, int debug) { "1000101000001" "0101010101000" }, + /* 47*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, "[)>\03605\035101\036\004", -1, 0, 12, 17, 1, 1, "Macro 05", + "10000010001000101" + "00000001000000010" + "10001010100010001" + "01010000010000000" + "10001010000010001" + "01000000010000010" + "10100010101000001" + "01010100000001010" + "00001000101010101" + "01010001000101000" + "10101010101010101" + "01010001010101010" + }, + /* 48*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, "[)>\03607Text\036\004", -1, 0, 14, 21, 1, 1, "Macro 07 (free form text)", + "100010001000001000101" + "010001000000010101010" + "000010101000100000101" + "010100000000010000000" + "001000100000000000100" + "010101010001010101010" + "101010101010100010100" + "010000010101000000000" + "001010001000001010001" + "000000000101010101010" + "001000000010001000001" + "000101000101000100000" + "100010101010100010101" + "000001010100010100000" + }, + /* 49*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, "[)>\03605\035Študentska št.\0352198390\036\004", -1, ZINT_WARN_USES_ECI, 23, 34, 1, 1, "Macro 05 with ECI", + "1010101000100000101000001010000010" + "0101000001000101010100000101000001" + "1000101000101000100010100010001000" + "0000010001010001000100010001010000" + "0000101000100010000010001010101000" + "0001010001000100010000010101010100" + "0000100010100000101010001000001010" + "0100010100010100010000010101000001" + "1010101000100010000010000010001010" + "0101000100000100010001010000010001" + "0010101000100010001000001010101000" + "0100010100010001000101010000010000" + "0000101010100010000010100010100010" + "0101000000000001010001010001000001" + "0010100010000000101010100010100010" + "0101000100010101000100000100010100" + "0010100010000010101000101000001000" + "0001000100000101000100010000010101" + "1000100010100000100010001010100010" + "0101010001000001000101000101000100" + "0010000010001010100010001000001000" + "0100000001000100010001010100010101" + "1010001000001010101000000010101000" + }, + /* 50*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, "[)>\03607Τεχτ\036\004", -1, ZINT_WARN_USES_ECI, 17, 26, 1, 1, "Macro 07 with ECI", + "10001010001000100000101000" + "00010101000101000000010101" + "00100010100000100010001000" + "00010101000101010101000100" + "10101000100010001010000000" + "00000100010100010100000001" + "00001010101000100000001010" + "01010000010001010100010100" + "00000010100010101010000010" + "00010101000101000101000001" + "00101000101000100010001000" + "00010101000100000001010100" + "10100010000010001010001000" + "00010100010100010000010001" + "10001000101000101010001000" + "01000101010100000000000101" + "10100010000010101010000010" + }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -1007,7 +1119,7 @@ static void test_encode(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, -1, data[i].option_2, data[i].option_3, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf)); + 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, data[i].expected); @@ -1039,6 +1151,401 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +static void test_encode_segs(int index, int generate, int debug) { + + struct item { + int input_mode; + int option_2; + int option_3; + struct zint_structapp structapp; + struct zint_seg segs[3]; + int ret; + + int expected_rows; + int expected_width; + int bwipp_cmp; + int zxingcpp_cmp; + char *comment; + char *expected; + }; + // ISS DotCode, Rev 4.0, DRAFT 0.15, TSC Pre-PR #5, MAY 28, 2019 + struct item data[] = { + /* 0*/ { UNICODE_MODE, 18, -1, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 7 }, { TU(""), 0, 0 } }, 0, 13, 18, 1, 1, "ISS DotCode Rev 4.0 13.5 example **NOT SAME** different encodation", + "100000001010101010" + "000100000100010101" + "001010000010101000" + "010101010001010001" + "100010100010000000" + "010100010100000101" + "001000101000000010" + "000001010101000100" + "100010100010000010" + "000001000101000001" + "101000101010100010" + "010100000000010001" + "100000101010000010" + }, + /* 1*/ { UNICODE_MODE, 18, -1, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 13, 18, 1, 1, "ISS DotCode Rev 4.0 13.5 example auto-ECI", + "100000001010101010" + "000100000100010101" + "001010000010101000" + "010101010001010001" + "100010100010000000" + "010100010100000101" + "001000101000000010" + "000001010101000100" + "100010100010000010" + "000001000101000001" + "101000101010100010" + "010100000000010001" + "100000101010000010" + }, + /* 2*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("Ж"), -1, 7 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, 0, 14, 21, 1, 1, "ISS DotCode Rev 4.0 13.5 example inverted", + "100010001010101010000" + "000100000101000001010" + "101000101000001000101" + "000001010100000101000" + "001010101010100010001" + "010001000001010101000" + "101000101000101010100" + "010101010001010001000" + "100010001000000000100" + "010100000001000100010" + "001000100010000000101" + "000000000100010100010" + "100010001000100000001" + "010101000100010001000" + }, + /* 3*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("Ж"), -1, 0 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 14, 21, 1, 1, "ISS DotCode Rev 4.0 13.5 example inverted auto-ECI", + "100010001010101010000" + "000100000101000001010" + "101000101000001000101" + "000001010100000101000" + "001010101010100010001" + "010001000001010101000" + "101000101000101010100" + "010101010001010001000" + "100010001000000000100" + "010100000001000100010" + "001000100010000000101" + "000000000100010100010" + "100010001000100000001" + "010101000100010001000" + }, + /* 4*/ { UNICODE_MODE, 95, -1, { 0, 0, "" }, { { TU("product:Google Pixel 4a - 128 GB of Storage - Black;price:$439.97"), -1, 3 }, { TU("品名:Google 谷歌 Pixel 4a -128 GB的存储空间-黑色;零售价:¥3149.79"), -1, 29 }, { TU("Produkt:Google Pixel 4a - 128 GB Speicher - Schwarz;Preis:444,90 €"), -1, 17 } }, 0, 64, 95, 0, 1, "AIM ITS/04-023:2022 Annex A example; BWIPP different encodation", + "10101000100000001010000000101000101010100010001010000010001000101000101000001000001000100010101" + "00000101010001010000010101000000010100000001010101000101010100010101000101000100000100000100000" + "10100010100010001000100000001010100000001000101000101010001010001010000000101000001000101000101" + "01010001000100000000000001010000010100010101010100010001010001010000010000010000010100010000010" + "10000010101000100000001010000010000000000000000000100010100010100000101010001000000010001000000" + "00010100000101000001010100000101010101010000010001010100000100010101010001010101000101000000010" + "10001010001010101010000010001010000010101000001000101000001000101000100010101010001000000010100" + "00010100010100010101000000010001010101000101000101010001010101000000000101010001010100000101000" + "10100000000000000000101000100010101010001000101010001010101010000000000010000000100010101010001" + "01000100010001010001000000000000000001000100000100000001010100010100010001010001010101010100010" + "00101000101010101000000010101000001010001010100010101000000000101010101000101010101010100000101" + "00000101010101010100010001010101000101010000010001010001000001010101000100000100000001010001010" + "00101010000010101000101000100000101000100010001000101000101010000010100010100000001000001010101" + "01000000010001000101010100000100000000010101000100000100010000010000010100000101000100000001010" + "00001010101000101000100000001000001010100010000010101010100000101010100010000000100010001000001" + "01010101010101010100000000010100010000010101000101010100000101010000000000010000010100010101000" + "10000000001010000010101000100010000010100000100000100010100010000000101010101010100010000000100" + "00010000000000010001010101000101010101000000010100000100010001000101010101010001000001010101010" + "10100000100000101010101010100000100010101010100010000010001010100010100010000010100000001010001" + "01000001010000000101010001010001000001010100010000000100000000000001000100000100000101000101010" + "10000010101010100010001010101010000000000010101000101010000000101000001000101010101010100000100" + "00010101000100000100000101010000010100010001000001010100000100010101010001010101010001010001010" + "00001010101000000010000010001010001000101000100000000000001010000000001000001010000000100010100" + "01000001000101000101010000000101010101010101000001000001010101000101010100010001010000010000000" + "10101010000010001000000000000000101010001010001010001000100000100010101010101000101010101010000" + "01010100000101010000010101010001000101000100010101000100010001010001010101000000010101010101000" + "00100010101000100010100010101000101000001000001010001010001010001010100000100010000010100010001" + "00000000010100010001000000000100010000010000010101000001000001000101000101010100010100010100000" + "10100000101010001000001000101010100000100000101000100010100000101000001000100000101000001010000" + "00010101000101000101010101000101000001000001000000010001010100000100000100000101010000000101010" + "00100000000010100010101010101010101000100010100010100010001010100010001000101010101000100010000" + "01000100010000010000000101000101010100000100010100010101000101010001010001000100010100000000010" + "10001000001000001010101010000000001010101000101010000000100010001010000010001000101010100000101" + "01010101000001000100000001010000010100010100000101000000010100000000000000010101000001010001000" + "00001010100000000000001000100010100010101010000000001000100000001010100010000010000000001010001" + "01010101000101000001010100010000000001010100000100010101000101010101010001010000010101000100000" + "00001010001000101000000000001010101010000010001000101010001000101000101010001000000010100010101" + "00010001010000010100000000000101000001010001000101010101010001010101010101000101010100000101010" + "10101000100010000000101010100010000000001010100010101010001010000010101000101010001010100010101" + "01000100010000010101000101010000010101000101010001010001000001000000000000010101010101010001010" + "10000010001000100010100010101000001010100010001010000000101000101010000010000010100010001000100" + "01010000010101010101010100000001010100010000010000000000010100010100000100000000000001010000010" + "00100000000010101010001000001010001010001000101010101010101010001000100010101000001000001000100" + "00000100000101010001010101010100000001010101010000000100010100010001010001010101000001000101000" + "00001010001010001010000000100000100000101000101000101000100010101010101000000010101000101000101" + "01010101010001010100000000010001000001010001010101010101010100000001000000010101000101010100000" + "10100010101000101010101010100010100000000010100000000010001000100010001010001000101010001010001" + "01010001010000000001010101010101010100000101010001000100000001010000010100000000000101000001010" + "00001010100010101000101010001000101000101010001010101010001000100000001010100000100000101010100" + "00000001000101000101010001010001000001000001010101010101000000000101010101010000010000010000010" + "10100000000010101000001000000000000010001010100010001000001010000000000000001000000010101000000" + "00000100000100000100000000000100010100000100010000000000010000000101010001000001010101010101000" + "00101000101000000010000000001000101010100000000010100010100010001010101010101010001010000000100" + "01000101010000010000010100000001010100010001000001010101000101010100000101000101010100010100000" + "10101010101010000010100010101010000000000010001000100000001000100000100000100010100010101000101" + "01010000010001010001010100000101010001010001000101010001000101010000000101010001000000000101010" + "10000000000010101000100010100010101010100000001000101000100010000000100000101010000010100010001" + "00010101010100000001010101010000000101000100000100010001010001000100010000000101010100000001010" + "10101010001010101010001000101010000010101010100010001000100000001000101000000000101000001000001" + "01010100000101010100000000000100010101000101010100000000010101010001010000000100000001000100010" + "10000010100000100000101010001000100000000000100000000010100010001010001010100010100010000010100" + "00010000010101000101010101010101010000010100010000010001010000010100000101000100010000010000000" + "10100000100000001010101010101010001010001010000010100010001010101010000010001010000000100010001" + "01000001000100000101000101010100000000010001000100000101000100000100010101010101000101010100010" + }, + /* 5*/ { DATA_MODE, -1, -1, { 0, 0, "" }, { { TU("\266"), 1, 0 }, { TU("\266"), 1, 7 }, { TU("\266"), 1, 0 } }, 0, 15, 22, 1, 1, "Standard example + extra seg, data mode", + "1000101010000000001000" + "0100000101000101000001" + "1000001000100010101000" + "0000010001000001010101" + "1000100000100010101010" + "0001010000010000010001" + "0010101000101010100010" + "0000010101000101000000" + "1000100010001010100000" + "0101000101000100010100" + "0010100000100000001010" + "0001000101000001010100" + "1010000010100010001010" + "0000010000010000010101" + "1010001010100000101010" + }, + /* 6*/ { UNICODE_MODE, 38, -1, { 0, 0, "" }, { { TU("1234567890β"), -1, 9 }, { TU("1234567890点"), -1, 20 }, { TU("1234567890"), -1, 0 } }, 0, 23, 38, 0, 1, "FNC2 ECI & BIN_LATCH ECI; BWIPP different encodation", + "10000000001010100000101010100000100010" + "00000001010001000001010001010101000100" + "10001010100000101000001010001010101000" + "01000101010001010001000100000000010101" + "00001000100010001010100000101000100000" + "01000101010000010101010001000000010101" + "10001000101000101010000000100010000010" + "01000100010001010001010000010100010001" + "10101000000010001010000010101010000000" + "01010100010000010100010000010000010101" + "00000010100010001010000010000010100010" + "01010000010001010001000101000001010101" + "10000000000010001010101000101000000010" + "00010001010001010100010000010101000101" + "10000010101010101000000010001000100010" + "00000101000101010100010000010100010000" + "00001010101000000010100010001010000010" + "01010001000100000100010001010000010101" + "00001010001010001000000000101010100010" + "01010101010000000100010101010000010100" + "00101010100010000010100010000010000010" + "01010000010100010001010000010000010101" + "10000010100000001010100000100010001010" + }, + /* 7*/ { UNICODE_MODE, 29, -1, { 0, 0, "" }, { { TU("çèéêëì"), -1, 0 }, { TU("òóô"), -1, 899 }, { TU(""), 0, 0 } }, 0, 20, 29, 1, 0, "BIN_LATCH ECI > 0xFF; ZXing-C++ test can't handle binary", + "10001010001010101000000010001" + "01000001000100010100010101010" + "10000000100000100000000010101" + "00010100010001000101010000000" + "10001000000000001010101010101" + "00000100010100010000010101000" + "10001000101000001000100000000" + "01010101000101010101000101010" + "10101010101010000010001010000" + "00000001000001010101010001010" + "10001000000010100000101010101" + "01000001010100010101010100000" + "00000010101000101000000000101" + "01000101000001000100000000000" + "00100010000010100010100000101" + "01010000010101000101010100010" + "10100000100010000010001000001" + "01010101000000000100000001010" + "10101000101010000010001010001" + "01010101010100010001010001010" + }, + /* 8*/ { UNICODE_MODE, 29, -1, { 0, 0, "" }, { { TU("çèéêëì"), -1, 0 }, { TU("òóô"), -1, 65536 }, { TU(""), 0, 0 } }, 0, 22, 29, 1, 0, "BIN_LATCH ECI > 0xFFFF; ZXing-C++ test can't handle binary", + "10101000100000101000001010001" + "00010101000000000100010100000" + "10100010001010000010101010100" + "00010100010101000100010001010" + "00001000001010101010101010101" + "00010000000001000100010100010" + "10001000001010000010000010001" + "00000001010101010000000101010" + "10101010101000001010100010101" + "01000100000100010001010001000" + "10000000000000101010100000001" + "00010101000101000001000001000" + "00101010101000100000001000101" + "00010001010001000101000100010" + "00000000100010100010000000001" + "01000001000100000000010101010" + "10100010100010001010001010101" + "01000100010001010100010100000" + "10101010001000100010100000101" + "01000001000000010001000001000" + "10001010101000101010000010001" + "01010101010101010001010000010" + }, + /* 9*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("[)>\03605\035"), -1, 0 }, { TU("A\036\004"), -1, 0 }, { TU(""), 0, 0 } }, 0, 10, 13, 1, 1, "Macro 05", + "1010001010101" + "0001000001010" + "1010100010001" + "0000000001000" + "1000101000100" + "0101010101000" + "1000001000001" + "0100010000010" + "0000100000100" + "0001010101010" + }, + /* 10*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("[)>\03605\035"), -1, 0 }, { TU("Študentska št."), -1, 4 }, { TU("\0352198390\036\004"), -1, 0 } }, 0, 24, 35, 1, 1, "Macro 05 with ECI", + "10101000000010101000000000101010001" + "00010100000001000000000101010001010" + "00000010001000000010100010001000101" + "00000000010100010101000001010001010" + "00000010101010000000101010100010000" + "00010000000101000101010001000100000" + "10001000000000001010100000001000101" + "01000001010101010100000101010101010" + "00100010000010100010001010101000000" + "00010101010000000001010100010101000" + "00101000100010001000001000100010101" + "00010000010101010000010001010100000" + "10100010101010101010000010000000001" + "01010100000100010100000100000000010" + "10001000100010100010101000001010101" + "01010101010000000101000001000100010" + "10001010101000001010101000001000100" + "01000101010101000101010101010101000" + "10101010101000100010100000000000000" + "01000101010000000000010000000001000" + "00100010001000101000100010101000100" + "01000000000101010101010100000101010" + "10001010000010100000001010000010001" + "01010001000001010001010001010101010" + }, + /* 11*/ { UNICODE_MODE, -1, -1, { 35, 35, "" }, { { TU("Τεχτ"), -1, 9 }, { TU("กขฯ"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 20, 29, 0, 1, "Structured Append with Terminate Latch A replaced", + "10101000001010000000001000101" + "01010101010101000000000100000" + "00101010001010100010101010001" + "01000100010000000101010100010" + "10000010100010001000100000000" + "00010000010101010100000101010" + "10100010101010101010001000001" + "00010101000000010101010001000" + "10000000100000101000101000101" + "01010000010001010001000100010" + "00101000000000100010001010101" + "01000001000101010001000001010" + "00001010000000000000100010101" + "00000101010101000100010001000" + "00101000001010001000001010101" + "01010101010100000100010001000" + "10000000101000100010100010001" + "00000000000000010001010101000" + "10101010001010101010100000001" + "01000101000001010100000100010" + }, + }; + int data_size = ARRAY_SIZE(data); + int i, j, seg_count, ret; + struct zint_symbol *symbol; + + char escaped[1024]; + char cmp_buf[8192]; + char cmp_msg[1024]; + + int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); // Only do BWIPP test if asked, too slow otherwise + int do_zxingcpp = (debug & ZINT_DEBUG_TEST_ZXINGCPP) && testUtilHaveZXingCPPDecoder(); // Only do ZXing-C++ test if asked, too slow otherwise + + testStart("test_encode_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + if ((debug & ZINT_DEBUG_TEST_PRINT) && !(debug & ZINT_DEBUG_TEST_LESS_NOISY)) printf("i:%d\n", i); + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + testUtilSetSymbol(symbol, BARCODE_DOTCODE, data[i].input_mode, -1 /*eci*/, + -1 /* option_1*/, data[i].option_2, data[i].option_3, -1 /*output_options*/, NULL, 0, debug); + if (data[i].structapp.count) { + symbol->structapp = data[i].structapp; + } + for (j = 0, seg_count = 0; j < 3 && data[i].segs[j].length; j++, seg_count++); + + ret = ZBarcode_Encode_Segs(symbol, data[i].segs, seg_count); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode_Segs ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + char escaped1[4096]; + char escaped2[4096]; + int length = data[i].segs[0].length == -1 ? (int) ustrlen(data[i].segs[0].source) : data[i].segs[0].length; + int length1 = data[i].segs[1].length == -1 ? (int) ustrlen(data[i].segs[1].source) : data[i].segs[1].length; + int length2 = data[i].segs[2].length == -1 ? (int) ustrlen(data[i].segs[2].source) : data[i].segs[2].length; + printf(" /*%3d*/ { %s, %d, %s, { %d, %d, \"%s\" }, { { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d } }, %s, %d, %d, %d, %d, \"%s\",\n", + i, testUtilInputModeName(data[i].input_mode), data[i].option_2, testUtilOption3Name(data[i].option_3), + data[i].structapp.index, data[i].structapp.count, data[i].structapp.id, + testUtilEscape((const char *) data[i].segs[0].source, length, escaped, sizeof(escaped)), data[i].segs[0].length, data[i].segs[0].eci, + testUtilEscape((const char *) data[i].segs[1].source, length1, escaped1, sizeof(escaped1)), data[i].segs[1].length, data[i].segs[1].eci, + testUtilEscape((const char *) data[i].segs[2].source, length2, escaped2, sizeof(escaped2)), data[i].segs[2].length, data[i].segs[2].eci, + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].bwipp_cmp, data[i].zxingcpp_cmp, data[i].comment); + testUtilModulesPrint(symbol, " ", "\n"); + printf(" },\n"); + } else { + if (ret < ZINT_ERROR) { + int width, row; + + 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); + + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d\n", i, ret, width, row); + + 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 { + 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); + 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, data[i].expected); + } + } + if (do_zxingcpp && testUtilCanZXingCPP(i, symbol, (const char *) data[i].segs[0].source, data[i].segs[0].length, debug)) { + if (!data[i].zxingcpp_cmp) { + if (debug & ZINT_DEBUG_TEST_PRINT) printf("i:%d %s not ZXing-C++ compatible (%s)\n", i, testUtilBarcodeName(symbol->symbology), data[i].comment); + } else if (data[i].input_mode == DATA_MODE) { + if (debug & ZINT_DEBUG_TEST_PRINT) { + printf("i:%d multiple segments in DATA_MODE not currently supported for ZXing-C++ testing (%s)\n", + i, testUtilBarcodeName(symbol->symbology)); + } + } else { + int cmp_len, ret_len; + char modules_dump[16384]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilZXingCPP(i, symbol, (const char *) data[i].segs[0].source, data[i].segs[0].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 = testUtilZXingCPPCmpSegs(symbol, cmp_msg, cmp_buf, cmp_len, data[i].segs, seg_count, + NULL /*primary*/, escaped, &ret_len); + assert_zero(ret, "i:%d %s testUtilZXingCPPCmpSegs %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); + } + + testFinish(); +} + // #181 Christian Hartlage / Nico Gunkel OSS-Fuzz static void test_fuzz(int index, int debug) { @@ -1238,7 +1745,7 @@ int main(int argc, char *argv[]) { { "test_options", test_options, 1, 0, 1 }, { "test_input", test_input, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 }, - { "test_fuzz", test_fuzz, 1, 0, 1 }, + { "test_encode_segs", test_encode_segs, 1, 1, 1 }, { "test_fuzz", test_fuzz, 1, 0, 1 }, { "test_generate", test_generate, 0, 1, 0 }, { "test_perf", test_perf, 1, 0, 1 }, diff --git a/backend/tests/test_eci.c b/backend/tests/test_eci.c index d12f5da6..fcb84abe 100644 --- a/backend/tests/test_eci.c +++ b/backend/tests/test_eci.c @@ -177,7 +177,7 @@ static void test_reduced_charset_input(int index, int debug) { /* 38*/ { BARCODE_PDF417, UNICODE_MODE, 12, "Ĩ", 0, 12, "In ISO 8859-10; Note no characters in ISO 8859-10 that aren't also in earlier ISO pages" }, /* 39*/ { BARCODE_PDF417, UNICODE_MODE, 0, "ก", ZINT_WARN_USES_ECI, 13, "" }, /* 40*/ { BARCODE_PDF417, UNICODE_MODE, 13, "ก", 0, 13, "" }, - /* 41*/ { BARCODE_PDF417, UNICODE_MODE, 14, "A", ZINT_ERROR_INVALID_DATA, -1, "Reserved ECI" }, + /* 41*/ { BARCODE_PDF417, UNICODE_MODE, 14, "A", ZINT_ERROR_INVALID_OPTION, -1, "Reserved ECI" }, /* 42*/ { BARCODE_PDF417, UNICODE_MODE, 0, "„", ZINT_WARN_USES_ECI, 15, "" }, /* 43*/ { BARCODE_PDF417, UNICODE_MODE, 15, "„", 0, 15, "In ISO 8859-13 and ISO 8859-16 and Win 125x pages" }, /* 44*/ { BARCODE_PDF417, UNICODE_MODE, 0, "Ḃ", ZINT_WARN_USES_ECI, 16, "In ISO 8859-14 only of single-byte pages" }, @@ -186,7 +186,7 @@ static void test_reduced_charset_input(int index, int debug) { /* 47*/ { BARCODE_PDF417, UNICODE_MODE, 0, "Ș", ZINT_WARN_USES_ECI, 18, "In ISO 8859-16 only of single-byte pages" }, /* 48*/ { BARCODE_PDF417, UNICODE_MODE, 18, "Ș", 0, 18, "" }, /* 49*/ { BARCODE_PDF417, UNICODE_MODE, 0, "テ", ZINT_WARN_USES_ECI, 26, "Not in any single-byte page" }, - /* 50*/ { BARCODE_PDF417, UNICODE_MODE, 19, "A", ZINT_ERROR_INVALID_DATA, -1, "Reserved ECI" }, + /* 50*/ { BARCODE_PDF417, UNICODE_MODE, 19, "A", ZINT_ERROR_INVALID_OPTION, -1, "Reserved ECI" }, /* 51*/ { BARCODE_PDF417, UNICODE_MODE, 20, "テ", 0, 20, "In Shift JIS" }, /* 52*/ { BARCODE_PDF417, UNICODE_MODE, 20, "テテ", 0, 20, "In Shift JIS" }, /* 53*/ { BARCODE_PDF417, UNICODE_MODE, 20, "\\\\", 0, 20, "In Shift JIS" }, @@ -742,6 +742,12 @@ static void test_utf8_to_eci_ascii(void) { /* 15*/ { 170, "}", -1, ZINT_ERROR_INVALID_DATA }, /* 16*/ { 170, "~", -1, ZINT_ERROR_INVALID_DATA }, /* 17*/ { 170, "\302\200", -1, ZINT_ERROR_INVALID_DATA }, + /* 18*/ { 170, "~", -1, ZINT_ERROR_INVALID_DATA }, + /* 19*/ { 1, "A", -1, ZINT_ERROR_INVALID_DATA }, + /* 20*/ { 2, "A", -1, ZINT_ERROR_INVALID_DATA }, + /* 21*/ { 14, "A", -1, ZINT_ERROR_INVALID_DATA }, + /* 22*/ { 19, "A", -1, ZINT_ERROR_INVALID_DATA }, + /* 23*/ { 26, "A", -1, ZINT_ERROR_INVALID_DATA }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -1177,6 +1183,138 @@ static void test_utf8_to_eci_euc_kr(void) { } } +static void test_utf8_to_eci_gbk(void) { + + struct item { + char *data; + int length; + int ret; + int expected_length; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037", 32, 0, 32 }, + /* 1*/ { " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\177", 96, 0, 96 }, + /* 2*/ { "\302\200", -1, ZINT_ERROR_INVALID_DATA, -1 }, // No mapping for U+0080 + /* 3*/ { "\343\200\200", -1, 0, 2 }, // U+3000 IDEOGRAPHIC SPACE + /* 4*/ { "\357\277\277", -1, ZINT_ERROR_INVALID_DATA, -1 }, // No mapping for U+FFFF + /* 5*/ { "\357\277\276", -1, ZINT_ERROR_INVALID_DATA, -1 }, // U+FFFE (reversed BOM) not allowed + /* 6*/ { "\355\240\200", -1, ZINT_ERROR_INVALID_DATA, -1 }, // U+D800 surrogate not allowed + }; + int data_size = ARRAY_SIZE(data); + int i, length, ret; + const int eci = 31; + + testStart("test_utf8_to_eci_gbk"); + + for (i = 0; i < data_size; i++) { + int out_length, eci_length; + char dest[1024]; + + length = data[i].length != -1 ? data[i].length : (int) strlen(data[i].data); + out_length = length; + eci_length = get_eci_length(eci, (const unsigned char *) data[i].data, length); + + assert_nonzero(eci_length + 1 <= 1024, "i:%d eci_length %d + 1 > 1024\n", i, eci_length); + ret = utf8_to_eci(eci, (const unsigned char *) data[i].data, (unsigned char *) dest, &out_length); + assert_equal(ret, data[i].ret, "i:%d utf8_to_eci ret %d != %d\n", i, ret, data[i].ret); + if (ret == 0) { + assert_equal(out_length, data[i].expected_length, "i:%d length %d != %d\n", i, out_length, data[i].expected_length); + assert_nonzero(out_length <= eci_length, "i:%d out_length %d > eci_length %d\n", i, out_length, eci_length); + } + } +} + +static void test_utf8_to_eci_gb18030(void) { + + struct item { + char *data; + int length; + int ret; + int expected_length; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037", 32, 0, 32 }, + /* 1*/ { " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\177", 96, 0, 96 }, + /* 2*/ { "\302\200", -1, 0, 4 }, // Has mapping for U+0080 + /* 3*/ { "\343\200\200", -1, 0, 2 }, // U+3000 IDEOGRAPHIC SPACE + /* 4*/ { "\357\277\277", -1, 0, 4 }, // Has mapping for U+FFFF + /* 5*/ { "\357\277\276", -1, 0, 4 }, // U+FFFE (reversed BOM) allowed + /* 6*/ { "\355\240\200", -1, ZINT_ERROR_INVALID_DATA, -1 }, // U+D800 surrogate not allowed + }; + int data_size = ARRAY_SIZE(data); + int i, length, ret; + const int eci = 32; + + testStart("test_utf8_to_eci_gb18030"); + + for (i = 0; i < data_size; i++) { + int out_length, eci_length; + char dest[1024]; + + length = data[i].length != -1 ? data[i].length : (int) strlen(data[i].data); + out_length = length; + eci_length = get_eci_length(eci, (const unsigned char *) data[i].data, length); + + assert_nonzero(eci_length + 1 <= 1024, "i:%d eci_length %d + 1 > 1024\n", i, eci_length); + ret = utf8_to_eci(eci, (const unsigned char *) data[i].data, (unsigned char *) dest, &out_length); + assert_equal(ret, data[i].ret, "i:%d utf8_to_eci ret %d != %d\n", i, ret, data[i].ret); + if (ret == 0) { + assert_equal(out_length, data[i].expected_length, "i:%d length %d != %d\n", i, out_length, data[i].expected_length); + assert_nonzero(out_length <= eci_length, "i:%d out_length %d > eci_length %d\n", i, out_length, eci_length); + } + } +} + +static void test_is_eci_convertible_segs(int index) { + + struct item { + struct zint_seg segs[3]; + int ret; + int expected_convertible[3]; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { { { TU("A"), -1, 0 }, { TU(""), 0, 0 }, { TU(""), 0, 0 } }, 1, { 1, -1, -1 } }, + /* 1*/ { { { TU("A"), -1, 26 }, { TU(""), 0, 0 }, { TU(""), 0, 0 } }, 0, { 0, -1, -1 } }, + /* 2*/ { { { TU("A"), -1, 36 }, { TU(""), 0, 0 }, { TU(""), 0, 0 } }, 0, { 0, -1, -1 } }, + /* 3*/ { { { TU("A"), -1, 170 }, { TU(""), 0, 0 }, { TU(""), 0, 0 } }, 1, { 1, -1, -1 } }, + /* 4*/ { { { TU("A"), -1, 899 }, { TU(""), 0, 0 }, { TU(""), 0, 0 } }, 0, { 0, -1, -1 } }, + /* 5*/ { { { TU("A"), -1, 3 }, { TU(""), 0, 0 }, { TU(""), 0, 0 } }, 1, { 1, -1, -1 } }, + /* 6*/ { { { TU("A"), -1, 899 }, { TU("A"), -1, 0 }, { TU(""), 0, 0 } }, 1, { 0, 1, -1 } }, + /* 7*/ { { { TU("A"), -1, 0 }, { TU("A"), -1, 899 }, { TU(""), 0, 0 } }, 1, { 1, 0, -1 } }, + /* 8*/ { { { TU("A"), -1, 3 }, { TU("A"), -1, 4 }, { TU("A"), -1, 35 } }, 1, { 1, 1, 1 } }, + /* 9*/ { { { TU("A"), -1, 3 }, { TU("A"), -1, 899 }, { TU("A"), -1, 0 } }, 1, { 1, 0, 1 } }, + /* 10*/ { { { TU("A"), -1, 899 }, { TU("A"), -1, 899 }, { TU("A"), -1, 0 } }, 1, { 0, 0, 1 } }, + /* 11*/ { { { TU("A"), -1, 899 }, { TU("A"), -1, 0 }, { TU("A"), -1, 899 } }, 1, { 0, 1, 0 } }, + /* 12*/ { { { TU("A"), -1, 899 }, { TU("A"), -1, 899 }, { TU("A"), -1, 899 } }, 0, { 0, 0, 0 } }, + }; + int data_size = ARRAY_SIZE(data); + int i, j, seg_count, ret; + + int convertible[3]; + + testStart("test_is_eci_convertible_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + for (j = 0, seg_count = 0; j < 3 && data[i].segs[j].length; j++, seg_count++); + + for (j = 0; j < 3; j++) convertible[j] = -1; + + ret = is_eci_convertible_segs(data[i].segs, seg_count, convertible); + assert_equal(ret, data[i].ret, "i:%d is_eci_convertible_segs ret %d != %d\n", i, ret, data[i].ret); + for (j = 0; j < 3; j++) { + assert_equal(convertible[j], data[i].expected_convertible[j], "i:%d is_eci_convertible_segs convertible[%d] %d != %d\n", i, j, convertible[j], data[i].expected_convertible[j]); + } + } + + testFinish(); +} + static void test_get_best_eci(int index) { struct item { @@ -1213,6 +1351,54 @@ static void test_get_best_eci(int index) { testFinish(); } +static void test_get_best_eci_segs(int index) { + + struct item { + struct zint_seg segs[3]; + int ret; + int expected_symbol_eci; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { { { TU("\300\301"), -1, 0 }, { TU(""), -1, 0 }, { TU(""), 0, 0 } }, 0, 0 }, + /* 1*/ { { { TU("A"), -1, 0 }, { TU("\300\301"), -1, 0 }, { TU(""), 0, 0 } }, 0, 0 }, + /* 2*/ { { { TU("A"), -1, 0 }, { TU("ÀÁ"), -1, 0 }, { TU(""), 0, 0 } }, 0, 0 }, // As 1st seg default ECI, 3 not returned + /* 3*/ { { { TU("A"), -1, 4 }, { TU("ÀÁ"), -1, 0 }, { TU(""), 0, 0 } }, 3, 0 }, + /* 4*/ { { { TU("A"), -1, 0 }, { TU("Ђ"), -1, 0 }, { TU(""), 0, 0 } }, 7, 0 }, + /* 5*/ { { { TU("A"), -1, 4 }, { TU("Ђ"), -1, 0 }, { TU(""), 0, 0 } }, 7, 0 }, + /* 6*/ { { { TU("A"), -1, 0 }, { TU("Ђ"), -1, 7 }, { TU("Ѐ"), -1, 0 } }, 26, 0 }, // Cyrillic U+0400 not in single-byte code pages + /* 7*/ { { { TU("A"), -1, 0 }, { TU("Ђ"), -1, 0 }, { TU("β"), -1, 0 } }, 7, 0 }, + /* 8*/ { { { TU("A"), -1, 0 }, { TU("Ђ"), -1, 7 }, { TU("β"), -1, 0 } }, 9, 0 }, + /* 9*/ { { { TU("˜"), -1, 0 }, { TU("Ђ"), -1, 7 }, { TU(""), 0, 0 } }, 23, 23 }, + }; + int data_size = ARRAY_SIZE(data); + int i, j, seg_count, ret; + struct zint_symbol *symbol; + + testStart("test_get_best_eci_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + for (j = 0, seg_count = 0; j < 3 && data[i].segs[j].length; j++, seg_count++); + for (j = 0; j < seg_count; j++) { + if (data[i].segs[j].length < 0) data[i].segs[j].length = (int) ustrlen(data[i].segs[j].source); + } + + ret = get_best_eci_segs(symbol, data[i].segs, seg_count); + assert_equal(ret, data[i].ret, "i:%d get_best_eci_segs ret %d != %d\n", i, ret, data[i].ret); + assert_equal(symbol->eci, data[i].expected_symbol_eci, "i:%d get_best_eci_segs symbol->eci %d != %d\n", i, symbol->eci, data[i].expected_symbol_eci); + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ @@ -1229,7 +1415,11 @@ int main(int argc, char *argv[]) { { "test_utf8_to_eci_big5", test_utf8_to_eci_big5, 0, 0, 0 }, { "test_utf8_to_eci_gb2312", test_utf8_to_eci_gb2312, 0, 0, 0 }, { "test_utf8_to_eci_euc_kr", test_utf8_to_eci_euc_kr, 0, 0, 0 }, + { "test_utf8_to_eci_gbk", test_utf8_to_eci_gbk, 0, 0, 0 }, + { "test_utf8_to_eci_gb18030", test_utf8_to_eci_gb18030, 0, 0, 0 }, + { "test_is_eci_convertible_segs", test_is_eci_convertible_segs, 1, 0, 0 }, { "test_get_best_eci", test_get_best_eci, 1, 0, 0 }, + { "test_get_best_eci_segs", test_get_best_eci_segs, 1, 0, 0 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_gridmtx.c b/backend/tests/test_gridmtx.c index 6cbffd9c..0ed0723d 100644 --- a/backend/tests/test_gridmtx.c +++ b/backend/tests/test_gridmtx.c @@ -34,6 +34,7 @@ static void test_large(int index, int debug) { struct item { int option_2; + int option_3; char *pattern; int length; int ret; @@ -42,21 +43,27 @@ static void test_large(int index, int debug) { }; // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { -1, "1", 2751, 0, 162, 162 }, - /* 1*/ { -1, "1", 2752, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 2*/ { -1, "1", 2755, ZINT_ERROR_TOO_LONG, -1, -1 }, // Triggers buffer > 9191 - /* 3*/ { -1, "A", 1836, 0, 162, 162 }, - /* 4*/ { -1, "A", 1837, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 5*/ { -1, "\200", 1143, 0, 162, 162 }, - /* 6*/ { -1, "\200", 1144, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 7*/ { 1, "1", 18, 0, 18, 18 }, - /* 8*/ { 1, "1", 19, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 9*/ { 1, "A", 13, 0, 18, 18 }, - /* 10*/ { 1, "A", 14, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 11*/ { 1, "\200", 7, 0, 18, 18 }, - /* 12*/ { 1, "\200", 8, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 13*/ { 11, "1", 1995, 0, 138, 138 }, - /* 14*/ { 11, "1", 1996, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 0*/ { -1, -1, "1", 2751, 0, 162, 162 }, + /* 1*/ { -1, -1, "1", 2752, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 2*/ { -1, -1, "1", 2755, ZINT_ERROR_TOO_LONG, -1, -1 }, // Triggers buffer > 9191 + /* 3*/ { -1, -1, "A", 1836, 0, 162, 162 }, + /* 4*/ { -1, -1, "A", 1837, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 5*/ { -1, -1, "A1", 1529, 0, 162, 162 }, + /* 6*/ { -1, -1, "A1", 1530, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 7*/ { -1, -1, "\200", 1143, 0, 162, 162 }, + /* 8*/ { -1, -1, "\200", 1144, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 9*/ { -1, ZINT_FULL_MULTIBYTE, "\241", 1410, 0, 162, 162 }, + /* 10*/ { -1, ZINT_FULL_MULTIBYTE, "\241", 1412, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 11*/ { 1, -1, "1", 18, 0, 18, 18 }, + /* 12*/ { 1, -1, "1", 19, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 13*/ { 1, -1, "A", 13, 0, 18, 18 }, + /* 14*/ { 1, -1, "A", 14, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 15*/ { 1, -1, "\200", 7, 0, 18, 18 }, + /* 16*/ { 1, -1, "\200", 8, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 17*/ { 1, ZINT_FULL_MULTIBYTE, "\241", 8, 0, 18, 18 }, + /* 18*/ { 1, ZINT_FULL_MULTIBYTE, "\241", 10, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 19*/ { 11, -1, "1", 1995, 0, 138, 138 }, + /* 20*/ { 11, -1, "1", 1996, ZINT_ERROR_TOO_LONG, -1, -1 }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -76,7 +83,7 @@ static void test_large(int index, int debug) { testUtilStrCpyRepeat(data_buf, data[i].pattern, data[i].length); assert_equal(data[i].length, (int) strlen(data_buf), "i:%d length %d != strlen(data_buf) %d\n", i, data[i].length, (int) strlen(data_buf)); - length = testUtilSetSymbol(symbol, BARCODE_GRIDMATRIX, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data_buf, data[i].length, debug); + length = testUtilSetSymbol(symbol, BARCODE_GRIDMATRIX, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, data[i].option_3, -1 /*output_options*/, data_buf, data[i].length, debug); 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); @@ -501,6 +508,351 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +static void test_encode_segs(int index, int generate, int debug) { + + struct item { + int input_mode; + int option_1; + int option_2; + struct zint_structapp structapp; + struct zint_seg segs[3]; + int ret; + + int expected_rows; + int expected_width; + char *comment; + char *expected; + }; + struct item data[] = { + /* 0*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 7 }, { TU(""), 0, 0 } }, 0, 30, 30, "Standard example", + "111111000000111111000000111111" + "111101011110111111011110111111" + "100101011110111111011110111111" + "110011000000100001000000100001" + "110011000000100001000000100001" + "111111000000111111000000111111" + "000000111111000000111111000000" + "011100110111010000110001011110" + "010000111111000110111101011110" + "000010100001000110110001000000" + "001000100001001100100001000000" + "000000111111000000111111000000" + "111111000000111111000000111111" + "111101010110101001010000111111" + "101111011110100001000100111111" + "100011000000110111011000100001" + "110111000000100001000000100001" + "111111000000111111000000111111" + "000000111111000000111111000000" + "011110110111010110110001011010" + "010110111111011110100001010000" + "011010100001000000101011011100" + "001000100001000000110001000110" + "000000111111000000111111000000" + "111111000000111111000000111111" + "111001011100111111011000111111" + "100001001100111101001110111011" + "100001001010111011011110100011" + "101011000010100001001110100101" + "111111000000111111000000111111" + }, + /* 1*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 30, 30, "Standard example auto-ECI", + "111111000000111111000000111111" + "111101011110111111011110111111" + "100101011110111111011110111111" + "110011000000100001000000100001" + "110011000000100001000000100001" + "111111000000111111000000111111" + "000000111111000000111111000000" + "011100110111010000110001011110" + "010000111111000110111101011110" + "000010100001000110110001000000" + "001000100001001100100001000000" + "000000111111000000111111000000" + "111111000000111111000000111111" + "111101010110101001010000111111" + "101111011110100001000100111111" + "100011000000110111011000100001" + "110111000000100001000000100001" + "111111000000111111000000111111" + "000000111111000000111111000000" + "011110110111010110110001011010" + "010110111111011110100001010000" + "011010100001000000101011011100" + "001000100001000000110001000110" + "000000111111000000111111000000" + "111111000000111111000000111111" + "111001011100111111011000111111" + "100001001100111101001110111011" + "100001001010111011011110100011" + "101011000010100001001110100101" + "111111000000111111000000111111" + }, + /* 2*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("Ж"), -1, 7 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, 0, 30, 30, "Standard example inverted", + "111111000000111111000000111111" + "111001011110111111011110111111" + "101111011110111111011110111111" + "111101000000100001000000100001" + "101011000000100001000000100001" + "111111000000111111000000111111" + "000000111111000000111111000000" + "011010110111010000110001011110" + "000000111111000000100011011110" + "010000100001001010111011000000" + "011000100001010000110111000000" + "000000111111000000111111000000" + "111111000000111111000000111111" + "111101010110101001010000111111" + "101011011110100011000110111111" + "111001000000111101000000100001" + "101011000000100001000000100001" + "111111000000111111000000111111" + "000000111111000000111111000000" + "011110110111010000110001011000" + "010000111111000000100011011000" + "001110100001001100101101001100" + "001100100001011000100001000000" + "000000111111000000111111000000" + "111111000000111111000000111111" + "111111011110111101011000111111" + "101111011010110001001110111101" + "110011001000101101001010110111" + "111101011000101001011010101001" + "111111000000111111000000111111" + }, + /* 3*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("Ж"), -1, 0 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 30, 30, "Standard example inverted auto-ECI", + "111111000000111111000000111111" + "111001011110111111011110111111" + "101111011110111111011110111111" + "111101000000100001000000100001" + "101011000000100001000000100001" + "111111000000111111000000111111" + "000000111111000000111111000000" + "011010110111010000110001011110" + "000000111111000000100011011110" + "010000100001001010111011000000" + "011000100001010000110111000000" + "000000111111000000111111000000" + "111111000000111111000000111111" + "111101010110101001010000111111" + "101011011110100011000110111111" + "111001000000111101000000100001" + "101011000000100001000000100001" + "111111000000111111000000111111" + "000000111111000000111111000000" + "011110110111010000110001011000" + "010000111111000000100011011000" + "001110100001001100101101001100" + "001100100001011000100001000000" + "000000111111000000111111000000" + "111111000000111111000000111111" + "111111011110111101011000111111" + "101111011010110001001110111101" + "110011001000101101001010110111" + "111101011000101001011010101001" + "111111000000111111000000111111" + }, + /* 4*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("product:Google Pixel 4a - 128 GB of Storage - Black;price:$439.97"), -1, 3 }, { TU("品名:Google 谷歌 Pixel 4a -128 GB的存储空间-黑色;零售价:¥3149.79"), -1, 29 }, { TU("Produkt:Google Pixel 4a - 128 GB Speicher - Schwarz;Preis:444,90 €"), -1, 17 } }, 0, 78, 78, "AIM ITS/04-023:2022 Annex A example", + "111111000000111111000000111111000000111111000000111111000000111111000000111111" + "100101000100100101000110100001000100100101000000100111000010100111000000100001" + "101001011010100111011110101001011100101111001110100001001110111101000110100101" + "101111011000100011001010101111000000110001000100110101001010110111001010111001" + "101011001010110111000010101111011100111011011100101001001100111101000000101101" + "111111000000111111000000111111000000111111000000111111000000111111000000111111" + "000000111111000000111111000000111111000000111111000000111111000000111111000000" + "000000111011011010111001011000111001011010111111011010111111011110111011000100" + "011110101101010010110001000000101111010110111111000000100011011110111111011010" + "010010100001011010110101001010100011010000101001011110110001000010111111001100" + "001000100111000000110011001010111111000000110001011100100001011010101011010100" + "000000111111000000111111000000111111000000111111000000111111000000111111000000" + "111111000000111111000000111111000000111111000000111111000000111111000000111111" + "100101011000110001010110110111010010110111010000110011010110110111011010100011" + "111001010010110001001100111011010100111111001110101111011100111101010110110001" + "111101011110100011000000111001001010100001001010110111000110111111000000101111" + "111111000010110111010000111011001000100011000010110011011100110101000000110001" + "111111000000111111000000111111000000111111000000111111000000111111000000111111" + "000000111111000000111111000000111111000000111111000000111111000000111111000000" + "000100111001010110101101001000101001001000101111001000101011010100111111000110" + "000010111011011000110011011010111011011110101001011100110101011010111111010000" + "010010110001000000111011011110101001010010100011010110111011011110100011001010" + "011110100001000010111111011010110011011010110001011110111111000110101111011110" + "000000111111000000111111000000111111000000111111000000111111000000111111000000" + "111111000000111111000000111111000000111111000000111111000000111111000000111111" + "100101011100110111001100100111000100100101000110100111001110110011011100100111" + "100011010100101111011110110001001110101111010000110001011000111011010010100001" + "111001010110111001000100101111000000110111000100111111000100101101011110101011" + "111101011010100011001010100111000100111111000100101101001010100001011110111111" + "111111000000111111000000111111000000111111000000111111000000111111000000111111" + "000000111111000000111111000000111111000000111111000000111111000000111111000000" + "000010111111010110101101000000111101011000111101000110101111010110111111000000" + "001010111111011100100001010000110001000000100111011110110011011110100011001100" + "010110100111001100101011010110110001010110111101011000111001011100110001010100" + "000010100101011010101001011110110111011100101111010010100001001110100001010100" + "000000111111000000111111000000111111000000111111000000111111000000111111000000" + "111111000000111111000000111111000000111111000000111111000000111111000000111111" + "100101011010110111001100100011011000110101011010100001001010110001011110100011" + "110111011010111011011100100011011100111111010110111111000000110001011110110011" + "110111010000110011001110111001010110101101001000111101010100100011001110110011" + "101111000000111111011000100101010110100001011010110001001000100001011110111111" + "111111000000111111000000111111000000111111000000111111000000111111000000111111" + "000000111111000000111111000000111111000000111111000000111111000000111111000000" + "000110111001010100101101000100111011011010111111000010101101010000111011000000" + "011000111001001010111001010000100101010110111001001110101111001100101101001010" + "011010110101000010110011011010101011000010101101011100111101001010101111010110" + "011010101001001010101101011110111001010010101101000100101001000010100101000100" + "000000111111000000111111000000111111000000111111000000111111000000111111000000" + "111111000000111111000000111111000000111111000000111111000000111111000000111111" + "100001011110110111001000100101000010100011000010100001001010110001011100100011" + "110011011110100001001000100001001010110111010100101101000000110001011110101101" + "110001001110111001001110100111001000101011011100100111000000111011010000100001" + "111011001000101111011010110111011110110011001100111111010000110111000000100111" + "111111000000111111000000111111000000111111000000111111000000111111000000111111" + "000000111111000000111111000000111111000000111111000000111111000000111111000000" + "000110111111010000101001001100101111001100101101001100101111010010111111000010" + "000110100111000000100111011010100001011110101001011010111101011010111111000000" + "001010110001011100100101001110100001011100111001000100101011000100100001001000" + "000000100001010010100011001110111111001110100001000110111111001110100011001010" + "000000111111000000111111000000111111000000111111000000111111000000111111000000" + "111111000000111111000000111111000000111111000000111111000000111111000000111111" + "100001011010110001010100110011010010110111010100110011010010110101011000100011" + "111111010100100111001110111111010010110101011000110011011110111011001010100111" + "111001011110110101011010100111011010110111011100101111001100100001001100100111" + "110011011100111001011100101111000000101011011110111011011010110011010110111001" + "111111000000111111000000111111000000111111000000111111000000111111000000111111" + "000000111111000000111111000000111111000000111111000000111111000000111111000000" + "000000111111011110111101011110111001011010111111011110111111011110111001000010" + "001100111111000000111011011110101101011110111111000000101011011110100001000010" + "010010101111010000110111000000110001010110101001000000110111001010100001000110" + "000100111111000000101111010110100001011110110101000000110101010010100001001000" + "000000111111000000111111000000111111000000111111000000111111000000111111000000" + "111111000000111111000000111111000000111111000000111111000000111111000000111111" + "100111000110100111000110100101000110100101000100100011000100100111000100100011" + "110011011100111011000100100011001010111001000110110101001100110011000110100001" + "111001000010100011001010100001000010100111010110111011000000110101011100110111" + "110111001010111011001010101011001000101111011110111001011010111111010100111111" + "111111000000111111000000111111000000111111000000111111000000111111000000111111" + }, + /* 5*/ { DATA_MODE, -1, -1, { 0, 0, "" }, { { TU("\266"), 1, 0 }, { TU("\266"), 1, 7 }, { TU("\266"), 1, 0 } }, 0, 30, 30, "Standard example + extra seg, data mode", + "111111000000111111000000111111" + "111101011110111111011110111111" + "111011011110111111011110111111" + "111101000000100001000000100001" + "101001000000100001000000100001" + "111111000000111111000000111111" + "000000111111000000111111000000" + "011010110111010000110001011110" + "000010111111000110111101011110" + "001010100001000110110001000000" + "011100100001001100100001000000" + "000000111111000000111111000000" + "111111000000111111000000111111" + "111111010000101001010000111111" + "101111000000100001000100111111" + "110001001100110111011000100001" + "101111000000100001000000100001" + "111111000000111111000000111111" + "000000111111000000111111000000" + "011110110001010010110001011010" + "010100110111010110111001001100" + "000110100001000000101011010010" + "010000100001000000110001000110" + "000000111111000000111111000000" + "111111000000111111000000111111" + "111011011010111101011010111111" + "111001000110101111011000101001" + "111101011000111011010010111011" + "101101011100110001001000111001" + "111111000000111111000000111111" + }, + /* 6*/ { UNICODE_MODE, -1, -1, { 1, 16, "" }, { { TU("齄齄"), -1, 29 }, { TU("Τεχτ"), -1, 0 }, { TU("Text"), -1, 0 } }, ZINT_WARN_USES_ECI, 30, 30, "Structured Append", + "111111000000111111000000111111" + "111011011000111101011010111111" + "101011000000101111001110100001" + "111011000010110111011100100011" + "110101010000101001000100111101" + "111111000000111111000000111111" + "000000111111000000111111000000" + "011000110101010000110111011110" + "010110110001000010111111011110" + "011010100111011010111111000000" + "011100111111010000110111000000" + "000000111111000000111111000000" + "111111000000111111000000111111" + "111011010100101001010110111111" + "111111011110101111011110111111" + "100101010010101101011010100001" + "100101011000100001011100100001" + "111111000000111111000000111111" + "000000111111000000111111000000" + "011100110111010010110011011100" + "010110110101001100110001011000" + "000100110001000000101111010100" + "000100100011000100100001001010" + "000000111111000000111111000000" + "111111000000111111000000111111" + "111011011010111001011000111011" + "111001010110100101011000111001" + "110111000010101001011100110011" + "100011011010111011001110101011" + "111111000000111111000000111111" + }, + }; + int data_size = ARRAY_SIZE(data); + int i, j, seg_count, ret; + struct zint_symbol *symbol; + + char escaped[8192]; + + testStart("test_encode_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + testUtilSetSymbol(symbol, BARCODE_GRIDMATRIX, data[i].input_mode, -1 /*eci*/, + data[i].option_1, data[i].option_2, -1, -1 /*output_options*/, + NULL, 0, debug); + for (j = 0, seg_count = 0; j < 3 && data[i].segs[j].length; j++, seg_count++); + + ret = ZBarcode_Encode_Segs(symbol, data[i].segs, seg_count); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode_Segs ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + char escaped1[8192]; + char escaped2[8192]; + int length = data[i].segs[0].length == -1 ? (int) ustrlen(data[i].segs[0].source) : data[i].segs[0].length; + int length1 = data[i].segs[1].length == -1 ? (int) ustrlen(data[i].segs[1].source) : data[i].segs[1].length; + int length2 = data[i].segs[2].length == -1 ? (int) ustrlen(data[i].segs[2].source) : data[i].segs[2].length; + printf(" /*%3d*/ { %s, %d, %d, { %d, %d, \"%s\" }, { { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d } }, %s, %d, %d, \"%s\",\n", + i, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_2, + data[i].structapp.index, data[i].structapp.count, data[i].structapp.id, + testUtilEscape((const char *) data[i].segs[0].source, length, escaped, sizeof(escaped)), data[i].segs[0].length, data[i].segs[0].eci, + testUtilEscape((const char *) data[i].segs[1].source, length1, escaped1, sizeof(escaped1)), data[i].segs[1].length, data[i].segs[1].eci, + testUtilEscape((const char *) data[i].segs[2].source, length2, escaped2, sizeof(escaped2)), data[i].segs[2].length, data[i].segs[2].eci, + testUtilErrorName(data[i].ret), + symbol->rows, symbol->width, data[i].comment); + testUtilModulesPrint(symbol, " ", "\n"); + printf(" },\n"); + } else { + if (ret < ZINT_ERROR) { + int width, row; + 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); + + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d\n", i, ret, width, row); + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + #include #define TEST_PERF_ITERATIONS 1000 @@ -593,6 +945,7 @@ int main(int argc, char *argv[]) { { "test_options", test_options, 1, 0, 1 }, { "test_input", test_input, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_encode_segs", test_encode_segs, 1, 1, 1 }, { "test_perf", test_perf, 1, 0, 1 }, }; diff --git a/backend/tests/test_gs1.c b/backend/tests/test_gs1.c index 8c7761c3..1c6bb918 100644 --- a/backend/tests/test_gs1.c +++ b/backend/tests/test_gs1.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2019 - 2021 Robin Stuart + Copyright (C) 2019-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "testcommon.h" @@ -238,7 +237,7 @@ static void test_gs1_reduce(int index, int generate, int debug) { assert_zero(ret, "i:%d %s testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, testUtilBarcodeName(data[i].symbology), ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) { - ret = testUtilBwipp(i, symbol, -1, -1, -1, text, length, symbol->primary, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, -1, -1, -1, text, length, symbol->primary, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -2187,3 +2186,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_hanxin.c b/backend/tests/test_hanxin.c index 33537263..a87b3670 100644 --- a/backend/tests/test_hanxin.c +++ b/backend/tests/test_hanxin.c @@ -35,6 +35,7 @@ static void test_large(int index, int debug) { struct item { int option_1; int option_2; + int option_3; char *pattern; int length; int ret; @@ -43,24 +44,28 @@ static void test_large(int index, int debug) { }; // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { -1, -1, "1", 7827, 0, 189, 189 }, - /* 1*/ { -1, -1, "1", 7828, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 2*/ { -1, -1, "A", 4350, 0, 189, 189 }, - /* 3*/ { -1, -1, "A", 4351, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 4*/ { -1, -1, "\200", 3261, 0, 189, 189 }, - /* 5*/ { -1, -1, "\200", 3262, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 6*/ { -1, 1, "1", 45, 0, 23, 23 }, - /* 7*/ { -1, 1, "1", 46, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 8*/ { -1, 1, "A", 26, 0, 23, 23 }, - /* 9*/ { -1, 1, "A", 27, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 10*/ { -1, 1, "\200", 18, 0, 23, 23 }, - /* 11*/ { -1, 1, "\200", 19, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 12*/ { 2, 1, "A", 21, 0, 23, 23 }, - /* 13*/ { 2, 1, "A", 22, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 14*/ { 3, 1, "A", 15, 0, 23, 23 }, - /* 15*/ { 3, 1, "A", 16, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 16*/ { 4, 1, "A", 10, 0, 23, 23 }, - /* 17*/ { 4, 1, "A", 11, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 0*/ { -1, -1, -1, "1", 7827, 0, 189, 189 }, + /* 1*/ { -1, -1, -1, "1", 7828, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 2*/ { -1, -1, -1, "A", 4350, 0, 189, 189 }, + /* 3*/ { -1, -1, -1, "A", 4351, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 4*/ { -1, -1, -1, "\200", 3261, 0, 189, 189 }, + /* 5*/ { -1, -1, -1, "\200", 3262, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 6*/ { -1, -1, ZINT_FULL_MULTIBYTE, "\241", 4348, 0, 189, 189 }, + /* 7*/ { -1, -1, ZINT_FULL_MULTIBYTE, "\241", 4350, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 8*/ { -1, 1, -1, "1", 45, 0, 23, 23 }, + /* 9*/ { -1, 1, -1, "1", 46, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 10*/ { -1, 1, -1, "A", 26, 0, 23, 23 }, + /* 11*/ { -1, 1, -1, "A", 27, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 12*/ { -1, 1, -1, "\200", 18, 0, 23, 23 }, + /* 13*/ { -1, 1, -1, "\200", 19, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 14*/ { -1, 1, ZINT_FULL_MULTIBYTE, "\241", 24, 0, 23, 23 }, + /* 15*/ { -1, 1, ZINT_FULL_MULTIBYTE, "\241", 26, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 16*/ { 2, 1, -1, "A", 21, 0, 23, 23 }, + /* 17*/ { 2, 1, -1, "A", 22, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 18*/ { 3, 1, -1, "A", 15, 0, 23, 23 }, + /* 19*/ { 3, 1, -1, "A", 16, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 20*/ { 4, 1, -1, "A", 10, 0, 23, 23 }, + /* 21*/ { 4, 1, -1, "A", 11, ZINT_ERROR_TOO_LONG, -1, -1 }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -80,7 +85,7 @@ static void test_large(int index, int debug) { testUtilStrCpyRepeat(data_buf, data[i].pattern, data[i].length); assert_equal(data[i].length, (int) strlen(data_buf), "i:%d length %d != strlen(data_buf) %d\n", i, data[i].length, (int) strlen(data_buf)); - length = testUtilSetSymbol(symbol, BARCODE_HANXIN, -1 /*input_mode*/, -1 /*eci*/, data[i].option_1, data[i].option_2, -1, -1 /*output_options*/, data_buf, data[i].length, debug); + length = testUtilSetSymbol(symbol, BARCODE_HANXIN, -1 /*input_mode*/, -1 /*eci*/, data[i].option_1, data[i].option_2, data[i].option_3, -1 /*output_options*/, data_buf, data[i].length, debug); 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); @@ -163,6 +168,7 @@ static void test_input(int index, int generate, int debug) { int ret; int expected_eci; char *expected; + int zxingcpp_cmp; char *comment; }; // é U+00E9 in ISO 8859-1 plus other ISO 8859 (but not in ISO 8859-7 or ISO 8859-11), Win 1250 plus other Win, in GB 18030 0xA8A6, UTF-8 C3A9 @@ -175,97 +181,104 @@ static void test_input(int index, int generate, int debug) { // 丂 U+4E02 GB 18030 2-byte Region 0x8140, UTF-8 E4B882 // � (REPLACEMENT CHARACTER) U+FFFD GB 18030 4-byte Region 0x81308130, UTF-8 EFBFBD (\357\277\275) struct item data[] = { - /* 0*/ { UNICODE_MODE, 0, -1, "é", -1, 0, 0, "30 00 F4 80 00 00 00 00 00", "B1 (ISO 8859-1)" }, - /* 1*/ { UNICODE_MODE, 3, -1, "é", -1, 0, 3, "80 33 00 0F 48 00 00 00 00", "ECI-3 B1 (ISO 8859-1)" }, - /* 2*/ { UNICODE_MODE, 29, -1, "é", -1, 0, 29, "81 D3 00 15 45 30 00 00 00", "ECI-29 B2 (GB 2312)" }, - /* 3*/ { UNICODE_MODE, 32, -1, "é", -1, 0, 32, "82 04 FC FF FF 00 00 00 00", "ECI-32 H(1)1 (GB 18030) (Region One)" }, - /* 4*/ { UNICODE_MODE, 26, -1, "é", -1, 0, 26, "81 A3 00 16 1D 48 00 00 00", "ECI-26 B2 (UTF-8)" }, - /* 5*/ { UNICODE_MODE, 26, ZINT_FULL_MULTIBYTE, "é", -1, 0, 26, "81 A4 70 2F FF 00 00 00 00", "ECI-26 H(1)1 (Region One) (UTF-8) (full multibyte)" }, - /* 6*/ { DATA_MODE, 0, -1, "é", -1, 0, 0, "30 01 61 D4 80 00 00 00 00", "B2 (UTF-8)" }, - /* 7*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "é", -1, 0, 0, "47 02 FF F0 00 00 00 00 00", "H(1)1 (UTF-8) (Region One) (full multibyte)" }, - /* 8*/ { DATA_MODE, 0, -1, "\351", -1, 0, 0, "30 00 F4 80 00 00 00 00 00", "B1 (ISO 8859-1) (0xE9)" }, - /* 9*/ { UNICODE_MODE, 0, -1, "β", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 30 01 53 61 00 00 00 00 00", "B2 (GB 18030) (2-byte Region)" }, - /* 10*/ { UNICODE_MODE, 9, -1, "β", -1, 0, 9, "80 93 00 0F 10 00 00 00 00", "ECI-9 B1 (ISO 8859-7)" }, - /* 11*/ { UNICODE_MODE, 29, -1, "β", -1, 0, 29, "81 D3 00 15 36 10 00 00 00", "ECI-29 B2 (GB 2312)" }, - /* 12*/ { UNICODE_MODE, 32, -1, "β", -1, 0, 32, "82 03 00 15 36 10 00 00 00", "ECI-32 B2 (GB 18030) (2-byte Region)" }, - /* 13*/ { UNICODE_MODE, 26, -1, "β", -1, 0, 26, "81 A3 00 16 75 90 00 00 00", "ECI-26 B2 (UTF-8)" }, - /* 14*/ { UNICODE_MODE, 26, ZINT_FULL_MULTIBYTE, "β", -1, 0, 26, "81 A4 B1 5F FF 00 00 00 00", "ECI-26 B2 (UTF-8) (full multibyte)" }, - /* 15*/ { DATA_MODE, 0, -1, "β", -1, 0, 0, "30 01 67 59 00 00 00 00 00", "B2 (UTF-8)" }, - /* 16*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "β", -1, 0, 0, "4B 15 FF F0 00 00 00 00 00", "H(1)1 (UTF-8) (Region One) (full multibyte)" }, - /* 17*/ { UNICODE_MODE, 0, -1, "ÿ", -1, 0, 0, "30 00 FF 80 00 00 00 00 00", "B1 (ISO 8859-1)" }, - /* 18*/ { UNICODE_MODE, 0, -1, "ÿÿÿ", -1, 0, 0, "30 01 FF FF FF 80 00 00 00", "B3 (ISO 8859-1)" }, - /* 19*/ { UNICODE_MODE, 0, -1, "\302\200", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 00 00 00 00 00 00 00 00", "H(f)1 (GB 18030) (4-byte Region) (not DATA_MODE so GB 18030 mapping)" }, - /* 20*/ { UNICODE_MODE, 0, ZINT_FULL_MULTIBYTE, "\302\200", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 00 00 00 00 00 00 00 00", "H(f)1 (GB 18030) (4-byte Region)" }, - /* 21*/ { DATA_MODE, 0, 0, "\302\200", -1, 0, 0, "30 01 61 40 00 00 00 00 00", "B2 (UTF-8)" }, - /* 22*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "\302\200", -1, 0, 0, "30 01 61 40 00 00 00 00 00", "B2 (UTF-8) (full multibyte)" }, - /* 23*/ { UNICODE_MODE, 0, -1, "\302\200�", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 00 00 38 26 7E 40 00 00", "H(f)2 (GB 18030) (both 4-byte Region) (not DATA_MODE so GB 18030 mapping)" }, - /* 24*/ { UNICODE_MODE, 0, ZINT_FULL_MULTIBYTE, "\302\200�", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 00 00 38 26 7E 40 00 00", "H(f)2 (GB 18030) (both 4-byte Region)" }, - /* 25*/ { UNICODE_MODE, 0, -1, "啊亍齄丂\302\200", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 64 68 50 3C AC 28 80 00 FF FE E0 00 00", "H(d)4 H(f)1 (GB 18030)" }, - /* 26*/ { DATA_MODE, 0, -1, "\177\177", -1, 0, 0, "2F BD F7 F0 00 00 00 00 00", "T2 (ASCII)" }, - /* 27*/ { DATA_MODE, 0, -1, "\177\177\177", -1, 0, 0, "2F BD F7 DF C0 00 00 00 00", "T3 (ASCII)" }, - /* 28*/ { UNICODE_MODE, 0, -1, "123", -1, 0, 0, "11 EF FF 00 00 00 00 00 00", "N3 (ASCII)" }, - /* 29*/ { UNICODE_MODE, 0, -1, "12345", -1, 0, 0, "11 EC 2D FF 80 00 00 00 00", "N5 (ASCII)" }, - /* 30*/ { UNICODE_MODE, 0, -1, "Aa%$Bb9", -1, 0, 0, "22 A4 FA 18 3E 2E 52 7F 00", "T7 (ASCII)" }, - /* 31*/ { UNICODE_MODE, 0, -1, "Summer Palace Ticket for 6 June 2015 13:00;2015年6月6日夜01時00分PM頤和園のチケット;2015년6월6일13시오후여름궁전티켓.2015年6月6号下午13:00的颐和园门票;", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning (171) 27 38 C3 0A 35 F9 CF 99 92 F9 26 A3 E7 3E 76 C9 AE A3 7F CC 08 04 0C CD EE 44 06 C4", "T20 B64 N4 H(f)1 T1 H(f)1 T1 H(f)1 T2 H(f)9 B35 (GB 18030)" }, - /* 32*/ { DATA_MODE, 0, -1, "Summer Palace Ticket for 6 June 2015 13:00;2015年6月6日夜01時00分PM頤和園のチケット;2015년6월6일13시오후여름궁전티켓.2015年6月6号下午13:00的颐和园门票;", -1, 0, 0, "(209) 27 38 C3 0A 35 F9 CF 99 92 F9 26 A3 E7 3E 76 C9 AE A3 7F CC 15 04 0C CD EE 44 06 C4", "T20 B117 (UTF-8)" }, - /* 33*/ { UNICODE_MODE, 0, -1, "\000\014\033 #/059:<@AMZ", 15, 0, 0, "2F 80 31 B7 1F AF E0 05 27 EB 2E CB E2 96 8F F0 00", "T15 (ASCII)" }, - /* 34*/ { UNICODE_MODE, 0, -1, "Z[\\`alz{~\177", -1, 0, 0, "28 FE CF 4E 3E 92 FF 7E E7 CF 7F 00 00", "T10 (ASCII)" }, - /* 35*/ { DATA_MODE, 26, ZINT_FULL_MULTIBYTE, "\202\061\203\063", -1, 0, 26, "81 A7 01 B1 D8 00 00 00 00", "ECI-26 H(f)1 (GB 18030) (Invalid UTF-8, forces GB 2312/18030 utf8tosb() difference) NOTE: 2021-01-10 now UTF-8 is checked and mode -> DATA_MODE this test no longer shows difference" }, - /* 36*/ { UNICODE_MODE, 128, 0, "A", -1, 0, 128, "88 08 02 2B F0 00 00 00 00", "ECI > 127" }, - /* 37*/ { UNICODE_MODE, 16364, 0, "A", -1, 0, 16364, "8B FE C2 2B F0 00 00 00 00", "ECI > 16363" }, - /* 38*/ { UNICODE_MODE, 0, -1, "啊啊啊亍", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 40 00 00 00 00 FF E0 00 FF F0 00 00 00", "Region 1 (FFE terminator) -> Region 2 (no indicator)" }, - /* 39*/ { UNICODE_MODE, 0, -1, "亍亍亍啊", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 50 00 00 00 00 FF E0 00 FF F0 00 00 00", "Region 2 (FFE terminator) -> Region 1 (no indicator)" }, - /* 40*/ { UNICODE_MODE, 0, -1, "啊啊啊啊亍亍啊", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 40 00 00 00 00 00 0F FE 00 00 00 FF E0 00 FF F0 00", "Region 1 (FFE) -> Region 2 (FFE) -> Region 1" }, - /* 41*/ { UNICODE_MODE, 0, -1, "亍亍亍亍啊啊亍", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 50 00 00 00 00 00 0F FE 00 00 00 FF E0 00 FF F0 00", "Region 2 (FFE) -> Region 1 (FFE) -> Region 2" }, - /* 42*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE | (2 << 8), "é", -1, 0, 0, "47 02 FF F0 00 00 00 00 00", "H(1)1 (UTF-8) (Region One) (full multibyte with mask)" }, - /* 43*/ { UNICODE_MODE, 0, -1, "˘", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 01 16 80 00 00 00 00 00", "H(f)1 (GB 18030)" }, - /* 44*/ { UNICODE_MODE, 4, -1, "˘", -1, 0, 4, "80 43 00 0D 10 00 00 00 00", "ECI-4 B1 (ISO 8859-2)" }, - /* 45*/ { UNICODE_MODE, 0, -1, "Ħ", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 00 47 80 00 00 00 00 00", "H(f)1 (GB 18030)" }, - /* 46*/ { UNICODE_MODE, 5, -1, "Ħ", -1, 0, 5, "80 53 00 0D 08 00 00 00 00", "ECI-5 B1 (ISO 8859-3)" }, - /* 47*/ { UNICODE_MODE, 0, -1, "ĸ", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 00 50 00 00 00 00 00 00", "H(f)1 (GB 18030)" }, - /* 48*/ { UNICODE_MODE, 6, -1, "ĸ", -1, 0, 6, "80 63 00 0D 10 00 00 00 00", "ECI-6 B1 (ISO 8859-4)" }, - /* 49*/ { UNICODE_MODE, 0, -1, "Ж", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 30 01 53 D4 00 00 00 00 00", "B2 (GB 18030)" }, - /* 50*/ { UNICODE_MODE, 7, -1, "Ж", -1, 0, 7, "80 73 00 0D B0 00 00 00 00", "ECI-7 B1 (ISO 8859-5)" }, - /* 51*/ { UNICODE_MODE, 0, -1, "Ș", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 00 B9 80 00 00 00 00 00", "H(f)1 (GB 18030)" }, - /* 52*/ { UNICODE_MODE, 18, -1, "Ș", -1, 0, 18, "81 23 00 0D 50 00 00 00 00", "ECI-18 B1 (ISO 8859-16)" }, - /* 53*/ { UNICODE_MODE, 0, -1, "テ", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 30 01 52 E3 00 00 00 00 00", "B2 (GB 18030)" }, - /* 54*/ { UNICODE_MODE, 20, -1, "テ", -1, 0, 20, "81 43 00 14 1B 28 00 00 00", "ECI-20 B2 (SHIFT JIS)" }, - /* 55*/ { UNICODE_MODE, 20, -1, "テテ", -1, 0, 20, "81 43 00 24 1B 2C 1B 28 00", "ECI-20 B4 (SHIFT JIS)" }, - /* 56*/ { UNICODE_MODE, 20, -1, "\\\\", -1, 0, 20, "81 43 00 24 0A FC 0A F8 00", "ECI-20 B4 (SHIFT JIS)" }, - /* 57*/ { UNICODE_MODE, 0, -1, "…", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 4E BC FF F0 00 00 00 00 00", "H(1)1 (GB 18030)" }, - /* 58*/ { UNICODE_MODE, 21, -1, "…", -1, 0, 21, "81 53 00 0C 28 00 00 00 00", "ECI-21 B1 (Win 1250)" }, - /* 59*/ { UNICODE_MODE, 0, -1, "Ґ", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 01 B9 00 00 00 00 00 00", "H(f)1 (GB 18030)" }, - /* 60*/ { UNICODE_MODE, 22, -1, "Ґ", -1, 0, 22, "81 63 00 0D 28 00 00 00 00", "ECI-22 B1 (Win 1251)" }, - /* 61*/ { UNICODE_MODE, 0, -1, "˜", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 01 18 00 00 00 00 00 00", "H(f)1 (GB 18030)" }, - /* 62*/ { UNICODE_MODE, 23, -1, "˜", -1, 0, 23, "81 73 00 0C C0 00 00 00 00", "ECI-23 B1 (Win 1252)" }, - /* 63*/ { UNICODE_MODE, 24, -1, "پ", -1, 0, 24, "81 83 00 0C 08 00 00 00 00", "ECI-24 B1 (Win 1256)" }, - /* 64*/ { UNICODE_MODE, 0, -1, "က", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 07 71 00 00 00 00 00 00", "H(f)1 (GB 18030)" }, - /* 65*/ { UNICODE_MODE, 25, -1, "က", -1, 0, 25, "81 92 F9 00 3F 00 00 00 00", "ECI-25 T2 (UCS-2BE)" }, - /* 66*/ { UNICODE_MODE, 25, -1, "ကက", -1, 0, 25, "81 92 F9 00 10 03 F0 00 00", "ECI-25 T4 (UCS-2BE)" }, - /* 67*/ { UNICODE_MODE, 25, -1, "12", -1, 0, 25, "81 93 00 20 01 88 01 90 00", "ECI-25 B4 (UCS-2BE ASCII)" }, - /* 68*/ { UNICODE_MODE, 27, -1, "@", -1, 0, 27, "81 B2 FB 2F C0 00 00 00 00", "ECI-27 T1 (ASCII)" }, - /* 69*/ { UNICODE_MODE, 0, -1, "龘", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 30 01 7E C9 80 00 00 00 00", "B2 (GB 18030)" }, - /* 70*/ { UNICODE_MODE, 28, -1, "龘", -1, 0, 28, "81 C3 00 17 CE A8 00 00 00", "ECI-28 B2 (Big5)" }, - /* 71*/ { UNICODE_MODE, 28, -1, "龘龘", -1, 0, 28, "81 C3 00 27 CE AF CE A8 00", "ECI-28 B4 (Big5)" }, - /* 72*/ { UNICODE_MODE, 0, -1, "齄", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 5B BF FF F0 00 00 00 00 00", "H(2)1 (GB 18030)" }, - /* 73*/ { UNICODE_MODE, 29, -1, "齄", -1, 0, 29, "81 D3 00 17 BF F0 00 00 00", "ECI-29 B2 (GB 2312)" }, - /* 74*/ { UNICODE_MODE, 32, -1, "齄", -1, 0, 32, "82 05 BB FF FF 00 00 00 00", "ECI-32 H(2)1 (GB 2312)" }, - /* 75*/ { UNICODE_MODE, 29, -1, "齄齄", -1, 0, 29, "81 D3 00 27 BF F7 BF F0 00", "ECI-29 B4 (GB 2312)" }, - /* 76*/ { UNICODE_MODE, 32, -1, "齄齄", -1, 0, 32, "82 05 BB FB BF FF F0 00 00", "ECI-32 H(2)2 (GB 2312)" }, - /* 77*/ { UNICODE_MODE, 0, -1, "가", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 2B 5E 80 00 00 00 00 00", "H(f)1 (GB 18030)" }, - /* 78*/ { UNICODE_MODE, 30, -1, "가", -1, 0, 30, "81 E3 00 15 85 08 00 00 00", "ECI-30 T2 (EUC-KR)" }, - /* 79*/ { UNICODE_MODE, 30, -1, "가가", -1, 0, 30, "81 E3 00 25 85 0D 85 08 00", "ECI-30 B4 (EUC-KR)" }, - /* 80*/ { UNICODE_MODE, 170, -1, "?", -1, 0, 170, "88 0A A2 FB 1F C0 00 00 00", "ECI-170 L1 (ASCII invariant)" }, - /* 81*/ { DATA_MODE, 899, -1, "\200", -1, 0, 899, "88 38 33 00 0C 00 00 00 00", "ECI-899 B1 (8-bit binary)" }, - /* 82*/ { UNICODE_MODE, 900, -1, "é", -1, 0, 900, "88 38 43 00 16 1D 48 00 00", "ECI-900 B2 (no conversion)" }, - /* 83*/ { UNICODE_MODE, 16384, -1, "é", -1, 0, 16384, "8C 04 00 03 00 16 1D 48 00", "ECI-16384 B2 (no conversion)" }, - /* 84*/ { UNICODE_MODE, 3, -1, "β", -1, ZINT_ERROR_INVALID_DATA, 3, "Error 545: Invalid character in input data for ECI 3", "" }, + /* 0*/ { UNICODE_MODE, 0, -1, "é", -1, 0, 0, "30 00 F4 80 00 00 00 00 00", 1, "B1 (ISO 8859-1)" }, + /* 1*/ { UNICODE_MODE, 3, -1, "é", -1, 0, 3, "80 33 00 0F 48 00 00 00 00", 1, "ECI-3 B1 (ISO 8859-1)" }, + /* 2*/ { UNICODE_MODE, 29, -1, "é", -1, 0, 29, "81 D3 00 15 45 30 00 00 00", 1, "ECI-29 B2 (GB 2312)" }, + /* 3*/ { UNICODE_MODE, 32, -1, "é", -1, 0, 32, "82 04 FC FF FF 00 00 00 00", 1, "ECI-32 H(1)1 (GB 18030) (Region One)" }, + /* 4*/ { UNICODE_MODE, 26, -1, "é", -1, 0, 26, "81 A3 00 16 1D 48 00 00 00", 1, "ECI-26 B2 (UTF-8)" }, + /* 5*/ { UNICODE_MODE, 26, ZINT_FULL_MULTIBYTE, "é", -1, 0, 26, "81 A4 70 2F FF 00 00 00 00", 1, "ECI-26 H(1)1 (Region One) (UTF-8) (full multibyte)" }, + /* 6*/ { DATA_MODE, 0, -1, "é", -1, 0, 0, "30 01 61 D4 80 00 00 00 00", 1, "B2 (UTF-8)" }, + /* 7*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "é", -1, 0, 0, "47 02 FF F0 00 00 00 00 00", 1, "H(1)1 (UTF-8) (Region One) (full multibyte)" }, + /* 8*/ { DATA_MODE, 0, -1, "\351", -1, 0, 0, "30 00 F4 80 00 00 00 00 00", 1, "B1 (ISO 8859-1) (0xE9)" }, + /* 9*/ { UNICODE_MODE, 0, -1, "β", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 30 01 53 61 00 00 00 00 00", 1, "B2 (GB 18030) (2-byte Region)" }, + /* 10*/ { UNICODE_MODE, 9, -1, "β", -1, 0, 9, "80 93 00 0F 10 00 00 00 00", 1, "ECI-9 B1 (ISO 8859-7)" }, + /* 11*/ { UNICODE_MODE, 29, -1, "β", -1, 0, 29, "81 D3 00 15 36 10 00 00 00", 1, "ECI-29 B2 (GB 2312)" }, + /* 12*/ { UNICODE_MODE, 32, -1, "β", -1, 0, 32, "82 03 00 15 36 10 00 00 00", 1, "ECI-32 B2 (GB 18030) (2-byte Region)" }, + /* 13*/ { UNICODE_MODE, 26, -1, "β", -1, 0, 26, "81 A3 00 16 75 90 00 00 00", 1, "ECI-26 B2 (UTF-8)" }, + /* 14*/ { UNICODE_MODE, 26, ZINT_FULL_MULTIBYTE, "β", -1, 0, 26, "81 A4 B1 5F FF 00 00 00 00", 1, "ECI-26 B2 (UTF-8) (full multibyte)" }, + /* 15*/ { DATA_MODE, 0, -1, "β", -1, 0, 0, "30 01 67 59 00 00 00 00 00", 1, "B2 (UTF-8)" }, + /* 16*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "β", -1, 0, 0, "4B 15 FF F0 00 00 00 00 00", 1, "H(1)1 (UTF-8) (Region One) (full multibyte)" }, + /* 17*/ { UNICODE_MODE, 0, -1, "ÿ", -1, 0, 0, "30 00 FF 80 00 00 00 00 00", 1, "B1 (ISO 8859-1)" }, + /* 18*/ { UNICODE_MODE, 0, -1, "ÿÿÿ", -1, 0, 0, "30 01 FF FF FF 80 00 00 00", 1, "B3 (ISO 8859-1)" }, + /* 19*/ { UNICODE_MODE, 0, -1, "\302\200", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 00 00 00 00 00 00 00 00", 1, "H(f)1 (GB 18030) (4-byte Region) (not DATA_MODE so GB 18030 mapping)" }, + /* 20*/ { UNICODE_MODE, 0, ZINT_FULL_MULTIBYTE, "\302\200", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 00 00 00 00 00 00 00 00", 1, "H(f)1 (GB 18030) (4-byte Region)" }, + /* 21*/ { DATA_MODE, 0, 0, "\302\200", -1, 0, 0, "30 01 61 40 00 00 00 00 00", 1, "B2 (UTF-8)" }, + /* 22*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "\302\200", -1, 0, 0, "30 01 61 40 00 00 00 00 00", 1, "B2 (UTF-8) (full multibyte)" }, + /* 23*/ { UNICODE_MODE, 0, -1, "\302\200�", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 00 00 38 26 7E 40 00 00", 1, "H(f)2 (GB 18030) (both 4-byte Region) (not DATA_MODE so GB 18030 mapping)" }, + /* 24*/ { UNICODE_MODE, 0, ZINT_FULL_MULTIBYTE, "\302\200�", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 00 00 38 26 7E 40 00 00", 1, "H(f)2 (GB 18030) (both 4-byte Region)" }, + /* 25*/ { UNICODE_MODE, 0, -1, "啊亍齄丂\302\200", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 64 68 50 3C AC 28 80 00 FF FE E0 00 00", 1, "H(d)4 H(f)1 (GB 18030)" }, + /* 26*/ { DATA_MODE, 0, -1, "\177\177", -1, 0, 0, "2F BD F7 F0 00 00 00 00 00", 1, "T2 (ASCII)" }, + /* 27*/ { DATA_MODE, 0, -1, "\177\177\177", -1, 0, 0, "2F BD F7 DF C0 00 00 00 00", 1, "T3 (ASCII)" }, + /* 28*/ { UNICODE_MODE, 0, -1, "123", -1, 0, 0, "11 EF FF 00 00 00 00 00 00", 1, "N3 (ASCII)" }, + /* 29*/ { UNICODE_MODE, 0, -1, "12345", -1, 0, 0, "11 EC 2D FF 80 00 00 00 00", 1, "N5 (ASCII)" }, + /* 30*/ { UNICODE_MODE, 0, -1, "Aa%$Bb9", -1, 0, 0, "22 A4 FA 18 3E 2E 52 7F 00", 1, "T7 (ASCII)" }, + /* 31*/ { UNICODE_MODE, 0, -1, "Summer Palace Ticket for 6 June 2015 13:00;2015年6月6日夜01時00分PM頤和園のチケット;2015년6월6일13시오후여름궁전티켓.2015年6月6号下午13:00的颐和园门票;", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning (171) 27 38 C3 0A 35 F9 CF 99 92 F9 26 A3 E7 3E 76 C9 AE A3 7F CC 08 04 0C CD EE 44 06 C4", 1, "T20 B64 N4 H(f)1 T1 H(f)1 T1 H(f)1 T2 H(f)9 B35 (GB 18030)" }, + /* 32*/ { DATA_MODE, 0, -1, "Summer Palace Ticket for 6 June 2015 13:00;2015年6月6日夜01時00分PM頤和園のチケット;2015년6월6일13시오후여름궁전티켓.2015年6月6号下午13:00的颐和园门票;", -1, 0, 0, "(209) 27 38 C3 0A 35 F9 CF 99 92 F9 26 A3 E7 3E 76 C9 AE A3 7F CC 15 04 0C CD EE 44 06 C4", 1, "T20 B117 (UTF-8)" }, + /* 33*/ { UNICODE_MODE, 0, -1, "\000\014\033 #/059:<@AMZ", 15, 0, 0, "2F 80 31 B7 1F AF E0 05 27 EB 2E CB E2 96 8F F0 00", 1, "T15 (ASCII)" }, + /* 34*/ { UNICODE_MODE, 0, -1, "Z[\\`alz{~\177", -1, 0, 0, "28 FE CF 4E 3E 92 FF 7E E7 CF 7F 00 00", 1, "T10 (ASCII)" }, + /* 35*/ { DATA_MODE, 26, ZINT_FULL_MULTIBYTE, "\202\061\203\063", -1, 0, 26, "81 A7 01 B1 D8 00 00 00 00", 0, "ECI-26 H(f)1 (GB 18030) (Invalid UTF-8, forces GB 2312/18030 utf8tosb() difference) NOTE: 2021-01-10 now UTF-8 is checked and mode -> DATA_MODE this test no longer shows difference; ZXing-C++ returns null string" }, + /* 36*/ { UNICODE_MODE, 128, 0, "A", -1, 0, 128, "88 08 02 2B F0 00 00 00 00", 1, "ECI > 127" }, + /* 37*/ { UNICODE_MODE, 16364, 0, "A", -1, 0, 16364, "8B FE C2 2B F0 00 00 00 00", 1, "ECI > 16363" }, + /* 38*/ { UNICODE_MODE, 0, -1, "啊啊啊亍", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 40 00 00 00 00 FF E0 00 FF F0 00 00 00", 1, "Region One (FFE terminator) -> Region Two (no indicator)" }, + /* 39*/ { UNICODE_MODE, 0, -1, "亍亍亍啊", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 50 00 00 00 00 FF E0 00 FF F0 00 00 00", 1, "Region Two (FFE terminator) -> Region One (no indicator)" }, + /* 40*/ { UNICODE_MODE, 0, -1, "啊啊啊啊亍亍啊", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 40 00 00 00 00 00 0F FE 00 00 00 FF E0 00 FF F0 00", 1, "Region One (FFE) -> Region Two (FFE) -> Region One" }, + /* 41*/ { UNICODE_MODE, 0, -1, "亍亍亍亍啊啊亍", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 50 00 00 00 00 00 0F FE 00 00 00 FF E0 00 FF F0 00", 1, "Region Two (FFE) -> Region One (FFE) -> Region Two" }, + /* 42*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE | (2 << 8), "é", -1, 0, 0, "47 02 FF F0 00 00 00 00 00", 1, "H(1)1 (UTF-8) (Region One) (full multibyte with mask)" }, + /* 43*/ { UNICODE_MODE, 0, -1, "˘", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 01 16 80 00 00 00 00 00", 1, "H(f)1 (GB 18030)" }, + /* 44*/ { UNICODE_MODE, 4, -1, "˘", -1, 0, 4, "80 43 00 0D 10 00 00 00 00", 1, "ECI-4 B1 (ISO 8859-2)" }, + /* 45*/ { UNICODE_MODE, 0, -1, "Ħ", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 00 47 80 00 00 00 00 00", 1, "H(f)1 (GB 18030)" }, + /* 46*/ { UNICODE_MODE, 5, -1, "Ħ", -1, 0, 5, "80 53 00 0D 08 00 00 00 00", 1, "ECI-5 B1 (ISO 8859-3)" }, + /* 47*/ { UNICODE_MODE, 0, -1, "ĸ", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 00 50 00 00 00 00 00 00", 1, "H(f)1 (GB 18030)" }, + /* 48*/ { UNICODE_MODE, 6, -1, "ĸ", -1, 0, 6, "80 63 00 0D 10 00 00 00 00", 1, "ECI-6 B1 (ISO 8859-4)" }, + /* 49*/ { UNICODE_MODE, 0, -1, "Ж", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 30 01 53 D4 00 00 00 00 00", 1, "B2 (GB 18030)" }, + /* 50*/ { UNICODE_MODE, 7, -1, "Ж", -1, 0, 7, "80 73 00 0D B0 00 00 00 00", 1, "ECI-7 B1 (ISO 8859-5)" }, + /* 51*/ { UNICODE_MODE, 0, -1, "Ș", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 00 B9 80 00 00 00 00 00", 1, "H(f)1 (GB 18030)" }, + /* 52*/ { UNICODE_MODE, 18, -1, "Ș", -1, 0, 18, "81 23 00 0D 50 00 00 00 00", 1, "ECI-18 B1 (ISO 8859-16)" }, + /* 53*/ { UNICODE_MODE, 0, -1, "テ", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 30 01 52 E3 00 00 00 00 00", 1, "B2 (GB 18030)" }, + /* 54*/ { UNICODE_MODE, 20, -1, "テ", -1, 0, 20, "81 43 00 14 1B 28 00 00 00", 1, "ECI-20 B2 (SHIFT JIS)" }, + /* 55*/ { UNICODE_MODE, 20, -1, "テテ", -1, 0, 20, "81 43 00 24 1B 2C 1B 28 00", 1, "ECI-20 B4 (SHIFT JIS)" }, + /* 56*/ { UNICODE_MODE, 20, -1, "\\\\", -1, 0, 20, "81 43 00 24 0A FC 0A F8 00", 0, "ECI-20 B4 (SHIFT JIS); ZXing-C++ does straight-through ASCII conversion for Shift JIS" }, + /* 57*/ { UNICODE_MODE, 0, -1, "…", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 4E BC FF F0 00 00 00 00 00", 1, "H(1)1 (GB 18030)" }, + /* 58*/ { UNICODE_MODE, 21, -1, "…", -1, 0, 21, "81 53 00 0C 28 00 00 00 00", 1, "ECI-21 B1 (Win 1250)" }, + /* 59*/ { UNICODE_MODE, 0, -1, "Ґ", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 01 B9 00 00 00 00 00 00", 1, "H(f)1 (GB 18030)" }, + /* 60*/ { UNICODE_MODE, 22, -1, "Ґ", -1, 0, 22, "81 63 00 0D 28 00 00 00 00", 1, "ECI-22 B1 (Win 1251)" }, + /* 61*/ { UNICODE_MODE, 0, -1, "˜", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 01 18 00 00 00 00 00 00", 1, "H(f)1 (GB 18030)" }, + /* 62*/ { UNICODE_MODE, 23, -1, "˜", -1, 0, 23, "81 73 00 0C C0 00 00 00 00", 1, "ECI-23 B1 (Win 1252)" }, + /* 63*/ { UNICODE_MODE, 24, -1, "پ", -1, 0, 24, "81 83 00 0C 08 00 00 00 00", 1, "ECI-24 B1 (Win 1256)" }, + /* 64*/ { UNICODE_MODE, 0, -1, "က", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 07 71 00 00 00 00 00 00", 1, "H(f)1 (GB 18030)" }, + /* 65*/ { UNICODE_MODE, 25, -1, "က", -1, 0, 25, "81 92 F9 00 3F 00 00 00 00", 1, "ECI-25 T2 (UCS-2BE)" }, + /* 66*/ { UNICODE_MODE, 25, -1, "ကက", -1, 0, 25, "81 92 F9 00 10 03 F0 00 00", 1, "ECI-25 T4 (UCS-2BE)" }, + /* 67*/ { UNICODE_MODE, 25, -1, "12", -1, 0, 25, "81 93 00 20 01 88 01 90 00", 1, "ECI-25 B4 (UCS-2BE ASCII)" }, + /* 68*/ { UNICODE_MODE, 27, -1, "@", -1, 0, 27, "81 B2 FB 2F C0 00 00 00 00", 1, "ECI-27 T1 (ASCII)" }, + /* 69*/ { UNICODE_MODE, 0, -1, "龘", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 30 01 7E C9 80 00 00 00 00", 1, "B2 (GB 18030)" }, + /* 70*/ { UNICODE_MODE, 28, -1, "龘", -1, 0, 28, "81 C3 00 17 CE A8 00 00 00", 1, "ECI-28 B2 (Big5)" }, + /* 71*/ { UNICODE_MODE, 28, -1, "龘龘", -1, 0, 28, "81 C3 00 27 CE AF CE A8 00", 1, "ECI-28 B4 (Big5)" }, + /* 72*/ { UNICODE_MODE, 0, -1, "齄", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 5B BF FF F0 00 00 00 00 00", 1, "H(2)1 (GB 18030)" }, + /* 73*/ { UNICODE_MODE, 29, -1, "齄", -1, 0, 29, "81 D3 00 17 BF F0 00 00 00", 1, "ECI-29 B2 (GB 2312)" }, + /* 74*/ { UNICODE_MODE, 32, -1, "齄", -1, 0, 32, "82 05 BB FF FF 00 00 00 00", 1, "ECI-32 H(2)1 (GB 2312)" }, + /* 75*/ { UNICODE_MODE, 29, -1, "齄齄", -1, 0, 29, "81 D3 00 27 BF F7 BF F0 00", 1, "ECI-29 B4 (GB 2312)" }, + /* 76*/ { UNICODE_MODE, 32, -1, "齄齄", -1, 0, 32, "82 05 BB FB BF FF F0 00 00", 1, "ECI-32 H(2)2 (GB 2312)" }, + /* 77*/ { UNICODE_MODE, 0, -1, "가", -1, ZINT_WARN_NONCOMPLIANT, 0, "Warning 70 2B 5E 80 00 00 00 00 00", 1, "H(f)1 (GB 18030)" }, + /* 78*/ { UNICODE_MODE, 30, -1, "가", -1, 0, 30, "81 E3 00 15 85 08 00 00 00", 1, "ECI-30 T2 (EUC-KR)" }, + /* 79*/ { UNICODE_MODE, 30, -1, "가가", -1, 0, 30, "81 E3 00 25 85 0D 85 08 00", 1, "ECI-30 B4 (EUC-KR)" }, + /* 80*/ { UNICODE_MODE, 170, -1, "?", -1, 0, 170, "88 0A A2 FB 1F C0 00 00 00", 1, "ECI-170 L1 (ASCII invariant)" }, + /* 81*/ { DATA_MODE, 899, -1, "\200", -1, 0, 899, "88 38 33 00 0C 00 00 00 00", 1, "ECI-899 B1 (8-bit binary)" }, + /* 82*/ { UNICODE_MODE, 900, -1, "é", -1, 0, 900, "88 38 43 00 16 1D 48 00 00", 0, "ECI-900 B2 (no conversion); ZXing-C++ test can't handle UNICODE_MODE binary" }, + /* 83*/ { DATA_MODE, 900, -1, "\303\251", -1, 0, 900, "88 38 43 00 16 1D 48 00 00", 1, "ECI-900 B2 (no conversion)" }, + /* 84*/ { UNICODE_MODE, 16384, -1, "é", -1, 0, 16384, "8C 04 00 03 00 16 1D 48 00", 0, "ECI-16384 B2 (no conversion); ZXing-C++ test can't handle UNICODE_MODE binary" }, + /* 85*/ { DATA_MODE, 16384, -1, "\303\251", -1, 0, 16384, "8C 04 00 03 00 16 1D 48 00", 1, "ECI-16384 B2 (no conversion)" }, + /* 86*/ { UNICODE_MODE, 3, -1, "β", -1, ZINT_ERROR_INVALID_DATA, 3, "Error 545: Invalid character in input data for ECI 3", 1, "" }, + /* 87*/ { GS1_MODE, -1, -1, "[10]01", -1, ZINT_ERROR_INVALID_OPTION, 0, "Error 220: Selected symbology does not support GS1 mode", 1, "" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol; char escaped[1024]; + 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 testStart("test_input"); @@ -284,15 +297,34 @@ static void test_input(int index, int generate, int debug) { assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, %d, %s, \"%s\", %d, %s, %d, \"%s\", \"%s\" },\n", + printf(" /*%3d*/ { %s, %d, %s, \"%s\", %d, %s, %d, \"%s\", %d, \"%s\" },\n", i, testUtilInputModeName(data[i].input_mode), data[i].eci, testUtilOption3Name(data[i].option_3), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].length, - testUtilErrorName(data[i].ret), ret < ZINT_ERROR ? symbol->eci : -1, symbol->errtxt, data[i].comment); + testUtilErrorName(data[i].ret), ret < ZINT_ERROR ? symbol->eci : -1, symbol->errtxt, + data[i].zxingcpp_cmp, data[i].comment); } else { if (ret < ZINT_ERROR) { assert_equal(symbol->eci, data[i].expected_eci, "i:%d eci %d != %d\n", i, symbol->eci, data[i].expected_eci); } assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + + if (ret < ZINT_ERROR) { + if (do_zxingcpp && testUtilCanZXingCPP(i, symbol, data[i].data, length, debug)) { + if (!data[i].zxingcpp_cmp) { + if (debug & ZINT_DEBUG_TEST_PRINT) printf("i:%d %s not ZXing-C++ compatible (%s)\n", i, testUtilBarcodeName(symbol->symbology), data[i].comment); + } else { + int cmp_len, ret_len; + char modules_dump[189 * 189 + 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); @@ -371,7 +403,7 @@ static void test_encode(int index, int generate, int debug) { "1110101010000010000000001" "1110101011000100101111111" }, - /* 2*/ { UNICODE_MODE, -1, -1, 24, 3 << 8, "汉信码标准\015\012中国物品编码中心\015\012北京网路畅想科技发展有限公司\015\012张成海、赵楠、黄燕滨、罗秋科、王毅、张铎、王越\015\012施煜、边峥、修兴强\015\012汉信码标准\015\012中国物品编码中心\015\012北京网路畅想科技发展有限公司", -1, ZINT_WARN_NONCOMPLIANT, 69, 69, "ISO 20830 Figure 2 **NOT SAME** different encodation, Binary mode not used by figure", + /* 2*/ { UNICODE_MODE, -1, -1, 24, 3 << 8, "汉信码标准\015\012中国物品编码中心\015\012北京网路畅想科技发展有限公司\015\012张成海、赵楠、黄燕滨、罗秋科、王毅、张铎、王越\015\012施煜、边峥、修兴强\015\012汉信码标准\015\012中国物品编码中心\015\012北京网路畅想科技发展有限公司", -1, ZINT_WARN_NONCOMPLIANT, 69, 69, "ISO 20830 Figure 2 **NOT SAME** different encodation, Binary mode not used by figure, nor Region One/Two 0xFFE switching (same if force mode 11111tt11111111tt11111111111111tt11111211111111111112111tt121121111tt11111tt11111111tt11111111111111 and disable Region One/Two 0xFFE switch", "111111100000010101011111111111111111000001110110100100011010101111111" "100000001000101000000000000000000010100000101100000001101001100000001" "101111100010110110110000010011001010001011001011111000011101001111101" @@ -796,7 +828,7 @@ static void test_encode(int index, int generate, int debug) { "11101010111010000000001" "11101010011010001111111" }, - /* 13*/ { UNICODE_MODE, -1, -1, -1, 3 << 8, "汉信码标准", -1, ZINT_WARN_NONCOMPLIANT, 23, 23, "ISO 20830 Figure 4, explict mask 10, same except no alternating filler", + /* 13*/ { UNICODE_MODE, -1, -1, -1, 3 << 8, "汉信码标准", -1, ZINT_WARN_NONCOMPLIANT, 23, 23, "ISO 20830 Figure 4, explicit mask 10, same except no alternating filler", "11111110100001101111111" "10000000101011100000001" "10111110101110001111101" @@ -1753,7 +1785,7 @@ static void test_encode(int index, int generate, int debug) { "11101010110101000000001" "11101010101010001111111" }, - /* 32*/ { UNICODE_MODE, 7, 2, -1, -1, "Россия", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 7 Example 1 **NOT SAME** different encodation, figure uses Region 1", + /* 32*/ { UNICODE_MODE, 7, 2, -1, -1, "Россия", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 7 Example 1 **NOT SAME** different encodation, figure uses Region One", "11111110011010101111111" "10000000010101100000001" "10111110001010001111101" @@ -2021,7 +2053,7 @@ static void test_encode(int index, int generate, int debug) { "11101010111110000000001" "11101010101010001111111" }, - /* 42*/ { UNICODE_MODE, 13, 2, -1, -1, "บาร๋แค่ด", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 13 Example 1 **NOT SAME** example uses Region 1", + /* 42*/ { UNICODE_MODE, 13, 2, -1, -1, "บาร๋แค่ด", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 13 Example 1 **NOT SAME** example uses Region One", "11111110011010101111111" "10000000010101100000001" "10111110001010001111101" @@ -2558,7 +2590,7 @@ static void test_encode(int index, int generate, int debug) { "11101010110101000000001" "11101010101010001111111" }, - /* 63*/ { UNICODE_MODE, 29, 2, -1, -1, "条码", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 29 Example 1 **NOT SAME** example uses Region 1 mode", + /* 63*/ { UNICODE_MODE, 29, 2, -1, -1, "条码", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 29 Example 1 **NOT SAME** example uses Region One mode", "11111110011010101111111" "10000000010001100000001" "10111110001010001111101" @@ -2583,7 +2615,7 @@ static void test_encode(int index, int generate, int debug) { "11101010110101000000001" "11101010101010001111111" }, - /* 64*/ { UNICODE_MODE, 29, 2, -1, -1, "北京", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 29 Example 2 **NOT SAME** example uses Region 1 mode", + /* 64*/ { UNICODE_MODE, 29, 2, -1, -1, "北京", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 29 Example 2 **NOT SAME** example uses Region One mode", "11111110011010101111111" "10000000010001100000001" "10111110001010001111101" @@ -2608,7 +2640,7 @@ static void test_encode(int index, int generate, int debug) { "11101010110101000000001" "11101010101010001111111" }, - /* 65*/ { UNICODE_MODE, 30, 2, -1, -1, "바코드", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 30 Example 1 **NOT SAME** example uses Region 1 mode", + /* 65*/ { UNICODE_MODE, 30, 2, -1, -1, "바코드", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 30 Example 1 **NOT SAME** example uses Region One mode", "11111110011010101111111" "10000000010001100000001" "10111110001010001111101" @@ -2633,7 +2665,7 @@ static void test_encode(int index, int generate, int debug) { "11101010110101000000001" "11101010101010001111111" }, - /* 66*/ { UNICODE_MODE, 30, 2, -1, -1, "서울", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 30 Example 2 **NOT SAME** example uses Region 1 mode", + /* 66*/ { UNICODE_MODE, 30, 2, -1, -1, "서울", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 30 Example 2 **NOT SAME** example uses Region One mode", "11111110011010101111111" "10000000010001100000001" "10111110001010001111101" @@ -2658,7 +2690,7 @@ static void test_encode(int index, int generate, int debug) { "11101010110101000000001" "11101010101010001111111" }, - /* 67*/ { UNICODE_MODE, 31, 2, -1, -1, "条码", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 31 Example 1 **NOT SAME** example uses Region 1 mode", + /* 67*/ { UNICODE_MODE, 31, 2, -1, -1, "条码", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 31 Example 1 **NOT SAME** example uses Region One mode", "11111110011010101111111" "10000000010001100000001" "10111110001010001111101" @@ -2683,7 +2715,7 @@ static void test_encode(int index, int generate, int debug) { "11101010110101000000001" "11101010101010001111111" }, - /* 68*/ { UNICODE_MODE, 31, 2, -1, -1, "北京", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 31 Example 2 **NOT SAME** example uses Region 1 mode", + /* 68*/ { UNICODE_MODE, 31, 2, -1, -1, "北京", -1, 0, 23, 23, "AIM ITS/04-023:2022 ECI 31 Example 2 **NOT SAME** example uses Region One mode", "11111110011001001111111" "10000000000000000000001" "10111110011111101111101" @@ -3228,6 +3260,309 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +static void test_encode_segs(int index, int generate, int debug) { + + struct item { + int input_mode; + int option_1; + int option_2; + int option_3; + struct zint_seg segs[3]; + int ret; + + int expected_rows; + int expected_width; + char *comment; + char *expected; + }; + struct item data[] = { + /* 0*/ { UNICODE_MODE, -1, -1, -1, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 7 }, { TU(""), 0, 0 } }, 0, 23, 23, "Standard example", + "11111110101100101111111" + "10000000010110000000001" + "10111110110000001111101" + "10100000110101000000101" + "10101110001010101110101" + "10101110111110101110101" + "10101110001100001110101" + "00000000101110100000000" + "00010101111111001000000" + "11111101010110101111001" + "00111010100000101010110" + "10000101011001001100101" + "11001000111111101010100" + "00010100101000101011001" + "00000010011010110101000" + "00000000101011100000000" + "11111110000000001110101" + "00000010110111101110101" + "11111010110101001110101" + "00001010001000100000101" + "11101010000110101111101" + "11101010010110000000001" + "11101010101010101111111" + }, + /* 1*/ { UNICODE_MODE, -1, -1, -1, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 23, 23, "Standard example auto-ECI", + "11111110101100101111111" + "10000000010110000000001" + "10111110110000001111101" + "10100000110101000000101" + "10101110001010101110101" + "10101110111110101110101" + "10101110001100001110101" + "00000000101110100000000" + "00010101111111001000000" + "11111101010110101111001" + "00111010100000101010110" + "10000101011001001100101" + "11001000111111101010100" + "00010100101000101011001" + "00000010011010110101000" + "00000000101011100000000" + "11111110000000001110101" + "00000010110111101110101" + "11111010110101001110101" + "00001010001000100000101" + "11101010000110101111101" + "11101010010110000000001" + "11101010101010101111111" + }, + /* 2*/ { UNICODE_MODE, -1, -1, -1, { { TU("Ж"), -1, 7 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, 0, 23, 23, "Standard example inverted", + "11111110111010001111111" + "10000000110110000000001" + "10111110111000101111101" + "10100000100010000000101" + "10101110001100001110101" + "10101110111010001110101" + "10101110010010001110101" + "00000000010101000000000" + "00010101101011110000000" + "00010100111110000010001" + "11100000000010101011000" + "10001001100101010100110" + "10101001111000110001111" + "00110100010101001111000" + "00000001101010110101000" + "00000000010110000000000" + "11111110001101001110101" + "00000010010101101110101" + "11111010001011001110101" + "00001010010110100000101" + "11101010101010101111101" + "11101010010101100000001" + "11101010001010101111111" + }, + /* 3*/ { UNICODE_MODE, -1, -1, -1, { { TU("Ж"), -1, 0 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 23, 23, "Standard example inverted auto-ECI", + "11111110111010001111111" + "10000000110110000000001" + "10111110111000101111101" + "10100000100010000000101" + "10101110001100001110101" + "10101110111010001110101" + "10101110010010001110101" + "00000000010101000000000" + "00010101101011110000000" + "00010100111110000010001" + "11100000000010101011000" + "10001001100101010100110" + "10101001111000110001111" + "00110100010101001111000" + "00000001101010110101000" + "00000000010110000000000" + "11111110001101001110101" + "00000010010101101110101" + "11111010001011001110101" + "00001010010110100000101" + "11101010101010101111101" + "11101010010101100000001" + "11101010001010101111111" + }, + /* 4*/ { UNICODE_MODE, -1, -1, 4 << 8, { { TU("product:Google Pixel 4a - 128 GB of Storage - Black;price:$439.97"), -1, 3 }, { TU("品名:Google 谷歌 Pixel 4a -128 GB的存储空间-黑色;零售价:¥3149.79"), -1, 29 }, { TU("Produkt:Google Pixel 4a - 128 GB Speicher - Schwarz;Preis:444,90 €"), -1, 17 } }, 0, 51, 51, "AIM ITS/04-023:2022 Annex A example **NOT SAME ** example corrupt???", + "111111100111111110011011000110010101001011101111111" + "100000000000000011100101000111110000010100100000001" + "101111101110011011101101000011010010010001001111101" + "101000001001111010100101100101010111101100100000101" + "101011100001110010100101010100111100010110001110101" + "101011101000000011001001010001100001000011001110101" + "101011101001101011110101011110100011100100001110101" + "000000000000000011011110101000100111010001100000000" + "001000110010011010000001111010101101101100001000000" + "001010111000010011111011010010001101111101001001011" + "110010110000111010001010001111000001000110001001010" + "111100100000011010101001100000101101010001011010101" + "100010001001110010101001010001100011110011101001011" + "111001111101010011011111111101000010110100000011101" + "000100000100010010110111110000110100111011010011000" + "011001011101001011100101110010101010011101110011011" + "001100010000001011110101011000000010001111101010100" + "101011100100010011111111111111111101011000010100101" + "000111010000010000000000000000000110001101111011100" + "100001011001110000011011010111000101001111101101010" + "101000111100100101110100001001010111010000010010000" + "110101000011101100100010001100110110011100110010000" + "111101100011001000011101101110010101001010101010110" + "110100100010010011011011111011000100011100000101010" + "100011011101110000011101101001000100010010001110110" + "111110010100001001110110000001000101011111011001011" + "111101100101111110010000101001110111010011001110011" + "111000001110111101100100010100100111100101101100110" + "110000110011101100001111001100110101000010000110001" + "101110001001011110101001110101100101110001001100001" + "111101000101011001011111001101000111111010010001000" + "110010011000111100011011001100010111101011110101001" + "111100111101111111011101111110000111101100010100010" + "110001011010011101111100110100100111001110011100001" + "111111111111111110011011000100000111111111111111111" + "000000000000000011001010100111010000000000000000001" + "111010001110010010110011000010100110010010010111101" + "001100111011101011011100110010100101011101010101101" + "100010010001101010100111110101111101001001011101101" + "001100001000111010111110011000000000000010000011001" + "110101100010111010100010101001111010110011110100001" + "111011101001011010111111101101011101000001010101101" + "000000100011001011110010011110010010110000011000100" + "000000001001101010101111000010000011000100000000000" + "111111100101101011101001011000111110100111101110101" + "000000100101100011010011110011000101101100101110101" + "111110100110010010000111010110111001001101001110101" + "000010101010110010011001111100010010001010100000101" + "111010100110011010000010110001111100010001101111101" + "111010101000000011001110011001100001110110000000001" + "111010101011000011111111111111110101110100001111111" + }, + /* 5*/ { DATA_MODE, -1, -1, -1, { { TU("\266"), 1, 0 }, { TU("\266"), 1, 7 }, { TU("\266"), 1, 0 } }, 0, 23, 23, "Standard example + extra seg, data mode", + "11111110101100001111111" + "10000000110110000000001" + "10111110110101101111101" + "10100000100101000000101" + "10101110001010001110101" + "10101110110001001110101" + "10101110010100001110101" + "00000000001110000000000" + "00010101101001110000000" + "10011101010001000011001" + "00111100100000101010010" + "11110101011000100100101" + "11000000001101101010100" + "00100110110011010010110" + "00000001101010110101000" + "00000000010111000000000" + "11111110011110001110101" + "00000010000110101110101" + "11111010000110001110101" + "00001010000100100000101" + "11101010101100101111101" + "11101010010101100000001" + "11101010001010101111111" + }, + /* 6*/ { UNICODE_MODE, -1, -1, -1, { { TU("éÿ"), -1, 0 }, { TU("กขฯ"), -1, 13 }, { TU("αβγώ"), -1, 0 } }, ZINT_WARN_USES_ECI, 23, 23, "Auto-ECI", + "11111110001100001111111" + "10000000110101100000001" + "10111110001010101111101" + "10100000110101100000101" + "10101110001001101110101" + "10101110110010001110101" + "10101110001001001110101" + "00000000000001100000000" + "00010101001101011000000" + "11001010101111101100110" + "10101101010111000011011" + "01010001010101010101010" + "10010010101010001011000" + "00011110010000110000101" + "00000011001101010101000" + "00000000101111000000000" + "11111110001010001110101" + "00000010010101101110101" + "11111010101110001110101" + "00001010111010100000101" + "11101010111000001111101" + "11101010111001100000001" + "11101010001010001111111" + }, + }; + int data_size = ARRAY_SIZE(data); + int i, j, seg_count, ret; + struct zint_symbol *symbol; + + 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 + + testStart("test_encode_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + testUtilSetSymbol(symbol, BARCODE_HANXIN, data[i].input_mode, -1 /*eci*/, + data[i].option_1, data[i].option_2, data[i].option_3, -1 /*output_options*/, + NULL, 0, debug); + for (j = 0, seg_count = 0; j < 3 && data[i].segs[j].length; j++, seg_count++); + + ret = ZBarcode_Encode_Segs(symbol, data[i].segs, seg_count); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode_Segs ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + char escaped1[8192]; + char escaped2[8192]; + int length = data[i].segs[0].length == -1 ? (int) ustrlen(data[i].segs[0].source) : data[i].segs[0].length; + int length1 = data[i].segs[1].length == -1 ? (int) ustrlen(data[i].segs[1].source) : data[i].segs[1].length; + int length2 = data[i].segs[2].length == -1 ? (int) ustrlen(data[i].segs[2].source) : data[i].segs[2].length; + printf(" /*%3d*/ { %s, %d, %d, %s, { { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d } }, %s, %d, %d, \"%s\",\n", + i, testUtilInputModeName(data[i].input_mode), + data[i].option_1, data[i].option_2, testUtilOption3Name(data[i].option_3), + testUtilEscape((const char *) data[i].segs[0].source, length, escaped, sizeof(escaped)), data[i].segs[0].length, data[i].segs[0].eci, + testUtilEscape((const char *) data[i].segs[1].source, length1, escaped1, sizeof(escaped1)), data[i].segs[1].length, data[i].segs[1].eci, + testUtilEscape((const char *) data[i].segs[2].source, length2, escaped2, sizeof(escaped2)), data[i].segs[2].length, data[i].segs[2].eci, + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment); + testUtilModulesPrint(symbol, " ", "\n"); + printf(" },\n"); + } else { + if (ret < ZINT_ERROR) { + int width, row; + 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); + + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d\n", i, ret, width, row); + + if (do_zxingcpp) { + if ((symbol->input_mode & 0x07) == DATA_MODE) { + if (debug & ZINT_DEBUG_TEST_PRINT) { + printf("i:%d multiple segments in DATA_MODE not currently supported for ZXing-C++ testing (%s)\n", + i, testUtilBarcodeName(symbol->symbology)); + } + } else { + int length = data[i].segs[0].length == -1 ? (int) ustrlen(data[i].segs[0].source) : data[i].segs[0].length; + if (testUtilCanZXingCPP(i, symbol, (const char *) data[i].segs[0].source, length, debug)) { + int cmp_len, ret_len; + char modules_dump[49152]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilZXingCPP(i, symbol, (const char *) data[i].segs[0].source, 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 = testUtilZXingCPPCmpSegs(symbol, cmp_msg, cmp_buf, cmp_len, data[i].segs, seg_count, + NULL /*primary*/, escaped, &ret_len); + assert_zero(ret, "i:%d %s testUtilZXingCPPCmpSegs %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); + } + + testFinish(); +} + #include #define TEST_PERF_ITERATIONS 1000 @@ -3250,7 +3585,7 @@ static void test_perf(int index, int debug) { struct item data[] = { /* 0*/ { BARCODE_HANXIN, UNICODE_MODE, -1, -1, "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。", - 0, 43, 43, "98 chars, Region 1 and Text" }, + 0, 43, 43, "98 chars, Region One and Text" }, /* 1*/ { BARCODE_HANXIN, UNICODE_MODE, -1, -1, "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" @@ -3262,7 +3597,7 @@ static void test_perf(int index, int debug) { "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。", - 0, 121, 121, "980 chars, Region 1 and Text" }, + 0, 121, 121, "980 chars, Region One and Text" }, /* 2*/ { BARCODE_HANXIN, UNICODE_MODE, -1, -1, "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" @@ -3279,7 +3614,7 @@ static void test_perf(int index, int debug) { "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。", - 0, 147, 147, "1470 chars, Region 1 and Text" }, + 0, 147, 147, "1470 chars, Region One and Text" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -3336,6 +3671,7 @@ int main(int argc, char *argv[]) { { "test_options", test_options, 1, 0, 1 }, { "test_input", test_input, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_encode_segs", test_encode_segs, 1, 1, 1 }, { "test_perf", test_perf, 1, 0, 1 }, }; diff --git a/backend/tests/test_imail.c b/backend/tests/test_imail.c index b23c26b8..e89c7348 100644 --- a/backend/tests/test_imail.c +++ b/backend/tests/test_imail.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2019 - 2021 Robin Stuart + Copyright (C) 2019-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ /* * Intelligent Mail barcode Encoder Test Case Reference Set (csv file) * Copyright (C) 2009 U.S. Postal Service @@ -280,7 +279,7 @@ static void test_encode(int index, int generate, int debug) { assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) { - ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -311,3 +310,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_library.c b/backend/tests/test_library.c index ec512e97..852e4354 100644 --- a/backend/tests/test_library.c +++ b/backend/tests/test_library.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2019 - 2021 Robin Stuart + Copyright (C) 2019-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "testcommon.h" #include @@ -61,7 +60,7 @@ static void test_checks(int index, int debug) { /* 0*/ { BARCODE_CODE128, -1, "1234", -1, -1, 3, 0, 0, 0, 0, -1, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 217: Symbology does not support ECI switching", -1 }, /* 1*/ { BARCODE_CODE128, -1, "1234", -1, -1, 0, 0, 0, 0, 0, -1, -1, -1, -1, 0, "", -1 }, /* 2*/ { BARCODE_QRCODE, -1, "1234", -1, -1, 3, 0, 0, 0, 0, -1, -1, -1, -1, 0, "", -1 }, - /* 3*/ { BARCODE_QRCODE, -1, "1234", -1, -1, 999999 + 1, 0, 0, 0, 0, -1, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 218: Invalid ECI mode", -1 }, + /* 3*/ { BARCODE_QRCODE, -1, "1234", -1, -1, 999999 + 1, 0, 0, 0, 0, -1, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 218: Invalid ECI code 1000000", -1 }, /* 4*/ { BARCODE_CODE128, -1, "1234", -1, -1, -1, 0, 0, 0, 0, 0.009, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 227: Scale out of range (0.01 to 100)", -1 }, /* 5*/ { BARCODE_CODE128, -1, "1234", -1, -1, -1, 0, 0, 0, 0, 100.01, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 227: Scale out of range (0.01 to 100)", -1 }, /* 6*/ { BARCODE_CODE128, -1, "1234", -1, -1, -1, 0, 0, 0, 0, -1, 20.1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 221: Dot size out of range (0.01 to 20)", -1 }, @@ -251,7 +250,7 @@ static void test_checks(int index, int debug) { symbol->warn_level = data[i].warn_level; } - ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + ret = ZBarcode_Encode(symbol, TU(data[i].data), length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode(%d) ret %d != %d (%s)\n", i, data[i].symbology, ret, data[i].ret, symbol->errtxt); ret = strcmp(symbol->errtxt, data[i].expected); @@ -269,6 +268,68 @@ static void test_checks(int index, int debug) { testFinish(); } +static void test_checks_segs(int index, int debug) { + + struct item { + int symbology; + int option_1; + struct zint_seg segs[2]; + int seg_count; + int input_mode; + int eci; + int warn_level; + int ret; + + char *expected; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { BARCODE_CODE128, -1, { { NULL, 0, 0 }, { NULL, 0, 0 } }, 0, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 205: Input segment count 0" }, + /* 1*/ { BARCODE_CODE128, -1, { { NULL, 0, 0 }, { NULL, 0, 0 } }, 257, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 771: Too many input segments (max 256)" }, + /* 2*/ { BARCODE_CODE128, -1, { { NULL, 0, 0 }, { NULL, 0, 0 } }, 1, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 772: Input segment 0 source NULL" }, + /* 3*/ { BARCODE_CODE128, -1, { { TU(""), 0, 0 }, { NULL, 0, 0 } }, 1, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 773: Input segment 0 length zero" }, + /* 4*/ { BARCODE_CODE128, -1, { { TU("A"), 0, 0 }, { NULL, 0, 0 } }, 2, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 772: Input segment 1 source NULL" }, + /* 4*/ { BARCODE_CODE128, -1, { { TU("A"), 0, 0 }, { TU(""), 0, 0 } }, 2, -1, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 773: Input segment 1 length zero" }, + /* 5*/ { BARCODE_CODE128, -1, { { TU("A"), 0, 3 }, { TU("B"), 0, 0 } }, 2, -1, 4, -1, ZINT_ERROR_INVALID_OPTION, "Error 774: Symbol ECI 4 must match segment zero ECI 3" }, + /* 6*/ { BARCODE_CODE128, -1, { { TU("A"), 0, 3 }, { TU("B"), 0, 4 } }, 2, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 775: Symbology does not support multiple segments" }, + /* 7*/ { BARCODE_CODE128, -1, { { TU("A"), 0, 3 }, { NULL, 0, 0 } }, 1, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 217: Symbology does not support ECI switching" }, + /* 8*/ { BARCODE_AZTEC, -1, { { TU("A"), 0, 3 }, { TU("B"), 0, 1 } }, 2, -1, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 218: Invalid ECI code 1" }, + /* 9*/ { BARCODE_AZTEC, -1, { { TU("A"), 0, 3 }, { TU("B"), 0, 4 } }, 2, GS1_MODE, -1, -1, ZINT_ERROR_INVALID_OPTION, "Error 776: GS1_MODE not supported for multiple segments" }, + /* 10*/ { BARCODE_AZTEC, -1, { { TU("A"), 0, 3 }, { TU("\200"), 0, 4 } }, 2, UNICODE_MODE, -1, -1, ZINT_ERROR_INVALID_DATA, "Error 245: Invalid UTF-8 in input data" }, + /* 11*/ { BARCODE_AZTEC, -1, { { TU("A"), 0, 3 }, { TU("B"), 0, 4 } }, 2, -1, -1, -1, 0, "" }, + /* 12*/ { BARCODE_AZTEC, -1, { { TU("A"), 0, 0 }, { TU("B"), 0, 4 } }, 2, -1, 3, -1, 0, "" }, + /* 13*/ { BARCODE_AZTEC, -1, { { TU("A"), ZINT_MAX_DATA_LEN, 3 }, { TU("B"), 1, 4 } }, 2, -1, -1, -1, ZINT_ERROR_TOO_LONG, "Error 243: Input data too long" }, + }; + int data_size = ARRAY_SIZE(data); + int i, ret; + struct zint_symbol *symbol; + + testStart("test_checks_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, data[i].eci, data[i].option_1, -1, -1, -1 /*output_options*/, NULL, 0, debug); + if (data[i].warn_level != -1) { + symbol->warn_level = data[i].warn_level; + } + + ret = ZBarcode_Encode_Segs(symbol, data[i].segs, data[i].seg_count); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode_Segs(%d) ret %d != %d (%s)\n", i, data[i].symbology, ret, data[i].ret, symbol->errtxt); + + ret = strcmp(symbol->errtxt, data[i].expected); + assert_zero(ret, "i:%d (%d) strcmp(%s, %s) %d != 0\n", i, data[i].symbology, symbol->errtxt, data[i].expected, ret); + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + static void test_symbologies(void) { int i, ret; struct zint_symbol symbol = {0}; @@ -277,7 +338,7 @@ static void test_symbologies(void) { for (i = -1; i < 148; i++) { symbol.symbology = i; - ret = ZBarcode_Encode(&symbol, (unsigned char *) "1", 0); + ret = ZBarcode_Encode(&symbol, TU("1"), 0); assert_notequal(ret, ZINT_ERROR_ENCODING_PROBLEM, "i:%d Encoding problem (%s)\n", i, symbol.errtxt); } @@ -322,7 +383,7 @@ static void test_input_mode(int index, int debug) { length = testUtilSetSymbol(symbol, BARCODE_CODE49 /*Supports GS1*/, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); - ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + ret = ZBarcode_Encode(symbol, TU(data[i].data), length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); assert_equal(symbol->input_mode, data[i].expected_input_mode, "i:%d symbol->input_mode %d != %d\n", i, symbol->input_mode, data[i].expected_input_mode); @@ -349,7 +410,7 @@ static void test_escape_char_process(int index, int generate, int debug) { /* 0*/ { BARCODE_DATAMATRIX, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\e\\G\\R\\x81\\\\", 0, 26, "01 05 08 09 0A 0B 0C 0D 0E 1C 1E 1F EB 02 5D 81 21 0D 92 2E 3D FD B6 9A 37 2A CD 61 FB 95", 0, "" }, /* 1*/ { BARCODE_CODABLOCKF, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\e\\G\\R\\x81\\\\", 0, 101, "(45) 67 62 43 40 44 47 48 29 6A 67 62 0B 49 4A 4B 4C 18 6A 67 62 0C 4D 5B 5D 5E 62 6A 67", 0, "" }, /* 2*/ { BARCODE_CODE16K, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\e\\G\\R\\x81\\\\", 0, 70, "(20) 14 64 68 71 72 73 74 75 76 77 91 93 94 101 65 60 103 103 45 61", 0, "" }, - /* 3*/ { BARCODE_DOTCODE, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\e\\G\\R\\x81\\\\", 0, 28, "65 40 44 47 48 49 4A 4B 4C 4D 5B 5D 5E 6E 41 3C", 0, "" }, + /* 3*/ { BARCODE_DOTCODE, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\e\\G\\R\\x81\\\\", 0, 28, "65 40 44 47 48 49 4A 4B 4C 4D 5B 5D 5E 6E 41 3C 6A", 0, "" }, /* 4*/ { BARCODE_GRIDMATRIX, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\e\\G\\R\\x81\\\\", 0, 30, "30 1A 00 02 01 61 00 48 28 16 0C 06 46 63 51 74 05 38 00", 0, "" }, /* 5*/ { BARCODE_HANXIN, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\e\\G\\R\\x81\\\\", 0, 23, "2F 80 10 72 09 28 B3 0D 6F F3 00 20 E8 F4 0A E0 00", 0, "" }, /* 6*/ { BARCODE_MAXICODE, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\e\\G\\R\\x81\\\\", 0, 30, "(144) 04 3E 3E 00 04 07 08 09 0A 0B 03 3D 2C 24 19 1E 23 1B 18 0E 0C 0D 1E 21 3C 1E 3C 31", 0, "" }, @@ -380,6 +441,7 @@ static void test_escape_char_process(int index, int generate, int debug) { /* 31*/ { BARCODE_DATAMATRIX, DATA_MODE, 17, "\\xA4", 0, 12, "F1 12 EB 25 81 4A 0A 8C 31 AC E3 2E", 1, "" }, /* 32*/ { BARCODE_DATAMATRIX, DATA_MODE, 28, "\\xB1\\x60", 0, 12, "F1 1D EB 32 61 D9 1C 0C C2 46 C3 B2", 0, "Zint manual 4.10 Ex2" }, /* 33*/ { BARCODE_DATAMATRIX, UNICODE_MODE, 28, "\\u5E38", 0, 12, "F1 1D EB 32 61 D9 1C 0C C2 46 C3 B2", 1, "" }, + /* 34*/ { BARCODE_DATAMATRIX, UNICODE_MODE, -1, "\\u007F", 0, 10, "80 81 46 73 64 88 6A 84", 0, "" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -403,7 +465,7 @@ static void test_escape_char_process(int index, int generate, int debug) { length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode | ESCAPE_MODE, data[i].eci, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); - ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); + ret = ZBarcode_Encode(symbol, TU(data[i].data), length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { @@ -711,12 +773,104 @@ static void test_encode_file_directory(void) { testFinish(); } +static void test_encode_file(void) { + int ret; + struct zint_symbol *symbol; + char *data = "1"; + char *filename = "test_encode_file_in.txt"; + char *outfile = "test_encode_file_out.gif"; + FILE *fp; + + testStart("test_encode_file"); + + (void) remove(filename); // In case junk hanging around + (void) remove(outfile); // In case junk hanging around + + fp = fopen(filename, "w+"); + assert_nonnull(fp, "fopen(%s) failed (%d)\n", filename, ferror(fp)); + assert_notequal(fputs(data, fp), EOF, "fputs(%s) failed == EOF (%d)\n", data, ferror(fp)); + ret = fclose(fp); + assert_zero(ret, "fclose(%s) %d != 0\n", filename, ret); + + { + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + strcpy(symbol->outfile, outfile); + ret = ZBarcode_Encode_File_and_Print(symbol, filename, 0); + assert_zero(ret, "ret %d != 0 (%s)\n", ret, symbol->errtxt); + + ret = remove(outfile); + assert_zero(ret, "remove(%s) != 0 (%d: %s)\n", outfile, errno, strerror(errno)); + + ZBarcode_Delete(symbol); + } + + { + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + strcpy(symbol->outfile, outfile); + ret = ZBarcode_Encode_File_and_Buffer(symbol, filename, 0); + assert_zero(ret, "ret %d != 0 (%s)\n", ret, symbol->errtxt); + assert_nonnull(symbol->bitmap, "symbol->bitmap NULL (%s)\n", symbol->errtxt); + + ZBarcode_Delete(symbol); + } + + { + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + strcpy(symbol->outfile, outfile); + ret = ZBarcode_Encode_File_and_Buffer_Vector(symbol, filename, 0); + assert_zero(ret, "ret %d != 0 (%s)\n", ret, symbol->errtxt); + assert_nonnull(symbol->vector, "symbol->vector NULL (%s)\n", symbol->errtxt); + + ZBarcode_Delete(symbol); + } + + ret = remove(filename); + assert_zero(ret, "remove(%s) != 0 (%d: %s)\n", filename, errno, strerror(errno)); + + testFinish(); +} + +static void test_encode_print_outfile_directory(void) { + int ret; + struct zint_symbol *symbol; + char dirname[] = "outdir.txt"; + + testStart("test_encode_print_outfile_directory"); + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + (void) testUtilRmDir(dirname); // In case junk hanging around + ret = testUtilMkDir(dirname); + assert_zero(ret, "testUtilMkDir(%s) %d != 0 (%d: %s)\n", dirname, ret, errno, strerror(errno)); + + strcpy(symbol->outfile, dirname); + ret = ZBarcode_Encode_and_Print(symbol, TU("1"), 0, 0); + assert_equal(ret, ZINT_ERROR_FILE_ACCESS, "ret %d != ZINT_ERROR_FILE_ACCESS (%s)\n", ret, symbol->errtxt); + + ret = testUtilRmDir(dirname); + assert_zero(ret, "testUtilRmDir(%s) %d != 0 (%d: %s)\n", dirname, ret, errno, strerror(errno)); + + ZBarcode_Delete(symbol); + + testFinish(); +} + static void test_bad_args(void) { int ret; struct zint_symbol *symbol; char *data = "1"; char *filename = "1.png"; char *empty = ""; + struct zint_seg seg = { TU("1"), -1, 4 }; + struct zint_seg seg_empty = { TU(""), -1, 4 }; + struct zint_seg seg_too_long = { TU("1"), ZINT_MAX_DATA_LEN + 1, 4 }; testStart("test_bad_args"); @@ -736,12 +890,17 @@ static void test_bad_args(void) { assert_zero(ret, "ZBarcode_Cap(10, ~0) ret 0x%X != 0\n", ret); // NULL symbol - assert_equal(ZBarcode_Encode(NULL, (unsigned char *) data, 1), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode(NULL, data, 1) != ZINT_ERROR_INVALID_DATA\n"); + assert_equal(ZBarcode_Encode(NULL, TU(data), 1), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode(NULL, data, 1) != ZINT_ERROR_INVALID_DATA\n"); + assert_equal(ZBarcode_Encode_Segs(NULL, &seg, 1), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_Segs(NULL, &seg, 1) != ZINT_ERROR_INVALID_DATA\n"); assert_equal(ZBarcode_Print(NULL, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Print(NULL, 0) != ZINT_ERROR_INVALID_DATA\n"); assert_equal(ZBarcode_Buffer(NULL, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Buffer(NULL, 0) != ZINT_ERROR_INVALID_DATA\n"); assert_equal(ZBarcode_Buffer_Vector(NULL, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Buffer_Vector(NULL, 0) != ZINT_ERROR_INVALID_DATA\n"); - assert_equal(ZBarcode_Encode_and_Print(NULL, (unsigned char *) data, 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_and_Print(NULL, data, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); - assert_equal(ZBarcode_Encode_and_Buffer(NULL, (unsigned char *) data, 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_and_Buffer(NULL, data, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_equal(ZBarcode_Encode_and_Print(NULL, TU(data), 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_and_Print(NULL, data, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_equal(ZBarcode_Encode_Segs_and_Print(NULL, &seg, 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_Seg_and_Print(NULL, &seg, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_equal(ZBarcode_Encode_and_Buffer(NULL, TU(data), 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_and_Buffer(NULL, data, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_equal(ZBarcode_Encode_Segs_and_Buffer(NULL, &seg, 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_Segs_and_Buffer(NULL, &seg, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_equal(ZBarcode_Encode_and_Buffer_Vector(NULL, TU(data), 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_and_Buffer_Vector(NULL, data, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_equal(ZBarcode_Encode_Segs_and_Buffer_Vector(NULL, &seg, 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_Segs_and_Buffer_Vector(NULL, &seg, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); assert_equal(ZBarcode_Encode_File(NULL, filename), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_File(NULL, filename) != ZINT_ERROR_INVALID_DATA\n"); assert_equal(ZBarcode_Encode_File_and_Print(NULL, filename, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_File_and_Print(NULL, filename, 0) != ZINT_ERROR_INVALID_DATA\n"); assert_equal(ZBarcode_Encode_File_and_Buffer(NULL, filename, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_File_and_Buffer(NULL, filename, 0) != ZINT_ERROR_INVALID_DATA\n"); @@ -749,17 +908,29 @@ static void test_bad_args(void) { symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - // NULL data/filename + // NULL data/segs/filename symbol->errtxt[0] = '\0'; assert_equal(ZBarcode_Encode(symbol, NULL, 1), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode(symbol, NULL, 1) != ZINT_ERROR_INVALID_DATA\n"); assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode(symbol, NULL, 1) no errtxt\n"); symbol->errtxt[0] = '\0'; + assert_equal(ZBarcode_Encode_Segs(symbol, NULL, 1), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_Segs(symbol, NULL, 1) != ZINT_ERROR_INVALID_DATA\n"); + assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_Segs(symbol, NULL, 1) no errtxt\n"); + symbol->errtxt[0] = '\0'; assert_equal(ZBarcode_Encode_and_Print(symbol, NULL, 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_and_Print(symbol, NULL, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_and_Print(symbol, NULL, 1, 0) no errtxt\n"); symbol->errtxt[0] = '\0'; assert_equal(ZBarcode_Encode_and_Buffer(symbol, NULL, 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_and_Buffer(symbol, NULL, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_and_Buffer(symbol, NULL, 1, 0) no errtxt\n"); symbol->errtxt[0] = '\0'; + assert_equal(ZBarcode_Encode_Segs_and_Buffer(symbol, NULL, 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_Segs_and_Buffer(symbol, NULL, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_Segs_and_Buffer(symbol, NULL, 1, 0) no errtxt\n"); + symbol->errtxt[0] = '\0'; + assert_equal(ZBarcode_Encode_and_Buffer_Vector(symbol, NULL, 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_and_Buffer_Vector(symbol, NULL, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_and_Buffer_Vector(symbol, NULL, 1, 0) no errtxt\n"); + symbol->errtxt[0] = '\0'; + assert_equal(ZBarcode_Encode_Segs_and_Buffer_Vector(symbol, NULL, 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_Segs_and_Buffer_Vector(symbol, NULL, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_Segs_and_Buffer_Vector(symbol, NULL, 1, 0) no errtxt\n"); + symbol->errtxt[0] = '\0'; assert_equal(ZBarcode_Encode_File(symbol, NULL), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_File(symbol, NULL) != ZINT_ERROR_INVALID_DATA\n"); assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_File(symbol, NULL) no errtxt\n"); symbol->errtxt[0] = '\0'; @@ -768,18 +939,33 @@ static void test_bad_args(void) { symbol->errtxt[0] = '\0'; assert_equal(ZBarcode_Encode_File_and_Buffer(symbol, NULL, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_File_and_Buffer(symbol, NULL, 0) != ZINT_ERROR_INVALID_DATA\n"); assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_File_and_Buffer(symbol, NULL, 0) no errtxt\n"); - - // Empty data/filename symbol->errtxt[0] = '\0'; - assert_equal(ZBarcode_Encode(symbol, (unsigned char *) empty, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode(symbol, empty, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_equal(ZBarcode_Encode_File_and_Buffer_Vector(symbol, NULL, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_File_and_Buffer_Vector(symbol, NULL, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_File_and_Buffer_Vector(symbol, NULL, 0) no errtxt\n"); + + // Empty data/segs/filename + symbol->errtxt[0] = '\0'; + assert_equal(ZBarcode_Encode(symbol, TU(empty), 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode(symbol, empty, 0) != ZINT_ERROR_INVALID_DATA\n"); assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode(symbol, empty, 0) no errtxt\n"); symbol->errtxt[0] = '\0'; - assert_equal(ZBarcode_Encode_and_Print(symbol, (unsigned char *) empty, 0, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_and_Print(symbol, empty, 0, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_equal(ZBarcode_Encode_Segs(symbol, &seg_empty, 1), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_Segs(symbol, &seg_empty, 1) != ZINT_ERROR_INVALID_DATA\n"); + assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_Segs(symbol, &seg_empty, 1) no errtxt\n"); + symbol->errtxt[0] = '\0'; + assert_equal(ZBarcode_Encode_and_Print(symbol, TU(empty), 0, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_and_Print(symbol, empty, 0, 0) != ZINT_ERROR_INVALID_DATA\n"); assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_and_Print(symbol, empty, 0, 0) no errtxt\n"); symbol->errtxt[0] = '\0'; - assert_equal(ZBarcode_Encode_and_Buffer(symbol, (unsigned char *) empty, 0, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_and_Buffer(symbol, empty, 0, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_equal(ZBarcode_Encode_and_Buffer(symbol, TU(empty), 0, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_and_Buffer(symbol, empty, 0, 0) != ZINT_ERROR_INVALID_DATA\n"); assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_and_Buffer(symbol, empty, 0, 0) no errtxt\n"); symbol->errtxt[0] = '\0'; + assert_equal(ZBarcode_Encode_Segs_and_Buffer(symbol, &seg_empty, 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_Segs_and_Buffer(symbol, &seg_empty, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_Segs_and_Buffer(symbol, &seg_empty, 1, 0) no errtxt\n"); + symbol->errtxt[0] = '\0'; + assert_equal(ZBarcode_Encode_and_Buffer_Vector(symbol, TU(empty), 0, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_and_Buffer_Vector(symbol, empty, 0, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_and_Buffer_Vector(symbol, empty, 0, 0) no errtxt\n"); + symbol->errtxt[0] = '\0'; + assert_equal(ZBarcode_Encode_Segs_and_Buffer_Vector(symbol, &seg_empty, 1, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_Segs_and_Buffer_Vector(symbol, &seg_empty, 1, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_Segs_and_Buffer_Vector(symbol, &seg_empty, 1, 0) no errtxt\n"); + symbol->errtxt[0] = '\0'; assert_equal(ZBarcode_Encode_File(symbol, empty), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_File(symbol, empty) != ZINT_ERROR_INVALID_DATA\n"); assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_File(symbol, empty) no errtxt\n"); symbol->errtxt[0] = '\0'; @@ -788,11 +974,28 @@ static void test_bad_args(void) { symbol->errtxt[0] = '\0'; assert_equal(ZBarcode_Encode_File_and_Buffer(symbol, empty, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_File_and_Buffer(symbol, empty, 0) != ZINT_ERROR_INVALID_DATA\n"); assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_File_and_Buffer(symbol, empty, 0) no errtxt\n"); - - // Data too big symbol->errtxt[0] = '\0'; - assert_equal(ZBarcode_Encode(symbol, (unsigned char *) empty, ZINT_MAX_DATA_LEN + 1), ZINT_ERROR_TOO_LONG, "ZBarcode_Encode(symbol, empty, ZINT_MAX_DATA_LEN + 1) != ZINT_ERROR_TOO_LONG\n"); + assert_equal(ZBarcode_Encode_File_and_Buffer_Vector(symbol, empty, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_File_and_Buffer_Vector(symbol, empty, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_nonzero(strlen(symbol->errtxt), "ZBarcode_Encode_File_and_Buffer_Vector(symbol, empty, 0) no errtxt\n"); + + // Bad seg_count + symbol->errtxt[0] = '\0'; + assert_equal(ZBarcode_Encode_Segs(symbol, &seg_empty, ZINT_MAX_SEG_COUNT + 1), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_Segs(symbol, &seg_empty, ZINT_MAX_SEG_COUNT + 1) != ZINT_ERROR_INVALID_DATA\n"); + assert_nonzero((int) strlen(symbol->errtxt), "ZBarcode_Encode_Segs(symbol, &seg_empty, ZINT_MAX_SEG_COUNT + 1) no errtxt\n"); + symbol->errtxt[0] = '\0'; + assert_equal(ZBarcode_Encode_Segs(symbol, &seg_empty, 0), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_Segs(symbol, &seg_empty, 0) != ZINT_ERROR_INVALID_DATA\n"); + assert_nonzero((int) strlen(symbol->errtxt), "ZBarcode_Encode_Segs(symbol, &seg_empty, 0) no errtxt\n"); + symbol->errtxt[0] = '\0'; + assert_equal(ZBarcode_Encode_Segs(symbol, &seg_empty, -1), ZINT_ERROR_INVALID_DATA, "ZBarcode_Encode_Segs(symbol, &seg_empty, -1) != ZINT_ERROR_INVALID_DATA\n"); + assert_nonzero((int) strlen(symbol->errtxt), "ZBarcode_Encode_Segs(symbol, &seg_empty, -1) no errtxt\n"); + + // Data/seg too big + symbol->errtxt[0] = '\0'; + assert_equal(ZBarcode_Encode(symbol, TU(empty), ZINT_MAX_DATA_LEN + 1), ZINT_ERROR_TOO_LONG, "ZBarcode_Encode(symbol, empty, ZINT_MAX_DATA_LEN + 1) != ZINT_ERROR_TOO_LONG\n"); assert_nonzero((int) strlen(symbol->errtxt), "ZBarcode_Encode(symbol, empty, ZINT_MAX_DATA_LEN + 1) no errtxt\n"); + symbol->errtxt[0] = '\0'; + assert_equal(ZBarcode_Encode_Segs(symbol, &seg_too_long, 1), ZINT_ERROR_TOO_LONG, "ZBarcode_Encode_Segs(symbol, &seg_too_long, 1) != ZINT_ERROR_TOO_LONG\n"); + assert_nonzero((int) strlen(symbol->errtxt), "ZBarcode_Encode_Segs(symbol, &seg_too_long, 1) no errtxt\n"); ZBarcode_Delete(symbol); @@ -892,7 +1095,7 @@ static void test_strip_bom(void) { strcpy(buf, data); length = (int) strlen(buf); - strip_bom((unsigned char *) buf, &length); + strip_bom(TU(buf), &length); assert_equal(length, 1, "length %d != 1\n", length); assert_zero(buf[1], "buf[1] %d != 0\n", buf[1]); @@ -900,7 +1103,7 @@ static void test_strip_bom(void) { strcpy(buf, bom_only); length = (int) strlen(buf); - strip_bom((unsigned char *) buf, &length); + strip_bom(TU(buf), &length); assert_equal(length, 3, "BOM only length %d != 3\n", length); ret = strcmp(buf, bom_only); assert_zero(ret, "BOM only strcmp ret %d != 0\n", ret); @@ -922,7 +1125,7 @@ static void test_zero_outfile(void) { assert_nonzero(symbol->outfile[0], "ZBarcode_Create() outfile zero\n"); symbol->outfile[0] = '\0'; - ret = ZBarcode_Encode(symbol, (unsigned char *) data, 0); + ret = ZBarcode_Encode(symbol, TU(data), 0); assert_zero(ret, "ZBarcode_Encode(%s) ret %d != 0 (%s)\n", data, ret, symbol->errtxt); assert_zero(symbol->outfile[0], "ZBarcode_Encode() outfile non-zero\n"); @@ -960,7 +1163,7 @@ static void test_clear(void) { // Raster - ret = ZBarcode_Encode(symbol, (unsigned char *) data, 0); + ret = ZBarcode_Encode(symbol, TU(data), 0); assert_zero(ret, "ZBarcode_Encode() ret %d != 0 (%s)\n", ret, symbol->errtxt); assert_nonzero(symbol->rows, "ZBarcode_Encode() rows 0\n"); @@ -993,7 +1196,7 @@ static void test_clear(void) { // Vector - ret = ZBarcode_Encode(symbol, (unsigned char *) data, 0); + ret = ZBarcode_Encode(symbol, TU(data), 0); assert_zero(ret, "ZBarcode_Encode() ret %d != 0 (%s)\n", ret, symbol->errtxt); assert_nonzero(symbol->rows, "ZBarcode_Encode() rows 0\n"); @@ -1035,6 +1238,7 @@ int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ { "test_checks", test_checks, 1, 0, 1 }, + { "test_checks_segs", test_checks_segs, 1, 0, 1 }, { "test_symbologies", test_symbologies, 0, 0, 0 }, { "test_input_mode", test_input_mode, 1, 0, 1 }, { "test_escape_char_process", test_escape_char_process, 1, 1, 1 }, @@ -1044,6 +1248,8 @@ int main(int argc, char *argv[]) { { "test_encode_file_too_large", test_encode_file_too_large, 0, 0, 0 }, { "test_encode_file_unreadable", test_encode_file_unreadable, 0, 0, 0 }, { "test_encode_file_directory", test_encode_file_directory, 0, 0, 0 }, + { "test_encode_file", test_encode_file, 0, 0, 0 }, + { "test_encode_print_outfile_directory", test_encode_print_outfile_directory, 0, 0, 0 }, { "test_bad_args", test_bad_args, 0, 0, 0 }, { "test_valid_id", test_valid_id, 0, 0, 0 }, { "test_error_tag", test_error_tag, 1, 0, 0 }, @@ -1058,3 +1264,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_maxicode.c b/backend/tests/test_maxicode.c index 7915d9aa..8648b48d 100644 --- a/backend/tests/test_maxicode.c +++ b/backend/tests/test_maxicode.c @@ -128,65 +128,72 @@ static void test_input(int index, int generate, int debug) { int ret; int expected_width; char *expected; + int bwipp_cmp; + int zxingcpp_cmp; char *comment; }; struct item data[] = { - /* 0*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 01 21 21 21 21 21 21 21 21 08 0E 19 2B 20 0C 24 06 32 1C 21 21 21 21 21 21 21 21", "" }, - /* 1*/ { UNICODE_MODE, -1, 2, -1, { 0, 0, "" }, "A", -1, "", ZINT_ERROR_INVALID_DATA, 0, "Error 551: Invalid length for Primary Message", "" }, - /* 2*/ { UNICODE_MODE, -1, 2, -1, { 0, 0, "" }, "A", -1, "A123456", ZINT_ERROR_INVALID_DATA, 0, "Error 555: Non-numeric postcode in Primary Message", "" }, - /* 3*/ { UNICODE_MODE, -1, 2, -1, { 0, 0, "" }, "A", -1, "1123456", 0, 30, "(144) 12 00 00 00 00 10 30 1E 20 1C 1A 3D 1C 0D 1B 15 3C 17 3C 08 01 21 21 21 21 21 21 21", "1-digit postcode" }, - /* 4*/ { UNICODE_MODE, -1, 2, -1, { 0, 0, "" }, "A", -1, "1 123456", 0, 30, "(144) 12 00 00 00 00 10 30 1E 20 1C 1A 3D 1C 0D 1B 15 3C 17 3C 08 01 21 21 21 21 21 21 21", "1-digit postcode" }, - /* 5*/ { UNICODE_MODE, -1, 2, -1, { 0, 0, "" }, "A", -1, "123456789123456", 0, 30, "(144) 12 05 0D 2F 35 11 32 1E 20 1C 0D 1D 3B 12 22 3F 30 14 23 1A 01 21 21 21 21 21 21 21", "9-digit postcode" }, - /* 6*/ { UNICODE_MODE, -1, 2, -1, { 0, 0, "" }, "A", -1, "1234567890123456", ZINT_ERROR_INVALID_DATA, 0, "Error 551: Invalid length for Primary Message", "10-digit postcode" }, - /* 7*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "1123456", 0, 30, "(144) 12 00 00 00 00 10 30 1E 20 1C 1A 3D 1C 0D 1B 15 3C 17 3C 08 01 21 21 21 21 21 21 21", "1-digit postcode" }, - /* 8*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "123456789123456", 0, 30, "(144) 12 05 0D 2F 35 11 32 1E 20 1C 0D 1D 3B 12 22 3F 30 14 23 1A 01 21 21 21 21 21 21 21", "9-digit postcode" }, - /* 9*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "1234567890123456", ZINT_ERROR_INVALID_DATA, 0, "Error 551: Invalid length for Primary Message", "10-digit postcode" }, - /* 10*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "123456", ZINT_ERROR_INVALID_DATA, 0, "Error 551: Invalid length for Primary Message", "0-digit postcode" }, - /* 11*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "12345678123456", 0, 30, "(144) 22 13 21 31 0B 00 32 1E 20 1C 04 14 07 30 10 07 08 28 1D 09 01 21 21 21 21 21 21 21", "8-digit postcode" }, - /* 12*/ { UNICODE_MODE, -1, 3, -1, { 0, 0, "" }, "A", -1, "", ZINT_ERROR_INVALID_DATA, 0, "Error 551: Invalid length for Primary Message", "" }, - /* 13*/ { UNICODE_MODE, -1, 3, -1, { 0, 0, "" }, "A", -1, "A123456", 0, 30, "(144) 03 08 08 08 08 18 30 1E 20 1C 22 35 1C 0F 02 1A 26 04 10 31 01 21 21 21 21 21 21 21", "1-alphanumeric postcode" }, - /* 14*/ { UNICODE_MODE, -1, 3, -1, { 0, 0, "" }, "A", -1, "1123456", 0, 30, "(144) 03 08 08 08 08 18 3C 1E 20 1C 13 37 07 2C 26 2D 18 29 3F 2C 01 21 21 21 21 21 21 21", "1-digit postcode" }, - /* 15*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "A123456", 0, 30, "(144) 03 08 08 08 08 18 30 1E 20 1C 22 35 1C 0F 02 1A 26 04 10 31 01 21 21 21 21 21 21 21", "1-alphanumeric postcode" }, - /* 16*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "ABCDEF123456", 0, 30, "(144) 23 11 01 31 20 10 30 1E 20 1C 3C 1D 22 03 19 15 0F 20 0F 2A 01 21 21 21 21 21 21 21", "6-alphanumeric postcode" }, - /* 17*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "ABCDEFG123456", 0, 30, "(144) 23 11 01 31 20 10 30 1E 20 1C 3C 1D 22 03 19 15 0F 20 0F 2A 01 21 21 21 21 21 21 21", "7-alphanumeric postcode truncated" }, - /* 18*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "ABCDE123456", 0, 30, "(144) 03 18 01 31 20 10 30 1E 20 1C 0F 38 38 1A 39 10 2F 37 22 12 01 21 21 21 21 21 21 21", "5-alphanumeric postcode" }, - /* 19*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "AAAAAA 840001", 0, 30, "(144) 13 10 10 10 10 10 00 12 07 00 17 36 2E 38 04 29 16 0D 27 16 01 21 21 21 21 21 21 21", "6-alphanumeric postcode with padding" }, - /* 20*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "AAAAA A840001", 0, 30, "(144) 03 18 10 10 10 10 00 12 07 00 19 07 29 31 26 01 23 2C 2E 07 01 21 21 21 21 21 21 21", "7-alphanumeric with embedded padding truncated" }, - /* 21*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "AA\015AAA840001", ZINT_ERROR_INVALID_DATA, 0, "Error 556: Invalid character in postcode in Primary Message", "Alphanumeric postcode with CR" }, - /* 22*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "A#%-/A840001", 0, 30, "(144) 13 30 1B 1B 39 18 00 12 07 00 3F 1E 25 07 2A 1E 14 3C 28 2D 01 21 21 21 21 21 21 21", "Alphanumeric postcode with non-control Code A chars" }, - /* 23*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "1A23456", ZINT_ERROR_INVALID_DATA, 0, "Error 552: Non-numeric country code or service class in Primary Message", "Non-numeric country code" }, - /* 24*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "12345678912345A", ZINT_ERROR_INVALID_DATA, 0, "Error 552: Non-numeric country code or service class in Primary Message", "Non-numeric service class" }, - /* 25*/ { UNICODE_MODE, -1, 0, -1, { 0, 0, "" }, "A", -1, "123456789123456", 0, 30, "(144) 12 05 0D 2F 35 11 32 1E 20 1C 0D 1D 3B 12 22 3F 30 14 23 1A 01 21 21 21 21 21 21 21", "Auto-determine mode 2" }, - /* 26*/ { UNICODE_MODE, -1, 0, -1, { 0, 0, "" }, "A", -1, "", ZINT_ERROR_INVALID_DATA, 0, "Error 554: Primary Message empty", "Auto-determine mode 2/3 requires primary message" }, - /* 27*/ { UNICODE_MODE, -1, 0, -1, { 0, 0, "" }, "A", -1, "A23456123456", 0, 30, "(144) 23 1D 0D 3D 2C 1C 30 1E 20 1C 24 35 30 31 2A 0D 17 14 16 3D 01 21 21 21 21 21 21 21", "Auto-determine mode 3" }, - /* 28*/ { UNICODE_MODE, -1, -1, 100, { 0, 0, "" }, "A", -1, "123456123456", 0, 30, "(144) 02 10 22 07 00 20 31 1E 20 1C 0E 29 13 1B 0D 26 36 25 3B 22 3B 2A 29 3B 28 1E 30 31", "SCM prefix version" }, - /* 29*/ { UNICODE_MODE, -1, -1, 101, { 0, 0, "" }, "A", -1, "123456123456", ZINT_ERROR_INVALID_OPTION, 0, "Error 557: Invalid SCM prefix version", "SCM prefix version" }, - /* 30*/ { UNICODE_MODE, 3, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 03 01 21 21 21 21 21 21 2F 14 23 21 05 24 27 00 24 0C 21 21 21 21 21 21 21 21", "" }, - /* 31*/ { UNICODE_MODE, 31, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 1F 01 21 21 21 21 21 21 00 2F 0E 09 39 3B 24 1A 21 05 21 21 21 21 21 21 21 21", "ECI 0x1F" }, - /* 32*/ { UNICODE_MODE, 32, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 20 20 01 21 21 21 21 21 3D 15 0F 30 0D 22 24 35 22 06 21 21 21 21 21 21 21 21", "ECI 0x20" }, - /* 33*/ { UNICODE_MODE, 1023, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 2F 3F 01 21 21 21 21 21 2E 27 23 1D 35 19 21 04 3A 26 21 21 21 21 21 21 21 21", "ECI 0x3FF" }, - /* 34*/ { UNICODE_MODE, 1024, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 30 10 00 01 21 21 21 21 11 2F 15 10 1D 29 06 35 14 2B 21 21 21 21 21 21 21 21", "ECI 0x400" }, - /* 35*/ { UNICODE_MODE, 32767, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 37 3F 3F 01 21 21 21 21 3E 15 12 01 07 30 39 27 04 2B 21 21 21 21 21 21 21 21", "ECI 0x7FFF" }, - /* 36*/ { UNICODE_MODE, 32768, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 38 08 00 00 01 21 21 21 10 30 3A 04 26 23 0E 21 3D 0F 21 21 21 21 21 21 21 21", "ECI 0x8000" }, - /* 37*/ { UNICODE_MODE, 65535, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 38 0F 3F 3F 01 21 21 21 1C 0E 1D 39 3B 0D 38 25 00 30 21 21 21 21 21 21 21 21", "ECI 0xFFFF" }, - /* 38*/ { UNICODE_MODE, 65536, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 38 10 00 00 01 21 21 21 2B 1F 24 06 38 2E 17 1B 10 2F 21 21 21 21 21 21 21 21", "ECI 0x10000" }, - /* 39*/ { UNICODE_MODE, 131071, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 38 1F 3F 3F 01 21 21 21 0F 05 09 04 2F 3A 17 09 36 31 21 21 21 21 21 21 21 21", "ECI 0x1FFFF" }, - /* 40*/ { UNICODE_MODE, 999999, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 3B 34 08 3F 01 21 21 21 26 3B 2B 23 08 17 32 05 26 35 21 21 21 21 21 21 21 21", "Max ECI" }, - /* 41*/ { UNICODE_MODE, -1, 1, -1, { 0, 0, "" }, "A", -1, "", ZINT_ERROR_INVALID_OPTION, 0, "Error 550: Invalid MaxiCode Mode", "" }, - /* 42*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "\015", -1, "", 0, 30, "(144) 04 00 21 21 21 21 21 21 21 21 37 32 10 01 24 1B 10 11 38 0C 21 21 21 21 21 21 21 21", "" }, - /* 43*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "\001\034\001\035\001\036\001a:b", -1, "", 0, 30, "(144) 04 3E 3E 01 20 01 21 01 22 01 27 0B 35 01 08 0D 16 02 17 1A 3F 01 33 02 21 21 21 21", "" }, - /* 44*/ { UNICODE_MODE, -1, -1, -1, { 1, 2, "" }, "A", -1, "", 0, 30, "(144) 04 21 01 01 21 21 21 21 21 21 09 0B 26 03 37 0E 25 27 07 1E 21 21 21 21 21 21 21 21", "" }, - /* 45*/ { UNICODE_MODE, -1, -1, -1, { 0, 2, "" }, "A", -1, "", ZINT_ERROR_INVALID_OPTION, 0, "Error 559: Structured Append index out of range (1-2)", "" }, - /* 46*/ { UNICODE_MODE, -1, -1, -1, { 1, 1, "" }, "A", -1, "", ZINT_ERROR_INVALID_OPTION, 0, "Error 558: Structured Append count out of range (2-8)", "" }, - /* 47*/ { UNICODE_MODE, -1, -1, -1, { 1, 9, "" }, "A", -1, "", ZINT_ERROR_INVALID_OPTION, 0, "Error 558: Structured Append count out of range (2-8)", "" }, - /* 48*/ { UNICODE_MODE, -1, -1, -1, { 3, 2, "" }, "A", -1, "", ZINT_ERROR_INVALID_OPTION, 0, "Error 559: Structured Append index out of range (1-2)", "" }, - /* 49*/ { UNICODE_MODE, -1, -1, -1, { 1, 2, "A" }, "A", -1, "", ZINT_ERROR_INVALID_OPTION, 0, "Error 549: Structured Append ID not available for MaxiCode", "" }, + /* 0*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 01 21 21 21 21 21 21 21 21 08 0E 19 2B 20 0C 24 06 32 1C 21 21 21 21 21 21 21 21", 1, 1, "" }, + /* 1*/ { UNICODE_MODE, -1, 2, -1, { 0, 0, "" }, "A", -1, "", ZINT_ERROR_INVALID_DATA, 0, "Error 551: Invalid length for Primary Message", 1, 1, "" }, + /* 2*/ { UNICODE_MODE, -1, 2, -1, { 0, 0, "" }, "A", -1, "A123456", ZINT_ERROR_INVALID_DATA, 0, "Error 555: Non-numeric postcode in Primary Message", 1, 1, "" }, + /* 3*/ { UNICODE_MODE, -1, 2, -1, { 0, 0, "" }, "A", -1, "1123456", 0, 30, "(144) 12 00 00 00 00 10 30 1E 20 1C 1A 3D 1C 0D 1B 15 3C 17 3C 08 01 21 21 21 21 21 21 21", 0, 1, "1-digit postcode" }, + /* 4*/ { UNICODE_MODE, -1, 2, -1, { 0, 0, "" }, "A", -1, "1 123456", 0, 30, "(144) 12 00 00 00 00 10 30 1E 20 1C 1A 3D 1C 0D 1B 15 3C 17 3C 08 01 21 21 21 21 21 21 21", 0, 0, "1-digit postcode; ZXing-C++ test can't handle space" }, + /* 5*/ { UNICODE_MODE, -1, 2, -1, { 0, 0, "" }, "A", -1, "123456789123456", 0, 30, "(144) 12 05 0D 2F 35 11 32 1E 20 1C 0D 1D 3B 12 22 3F 30 14 23 1A 01 21 21 21 21 21 21 21", 0, 1, "9-digit postcode" }, + /* 6*/ { UNICODE_MODE, -1, 2, -1, { 0, 0, "" }, "A", -1, "1234567890123456", ZINT_ERROR_INVALID_DATA, 0, "Error 551: Invalid length for Primary Message", 1, 1, "10-digit postcode" }, + /* 7*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "1123456", 0, 30, "(144) 12 00 00 00 00 10 30 1E 20 1C 1A 3D 1C 0D 1B 15 3C 17 3C 08 01 21 21 21 21 21 21 21", 0, 1, "1-digit postcode" }, + /* 8*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "123456789123456", 0, 30, "(144) 12 05 0D 2F 35 11 32 1E 20 1C 0D 1D 3B 12 22 3F 30 14 23 1A 01 21 21 21 21 21 21 21", 0, 1, "9-digit postcode" }, + /* 9*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "1234567890123456", ZINT_ERROR_INVALID_DATA, 0, "Error 551: Invalid length for Primary Message", 1, 1, "10-digit postcode" }, + /* 10*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "123456", ZINT_ERROR_INVALID_DATA, 0, "Error 551: Invalid length for Primary Message", 1, 1, "0-digit postcode" }, + /* 11*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "12345678123456", 0, 30, "(144) 22 13 21 31 0B 00 32 1E 20 1C 04 14 07 30 10 07 08 28 1D 09 01 21 21 21 21 21 21 21", 0, 1, "8-digit postcode" }, + /* 12*/ { UNICODE_MODE, -1, 3, -1, { 0, 0, "" }, "A", -1, "", ZINT_ERROR_INVALID_DATA, 0, "Error 551: Invalid length for Primary Message", 1, 1, "" }, + /* 13*/ { UNICODE_MODE, -1, 3, -1, { 0, 0, "" }, "A", -1, "A123456", 0, 30, "(144) 03 08 08 08 08 18 30 1E 20 1C 22 35 1C 0F 02 1A 26 04 10 31 01 21 21 21 21 21 21 21", 1, 1, "1-alphanumeric postcode" }, + /* 14*/ { UNICODE_MODE, -1, 3, -1, { 0, 0, "" }, "A", -1, "1123456", 0, 30, "(144) 03 08 08 08 08 18 3C 1E 20 1C 13 37 07 2C 26 2D 18 29 3F 2C 01 21 21 21 21 21 21 21", 0, 0, "1-digit postcode; ZXing-C++ test can't handle padding" }, + /* 15*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "A123456", 0, 30, "(144) 03 08 08 08 08 18 30 1E 20 1C 22 35 1C 0F 02 1A 26 04 10 31 01 21 21 21 21 21 21 21", 1, 1, "1-alphanumeric postcode" }, + /* 16*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "ABCDEF123456", 0, 30, "(144) 23 11 01 31 20 10 30 1E 20 1C 3C 1D 22 03 19 15 0F 20 0F 2A 01 21 21 21 21 21 21 21", 1, 1, "6-alphanumeric postcode" }, + /* 17*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "ABCDEFG123456", 0, 30, "(144) 23 11 01 31 20 10 30 1E 20 1C 3C 1D 22 03 19 15 0F 20 0F 2A 01 21 21 21 21 21 21 21", 1, 0, "7-alphanumeric postcode truncated; ZXing-C++ test can't handle truncation" }, + /* 18*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "ABCDE123456", 0, 30, "(144) 03 18 01 31 20 10 30 1E 20 1C 0F 38 38 1A 39 10 2F 37 22 12 01 21 21 21 21 21 21 21", 1, 1, "5-alphanumeric postcode" }, + /* 19*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "AAAAAA 840001", 0, 30, "(144) 13 10 10 10 10 10 00 12 07 00 17 36 2E 38 04 29 16 0D 27 16 01 21 21 21 21 21 21 21", 1, 0, "6-alphanumeric postcode with padding; ZXing-C++ test can't handle padding" }, + /* 20*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "AAAAA A840001", 0, 30, "(144) 03 18 10 10 10 10 00 12 07 00 19 07 29 31 26 01 23 2C 2E 07 01 21 21 21 21 21 21 21", 1, 0, "7-alphanumeric with embedded padding truncated; ZXing-C++ test can't handle truncation" }, + /* 21*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "AA\015AAA840001", ZINT_ERROR_INVALID_DATA, 0, "Error 556: Invalid character in postcode in Primary Message", 1, 1, "Alphanumeric postcode with CR" }, + /* 22*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "A#%-/A840001", 0, 30, "(144) 13 30 1B 1B 39 18 00 12 07 00 3F 1E 25 07 2A 1E 14 3C 28 2D 01 21 21 21 21 21 21 21", 1, 1, "Alphanumeric postcode with non-control Code A chars" }, + /* 23*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "1A23456", ZINT_ERROR_INVALID_DATA, 0, "Error 552: Non-numeric country code or service class in Primary Message", 1, 1, "Non-numeric country code" }, + /* 24*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "A", -1, "12345678912345A", ZINT_ERROR_INVALID_DATA, 0, "Error 552: Non-numeric country code or service class in Primary Message", 1, 1, "Non-numeric service class" }, + /* 25*/ { UNICODE_MODE, -1, 0, -1, { 0, 0, "" }, "A", -1, "123456789123456", 0, 30, "(144) 12 05 0D 2F 35 11 32 1E 20 1C 0D 1D 3B 12 22 3F 30 14 23 1A 01 21 21 21 21 21 21 21", 0, 1, "Auto-determine mode 2" }, + /* 26*/ { UNICODE_MODE, -1, 0, -1, { 0, 0, "" }, "A", -1, "", ZINT_ERROR_INVALID_DATA, 0, "Error 554: Primary Message empty", 1, 1, "Auto-determine mode 2/3 requires primary message" }, + /* 27*/ { UNICODE_MODE, -1, 0, -1, { 0, 0, "" }, "A", -1, "A23456123456", 0, 30, "(144) 23 1D 0D 3D 2C 1C 30 1E 20 1C 24 35 30 31 2A 0D 17 14 16 3D 01 21 21 21 21 21 21 21", 1, 1, "Auto-determine mode 3" }, + /* 28*/ { UNICODE_MODE, -1, -1, 100, { 0, 0, "" }, "A", -1, "123456123456", 0, 30, "(144) 02 10 22 07 00 20 31 1E 20 1C 0E 29 13 1B 0D 26 36 25 3B 22 3B 2A 29 3B 28 1E 30 31", 0, 1, "SCM prefix version" }, + /* 29*/ { UNICODE_MODE, -1, -1, 101, { 0, 0, "" }, "A", -1, "123456123456", ZINT_ERROR_INVALID_OPTION, 0, "Error 557: Invalid SCM prefix version", 1, 1, "SCM prefix version" }, + /* 30*/ { UNICODE_MODE, 3, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 03 01 21 21 21 21 21 21 2F 14 23 21 05 24 27 00 24 0C 21 21 21 21 21 21 21 21", 1, 1, "" }, + /* 31*/ { UNICODE_MODE, 31, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 1F 01 21 21 21 21 21 21 00 2F 0E 09 39 3B 24 1A 21 05 21 21 21 21 21 21 21 21", 1, 1, "ECI 0x1F" }, + /* 32*/ { UNICODE_MODE, 32, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 20 20 01 21 21 21 21 21 3D 15 0F 30 0D 22 24 35 22 06 21 21 21 21 21 21 21 21", 1, 1, "ECI 0x20" }, + /* 33*/ { UNICODE_MODE, 1023, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 2F 3F 01 21 21 21 21 21 2E 27 23 1D 35 19 21 04 3A 26 21 21 21 21 21 21 21 21", 1, 1, "ECI 0x3FF" }, + /* 34*/ { UNICODE_MODE, 1024, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 30 10 00 01 21 21 21 21 11 2F 15 10 1D 29 06 35 14 2B 21 21 21 21 21 21 21 21", 1, 1, "ECI 0x400" }, + /* 35*/ { UNICODE_MODE, 32767, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 37 3F 3F 01 21 21 21 21 3E 15 12 01 07 30 39 27 04 2B 21 21 21 21 21 21 21 21", 1, 1, "ECI 0x7FFF" }, + /* 36*/ { UNICODE_MODE, 32768, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 38 08 00 00 01 21 21 21 10 30 3A 04 26 23 0E 21 3D 0F 21 21 21 21 21 21 21 21", 1, 1, "ECI 0x8000" }, + /* 37*/ { UNICODE_MODE, 65535, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 38 0F 3F 3F 01 21 21 21 1C 0E 1D 39 3B 0D 38 25 00 30 21 21 21 21 21 21 21 21", 1, 1, "ECI 0xFFFF" }, + /* 38*/ { UNICODE_MODE, 65536, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 38 10 00 00 01 21 21 21 2B 1F 24 06 38 2E 17 1B 10 2F 21 21 21 21 21 21 21 21", 1, 1, "ECI 0x10000" }, + /* 39*/ { UNICODE_MODE, 131071, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 38 1F 3F 3F 01 21 21 21 0F 05 09 04 2F 3A 17 09 36 31 21 21 21 21 21 21 21 21", 1, 1, "ECI 0x1FFFF" }, + /* 40*/ { UNICODE_MODE, 999999, -1, -1, { 0, 0, "" }, "A", -1, "", 0, 30, "(144) 04 1B 3B 34 08 3F 01 21 21 21 26 3B 2B 23 08 17 32 05 26 35 21 21 21 21 21 21 21 21", 1, 1, "Max ECI" }, + /* 41*/ { UNICODE_MODE, -1, 1, -1, { 0, 0, "" }, "A", -1, "", ZINT_ERROR_INVALID_OPTION, 0, "Error 550: Invalid MaxiCode Mode", 1, 1, "" }, + /* 42*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "\015", -1, "", 0, 30, "(144) 04 00 21 21 21 21 21 21 21 21 37 32 10 01 24 1B 10 11 38 0C 21 21 21 21 21 21 21 21", 1, 0, "ZXing-C++ test can't handle LF" }, + /* 43*/ { UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, "\001\034\001\035\001\036\001a:b", -1, "", 0, 30, "(144) 04 3E 3E 01 20 01 21 01 22 01 27 0B 35 01 08 0D 16 02 17 1A 3F 01 33 02 21 21 21 21", 1, 1, "" }, + /* 44*/ { UNICODE_MODE, -1, -1, -1, { 1, 2, "" }, "A", -1, "", 0, 30, "(144) 04 21 01 01 21 21 21 21 21 21 09 0B 26 03 37 0E 25 27 07 1E 21 21 21 21 21 21 21 21", 1, 1, "" }, + /* 45*/ { UNICODE_MODE, -1, -1, -1, { 0, 2, "" }, "A", -1, "", ZINT_ERROR_INVALID_OPTION, 0, "Error 559: Structured Append index out of range (1-2)", 1, 1, "" }, + /* 46*/ { UNICODE_MODE, -1, -1, -1, { 1, 1, "" }, "A", -1, "", ZINT_ERROR_INVALID_OPTION, 0, "Error 558: Structured Append count out of range (2-8)", 1, 1, "" }, + /* 47*/ { UNICODE_MODE, -1, -1, -1, { 1, 9, "" }, "A", -1, "", ZINT_ERROR_INVALID_OPTION, 0, "Error 558: Structured Append count out of range (2-8)", 1, 1, "" }, + /* 48*/ { UNICODE_MODE, -1, -1, -1, { 3, 2, "" }, "A", -1, "", ZINT_ERROR_INVALID_OPTION, 0, "Error 559: Structured Append index out of range (1-2)", 1, 1, "" }, + /* 49*/ { UNICODE_MODE, -1, -1, -1, { 1, 2, "A" }, "A", -1, "", ZINT_ERROR_INVALID_OPTION, 0, "Error 549: Structured Append ID not available for MaxiCode", 1, 1, "" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol; char escaped[1024]; + 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 testStart("test_input"); @@ -209,16 +216,48 @@ static void test_input(int index, int generate, int debug) { assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, %d, %d, %d, { %d, %d, \"%s\" }, \"%s\", %d, \"%s\", %s, %d, \"%s\", \"%s\" },\n", + printf(" /*%3d*/ { %s, %d, %d, %d, { %d, %d, \"%s\" }, \"%s\", %d, \"%s\", %s, %d, \"%s\", %d, %d, \"%s\" },\n", i, testUtilInputModeName(data[i].input_mode), data[i].eci, data[i].option_1, data[i].option_2, data[i].structapp.index, data[i].structapp.count, data[i].structapp.id, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].length, data[i].primary, - testUtilErrorName(data[i].ret), symbol->width, symbol->errtxt, data[i].comment); + testUtilErrorName(data[i].ret), symbol->width, symbol->errtxt, data[i].bwipp_cmp, data[i].zxingcpp_cmp, data[i].comment); } else { if (ret < ZINT_ERROR) { assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); } assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + + if (ret < ZINT_ERROR) { + if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, -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[33 * 33 + 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, -1, data[i].data, length, symbol->primary, 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)) { + if (!data[i].zxingcpp_cmp) { + if (debug & ZINT_DEBUG_TEST_PRINT) printf("i:%d %s not ZXing-C++ compatible (%s)\n", i, testUtilBarcodeName(symbol->symbology), data[i].comment); + } else { + int cmp_len, ret_len; + char modules_dump[33 * 33 + 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, symbol->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); @@ -928,7 +967,7 @@ static void test_encode(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, -1, data[i].data, length, data[i].primary, cmp_buf, sizeof(cmp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, -1, data[i].data, length, data[i].primary, 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, data[i].expected); @@ -956,6 +995,437 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +static void test_encode_segs(int index, int generate, int debug) { + + struct item { + int input_mode; + int option_1; + int option_2; + struct zint_structapp structapp; + struct zint_seg segs[3]; + char *primary; + int ret; + + int expected_rows; + int expected_width; + int bwipp_cmp; + char *comment; + char *expected; + }; + struct item data[] = { + /* 0*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 7 }, { TU(""), 0, 0 } }, "", 0, 33, 30, 1, "ISO 16023:2000 4.15.4 example", + "010101010101010101010101010111" + "000000000000000000000000000000" + "101010101010101010101010101010" + "010101010101010101010101010110" + "000000000000000000000000000001" + "101010101010101010101010101000" + "010101010101010101010101010110" + "000000000000000000000000000010" + "101010101010101010101010101001" + "010101010011010100000101010100" + "000000000011111110001000000000" + "101010101110000000101010101010" + "010101110110000000110101010110" + "000000110000000000100100000000" + "101010011000000000010010101000" + "010101111000000000001001010110" + "000000001000000000001000000010" + "101010001000000000001110101000" + "010101111100000000000001010111" + "000000010000000000110100000010" + "101010000110000000010110101011" + "010101011010000001110001010100" + "000000000010110101000100000011" + "101010100111110001001110101010" + "010101010101010101011111010111" + "000000000000000000001111010110" + "101010101010101010100000000010" + "111111110000111100000101000000" + "010110101111000011110101010100" + "101010100000010101011111101010" + "111101011010000011110101101010" + "010110101111010110101010111100" + "010100000000010110101010010100" + }, + /* 1*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 0 }, { TU(""), 0, 0 } }, "", ZINT_WARN_USES_ECI, 33, 30, 1, "ISO 16023:2000 4.15.4 example auto-ECI", + "010101010101010101010101010111" + "000000000000000000000000000000" + "101010101010101010101010101010" + "010101010101010101010101010110" + "000000000000000000000000000001" + "101010101010101010101010101000" + "010101010101010101010101010110" + "000000000000000000000000000010" + "101010101010101010101010101001" + "010101010011010100000101010100" + "000000000011111110001000000000" + "101010101110000000101010101010" + "010101110110000000110101010110" + "000000110000000000100100000000" + "101010011000000000010010101000" + "010101111000000000001001010110" + "000000001000000000001000000010" + "101010001000000000001110101000" + "010101111100000000000001010111" + "000000010000000000110100000010" + "101010000110000000010110101011" + "010101011010000001110001010100" + "000000000010110101000100000011" + "101010100111110001001110101010" + "010101010101010101011111010111" + "000000000000000000001111010110" + "101010101010101010100000000010" + "111111110000111100000101000000" + "010110101111000011110101010100" + "101010100000010101011111101010" + "111101011010000011110101101010" + "010110101111010110101010111100" + "010100000000010110101010010100" + }, + /* 2*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("Ж"), -1, 7 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, "", 0, 33, 30, 1, "ISO 16023:2000 4.15.4 example inverted", + "010101010101010101010101010111" + "000000000000000000000000000000" + "101010101010101010101010101010" + "010101010101010101010101010110" + "000000000000000000000000000001" + "101010101010101010101010101000" + "010101010101010101010101010110" + "000000000000000000000000000010" + "101010101010101010101010101001" + "010101010011000000110101010100" + "000000000111100010011000000000" + "101010100110000000011010101010" + "010101010110000000110101010110" + "000000000000000000111100000000" + "101010101000000000001110101000" + "010101110000000000001101010110" + "000000001000000000001000000010" + "101010111000000000001110101000" + "010101101000000000010101010111" + "000000100100000000111000000010" + "101010011010000000110110101011" + "010101010110000001111001010100" + "000000001010101111101100000011" + "101010101110010101110010101010" + "010101010101010101011111010111" + "000000000000000000001111010110" + "101010101010101010100000000010" + "111111110000111100000101000000" + "010110101111000011110101010100" + "101010100000010101011111101010" + "111101011010000011110101101010" + "010110101111010110101010111100" + "010100000000010110101010010100" + }, + /* 3*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("Ж"), -1, 0 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, "", ZINT_WARN_USES_ECI, 33, 30, 1, "ISO 16023:2000 4.15.4 example inverted auto-ECI", + "010101010101010101010101010111" + "000000000000000000000000000000" + "101010101010101010101010101010" + "010101010101010101010101010110" + "000000000000000000000000000001" + "101010101010101010101010101000" + "010101010101010101010101010110" + "000000000000000000000000000010" + "101010101010101010101010101001" + "010101010011000000110101010100" + "000000000111100010011000000000" + "101010100110000000011010101010" + "010101010110000000110101010110" + "000000000000000000111100000000" + "101010101000000000001110101000" + "010101110000000000001101010110" + "000000001000000000001000000010" + "101010111000000000001110101000" + "010101101000000000010101010111" + "000000100100000000111000000010" + "101010011010000000110110101011" + "010101010110000001111001010100" + "000000001010101111101100000011" + "101010101110010101110010101010" + "010101010101010101011111010111" + "000000000000000000001111010110" + "101010101010101010100000000010" + "111111110000111100000101000000" + "010110101111000011110101010100" + "101010100000010101011111101010" + "111101011010000011110101101010" + "010110101111010110101010111100" + "010100000000010110101010010100" + }, + /* 4*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("Pixel 4a 128 GB:$439.97"), -1, 3 }, { TU("Pixel 4a 128 GB:¥3149.79"), -1, 29 }, { TU("Pixel 4a 128 GB:444,90 €"), -1, 17 } }, "", 0, 33, 30, 0, "AIM ITS/04-023:2022 Annex A example (shortened)", + "011100110111111101000011011111" + "001000110000000100100001101000" + "000010110010010000110101000010" + "110000100011101010111101111100" + "011110010111001101100111010010" + "000010001011001011111001101100" + "011100110111111101000011110111" + "001000110000000100100001111000" + "000010110010010000110101011110" + "011111110011001000000111011100" + "110110000101000110011000011110" + "011000100000000000101011000100" + "111110101110000000011110101100" + "100101100100000000001100001100" + "111011100000000000000110001101" + "011100010000000000000000100010" + "000111001000000000001010010110" + "000000110000000000001010001010" + "110011010100000000011001111111" + "100011101100000000111000000000" + "001011100010000000011000100100" + "111111000010000001111000011110" + "101001000110101011100010000110" + "000001010110011101000111000010" + "110111110111010101010010100001" + "101101000011010000000001011000" + "000010000001001010100100111001" + "101010010101100010111000111000" + "000111001101011101010101101000" + "110111101110001101100111010100" + "101000010100101000011010011110" + "100000110001100001110001101000" + "010000101110100111010101100101" + }, + /* 5*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("$439.97"), -1, 3 }, { TU("¥3149.79"), -1, 29 }, { TU("444,90 €"), -1, 17 } }, "", 0, 33, 30, 1, "AIM ITS/04-023:2022 Annex A example price only", + "101011011101111111110111111011" + "011111101101000010011110010100" + "111001110100111000100111101110" + "010101010111011111011111111010" + "000000000111000001111010100011" + "101010100001000010000000001010" + "010101010101010101010101010111" + "000000000000000000000000000010" + "101010101010101010101010101000" + "010101010111001100100001010100" + "000000001001000110011100000010" + "101010100010000000011110101010" + "010101011110000000001101010100" + "000000101000000000010000000000" + "101010001100000000000110101000" + "010101111000000000001001010110" + "000000101000000000001000000010" + "101010011000000000001110101010" + "010101110100000000001101010101" + "000000001000000000011000000000" + "101010010010000000101010101000" + "010101010100000001111101010100" + "000000000110101111101000000011" + "101010100110011101000110101000" + "010101010101010101011001001110" + "000000000000000000000000000100" + "101010101010101010100101100101" + "001001110101111010110011011100" + "001100001100101000100101110110" + "011101100101000100110011000100" + "000100101101010011010011101111" + "010111011011100000011000101000" + "001111010010000100010110011110" + }, + /* 6*/ { DATA_MODE, -1, -1, { 0, 0, "" }, { { TU("\266"), 1, 0 }, { TU("\266"), 1, 7 }, { TU("\266"), 1, 0 } }, "", 0, 33, 30, 1, "Standard example + extra seg, data mode", + "010101010101010101010101010111" + "110000000000000000000000000010" + "111010101010101010101010101011" + "010101010101010101010101010110" + "000000000000000000000000000000" + "101010101010101010101010101000" + "010101010101010101010101010110" + "000000000000000000000000000010" + "101010101010101010101010101001" + "010101010011010100111101010110" + "000000000011111110000100000010" + "101010100010000000111010101010" + "010101001110000000110001010100" + "000000001100000000101000000000" + "101010000100000000010010101000" + "010101011000000000001101010110" + "000000001000000000001000000010" + "101010001000000000001010101000" + "010101001000000000000001010101" + "000000111100000000110100000000" + "101010011010000000011010101000" + "010101011010000001010101010100" + "000000001010110101000100000011" + "101010101111110001011110101010" + "010101010101010101010011100111" + "000000000000000000000111010110" + "101010101010101010100100000010" + "110011010010110000000111001110" + "011010011101001011010111010101" + "101010000011010101001111100110" + "001110010010000001111001111010" + "000111101111000100101110001100" + "000100001000100111100110010100" + }, + /* 7*/ { UNICODE_MODE, -1, -1, { 0, 0, "" }, { { TU("αβ"), -1, 0 }, { TU("ÿ"), -1, 0 }, { TU("貫やぐ禁"), -1, 20 } }, "", ZINT_WARN_USES_ECI, 33, 30, 1, "Auto-ECI", + "011010110111101111110011111111" + "100110111111001100110011001110" + "001100101100100001100100010111" + "010101010101010101101111110100" + "000000000000000000101100111110" + "101010101010101010010000100110" + "010101010101010101010101010111" + "000000000000000000000000000000" + "101010101010101010101010101000" + "010101010111000000110101010100" + "000000000011010010001100000010" + "101010101100000000111010101010" + "010101101100000000110101010110" + "000000011100000000011100000000" + "101010001000000000011110101000" + "010101011000000000001101010110" + "000000001000000000001000000011" + "101010001000000000001010101010" + "010101010000000000001001010100" + "000000010100000000000000000000" + "101010110010000000110110101000" + "010101010010000001110101010110" + "000000000010101011100100000001" + "101010101011010001100010101000" + "010101010101010101011010000110" + "000000000000000000001001001100" + "101010101010101010100101111110" + "110111000101110010100001011100" + "111110011010010010000011001011" + "111000110110111111111000010100" + "101001001111001011110110101001" + "101010010100011001011101100110" + "111011110000111001101101111000" + }, + /* 8*/ { UNICODE_MODE, -1, -1, { 1, 2, "" }, { { TU("αβ"), -1, 9 }, { TU("ÿ"), -1, 3 }, { TU("貫やぐ禁"), -1, 20 } }, "", 0, 33, 30, 1, "Structured Append", + "001101101011011110111111001111" + "001110011011111100110011001110" + "111000110010110010000110010011" + "010101010101011011111101111110" + "000000000000001011001111110011" + "101010101010100100001001010100" + "010101010101010101010101010111" + "000000000000000000000000000010" + "101010101010101010101010101011" + "010101010011000000111101010110" + "000000001101000010010000000011" + "101010101010000000100010101000" + "010101111000000000111101010111" + "000000000100000000100000000000" + "101010001100000000011010101010" + "010101011000000000000101010110" + "000000001000000000001000000000" + "101010001000000000001110101000" + "010101100000000000011001010100" + "000000111000000000001000000010" + "101010100110000000010110101011" + "010101011010000000001001010110" + "000000001010011011100000000010" + "101010101011000001000010101000" + "010101010101010101011111010011" + "000000000000000000000100001000" + "101010101010101010100101111111" + "111101010111011110110011111100" + "000011111110111101111100110001" + "001101101111000110000011100010" + "111110010111110110000111100100" + "101010011010110110110010010100" + "100101010111100011100010101000" + }, + }; + int data_size = ARRAY_SIZE(data); + int i, j, seg_count, ret; + struct zint_symbol *symbol; + + char escaped[1024]; + char cmp_buf[8192]; + char cmp_msg[1024]; + + int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); // Only do BWIPP test if asked, too slow otherwise + int do_zxingcpp = (debug & ZINT_DEBUG_TEST_ZXINGCPP) && testUtilHaveZXingCPPDecoder(); // Only do ZXing-C++ test if asked, too slow otherwise + + testStart("test_encode_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + testUtilSetSymbol(symbol, BARCODE_MAXICODE, data[i].input_mode, -1 /*eci*/, + data[i].option_1, data[i].option_2, -1, -1 /*output_options*/, NULL, 0, debug); + if (data[i].structapp.count) { + symbol->structapp = data[i].structapp; + } + strcpy(symbol->primary, data[i].primary); + for (j = 0, seg_count = 0; j < 3 && data[i].segs[j].length; j++, seg_count++); + + ret = ZBarcode_Encode_Segs(symbol, data[i].segs, seg_count); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode_Segs ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + char escaped1[4096]; + char escaped2[4096]; + int length = data[i].segs[0].length == -1 ? (int) ustrlen(data[i].segs[0].source) : data[i].segs[0].length; + int length1 = data[i].segs[1].length == -1 ? (int) ustrlen(data[i].segs[1].source) : data[i].segs[1].length; + int length2 = data[i].segs[2].length == -1 ? (int) ustrlen(data[i].segs[2].source) : data[i].segs[2].length; + printf(" /*%3d*/ { %s, %d, %d, { %d, %d, \"%s\" }, { { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d } }, \"%s\", %s, %d, %d, %d, \"%s\",\n", + i, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_2, + data[i].structapp.index, data[i].structapp.count, data[i].structapp.id, + testUtilEscape((const char *) data[i].segs[0].source, length, escaped, sizeof(escaped)), data[i].segs[0].length, data[i].segs[0].eci, + testUtilEscape((const char *) data[i].segs[1].source, length1, escaped1, sizeof(escaped1)), data[i].segs[1].length, data[i].segs[1].eci, + testUtilEscape((const char *) data[i].segs[2].source, length2, escaped2, sizeof(escaped2)), data[i].segs[2].length, data[i].segs[2].eci, + data[i].primary, testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].bwipp_cmp, data[i].comment); + testUtilModulesPrint(symbol, " ", "\n"); + printf(" },\n"); + } else { + if (ret < ZINT_ERROR) { + int width, row; + + 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); + + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d\n", i, ret, width, row); + + if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, data[i].option_2, -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 { + ret = testUtilBwippSegs(i, symbol, -1, data[i].option_2, -1, 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); + 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, data[i].expected); + } + } + if (do_zxingcpp && testUtilCanZXingCPP(i, symbol, (const char *) data[i].segs[0].source, data[i].segs[0].length, debug)) { + if (data[i].input_mode == DATA_MODE) { + if (debug & ZINT_DEBUG_TEST_PRINT) { + printf("i:%d multiple segments in DATA_MODE not currently supported for ZXing-C++ testing (%s)\n", + i, testUtilBarcodeName(symbol->symbology)); + } + } else { + int cmp_len, ret_len; + char modules_dump[17984 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilZXingCPP(i, symbol, (const char *) data[i].segs[0].source, data[i].segs[0].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 = testUtilZXingCPPCmpSegs(symbol, cmp_msg, cmp_buf, cmp_len, data[i].segs, seg_count, + data[i].primary, escaped, &ret_len); + assert_zero(ret, "i:%d %s testUtilZXingCPPCmpSegs %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); + } + + testFinish(); +} + static void test_best_supported_set(int index, int generate, int debug) { struct item { @@ -1174,6 +1644,7 @@ int main(int argc, char *argv[]) { { "test_large", test_large, 1, 0, 1 }, { "test_input", test_input, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_encode_segs", test_encode_segs, 1, 1, 1 }, { "test_best_supported_set", test_best_supported_set, 1, 1, 1 }, { "test_fuzz", test_fuzz, 1, 0, 1 }, { "test_perf", test_perf, 1, 0, 1 }, diff --git a/backend/tests/test_medical.c b/backend/tests/test_medical.c index c02d964f..b6b4ada8 100644 --- a/backend/tests/test_medical.c +++ b/backend/tests/test_medical.c @@ -294,7 +294,7 @@ static void test_encode(int index, int generate, int debug) { assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, -1, debug)) { - ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf)); + ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -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, data[i].expected); diff --git a/backend/tests/test_pdf417.c b/backend/tests/test_pdf417.c index 91900f12..6249100a 100644 --- a/backend/tests/test_pdf417.c +++ b/backend/tests/test_pdf417.c @@ -1692,7 +1692,7 @@ static void test_encode(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, data[i].option_3, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_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, data[i].expected); @@ -1720,6 +1720,382 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +static void test_encode_segs(int index, int generate, int debug) { + + struct item { + int symbology; + int input_mode; + int option_1; + int option_2; + int option_3; + struct zint_structapp structapp; + struct zint_seg segs[3]; + int ret; + + int expected_rows; + int expected_width; + int bwipp_cmp; + char *comment; + char *expected; + }; + struct item data[] = { + /* 0*/ { BARCODE_PDF417, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 7 }, { TU(""), 0, 0 } }, 0, 8, 103, 1, "Standard example", + "1111111101010100011111010101111100110101000011000001111001111001010011110101011110000111111101000101001" + "1111111101010100011111101010001110101000011110010001001111110010110011110101001000000111111101000101001" + "1111111101010100011101010111111000111010100011111101001111110011101011101010001111110111111101000101001" + "1111111101010100011010111100111110110110100010000001000011000110010010101111001111000111111101000101001" + "1111111101010100011101011100001100101110100011111001111000001001001011110101110011100111111101000101001" + "1111111101010100011110101111010000111011111000101101001111100001101011101011111010000111111101000101001" + "1111111101010100011101001110111110101000111011100001000111011100100011010011101111000111111101000101001" + "1111111101010100011111010010110000111000101110110001101011100001000010101111110111000111111101000101001" + }, + /* 1*/ { BARCODE_PDF417, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 8, 103, 1, "Standard example auto-ECI", + "1111111101010100011111010101111100110101000011000001111001111001010011110101011110000111111101000101001" + "1111111101010100011111101010001110101000011110010001001111110010110011110101001000000111111101000101001" + "1111111101010100011101010111111000111010100011111101001111110011101011101010001111110111111101000101001" + "1111111101010100011010111100111110110110100010000001000011000110010010101111001111000111111101000101001" + "1111111101010100011101011100001100101110100011111001111000001001001011110101110011100111111101000101001" + "1111111101010100011110101111010000111011111000101101001111100001101011101011111010000111111101000101001" + "1111111101010100011101001110111110101000111011100001000111011100100011010011101111000111111101000101001" + "1111111101010100011111010010110000111000101110110001101011100001000010101111110111000111111101000101001" + }, + /* 2*/ { BARCODE_PDF417, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("Ж"), -1, 7 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, 0, 9, 103, 1, "Standard example inverted", + "1111111101010100011111010101111100110101000001100001100011100011001011110101011110000111111101000101001" + "1111111101010100011110101000010000111111010100011101011111100100011011110101001000000111111101000101001" + "1111111101010100011101010111111000110010010111110001000011111011001010101000011110000111111101000101001" + "1111111101010100011010111100111110111010100111000001111001111001010010101111001111000111111101000101001" + "1111111101010100011010111000001000101000011110010001011111101011000011110101110011100111111101000101001" + "1111111101010100011110101111010000111000111111010101100111110100010011110101111101100111111101000101001" + "1111111101010100011101001110111110111110111010111001111001100101110011010011101111000111111101000101001" + "1111111101010100011111101001011100111100100010100001001111101011100010101111110111000111111101000101001" + "1111111101010100011010011011111100100111010011000001100011010011110011111010011101000111111101000101001" + }, + /* 3*/ { BARCODE_PDF417, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("Ж"), -1, 0 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 9, 103, 1, "Standard example inverted auto-ECI", + "1111111101010100011111010101111100110101000001100001100011100011001011110101011110000111111101000101001" + "1111111101010100011110101000010000111111010100011101011111100100011011110101001000000111111101000101001" + "1111111101010100011101010111111000110010010111110001000011111011001010101000011110000111111101000101001" + "1111111101010100011010111100111110111010100111000001111001111001010010101111001111000111111101000101001" + "1111111101010100011010111000001000101000011110010001011111101011000011110101110011100111111101000101001" + "1111111101010100011110101111010000111000111111010101100111110100010011110101111101100111111101000101001" + "1111111101010100011101001110111110111110111010111001111001100101110011010011101111000111111101000101001" + "1111111101010100011111101001011100111100100010100001001111101011100010101111110111000111111101000101001" + "1111111101010100011010011011111100100111010011000001100011010011110011111010011101000111111101000101001" + }, + /* 4*/ { BARCODE_PDF417, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("product:Google Pixel 4a - 128 GB of Storage - Black;price:$439.97"), -1, 3 }, { TU("品名:Google 谷歌 Pixel 4a -128 GB的存储空间-黑色;零售价:¥3149.79"), -1, 29 }, { TU("Produkt:Google Pixel 4a - 128 GB Speicher - Schwarz;Preis:444,90 €"), -1, 17 } }, 0, 24, 188, 0, "AIM ITS/04-023:2022 Annex A example; BWIPP different encodation", + "11111111010101000111010100011100001001010000100000011000111000110010111010100111000001000011000110010011000001001011000100110001101000001101000010000110011010100011000000111111101000101001" + "11111111010101000111110101000001101111010011011000011110000011011010100000101111101101111011000011001011110100000100010110100011100001001110000110111010011111101010001110111111101000101001" + "11111111010101000110101000111110001101100010001111011100101011111100110011111011011001001011000111110011111101011100110100111110001100101100011110101100011111101011010000111111101000101001" + "11111111010101000111110100101111101101001111011111010000010100010000111110110100111101100000101001100010011011100001100110000010100110001110011000010011011110100101111000111111101000101001" + "11111111010101000110101111011000001110010000011001011111010100011000110100011100001001001111010001111011000001011101000101011111001100001001001111000001011101011100001100111111101000101001" + "11111111010101000111101011110000101010011101111110010000001100101110111100001011110101001000100001111010010110000111110100110000110111101101000001011111011101011111000100111111101000101001" + "11111111010101000101001111011110001111011000100111010010001110011100110001110001100101010111101111000010000010000100010111011011001110001110110100011000011010011100011110111111101000101001" + "11111111010101000111111010010011101110100000110001011100101111001110101111110101100001111000001101101011101000000110010111101100001100101111010000010001011111010010110000111111101000101001" + "11111111010101000101001100011111001111110010110001011001111110110010100100100111100001011011101111100010110110111100000101100100000111001100011111001001011111010011100100111111101000101001" + "11111111010101000110100011100111101111011110001001011000011010010000110000100011011101100010101100000010000110111101110100000101000001001000001010001000010100011100111000111111101000101001" + "11111111010101000110100111000000101000101111010000011111101001011100110000010111010001101000011110110011011111101011100110010011101000001111110111010010011101001110001100111111101000101001" + "11111111010101000101000110111110001000010100011110011111101011000100110011100010011101100110100111100010111000110011100110110000010111101001100110001111011111010001110100111111101000101001" + "11111111010101000101000001001000001100110000010001010001010000010000110011000001001001101111001110001010100000101000000110110011000011001100100000100011011101000001011100111111101000101001" + "11111111010101000111101000110110001101111101011110011111011001010000101110111111010001111001110011101011110100001001000101111110100110001111101011011100011111010001000110111111101000101001" + "11111111010101000101000001101111101001110011001110011000111110010010101111110011100101110110111111001010000111110110010111111010110001001100011111001001011100101011111100111111101000101001" + "11111111010101000111100101101111101001100110000100010011000110100000110100001000011001011000111000011011100111101100010100000101110011101110111010100000011100101101111000111111101000101001" + "11111111010101000101000111111011101111010000010001011010001110000100111000011011101001001011111101110011110100011011000110000010111010001101000111000001010100011111011000111111101000101001" + "11111111010101000111110010111101101111110101110011010011111000110010110001111010110001111101001110100011001111101101100100100101111000001000111101110111011100101111100100111111101000101001" + "11111111010101000111101101000011101100000100101100011010000010011000101001111011110001010000011000110010000010100010000111011100100000101000001000101000011101101000011000111111101000101001" + "11111111010101000111101000001000101000001011110100011100101100000100111101011001100001111001110011101011101011101100000111100010110011001111010001000010010100001111100110111111101000101001" + "11111111010101000110010010011111001011110010000010010111000100110000101000001001111001011100100011000011111101011100110100111111001110101110010111111011010010010000111100111111101000101001" + "11111111010101000101101110001100001000011000110010010000110001100100100001100011001001000011000110010010000110001100100110011000010010001101110110100000011101101110011110111111101000101001" + "11111111010101000111100101000000101111010000010001010100011110010000101110100111110001110000010110001011101000011000010110110001111001001100010111000100011111001010001100111111101000101001" + "11111111010101000111001001111101001011101100011100011001110010001110110000111110100101001111001100011010110011001111000101100100001110001101111001000011011001001111110010111111101000101001" + }, + /* 5*/ { BARCODE_PDF417, DATA_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("\357"), 1, 0 }, { TU("\357"), 1, 7 }, { TU("\357"), 1, 0 } }, 0, 10, 103, 1, "Standard example + extra seg, data mode", + "1111111101010100011101010011100000110101101110000001111001111001010011110101011110000111111101000101001" + "1111111101010100011111010100011000111100101110011101001111110010110011111010100110000111111101000101001" + "1111111101010100011101010111111000111010100011111101001111110011101011010100011111000111111101000101001" + "1111111101010100010101111101111100111011001000110001100011100011001010101111001111000111111101000101001" + "1111111101010100011010111000010000111110101001100001011111100100011011010111000100000111111101000101001" + "1111111101010100011110101111010000101100110011110001100011111001001011110101111000010111111101000101001" + "1111111101010100010100111001110000110101000011000001100100011001110011010011101111000111111101000101001" + "1111111101010100011110100101000000100001011110000101101011111101111011010111111011110111111101000101001" + "1111111101010100011010011011111100110100111111010001001011101111110010100110001111100111111101000101001" + "1111111101010100010100011000001100111100100100111101100011001010000011010001100011100111111101000101001" + }, + /* 6*/ { BARCODE_PDF417, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("Τεχτ"), -1, 9 }, { TU("กขฯ"), -1, 0 }, { TU("貫やぐ禁"), -1, 20 } }, ZINT_WARN_USES_ECI, 11, 120, 1, "Auto-ECI", + "111111110101010001110101001110000011010111001111000110001110001100101010100000100000011111010101111100111111101000101001" + "111111110101010001111110101000111011011111101011100111111001010111001111001011000110011111010100110000111111101000101001" + "111111110101010001010100111100000010110011101111100111111001000110101000011111011001011101010001111110111111101000101001" + "111111110101010001010111110111110011101011011110000100000100001000101001011000110000011010111100111110111111101000101001" + "111111110101010001110101110000110011110100001010000111010000001100101001111110010110011010111000100000111111101000101001" + "111111110101010001111101011110110011111101011000010110011111101100101011001000001110011101011111010000111111101000101001" + "111111110101010001010011100111000011001100001100110101100011110011101100111001110011011101001110111110111111101000101001" + "111111110101010001111101001011000011111010001011000110100011101000001111100101001100011010111111011110111111101000101001" + "111111110101010001111110100110010011000111110010010100111010011000001110101111100010010100110000111110111111101000101001" + "111111110101010001010001100000110011001000010011000110011000110011001011110011110010010100011000011000111111101000101001" + "111111110101010001110100111000110011010001111011000110000110111100101101001111000011011010011100100000111111101000101001" + }, + /* 7*/ { BARCODE_PDF417, UNICODE_MODE, -1, -1, -1, { 2, 4, "017053" }, { { TU("Τεχτ"), -1, 9 }, { TU("กขฯ"), -1, 13 }, { TU("貫やぐ禁"), -1, 20 } }, 0, 11, 120, 1, "Structured Append", + "111111110101010001110101001110000011010111001111000110001110001100101010100000100000011111010101111100111111101000101001" + "111111110101010001111110101000111011011111101011100111111001010111001111001011000110011111010100110000111111101000101001" + "111111110101010001010100111100000010110011101111100111111001000110101000011111011001011101010001111110111111101000101001" + "111111110101010001010111110111110011101011011110000100000100001000101001011000110000011010111100111110111111101000101001" + "111111110101010001110101110000110011110100001010000111010000001100101001111110010110011010111000100000111111101000101001" + "111111110101010001111101011110110011111101011000010110011111101100101011001000001110011101011111010000111111101000101001" + "111111110101010001010011100111000011001100001100110101100011110011101100111001110011011101001110111110111111101000101001" + "111111110101010001111101001011000011111010001011000110100011101000001111100101001100011010111111011110111111101000101001" + "111111110101010001111110100110010011000111110010010100111010011000001110101111100010010100110000111110111111101000101001" + "111111110101010001010001100000110011001000010011000110011000110011001011110011110010010100011000011000111111101000101001" + "111111110101010001110100111000110011010001111011000110000110111100101101001111000011011010011100100000111111101000101001" + }, + /* 8*/ { BARCODE_MICROPDF417, UNICODE_MODE, -1, 3, -1, { 0, 0, "" }, { { TU("¶¶"), -1, 0 }, { TU("ЖЖ"), -1, 7 }, { TU(""), 0, 0 } }, 0, 8, 82, 1, "Standard example (doubled to avoid Byte Shift)", + "1100111010100000100001000101000010110110110100010000001101101000100000011001110101" + "1110111010100111111001011001000010010111111010100011101101111110101110011101110101" + "1110011010110010010111110001000011010110010010111110001100011111001001011100110101" + "1111011010100001100011001001000111010100001011101110001100010000010011011110110101" + "1111001010111001000011010001000110010110111001111101001101000011101000011110010101" + "1110001010101101101111000001000100010100111100001101101011011100011111011100010101" + "1100001010111011100010100001001100010101110001110010001100100111011110011000010101" + "1100011010101111100100111001001110010111010001100010001111000101000001011000110101" + }, + /* 9*/ { BARCODE_MICROPDF417, UNICODE_MODE, -1, 3, -1, { 0, 0, "" }, { { TU("¶¶"), -1, 0 }, { TU("ЖЖ"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 8, 82, 1, "Standard example auto-ECI", + "1100111010100000100001000101000010110110110100010000001101101000100000011001110101" + "1110111010100111111001011001000010010111111010100011101101111110101110011101110101" + "1110011010110010010111110001000011010110010010111110001100011111001001011100110101" + "1111011010100001100011001001000111010100001011101110001100010000010011011110110101" + "1111001010111001000011010001000110010110111001111101001101000011101000011110010101" + "1110001010101101101111000001000100010100111100001101101011011100011111011100010101" + "1100001010111011100010100001001100010101110001110010001100100111011110011000010101" + "1100011010101111100100111001001110010111010001100010001111000101000001011000110101" + }, + /* 10*/ { BARCODE_MICROPDF417, UNICODE_MODE, -1, 3, -1, { 0, 0, "" }, { { TU("ЖЖ"), -1, 7 }, { TU("¶¶"), -1, 0 }, { TU(""), 0, 0 } }, 0, 8, 82, 1, "Standard example inverted", + "1100111010110001110001100101000010110111010100011100001000001000010001011001110101" + "1110111010101000011110010001000010010101000011110010001001111110010110011101110101" + "1110011010110101001111100001000011010110011111101100101100100101111100011100110101" + "1111011010110110100010000001000111010100000100111011101010000010100000011110110101" + "1111001010110111001111101001000110010110111011111010001011111010011100011110010101" + "1110001010101100010001110001000100010110111110010000101000000110101110011100010101" + "1100001010110100001000110001001100010111010010000111001110001100010011011000010101" + "1100011010111110111011000101001110010111011000111000101110100111000110011000110101" + }, + /* 11*/ { BARCODE_MICROPDF417, UNICODE_MODE, -1, 3, -1, { 0, 0, "" }, { { TU("ЖЖ"), -1, 0 }, { TU("¶¶"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 8, 82, 1, "Standard example inverted auto-ECI", + "1100111010110001110001100101000010110111010100011100001000001000010001011001110101" + "1110111010101000011110010001000010010101000011110010001001111110010110011101110101" + "1110011010110101001111100001000011010110011111101100101100100101111100011100110101" + "1111011010110110100010000001000111010100000100111011101010000010100000011110110101" + "1111001010110111001111101001000110010110111011111010001011111010011100011110010101" + "1110001010101100010001110001000100010110111110010000101000000110101110011100010101" + "1100001010110100001000110001001100010111010010000111001110001100010011011000010101" + "1100011010111110111011000101001110010111011000111000101110100111000110011000110101" + }, + /* 12*/ { BARCODE_MICROPDF417, UNICODE_MODE, -1, 4, -1, { 0, 0, "" }, { { TU("product:Google Pixel 4a 128 GB Black;price:$439.97"), -1, 3 }, { TU("品名:Google 谷歌 Pixel 4a 128 GB 黑色;零售价:¥3149.79"), -1, 29 }, { TU("Produkt:Google Pixel 4a 128 GB Schwarz;Preis:444,90 €"), -1, 17 } }, 0, 44, 99, 0, "AIM ITS/04-023:2022 Annex A example (shortened); BWIPP different encodation", + "110010001011000111000110010111010100111000001011000010100001100011001001100000100101100011010001001" + "111010001011000100111010000101001111000010001011100010111101001101100001111000001101101011010001101" + "111011001010001111001101100101110001100111001011100110100100100001111001111110010110001011010000101" + "110011001011000001001011000110010001101110001011100100110100000100011001000001010001000011011000101" + "110111001011010001110000010111010110000001001011101100111100000100010101111110100101110011001000101" + "110111101011001111101101100100100101111000001001101100110001111010110001110111111010100011101000101" + "110011101011111010101111100110110000100001001000101100110101100111000001101110011000010011101100101" + "111011101010101111110011100110011110101111101000101000100010011111011001110100111000011011001100101" + "111001101010111101001000000101100110011110001001101000100001111101100101010111000111111011011100101" + "111101101010000010000100010111011011001110001011101000111011010001100001110010010011100011011110101" + "111100101011100101111001110101111110101100001011001000111100000110110101110100000011001011001110101" + "111000101010111000110011100100100100001111001011001100111111001011000101100111111011001011101110101" + "110000101011011010000100000101101100010000001011000100111101101000111001110110010110000011100110101" + "110001101010111111010110000101111001000111101011000110100001101011111101000110100111111011110110101" + "110001001011011101001110000100111110011101101010000110100111110110010001100111110110110011110010101" + "111001001011010111100111110100100011001100001010001110111000111010010001101001100011100011100010101" + "111101001011011111101011100110110111100010001010001100111110100010110001100011001111001011000010101" + "111101011010011001000011100110001111000101101010011100110001000101111101000111001011000011000110101" + "111101010010100010000010000111101000101111001010011000111101110100110001001011000011000011000100101" + "111001010011110100001001000101111110100110001010111000111110101101110001011101011111000011100100101" + "111011010011000111110010010101111110011100101010110000111011011111100101000011111011001011110100101" + "111010010011110101100111110100001100011001001010010000100110011000010001001100011010000011110101101" + "111010011010100111100001000110010011110110001011010000111100000110110101000001011111011011110101001" + "111010111010111000110011100100100100001111001001010000111111001011000101100111110010100011100101001" + "111010110011001000110111000110100000100011001001011000100000101000100001110010100111000011101101001" + "111010100011101011000000100111100000100010101001011100111111010010111001100000101110100011101001001" + "110010100010010010111100000100011110111011101011011100100111110110001001011001000001110011101001101" + "110010110011110101100111110110111100111000101011011110101011100011100001110001000100111011101011101" + "110010111011110100010000100111100010001010001011001110100100001111000101111010001001000011101011001" + "110010011010111001000110000111111010111001101001001110100111111001110101110010111111011011101010001" + "110011011010000110001100100100001100011001001001101110100001100011001001000011000110010011001010001" + "111011011010111111010110000101111110101100001000101110111110101100011101101110011111010011001011001" + "111001011011011110010011000111111000101100101000100110101111011101110001000011010111000011001011101" + "110001011010011000110100000110000100011011101000110110111000110001001101001101111101111011001001101" + "110001010010011111010011100110110011110001001000010110111101100111001101111010000010100011001101101" + "110011010011111001000111010100010000101111001000010010111010001011111101001100001000111011101101101" + "110111010010001100110000010100001100110010001000011010100010001100001101100100000100011011100101101" + "110110010011101111011111010111111011010011001000111010111100010100100001110000110111010011000101101" + "110110011010011001001110000111001111101001101000110010101110010001100001000101100111110011000101001" + "110110111011101101100111000100110001110110001000100010110111100011100101000110110010000011001101001" + "110110110011111011100110100111001000001100101001100010111101100110000101100100000111001011011101001" + "110110100011101110010111100110001111010001101001110010110111111001101001011010000011100011011001001" + "110100100010110011110001110101100001100010001001111010111011000100110001010000011001100011011001101" + "110101100011111011000010100111110100001011001011111010111110111011000101011101111110001011011011101" + }, + /* 13*/ { BARCODE_MICROPDF417, DATA_MODE, -1, 3, -1, { 0, 0, "" }, { { TU("\357\357"), 2, 0 }, { TU("\357\357"), 2, 7 }, { TU("\357\357"), 2, 0 } }, 0, 10, 82, 1, "Standard example (doubled) + extra seg, data mode", + "1100010010110011111101100101001111010101100110011110001011001100111100011000100101" + "1110010010110001110001100101011111010111010100011100001000001000010001011100100101" + "1111010010111100101110011101011110010111100101110011101001111110010110011110100101" + "1111010110110101001111100001011110110110011111101100101011001100111100011110101101" + "1111010100111011001000110001001110110100001100011001001100111011001000011110101001" + "1110010100110001000001110101001110100111111011101010001101110111110100011100101001" + "1110110100110100010011111001001100100110010100001111101110011111101010011101101001" + "1110100100110110000010000101001100110101001000001000001110100000100111011101001001" + "1110100110111101000011001101001000110111101001000100001100100111010000011101001101" + "1110101110100000101101111101001000010111010011111000101001110111001111011101011101" + }, + /* 14*/ { BARCODE_MICROPDF417, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("Τεχτ"), -1, 9 }, { TU("กขฯ"), -1, 0 }, { TU("貫やぐ禁"), -1, 20 } }, ZINT_WARN_USES_ECI, 17, 55, 1, "Auto-ECI", + "1100110100100001111101100101101010000111110011001101001" + "1101110100100000100001000101100100110011100011011101001" + "1101100100111100101100011001100101111011000011011001001" + "1101100110111111001000110101000011111011001011011001101" + "1101101110111010110111100001000001000010001011011011101" + "1101101100101000111111011101111010000101000011011011001" + "1101101000100100111011111101000011111011001011011010001" + "1101001000101011000011000001000001000010001011010010001" + "1101011000111001011000001001111011101110100011010110001" + "1101011100110011010011110001101111100010001011010111001" + "1101011110110100001110111101110100000010111011010111101" + "1101001110111110010100110001011111101011000011010011101" + "1101001100101000011001111101000000110100111011010011001" + "1101000100110100110111000001000010000100100011010001001" + "1101000110111001011110011101101101111001000011010001101" + "1101000010110000011010111101100110010001111011010000101" + "1101100010100001001101100001001001110111000011011000101" + }, + /* 15*/ { BARCODE_MICROPDF417, UNICODE_MODE, -1, -1, -1, { 3, 4, "017053" }, { { TU("Τεχτ"), -1, 9 }, { TU("กขฯ"), -1, 13 }, { TU("貫やぐ禁"), -1, 20 } }, 0, 17, 55, 1, "Structured Append", + "1100110100100001111101100101101010000111110011001101001" + "1101110100100000100001000101100100110011100011011101001" + "1101100100111100101100011001100101111011000011011001001" + "1101100110111111001000110101000011111011001011011001101" + "1101101110111010110111100001000001000010001011011011101" + "1101101100101000111111011101111010000101000011011011001" + "1101101000100100111011111101000011111011001011011010001" + "1101001000101011000011000001000001000010001011010010001" + "1101011000111001011000001001111011101110100011010110001" + "1101011100110011010011110001101111100010001011010111001" + "1101011110110100001110111101110100000010111011010111101" + "1101001110111110010100110001011111101011000011010011101" + "1101001100101000011001111101000000110100111011010011001" + "1101000100110100110111000001000010000100100011010001001" + "1101000110111001011110011101101101111001000011010001101" + "1101000010110000011010111101100110010001111011010000101" + "1101100010100001001101100001001001110111000011011000101" + }, + /* 16*/ { BARCODE_PDF417COMP, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 7 }, { TU(""), 0, 0 } }, 0, 8, 69, 1, "Standard example", + "111111110101010001111101010111110011010100001100000111100111100101001" + "111111110101010001111110101000111010100001111001000100111111001011001" + "111111110101010001110101011111100011101010001111110100111111001110101" + "111111110101010001101011110011111011011010001000000100001100011001001" + "111111110101010001110101110000110010111010001111100111100000100100101" + "111111110101010001111010111101000011101111100010110100111110000110101" + "111111110101010001110100111011111010100011101110000100011101110010001" + "111111110101010001111101001011000011100010111011000110101110000100001" + }, + /* 17*/ { BARCODE_HIBC_PDF, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("H123ABC"), -1, 0 }, { TU("012345678"), -1, 0 }, { TU("90D"), -1, 20 } }, ZINT_ERROR_INVALID_OPTION, 0, 0, 1, "HIBC", + "" + }, + /* 18*/ { BARCODE_HIBC_MICPDF, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("H123ABC"), -1, 0 }, { TU("012345678"), -1, 0 }, { TU("90D"), -1, 20 } }, ZINT_ERROR_INVALID_OPTION, 0, 0, 1, "HIBC", + "" + }, + }; + int data_size = ARRAY_SIZE(data); + int i, j, seg_count, ret; + struct zint_symbol *symbol; + + char escaped[1024]; + 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 + + testStart("test_encode_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, + data[i].option_1, data[i].option_2, data[i].option_3, -1 /*output_options*/, NULL, 0, debug); + for (j = 0, seg_count = 0; j < 3 && data[i].segs[j].length; j++, seg_count++); + + ret = ZBarcode_Encode_Segs(symbol, data[i].segs, seg_count); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode_Segs ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + char escaped1[4096]; + char escaped2[4096]; + int length = data[i].segs[0].length == -1 ? (int) ustrlen(data[i].segs[0].source) : data[i].segs[0].length; + int length1 = data[i].segs[1].length == -1 ? (int) ustrlen(data[i].segs[1].source) : data[i].segs[1].length; + int length2 = data[i].segs[2].length == -1 ? (int) ustrlen(data[i].segs[2].source) : data[i].segs[2].length; + printf(" /*%3d*/ { %s, %s, %d, %d, %d, { %d, %d, \"%s\" }, { { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d } }, %s, %d, %d, %d, \"%s\",\n", + i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), + data[i].option_1, data[i].option_2, data[i].option_3, + data[i].structapp.index, data[i].structapp.count, data[i].structapp.id, + testUtilEscape((const char *) data[i].segs[0].source, length, escaped, sizeof(escaped)), data[i].segs[0].length, data[i].segs[0].eci, + testUtilEscape((const char *) data[i].segs[1].source, length1, escaped1, sizeof(escaped1)), data[i].segs[1].length, data[i].segs[1].eci, + testUtilEscape((const char *) data[i].segs[2].source, length2, escaped2, sizeof(escaped2)), data[i].segs[2].length, data[i].segs[2].eci, + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].bwipp_cmp, data[i].comment); + if (data[i].ret < ZINT_ERROR) { + testUtilModulesPrint(symbol, " ", "\n"); + } else { + printf(" \"\"\n"); + } + printf(" },\n"); + } else { + if (ret < ZINT_ERROR) { + int width, row; + + 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); + + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d\n", i, ret, width, row); + + if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_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 { + ret = testUtilBwippSegs(i, symbol, data[i].option_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); + 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, data[i].expected); + } + } + if (do_zxingcpp && testUtilCanZXingCPP(i, symbol, (const char *) data[i].segs[0].source, data[i].segs[0].length, debug)) { + if (data[i].input_mode == DATA_MODE) { + if (debug & ZINT_DEBUG_TEST_PRINT) { + printf("i:%d multiple segments in DATA_MODE not currently supported for ZXing-C++ testing (%s)\n", + i, testUtilBarcodeName(symbol->symbology)); + } + } else { + int cmp_len, ret_len; + char modules_dump[2710 * 8 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilZXingCPP(i, symbol, (const char *) data[i].segs[0].source, data[i].segs[0].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 = testUtilZXingCPPCmpSegs(symbol, cmp_msg, cmp_buf, cmp_len, data[i].segs, seg_count, + NULL /*primary*/, escaped, &ret_len); + assert_zero(ret, "i:%d %s testUtilZXingCPPCmpSegs %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); + } + + testFinish(); +} + // #181 Nico Gunkel OSS-Fuzz static void test_fuzz(int index, int debug) { @@ -2161,6 +2537,7 @@ int main(int argc, char *argv[]) { { "test_reader_init", test_reader_init, 1, 1, 1 }, { "test_input", test_input, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_encode_segs", test_encode_segs, 1, 1, 1 }, { "test_fuzz", test_fuzz, 1, 0, 1 }, { "test_perf", test_perf, 1, 0, 1 }, }; diff --git a/backend/tests/test_plessey.c b/backend/tests/test_plessey.c index 3b88b0a3..24849bf4 100644 --- a/backend/tests/test_plessey.c +++ b/backend/tests/test_plessey.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2020 - 2021 Robin Stuart + Copyright (C) 2020-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "testcommon.h" @@ -303,7 +302,7 @@ static void test_encode(int index, int generate, int debug) { assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, -1, debug)) { - ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -436,3 +435,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_postal.c b/backend/tests/test_postal.c index b590c546..86e53256 100644 --- a/backend/tests/test_postal.c +++ b/backend/tests/test_postal.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2019 - 2021 Robin Stuart + Copyright (C) 2019-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ // USPS Publication 25 (July 2003) Designing Letter and Reply Mail https://web.archive.org/web/20050118015758/http://www.siemons.com/forms/pdf/designing_letter_reply_mail.pdf // USPS DMM Domestic Mail Manual https://pe.usps.com/DMM300 @@ -474,7 +473,7 @@ static void test_encode(int index, int generate, int debug) { assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) { - ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -607,3 +606,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_qr.c b/backend/tests/test_qr.c index 1b3a57ef..65ac38e7 100644 --- a/backend/tests/test_qr.c +++ b/backend/tests/test_qr.c @@ -135,11 +135,14 @@ static void test_qr_input(int index, int generate, int debug) { struct item { int input_mode; int eci; + int option_1; int option_3; char *data; int ret; int expected_eci; char *expected; + int bwipp_cmp; + int zxingcpp_cmp; char *comment; }; // é U+00E9 in ISO 8859-1 plus other ISO 8859 (but not in ISO 8859-7 or ISO 8859-11), Win 1250 plus other Win, not in Shift JIS, UTF-8 C3A9 @@ -157,139 +160,145 @@ static void test_qr_input(int index, int generate, int debug) { // テ U+30C6 katakana, in Shift JIS 0x8365 (\203\145), UTF-8 E38386 // Á U+00C1, UTF-8 C381; ȁ U+0201, UTF-8 C881; Ȃ U+0202, UTF-8 C882; ¢ U+00A2, UTF-8 C2A2; á U+00E1, UTF-8 C3A1 struct item data[] = { - /* 0*/ { UNICODE_MODE, 0, -1, "é", 0, 0, "40 1E 90 EC 11 EC 11 EC 11", "B1 (ISO 8859-1)" }, - /* 1*/ { UNICODE_MODE, 3, -1, "é", 0, 3, "70 34 01 E9 00 EC 11 EC 11", "ECI-3 B1 (ISO 8859-1)" }, - /* 2*/ { UNICODE_MODE, 20, -1, "é", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", "é not in Shift JIS" }, - /* 3*/ { UNICODE_MODE, 26, -1, "é", 0, 26, "71 A4 02 C3 A9 00 EC 11 EC", "ECI-26 B2 (UTF-8)" }, - /* 4*/ { DATA_MODE, 0, -1, "é", 0, 0, "40 2C 3A 90 EC 11 EC 11 EC", "B2 (UTF-8)" }, - /* 5*/ { DATA_MODE, 0, -1, "\351", 0, 0, "40 1E 90 EC 11 EC 11 EC 11", "B1 (ISO 8859-1)" }, - /* 6*/ { UNICODE_MODE, 0, -1, "β", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 11 00 00 EC 11 EC 11 EC", "K1 (Shift JIS)" }, - /* 7*/ { UNICODE_MODE, 9, -1, "β", 0, 9, "70 94 01 E2 00 EC 11 EC 11", "ECI-9 B1 (ISO 8859-7)" }, - /* 8*/ { UNICODE_MODE, 20, -1, "β", 0, 20, "71 48 01 10 00 00 EC 11 EC", "ECI-20 K1 (Shift JIS)" }, - /* 9*/ { UNICODE_MODE, 26, -1, "β", 0, 26, "71 A4 02 CE B2 00 EC 11 EC", "ECI-26 B2 (UTF-8)" }, - /* 10*/ { DATA_MODE, 0, -1, "β", 0, 0, "40 2C EB 20 EC 11 EC 11 EC", "B2 (UTF-8)" }, - /* 11*/ { UNICODE_MODE, 0, -1, "ก", ZINT_WARN_USES_ECI, 13, "Warning 70 D4 01 A1 00 EC 11 EC 11", "ECI-13 B1 (ISO 8859-11)" }, - /* 12*/ { UNICODE_MODE, 13, -1, "ก", 0, 13, "70 D4 01 A1 00 EC 11 EC 11", "ECI-13 B1 (ISO 8859-11)" }, - /* 13*/ { UNICODE_MODE, 20, -1, "ก", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", "ก not in Shift JIS" }, - /* 14*/ { UNICODE_MODE, 26, -1, "ก", 0, 26, "71 A4 03 E0 B8 81 00 EC 11", "ECI-26 B3 (UTF-8)" }, - /* 15*/ { DATA_MODE, 0, -1, "ก", 0, 0, "40 3E 0B 88 10 EC 11 EC 11", "B3 (UTF-8)" }, - /* 16*/ { UNICODE_MODE, 0, -1, "Ж", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 11 23 80 EC 11 EC 11 EC", "K1 (Shift JIS)" }, - /* 17*/ { UNICODE_MODE, 7, -1, "Ж", 0, 7, "70 74 01 B6 00 EC 11 EC 11", "ECI-7 B1 (ISO 8859-5)" }, - /* 18*/ { UNICODE_MODE, 20, -1, "Ж", 0, 20, "71 48 01 12 38 00 EC 11 EC", "ECI-20 K1 (Shift JIS)" }, - /* 19*/ { UNICODE_MODE, 26, -1, "Ж", 0, 26, "71 A4 02 D0 96 00 EC 11 EC", "ECI-26 B2 (UTF-8)" }, - /* 20*/ { DATA_MODE, 0, -1, "Ж", 0, 0, "40 2D 09 60 EC 11 EC 11 EC", "B2 (UTF-8)" }, - /* 21*/ { UNICODE_MODE, 0, -1, "ກ", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 03 E0 BA 81 00 EC 11", "ECI-26 B3 (UTF-8)" }, - /* 22*/ { UNICODE_MODE, 20, -1, "ກ", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", "ກ not in Shift JIS" }, - /* 23*/ { UNICODE_MODE, 26, -1, "ກ", 0, 26, "71 A4 03 E0 BA 81 00 EC 11", "ECI-26 B3 (UTF-8)" }, - /* 24*/ { DATA_MODE, 0, -1, "ກ", 0, 0, "40 3E 0B A8 10 EC 11 EC 11", "B3 (UTF-8)" }, - /* 25*/ { UNICODE_MODE, 0, -1, "\\", 0, 0, "40 15 C0 EC 11 EC 11 EC 11", "B1 (ASCII)" }, - /* 26*/ { UNICODE_MODE, 20, -1, "\\", 0, 20, "71 48 01 00 F8 00 EC 11 EC", "ECI-20 K1 (Shift JIS)" }, - /* 27*/ { UNICODE_MODE, 20, -1, "[", 0, 20, "71 44 01 5B 00 EC 11 EC 11", "B1 (ASCII)" }, - /* 28*/ { UNICODE_MODE, 20, -1, "\177", 0, 20, "71 44 01 7F 00 EC 11 EC 11", "ECI-20 B1 (ASCII)" }, - /* 29*/ { UNICODE_MODE, 0, -1, "¥", 0, 0, "40 1A 50 EC 11 EC 11 EC 11", "B1 (ISO 8859-1) (same bytes as ・ Shift JIS below, so ambiguous)" }, - /* 30*/ { UNICODE_MODE, 3, -1, "¥", 0, 3, "70 34 01 A5 00 EC 11 EC 11", "ECI-3 B1 (ISO 8859-1)" }, - /* 31*/ { UNICODE_MODE, 20, -1, "¥", 0, 20, "71 44 01 5C 00 EC 11 EC 11", "ECI-20 B1 (Shift JIS) (to single-byte backslash codepoint 5C, so byte mode)" }, - /* 32*/ { UNICODE_MODE, 26, -1, "¥", 0, 26, "71 A4 02 C2 A5 00 EC 11 EC", "ECI-26 B2 (UTF-8)" }, - /* 33*/ { DATA_MODE, 0, -1, "¥", 0, 0, "40 2C 2A 50 EC 11 EC 11 EC", "B2 (UTF-8)" }, - /* 34*/ { UNICODE_MODE, 0, -1, "・", ZINT_WARN_NONCOMPLIANT, 0, "Warning 40 1A 50 EC 11 EC 11 EC 11", "B1 (Shift JIS) single-byte codepoint A5 (same bytes as ¥ ISO 8859-1 above, so ambiguous)" }, - /* 35*/ { UNICODE_MODE, 3, -1, "・", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", "" }, - /* 36*/ { UNICODE_MODE, 20, -1, "・", 0, 20, "71 44 01 A5 00 EC 11 EC 11", "ECI-20 B1 (Shift JIS) single-byte codepoint A5" }, - /* 37*/ { UNICODE_MODE, 26, -1, "・", 0, 26, "71 A4 03 EF BD A5 00 EC 11", "ECI-26 B3 (UTF-8)" }, - /* 38*/ { DATA_MODE, 0, -1, "・", 0, 0, "40 3E FB DA 50 EC 11 EC 11", "B3 (UTF-8)" }, - /* 39*/ { UNICODE_MODE, 0, -1, "¿", 0, 0, "40 1B F0 EC 11 EC 11 EC 11", "B1 (ISO 8859-1) (same bytes as ソ Shift JIS below, so ambiguous)" }, - /* 40*/ { UNICODE_MODE, 3, -1, "¿", 0, 3, "70 34 01 BF 00 EC 11 EC 11", "ECI-3 B1 (ISO 8859-1)" }, - /* 41*/ { UNICODE_MODE, 20, -1, "¿", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", "¿ not in Shift JIS" }, - /* 42*/ { UNICODE_MODE, 26, -1, "¿", 0, 26, "71 A4 02 C2 BF 00 EC 11 EC", "ECI-26 B2 (UTF-8)" }, - /* 43*/ { DATA_MODE, 0, -1, "¿", 0, 0, "40 2C 2B F0 EC 11 EC 11 EC", "B2 (UTF-8)" }, - /* 44*/ { UNICODE_MODE, 0, -1, "ソ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 40 1B F0 EC 11 EC 11 EC 11", "B1 (Shift JIS) single-byte codepoint BF (same bytes as ¿ ISO 8859-1 above, so ambiguous)" }, - /* 45*/ { UNICODE_MODE, 3, -1, "ソ", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", "" }, - /* 46*/ { UNICODE_MODE, 20, -1, "ソ", 0, 20, "71 44 01 BF 00 EC 11 EC 11", "ECI-20 B1 (Shift JIS) single-byte codepoint BF" }, - /* 47*/ { UNICODE_MODE, 26, -1, "ソ", 0, 26, "71 A4 03 EF BD BF 00 EC 11", "ECI-26 B3 (UTF-8)" }, - /* 48*/ { DATA_MODE, 0, -1, "ソ", 0, 0, "40 3E FB DB F0 EC 11 EC 11", "B3 (UTF-8)" }, - /* 49*/ { UNICODE_MODE, 0, -1, "~", 0, 0, "40 17 E0 EC 11 EC 11 EC 11", "B1 (ASCII) (same bytes as ‾ Shift JIS below, so ambiguous)" }, - /* 50*/ { UNICODE_MODE, 3, -1, "~", 0, 3, "70 34 01 7E 00 EC 11 EC 11", "ECI-3 B1 (ASCII)" }, - /* 51*/ { UNICODE_MODE, 20, -1, "~", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", "tilde not in Shift JIS (codepoint used for overline)" }, - /* 52*/ { UNICODE_MODE, 0, -1, "‾", ZINT_WARN_NONCOMPLIANT, 0, "Warning 40 17 E0 EC 11 EC 11 EC 11", "B1 (Shift JIS) single-byte codepoint 7E (same bytes as ~ ASCII above, so ambiguous)" }, - /* 53*/ { UNICODE_MODE, 3, -1, "‾", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", "" }, - /* 54*/ { UNICODE_MODE, 20, -1, "‾", 0, 20, "71 44 01 7E 00 EC 11 EC 11", "ECI-20 B1 (Shift JIS) (to single-byte tilde codepoint 7E, so byte mode)" }, - /* 55*/ { UNICODE_MODE, 26, -1, "‾", 0, 26, "71 A4 03 E2 80 BE 00 EC 11", "ECI-26 B3 (UTF-8)" }, - /* 56*/ { DATA_MODE, 0, -1, "‾", 0, 0, "40 3E 28 0B E0 EC 11 EC 11", "B3 (UTF-8)" }, - /* 57*/ { UNICODE_MODE, 0, -1, "点", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 16 CF 80 EC 11 EC 11 EC", "K1 (Shift JIS)" }, - /* 58*/ { UNICODE_MODE, 3, -1, "点", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", "" }, - /* 59*/ { UNICODE_MODE, 20, -1, "点", 0, 20, "71 48 01 6C F8 00 EC 11 EC", "ECI-20 K1 (Shift JIS)" }, - /* 60*/ { UNICODE_MODE, 26, -1, "点", 0, 26, "71 A4 03 E7 82 B9 00 EC 11", "ECI-26 B3 (UTF-8)" }, - /* 61*/ { DATA_MODE, 0, -1, "点", 0, 0, "40 3E 78 2B 90 EC 11 EC 11", "B3 (UTF-8)" }, - /* 62*/ { DATA_MODE, 0, -1, "\223\137", 0, 0, "40 29 35 F0 EC 11 EC 11 EC", "B2 (Shift JIS) (not full multibyte)" }, - /* 63*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "\223\137", 0, 0, "80 16 CF 80 EC 11 EC 11 EC", "K1 (Shift JIS)" }, - /* 64*/ { UNICODE_MODE, 0, -1, "¥・点", ZINT_WARN_NONCOMPLIANT, 0, "Warning 40 45 CA 59 35 F0 EC 11 EC", "B4 (Shift JIS) (optimized to byte mode only)" }, - /* 65*/ { UNICODE_MODE, 3, -1, "¥・点", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", "" }, - /* 66*/ { UNICODE_MODE, 20, -1, "¥・点", 0, 20, "71 44 04 5C A5 93 5F 00 EC", "ECI-20 B4 (Shift JIS)" }, - /* 67*/ { UNICODE_MODE, 26, -1, "¥・点", 0, 26, "71 A4 08 C2 A5 EF BD A5 E7 82 B9 00 EC", "ECI-26 B8 (UTF-8)" }, - /* 68*/ { DATA_MODE, 0, -1, "\134\245\223\137", 0, 0, "40 45 CA 59 35 F0 EC 11 EC", "B8 (Shift JIS)" }, - /* 69*/ { DATA_MODE, 0, -1, "¥・点", 0, 0, "40 8C 2A 5E FB DA 5E 78 2B 90 EC 11 EC", "B8 (UTF-8)" }, - /* 70*/ { UNICODE_MODE, 0, -1, "点茗", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 26 CF EA A8 00 EC 11 EC", "K2 (Shift JIS)" }, - /* 71*/ { UNICODE_MODE, 0, -1, "点茗テ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 36 CF EA A8 34 A0 EC 11", "K3 (Shift JIS)" }, - /* 72*/ { UNICODE_MODE, 0, -1, "点茗テ点", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 46 CF EA A8 34 AD 9F 00", "K4 (Shift JIS)" }, - /* 73*/ { UNICODE_MODE, 0, -1, "点茗テ点茗", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 56 CF EA A8 34 AD 9F D5 50 00 EC 11", "K5 (Shift JIS)" }, - /* 74*/ { UNICODE_MODE, 0, -1, "点茗テ点茗テ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 66 CF EA A8 34 AD 9F D5 50 69 40 EC", "K6 (Shift JIS)" }, - /* 75*/ { UNICODE_MODE, 0, -1, "点茗テ点茗テソ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 66 CF EA A8 34 AD 9F D5 50 69 50 06 FC 00 EC", "K6 B1 (Shift JIS)" }, - /* 76*/ { DATA_MODE, 0, -1, "\223\137\344\252\203\145\223\137\344\252\203\145\277", 0, 0, "40 D9 35 FE 4A A8 36 59 35 FE 4A A8 36 5B F0 EC", "B13 (Shift JIS)" }, - /* 77*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "\223\137\344\252\203\145\223\137\344\252\203\145\277", 0, 0, "80 66 CF EA A8 34 AD 9F D5 50 69 50 06 FC 00 EC", "K6 B1 (Shift JIS) (full multibyte)" }, - /* 78*/ { DATA_MODE, 0, -1, "点茗テ点茗テソ", 0, 0, "41 5E 78 2B 9E 88 C9 7E 38 38 6E 78 2B 9E 88 C9 7E 38 38 6E FB DB F0 EC 11 EC 11 EC", "B21 (UTF-8)" }, - /* 79*/ { DATA_MODE, 0, -1, "ÁȁȁȁȁȁȁȂ¢", 0, 0, "41 2C 38 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 2C 2A 20 EC 11", "B18 (UTF-8)" }, - /* 80*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "ÁȁȁȁȁȁȁȂ¢", 0, 0, "41 2C 38 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 2C 2A 20 EC 11", "B18 (UTF-8) (full multibyte)" }, - /* 81*/ { DATA_MODE, 0, -1, "ÁȁȁȁȁȁȁȁȂ¢", 0, 0, "41 4C 38 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 2C 2A 20", "B20 (UTF-8)" }, - /* 82*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "ÁȁȁȁȁȁȁȁȂ¢", 0, 0, "40 1C 38 09 04 40 22 01 10 08 80 44 02 20 11 00 88 0A 12 00 D1 00", "B1 K9 B1 (UTF-8) (full multibyte)" }, - /* 83*/ { UNICODE_MODE, 0, -1, "ÁȁȁȁȁȁȁȂ¢", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 12 C3 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 82 C2 A2 00", "B18 (UTF-8)" }, - /* 84*/ { UNICODE_MODE, 0, ZINT_FULL_MULTIBYTE, "ÁȁȁȁȁȁȁȂ¢", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 12 C3 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 82 C2 A2 00", "B18 (UTF-8)" }, - /* 85*/ { UNICODE_MODE, 0, -1, "ÁȁȁȁȁȁȁȁȂ¢", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 14 C3 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 82 C2 A2 00 EC 11 EC 11", "B20 (UTF-8)" }, - /* 86*/ { UNICODE_MODE, 0, ZINT_FULL_MULTIBYTE, "ÁȁȁȁȁȁȁȁȂ¢", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 01 C3 80 90 44 02 20 11 00 88 04 40 22 01 10 08 80 A1 20 0D 10 00 EC 11 EC 11", "B1 K9 B1 (UTF-8) (full multibyte)" }, - /* 87*/ { UNICODE_MODE, 0, -1, "áA", 0, 0, "40 2E 14 10 EC 11 EC 11 EC", "B2 (ISO 8859-1)" }, - /* 88*/ { UNICODE_MODE, 0, ZINT_FULL_MULTIBYTE, "áA", 0, 0, "80 1C 00 80 EC 11 EC 11 EC", "K1 (ISO 8859-1) (full multibyte)" }, - /* 89*/ { UNICODE_MODE, 0, -1, "A0B1C2D3E4F5G6H7I8J9KLMNOPQRSTUVWXYZ $%*+-./:", 0, 0, "(34) 21 69 C2 3E 08 79 26 27 A5 50 B5 98 23 32 6C 0E 65 FA C5 19 5B 42 6B 2D C1 C3 B9 E7", "A45" }, - /* 90*/ { UNICODE_MODE, 0, -1, "˘", ZINT_WARN_USES_ECI, 4, "Warning 70 44 01 A2 00 EC 11 EC 11", "ECI-4 B1 (ISO 8859-2)" }, - /* 91*/ { UNICODE_MODE, 4, -1, "˘", 0, 4, "70 44 01 A2 00 EC 11 EC 11", "ECI-4 B1 (ISO 8859-2)" }, - /* 92*/ { UNICODE_MODE, 0, -1, "Ħ", ZINT_WARN_USES_ECI, 5, "Warning 70 54 01 A1 00 EC 11 EC 11", "ECI-5 B1 (ISO 8859-3)" }, - /* 93*/ { UNICODE_MODE, 5, -1, "Ħ", 0, 5, "70 54 01 A1 00 EC 11 EC 11", "ECI-5 B1 (ISO 8859-3)" }, - /* 94*/ { UNICODE_MODE, 0, -1, "ĸ", ZINT_WARN_USES_ECI, 6, "Warning 70 64 01 A2 00 EC 11 EC 11", "ECI-6 B1 (ISO 8859-4)" }, - /* 95*/ { UNICODE_MODE, 6, -1, "ĸ", 0, 6, "70 64 01 A2 00 EC 11 EC 11", "ECI-6 B1 (ISO 8859-4)" }, - /* 96*/ { UNICODE_MODE, 0, -1, "Ș", ZINT_WARN_USES_ECI, 18, "Warning 71 24 01 AA 00 EC 11 EC 11", "ECI-18 B1 (ISO 8859-16)" }, - /* 97*/ { UNICODE_MODE, 18, -1, "Ș", 0, 18, "71 24 01 AA 00 EC 11 EC 11", "ECI-18 B1 (ISO 8859-16)" }, - /* 98*/ { UNICODE_MODE, 0, -1, "テ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 10 D2 80 EC 11 EC 11 EC", "K1 (SHIFT JIS)" }, - /* 99*/ { UNICODE_MODE, 20, -1, "テ", 0, 20, "71 48 01 0D 28 00 EC 11 EC", "ECI-20 K1 (SHIFT JIS)" }, - /*100*/ { UNICODE_MODE, 20, -1, "テテ", 0, 20, "71 48 02 0D 28 69 40 EC 11", "ECI-20 K2 (SHIFT JIS)" }, - /*101*/ { UNICODE_MODE, 20, -1, "\\\\", 0, 20, "71 48 02 00 F8 07 C0 EC 11", "ECI-20 K2 (SHIFT JIS)" }, - /*102*/ { UNICODE_MODE, 0, -1, "…", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 10 11 80 EC 11 EC 11 EC", "K1 (SHIFT JIS)" }, - /*103*/ { UNICODE_MODE, 21, -1, "…", 0, 21, "71 54 01 85 00 EC 11 EC 11", "ECI-21 B1 (Win 1250)" }, - /*104*/ { UNICODE_MODE, 0, -1, "Ґ", ZINT_WARN_USES_ECI, 22, "Warning 71 64 01 A5 00 EC 11 EC 11", "ECI-22 B1 (Win 1251)" }, - /*105*/ { UNICODE_MODE, 22, -1, "Ґ", 0, 22, "71 64 01 A5 00 EC 11 EC 11", "ECI-22 B1 (Win 1251)" }, - /*106*/ { UNICODE_MODE, 0, -1, "˜", ZINT_WARN_USES_ECI, 23, "Warning 71 74 01 98 00 EC 11 EC 11", "ECI-23 B1 (Win 1252)" }, - /*107*/ { UNICODE_MODE, 23, -1, "˜", 0, 23, "71 74 01 98 00 EC 11 EC 11", "ECI-23 B1 (Win 1252)" }, - /*108*/ { UNICODE_MODE, 24, -1, "پ", 0, 24, "71 84 01 81 00 EC 11 EC 11", "ECI-24 B1 (Win 1256)" }, - /*109*/ { UNICODE_MODE, 0, -1, "က", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 03 E1 80 80 00 EC 11", "ECI-26 B3 (UTF-8)" }, - /*110*/ { UNICODE_MODE, 25, -1, "က", 0, 25, "71 94 02 10 00 00 EC 11 EC", "ECI-25 B2 (UCS-2BE)" }, - /*111*/ { UNICODE_MODE, 25, -1, "ကက", 0, 25, "71 94 04 10 00 10 00 00 EC", "ECI-25 B4 (UCS-2BE)" }, - /*112*/ { UNICODE_MODE, 25, -1, "12", 0, 25, "71 94 04 00 31 00 32 00 EC", "ECI-25 B4 (UCS-2BE ASCII)" }, - /*113*/ { UNICODE_MODE, 27, -1, "@", 0, 27, "71 B4 01 40 00 EC 11 EC 11", "ECI-27 B1 (ASCII)" }, - /*114*/ { UNICODE_MODE, 0, -1, "龘", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 03 E9 BE 98 00 EC 11", "ECI-26 B3 (UTF-8)" }, - /*115*/ { UNICODE_MODE, 28, -1, "龘", 0, 28, "71 C4 02 F9 D5 00 EC 11 EC", "ECI-28 B2 (Big5)" }, - /*116*/ { UNICODE_MODE, 28, -1, "龘龘", 0, 28, "71 C4 04 F9 D5 F9 D5 00 EC", "ECI-28 B4 (Big5)" }, - /*117*/ { UNICODE_MODE, 0, -1, "齄", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 03 E9 BD 84 00 EC 11", "ECI-26 B3 (UTF-8)" }, - /*118*/ { UNICODE_MODE, 29, -1, "齄", 0, 29, "71 D4 02 F7 FE 00 EC 11 EC", "ECI-29 B2 (GB 2312)" }, - /*119*/ { UNICODE_MODE, 29, -1, "齄齄", 0, 29, "71 D4 04 F7 FE F7 FE 00 EC", "ECI-29 B4 (GB 2312)" }, - /*120*/ { UNICODE_MODE, 0, -1, "가", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 03 EA B0 80 00 EC 11", "ECI-26 B3 (UTF-8)" }, - /*121*/ { UNICODE_MODE, 30, -1, "가", 0, 30, "71 E4 02 B0 A1 00 EC 11 EC", "ECI-30 B2 (EUC-KR)" }, - /*122*/ { UNICODE_MODE, 30, -1, "가가", 0, 30, "71 E4 04 B0 A1 B0 A1 00 EC", "ECI-30 B4 (EUC-KR)" }, - /*123*/ { UNICODE_MODE, 170, -1, "?", 0, 170, "78 0A A4 01 3F 00 EC 11 EC", "ECI-170 B1 (ASCII invariant)" }, - /*124*/ { DATA_MODE, 899, -1, "\200", 0, 899, "78 38 34 01 80 00 EC 11 EC", "ECI-899 B1 (8-bit binary)" }, - /*125*/ { UNICODE_MODE, 900, -1, "é", 0, 900, "78 38 44 02 C3 A9 00 EC 11", "ECI-900 B2 (no conversion)" }, - /*126*/ { UNICODE_MODE, 16384, -1, "é", 0, 16384, "7C 04 00 04 02 C3 A9 00 EC", "ECI-16384 B2 (no conversion)" }, + /* 0*/ { UNICODE_MODE, 0, 4, 6 << 8, "é", 0, 0, "40 1E 90 EC 11 EC 11 EC 11", 1, 1, "B1 (ISO 8859-1)" }, + /* 1*/ { UNICODE_MODE, 3, 4, -1, "é", 0, 3, "70 34 01 E9 00 EC 11 EC 11", 1, 1, "ECI-3 B1 (ISO 8859-1)" }, + /* 2*/ { UNICODE_MODE, 20, -1, -1, "é", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", 1, 1, "é not in Shift JIS" }, + /* 3*/ { UNICODE_MODE, 26, 4, -1, "é", 0, 26, "71 A4 02 C3 A9 00 EC 11 EC", 1, 1, "ECI-26 B2 (UTF-8)" }, + /* 4*/ { DATA_MODE, 0, 4, 7 << 8, "é", 0, 0, "40 2C 3A 90 EC 11 EC 11 EC", 1, 0, "B2 (UTF-8); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 5*/ { DATA_MODE, 0, 4, 6 << 8, "\351", 0, 0, "40 1E 90 EC 11 EC 11 EC 11", 1, 1, "B1 (ISO 8859-1)" }, + /* 6*/ { UNICODE_MODE, 0, 4, 2 << 8, "β", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 11 00 00 EC 11 EC 11 EC", 1, 1, "K1 (Shift JIS)" }, + /* 7*/ { UNICODE_MODE, 9, 4, 7 << 8, "β", 0, 9, "70 94 01 E2 00 EC 11 EC 11", 1, 1, "ECI-9 B1 (ISO 8859-7)" }, + /* 8*/ { UNICODE_MODE, 20, 4, -1, "β", 0, 20, "71 48 01 10 00 00 EC 11 EC", 1, 1, "ECI-20 K1 (Shift JIS)" }, + /* 9*/ { UNICODE_MODE, 26, 4, 5 << 8, "β", 0, 26, "71 A4 02 CE B2 00 EC 11 EC", 1, 1, "ECI-26 B2 (UTF-8)" }, + /* 10*/ { DATA_MODE, 0, 4, 4 << 8, "β", 0, 0, "40 2C EB 20 EC 11 EC 11 EC", 1, 0, "B2 (UTF-8); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 11*/ { UNICODE_MODE, 0, 4, 5 << 8, "ก", ZINT_WARN_USES_ECI, 13, "Warning 70 D4 01 A1 00 EC 11 EC 11", 1, 1, "ECI-13 B1 (ISO 8859-11)" }, + /* 12*/ { UNICODE_MODE, 13, 4, 5 << 8, "ก", 0, 13, "70 D4 01 A1 00 EC 11 EC 11", 1, 1, "ECI-13 B1 (ISO 8859-11)" }, + /* 13*/ { UNICODE_MODE, 20, -1, -1, "ก", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", 1, 1, "ก not in Shift JIS" }, + /* 14*/ { UNICODE_MODE, 26, 4, 8 << 8, "ก", 0, 26, "71 A4 03 E0 B8 81 00 EC 11", 1, 1, "ECI-26 B3 (UTF-8)" }, + /* 15*/ { DATA_MODE, 0, 4, 3 << 8, "ก", 0, 0, "40 3E 0B 88 10 EC 11 EC 11", 1, 0, "B3 (UTF-8); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 16*/ { UNICODE_MODE, 0, 4, 8 << 8, "Ж", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 11 23 80 EC 11 EC 11 EC", 1, 1, "K1 (Shift JIS)" }, + /* 17*/ { UNICODE_MODE, 7, 4, -1, "Ж", 0, 7, "70 74 01 B6 00 EC 11 EC 11", 1, 1, "ECI-7 B1 (ISO 8859-5)" }, + /* 18*/ { UNICODE_MODE, 20, 4, 7 << 8, "Ж", 0, 20, "71 48 01 12 38 00 EC 11 EC", 1, 1, "ECI-20 K1 (Shift JIS)" }, + /* 19*/ { UNICODE_MODE, 26, 4, -1, "Ж", 0, 26, "71 A4 02 D0 96 00 EC 11 EC", 1, 1, "ECI-26 B2 (UTF-8)" }, + /* 20*/ { DATA_MODE, 0, 4, -1, "Ж", 0, 0, "40 2D 09 60 EC 11 EC 11 EC", 1, 0, "B2 (UTF-8); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 21*/ { UNICODE_MODE, 0, 4, -1, "ກ", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 03 E0 BA 81 00 EC 11", 1, 1, "ECI-26 B3 (UTF-8)" }, + /* 22*/ { UNICODE_MODE, 20, -1, -1, "ກ", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", 1, 1, "ກ not in Shift JIS" }, + /* 23*/ { UNICODE_MODE, 26, 4, -1, "ກ", 0, 26, "71 A4 03 E0 BA 81 00 EC 11", 1, 1, "ECI-26 B3 (UTF-8)" }, + /* 24*/ { DATA_MODE, 0, 4, 8 << 8, "ກ", 0, 0, "40 3E 0B A8 10 EC 11 EC 11", 1, 0, "B3 (UTF-8); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 25*/ { UNICODE_MODE, 0, 4, 2 << 8, "\\", 0, 0, "40 15 C0 EC 11 EC 11 EC 11", 1, 1, "B1 (ASCII)" }, + /* 26*/ { UNICODE_MODE, 20, 4, 4 << 8, "\\", 0, 20, "71 48 01 00 F8 00 EC 11 EC", 1, 0, "ECI-20 K1 (Shift JIS); ZXing-C++ doesn't map Shift JIS ASCII" }, + /* 27*/ { UNICODE_MODE, 20, 4, -1, "[", 0, 20, "71 44 01 5B 00 EC 11 EC 11", 1, 1, "B1 (ASCII)" }, + /* 28*/ { UNICODE_MODE, 20, 4, 3 << 8, "\177", 0, 20, "71 44 01 7F 00 EC 11 EC 11", 1, 1, "ECI-20 B1 (ASCII)" }, + /* 29*/ { UNICODE_MODE, 0, 4, 2 << 8, "¥", 0, 0, "40 1A 50 EC 11 EC 11 EC 11", 1, 1, "B1 (ISO 8859-1) (same bytes as ・ Shift JIS below, so ambiguous)" }, + /* 30*/ { UNICODE_MODE, 3, 4, 3 << 8, "¥", 0, 3, "70 34 01 A5 00 EC 11 EC 11", 1, 1, "ECI-3 B1 (ISO 8859-1)" }, + /* 31*/ { UNICODE_MODE, 20, 4, 5 << 8, "¥", 0, 20, "71 44 01 5C 00 EC 11 EC 11", 1, 0, "ECI-20 B1 (Shift JIS) (to single-byte backslash codepoint 5C, so byte mode); ZXing-C++ doesn't map Shift JIS ASCII" }, + /* 32*/ { UNICODE_MODE, 26, 4, 6 << 8, "¥", 0, 26, "71 A4 02 C2 A5 00 EC 11 EC", 1, 1, "ECI-26 B2 (UTF-8)" }, + /* 33*/ { DATA_MODE, 0, 4, 2 << 8, "¥", 0, 0, "40 2C 2A 50 EC 11 EC 11 EC", 1, 0, "B2 (UTF-8); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 34*/ { UNICODE_MODE, 0, 4, 2 << 8, "・", ZINT_WARN_NONCOMPLIANT, 0, "Warning 40 1A 50 EC 11 EC 11 EC 11", 1, 1, "B1 (Shift JIS) single-byte codepoint A5 (same bytes as ¥ ISO 8859-1 above, so ambiguous)" }, + /* 35*/ { UNICODE_MODE, 3, -1, -1, "・", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", 1, 1, "" }, + /* 36*/ { UNICODE_MODE, 20, 4, 7 << 8, "・", 0, 20, "71 44 01 A5 00 EC 11 EC 11", 1, 1, "ECI-20 B1 (Shift JIS) single-byte codepoint A5" }, + /* 37*/ { UNICODE_MODE, 26, 4, -1, "・", 0, 26, "71 A4 03 EF BD A5 00 EC 11", 1, 1, "ECI-26 B3 (UTF-8)" }, + /* 38*/ { DATA_MODE, 0, 4, 8 << 8, "・", 0, 0, "40 3E FB DA 50 EC 11 EC 11", 1, 0, "B3 (UTF-8); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 39*/ { UNICODE_MODE, 0, 4, -1, "¿", 0, 0, "40 1B F0 EC 11 EC 11 EC 11", 1, 1, "B1 (ISO 8859-1) (same bytes as ソ Shift JIS below, so ambiguous)" }, + /* 40*/ { UNICODE_MODE, 3, 4, 8 << 8, "¿", 0, 3, "70 34 01 BF 00 EC 11 EC 11", 1, 1, "ECI-3 B1 (ISO 8859-1)" }, + /* 41*/ { UNICODE_MODE, 20, -1, -1, "¿", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", 1, 1, "¿ not in Shift JIS" }, + /* 42*/ { UNICODE_MODE, 26, 4, 2 << 8, "¿", 0, 26, "71 A4 02 C2 BF 00 EC 11 EC", 1, 1, "ECI-26 B2 (UTF-8)" }, + /* 43*/ { DATA_MODE, 0, 4, 3 << 8, "¿", 0, 0, "40 2C 2B F0 EC 11 EC 11 EC", 1, 0, "B2 (UTF-8); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 44*/ { UNICODE_MODE, 0, 4, -1, "ソ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 40 1B F0 EC 11 EC 11 EC 11", 1, 1, "B1 (Shift JIS) single-byte codepoint BF (same bytes as ¿ ISO 8859-1 above, so ambiguous)" }, + /* 45*/ { UNICODE_MODE, 3, -1, -1, "ソ", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", 1, 1, "" }, + /* 46*/ { UNICODE_MODE, 20, 4, 6 << 8, "ソ", 0, 20, "71 44 01 BF 00 EC 11 EC 11", 1, 1, "ECI-20 B1 (Shift JIS) single-byte codepoint BF" }, + /* 47*/ { UNICODE_MODE, 26, 4, 4 << 8, "ソ", 0, 26, "71 A4 03 EF BD BF 00 EC 11", 1, 1, "ECI-26 B3 (UTF-8)" }, + /* 48*/ { DATA_MODE, 0, 4, -1, "ソ", 0, 0, "40 3E FB DB F0 EC 11 EC 11", 1, 0, "B3 (UTF-8); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 49*/ { UNICODE_MODE, 0, 4, -1, "~", 0, 0, "40 17 E0 EC 11 EC 11 EC 11", 1, 1, "B1 (ASCII) (same bytes as ‾ Shift JIS below, so ambiguous)" }, + /* 50*/ { UNICODE_MODE, 3, 4, -1, "~", 0, 3, "70 34 01 7E 00 EC 11 EC 11", 1, 1, "ECI-3 B1 (ASCII)" }, + /* 51*/ { UNICODE_MODE, 20, -1, -1, "~", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", 1, 1, "tilde not in Shift JIS (codepoint used for overline)" }, + /* 52*/ { UNICODE_MODE, 0, 4, -1, "‾", ZINT_WARN_NONCOMPLIANT, 0, "Warning 40 17 E0 EC 11 EC 11 EC 11", 1, 0, "B1 (Shift JIS) single-byte codepoint 7E (same bytes as ~ ASCII above, so ambiguous); ZXing-C++ doesn't map Shift JIS ASCII" }, + /* 53*/ { UNICODE_MODE, 3, -1, -1, "‾", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", 1, 1, "" }, + /* 54*/ { UNICODE_MODE, 20, 4, 7 << 8, "‾", 0, 20, "71 44 01 7E 00 EC 11 EC 11", 1, 0, "ECI-20 B1 (Shift JIS) (to single-byte tilde codepoint 7E, so byte mode); ZXing-C++ doesn't map Shift JIS ASCII" }, + /* 55*/ { UNICODE_MODE, 26, 4, 1 << 8, "‾", 0, 26, "71 A4 03 E2 80 BE 00 EC 11", 1, 1, "ECI-26 B3 (UTF-8)" }, + /* 56*/ { DATA_MODE, 0, 4, -1, "‾", 0, 0, "40 3E 28 0B E0 EC 11 EC 11", 1, 0, "B3 (UTF-8); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 57*/ { UNICODE_MODE, 0, 4, -1, "点", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 16 CF 80 EC 11 EC 11 EC", 1, 1, "K1 (Shift JIS)" }, + /* 58*/ { UNICODE_MODE, 3, -1, -1, "点", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", 1, 1, "" }, + /* 59*/ { UNICODE_MODE, 20, 4, 3 << 8, "点", 0, 20, "71 48 01 6C F8 00 EC 11 EC", 1, 1, "ECI-20 K1 (Shift JIS)" }, + /* 60*/ { UNICODE_MODE, 26, 4, -1, "点", 0, 26, "71 A4 03 E7 82 B9 00 EC 11", 1, 1, "ECI-26 B3 (UTF-8)" }, + /* 61*/ { DATA_MODE, 0, 4, 6 << 8, "点", 0, 0, "40 3E 78 2B 90 EC 11 EC 11", 1, 0, "B3 (UTF-8); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 62*/ { DATA_MODE, 0, 4, 4 << 8, "\223\137", 0, 0, "40 29 35 F0 EC 11 EC 11 EC", 0, 0, "B2 (Shift JIS) (not full multibyte); BWIPP same as FULL_MULTIBYTE; ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 63*/ { DATA_MODE, 0, 4, ZINT_FULL_MULTIBYTE, "\223\137", 0, 0, "80 16 CF 80 EC 11 EC 11 EC", 1, 1, "K1 (Shift JIS)" }, + /* 64*/ { UNICODE_MODE, 0, 4, -1, "¥・点", ZINT_WARN_NONCOMPLIANT, 0, "Warning 40 45 CA 59 35 F0 EC 11 EC", 1, 0, "B4 (Shift JIS) (optimized to byte mode only); ZXing-C++ doesn't map Shift JIS ASCII" }, + /* 65*/ { UNICODE_MODE, 3, -1, -1, "¥・点", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", 1, 1, "" }, + /* 66*/ { UNICODE_MODE, 20, 4, 4 << 8, "¥・点", 0, 20, "71 44 04 5C A5 93 5F 00 EC", 1, 0, "ECI-20 B4 (Shift JIS); ZXing-C++ doesn't map Shift JIS ASCII" }, + /* 67*/ { UNICODE_MODE, 26, 3, 7 << 8, "¥・点", 0, 26, "71 A4 08 C2 A5 EF BD A5 E7 82 B9 00 EC", 1, 1, "ECI-26 B8 (UTF-8)" }, + /* 68*/ { DATA_MODE, 0, 4, -1, "\134\245\223\137", 0, 0, "40 45 CA 59 35 F0 EC 11 EC", 1, 0, "B8 (Shift JIS); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 69*/ { DATA_MODE, 0, 3, -1, "¥・点", 0, 0, "40 8C 2A 5E FB DA 5E 78 2B 90 EC 11 EC", 1, 0, "B8 (UTF-8); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 70*/ { UNICODE_MODE, 0, 4, 8 << 8, "点茗", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 26 CF EA A8 00 EC 11 EC", 1, 1, "K2 (Shift JIS)" }, + /* 71*/ { UNICODE_MODE, 0, 4, -1, "点茗テ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 36 CF EA A8 34 A0 EC 11", 1, 1, "K3 (Shift JIS)" }, + /* 72*/ { UNICODE_MODE, 0, 4, -1, "点茗テ点", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 46 CF EA A8 34 AD 9F 00", 1, 1, "K4 (Shift JIS)" }, + /* 73*/ { UNICODE_MODE, 0, 3, -1, "点茗テ点茗", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 56 CF EA A8 34 AD 9F D5 50 00 EC 11", 1, 1, "K5 (Shift JIS)" }, + /* 74*/ { UNICODE_MODE, 0, 3, 1 << 8, "点茗テ点茗テ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 66 CF EA A8 34 AD 9F D5 50 69 40 EC", 1, 1, "K6 (Shift JIS)" }, + /* 75*/ { UNICODE_MODE, 0, 2, 4 << 8, "点茗テ点茗テソ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 66 CF EA A8 34 AD 9F D5 50 69 50 06 FC 00 EC", 1, 1, "K6 B1 (Shift JIS)" }, + /* 76*/ { DATA_MODE, 0, 2, 8 << 8, "\223\137\344\252\203\145\223\137\344\252\203\145\277", 0, 0, "40 D9 35 FE 4A A8 36 59 35 FE 4A A8 36 5B F0 EC", 0, 0, "B13 (Shift JIS); BWIPP same as FULL_MULTIBYTE; ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 77*/ { DATA_MODE, 0, 2, ZINT_FULL_MULTIBYTE | (4 << 8), "\223\137\344\252\203\145\223\137\344\252\203\145\277", 0, 0, "80 66 CF EA A8 34 AD 9F D5 50 69 50 06 FC 00 EC", 1, 1, "K6 B1 (Shift JIS) (full multibyte)" }, + /* 78*/ { DATA_MODE, 0, 2, 2 << 8, "点茗テ点茗テソ", 0, 0, "41 5E 78 2B 9E 88 C9 7E 38 38 6E 78 2B 9E 88 C9 7E 38 38 6E FB DB F0 EC 11 EC 11 EC", 1, 0, "B21 (UTF-8); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 79*/ { DATA_MODE, 0, 3, 8 << 8, "ÁȁȁȁȁȁȁȂ¢", 0, 0, "41 2C 38 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 2C 2A 20 EC 11", 1, 0, "B18 (UTF-8); ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 80*/ { DATA_MODE, 0, 3, ZINT_FULL_MULTIBYTE | (8 << 8), "ÁȁȁȁȁȁȁȂ¢", 0, 0, "41 2C 38 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 2C 2A 20 EC 11", 1, 1, "B18 (UTF-8) (full multibyte)" }, + /* 81*/ { DATA_MODE, 0, 3, 4 << 8, "ÁȁȁȁȁȁȁȁȂ¢", 0, 0, "41 4C 38 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 2C 2A 20", 0, 0, "B20 (UTF-8); BWIPP same as FULL_MULTIBYTE; ZXing-C++ test can't handle DATA_MODE for certain inputs" }, + /* 82*/ { DATA_MODE, 0, 3, ZINT_FULL_MULTIBYTE | (4 << 8), "ÁȁȁȁȁȁȁȁȂ¢", 0, 0, "40 1C 38 09 04 40 22 01 10 08 80 44 02 20 11 00 88 0A 12 00 D1 00", 1, 1, "B1 K9 B1 (UTF-8) (full multibyte)" }, + /* 83*/ { UNICODE_MODE, 0, 3, 8 << 8, "ÁȁȁȁȁȁȁȂ¢", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 12 C3 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 82 C2 A2 00", 1, 1, "B18 (UTF-8)" }, + /* 84*/ { UNICODE_MODE, 0, 3, ZINT_FULL_MULTIBYTE | (8 << 8), "ÁȁȁȁȁȁȁȂ¢", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 12 C3 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 82 C2 A2 00", 1, 1, "B18 (UTF-8)" }, + /* 85*/ { UNICODE_MODE, 0, 2, 1 << 8, "ÁȁȁȁȁȁȁȁȂ¢", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 14 C3 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 82 C2 A2 00 EC 11 EC 11", 0, 1, "B20 (UTF-8); BWIPP same as FULL_MULTIBYTE" }, + /* 86*/ { UNICODE_MODE, 0, 2, ZINT_FULL_MULTIBYTE | (1 << 8), "ÁȁȁȁȁȁȁȁȂ¢", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 01 C3 80 90 44 02 20 11 00 88 04 40 22 01 10 08 80 A1 20 0D 10 00 EC 11 EC 11", 1, 1, "B1 K9 B1 (UTF-8) (full multibyte)" }, + /* 87*/ { UNICODE_MODE, 0, 4, -1, "áA", 0, 0, "40 2E 14 10 EC 11 EC 11 EC", 0, 1, "B2 (ISO 8859-1); BWIPP same as FULL_MULTIBYTE" }, + /* 88*/ { UNICODE_MODE, 0, 4, ZINT_FULL_MULTIBYTE, "áA", 0, 0, "80 1C 00 80 EC 11 EC 11 EC", 1, 1, "K1 (ISO 8859-1) (full multibyte)" }, + /* 89*/ { UNICODE_MODE, 0, 1, -1, "A0B1C2D3E4F5G6H7I8J9KLMNOPQRSTUVWXYZ $%*+-./:", 0, 0, "(34) 21 69 C2 3E 08 79 26 27 A5 50 B5 98 23 32 6C 0E 65 FA C5 19 5B 42 6B 2D C1 C3 B9 E7", 1, 1, "A45" }, + /* 90*/ { UNICODE_MODE, 0, 4, 7 << 8, "˘", ZINT_WARN_USES_ECI, 4, "Warning 70 44 01 A2 00 EC 11 EC 11", 1, 1, "ECI-4 B1 (ISO 8859-2)" }, + /* 91*/ { UNICODE_MODE, 4, 4, 7 << 8, "˘", 0, 4, "70 44 01 A2 00 EC 11 EC 11", 1, 1, "ECI-4 B1 (ISO 8859-2)" }, + /* 92*/ { UNICODE_MODE, 0, 4, 7 << 8, "Ħ", ZINT_WARN_USES_ECI, 5, "Warning 70 54 01 A1 00 EC 11 EC 11", 1, 1, "ECI-5 B1 (ISO 8859-3)" }, + /* 93*/ { UNICODE_MODE, 5, 4, 7 << 8, "Ħ", 0, 5, "70 54 01 A1 00 EC 11 EC 11", 1, 1, "ECI-5 B1 (ISO 8859-3)" }, + /* 94*/ { UNICODE_MODE, 0, 4, -1, "ĸ", ZINT_WARN_USES_ECI, 6, "Warning 70 64 01 A2 00 EC 11 EC 11", 1, 1, "ECI-6 B1 (ISO 8859-4)" }, + /* 95*/ { UNICODE_MODE, 6, 4, -1, "ĸ", 0, 6, "70 64 01 A2 00 EC 11 EC 11", 1, 1, "ECI-6 B1 (ISO 8859-4)" }, + /* 96*/ { UNICODE_MODE, 0, 4, 8 << 8, "Ș", ZINT_WARN_USES_ECI, 18, "Warning 71 24 01 AA 00 EC 11 EC 11", 1, 1, "ECI-18 B1 (ISO 8859-16)" }, + /* 97*/ { UNICODE_MODE, 18, 4, 8 << 8, "Ș", 0, 18, "71 24 01 AA 00 EC 11 EC 11", 1, 1, "ECI-18 B1 (ISO 8859-16)" }, + /* 98*/ { UNICODE_MODE, 0, 4, 2 << 8, "テ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 10 D2 80 EC 11 EC 11 EC", 1, 1, "K1 (SHIFT JIS)" }, + /* 99*/ { UNICODE_MODE, 20, 4, 2 << 8, "テ", 0, 20, "71 48 01 0D 28 00 EC 11 EC", 1, 1, "ECI-20 K1 (SHIFT JIS)" }, + /*100*/ { UNICODE_MODE, 20, 4, 4 << 8, "テテ", 0, 20, "71 48 02 0D 28 69 40 EC 11", 1, 1, "ECI-20 K2 (SHIFT JIS)" }, + /*101*/ { UNICODE_MODE, 20, 4, -1, "\\\\", 0, 20, "71 48 02 00 F8 07 C0 EC 11", 1, 0, "ECI-20 K2 (SHIFT JIS); ZXing-C++ doesn't map Shift JIS ASCII" }, + /*102*/ { UNICODE_MODE, 0, 4, -1, "…", ZINT_WARN_NONCOMPLIANT, 0, "Warning 80 10 11 80 EC 11 EC 11 EC", 1, 1, "K1 (SHIFT JIS)" }, + /*103*/ { UNICODE_MODE, 21, 4, -1, "…", 0, 21, "71 54 01 85 00 EC 11 EC 11", 1, 1, "ECI-21 B1 (Win 1250)" }, + /*104*/ { UNICODE_MODE, 0, 4, 7 << 8, "Ґ", ZINT_WARN_USES_ECI, 22, "Warning 71 64 01 A5 00 EC 11 EC 11", 1, 1, "ECI-22 B1 (Win 1251)" }, + /*105*/ { UNICODE_MODE, 22, 4, 7 << 8, "Ґ", 0, 22, "71 64 01 A5 00 EC 11 EC 11", 1, 1, "ECI-22 B1 (Win 1251)" }, + /*106*/ { UNICODE_MODE, 0, 4, 6 << 8, "˜", ZINT_WARN_USES_ECI, 23, "Warning 71 74 01 98 00 EC 11 EC 11", 1, 1, "ECI-23 B1 (Win 1252)" }, + /*107*/ { UNICODE_MODE, 23, 4, 6 << 8, "˜", 0, 23, "71 74 01 98 00 EC 11 EC 11", 1, 1, "ECI-23 B1 (Win 1252)" }, + /*108*/ { UNICODE_MODE, 24, 4, 5 << 8, "پ", 0, 24, "71 84 01 81 00 EC 11 EC 11", 1, 1, "ECI-24 B1 (Win 1256)" }, + /*109*/ { UNICODE_MODE, 0, 4, 7 << 8, "က", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 03 E1 80 80 00 EC 11", 1, 1, "ECI-26 B3 (UTF-8)" }, + /*110*/ { UNICODE_MODE, 25, 4, -1, "က", 0, 25, "71 94 02 10 00 00 EC 11 EC", 1, 1, "ECI-25 B2 (UCS-2BE)" }, + /*111*/ { UNICODE_MODE, 25, 4, 4 << 8, "ကက", 0, 25, "71 94 04 10 00 10 00 00 EC", 1, 1, "ECI-25 B4 (UCS-2BE)" }, + /*112*/ { UNICODE_MODE, 25, 4, -1, "12", 0, 25, "71 94 04 00 31 00 32 00 EC", 1, 1, "ECI-25 B4 (UCS-2BE ASCII)" }, + /*113*/ { UNICODE_MODE, 27, 4, 4 << 8, "@", 0, 27, "71 B4 01 40 00 EC 11 EC 11", 1, 1, "ECI-27 B1 (ASCII)" }, + /*114*/ { UNICODE_MODE, 0, 4, -1, "龘", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 03 E9 BE 98 00 EC 11", 1, 1, "ECI-26 B3 (UTF-8)" }, + /*115*/ { UNICODE_MODE, 28, 4, 3 << 8, "龘", 0, 28, "71 C4 02 F9 D5 00 EC 11 EC", 1, 1, "ECI-28 B2 (Big5)" }, + /*116*/ { UNICODE_MODE, 28, 4, 4 << 8, "龘龘", 0, 28, "71 C4 04 F9 D5 F9 D5 00 EC", 1, 1, "ECI-28 B4 (Big5)" }, + /*117*/ { UNICODE_MODE, 0, 4, 8 << 8, "齄", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 03 E9 BD 84 00 EC 11", 1, 1, "ECI-26 B3 (UTF-8)" }, + /*118*/ { UNICODE_MODE, 29, 4, -1, "齄", 0, 29, "71 D4 02 F7 FE 00 EC 11 EC", 1, 1, "ECI-29 B2 (GB 2312)" }, + /*119*/ { UNICODE_MODE, 29, 4, 4 << 8, "齄齄", 0, 29, "71 D4 04 F7 FE F7 FE 00 EC", 1, 1, "ECI-29 B4 (GB 2312)" }, + /*120*/ { UNICODE_MODE, 0, 4, 8 << 8, "가", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 03 EA B0 80 00 EC 11", 1, 1, "ECI-26 B3 (UTF-8)" }, + /*121*/ { UNICODE_MODE, 30, 4, -1, "가", 0, 30, "71 E4 02 B0 A1 00 EC 11 EC", 1, 1, "ECI-30 B2 (EUC-KR)" }, + /*122*/ { UNICODE_MODE, 30, 4, -1, "가가", 0, 30, "71 E4 04 B0 A1 B0 A1 00 EC", 1, 1, "ECI-30 B4 (EUC-KR)" }, + /*123*/ { UNICODE_MODE, 170, 4, 2 << 8, "?", 0, 170, "78 0A A4 01 3F 00 EC 11 EC", 1, 1, "ECI-170 B1 (ASCII invariant)" }, + /*124*/ { DATA_MODE, 899, 4, 3 << 8, "\200", 0, 899, "78 38 34 01 80 00 EC 11 EC", 1, 1, "ECI-899 B1 (8-bit binary)" }, + /*125*/ { UNICODE_MODE, 900, 4, 8 << 8, "é", 0, 900, "78 38 44 02 C3 A9 00 EC 11", 1, 1, "ECI-900 B2 (no conversion)" }, + /*126*/ { UNICODE_MODE, 16384, 4, 8 << 8, "é", 0, 16384, "7C 04 00 04 02 C3 A9 00 EC", 1, 1, "ECI-16384 B2 (no conversion)" }, + /*127*/ { UNICODE_MODE, 3, 4, -1, "product:Google Pixel 4a - 128 GB of Storage - Black;price:$439.97", 0, 3, "(86) 70 34 39 70 72 6F 64 75 63 74 3A 47 6F 6F 67 6C 65 20 50 69 78 65 6C 20 34 61 20 2D", 0, 1, "ECI-3 B57 A8; BWIPP different encodation (B65)" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol; char escaped[4096]; + 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 testStart("test_qr_input"); @@ -303,21 +312,54 @@ static void test_qr_input(int index, int generate, int debug) { debug |= ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - length = testUtilSetSymbol(symbol, BARCODE_QRCODE, data[i].input_mode, data[i].eci, -1 /*option_1*/, -1, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, BARCODE_QRCODE, data[i].input_mode, data[i].eci, data[i].option_1, -1, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, %d, %s, \"%s\", %s, %d, \"%s\", \"%s\" },\n", - i, testUtilInputModeName(data[i].input_mode), data[i].eci, testUtilOption3Name(data[i].option_3), + printf(" /*%3d*/ { %s, %d, %d, %s, \"%s\", %s, %d, \"%s\", %d, %d, \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), data[i].eci, data[i].option_1, testUtilOption3Name(data[i].option_3), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), - testUtilErrorName(data[i].ret), ret < ZINT_ERROR ? symbol->eci : -1, symbol->errtxt, data[i].comment); + testUtilErrorName(data[i].ret), ret < ZINT_ERROR ? symbol->eci : -1, symbol->errtxt, + data[i].bwipp_cmp, data[i].zxingcpp_cmp, data[i].comment); } else { if (ret < ZINT_ERROR) { assert_equal(symbol->eci, data[i].expected_eci, "i:%d eci %d != %d\n", i, symbol->eci, data[i].expected_eci); } assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + + if (ret < ZINT_ERROR) { + if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, -1, data[i].option_3 | ZINT_FULL_MULTIBYTE, 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[177 * 177 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilBwipp(i, symbol, data[i].option_1, -1, data[i].option_3 | ZINT_FULL_MULTIBYTE, 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)) { + if (!data[i].zxingcpp_cmp) { + if (debug & ZINT_DEBUG_TEST_PRINT) printf("i:%d %s not ZXing-C++ compatible (%s)\n", i, testUtilBarcodeName(symbol->symbology), data[i].comment); + } else { + int cmp_len, ret_len; + char modules_dump[177 * 177 + 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); @@ -330,31 +372,37 @@ static void test_qr_gs1(int index, int generate, int debug) { struct item { int input_mode; + int option_1; + int option_3; char *data; int ret; char *expected; char *comment; }; struct item data[] = { - /* 0*/ { GS1_MODE, "[01]12345678901231", 0, "51 04 00 B3 AA 37 DE 87 B1", "N16" }, - /* 1*/ { GS1_MODE | GS1PARENS_MODE, "(01)12345678901231", 0, "51 04 00 B3 AA 37 DE 87 B1", "N16" }, - /* 2*/ { GS1_MODE, "[01]04912345123459[15]970331[30]128[10]ABC123", 0, "51 07 40 A7 AC EA 80 15 9E 4F CA 52 D2 D3 84 09 D5 E0 28 FD 82 F0 C0 EC 11 EC 11 EC", "N29 A9" }, - /* 3*/ { GS1_MODE | GS1PARENS_MODE, "(01)04912345123459(15)970331(30)128(10)ABC123", 0, "51 07 40 A7 AC EA 80 15 9E 4F CA 52 D2 D3 84 09 D5 E0 28 FD 82 F0 C0 EC 11 EC 11 EC", "N29 A9" }, - /* 4*/ { GS1_MODE, "[91]12%[20]12", 0, "52 05 99 60 5F B5 35 80 01 08 00 EC 11", "A10(11)" }, - /* 5*/ { GS1_MODE, "[91]123%[20]12", 0, "52 06 19 60 5E 2B 76 A0 5A 05 E0 EC 11", "A11(12)" }, - /* 6*/ { GS1_MODE, "[91]1234%[20]12", 0, "52 06 99 60 5E 22 F6 A6 B0 00 21 00 EC", "A12(13)" }, - /* 7*/ { GS1_MODE, "[91]12345%[20]12", 0, "51 01 F8 F3 A9 48 0F B5 35 80 01 08 00", "N7 A6(7) (same bit count as A13(14))" }, - /* 8*/ { GS1_MODE, "[91]%%[20]12", 0, "52 05 99 6D A9 B5 35 80 01 08 00 EC 11", "A9(11)" }, - /* 9*/ { GS1_MODE, "[91]%%%[20]12", 0, "52 06 99 6D A9 B5 36 A6 B0 00 21 00 EC", "A10(13)" }, - /* 10*/ { GS1_MODE, "[91]A%%%%1234567890123AA%", 0, "52 05 99 63 D1 B5 36 A6 D4 98 40 D1 ED C8 C5 40 C3 20 21 CC DA 80", "A7(11) N13 A3(4)" }, - /* 11*/ { GS1_MODE, "[91]%23%%6789%%%34567%%%%234%%%%%", 0, "(34) 52 17 19 6D A8 17 76 A6 D4 22 A5 C7 6A 6D 4D A8 22 C7 39 61 DA 9B 53 6A 6B 01 17 B5", "A31(46)" }, - /* 12*/ { GS1_MODE, "[91]ABCDEFGHI[92]ABCDEF", 0, "52 0A 19 63 9A 8A 54 2A E1 6A 06 5C E6 A2 95 0A", "A20(23)" }, + /* 0*/ { GS1_MODE, 4, 7 << 8, "[01]12345678901231", 0, "51 04 00 B3 AA 37 DE 87 B1", "N16" }, + /* 1*/ { GS1_MODE | GS1PARENS_MODE, 4, 7 << 8, "(01)12345678901231", 0, "51 04 00 B3 AA 37 DE 87 B1", "N16" }, + /* 2*/ { GS1_MODE, 2, 4 << 8, "[01]04912345123459[15]970331[30]128[10]ABC123", 0, "51 07 40 A7 AC EA 80 15 9E 4F CA 52 D2 D3 84 09 D5 E0 28 FD 82 F0 C0 EC 11 EC 11 EC", "N29 A9" }, + /* 3*/ { GS1_MODE | GS1PARENS_MODE, 2, 4 << 8, "(01)04912345123459(15)970331(30)128(10)ABC123", 0, "51 07 40 A7 AC EA 80 15 9E 4F CA 52 D2 D3 84 09 D5 E0 28 FD 82 F0 C0 EC 11 EC 11 EC", "N29 A9" }, + /* 4*/ { GS1_MODE, 3, -1, "[91]12%[20]12", 0, "52 05 99 60 5F B5 35 80 01 08 00 EC 11", "A10(11)" }, + /* 5*/ { GS1_MODE, 3, 1 << 8, "[91]123%[20]12", 0, "52 06 19 60 5E 2B 76 A0 5A 05 E0 EC 11", "A11(12)" }, + /* 6*/ { GS1_MODE, 3, 6 << 8, "[91]1234%[20]12", 0, "52 06 99 60 5E 22 F6 A6 B0 00 21 00 EC", "A12(13)" }, + /* 7*/ { GS1_MODE, 3, -1, "[91]12345%[20]12", 0, "51 01 F8 F3 A9 48 0F B5 35 80 01 08 00", "N7 A6(7) (same bit count as A13(14))" }, + /* 8*/ { GS1_MODE, 3, 8 << 8, "[91]%%[20]12", 0, "52 05 99 6D A9 B5 35 80 01 08 00 EC 11", "A9(11)" }, + /* 9*/ { GS1_MODE, 3, 6 << 8, "[91]%%%[20]12", 0, "52 06 99 6D A9 B5 36 A6 B0 00 21 00 EC", "A10(13)" }, + /* 10*/ { GS1_MODE, 3, 6 << 8, "[91]A%%%%1234567890123AA%", 0, "52 05 99 63 D1 B5 36 A6 D4 98 40 D1 ED C8 C5 40 C3 20 21 CC DA 80", "A7(11) N13 A3(4)" }, + /* 11*/ { GS1_MODE, 1, -1, "[91]%23%%6789%%%34567%%%%234%%%%%", 0, "(34) 52 17 19 6D A8 17 76 A6 D4 22 A5 C7 6A 6D 4D A8 22 C7 39 61 DA 9B 53 6A 6B 01 17 B5", "A31(46)" }, + /* 12*/ { GS1_MODE, 2, 5 << 8, "[91]ABCDEFGHI[92]ABCDEF", 0, "52 0A 19 63 9A 8A 54 2A E1 6A 06 5C E6 A2 95 0A", "A20(23)" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol; char escaped[4096]; + 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 testStart("test_qr_gs1"); @@ -368,16 +416,32 @@ static void test_qr_gs1(int index, int generate, int debug) { debug |= ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - length = testUtilSetSymbol(symbol, BARCODE_QRCODE, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, BARCODE_QRCODE, data[i].input_mode, -1 /*eci*/, data[i].option_1, -1, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, \"%s\", %s, \"%s\", \"%s\" },\n", - i, testUtilInputModeName(data[i].input_mode), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), testUtilErrorName(data[i].ret), symbol->errtxt, data[i].comment); + printf(" /*%3d*/ { %s, %d, %d, \"%s\", %s, \"%s\", \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_3, + testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), testUtilErrorName(data[i].ret), symbol->errtxt, data[i].comment); } else { assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + + if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, -1, data[i].option_3, debug)) { + if (0 /*!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[177 * 177 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilBwipp(i, symbol, data[i].option_1, -1, 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); + } + } } ZBarcode_Delete(symbol); @@ -391,48 +455,55 @@ static void test_qr_optimize(int index, int generate, int debug) { struct item { int input_mode; int option_1; + int option_3; // OR-ed with ZINT_FULL_MULTIBYTE char *data; int ret; char *expected; + int bwipp_cmp; char *comment; }; struct item data[] = { - /* 0*/ { UNICODE_MODE, -1, "1", 0, "10 04 40 EC 11 EC 11 EC 11", "N1" }, - /* 1*/ { UNICODE_MODE, -1, "AAA", 0, "20 19 CC 28 00 EC 11 EC 11", "A3" }, - /* 2*/ { UNICODE_MODE, -1, "0123456789", 0, "10 28 0C 56 6A 69 00 EC 11", " N10 (nayuki.io - pure numeric)" }, - /* 3*/ { UNICODE_MODE, -1, "ABCDEF", 0, "20 31 CD 45 2A 14 00 EC 11", "A6 (nayuki.io - pure alphanumeric)" }, - /* 4*/ { UNICODE_MODE, -1, "wxyz", 0, "40 47 77 87 97 A0 EC 11 EC", "B4 (nayuki.io - pure byte)" }, - /* 5*/ { UNICODE_MODE, 1, "「魔法少女まどか☆マギカ」って、 ИАИ desu κα?", ZINT_WARN_NONCOMPLIANT, "Warning (55) 81 D0 1A C0 09 F8 0A ED 56 B8 57 02 8E 12 90 2C 86 F4 31 A1 8A 01 B0 50 42 88 00 10", "K29 (nayuki.io - pure kanji)" }, - /* 6*/ { UNICODE_MODE, -1, "012345A", 0, "20 38 01 0B A2 E4 A0 EC 11", "A7 (nayuki.io - alpha/numeric)" }, - /* 7*/ { UNICODE_MODE, -1, "0123456A", 0, "10 1C 0C 56 58 80 25 00 EC", "N7 A1 (nayuki.io - alpha/numeric) (note same bits as A8)" }, - /* 8*/ { UNICODE_MODE, -1, "012a", 0, "40 43 03 13 26 10 EC 11 EC", "B4 (nayuki.io - numeric/byte)" }, - /* 9*/ { UNICODE_MODE, -1, "0123a", 0, "10 10 0C 34 01 61 00 EC 11", "N4 B1 (nayuki.io - numeric/byte)" }, - /* 10*/ { UNICODE_MODE, -1, "ABCDEa", 0, "40 64 14 24 34 44 56 10 EC", "B6 (nayuki.io - alphanumeric/byte)" }, - /* 11*/ { UNICODE_MODE, -1, "ABCDEFa", 0, "20 31 CD 45 2A 15 00 58 40", "A6 B1 (nayuki.io - alphanumeric/byte)" }, - /* 12*/ { UNICODE_MODE, 1, "THE SQUARE ROOT OF 2 IS 1.41421356237309504880168872420969807856967187537694807317667973799", 0, "(55) 20 D5 2A 53 54 1A A8 4C DC DF 14 29 EC 47 CA D9 9A 88 05 71 10 59 E3 56 32 5D 45 F0", " A26 N65 (nayuki.io - alpha/numeric)" }, - /* 13*/ { UNICODE_MODE, 1, "Golden ratio φ = 1.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374......", ZINT_WARN_NONCOMPLIANT, "Warning (80) 41 44 76 F6 C6 46 56 E2 07 26 17 46 96 F2 08 3D 32 03 D2 03 12 E1 19 26 A0 87 DC BB", "B20 N100 A6 (nayuki.io - alpha/numeric/byte)" }, - /* 14*/ { UNICODE_MODE, 1, "こんにちwa、世界! αβγδ", ZINT_WARN_NONCOMPLIANT, "Warning (34) 41 B8 2B 18 2F 18 2C 98 2B F7 76 18 14 19 0A 28 A4 58 14 92 08 3B F8 3C 08 3C 18 3C", "B27 (nayuki.io - kanji/european **NOT SAME** K4 B2 K4 A1 K4, less bits as nayuki (1.5.0) miscounting byte-mode input as UTF-8)" }, - /* 15*/ { UNICODE_MODE, 1, "こんにちテwa、世界! αβγδ", ZINT_WARN_NONCOMPLIANT, "Warning (34) 80 50 98 85 C4 29 21 3F 0D 2A 09 BB B0 C0 A0 C8 51 45 22 C0 A4 90 41 DF C1 E0 41 E0", "K5 B19 (nayuki.io - kanji/european + extra leading kanji **NOT SAME** K5 B2 K4 A1 K4, same reason as above)" }, - /* 16*/ { UNICODE_MODE, 1, "67128177921547861663com.acme35584af52fa3-88d0-093b-6c14-b37ddafb59c528908608sg.com.dash.www0530329356521790265903SG.COM.NETS46968696003522G33250183309051017567088693441243693268766948304B2AE13344004SG.SGQR209710339366720B439682.63667470805057501195235502733744600368027857918629797829126902859SG8236HELLO FOO2517Singapore3272B815", 0, "(232) 10 52 9F 46 70 B3 5D DE 9A 1F A1 7B 1B 7B 69 73 0B 1B 6B 29 99 A9 A9 C1 A3 0B 31 A9", "N20 B47 N9 B15 N22 A11 N14 A1 N47 A19 N15 A8 N65 A20 B8 A8 (nayuki.io - SGQR alpha/numeric/byte)" }, - /* 17*/ { UNICODE_MODE, -1, "纪", ZINT_WARN_USES_ECI, "Warning 71 A4 03 E7 BA AA 00 EC 11", "ECI-26 B3 (UTF-8 E7BAAA, U+7EAA, not in Shift JIS)" }, - /* 18*/ { DATA_MODE, -1, "纪", 0, "40 3E 7B AA A0 EC 11 EC 11", "B3 (UTF-8 or Shift JIS, note ambiguous as 0xE7BA 0xAA happens to be valid Shift JIS 郤ェ as well)" }, - /* 19*/ { UNICODE_MODE, -1, "郤ェ", ZINT_WARN_NONCOMPLIANT, "Warning 40 3E 7B AA A0 EC 11 EC 11", "B3 (Shift JIS or UTF-8 E7BAAA 纪, see above)" }, - /* 20*/ { UNICODE_MODE, 1, "2004年大西洋颶風季是有纪录以来造成人员伤亡和财产损失最为惨重的大西洋飓风季之一,于2004年6月1日正式开始,同年11月30日结束,传统上这样的日期界定了一年中绝大多数热带气旋在大西洋形成的时间段lll ku", ZINT_WARN_USES_ECI, "Warning (324) 71 A1 00 43 21 10 04 4B 96 E6 D3 96 92 9F A2 96 FF 9A D2 2F A6 8A DB A6 8A A3 96 B6", "ECI-26 N4 B274 (nayuki.io - kanji/byte/numeric **NOT SAME* N4 K9 B6 K5 etc mixing Shift JIS and UTF-8)" }, - /* 21*/ { UNICODE_MODE, -1, "AB123456A", 0, "20 49 CD 05 E2 2C 73 94 00", "A9" }, - /* 22*/ { UNICODE_MODE, -1, "AB1234567890A", 0, "20 69 CD 05 E2 2C 73 94 33 2A 50 00 EC", "A13" }, - /* 23*/ { UNICODE_MODE, -1, "AB123456789012A", 0, "20 79 CD 05 E2 2C 73 94 33 2A 0B CA 00", "A15" }, - /* 24*/ { UNICODE_MODE, -1, "AB1234567890123A", 0, "20 11 CD 10 34 7B 72 31 50 30 C8 02 50", "A2 N13 A1" }, - /* 25*/ { UNICODE_MODE, -1, "テaABCD1", ZINT_WARN_NONCOMPLIANT, "Warning 40 88 36 56 14 14 24 34 43 10 EC 11 EC", "B8" }, - /* 26*/ { UNICODE_MODE, -1, "テaABCDE1", ZINT_WARN_NONCOMPLIANT, "Warning 40 38 36 56 12 03 1C D4 52 9D C0 EC 11", "B3 A6" }, - /* 27*/ { UNICODE_MODE, -1, "テéaABCDE1", ZINT_WARN_USES_ECI, "Warning 71 A4 06 E3 83 86 C3 A9 61 20 31 CD 45 29 DC 00", "B6 A6" }, - /* 28*/ { UNICODE_MODE, -1, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", ZINT_WARN_NONCOMPLIANT, "Warning (44) 80 83 A8 85 88 25 CA 2F 40 B0 53 C2 44 98 41 00 4A 02 0E A8 F8 F5 0D 30 4C 35 A1 CC", "K8 N1 K8 B3" }, - /* 29*/ { UNICODE_MODE, -1, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。社ト可化モマ試音ばじご育青康演ぴぎ権型固スで能麩ぜらもほ河都しちほラ収90作の年要とだむ部動ま者断チ第41一1米索焦茂げむしれ。測フ物使だて目月国スリカハ夏検にいへ児72告物ゆは載核ロアメヱ登輸どべゃ催行アフエハ議歌ワ河倫剖だ。記タケウ因載ヒイホヤ禁3輩彦関トえび肝区勝ワリロ成禁ぼよ界白ウヒキレ中島べせぜい各安うしぽリ覧生テ基一でむしゃ中新トヒキソ声碁スしび起田ア信大未ゅもばち。", ZINT_WARN_NONCOMPLIANT, "Warning (589) 80 20 EA 21 62 09 72 8B D0 2C 14 F0 91 26 10 40 04 A0 08 3A A3 E3 D4 34 C1 30 D6 87", "K8 N1 K8 N1 K10 N2 K33 N2 K16 N1 K89 N2 K14 B5 K28 N2 K40 N1 K65" }, + /* 0*/ { UNICODE_MODE, 4, -1, "1", 0, "10 04 40 EC 11 EC 11 EC 11", 1, "N1" }, + /* 1*/ { UNICODE_MODE, 4, 5 << 8, "AAA", 0, "20 19 CC 28 00 EC 11 EC 11", 1, "A3" }, + /* 2*/ { UNICODE_MODE, 4, 1 << 8, "0123456789", 0, "10 28 0C 56 6A 69 00 EC 11", 1, " N10 (nayuki.io - pure numeric)" }, + /* 3*/ { UNICODE_MODE, 4, -1, "ABCDEF", 0, "20 31 CD 45 2A 14 00 EC 11", 1, "A6 (nayuki.io - pure alphanumeric)" }, + /* 4*/ { UNICODE_MODE, 4, -1, "wxyz", 0, "40 47 77 87 97 A0 EC 11 EC", 1, "B4 (nayuki.io - pure byte)" }, + /* 5*/ { UNICODE_MODE, 1, -1, "「魔法少女まどか☆マギカ」って、 ИАИ desu κα?", ZINT_WARN_NONCOMPLIANT, "Warning (55) 81 D0 1A C0 09 F8 0A ED 56 B8 57 02 8E 12 90 2C 86 F4 31 A1 8A 01 B0 50 42 88 00 10", 1, "K29 (nayuki.io - pure kanji)" }, + /* 6*/ { UNICODE_MODE, 4, 1 << 8, "012345A", 0, "20 38 01 0B A2 E4 A0 EC 11", 1, "A7 (nayuki.io - alpha/numeric)" }, + /* 7*/ { UNICODE_MODE, 4, -1, "0123456A", 0, "10 1C 0C 56 58 80 25 00 EC", 1, "N7 A1 (nayuki.io - alpha/numeric) (note same bits as A8)" }, + /* 8*/ { UNICODE_MODE, 4, 1 << 8, "012a", 0, "40 43 03 13 26 10 EC 11 EC", 1, "B4 (nayuki.io - numeric/byte)" }, + /* 9*/ { UNICODE_MODE, 4, 4 << 8, "0123a", 0, "10 10 0C 34 01 61 00 EC 11", 1, "N4 B1 (nayuki.io - numeric/byte)" }, + /* 10*/ { UNICODE_MODE, 4, 4 << 8, "ABCDEa", 0, "40 64 14 24 34 44 56 10 EC", 1, "B6 (nayuki.io - alphanumeric/byte)" }, + /* 11*/ { UNICODE_MODE, 4, -1, "ABCDEFa", 0, "20 31 CD 45 2A 15 00 58 40", 1, "A6 B1 (nayuki.io - alphanumeric/byte)" }, + /* 12*/ { UNICODE_MODE, 1, 1 << 8, "THE SQUARE ROOT OF 2 IS 1.41421356237309504880168872420969807856967187537694807317667973799", 0, "(55) 20 D5 2A 53 54 1A A8 4C DC DF 14 29 EC 47 CA D9 9A 88 05 71 10 59 E3 56 32 5D 45 F0", 1, " A26 N65 (nayuki.io - alpha/numeric)" }, + /* 13*/ { UNICODE_MODE, 1, -1, "Golden ratio φ = 1.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374......", ZINT_WARN_NONCOMPLIANT, "Warning (80) 41 44 76 F6 C6 46 56 E2 07 26 17 46 96 F2 08 3D 32 03 D2 03 12 E1 19 26 A0 87 DC BB", 1, "B20 N100 A6 (nayuki.io - alpha/numeric/byte)" }, + /* 14*/ { UNICODE_MODE, 1, -1, "こんにちwa、世界! αβγδ", ZINT_WARN_NONCOMPLIANT, "Warning (34) 41 B8 2B 18 2F 18 2C 98 2B F7 76 18 14 19 0A 28 A4 58 14 92 08 3B F8 3C 08 3C 18 3C", 1, "B27 (nayuki.io - kanji/european **NOT SAME** K4 B2 K4 A1 K4, less bits as nayuki (1.5.0) miscounting byte-mode input as UTF-8)" }, + /* 15*/ { UNICODE_MODE, 1, 2 << 8, "こんにちテwa、世界! αβγδ", ZINT_WARN_NONCOMPLIANT, "Warning (34) 80 50 98 85 C4 29 21 3F 0D 2A 09 BB B0 C0 A0 C8 51 45 22 C0 A4 90 41 DF C1 E0 41 E0", 1, "K5 B19 (nayuki.io - kanji/european + extra leading kanji **NOT SAME** K5 B2 K4 A1 K4, same reason as above)" }, + /* 16*/ { UNICODE_MODE, 1, 8 << 8, "67128177921547861663com.acme35584af52fa3-88d0-093b-6c14-b37ddafb59c528908608sg.com.dash.www0530329356521790265903SG.COM.NETS46968696003522G33250183309051017567088693441243693268766948304B2AE13344004SG.SGQR209710339366720B439682.63667470805057501195235502733744600368027857918629797829126902859SG8236HELLO FOO2517Singapore3272B815", 0, "(232) 10 52 9F 46 70 B3 5D DE 9A 1F A1 7B 1B 7B 69 73 0B 1B 6B 29 99 A9 A9 C1 A3 0B 31 A9", 0, "N20 B47 N9 B15 N22 A11 N14 A1 N47 A19 N15 A8 N65 A20 B8 A8 (nayuki.io - SGQR alpha/numeric/byte); BWIPP different encodation (B13 N3 at end instead of B8 A8)" }, + /* 17*/ { UNICODE_MODE, 4, 1 << 8, "纪", ZINT_WARN_USES_ECI, "Warning 71 A4 03 E7 BA AA 00 EC 11", 1, "ECI-26 B3 (UTF-8 E7BAAA, U+7EAA, not in Shift JIS)" }, + /* 18*/ { DATA_MODE, 4, 1 << 8, "纪", 0, "40 3E 7B AA A0 EC 11 EC 11", 1, "B3 (UTF-8 or Shift JIS, note ambiguous as 0xE7BA 0xAA happens to be valid Shift JIS 郤ェ as well)" }, + /* 19*/ { UNICODE_MODE, 4, 1 << 8, "郤ェ", ZINT_WARN_NONCOMPLIANT, "Warning 40 3E 7B AA A0 EC 11 EC 11", 1, "B3 (Shift JIS or UTF-8 E7BAAA 纪, see above)" }, + /* 20*/ { UNICODE_MODE, 1, -1, "2004年大西洋颶風季是有纪录以来造成人员伤亡和财产损失最为惨重的大西洋飓风季之一,于2004年6月1日正式开始,同年11月30日结束,传统上这样的日期界定了一年中绝大多数热带气旋在大西洋形成的时间段lll ku", ZINT_WARN_USES_ECI, "Warning (324) 71 A1 00 43 21 10 04 4B 96 E6 D3 96 92 9F A2 96 FF 9A D2 2F A6 8A DB A6 8A A3 96 B6", 0, "ECI-26 N4 B274 (nayuki.io - kanji/byte/numeric **NOT SAME* N4 K9 B6 K5 etc mixing Shift JIS and UTF-8); BWIPP different encodation (N4 K1 B272)" }, + /* 21*/ { UNICODE_MODE, 4, 1 << 8, "AB123456A", 0, "20 49 CD 05 E2 2C 73 94 00", 1, "A9" }, + /* 22*/ { UNICODE_MODE, 3, -1, "AB1234567890A", 0, "20 69 CD 05 E2 2C 73 94 33 2A 50 00 EC", 1, "A13" }, + /* 23*/ { UNICODE_MODE, 3, -1, "AB123456789012A", 0, "20 79 CD 05 E2 2C 73 94 33 2A 0B CA 00", 1, "A15" }, + /* 24*/ { UNICODE_MODE, 3, -1, "AB1234567890123A", 0, "20 11 CD 10 34 7B 72 31 50 30 C8 02 50", 1, "A2 N13 A1" }, + /* 25*/ { UNICODE_MODE, 3, 2 << 8, "テaABCD1", ZINT_WARN_NONCOMPLIANT, "Warning 40 88 36 56 14 14 24 34 43 10 EC 11 EC", 1, "B8" }, + /* 26*/ { UNICODE_MODE, 3, -1, "テaABCDE1", ZINT_WARN_NONCOMPLIANT, "Warning 40 38 36 56 12 03 1C D4 52 9D C0 EC 11", 0, "B3 A6; BWIPP different encodation (B9)" }, + /* 27*/ { UNICODE_MODE, 2, -1, "テéaABCDE1", ZINT_WARN_USES_ECI, "Warning 71 A4 06 E3 83 86 C3 A9 61 20 31 CD 45 29 DC 00", 0, "B6 A6; BWIPP different encodation (B12)" }, + /* 28*/ { UNICODE_MODE, 2, -1, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", ZINT_WARN_NONCOMPLIANT, "Warning (44) 80 83 A8 85 88 25 CA 2F 40 B0 53 C2 44 98 41 00 4A 02 0E A8 F8 F5 0D 30 4C 35 A1 CC", 0, "K8 N1 K8 B3; BWIPP different encodation (K8 N1 K8 N1 K1)" }, + /* 29*/ { UNICODE_MODE, 1, -1, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。社ト可化モマ試音ばじご育青康演ぴぎ権型固スで能麩ぜらもほ河都しちほラ収90作の年要とだむ部動ま者断チ第41一1米索焦茂げむしれ。測フ物使だて目月国スリカハ夏検にいへ児72告物ゆは載核ロアメヱ登輸どべゃ催行アフエハ議歌ワ河倫剖だ。記タケウ因載ヒイホヤ禁3輩彦関トえび肝区勝ワリロ成禁ぼよ界白ウヒキレ中島べせぜい各安うしぽリ覧生テ基一でむしゃ中新トヒキソ声碁スしび起田ア信大未ゅもばち。", ZINT_WARN_NONCOMPLIANT, "Warning (589) 80 20 EA 21 62 09 72 8B D0 2C 14 F0 91 26 10 40 04 A0 08 3A A3 E3 D4 34 C1 30 D6 87", 0, "K8 N1 K8 N1 K10 N2 K33 N2 K16 N1 K89 N2 K14 B5 K28 N2 K40 N1 K65; BWIPP different encodation (same except A2 B6 instead of B5)" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol; char escaped[4096]; + 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 testStart("test_qr_optimize"); @@ -446,17 +517,43 @@ static void test_qr_optimize(int index, int generate, int debug) { debug |= ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - length = testUtilSetSymbol(symbol, BARCODE_QRCODE, data[i].input_mode, -1 /*eci*/, data[i].option_1, -1, ZINT_FULL_MULTIBYTE, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, BARCODE_QRCODE, data[i].input_mode, -1 /*eci*/, data[i].option_1, -1, data[i].option_3 | ZINT_FULL_MULTIBYTE, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, %d, \"%s\", %s, \"%s\", \"%s\" },\n", - i, testUtilInputModeName(data[i].input_mode), data[i].option_1, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), - testUtilErrorName(data[i].ret), symbol->errtxt, data[i].comment); + printf(" /*%3d*/ { %s, %d, %d, \"%s\", %s, \"%s\", %d, \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_3, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), + testUtilErrorName(data[i].ret), symbol->errtxt, data[i].bwipp_cmp, data[i].comment); } else { assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + + if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, -1, data[i].option_3 | ZINT_FULL_MULTIBYTE, 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[177 * 177 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilBwipp(i, symbol, data[i].option_1, -1, data[i].option_3 | ZINT_FULL_MULTIBYTE, 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[177 * 177 + 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); @@ -1575,7 +1672,34 @@ static void test_qr_encode(int index, int generate, int debug) { "1000001011001010011000001" "1111111011010111011011111" }, - /* 32*/ { BARCODE_QRCODE, UNICODE_MODE, 4, 1, -1, -1, { 0, 0, "" }, "Študentska št. 2198390", -1, 0, 25, 25, 0, "AIM ITS/04-023:2022 ECI 4 Example 1 **NOT SAME** different encodation; BWIPP same encodation as Zint but uses mask 011 instead of 100", + /* 32*/ { BARCODE_QRCODE, UNICODE_MODE, 3, 1, -1, 1 << 8, { 0, 0, "" }, "C:\\DOCS\\EXAMPLE.TXT", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 3 Example 3 **NOT SAME** different encodation", + "1111111001001101101111111" + "1000001000111001101000001" + "1011101011101010001011101" + "1011101001110011001011101" + "1011101000100000101011101" + "1000001001000111101000001" + "1111111010101010101111111" + "0000000011101101100000000" + "1110111110110010011000100" + "0010110010110001010011001" + "1001101111000101101111001" + "1011100000010000111001110" + "1010011000001001001100011" + "0011010001011101010100010" + "1010001101111010011111100" + "0111110101001111000000110" + "1010101011010010111110101" + "0000000011110010100010010" + "1111111011100101101010111" + "1000001010110001100010001" + "1011101011101001111110101" + "1011101000011100111010010" + "1011101010111010100010101" + "1000001011101110111100101" + "1111111011110011111111011" + }, + /* 33*/ { BARCODE_QRCODE, UNICODE_MODE, 4, 1, -1, -1, { 0, 0, "" }, "Študentska št. 2198390", -1, 0, 25, 25, 0, "AIM ITS/04-023:2022 ECI 4 Example 1 **NOT SAME** different encodation; BWIPP same encodation as Zint but uses mask 011 instead of 100", "1111111010000110001111111" "1000001010011110101000001" "1011101011001111101011101" @@ -1602,7 +1726,34 @@ static void test_qr_encode(int index, int generate, int debug) { "1000001011110101110010101" "1111111010101100000011011" }, - /* 33*/ { BARCODE_QRCODE, UNICODE_MODE, 4, 1, -1, -1, { 0, 0, "" }, "Szczegółowe dane kontaktowe:+48 22 694 60 00", -1, 0, 29, 29, 0, "AIM ITS/04-023:2022 ECI 4 Example 2 **NOT SAME** different encodation; BWIPP same encodation as example but uses mask 100 instead of 111", + /* 34*/ { BARCODE_QRCODE, UNICODE_MODE, 4, 1, -1, 4 << 8, { 0, 0, "" }, "Študentska št. 2198390", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 4 Example 1 **NOT SAME** different encodation", + "1111111011000001001111111" + "1000001000000010101000001" + "1011101010011010101011101" + "1011101011010011001011101" + "1011101011110110001011101" + "1000001001001110101000001" + "1111111010101010101111111" + "0000000001010101000000000" + "1111001010000000110011101" + "1000100001000110110000011" + "1101011110000001000101111" + "0101010010011111101001101" + "1101101101010001000001000" + "0010100100110100101111001" + "0111011111001110010011011" + "1001010010001000100100001" + "0010001000110010111111010" + "0000000011101101100011100" + "1111111000011001101011111" + "1000001000101010100011010" + "1011101000111101111110110" + "1011101011101100101010001" + "1011101010011100100100110" + "1000001010100000100111111" + "1111111011101011000100011" + }, + /* 35*/ { BARCODE_QRCODE, UNICODE_MODE, 4, 1, -1, -1, { 0, 0, "" }, "Szczegółowe dane kontaktowe:+48 22 694 60 00", -1, 0, 29, 29, 0, "AIM ITS/04-023:2022 ECI 4 Example 2 **NOT SAME** different encodation; BWIPP same encodation as example but uses mask 100 instead of 111", "11111110000111011111001111111" "10000010011001101100101000001" "10111010000010110011101011101" @@ -1633,7 +1784,7 @@ static void test_qr_encode(int index, int generate, int debug) { "10000010110011101010011100110" "11111110101010100011111001100" }, - /* 34*/ { BARCODE_QRCODE, UNICODE_MODE, 5, 1, -1, -1, { 0, 0, "" }, "Liĥtenŝtejno", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 5 Example 1; BWIPP uses mask 011 instead of 101", + /* 36*/ { BARCODE_QRCODE, UNICODE_MODE, 5, 1, -1, -1, { 0, 0, "" }, "Liĥtenŝtejno", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 5 Example 1; BWIPP uses mask 011 instead of 101", "111111100111101111111" "100000100101001000001" "101110100100001011101" @@ -1656,7 +1807,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101010010111111" "111111101011110000010" }, - /* 35*/ { BARCODE_QRCODE, UNICODE_MODE, 6, 1, -1, -1, { 0, 0, "" }, "Lietuvą", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 6 Example 1", + /* 37*/ { BARCODE_QRCODE, UNICODE_MODE, 5, 1, -1, 4 << 8, { 0, 0, "" }, "Liĥtenŝtejno", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 5 Example 1 **NOT SAME** explicit mask 011", + "111111101100101111111" + "100000100100101000001" + "101110101010101011101" + "101110101001001011101" + "101110101111001011101" + "100000100000001000001" + "111111101010101111111" + "000000000111000000000" + "111100101010010011101" + "110101001111011111100" + "001001110110110111010" + "010111000100101001110" + "111000110001101000100" + "000000001101111100001" + "111111100111101110100" + "100000100100010110010" + "101110100110001100011" + "101110101010100010110" + "101110101100001001000" + "100000101011111110010" + "111111101101000110100" + }, + /* 38*/ { BARCODE_QRCODE, UNICODE_MODE, 6, 1, -1, -1, { 0, 0, "" }, "Lietuvą", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 6 Example 1", "111111101000101111111" "100000101010001000001" "101110100000101011101" @@ -1679,7 +1853,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101011011111011" "111111101111111010101" }, - /* 36*/ { BARCODE_QRCODE, UNICODE_MODE, 7, 1, -1, -1, { 0, 0, "" }, "Россия", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 7 Example 1", + /* 39*/ { BARCODE_QRCODE, UNICODE_MODE, 7, 1, -1, -1, { 0, 0, "" }, "Россия", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 7 Example 1", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -1702,7 +1876,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101011100101011" "111111101100010100110" }, - /* 37*/ { BARCODE_QRCODE, UNICODE_MODE, 7, 1, -1, -1, { 0, 0, "" }, "Монголулс", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 7 Example 2; BWIPP uses mask 000 instead of 111", + /* 40*/ { BARCODE_QRCODE, UNICODE_MODE, 7, 1, -1, -1, { 0, 0, "" }, "Монголулс", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 7 Example 2; BWIPP uses mask 000 instead of 111", "111111100101101111111" "100000101101001000001" "101110101100101011101" @@ -1725,7 +1899,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101011000010111" "111111101001110100110" }, - /* 38*/ { BARCODE_QRCODE, UNICODE_MODE, 8, 1, -1, -1, { 0, 0, "" }, "جواز السفر", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 8 Example 1", + /* 41*/ { BARCODE_QRCODE, UNICODE_MODE, 7, 1, -1, 1 << 8, { 0, 0, "" }, "Монголулс", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 7 Example 2 **NOT SAME** explicit mask 000", + "111111100101101111111" + "100000100111001000001" + "101110101101101011101" + "101110100101001011101" + "101110100010101011101" + "100000100000101000001" + "111111101010101111111" + "000000001101100000000" + "111011111111011000100" + "111110010000001011100" + "000100110000100001000" + "101001010010010000110" + "000011110010110100101" + "000000001111001110110" + "111111101011011101111" + "100000101001111000101" + "101110101011010100011" + "101110100111001010110" + "101110101110100011101" + "100000101001010000101" + "111111101000111101111" + }, + /* 42*/ { BARCODE_QRCODE, UNICODE_MODE, 8, 1, -1, -1, { 0, 0, "" }, "جواز السفر", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 8 Example 1", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -1748,7 +1945,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101110000010011" "111111101000010100010" }, - /* 39*/ { BARCODE_QRCODE, UNICODE_MODE, 8, 1, -1, -1, { 0, 0, "" }, "المنشأ: المملكة العربية السعودية", -1, 0, 29, 29, 0, "AIM ITS/04-023:2022 ECI 8 Example 2; BWIPP uses mask 000 instead of 010", + /* 43*/ { BARCODE_QRCODE, UNICODE_MODE, 8, 1, -1, -1, { 0, 0, "" }, "المنشأ: المملكة العربية السعودية", -1, 0, 29, 29, 0, "AIM ITS/04-023:2022 ECI 8 Example 2; BWIPP uses mask 000 instead of 010", "11111110001011110110001111111" "10000010101001111101001000001" "10111010000011010110101011101" @@ -1779,7 +1976,38 @@ static void test_qr_encode(int index, int generate, int debug) { "10000010100011001101001000101" "11111110110010101010110010100" }, - /* 40*/ { BARCODE_QRCODE, UNICODE_MODE, 9, 1, -1, -1, { 0, 0, "" }, "Μέρος #. α123", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 9 Example 1 **NOT SAME** example uses mask 111 instead of 000", + /* 44*/ { BARCODE_QRCODE, UNICODE_MODE, 8, 1, -1, 1 << 8, { 0, 0, "" }, "المنشأ: المملكة العربية السعودية", -1, 0, 29, 29, 1, "AIM ITS/04-023:2022 ECI 8 Example 2 **NOT SAME** explicit mask 000", + "11111110010011001110101111111" + "10000010001110111010001000001" + "10111010111011101110001011101" + "10111010011101110000101011101" + "10111010001000100110101011101" + "10000010010001000111101000001" + "11111110101010101010101111111" + "00000000111011101001100000000" + "11101111101100111011011000100" + "01000001101100110111000000110" + "11001011010001001111010000011" + "01001001000100010101111010011" + "00110011000010000011111011110" + "11000100110111010001100000101" + "01010010101110111000110000011" + "10101001101011111100111010010" + "00110111110100111101011100010" + "01110001000100100010110000110" + "10110110110001011100110011101" + "01000000111100001101111010011" + "10100010110010010001111110101" + "00000000110111001001100010110" + "11111110101110111000101010111" + "10000010101011111111100011010" + "10111010110100111110111111000" + "10111010001100110011110101010" + "10111010111001011000110011001" + "10000010100100001010001111101" + "11111110101010010010001010011" + }, + /* 45*/ { BARCODE_QRCODE, UNICODE_MODE, 9, 1, -1, -1, { 0, 0, "" }, "Μέρος #. α123", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 9 Example 1 **NOT SAME** example uses mask 111 instead of 000", "111111100100101111111" "100000100111001000001" "101110101100101011101" @@ -1802,7 +2030,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101111110111001" "111111101101001101111" }, - /* 41*/ { BARCODE_QRCODE, UNICODE_MODE, 9, 1, -1, 8 << 8, { 0, 0, "" }, "Μέρος #. α123", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 9 Example 1 with explicit mask 111; BWIPP uses mask 000", + /* 46*/ { BARCODE_QRCODE, UNICODE_MODE, 9, 1, -1, 8 << 8, { 0, 0, "" }, "Μέρος #. α123", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 9 Example 1 with explicit mask 111; BWIPP uses mask 000", "111111100100101111111" "100000101101001000001" "101110101101101011101" @@ -1825,7 +2053,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101101100101011" "111111101100000100110" }, - /* 42*/ { BARCODE_QRCODE, UNICODE_MODE, 10, 1, -1, -1, { 0, 0, "" }, "דרכון", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 10 Example 1; BWIPP uses mask 000 instead of 101", + /* 47*/ { BARCODE_QRCODE, UNICODE_MODE, 9, 1, -1, 1 << 8, { 0, 0, "" }, "Μέρος #. α123", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 9 Example 1 **NOT SAME** explicit mask 000", + "111111100100101111111" + "100000100111001000001" + "101110101100101011101" + "101110100101001011101" + "101110100011001011101" + "100000100001101000001" + "111111101010101111111" + "000000001100100000000" + "111011111111111000100" + "101100010001010100111" + "101101101011000010100" + "100010000101010110110" + "010111101110110010101" + "000000001001010110110" + "111111101000100011111" + "100000101000001010100" + "101110101100100101100" + "101110100010010010110" + "101110101010100101001" + "100000101111110111001" + "111111101101001101111" + }, + /* 48*/ { BARCODE_QRCODE, UNICODE_MODE, 10, 1, -1, -1, { 0, 0, "" }, "דרכון", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 10 Example 1; BWIPP uses mask 000 instead of 101", "111111100000101111111" "100000100010101000001" "101110100011101011101" @@ -1848,7 +2099,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101111111010011" "111111101110100011010" }, - /* 43*/ { BARCODE_QRCODE, UNICODE_MODE, 10, 1, -1, -1, { 0, 0, "" }, "מספר חלק: A20200715001", -1, 0, 25, 25, 0, "AIM ITS/04-023:2022 ECI 10 Example 2 **NOT SAME** different encodation; BWIPP uses mask 000 instead of 100", + /* 49*/ { BARCODE_QRCODE, UNICODE_MODE, 10, 1, -1, 1 << 8, { 0, 0, "" }, "דרכון", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 10 Example 1 **NOT SAME** explicit mask 000", + "111111100101101111111" + "100000100111001000001" + "101110101101101011101" + "101110100101001011101" + "101110100010101011101" + "100000100000101000001" + "111111101010101111111" + "000000001101100000000" + "111011111111011000100" + "010001001110001100100" + "000000110000100010011" + "101001000100001101010" + "000001101000101011001" + "000000001001010010110" + "111111101001011101011" + "100000101011110111111" + "101110101111011100100" + "101110100000001000110" + "101110101100100110001" + "100000101010001111101" + "111111101000101101011" + }, + /* 50*/ { BARCODE_QRCODE, UNICODE_MODE, 10, 1, -1, -1, { 0, 0, "" }, "מספר חלק: A20200715001", -1, 0, 25, 25, 0, "AIM ITS/04-023:2022 ECI 10 Example 2 **NOT SAME** different encodation; BWIPP uses mask 000 instead of 100", "1111111011101100001111111" "1000001011100001001000001" "1011101010110001001011101" @@ -1875,7 +2149,34 @@ static void test_qr_encode(int index, int generate, int debug) { "1000001011001010100011101" "1111111011010110001000011" }, - /* 44*/ { BARCODE_QRCODE, UNICODE_MODE, 11, 1, -1, -1, { 0, 0, "" }, "Amerika Birleşik Devletleri", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 11 Example 1", + /* 51*/ { BARCODE_QRCODE, UNICODE_MODE, 10, 1, -1, 1 << 8, { 0, 0, "" }, "מספר חלק: A20200715001", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 10 Example 2 **NOT SAME** different encodation", + "1111111001001000101111111" + "1000001000111010001000001" + "1011101011101010001011101" + "1011101001110100101011101" + "1011101000100010101011101" + "1000001001000001001000001" + "1111111010101010101111111" + "0000000011101101000000000" + "1110111110110010111000100" + "0000110000110000001000111" + "1010011011000101101101010" + "0011010110010001101011011" + "1101011110001001100011110" + "0010000111011101111010101" + "1000001111111011101001000" + "0101010101001110011010010" + "1011111100110010111110101" + "0000000011110011100010110" + "1111111010100100101011011" + "1000001010110001100011111" + "1011101010101000111110100" + "1011101000011100010011010" + "1011101010011010101110001" + "1000001011101110000111001" + "1111111011110010101100111" + }, + /* 52*/ { BARCODE_QRCODE, UNICODE_MODE, 11, 1, -1, -1, { 0, 0, "" }, "Amerika Birleşik Devletleri", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 11 Example 1", "1111111000111100101111111" "1000001001101101001000001" "1011101000001000101011101" @@ -1902,7 +2203,7 @@ static void test_qr_encode(int index, int generate, int debug) { "1000001010110000111010110" "1111111010110101100010101" }, - /* 45*/ { BARCODE_QRCODE, UNICODE_MODE, 11, 1, -1, -1, { 0, 0, "" }, "Biniş kartı #120921039", -1, 0, 25, 25, 0, "AIM ITS/04-023:2022 ECI 11 Example 2 **NOT SAME** different encodation; BWIPP same encodation as Zint but uses mask 101 instead of 111", + /* 53*/ { BARCODE_QRCODE, UNICODE_MODE, 11, 1, -1, -1, { 0, 0, "" }, "Biniş kartı #120921039", -1, 0, 25, 25, 0, "AIM ITS/04-023:2022 ECI 11 Example 2 **NOT SAME** different encodation; BWIPP same encodation as Zint but uses mask 101 instead of 111", "1111111000100110101111111" "1000001011100110001000001" "1011101010000001001011101" @@ -1929,7 +2230,34 @@ static void test_qr_encode(int index, int generate, int debug) { "1000001011100010011100111" "1111111010001001010010011" }, - /* 46*/ { BARCODE_QRCODE, UNICODE_MODE, 12, 1, -1, -1, { 0, 0, "" }, "Kūrybiškumą", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 12 Example 1; BWIPP uses mask 111 instead of 100", + /* 54*/ { BARCODE_QRCODE, UNICODE_MODE, 11, 1, -1, 6 << 8, { 0, 0, "" }, "Biniş kartı #120921039", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 11 Example 2 **NOT SAME** different encodation", + "1111111001110011101111111" + "1000001000011111101000001" + "1011101001110000101011101" + "1011101010110100101011101" + "1011101010101001101011101" + "1000001001100010001000001" + "1111111010101010101111111" + "0000000001001001000000000" + "1100011101101101000011000" + "1100110000100010111011100" + "1000101011011111111011101" + "1010010100110010010100101" + "0100001011100111011000101" + "1100010101101101000011011" + "1010111101100111011011110" + "1000110100101111110111001" + "1001001111101011111111101" + "0000000011100000100011001" + "1111111011001111101011001" + "1000001010110010100010110" + "1011101001010001111110000" + "1011101001101100011011001" + "1011101001100111001000101" + "1000001010101101010011110" + "1111111011011100000111001" + }, + /* 55*/ { BARCODE_QRCODE, UNICODE_MODE, 12, 1, -1, -1, { 0, 0, "" }, "Kūrybiškumą", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 12 Example 1; BWIPP uses mask 111 instead of 100", "111111101111101111111" "100000101010101000001" "101110101000001011101" @@ -1952,7 +2280,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101011110001011" "111111101001101100001" }, - /* 47*/ { BARCODE_QRCODE, UNICODE_MODE, 13, 1, -1, -1, { 0, 0, "" }, "บาร๋แค่ด", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 13 Example 1; BWIPP uses mask 001 instead of 111", + /* 56*/ { BARCODE_QRCODE, UNICODE_MODE, 12, 1, -1, 8 << 8, { 0, 0, "" }, "Kūrybiškumą", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 12 Example 1 **NOT SAME** explicit mask 111", + "111111100101101111111" + "100000101101001000001" + "101110101100101011101" + "101110100101001011101" + "101110101000101011101" + "100000101001101000001" + "111111101010101111111" + "000000001111100000000" + "110100110110001110110" + "001011000111011000001" + "101100111100100010110" + "011011010110010110111" + "011111111000100111001" + "000000001010010101100" + "111111101001101010010" + "100000100110111110110" + "101110100110000100000" + "101110101011001001011" + "101110100001010001001" + "100000101011110001011" + "111111101010110111010" + }, + /* 57*/ { BARCODE_QRCODE, UNICODE_MODE, 13, 1, -1, -1, { 0, 0, "" }, "บาร๋แค่ด", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 13 Example 1; BWIPP uses mask 001 instead of 111", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -1975,7 +2326,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101011100101011" "111111101010000100010" }, - /* 48*/ { BARCODE_QRCODE, UNICODE_MODE, 15, 1, -1, -1, { 0, 0, "" }, "uzņēmums", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 15 Example 1; BWIPP uses mask 011 instead of 111", + /* 58*/ { BARCODE_QRCODE, UNICODE_MODE, 13, 1, -1, 2 << 8, { 0, 0, "" }, "บาร๋แค่ด", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 13 Example 1 **NOT SAME** explicit mask 001", + "111111101111101111111" + "100000101101101000001" + "101110100111001011101" + "101110100101101011101" + "101110101000101011101" + "100000101010001000001" + "111111101010101111111" + "000000001111000000000" + "111001101111111110011" + "001011011010011000100" + "101011111010010010010" + "010001010000101010100" + "000110111010011101011" + "000000001011001101100" + "111111100011100110101" + "100000101011010010010" + "101110100101111001000" + "101110100100000111100" + "101110101010011101111" + "100000101100100010011" + "111111101110011000001" + }, + /* 59*/ { BARCODE_QRCODE, UNICODE_MODE, 15, 1, -1, -1, { 0, 0, "" }, "uzņēmums", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 15 Example 1; BWIPP uses mask 011 instead of 111", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -1998,7 +2372,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101111100101011" "111111101000000101010" }, - /* 49*/ { BARCODE_QRCODE, UNICODE_MODE, 16, 1, -1, -1, { 0, 0, "" }, "ṁórṡáċ", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 16 Example 1; BWIPP uses mask 001 instead of 111", + /* 60*/ { BARCODE_QRCODE, UNICODE_MODE, 15, 1, -1, 4 << 8, { 0, 0, "" }, "uzņēmums", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 15 Example 1 **NOT SAME** explicit mask 011", + "111111101100101111111" + "100000100100101000001" + "101110101010101011101" + "101110101001001011101" + "101110101110001011101" + "100000100000001000001" + "111111101010101111111" + "000000000110000000000" + "111100101010010011101" + "000001011010110001100" + "110010111100100100100" + "010101000000101101010" + "001100111101010001100" + "000000001010011100001" + "111111100100001101100" + "100000100001100110011" + "101110100111010101110" + "101110101000010101110" + "101110101001000001000" + "100000101001101011010" + "111111101001110100100" + }, + /* 61*/ { BARCODE_QRCODE, UNICODE_MODE, 16, 1, -1, -1, { 0, 0, "" }, "ṁórṡáċ", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 16 Example 1; BWIPP uses mask 001 instead of 111", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -2021,7 +2418,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101101100001011" "111111101010010001010" }, - /* 50*/ { BARCODE_QRCODE, UNICODE_MODE, 17, 1, -1, -1, { 0, 0, "" }, "Price: €13.50", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 17 Example 1", + /* 62*/ { BARCODE_QRCODE, UNICODE_MODE, 16, 1, -1, 2 << 8, { 0, 0, "" }, "ṁórṡáċ", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 16 Example 1 **NOT SAME** explicit mask 001", + "111111101111101111111" + "100000101101101000001" + "101110100111001011101" + "101110100101101011101" + "101110101000101011101" + "100000101010001000001" + "111111101010101111111" + "000000001111000000000" + "111001101111111110011" + "010001010010000100101" + "011101111010011010001" + "010101010100100011000" + "100010100110011100111" + "000000001011011101100" + "111111100101110110001" + "100000101111011010000" + "101110100011111000011" + "101110100100000111010" + "101110101010001000011" + "100000101010100110011" + "111111101110001101001" + }, + /* 63*/ { BARCODE_QRCODE, UNICODE_MODE, 17, 1, -1, -1, { 0, 0, "" }, "Price: €13.50", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 17 Example 1", "111111100100101111111" "100000101101001000001" "101110101101101011101" @@ -2044,7 +2464,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101000100101111" "111111101101110110110" }, - /* 51*/ { BARCODE_QRCODE, UNICODE_MODE, 18, 1, -1, -1, { 0, 0, "" }, "Te słowa są głębokie", -1, 0, 25, 25, 0, "AIM ITS/04-023:2022 ECI 18 Example 1; BWIPP uses mask 001 instead of 100", + /* 64*/ { BARCODE_QRCODE, UNICODE_MODE, 18, 1, -1, -1, { 0, 0, "" }, "Te słowa są głębokie", -1, 0, 25, 25, 0, "AIM ITS/04-023:2022 ECI 18 Example 1; BWIPP uses mask 001 instead of 100", "1111111010000111001111111" "1000001010011000001000001" "1011101011001100001011101" @@ -2071,7 +2491,34 @@ static void test_qr_encode(int index, int generate, int debug) { "1000001011110101011011101" "1111111010001100000011111" }, - /* 52*/ { BARCODE_QRCODE, UNICODE_MODE, 20, 1, -1, -1, { 0, 0, "" }, "バーコード", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 20 Example 1; BWIPP uses mask 011 instead of 111", + /* 65*/ { BARCODE_QRCODE, UNICODE_MODE, 18, 1, -1, 2 << 8, { 0, 0, "" }, "Te słowa są głębokie", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 18 Example 1 **NOT SAME** explicit mask 001", + "1111111011110110101111111" + "1000001010010110001000001" + "1011101001000010001011101" + "1011101000011110101011101" + "1011101010011101001011101" + "1000001011101111101000001" + "1111111010101010101111111" + "0000000011000101100000000" + "1110011011011010011110011" + "1111100100001011010001000" + "0100101001101001011101001" + "1011010010111101001101010" + "1100101111100110011000101" + "0111100010100011100100000" + "1101101001110001101001001" + "0010010110000001111100010" + "1101011101011101111111111" + "0000000011101010100011000" + "1111111000101111101010001" + "1000001011111000100010001" + "1011101000100111111110011" + "1011101001100100100110110" + "1011101010010001100000011" + "1000001010000100101010011" + "1111111011111101110010001" + }, + /* 66*/ { BARCODE_QRCODE, UNICODE_MODE, 20, 1, -1, -1, { 0, 0, "" }, "バーコード", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 20 Example 1; BWIPP uses mask 011 instead of 111", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -2094,7 +2541,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101011100110011" "111111101010000101010" }, - /* 53*/ { BARCODE_QRCODE, UNICODE_MODE, 20, 1, -1, -1, { 0, 0, "" }, "東京都", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 20 Example 2; BWIPP uses mask 000 instead of 100", + /* 67*/ { BARCODE_QRCODE, UNICODE_MODE, 20, 1, -1, 4 << 8, { 0, 0, "" }, "バーコード", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 20 Example 1 **NOT SAME** explicit mask 011", + "111111101100101111111" + "100000100100101000001" + "101110101010101011101" + "101110101001001011101" + "101110101110001011101" + "100000100000001000001" + "111111101010101111111" + "000000000110000000000" + "111100101010010011101" + "011010001010101000110" + "000010101000110001011" + "001001010010110011110" + "101001111101000101100" + "000000001110010000001" + "111111100100000111111" + "100000100111110110000" + "101110100111001001011" + "101110101110010100000" + "101110101101000100100" + "100000101101101000010" + "111111101011110100100" + }, + /* 68*/ { BARCODE_QRCODE, UNICODE_MODE, 20, 1, -1, -1, { 0, 0, "" }, "東京都", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 20 Example 2; BWIPP uses mask 000 instead of 100", "111111101111101111111" "100000101010101000001" "101110101000001011101" @@ -2117,7 +2587,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101010011010011" "111111101100111011001" }, - /* 54*/ { BARCODE_QRCODE, UNICODE_MODE, 21, 1, -1, -1, { 0, 0, "" }, "Študentska št. 2198390", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 21 Example 1 **NOT SAME** different encodation", + /* 69*/ { BARCODE_QRCODE, UNICODE_MODE, 20, 1, -1, 1 << 8, { 0, 0, "" }, "東京都", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 20 Example 2 **NOT SAME** explicit mask 000", + "111111100101101111111" + "100000100111001000001" + "101110101101101011101" + "101110100101001011101" + "101110100010101011101" + "100000100000101000001" + "111111101010101111111" + "000000001101100000000" + "111011111111011000100" + "110011010000001100001" + "010110101010100010001" + "111100001110001100110" + "000000101010101010001" + "000000001001010110010" + "111111101101011110000" + "100000101011110111010" + "101110101111011111111" + "101110100110001010100" + "101110101000100001001" + "100000101000001000001" + "111111101110101001011" + }, + /* 70*/ { BARCODE_QRCODE, UNICODE_MODE, 21, 1, -1, -1, { 0, 0, "" }, "Študentska št. 2198390", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 21 Example 1 **NOT SAME** different encodation", "1111111010000110001111111" "1000001010011110101000001" "1011101011001111101011101" @@ -2144,7 +2637,7 @@ static void test_qr_encode(int index, int generate, int debug) { "1000001010010101110010101" "1111111010101100000011011" }, - /* 55*/ { BARCODE_QRCODE, UNICODE_MODE, 22, 1, -1, -1, { 0, 0, "" }, "Россия", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 22 Example 1", + /* 71*/ { BARCODE_QRCODE, UNICODE_MODE, 22, 1, -1, -1, { 0, 0, "" }, "Россия", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 22 Example 1", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -2167,7 +2660,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101001100001011" "111111101100010100110" }, - /* 56*/ { BARCODE_QRCODE, UNICODE_MODE, 22, 1, -1, -1, { 0, 0, "" }, "Монголулс", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 22 Example 2; BWIPP uses mask 000 instead of 100", + /* 72*/ { BARCODE_QRCODE, UNICODE_MODE, 22, 1, -1, -1, { 0, 0, "" }, "Монголулс", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 22 Example 2; BWIPP uses mask 000 instead of 100", "111111101111101111111" "100000101010101000001" "101110101000001011101" @@ -2190,7 +2683,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101001000100111" "111111101000101111101" }, - /* 57*/ { BARCODE_QRCODE, UNICODE_MODE, 23, 1, -1, -1, { 0, 0, "" }, "bœuf", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 23 Example 1; BWIPP uses mask 000 instead of 111", + /* 73*/ { BARCODE_QRCODE, UNICODE_MODE, 22, 1, -1, 1 << 8, { 0, 0, "" }, "Монголулс", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 22 Example 2 **NOT SAME** explicit mask 000", + "111111100101101111111" + "100000100111001000001" + "101110101101101011101" + "101110100101001011101" + "101110100010101011101" + "100000100000101000001" + "111111101010101111111" + "000000001101100000000" + "111011111111011000100" + "011111001100001010100" + "000100111000110000100" + "001001011110010110110" + "100100101110110100101" + "000000001001001110110" + "111111101101000100011" + "100000101001111110111" + "101110101101010100011" + "101110100011001010100" + "101110101000110010001" + "100000101011010110101" + "111111101010111101111" + }, + /* 74*/ { BARCODE_QRCODE, UNICODE_MODE, 23, 1, -1, -1, { 0, 0, "" }, "bœuf", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 23 Example 1; BWIPP uses mask 000 instead of 111", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -2213,7 +2729,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101001100100011" "111111101000010110110" }, - /* 58*/ { BARCODE_QRCODE, UNICODE_MODE, 24, 1, -1, -1, { 0, 0, "" }, "جواز السفر", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 24 Example 1", + /* 75*/ { BARCODE_QRCODE, UNICODE_MODE, 23, 1, -1, 1 << 8, { 0, 0, "" }, "bœuf", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 23 Example 1 ** NOT SAME** explicit mask 000", + "111111100010101111111" + "100000100000101000001" + "101110101010001011101" + "101110100000101011101" + "101110100101101011101" + "100000100111001000001" + "111111101010101111111" + "000000001010000000000" + "111011111010111000100" + "010001001111010100010" + "000011110001011100011" + "110110000101110111010" + "010100110101011100001" + "000000001000001101110" + "111111101010100011111" + "100000101100001100101" + "101110101100101010111" + "101110100101010110000" + "101110101101011111001" + "100000101011110110001" + "111111101001011111111" + }, + /* 76*/ { BARCODE_QRCODE, UNICODE_MODE, 24, 1, -1, -1, { 0, 0, "" }, "جواز السفر", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 24 Example 1", "111111100010101111111" "100000100000101000001" "101110101010001011101" @@ -2236,7 +2775,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101010001000001" "111111101101011101011" }, - /* 59*/ { BARCODE_QRCODE, UNICODE_MODE, 24, 1, -1, -1, { 0, 0, "" }, "المنشأ: المملكة العربية السعودية", -1, 0, 29, 29, 0, "AIM ITS/04-023:2022 ECI 24 Example 2; BWIPP uses mask 000 instead of 100", + /* 77*/ { BARCODE_QRCODE, UNICODE_MODE, 24, 1, -1, -1, { 0, 0, "" }, "المنشأ: المملكة العربية السعودية", -1, 0, 29, 29, 0, "AIM ITS/04-023:2022 ECI 24 Example 2; BWIPP uses mask 000 instead of 100", "11111110111010000111101111111" "10000010111000001100101000001" "10111010101101011000101011101" @@ -2267,7 +2806,38 @@ static void test_qr_encode(int index, int generate, int debug) { "10000010111101000011000110100" "11111110111011010111000011010" }, - /* 60*/ { BARCODE_QRCODE, UNICODE_MODE, 25, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 25 Example 1", + /* 78*/ { BARCODE_QRCODE, UNICODE_MODE, 24, 1, -1, 1 << 8, { 0, 0, "" }, "المنشأ: المملكة العربية السعودية", -1, 0, 29, 29, 1, "AIM ITS/04-023:2022 ECI 24 Example 2 **NOT SAME** explicit mask 000", + "11111110010011001110101111111" + "10000010001110111010001000001" + "10111010111011101110001011101" + "10111010011101110110101011101" + "10111010001000100100101011101" + "10000010010001000111101000001" + "11111110101010101010101111111" + "00000000111011101001100000000" + "11101111101100111011111000100" + "00101000001100110110001100100" + "00101011110001001111010000001" + "10110100100100010101111011011" + "00011010100010000011001111010" + "11010101110111010001001100101" + "11111110100110111000110000011" + "00110001101011111100111010010" + "11101010110100110101001100110" + "01001001111100111010100000110" + "10100010001001011100110011101" + "01000001111100001101100010011" + "10100011101010010011111110101" + "00000000100111001011100010110" + "11111110110110111000101010111" + "10000010111011111111100011010" + "10111010110100111110111111000" + "10111010001100101011101101000" + "10111010100001001000110011001" + "10000010110100001010001111101" + "11111110110010011110001010011" + }, + /* 79*/ { BARCODE_QRCODE, UNICODE_MODE, 25, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 25 Example 1", "111111100010101111111" "100000100000101000001" "101110101010001011101" @@ -2290,7 +2860,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101011110101101" "111111101111011010111" }, - /* 61*/ { BARCODE_QRCODE, UNICODE_MODE, 25, 1, -1, -1, { 0, 0, "" }, "バーコード", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 25 Example 2; BWIPP uses mask 000 instead of 111", + /* 80*/ { BARCODE_QRCODE, UNICODE_MODE, 25, 1, -1, -1, { 0, 0, "" }, "バーコード", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 25 Example 2; BWIPP uses mask 000 instead of 111", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -2313,7 +2883,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101001000001011" "111111101110000101110" }, - /* 62*/ { BARCODE_QRCODE, UNICODE_MODE, 25, 1, -1, -1, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 25 Example 3", + /* 81*/ { BARCODE_QRCODE, UNICODE_MODE, 25, 1, -1, 1 << 8, { 0, 0, "" }, "バーコード", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 25 Example 2 **NOT SAME** explicit mask 000", + "111111100010101111111" + "100000100000101000001" + "101110101010001011101" + "101110100000101011101" + "101110100101101011101" + "100000100111001000001" + "111111101010101111111" + "000000001010000000000" + "111011111010111000100" + "011011010111010011011" + "100000100001010011000" + "110101011111110011010" + "000001100011001000101" + "000000001011001100110" + "111111101000110011111" + "100000101001001011000" + "101110101110101010100" + "101110100000010101000" + "101110101000010101001" + "100000101011010011001" + "111111101111001100111" + }, + /* 82*/ { BARCODE_QRCODE, UNICODE_MODE, 25, 1, -1, -1, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 25 Example 3", "111111100010101111111" "100000100000101000001" "101110101010001011101" @@ -2336,7 +2929,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101101110000101" "111111101001011111011" }, - /* 63*/ { BARCODE_QRCODE, UNICODE_MODE, 26, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 26 Example 1; BWIPP uses mask 000 instead of 111", + /* 83*/ { BARCODE_QRCODE, UNICODE_MODE, 26, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 26 Example 1; BWIPP uses mask 000 instead of 111", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -2359,7 +2952,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101111100101011" "111111101110010100110" }, - /* 64*/ { BARCODE_QRCODE, UNICODE_MODE, 26, 2, -1, -1, { 0, 0, "" }, "バーコード", -1, 0, 25, 25, 0, "AIM ITS/04-023:2022 ECI 26 Example 2; BWIPP uses mask 101 instead of 010", + /* 84*/ { BARCODE_QRCODE, UNICODE_MODE, 26, 1, -1, 1 << 8, { 0, 0, "" }, "条码", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 26 Example 1 **NOT SAME** explicit mask 000", + "111111100010101111111" + "100000100000101000001" + "101110101010001011101" + "101110100000101011101" + "101110100101101011101" + "100000100111001000001" + "111111101010101111111" + "000000001010000000000" + "111011111010111000100" + "010111001111010000111" + "101000110001001010011" + "110011011001110100010" + "011001110101001000001" + "000000001110001101110" + "111111101110100011111" + "100000101110001110111" + "101110101000101001100" + "101110100111010011100" + "101110101011011110001" + "100000101101110111001" + "111111101111011101111" + }, + /* 85*/ { BARCODE_QRCODE, UNICODE_MODE, 26, 2, -1, -1, { 0, 0, "" }, "バーコード", -1, 0, 25, 25, 0, "AIM ITS/04-023:2022 ECI 26 Example 2; BWIPP uses mask 101 instead of 010", "1111111001111101001111111" "1000001001001111001000001" "1011101011101101001011101" @@ -2386,7 +3002,34 @@ static void test_qr_encode(int index, int generate, int debug) { "1000001001110010100111010" "1111111010110001001010111" }, - /* 65*/ { BARCODE_QRCODE, UNICODE_MODE, 26, 2, -1, -1, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 26 Example 3; BWIPP uses mask 111 instead of 001", + /* 86*/ { BARCODE_QRCODE, UNICODE_MODE, 26, 2, -1, 6 << 8, { 0, 0, "" }, "バーコード", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 26 Example 2 **NOT SAME** explicit mask 101", + "1111111001001011101111111" + "1000001010001110001000001" + "1011101011101101001011101" + "1011101010011000001011101" + "1011101000011001001011101" + "1000001001100001001000001" + "1111111010101010101111111" + "0000000011100010000000000" + "1000001011011000111001110" + "0011110001110101100010010" + "0110001111000111000001001" + "1011010011111100010010000" + "1001001100001100011000000" + "1001110000100001010000110" + "1001011111111001010010010" + "1001000101010001000100101" + "1010101001110000111111001" + "0000000010001110100011101" + "1111111001110001101011001" + "1000001000001101100010000" + "1011101000101010111110100" + "1011101000000011001010011" + "1011101000011001110111001" + "1000001000110011100110010" + "1111111010000111111100001" + }, + /* 87*/ { BARCODE_QRCODE, UNICODE_MODE, 26, 2, -1, -1, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 26 Example 3; BWIPP uses mask 111 instead of 001", "111111101011001111111" "100000100001001000001" "101110101100101011101" @@ -2409,7 +3052,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000100010011011011" "111111101011111001101" }, - /* 66*/ { BARCODE_QRCODE, UNICODE_MODE, 27, 2, -1, -1, { 0, 0, "" }, "sn:7QPB4MN", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 27 Example 1 **NOT SAME** different encodation; BWIPP same encodation as example but uses mask 111 instead of 010", + /* 88*/ { BARCODE_QRCODE, UNICODE_MODE, 26, 2, -1, 8 << 8, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 26 Example 3 **NOT SAME** explicit mask 111", + "111111100110001111111" + "100000100110001000001" + "101110100000101011101" + "101110100100001011101" + "101110100000101011101" + "100000101101101000001" + "111111101010101111111" + "000000000001100000000" + "100101101010010100000" + "101100000000001100100" + "110101100100110100010" + "001100001111010000111" + "000000110010110001001" + "000000001001001011100" + "111111100010010100010" + "100000101111110011011" + "101110100001000010110" + "101110101000010100101" + "101110100110111101101" + "100000100101011100011" + "111111101111100101110" + }, + /* 89*/ { BARCODE_QRCODE, UNICODE_MODE, 27, 2, -1, -1, { 0, 0, "" }, "sn:7QPB4MN", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 27 Example 1 **NOT SAME** different encodation; BWIPP same encodation as example but uses mask 111 instead of 010", "111111101010101111111" "100000101111101000001" "101110100110001011101" @@ -2432,7 +3098,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000100011000001010" "111111101000111110000" }, - /* 67*/ { BARCODE_QRCODE, UNICODE_MODE, 28, 1, -1, -1, { 0, 0, "" }, "條碼", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 28 Example 1", + /* 90*/ { BARCODE_QRCODE, UNICODE_MODE, 28, 1, -1, -1, { 0, 0, "" }, "條碼", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 28 Example 1", "111111100010101111111" "100000100000101000001" "101110101010001011101" @@ -2455,7 +3121,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101101110000101" "111111101101011111111" }, - /* 68*/ { BARCODE_QRCODE, UNICODE_MODE, 29, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 29 Example 1", + /* 91*/ { BARCODE_QRCODE, UNICODE_MODE, 29, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 29 Example 1", "111111100010101111111" "100000100000101000001" "101110101010001011101" @@ -2478,7 +3144,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101111110111001" "111111101101011100011" }, - /* 69*/ { BARCODE_QRCODE, UNICODE_MODE, 29, 1, -1, -1, { 0, 0, "" }, "北京", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 29 Example 2", + /* 92*/ { BARCODE_QRCODE, UNICODE_MODE, 29, 1, -1, -1, { 0, 0, "" }, "北京", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 29 Example 2", "111111100100101111111" "100000101001001000001" "101110100100001011101" @@ -2501,7 +3167,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101100000111011" "111111101011010110010" }, - /* 70*/ { BARCODE_QRCODE, UNICODE_MODE, 30, 1, -1, -1, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 30 Example 1; BWIPP uses mask 000 instead of 111", + /* 93*/ { BARCODE_QRCODE, UNICODE_MODE, 30, 1, -1, -1, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 30 Example 1; BWIPP uses mask 000 instead of 111", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -2524,7 +3190,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101001100010011" "111111101110010101110" }, - /* 71*/ { BARCODE_QRCODE, UNICODE_MODE, 30, 1, -1, -1, { 0, 0, "" }, "서울", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 30 Example 2", + /* 94*/ { BARCODE_QRCODE, UNICODE_MODE, 30, 1, -1, 1 << 8, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 30 Example 1 **NOT SAME** explicit mask 000", + "111111100010101111111" + "100000100000101000001" + "101110101010001011101" + "101110100000101011101" + "101110100101101011101" + "100000100111001000001" + "111111101010101111111" + "000000001010000000000" + "111011111010111000100" + "000010000001010001111" + "010101100011001111011" + "000011011011110111110" + "100110110111001101101" + "000000001010001000110" + "111111101100100111111" + "100000101110001011111" + "101110101000101001110" + "101110100111010110100" + "101110101001011000101" + "100000101011110000001" + "111111101111011100111" + }, + /* 95*/ { BARCODE_QRCODE, UNICODE_MODE, 30, 1, -1, -1, { 0, 0, "" }, "서울", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 30 Example 2", "111111100010101111111" "100000100000101000001" "101110101010001011101" @@ -2547,7 +3236,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101001110110101" "111111101011011101011" }, - /* 72*/ { BARCODE_QRCODE, UNICODE_MODE, 31, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 31 Example 1", + /* 96*/ { BARCODE_QRCODE, UNICODE_MODE, 31, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 31 Example 1", "111111100010101111111" "100000100000101000001" "101110101010001011101" @@ -2570,7 +3259,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101011110111001" "111111101101011100011" }, - /* 73*/ { BARCODE_QRCODE, UNICODE_MODE, 31, 1, -1, -1, { 0, 0, "" }, "北京", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 31 Example 2; BWIPP uses mask 011 instead of 010", + /* 97*/ { BARCODE_QRCODE, UNICODE_MODE, 31, 1, -1, -1, { 0, 0, "" }, "北京", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 31 Example 2; BWIPP uses mask 011 instead of 010", "111111100100101111111" "100000101001001000001" "101110100100001011101" @@ -2593,7 +3282,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101000000111011" "111111101011010110010" }, - /* 74*/ { BARCODE_QRCODE, UNICODE_MODE, 31, 1, -1, -1, { 0, 0, "" }, "條碼", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 31 Example 3", + /* 98*/ { BARCODE_QRCODE, UNICODE_MODE, 31, 1, -1, 4 << 8, { 0, 0, "" }, "北京", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 31 Example 2 **NOT SAME** explicit mask 011", + "111111101100101111111" + "100000100100101000001" + "101110101010101011101" + "101110101001001011101" + "101110101110001011101" + "100000100000001000001" + "111111101010101111111" + "000000000110000000000" + "111100101010010011101" + "001001000110100100000" + "000110110000111110111" + "010101010000110000010" + "011011100001010011100" + "000000001100010001101" + "111111100010011011100" + "100000100001111100111" + "101110100011001000010" + "101110101110010110100" + "101110101001010111000" + "100000101101101010110" + "111111101101100000100" + }, + /* 99*/ { BARCODE_QRCODE, UNICODE_MODE, 31, 1, -1, -1, { 0, 0, "" }, "條碼", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 31 Example 3", "111111100010101111111" "100000100000101000001" "101110101010001011101" @@ -2616,7 +3328,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101001110110001" "111111101111011110111" }, - /* 75*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 32 Example 1", + /*100*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 32 Example 1", "111111100100101111111" "100000101001001000001" "101110100100001011101" @@ -2639,7 +3351,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101100000110111" "111111101111010010010" }, - /* 76*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, -1, { 0, 0, "" }, "北京", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 32 Example 2; BWIPP uses mask 011 instead of 111", + /*101*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, -1, { 0, 0, "" }, "北京", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 32 Example 2; BWIPP uses mask 011 instead of 111", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -2662,7 +3374,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101101100100111" "111111101000010001010" }, - /* 77*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, -1, { 0, 0, "" }, "條碼", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 32 Example 3; BWIPP uses mask 011 instead of 001", + /*102*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, 4 << 8, { 0, 0, "" }, "北京", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 32 Example 2 **NOT SAME** explicit mask 011", + "111111101100101111111" + "100000100100101000001" + "101110101010101011101" + "101110101001001011101" + "101110101110001011101" + "100000100000001000001" + "111111101010101111111" + "000000000110000000000" + "111100101010010011101" + "111100000110100100000" + "110011100100111110111" + "110110001100110000010" + "101011111001010011100" + "000000001100010001101" + "111111100110011011100" + "100000100111111100100" + "101110100101001000001" + "101110101010010110111" + "101110101101010111000" + "100000101011101010110" + "111111101001100000100" + }, + /*103*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, -1, { 0, 0, "" }, "條碼", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 32 Example 3; BWIPP uses mask 011 instead of 001", "111111101111101111111" "100000101101101000001" "101110100111001011101" @@ -2685,7 +3420,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101010100011011" "111111101110001011101" }, - /* 78*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, -1, { 0, 0, "" }, "པེ་ཅིང།", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 32 Example 4", + /*104*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, 4 << 8, { 0, 0, "" }, "條碼", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 32 Example 3 **NOT SAME** explicit mask 011", + "111111101100101111111" + "100000100100101000001" + "101110101010101011101" + "101110101001001011101" + "101110101110001011101" + "100000100000001000001" + "111111101010101111111" + "000000000110000000000" + "111100101010010011101" + "000000001110100100000" + "010010100010111110011" + "111001000010110001010" + "001100101111010011000" + "000000001100010000001" + "111111100110011010100" + "100000100101111101000" + "101110100011001001001" + "101110101010010110111" + "101110101111010101000" + "100000101011101010010" + "111111101011100110000" + }, + /*105*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, -1, { 0, 0, "" }, "པེ་ཅིང།", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 32 Example 4", "1111111011110110001111111" "1000001000011010101000001" "1011101010110101101011101" @@ -2712,7 +3470,7 @@ static void test_qr_encode(int index, int generate, int debug) { "1000001010111111111010111" "1111111010011101100000011" }, - /* 79*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, -1, { 0, 0, "" }, "バーコード", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 32 Example 5; BWIPP uses mask 011 instead of 111", + /*106*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, -1, { 0, 0, "" }, "バーコード", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 32 Example 5; BWIPP uses mask 011 instead of 111", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -2735,7 +3493,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101001010101111" "111111101110010110110" }, - /* 80*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, -1, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 32 Example 6; BWIPP uses mask 011 instead of 111", + /*107*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, 4 << 8, { 0, 0, "" }, "バーコード", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 32 Example 5 **NOT SAME** explicit mask 011", + "111111101100101111111" + "100000100100101000001" + "101110101010101011101" + "101110101001001011101" + "101110101110001011101" + "100000100000001000001" + "111111101010101111111" + "000000000110000000000" + "111100101010010011101" + "000110011100101010001" + "011100110110100001100" + "001000010110111101010" + "110000101011010111100" + "000000001101011100101" + "111111100100011111000" + "100000100010100110100" + "101110100001001011001" + "101110101101011010111" + "101110101100001100000" + "100000101111011011110" + "111111101111100111000" + }, + /*108*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, -1, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 32 Example 6; BWIPP uses mask 011 instead of 111", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -2758,7 +3539,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101110100001011" "111111101101101010110" }, - /* 81*/ { BARCODE_QRCODE, UNICODE_MODE, 33, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 33 Example 1; BWIPP uses mask 111 instead of 010", + /*109*/ { BARCODE_QRCODE, UNICODE_MODE, 32, 1, -1, 4 << 8, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 32 Example 6 **NOT SAME** explicit mask 011", + "111111101100101111111" + "100000100100101000001" + "101110101010101011101" + "101110101001001011101" + "101110101111001011101" + "100000100000001000001" + "111111101010101111111" + "000000000111000000000" + "111100101010010011101" + "010111000011011100000" + "010010110011000101010" + "110000000001100100010" + "100110111010110101000" + "000000001001101111001" + "111111100111001011100" + "100000100011001100100" + "101110100001111011001" + "101110101111011111111" + "101110101010000101000" + "100000101000101111010" + "111111101100011011000" + }, + /*110*/ { BARCODE_QRCODE, UNICODE_MODE, 33, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 33 Example 1; BWIPP uses mask 111 instead of 010", "111111100100101111111" "100000101001001000001" "101110100100001011101" @@ -2781,7 +3585,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101010000010111" "111111101101010001110" }, - /* 82*/ { BARCODE_QRCODE, UNICODE_MODE, 33, 1, -1, -1, { 0, 0, "" }, "バーコード", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 33 Example 2", + /*111*/ { BARCODE_QRCODE, UNICODE_MODE, 33, 1, -1, 8 << 8, { 0, 0, "" }, "条码", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 33 Example 1 **NOT SAME** explicit mask 111", + "111111100010101111111" + "100000101010101000001" + "101110101011001011101" + "101110100000101011101" + "101110101111101011101" + "100000101110001000001" + "111111101010101111111" + "000000001000000000000" + "110100110011101110110" + "000011010101010100010" + "011101100001001110001" + "001101011100111110011" + "000001100001011101101" + "000000001000011110000" + "111111101111101011010" + "100000100000001100000" + "101110100010111001011" + "101110101010011100010" + "101110100001011000101" + "100000101001100001011" + "111111101010010110110" + }, + /*112*/ { BARCODE_QRCODE, UNICODE_MODE, 33, 1, -1, -1, { 0, 0, "" }, "バーコード", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 33 Example 2", "111111100010101111111" "100000100000101000001" "101110101010001011101" @@ -2804,7 +3631,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101100111010101" "111111101110111010111" }, - /* 83*/ { BARCODE_QRCODE, UNICODE_MODE, 33, 1, -1, -1, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 33 Example 3; BWIPP uses mask 000 instead of 111", + /*113*/ { BARCODE_QRCODE, UNICODE_MODE, 33, 1, -1, -1, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 33 Example 3; BWIPP uses mask 000 instead of 111", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -2827,7 +3654,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101111100110011" "111111101000010101110" }, - /* 84*/ { BARCODE_QRCODE, UNICODE_MODE, 34, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 34 Example 1", + /*114*/ { BARCODE_QRCODE, UNICODE_MODE, 33, 1, -1, 1 << 8, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 33 Example 3 **NOT SAME** explicit mask 000", + "111111100010101111111" + "100000100000101000001" + "101110101010001011101" + "101110100000101011101" + "101110100101101011101" + "100000100111001000001" + "111111101010101111111" + "000000001010000000000" + "111011111010111000100" + "111111011101010101011" + "000110110011001111111" + "100100000111110010010" + "001101111001001000101" + "000000001100001101110" + "111111101000100101011" + "100000101110001000100" + "101110101000101100101" + "101110100101010010011" + "101110101101011101101" + "100000101101110100001" + "111111101001011100111" + }, + /*115*/ { BARCODE_QRCODE, UNICODE_MODE, 34, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 34 Example 1", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -2850,7 +3700,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101011100100011" "111111101110000110010" }, - /* 85*/ { BARCODE_QRCODE, UNICODE_MODE, 34, 1, -1, -1, { 0, 0, "" }, "バーコード", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 34 Example 2", + /*116*/ { BARCODE_QRCODE, UNICODE_MODE, 34, 1, -1, -1, { 0, 0, "" }, "バーコード", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 34 Example 2", "1111111000100010001111111" "1000001001000100101000001" "1011101010010011001011101" @@ -2877,7 +3727,7 @@ static void test_qr_encode(int index, int generate, int debug) { "1000001010110001010101001" "1111111010001000110010111" }, - /* 86*/ { BARCODE_QRCODE, UNICODE_MODE, 34, 1, -1, -1, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 34 Example 3", + /*117*/ { BARCODE_QRCODE, UNICODE_MODE, 34, 1, -1, -1, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 34 Example 3", "111111100010101111111" "100000100000101000001" "101110101010001011101" @@ -2900,7 +3750,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101101010000101" "111111101010101010111" }, - /* 87*/ { BARCODE_QRCODE, UNICODE_MODE, 35, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 35 Example 1", + /*118*/ { BARCODE_QRCODE, UNICODE_MODE, 35, 1, -1, -1, { 0, 0, "" }, "条码", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 35 Example 1", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -2923,7 +3773,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101011100111011" "111111101110000011110" }, - /* 88*/ { BARCODE_QRCODE, UNICODE_MODE, 35, 1, -1, -1, { 0, 0, "" }, "バーコード", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 35 Example 2", + /*119*/ { BARCODE_QRCODE, UNICODE_MODE, 35, 1, -1, -1, { 0, 0, "" }, "バーコード", -1, 0, 25, 25, 1, "AIM ITS/04-023:2022 ECI 35 Example 2", "1111111000100110101111111" "1000001001000111001000001" "1011101010010110101011101" @@ -2950,7 +3800,7 @@ static void test_qr_encode(int index, int generate, int debug) { "1000001010110001010010101" "1111111011001000101010111" }, - /* 89*/ { BARCODE_QRCODE, UNICODE_MODE, 35, 1, -1, -1, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 35 Example 3; BWIPP uses mask 011 instead of 111", + /*120*/ { BARCODE_QRCODE, UNICODE_MODE, 35, 1, -1, -1, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 35 Example 3; BWIPP uses mask 011 instead of 111", "111111100010101111111" "100000101010101000001" "101110101011001011101" @@ -2973,7 +3823,30 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101000111111011" "111111101101000011110" }, - /* 90*/ { BARCODE_QRCODE, UNICODE_MODE, 170, 1, -1, -1, { 0, 0, "" }, "sn:7QPB4MN", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 170 Example 1 **NOT SAME** different encodation; BWIPP same encodation as example but uses mask 011 instead of 111", + /*121*/ { BARCODE_QRCODE, UNICODE_MODE, 35, 1, -1, 4 << 8, { 0, 0, "" }, "바코드", -1, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 35 Example 3 **NOT SAME** explicit mask 011", + "111111101100101111111" + "100000100100101000001" + "101110101010101011101" + "101110101001001011101" + "101110101111001011101" + "100000100000001000001" + "111111101010101111111" + "000000000111000000000" + "111100101010010011101" + "101010001000100010100" + "010000100011001110010" + "000001011010010011010" + "110101101000100010100" + "000000001011001001101" + "111111100110010111100" + "100000100000100001011" + "101110100111001101001" + "101110101010001010011" + "101110101001110100100" + "100000101110110001010" + "111111101100110010000" + }, + /*122*/ { BARCODE_QRCODE, UNICODE_MODE, 170, 1, -1, -1, { 0, 0, "" }, "sn:7QPB4MN", -1, 0, 21, 21, 0, "AIM ITS/04-023:2022 ECI 170 Example 1 **NOT SAME** different encodation; BWIPP same encodation as example but uses mask 011 instead of 111", "111111101100101111111" "100000100100101000001" "101110101010101011101" @@ -2996,7 +3869,7 @@ static void test_qr_encode(int index, int generate, int debug) { "100000101000110010110" "111111101011100010100" }, - /* 91*/ { BARCODE_QRCODE, DATA_MODE, 899, 1, -1, -1, { 0, 0, "" }, "\000\001\002\133\134\135\375\376\377", 9, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 899 Example 1", + /*123*/ { BARCODE_QRCODE, DATA_MODE, 899, 1, -1, -1, { 0, 0, "" }, "\000\001\002\133\134\135\375\376\377", 9, 0, 21, 21, 1, "AIM ITS/04-023:2022 ECI 899 Example 1", "111111101111101111111" "100000101101101000001" "101110100111001011101" @@ -3073,7 +3946,7 @@ static void test_qr_encode(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, data[i].option_3, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_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, data[i].expected); @@ -3101,6 +3974,347 @@ static void test_qr_encode(int index, int generate, int debug) { testFinish(); } +static void test_qr_encode_segs(int index, int generate, int debug) { + + struct item { + int symbology; + int input_mode; + int option_1; + int option_2; + int option_3; + struct zint_structapp structapp; + struct zint_seg segs[3]; + int ret; + + int expected_rows; + int expected_width; + int bwipp_cmp; + char *comment; + char *expected; + }; + struct item data[] = { + /* 0*/ { BARCODE_QRCODE, UNICODE_MODE, 4, -1, 8 << 8, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 7 }, { TU(""), 0, 0 } }, 0, 21, 21, 1, "Standard example", + "111111101101001111111" + "100000101100101000001" + "101110100010101011101" + "101110101011101011101" + "101110101011101011101" + "100000101110101000001" + "111111101010101111111" + "000000000100000000000" + "000100100011000111011" + "001000000000000001001" + "111100111101110000101" + "010111011010000001010" + "111110101101111011011" + "000000001100110110011" + "111111100001100101101" + "100000100110101111000" + "101110100101001110111" + "101110101100010100011" + "101110100110100011101" + "100000100100111101100" + "111111100010000110010" + }, + /* 1*/ { BARCODE_QRCODE, UNICODE_MODE, 4, -1, 8 << 8, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 21, 21, 1, "Standard example auto-ECI", + "111111101101001111111" + "100000101100101000001" + "101110100010101011101" + "101110101011101011101" + "101110101011101011101" + "100000101110101000001" + "111111101010101111111" + "000000000100000000000" + "000100100011000111011" + "001000000000000001001" + "111100111101110000101" + "010111011010000001010" + "111110101101111011011" + "000000001100110110011" + "111111100001100101101" + "100000100110101111000" + "101110100101001110111" + "101110101100010100011" + "101110100110100011101" + "100000100100111101100" + "111111100010000110010" + }, + /* 2*/ { BARCODE_QRCODE, UNICODE_MODE, 4, -1, 8 << 8, { 0, 0, "" }, { { TU("Ж"), -1, 7 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, 0, 21, 21, 1, "Standard example inverted", + "111111101111101111111" + "100000101011001000001" + "101110100000101011101" + "101110101110101011101" + "101110101101101011101" + "100000101010001000001" + "111111101010101111111" + "000000000011000000000" + "000100100000000111011" + "001100000111100101100" + "110010100000011001011" + "011000000001100101011" + "101000101011111010001" + "000000001001111100000" + "111111100101010110010" + "100000100110100011001" + "101110100111101010101" + "101110101000001000011" + "101110100001001011001" + "100000100100110110011" + "111111100001000011110" + }, + /* 3*/ { BARCODE_QRCODE, UNICODE_MODE, 4, -1, 8 << 8, { 0, 0, "" }, { { TU("Ж"), -1, 0 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 21, 21, 1, "Standard example inverted auto-ECI", + "111111101111101111111" + "100000101011001000001" + "101110100000101011101" + "101110101110101011101" + "101110101101101011101" + "100000101010001000001" + "111111101010101111111" + "000000000011000000000" + "000100100000000111011" + "001100000111100101100" + "110010100000011001011" + "011000000001100101011" + "101000101011111010001" + "000000001001111100000" + "111111100101010110010" + "100000100110100011001" + "101110100111101010101" + "101110101000001000011" + "101110100001001011001" + "100000100100110110011" + "111111100001000011110" + }, + /* 4*/ { BARCODE_QRCODE, UNICODE_MODE, -1, -1, -1, { 0, 0, "" }, { { TU("product:Google Pixel 4a - 128 GB of Storage - Black;price:$439.97"), -1, 3 }, { TU("品名:Google 谷歌 Pixel 4a -128 GB的存储空间-黑色;零售价:¥3149.79"), -1, 29 }, { TU("Produkt:Google Pixel 4a - 128 GB Speicher - Schwarz;Preis:444,90 €"), -1, 17 } }, 0, 53, 53, 0, "AIM ITS/04-023:2022 Annex A example; BWIPP different encodation", + "11111110010010001110011110000111001001011110001111111" + "10000010100101111001000000001000010110100111001000001" + "10111010010101001110001011100010000010111101001011101" + "10111010111101111000000010111011000100010010101011101" + "10111010001100111110110111111110011010010110001011101" + "10000010111000011101010110001111000011110110001000001" + "11111110101010101010101010101010101010101010101111111" + "00000000011101001000110110001101000000001111000000000" + "11111011100100000100000011111000011010101000010101010" + "11100000100111010011110110011110110010011011001001101" + "00110110000101000010110100111001100110000111110110101" + "10100100101111110111100110011000111111000010010011011" + "00001110111010001100110011100001100110011001110111000" + "00100100001010101011010001000110110110111010011011000" + "00111011011011100011010010001010100111110101001110110" + "10111001010100100110000111101101100011010010100101001" + "01000010001111110011000000001101011011010000011110001" + "00100100001100001110010100101100010000011010000001011" + "10001110001010011011010111100011001011110010100110110" + "01100001001101001110011111010010010001101000001011101" + "11110011100011000010011011100011110100010001100101000" + "00010101000010110010010000100000011000011000001111010" + "10100110010110000101011010110000000101100100011011110" + "01000000010101000000110101111100000111011010110101011" + "01101111111100000100010111111010011101110000111111001" + "10001000101101010011110010001100111001010100100011110" + "10011010111011100010110110101000001010000111101011010" + "10011000100111010001101010001111011100001111100011101" + "10111111111101111010000011111001101010111110111110100" + "01001100101111011100010101001100111100101001111101000" + "00001111111111100011101010101011010101110100010000101" + "10101000110010100110011011101011010011001011010110000" + "10100110010001110011001111010101001010100001101011111" + "10010101111110001110010011100000111001110011000011000" + "01111010110001011001011000001011001011100011110110111" + "01110001010100101000001010111110011001001000111011101" + "10011110000101101010101111100001110010111000000101010" + "01010001100011010110110100100100100010001011100101000" + "11011011001100001101010010111110010011000110010001100" + "01000001001101000000000011101101100111010010010111000" + "10100111010100000100010110011000001111110100000000001" + "10100100110001010011100111110000110000011011010010110" + "11011111010110100110110001001001010110110111011111000" + "01100000111011110111101110110011010110001100001101101" + "00010010010100111000010011111011110000011111111111010" + "00000000101011011000011010001100101010001011100010010" + "11111110110011000011001110101000111011000001101011100" + "10000010001011100110011110001011000101010011100010111" + "10111010100100010011001011111110101110111100111110100" + "10111010101000001110010011011100110000001010000101010" + "10111010100110111101011111100111011111010000111111010" + "10000010110010101000001000110100010100101010011010001" + "11111110100110011010100111101001110010111100100111000" + }, + /* 5*/ { BARCODE_QRCODE, DATA_MODE, 2, -1, 3 << 8, { 0, 0, "" }, { { TU("\266"), 1, 0 }, { TU("\266"), 1, 7 }, { TU("\266"), 1, 0 } }, 0, 21, 21, 1, "Standard example + extra seg, data mode", + "111111100111001111111" + "100000100010001000001" + "101110101010001011101" + "101110101101101011101" + "101110101000101011101" + "100000101101001000001" + "111111101010101111111" + "000000001100000000000" + "101111100001001111100" + "011001000111100100111" + "100010111100110100110" + "001100001101101101101" + "100110100000111001010" + "000000001010110011111" + "111111100101001100101" + "100000101000000100110" + "101110101101000100100" + "101110101001111010100" + "101110101110101001100" + "100000100101111110000" + "111111101110100001010" + }, + /* 6*/ { BARCODE_QRCODE, UNICODE_MODE, 2, -1, 3 << 8, { 0, 0, "" }, { { TU("éé"), -1, 0 }, { TU("กขฯ"), -1, 0 }, { TU("βββ"), -1, 0 } }, ZINT_WARN_USES_ECI, 21, 21, 1, "Auto-ECI", + "111111100001001111111" + "100000100111001000001" + "101110101011101011101" + "101110101000101011101" + "101110101100101011101" + "100000101100101000001" + "111111101010101111111" + "000000001100000000000" + "101111100110101111100" + "111100011010011100001" + "011000100111011011111" + "101011010000010111110" + "100100101010111101001" + "000000001000000110101" + "111111100011000110111" + "100000101100001001001" + "101110101010110101100" + "101110101000010111100" + "101110101011000110100" + "100000100101000010100" + "111111101100100100110" + }, + /* 7*/ { BARCODE_QRCODE, UNICODE_MODE, -1, -1, -1, { 2, 3, "123" }, { { TU("éé"), -1, 23 }, { TU("กขฯ"), -1, 13 }, { TU("βββ"), -1, 9 } }, 0, 25, 25, 1, "Structured Append", + "1111111010110011001111111" + "1000001010010000001000001" + "1011101011111011101011101" + "1011101010001101001011101" + "1011101010110111001011101" + "1000001001010010001000001" + "1111111010101010101111111" + "0000000011110000000000000" + "0110101101111000101011111" + "0001100000010100111110001" + "1101111111001011001100111" + "0010000101000110000101000" + "0000011011100010100010101" + "0011010001011111011101001" + "1000101100001000101010011" + "0100100111100101111000101" + "1000011110011100111110000" + "0000000010110000100011101" + "1111111011001110101011111" + "1000001001010111100010111" + "1011101010111111111110001" + "1011101001011111001001100" + "1011101011110010101101101" + "1000001010100000101100001" + "1111111000101101110011001" + }, + }; + int data_size = ARRAY_SIZE(data); + int i, j, seg_count, ret; + struct zint_symbol *symbol; + + char escaped[4096]; + 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 + + testStart("test_qr_encode_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + if ((debug & ZINT_DEBUG_TEST_PRINT) && !(debug & ZINT_DEBUG_TEST_LESS_NOISY)) printf("i:%d\n", i); + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, + data[i].option_1, data[i].option_2, data[i].option_3, -1 /*output_options*/, + NULL, 0, debug); + if (data[i].structapp.count) { + symbol->structapp = data[i].structapp; + } + for (j = 0, seg_count = 0; j < 3 && data[i].segs[j].length; j++, seg_count++); + + ret = ZBarcode_Encode_Segs(symbol, data[i].segs, seg_count); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode_Segs ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + char escaped1[4096]; + char escaped2[4096]; + int length = data[i].segs[0].length == -1 ? (int) ustrlen(data[i].segs[0].source) : data[i].segs[0].length; + int length1 = data[i].segs[1].length == -1 ? (int) ustrlen(data[i].segs[1].source) : data[i].segs[1].length; + int length2 = data[i].segs[2].length == -1 ? (int) ustrlen(data[i].segs[2].source) : data[i].segs[2].length; + printf(" /*%3d*/ { %s, %s, %d, %d, %s, { %d, %d, \"%s\" }, { { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d } }, %s, %d, %d, %d, \"%s\",\n", + i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), + data[i].option_1, data[i].option_2, testUtilOption3Name(data[i].option_3), + data[i].structapp.index, data[i].structapp.count, data[i].structapp.id, + testUtilEscape((const char *) data[i].segs[0].source, length, escaped, sizeof(escaped)), data[i].segs[0].length, data[i].segs[0].eci, + testUtilEscape((const char *) data[i].segs[1].source, length1, escaped1, sizeof(escaped1)), data[i].segs[1].length, data[i].segs[1].eci, + testUtilEscape((const char *) data[i].segs[2].source, length2, escaped2, sizeof(escaped2)), data[i].segs[2].length, data[i].segs[2].eci, + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].bwipp_cmp, data[i].comment); + testUtilModulesPrint(symbol, " ", "\n"); + printf(" },\n"); + } else { + if (ret < ZINT_ERROR) { + int width, row; + 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); + + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d\n", i, ret, width, row); + + if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_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 { + ret = testUtilBwippSegs(i, symbol, data[i].option_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); + 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, data[i].expected); + } + } + if (do_zxingcpp) { + if ((symbol->input_mode & 0x07) == DATA_MODE) { + if (debug & ZINT_DEBUG_TEST_PRINT) { + printf("i:%d multiple segments in DATA_MODE not currently supported for ZXing-C++ testing (%s)\n", + i, testUtilBarcodeName(symbol->symbology)); + } + } else { + int length = data[i].segs[0].length == -1 ? (int) ustrlen(data[i].segs[0].source) : data[i].segs[0].length; + if (testUtilCanZXingCPP(i, symbol, (const char *) data[i].segs[0].source, length, debug)) { + int cmp_len, ret_len; + char modules_dump[32768]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilZXingCPP(i, symbol, (const char *) data[i].segs[0].source, 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 = testUtilZXingCPPCmpSegs(symbol, cmp_msg, cmp_buf, cmp_len, data[i].segs, seg_count, + NULL /*primary*/, escaped, &ret_len); + assert_zero(ret, "i:%d %s testUtilZXingCPPCmpSegs %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); + } + + testFinish(); +} + #include #define TEST_PERF_ITERATIONS 1000 @@ -3187,9 +4401,9 @@ static void test_qr_perf(int index, int debug) { static void test_microqr_options(int index, int debug) { struct item { - char *data; int option_1; int option_2; + char *data; int ret_encode; int ret_vector; int expected_size; @@ -3197,58 +4411,69 @@ static void test_microqr_options(int index, int debug) { }; // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { "12345", -1, -1, 0, 0, 11, -1 }, // ECC auto-set to 1 (L), version auto-set to 1 - /* 1*/ { "12345", 1, -1, 0, 0, 11, 0 }, // ECC 1 (L), version auto-set to 1 - /* 2*/ { "12345", 2, -1, 0, 0, 13, 1 }, // ECC 2 (M), version auto-set to 2 - /* 3*/ { "12345", 3, -1, 0, 0, 17, 1 }, // ECC 3 (Q), version auto-set to 3 - /* 4*/ { "12345", 4, -1, ZINT_ERROR_INVALID_OPTION, -1, 0, -1 }, - /* 5*/ { "12345", -1, 1, 0, 0, 11, -1 }, // ECC auto-set to 1, version 1 - /* 6*/ { "12345", -1, 2, 0, 0, 13, 1 }, // ECC auto-set to 2, version 2 - /* 7*/ { "12345", 2, 2, 0, 0, 13, 0 }, - /* 8*/ { "12345", -1, 3, 0, 0, 15, 1 }, // ECC auto-set to 2, version 3 - /* 9*/ { "12345", 2, 3, 0, 0, 15, 0 }, - /* 10*/ { "12345", 1, 3, 0, 0, 15, 1 }, - /* 11*/ { "12345", -1, 4, 0, 0, 17, 1 }, // ECC auto-set to 3, version 4 - /* 12*/ { "12345", 3, 4, 0, 0, 17, 0 }, // ECC auto-set to 3, version 4 - /* 13*/ { "12345", 2, 4, 0, 0, 17, 1 }, - /* 14*/ { "12345", -1, 5, 0, 0, 11, -1 }, // Size > 4 ignored - /* 15*/ { "12345", 1, 5, 0, 0, 11, 0 }, // Ignored also if ECC given - /* 16*/ { "12345", 1, 1, 0, 0, 11, 0 }, // ECC 1, version 1 - /* 17*/ { "12345", 1, 2, 0, 0, 13, 1 }, // ECC 1, version 2 - /* 18*/ { "12345", 1, 3, 0, 0, 15, 1 }, // ECC 1, version 3 - /* 19*/ { "12345", 1, 4, 0, 0, 17, 1 }, // ECC 1, version 4 - /* 20*/ { "12345", 2, 1, ZINT_ERROR_INVALID_OPTION, -1, 0, -1 }, - /* 21*/ { "12345", 2, 2, 0, -1, 13, -1 }, // ECC 2, version 2 - /* 22*/ { "12345", 2, 3, 0, -1, 15, 1 }, // ECC 2, version 3 - /* 23*/ { "12345", 2, 4, 0, -1, 17, 1 }, // ECC 2, version 4 - /* 24*/ { "12345", 3, 1, ZINT_ERROR_INVALID_OPTION, -1, 0, -1 }, - /* 25*/ { "12345", 3, 2, ZINT_ERROR_INVALID_OPTION, -1, 0, -1 }, - /* 26*/ { "12345", 3, 3, ZINT_ERROR_INVALID_OPTION, -1, 0, -1 }, - /* 27*/ { "12345", 3, 4, 0, -1, 17, -1 }, // ECC 3, version 4 - /* 28*/ { "12345", 4, 4, ZINT_ERROR_INVALID_OPTION, -1, 0, -1 }, - /* 29*/ { "12345", 5, -1, 0, 0, 11, -1 }, // ECC > 4 ignored - /* 30*/ { "12345", 5, 1, 0, 0, 11, 0 }, // Ignored also if size given - /* 31*/ { "123456", 1, 1, ZINT_ERROR_TOO_LONG, -1, 0, -1 }, - /* 32*/ { "123456", 1, -1, 0, 0, 13, -1 }, // ECC 1 (L), version auto-set to 2 - /* 33*/ { "123456", 1, 2, 0, 0, 13, 0 }, - /* 34*/ { "ABCDEF", 2, 2, ZINT_ERROR_TOO_LONG, -1, 0, -1 }, - /* 35*/ { "ABCDEF", 1, -1, 0, 0, 13, -1 }, // ECC 1 (L), version auto-set to 2 - /* 36*/ { "ABCDEF", 1, 2, 0, 0, 13, 0 }, - /* 37*/ { "ABCDE", 2, -1, 0, 0, 13, -1 }, // ECC 2 (M), version auto-set to 2 - /* 38*/ { "ABCDE", 2, 2, 0, 0, 13, 0 }, // ECC 2 (M), version auto-set to 2 - /* 39*/ { "ABCDEABCDEABCD", 1, -1, 0, 0, 15, -1 }, // 14 alphanumerics, ECC 1, version auto-set to 3 - /* 40*/ { "ABCDEABCDEABCD", 1, 3, 0, 0, 15, 0 }, - /* 41*/ { "ABCDEABCDEABCD", 2, 3, ZINT_ERROR_TOO_LONG, -1, 0, -1 }, - /* 42*/ { "ABCDEABCDEA", 2, 3, 0, 0, 15, -1 }, // 11 alphanumerics, ECC 2, version 3 - /* 43*/ { "ABCDEFGHIJABCDEFGHIJA", 1, -1, 0, 0, 17, -1 }, // 21 alphanumerics, ECC 1, version auto-set to 4 - /* 44*/ { "ABCDEFGHIJABCDEFGHIJA", 1, 4, 0, 0, 17, 0 }, - /* 45*/ { "ABCDEFGHIJABCDEFGHIJA", 2, 4, ZINT_ERROR_TOO_LONG, -1, 0, -1 }, - /* 46*/ { "ABCDEFGHIJABCDEFGH", 2, 4, 0, 0, 17, -1 }, // 18 alphanumerics, ECC 2, version 4 - /* 47*/ { "ABCDEFGHIJABCDEFGH", 3, 4, ZINT_ERROR_TOO_LONG, -1, 0, -1 }, - /* 48*/ { "ABCDEFGHIJABC", 3, 4, 0, 0, 17, -1 }, // 13 alphanumerics, ECC 3 (Q), version 4 - /* 49*/ { "123456789012345678901234567890123456", -1, -1, ZINT_ERROR_TOO_LONG, -1, 0, -1 }, // 35 absolute max - /* 50*/ { "貫貫貫貫貫", -1, -1, 0, 0, 17, -1 }, // 5 Kanji max - /* 51*/ { "貫貫貫貫貫貫", -1, -1, ZINT_ERROR_TOO_LONG, -1, 0, -1 }, + /* 0*/ { -1, -1, "12345", 0, 0, 11, -1 }, // ECC auto-set to 1 (L), version auto-set to 1 + /* 1*/ { 1, -1, "12345", 0, 0, 11, 0 }, // ECC 1 (L), version auto-set to 1 + /* 2*/ { 2, -1, "12345", 0, 0, 13, 1 }, // ECC 2 (M), version auto-set to 2 + /* 3*/ { 3, -1, "12345", 0, 0, 17, 1 }, // ECC 3 (Q), version auto-set to 3 + /* 4*/ { 4, -1, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, -1 }, + /* 5*/ { -1, 1, "12345", 0, 0, 11, -1 }, // ECC auto-set to 1, version 1 + /* 6*/ { -1, 2, "12345", 0, 0, 13, 1 }, // ECC auto-set to 2, version 2 + /* 7*/ { 2, 2, "12345", 0, 0, 13, 0 }, + /* 8*/ { -1, 3, "12345", 0, 0, 15, 1 }, // ECC auto-set to 2, version 3 + /* 9*/ { 2, 3, "12345", 0, 0, 15, 0 }, + /* 10*/ { 1, 3, "12345", 0, 0, 15, 1 }, + /* 11*/ { -1, 4, "12345", 0, 0, 17, 1 }, // ECC auto-set to 3, version 4 + /* 12*/ { 3, 4, "12345", 0, 0, 17, 0 }, // ECC auto-set to 3, version 4 + /* 13*/ { 2, 4, "12345", 0, 0, 17, 1 }, + /* 14*/ { -1, 5, "12345", 0, 0, 11, -1 }, // Size > 4 ignored + /* 15*/ { 1, 5, "12345", 0, 0, 11, 0 }, // Ignored also if ECC given + /* 16*/ { 1, 1, "12345", 0, 0, 11, 0 }, // ECC 1, version 1 + /* 17*/ { 1, 2, "12345", 0, 0, 13, 1 }, // ECC 1, version 2 + /* 18*/ { 1, 3, "12345", 0, 0, 15, 1 }, // ECC 1, version 3 + /* 19*/ { 1, 4, "12345", 0, 0, 17, 1 }, // ECC 1, version 4 + /* 20*/ { 2, 1, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, -1 }, + /* 21*/ { 2, 2, "12345", 0, -1, 13, -1 }, // ECC 2, version 2 + /* 22*/ { 2, 3, "12345", 0, -1, 15, 1 }, // ECC 2, version 3 + /* 23*/ { 2, 4, "12345", 0, -1, 17, 1 }, // ECC 2, version 4 + /* 24*/ { 3, 1, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, -1 }, + /* 25*/ { 3, 2, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, -1 }, + /* 26*/ { 3, 3, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, -1 }, + /* 27*/ { 3, 4, "12345", 0, -1, 17, -1 }, // ECC 3, version 4 + /* 28*/ { 4, 4, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, -1 }, + /* 29*/ { 5, -1, "12345", 0, 0, 11, -1 }, // ECC > 4 ignored + /* 30*/ { 5, 1, "12345", 0, 0, 11, 0 }, // Ignored also if size given + /* 31*/ { 1, 1, "123456", ZINT_ERROR_TOO_LONG, -1, 0, -1 }, + /* 32*/ { 1, -1, "123456", 0, 0, 13, -1 }, // ECC 1 (L), version auto-set to 2 + /* 33*/ { 1, 2, "123456", 0, 0, 13, 0 }, + /* 34*/ { 2, 2, "ABCDEF", ZINT_ERROR_TOO_LONG, -1, 0, -1 }, + /* 35*/ { 1, -1, "ABCDEF", 0, 0, 13, -1 }, // ECC 1 (L), version auto-set to 2 + /* 36*/ { 1, 2, "ABCDEF", 0, 0, 13, 0 }, + /* 37*/ { 2, -1, "ABCDE", 0, 0, 13, -1 }, // ECC 2 (M), version auto-set to 2 + /* 38*/ { 2, 2, "ABCDE", 0, 0, 13, 0 }, // ECC 2 (M), version auto-set to 2 + /* 39*/ { 1, -1, "ABCDEABCDEABCD", 0, 0, 15, -1 }, // 14 alphanumerics, ECC 1, version auto-set to 3 + /* 40*/ { 1, 3, "ABCDEABCDEABCD", 0, 0, 15, 0 }, + /* 41*/ { 2, 3, "ABCDEABCDEABCD", ZINT_ERROR_TOO_LONG, -1, 0, -1 }, + /* 42*/ { 2, 3, "ABCDEABCDEA", 0, 0, 15, -1 }, // 11 alphanumerics, ECC 2, version 3 + /* 43*/ { 1, -1, "ABCDEFGHIJABCDEFGHIJA", 0, 0, 17, -1 }, // 21 alphanumerics, ECC 1, version auto-set to 4 + /* 44*/ { 1, 4, "ABCDEFGHIJABCDEFGHIJA", 0, 0, 17, 0 }, + /* 45*/ { 2, 4, "ABCDEFGHIJABCDEFGHIJA", ZINT_ERROR_TOO_LONG, -1, 0, -1 }, + /* 46*/ { 2, 4, "ABCDEFGHIJABCDEFGH", 0, 0, 17, -1 }, // 18 alphanumerics, ECC 2, version 4 + /* 47*/ { 3, 4, "ABCDEFGHIJABCDEFGH", ZINT_ERROR_TOO_LONG, -1, 0, -1 }, + /* 48*/ { 3, 4, "ABCDEFGHIJABC", 0, 0, 17, -1 }, // 13 alphanumerics, ECC 3 (Q), version 4 + /* 49*/ { -1, -1, "123456789012345678901234567890123456", ZINT_ERROR_TOO_LONG, -1, 0, -1 }, // 35 absolute max + /* 50*/ { -1, -1, "貫貫貫貫貫", 0, 0, 17, -1 }, // 5 Kanji max + /* 51*/ { -1, -1, "貫貫貫貫貫貫", ZINT_ERROR_TOO_LONG, -1, 0, -1 }, + /* 52*/ { -1, 1, "A", ZINT_ERROR_INVALID_DATA, -1, 0, -1 }, // Numeric only + /* 53*/ { -1, 2, "A", 0, 0, 13, -1 }, + /* 54*/ { -1, 2, " ", 0, 0, 13, -1 }, + /* 55*/ { -1, 2, "$%*+", 0, 0, 13, -1 }, + /* 56*/ { -1, 2, "-./:", 0, 0, 13, -1 }, + /* 57*/ { -1, 2, "a", ZINT_ERROR_INVALID_DATA, -1, 0, -1 }, // Uppercase only + /* 58*/ { -1, 2, "!", ZINT_ERROR_INVALID_DATA, -1, 0, -1 }, // Certain punctuation only + /* 59*/ { -1, 2, "#", ZINT_ERROR_INVALID_DATA, -1, 0, -1 }, // Certain punctuation only + /* 60*/ { -1, 2, ",", ZINT_ERROR_INVALID_DATA, -1, 0, -1 }, // Certain punctuation only + /* 61*/ { -1, 2, "@", ZINT_ERROR_INVALID_DATA, -1, 0, -1 }, // Certain punctuation only + /* 62*/ { -1, 2, "\177", ZINT_ERROR_INVALID_DATA, -1, 0, -1 }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -3292,10 +4517,12 @@ static void test_microqr_input(int index, int generate, int debug) { struct item { int input_mode; + int option_1; int option_3; char *data; int ret; char *expected; + int bwipp_cmp; char *comment; }; // é U+00E9 in ISO 8859-1 plus other ISO 8859 (but not in ISO 8859-7 or ISO 8859-11), Win 1250 plus other Win, not in Shift JIS, UTF-8 C3A9 @@ -3312,59 +4539,64 @@ static void test_microqr_input(int index, int generate, int debug) { // 茗 U+8317 kanji, in Shift JIS 0xE4AA (\344\252), UTF-8 E88C97 // Á U+00C1, UTF-8 C381; ȁ U+0201, UTF-8 C881; Ȃ U+0202, UTF-8 C882; ¢ U+00A2, UTF-8 C2A2; á U+00E1, UTF-8 C3A1 struct item data[] = { - /* 0*/ { UNICODE_MODE, -1, "é", 0, "87 A4 00 EC 11 EC 11 EC 00", "B1 (ISO 8859-1)" }, - /* 1*/ { DATA_MODE, -1, "é", 0, "8B 0E A4 00 EC 11 EC 11 00", "B2 (UTF-8)" }, - /* 2*/ { UNICODE_MODE, -1, "β", 0, "C8 80 00 00 EC 11 EC 11 00", "K1 (Shift JIS)" }, - /* 3*/ { UNICODE_MODE, -1, "ก", ZINT_ERROR_INVALID_DATA, "Error 800: Invalid character in input data", "ก not in Shift JIS" }, - /* 4*/ { UNICODE_MODE, -1, "Ж", 0, "C8 91 C0 00 EC 11 EC 11 00", "K1 (Shift JIS)" }, - /* 5*/ { UNICODE_MODE, -1, "ກ", ZINT_ERROR_INVALID_DATA, "Error 800: Invalid character in input data", "ກ not in Shift JIS" }, - /* 6*/ { UNICODE_MODE, -1, "\\", 0, "85 70 00 EC 11 EC 11 EC 00", "B1 (ASCII)" }, - /* 7*/ { UNICODE_MODE, -1, "¥", 0, "86 94 00 EC 11 EC 11 EC 00", "B1 (ISO 8859-1) (same bytes as ・ Shift JIS below, so ambiguous)" }, - /* 8*/ { UNICODE_MODE, -1, "・", 0, "86 94 00 EC 11 EC 11 EC 00", "B1 (Shift JIS) single-byte codepoint A5 (same bytes as ¥ ISO 8859-1 above, so ambiguous)" }, - /* 9*/ { UNICODE_MODE, -1, "¿", 0, "86 FC 00 EC 11 EC 11 EC 00", "B1 (ISO 8859-1) (same bytes as ソ Shift JIS below, so ambiguous)" }, - /* 10*/ { UNICODE_MODE, -1, "ソ", 0, "86 FC 00 EC 11 EC 11 EC 00", "B1 (Shift JIS) (same bytes as ¿ ISO 8859-1 above, so ambiguous)" }, - /* 11*/ { UNICODE_MODE, -1, "~", 0, "85 F8 00 EC 11 EC 11 EC 00", "B1 (ASCII) (same bytes as ‾ Shift JIS below, so ambiguous)" }, - /* 12*/ { UNICODE_MODE, -1, "‾", 0, "85 F8 00 EC 11 EC 11 EC 00", "B1 (Shift JIS) (same bytes as ~ ASCII above, so ambiguous)" }, - /* 13*/ { UNICODE_MODE, -1, "点", 0, "CB 67 C0 00 EC 11 EC 11 00", "K1 (Shift JIS)" }, - /* 14*/ { DATA_MODE, -1, "\223\137", 0, "8A 4D 7C 00 EC 11 EC 11 00", "B2 (Shift JIS)" }, - /* 15*/ { DATA_MODE, ZINT_FULL_MULTIBYTE, "\223\137", 0, "CB 67 C0 00 EC 11 EC 11 00", "K1 (Shift JIS) (full multibyte)" }, - /* 16*/ { DATA_MODE, -1, "点", 0, "8F 9E 0A E4 00 EC 11 EC 00", "B3 (UTF-8)" }, - /* 17*/ { UNICODE_MODE, -1, "茗", 0, "CE AA 80 00 EC 11 EC 11 00", "K1 (Shift JIS)" }, - /* 18*/ { DATA_MODE, -1, "\344\252", 0, "8B 92 A8 00 EC 11 EC 11 00", "B2 (Shift JIS)" }, - /* 19*/ { DATA_MODE, ZINT_FULL_MULTIBYTE, "\344\252", 0, "CE AA 80 00 EC 11 EC 11 00", "K1 (Shift JIS) (full multibyte)" }, - /* 20*/ { DATA_MODE, -1, "茗", 0, "8F A2 32 5C 00 EC 11 EC 00", "B3 (UTF-8)" }, - /* 21*/ { UNICODE_MODE, -1, "¥点", 0, "8D 72 4D 7C 00 EC 11 EC 00", "B3 (Shift JIS) (optimized from B1 K1)" }, - /* 22*/ { DATA_MODE, -1, "\134\223\137", 0, "8D 72 4D 7C 00 EC 11 EC 00", "B3 (Shift JIS) (optimized from B1 K1)" }, - /* 23*/ { DATA_MODE, -1, "¥点", 0, "97 0A 97 9E 0A E4 00 EC 00", "B5 (UTF-8)" }, - /* 24*/ { UNICODE_MODE, -1, "点茗", 0, "D3 67 F5 54 00 EC 11 EC 00", "K2 (Shift JIS)" }, - /* 25*/ { DATA_MODE, -1, "\223\137\344\252", 0, "92 4D 7F 92 A8 00 EC 11 00", "B4 (Shift JIS)" }, - /* 26*/ { DATA_MODE, ZINT_FULL_MULTIBYTE, "\223\137\344\252", 0, "D3 67 F5 54 00 EC 11 EC 00", "K2 (Shift JIS) (full multibyte)" }, - /* 27*/ { DATA_MODE, -1, "点茗", 0, "9B 9E 0A E7 A2 32 5C 00 00", "B6 (UTF-8)" }, - /* 28*/ { DATA_MODE, ZINT_FULL_MULTIBYTE, "点茗", 0, "9B 9E 0A E7 A2 32 5C 00 00", "B6 (UTF-8)" }, - /* 29*/ { UNICODE_MODE, -1, "点茗・", 0, "D3 67 F5 55 0D 28 00 EC 00", "K2 B1 (Shift JIS)" }, - /* 30*/ { DATA_MODE, -1, "\223\137\344\252\245", 0, "96 4D 7F 92 AA 94 00 EC 00", "B5 (Shift JIS)" }, - /* 31*/ { DATA_MODE, ZINT_FULL_MULTIBYTE, "\223\137\344\252\245", 0, "D3 67 F5 55 0D 28 00 EC 00", "K2 B1 (Shift JIS) (full multibyte)" }, - /* 32*/ { DATA_MODE, -1, "点茗・", 0, "A7 9E 0A E7 A2 32 5F BE F6 94 00", "B9 (UTF-8)" }, - /* 33*/ { UNICODE_MODE, -1, "¥点茗・", 0, "99 72 4D 7F 92 AA 94 00 00", "B6 (Shift JIS) (optimized from B1 K2 B1)" }, - /* 34*/ { DATA_MODE, -1, "\134\223\137\344\252\245", 0, "99 72 4D 7F 92 AA 94 00 00", "B6 (Shift JIS) (optimized from B1 K2 B1)" }, - /* 35*/ { DATA_MODE, -1, "¥点茗・", 0, "4B C2 A5 E7 82 B9 E8 8C 97 EF BD A5 00 00", "B11 (UTF-8)" }, - /* 36*/ { DATA_MODE, -1, "ÁȁȁȁȂ¢", 0, "4C C3 81 C8 81 C8 81 C8 81 C8 82 C2 A2 00", "B12 (UTF-8)" }, - /* 37*/ { DATA_MODE, -1, "ÁȁȁȁȁȂ¢", 0, "4E C3 81 C8 81 C8 81 C8 81 C8 81 C8 82 C2 A2 00", "B14 (UTF-8)" }, - /* 38*/ { DATA_MODE, ZINT_FULL_MULTIBYTE, "ÁȁȁȁȁȂ¢", 0, "41 C3 6C 08 80 44 02 20 11 00 88 0A 12 0D 10 00", "B1 K6 B1 (UTF-8) (full multibyte)" }, - /* 39*/ { UNICODE_MODE, -1, "áA", 0, "8B 85 04 00 EC 11 EC 11 00", "B2 (ISO 8859-1)" }, - /* 40*/ { UNICODE_MODE, ZINT_FULL_MULTIBYTE, "áA", 0, "CE 00 40 00 EC 11 EC 11 00", "K1 (ISO 8859-1) (full multibyte)" }, + /* 0*/ { UNICODE_MODE, 2, 1, "é", 0, "87 A4 00 EC 11 EC 11 EC 00", 1, "B1 (ISO 8859-1)" }, + /* 1*/ { DATA_MODE, 2, -1, "é", 0, "8B 0E A4 00 EC 11 EC 11 00", 1, "B2 (UTF-8)" }, + /* 2*/ { UNICODE_MODE, 2, -1, "β", 0, "C8 80 00 00 EC 11 EC 11 00", 1, "K1 (Shift JIS)" }, + /* 3*/ { UNICODE_MODE, 2, -1, "ก", ZINT_ERROR_INVALID_DATA, "Error 800: Invalid character in input data", 1, "ก not in Shift JIS" }, + /* 4*/ { UNICODE_MODE, 2, -1, "Ж", 0, "C8 91 C0 00 EC 11 EC 11 00", 1, "K1 (Shift JIS)" }, + /* 5*/ { UNICODE_MODE, 2, -1, "ກ", ZINT_ERROR_INVALID_DATA, "Error 800: Invalid character in input data", 1, "ກ not in Shift JIS" }, + /* 6*/ { UNICODE_MODE, 2, -1, "\\", 0, "85 70 00 EC 11 EC 11 EC 00", 1, "B1 (ASCII)" }, + /* 7*/ { UNICODE_MODE, 2, -1, "¥", 0, "86 94 00 EC 11 EC 11 EC 00", 1, "B1 (ISO 8859-1) (same bytes as ・ Shift JIS below, so ambiguous)" }, + /* 8*/ { UNICODE_MODE, 2, -1, "・", 0, "86 94 00 EC 11 EC 11 EC 00", 1, "B1 (Shift JIS) single-byte codepoint A5 (same bytes as ¥ ISO 8859-1 above, so ambiguous)" }, + /* 9*/ { UNICODE_MODE, 2, -1, "¿", 0, "86 FC 00 EC 11 EC 11 EC 00", 1, "B1 (ISO 8859-1) (same bytes as ソ Shift JIS below, so ambiguous)" }, + /* 10*/ { UNICODE_MODE, 2, -1, "ソ", 0, "86 FC 00 EC 11 EC 11 EC 00", 1, "B1 (Shift JIS) (same bytes as ¿ ISO 8859-1 above, so ambiguous)" }, + /* 11*/ { UNICODE_MODE, 2, -1, "~", 0, "85 F8 00 EC 11 EC 11 EC 00", 1, "B1 (ASCII) (same bytes as ‾ Shift JIS below, so ambiguous)" }, + /* 12*/ { UNICODE_MODE, 2, -1, "‾", 0, "85 F8 00 EC 11 EC 11 EC 00", 1, "B1 (Shift JIS) (same bytes as ~ ASCII above, so ambiguous)" }, + /* 13*/ { UNICODE_MODE, 2, -1, "点", 0, "CB 67 C0 00 EC 11 EC 11 00", 1, "K1 (Shift JIS)" }, + /* 14*/ { DATA_MODE, 2, -1, "\223\137", 0, "8A 4D 7C 00 EC 11 EC 11 00", 0, "B2 (Shift JIS); BWIPP uses Kanji (ZINT_FULL_MULTIBYTE) mode, see below)" }, + /* 15*/ { DATA_MODE, 2, ZINT_FULL_MULTIBYTE, "\223\137", 0, "CB 67 C0 00 EC 11 EC 11 00", 1, "K1 (Shift JIS) (full multibyte)" }, + /* 16*/ { DATA_MODE, 2, -1, "点", 0, "8F 9E 0A E4 00 EC 11 EC 00", 1, "B3 (UTF-8)" }, + /* 17*/ { UNICODE_MODE, 2, -1, "茗", 0, "CE AA 80 00 EC 11 EC 11 00", 1, "K1 (Shift JIS)" }, + /* 18*/ { DATA_MODE, 2, -1, "\344\252", 0, "8B 92 A8 00 EC 11 EC 11 00", 0, "B2 (Shift JIS); BWIPP uses Kanji (ZINT_FULL_MULTIBYTE) mode, see below)" }, + /* 19*/ { DATA_MODE, 2, ZINT_FULL_MULTIBYTE, "\344\252", 0, "CE AA 80 00 EC 11 EC 11 00", 1, "K1 (Shift JIS) (full multibyte)" }, + /* 20*/ { DATA_MODE, 2, -1, "茗", 0, "8F A2 32 5C 00 EC 11 EC 00", 1, "B3 (UTF-8)" }, + /* 21*/ { UNICODE_MODE, 2, -1, "¥点", 0, "8D 72 4D 7C 00 EC 11 EC 00", 1, "B3 (Shift JIS) (optimized from B1 K1)" }, + /* 22*/ { DATA_MODE, 2, -1, "\134\223\137", 0, "8D 72 4D 7C 00 EC 11 EC 00", 1, "B3 (Shift JIS) (optimized from B1 K1)" }, + /* 23*/ { DATA_MODE, 2, -1, "¥点", 0, "97 0A 97 9E 0A E4 00 EC 00", 1, "B5 (UTF-8)" }, + /* 24*/ { UNICODE_MODE, 2, -1, "点茗", 0, "D3 67 F5 54 00 EC 11 EC 00", 1, "K2 (Shift JIS)" }, + /* 25*/ { DATA_MODE, 2, -1, "\223\137\344\252", 0, "92 4D 7F 92 A8 00 EC 11 00", 0, "B4 (Shift JIS; BWIPP uses Kanji (ZINT_FULL_MULTIBYTE) mode, see below))" }, + /* 26*/ { DATA_MODE, 2, ZINT_FULL_MULTIBYTE, "\223\137\344\252", 0, "D3 67 F5 54 00 EC 11 EC 00", 1, "K2 (Shift JIS) (full multibyte)" }, + /* 27*/ { DATA_MODE, 2, -1, "点茗", 0, "9B 9E 0A E7 A2 32 5C 00 00", 1, "B6 (UTF-8)" }, + /* 28*/ { DATA_MODE, 2, ZINT_FULL_MULTIBYTE, "点茗", 0, "9B 9E 0A E7 A2 32 5C 00 00", 1, "B6 (UTF-8)" }, + /* 29*/ { UNICODE_MODE, 2, -1, "点茗・", 0, "D3 67 F5 55 0D 28 00 EC 00", 1, "K2 B1 (Shift JIS)" }, + /* 30*/ { DATA_MODE, 2, -1, "\223\137\344\252\245", 0, "96 4D 7F 92 AA 94 00 EC 00", 0, "B5 (Shift JIS); BWIPP uses Kanji (ZINT_FULL_MULTIBYTE) mode, see below)" }, + /* 31*/ { DATA_MODE, 2, ZINT_FULL_MULTIBYTE, "\223\137\344\252\245", 0, "D3 67 F5 55 0D 28 00 EC 00", 1, "K2 B1 (Shift JIS) (full multibyte)" }, + /* 32*/ { DATA_MODE, 1, -1, "点茗・", 0, "A7 9E 0A E7 A2 32 5F BE F6 94 00", 1, "B9 (UTF-8)" }, + /* 33*/ { UNICODE_MODE, 2, -1, "¥点茗・", 0, "99 72 4D 7F 92 AA 94 00 00", 1, "B6 (Shift JIS) (optimized from B1 K2 B1)" }, + /* 34*/ { DATA_MODE, 2, -1, "\134\223\137\344\252\245", 0, "99 72 4D 7F 92 AA 94 00 00", 1, "B6 (Shift JIS) (optimized from B1 K2 B1)" }, + /* 35*/ { DATA_MODE, 2, -1, "¥点茗・", 0, "4B C2 A5 E7 82 B9 E8 8C 97 EF BD A5 00 00", 1, "B11 (UTF-8)" }, + /* 36*/ { DATA_MODE, 2, -1, "ÁȁȁȁȂ¢", 0, "4C C3 81 C8 81 C8 81 C8 81 C8 82 C2 A2 00", 0, "B12 (UTF-8); BWIPP different encodation (B1 K5 B1)" }, + /* 37*/ { DATA_MODE, 1, -1, "ÁȁȁȁȁȂ¢", 0, "4E C3 81 C8 81 C8 81 C8 81 C8 81 C8 82 C2 A2 00", 0, "B14 (UTF-8); BWIPP uses Kanji (ZINT_FULL_MULTIBYTE) mode, see below)" }, + /* 38*/ { DATA_MODE, 1, ZINT_FULL_MULTIBYTE, "ÁȁȁȁȁȂ¢", 0, "41 C3 6C 08 80 44 02 20 11 00 88 0A 12 0D 10 00", 1, "B1 K6 B1 (UTF-8) (full multibyte)" }, + /* 39*/ { UNICODE_MODE, 2, -1, "áA", 0, "8B 85 04 00 EC 11 EC 11 00", 0, "B2 (ISO 8859-1); BWIPP uses Kanji (ZINT_FULL_MULTIBYTE) mode, see below)" }, + /* 40*/ { UNICODE_MODE, 2, ZINT_FULL_MULTIBYTE, "áA", 0, "CE 00 40 00 EC 11 EC 11 00", 1, "K1 (ISO 8859-1) (full multibyte)" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol; char escaped[4096]; + 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 testStart("test_microqr_input"); for (i = 0; i < data_size; i++) { if (index != -1 && i != index) continue; + if ((debug & ZINT_DEBUG_TEST_PRINT) && !(debug & ZINT_DEBUG_TEST_LESS_NOISY)) printf("i:%d\n", i); symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); @@ -3377,12 +4609,29 @@ static void test_microqr_input(int index, int generate, int debug) { assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, %s, \"%s\", %s, \"%s\", \"%s\" },\n", - i, testUtilInputModeName(data[i].input_mode), testUtilOption3Name(data[i].option_3), + printf(" /*%3d*/ { %s, %d, %s, \"%s\", %s, \"%s\", %d, \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), data[i].option_1, testUtilOption3Name(data[i].option_3), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), - testUtilErrorName(data[i].ret), symbol->errtxt, data[i].comment); + testUtilErrorName(data[i].ret), symbol->errtxt, data[i].bwipp_cmp, data[i].comment); } else { assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + + if (ret < ZINT_ERROR) { + if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, -1, 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[17 * 17 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilBwipp(i, symbol, data[i].option_1, -1, 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); + } + } + } } ZBarcode_Delete(symbol); @@ -3395,48 +4644,48 @@ static void test_microqr_input(int index, int generate, int debug) { static void test_microqr_padding(int index, int generate, int debug) { struct item { - char *data; int option_1; + char *data; int ret; char *expected; char *comment; }; struct item data[] = { - /* 0*/ { "1", -1, 0, "22 00 00", "M1, bits left 13" }, - /* 1*/ { "12", -1, 0, "43 00 00", "M1, bits left 10" }, - /* 2*/ { "123", -1, 0, "63 D8 00", "M1, bits left 7" }, - /* 3*/ { "1234", -1, 0, "83 DA 00", "M1, bits left 3" }, - /* 4*/ { "12345", -1, 0, "A3 DA D0", "M1, bits left 0" }, - /* 5*/ { "123456", 1, 0, "30 F6 E4 00 EC", "M2-L, bits left 15" }, - /* 6*/ { "1234567", 1, 0, "38 F6 E4 38 00", "M2-L, bits left 11" }, - /* 7*/ { "12345678", 1, 0, "40 F6 E4 4E 00", "M2-L, bits left 8" }, - /* 8*/ { "123456789", 1, 0, "48 F6 E4 62 A0", "M2-L, bits left 5" }, - /* 9*/ { "1234567890", 1, 0, "50 F6 E4 62 A0", "M2-L, bits left 1" }, - /* 10*/ { "1234", 2, 0, "20 F6 80 EC", "M2-M, bits left 13" }, - /* 11*/ { "123456", 2, 0, "30 F6 E4 00", "M2-M, bits left 7" }, - /* 12*/ { "1234567", 2, 0, "38 F6 E4 38", "M2-M, bits left 3" }, - /* 13*/ { "12345678", 2, 0, "40 F6 E4 4E", "M2-M, bits left 0" }, - /* 14*/ { "ABCDEF", 1, 0, "E3 9A 8A 54 28", "M2-L, bits left 3" }, - /* 15*/ { "ABCDE", 2, 0, "D3 9A 8A 4E", "M2-M, bits left 0" }, - /* 16*/ { "1234567890123456789", 1, 0, "26 3D B9 18 A8 18 AC D4 D2 00 00", "M3-L, bits left 13" }, - /* 17*/ { "12345678901234567890", 1, 0, "28 3D B9 18 A8 18 AC D4 D6 80 00", "M3-L, bits left 10" }, - /* 18*/ { "123456789012345678901", 1, 0, "2A 3D B9 18 A8 18 AC D4 DC 28 00", "M3-L, bits left 7" }, - /* 19*/ { "1234567890123456789012", 1, 0, "2C 3D B9 18 A8 18 AC D4 DC 29 00", "M3-L, bits left 3" }, - /* 20*/ { "12345678901234567890123", 1, 0, "2E 3D B9 18 A8 18 AC D4 DC 29 70", "M3-L, bits left 0" }, - /* 21*/ { "1234567890", 2, 0, "14 3D B9 18 A8 00 EC 11 00", "M3-M, bits left 27" }, - /* 22*/ { "123456789012345678", 2, 0, "24 3D B9 18 A8 18 AC D4 C0", "M3-M, bits left 1" }, - /* 23*/ { "ABCDEFGHIJKLMN", 1, 0, "78 E6 A2 95 0A B8 59 EB 99 7E A0", "M3-L, bits left 1" }, - /* 24*/ { "ABCDEFGHIJK", 2, 0, "6C E6 A2 95 0A B8 59 EA 80", "M3-M, bits left 1" }, - /* 25*/ { "1234567890123456789012345678", 1, 0, "0E 0F 6E 46 2A 06 2B 35 37 0A 75 46 F0 00 EC 11", "M4-L, bits left 25" }, - /* 26*/ { "123456789012345678901234567890", 1, 0, "0F 0F 6E 46 2A 06 2B 35 37 0A 75 46 FB D0 00 EC", "M4-L, bits left 19" }, - /* 27*/ { "1234567890123456789012345678901234", 1, 0, "11 0F 6E 46 2A 06 2B 35 37 0A 75 46 FB D0 F6 80", "M4-L, bits left 5" }, - /* 28*/ { "12345678901234567890123456789012345", 1, 0, "11 8F 6E 46 2A 06 2B 35 37 0A 75 46 FB D0 F6 B4", "M4-L, bits left 1" }, - /* 29*/ { "123456789012345ABCDEFGHIJK", 1, 0, "07 8F 6E 46 2A 06 2B 25 67 35 14 A8 55 C2 CF 54", "M4-L, bits left 0" }, - /* 30*/ { "123456789012345678901234567890", 2, 0, "0F 0F 6E 46 2A 06 2B 35 37 0A 75 46 FB D0", "M4-M, bits left 3" }, - /* 31*/ { "123456789012345678901", 3, 0, "0A 8F 6E 46 2A 06 2B 35 37 0A", "M4-Q, bits left 1" }, - /* 32*/ { "ABCDEFGHIJKLMNOPQRSTU", 1, 0, "35 39 A8 A5 42 AE 16 7A E6 5F AC 51 95 B4 25 E0", "M4-L, bits left 4" }, - /* 33*/ { "ABCDEFGHIJKLMNOPQR", 2, 0, "32 39 A8 A5 42 AE 16 7A E6 5F AC 51 95 A0", "M4-M, bits left 5" }, - /* 34*/ { "ABCDEFGHIJKLM", 3, 0, "2D 39 A8 A5 42 AE 16 7A E6 56", "M4-Q, bits left 0" }, + /* 0*/ { -1, "1", 0, "22 00 00", "M1, bits left 13" }, + /* 1*/ { -1, "12", 0, "43 00 00", "M1, bits left 10" }, + /* 2*/ { -1, "123", 0, "63 D8 00", "M1, bits left 7" }, + /* 3*/ { -1, "1234", 0, "83 DA 00", "M1, bits left 3" }, + /* 4*/ { -1, "12345", 0, "A3 DA D0", "M1, bits left 0" }, + /* 5*/ { 1, "123456", 0, "30 F6 E4 00 EC", "M2-L, bits left 15" }, + /* 6*/ { 1, "1234567", 0, "38 F6 E4 38 00", "M2-L, bits left 11" }, + /* 7*/ { 1, "12345678", 0, "40 F6 E4 4E 00", "M2-L, bits left 8" }, + /* 8*/ { 1, "123456789", 0, "48 F6 E4 62 A0", "M2-L, bits left 5" }, + /* 9*/ { 1, "1234567890", 0, "50 F6 E4 62 A0", "M2-L, bits left 1" }, + /* 10*/ { 2, "1234", 0, "20 F6 80 EC", "M2-M, bits left 13" }, + /* 11*/ { 2, "123456", 0, "30 F6 E4 00", "M2-M, bits left 7" }, + /* 12*/ { 2, "1234567", 0, "38 F6 E4 38", "M2-M, bits left 3" }, + /* 13*/ { 2, "12345678", 0, "40 F6 E4 4E", "M2-M, bits left 0" }, + /* 14*/ { 1, "ABCDEF", 0, "E3 9A 8A 54 28", "M2-L, bits left 3" }, + /* 15*/ { 2, "ABCDE", 0, "D3 9A 8A 4E", "M2-M, bits left 0" }, + /* 16*/ { 1, "1234567890123456789", 0, "26 3D B9 18 A8 18 AC D4 D2 00 00", "M3-L, bits left 13" }, + /* 17*/ { 1, "12345678901234567890", 0, "28 3D B9 18 A8 18 AC D4 D6 80 00", "M3-L, bits left 10" }, + /* 18*/ { 1, "123456789012345678901", 0, "2A 3D B9 18 A8 18 AC D4 DC 28 00", "M3-L, bits left 7" }, + /* 19*/ { 1, "1234567890123456789012", 0, "2C 3D B9 18 A8 18 AC D4 DC 29 00", "M3-L, bits left 3" }, + /* 20*/ { 1, "12345678901234567890123", 0, "2E 3D B9 18 A8 18 AC D4 DC 29 70", "M3-L, bits left 0" }, + /* 21*/ { 2, "1234567890", 0, "14 3D B9 18 A8 00 EC 11 00", "M3-M, bits left 27" }, + /* 22*/ { 2, "123456789012345678", 0, "24 3D B9 18 A8 18 AC D4 C0", "M3-M, bits left 1" }, + /* 23*/ { 1, "ABCDEFGHIJKLMN", 0, "78 E6 A2 95 0A B8 59 EB 99 7E A0", "M3-L, bits left 1" }, + /* 24*/ { 2, "ABCDEFGHIJK", 0, "6C E6 A2 95 0A B8 59 EA 80", "M3-M, bits left 1" }, + /* 25*/ { 1, "1234567890123456789012345678", 0, "0E 0F 6E 46 2A 06 2B 35 37 0A 75 46 F0 00 EC 11", "M4-L, bits left 25" }, + /* 26*/ { 1, "123456789012345678901234567890", 0, "0F 0F 6E 46 2A 06 2B 35 37 0A 75 46 FB D0 00 EC", "M4-L, bits left 19" }, + /* 27*/ { 1, "1234567890123456789012345678901234", 0, "11 0F 6E 46 2A 06 2B 35 37 0A 75 46 FB D0 F6 80", "M4-L, bits left 5" }, + /* 28*/ { 1, "12345678901234567890123456789012345", 0, "11 8F 6E 46 2A 06 2B 35 37 0A 75 46 FB D0 F6 B4", "M4-L, bits left 1" }, + /* 29*/ { 1, "123456789012345ABCDEFGHIJK", 0, "07 8F 6E 46 2A 06 2B 25 67 35 14 A8 55 C2 CF 54", "M4-L, bits left 0" }, + /* 30*/ { 2, "123456789012345678901234567890", 0, "0F 0F 6E 46 2A 06 2B 35 37 0A 75 46 FB D0", "M4-M, bits left 3" }, + /* 31*/ { 3, "123456789012345678901", 0, "0A 8F 6E 46 2A 06 2B 35 37 0A", "M4-Q, bits left 1" }, + /* 32*/ { 1, "ABCDEFGHIJKLMNOPQRSTU", 0, "35 39 A8 A5 42 AE 16 7A E6 5F AC 51 95 B4 25 E0", "M4-L, bits left 4" }, + /* 33*/ { 2, "ABCDEFGHIJKLMNOPQR", 0, "32 39 A8 A5 42 AE 16 7A E6 5F AC 51 95 A0", "M4-M, bits left 5" }, + /* 34*/ { 3, "ABCDEFGHIJKLM", 0, "2D 39 A8 A5 42 AE 16 7A E6 56", "M4-Q, bits left 0" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -3468,8 +4717,8 @@ static void test_microqr_padding(int index, int generate, int debug) { assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { \"%s\", %d, %s, \"%s\", \"%s\" },\n", - i, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].option_1, + printf(" /*%3d*/ { %d, \"%s\", %s, \"%s\", \"%s\" },\n", + i, data[i].option_1, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), testUtilErrorName(data[i].ret), symbol->errtxt, data[i].comment); } else { assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); @@ -3491,28 +4740,33 @@ static void test_microqr_optimize(int index, int generate, int debug) { char *data; int ret; char *expected; + int bwipp_cmp; char *comment; }; struct item data[] = { - /* 0*/ { UNICODE_MODE, -1, -1, -1, "1", 0, "22 00 00", "N1" }, - /* 1*/ { UNICODE_MODE, 1, 2, -1, "A123", 0, "92 86 3D 80 EC", "A1 N3" }, - /* 2*/ { UNICODE_MODE, 1, -1, -1, "AAAAAA", 0, "E3 98 73 0E 60", "A6" }, - /* 3*/ { UNICODE_MODE, 1, -1, -1, "AA123456", 0, "A3 98 61 ED C8", "A2 N6" }, - /* 4*/ { UNICODE_MODE, 1, 3, -1, "01a", 0, "04 06 16 10 00 EC 11 EC 11 EC 00", "N3 B1" }, - /* 5*/ { UNICODE_MODE, 1, 4, -1, "01a", 0, "43 30 31 61 00 00 EC 11 EC 11 EC 11 EC 11 EC 11", "B3" }, - /* 6*/ { UNICODE_MODE, 1, -1, -1, "こんwa、αβ", 0, "46 82 B1 82 F1 77 61 66 00 10 FF 88 00 00 EC 11", "B6 K3" }, - /* 7*/ { UNICODE_MODE, 1, -1, -1, "こんにwa、αβ", 0, "66 13 10 B8 85 25 09 DD 85 98 00 43 FE 20 00 00", "K3 B2 K3" }, - /* 8*/ { UNICODE_MODE, 1, 3, -1, "こんAB123\177", 0, "D0 4C 42 E2 91 CD 06 3D C2 FE 00", "K2 A2 N3 B1" }, - /* 9*/ { UNICODE_MODE, 1, 4, -1, "こんAB123\177", 0, "64 13 10 B8 92 9C D0 5E 1A 0B F8 00 EC 11 EC 11", "K2 A5 B1" }, - /* 10*/ { DATA_MODE, 1, -1, -1, "\223\137", 0, "8A 4D 7C 00 EC 11 EC 11 EC 11 00", "B2" }, - /* 11*/ { DATA_MODE, 1, -1, ZINT_FULL_MULTIBYTE, "\223\137", 0, "CB 67 C0 00 EC 11 EC 11 EC 11 00", "K1" }, - /* 12*/ { DATA_MODE, 1, -1, ZINT_FULL_MULTIBYTE | (1 << 8), "\223\137", 0, "CB 67 C0 00 EC 11 EC 11 EC 11 00", "K1" }, + /* 0*/ { UNICODE_MODE, -1, -1, -1, "1", 0, "22 00 00", 1, "N1" }, + /* 1*/ { UNICODE_MODE, 1, 2, -1, "A123", 0, "92 86 3D 80 EC", 1, "A1 N3" }, + /* 2*/ { UNICODE_MODE, 1, -1, -1, "AAAAAA", 0, "E3 98 73 0E 60", 1, "A6" }, + /* 3*/ { UNICODE_MODE, 1, -1, -1, "AA123456", 0, "A3 98 61 ED C8", 1, "A2 N6" }, + /* 4*/ { UNICODE_MODE, 1, 3, -1, "01a", 0, "04 06 16 10 00 EC 11 EC 11 EC 00", 1, "N3 B1" }, + /* 5*/ { UNICODE_MODE, 1, 4, -1, "01a", 0, "43 30 31 61 00 00 EC 11 EC 11 EC 11 EC 11 EC 11", 1, "B3" }, + /* 6*/ { UNICODE_MODE, 1, -1, -1, "こんwa、αβ", 0, "46 82 B1 82 F1 77 61 66 00 10 FF 88 00 00 EC 11", 1, "B6 K3" }, + /* 7*/ { UNICODE_MODE, 1, -1, -1, "こんにwa、αβ", 0, "66 13 10 B8 85 25 09 DD 85 98 00 43 FE 20 00 00", 1, "K3 B2 K3" }, + /* 8*/ { UNICODE_MODE, 1, 3, -1, "こんAB123\177", 0, "D0 4C 42 E2 91 CD 06 3D C2 FE 00", 0, "K2 A2 N3 B1; BWIPP different encodation (K2 A5 B1)" }, + /* 9*/ { UNICODE_MODE, 1, 4, -1, "こんAB123\177", 0, "64 13 10 B8 92 9C D0 5E 1A 0B F8 00 EC 11 EC 11", 1, "K2 A5 B1" }, + /* 10*/ { DATA_MODE, 1, -1, -1, "\223\137", 0, "8A 4D 7C 00 EC 11 EC 11 EC 11 00", 0, "B2; BWIPP uses Kanji (ZINT_FULL_MULTIBYTE) mode, see below)" }, + /* 11*/ { DATA_MODE, 1, -1, ZINT_FULL_MULTIBYTE, "\223\137", 0, "CB 67 C0 00 EC 11 EC 11 EC 11 00", 1, "K1" }, + /* 12*/ { DATA_MODE, 1, -1, ZINT_FULL_MULTIBYTE | (1 << 8), "\223\137", 0, "CB 67 C0 00 EC 11 EC 11 EC 11 00", 1, "K1" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol; char escaped[4096]; + 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 testStart("test_microqr_optimize"); @@ -3531,12 +4785,27 @@ static void test_microqr_optimize(int index, int generate, int debug) { assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, %d, %d, %s, \"%s\", %s, \"%s\", \"%s\" },\n", + printf(" /*%3d*/ { %s, %d, %d, %s, \"%s\", %s, \"%s\", %d, \"%s\" },\n", i, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_2, testUtilOption3Name(data[i].option_3), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), - testUtilErrorName(data[i].ret), symbol->errtxt, data[i].comment); + testUtilErrorName(data[i].ret), symbol->errtxt, data[i].bwipp_cmp, data[i].comment); } else { assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + + if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_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[17 * 17 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilBwipp(i, symbol, data[i].option_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); + } + } } ZBarcode_Delete(symbol); @@ -3884,7 +5153,7 @@ static void test_microqr_encode(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, data[i].option_3, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_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, data[i].expected); @@ -4035,9 +5304,9 @@ static void test_upnqr_encode(int index, int generate, int debug) { struct item { int input_mode; - char *data; int option_1; int option_2; + char *data; int ret; int expected_rows; @@ -4047,7 +5316,7 @@ static void test_upnqr_encode(int index, int generate, int debug) { }; struct item data[] = { - /* 0*/ { UNICODE_MODE, "Ą˘Ł¤ĽŚ§¨ŠŞŤŹŽŻ°ą˛ł´ľśˇ¸šşťź˝žżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙", -1, -1, 0, 77, 77, "ISO 8859-2", + /* 0*/ { UNICODE_MODE, -1, -1, "Ą˘Ł¤ĽŚ§¨ŠŞŤŹŽŻ°ą˛ł´ľśˇ¸šşťź˝žżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙", 0, 77, 77, "ISO 8859-2", "11111110000111101001000110101100101001111110111011001111111000110000001111111" "10000010001011100100110111111011110100001011110000100001001110011010101000001" "10111010110101111111101101111101001010110101111011011110100001100100101011101" @@ -4146,8 +5415,9 @@ static void test_upnqr_encode(int index, int generate, int debug) { assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, \"%s\", %d, %d, %s, %d, %d, \"%s\",\n", - i, testUtilInputModeName(data[i].input_mode), data[i].data, data[i].option_1, data[i].option_2, testUtilErrorName(data[i].ret), + printf(" /*%3d*/ { %s, %d, %d, \"%s\", %s, %d, %d, \"%s\",\n", + i, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_2, + data[i].data, testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment); testUtilModulesPrint(symbol, " ", "\n"); printf(" },\n"); @@ -4171,9 +5441,9 @@ static void test_upnqr_encode(int index, int generate, int debug) { static void test_rmqr_options(int index, int debug) { struct item { - char *data; int option_1; int option_2; + char *data; int ret_encode; int ret_vector; int expected_rows; @@ -4181,75 +5451,75 @@ static void test_rmqr_options(int index, int debug) { }; // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { "12345", -1, -1, 0, 0, 11, 27 }, // ECC auto-set to H, version auto-set to 11 (R11x27) - /* 1*/ { "12345", 4, 11, 0, 0, 11, 27 }, - /* 2*/ { "12345", 1, -1, ZINT_ERROR_INVALID_OPTION, -1, 0, 0 }, // ECC L not available - /* 3*/ { "12345", 3, -1, ZINT_ERROR_INVALID_OPTION, -1, 0, 0 }, // ECC Q not available - /* 4*/ { "123456789", 4, 11, 0, 0, 11, 27 }, // Max capacity ECC H, version 11, 9 numbers - /* 5*/ { "1234567890", 4, 11, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 6*/ { "12345678901234", 2, 11, 0, 0, 11, 27 }, // Max capacity ECC M, version 11, 14 numbers - /* 7*/ { "123456789012345", 2, 11, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 8*/ { "ABCDEF", 4, 11, 0, 0, 11, 27 }, // Max capacity ECC H, version 11, 6 letters - /* 9*/ { "ABCDEFG", 4, 11, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 10*/ { "ABCDEFGH", 2, 11, 0, 0, 11, 27 }, // Max capacity ECC M, version 11, 8 letters - /* 11*/ { "ABCDEFGHI", 2, 11, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 12*/ { "\177\177\177\177", 4, 11, 0, 0, 11, 27 }, // Max capacity ECC H, version 11, 4 bytes - /* 13*/ { "\177\177\177\177\177", 4, 11, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 14*/ { "\177\177\177\177\177\177", 2, 11, 0, 0, 11, 27 }, // Max capacity ECC M, version 11, 6 bytes - /* 15*/ { "\177\177\177\177\177\177\177", 2, 11, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 16*/ { "点茗", 4, 11, ZINT_WARN_NONCOMPLIANT, 0, 11, 27 }, // Max capacity ECC H, version 11, 2 kanji - /* 17*/ { "点茗点", 4, 11, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 18*/ { "点茗点", 2, 11, ZINT_WARN_NONCOMPLIANT, 0, 11, 27 }, // Max capacity ECC M, version 11, 3 kanji - /* 19*/ { "点茗点茗", 2, 11, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 20*/ { "12345", -1, 1, 0, 0, 7, 43 }, // ECC auto-set to M, version 1 (R7x43) - /* 21*/ { "12345", 2, 1, 0, 0, 7, 43 }, - /* 22*/ { "12345", 4, 1, 0, 0, 7, 43 }, // Max capacity ECC H, version 1, 5 numbers - /* 23*/ { "123456", 4, 1, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 24*/ { "123456789012", 2, 1, 0, 0, 7, 43 }, // Max capacity ECC M, version 1, 12 numbers - /* 25*/ { "1234567890123", 2, 1, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 26*/ { "ABC", 4, 1, 0, 0, 7, 43 }, // Max capacity ECC H, version 1, 3 letters - /* 27*/ { "ABCD", 4, 1, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 28*/ { "ABCDEFG", 2, 1, 0, 0, 7, 43 }, // Max capacity ECC M, version 1, 7 letters - /* 29*/ { "ABCDEFGH", 2, 1, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 30*/ { "\177\177", 4, 1, 0, 0, 7, 43 }, // Max capacity ECC H, version 1, 2 bytes - /* 31*/ { "\177\177\177", 4, 1, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 32*/ { "\177\177\177\177\177", 2, 1, 0, 0, 7, 43 }, // Max capacity ECC M, version 1, 5 bytes - /* 33*/ { "\177\177\177\177\177\177", 2, 1, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 34*/ { "点", 4, 1, ZINT_WARN_NONCOMPLIANT, 0, 7, 43 }, // Max capacity ECC H, version 1, 1 kanji - /* 35*/ { "点茗", 4, 1, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 36*/ { "点茗点", 2, 1, ZINT_WARN_NONCOMPLIANT, 0, 7, 43 }, // Max capacity ECC M, version 1, 3 kanji - /* 37*/ { "点茗点茗", 2, 1, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 38*/ { "12345678901234567890123", 4, 7, 0, 0, 9, 59 }, // Max capacity ECC H, version 7 (R9x59), 23 numbers - /* 39*/ { "123456789012345678901234", 4, 7, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 40*/ { "点茗点茗点茗", 4, 7, ZINT_WARN_NONCOMPLIANT, 0, 9, 59 }, // Max capacity ECC H, version 7, 6 kanji - /* 41*/ { "点茗点茗点茗点", 4, 7, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 42*/ { "点茗点茗点茗点茗", 4, 13, ZINT_WARN_NONCOMPLIANT, 0, 11, 59 }, // Max capacity ECC H, version 13 (R11x59), 8 kanji - /* 43*/ { "点茗点茗点茗点茗点", 4, 13, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 44*/ { "点茗点茗点茗点茗点茗点茗点茗点茗点", 4, 20, ZINT_WARN_NONCOMPLIANT, 0, 13, 77 }, // Max capacity ECC H, version 20 (R13x77), 17 kanji - /* 45*/ { "点茗点茗点茗点茗点茗点茗点茗点茗点茗", 4, 20, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 46*/ { "点茗点茗点茗点茗点茗点茗点茗点茗点点茗点茗点茗点点茗点茗", 4, 26, ZINT_WARN_NONCOMPLIANT, 0, 15, 99 }, // Max capacity ECC H, version 26 (R15x99), 28 kanji - /* 47*/ { "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点", 4, 26, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 48*/ { "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗", 4, 32, ZINT_WARN_NONCOMPLIANT, 0, 17, 139 }, // Max capacity ECC H, version 32 (R17x139), 46 kanji - /* 49*/ { "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点", 4, 32, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 50*/ { "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗", -1, 32, ZINT_WARN_NONCOMPLIANT, 0, 17, 139 }, // Max capacity ECC M, version 32, 92 kanji - /* 51*/ { "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点", 4, 32, ZINT_ERROR_TOO_LONG, -1, 0, 0 }, - /* 52*/ { "点茗点", -1, 33, ZINT_WARN_NONCOMPLIANT, 0, 7, 43 }, // ECC auto-set to M, version 33 (R7xAuto-width) auto-sets R7x43 - /* 53*/ { "点茗点", 4, 33, ZINT_WARN_NONCOMPLIANT, 0, 7, 59 }, // ECC set to H, version 33 (R7xAuto-width) auto-sets R7x59 - /* 54*/ { "点茗点", -1, 34, ZINT_WARN_NONCOMPLIANT, 0, 9, 43 }, // ECC auto-set to H, version 34 (R9xAuto-width) auto-sets R9x43 - /* 55*/ { "点茗点", -1, 35, ZINT_WARN_NONCOMPLIANT, 0, 11, 27 }, // ECC auto-set to M, version 35 (R11xAuto-width) auto-sets R11x27 - /* 56*/ { "点茗点茗点茗点", 4, 35, ZINT_WARN_NONCOMPLIANT, 0, 11, 59 }, // ECC set to H, version 35 (R11xAuto-width) auto-sets R11x59 - /* 57*/ { "点茗点茗点茗点", -1, 35, ZINT_WARN_NONCOMPLIANT, 0, 11, 43 }, // ECC auto-set to M, version 35 (R11xAuto-width) auto-sets R11x43 - /* 58*/ { "点茗点茗点茗点茗", -1, 36, ZINT_WARN_NONCOMPLIANT, 0, 13, 43 }, // ECC auto-set to M, version 36 (R13xAuto-width) auto-sets R13x43 - /* 59*/ { "点茗点茗点茗点茗", 4, 36, ZINT_WARN_NONCOMPLIANT, 0, 13, 59 }, // ECC set to H, version 36 (R13xAuto-width) auto-sets R13x59 - /* 60*/ { "点茗点茗点茗点茗点", -1, 37, ZINT_WARN_NONCOMPLIANT, 0, 15, 43 }, // ECC auto-set to M, version 37 (R15xAuto-width) auto-sets R15x43 - /* 61*/ { "点茗点茗点茗点茗点", 4, 37, ZINT_WARN_NONCOMPLIANT, 0, 15, 59 }, // ECC set to H, version 37 (R15xAuto-width) auto-sets R15x59 - /* 62*/ { "点茗点茗点茗点茗点茗点茗点茗点茗点茗", -1, 38, ZINT_WARN_NONCOMPLIANT, 0, 17, 43 }, // ECC auto-set to M, version 38 (R17xAuto-width) auto-sets R17x43 - /* 63*/ { "点茗点茗点茗点茗点茗点茗点茗点茗点茗", 4, 38, ZINT_WARN_NONCOMPLIANT, 0, 17, 77 }, // ECC set to H, version 38 (R17xAuto-width) auto-sets R17x77 - /* 64*/ { "点茗点", -1, 39, ZINT_ERROR_INVALID_OPTION, -1, 0, 0 }, - /* 65*/ { "点茗点", 4, -1, ZINT_WARN_NONCOMPLIANT, 0, 13, 27 }, // ECC set to H, auto-sets R13x27 - /* 66*/ { "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗", 4, -1, ZINT_WARN_NONCOMPLIANT, 0, 15, 99 }, // ECC set to H, auto-sets R15x99 (max capacity) - /* 67*/ { "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点", 4, -1, ZINT_WARN_NONCOMPLIANT, 0, 17, 99 }, // ECC set to H, auto-sets R17x99 - /* 68*/ { "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗", 4, -1, ZINT_WARN_NONCOMPLIANT, 0, 17, 139 }, // ECC set to H, auto-sets R17x139 (max capacity) + /* 0*/ { -1, -1, "12345", 0, 0, 11, 27 }, // ECC auto-set to H, version auto-set to 11 (R11x27) + /* 1*/ { 4, 11, "12345", 0, 0, 11, 27 }, + /* 2*/ { 1, -1, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, 0 }, // ECC L not available + /* 3*/ { 3, -1, "12345", ZINT_ERROR_INVALID_OPTION, -1, 0, 0 }, // ECC Q not available + /* 4*/ { 4, 11, "123456789", 0, 0, 11, 27 }, // Max capacity ECC H, version 11, 9 numbers + /* 5*/ { 4, 11, "1234567890", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 6*/ { 2, 11, "12345678901234", 0, 0, 11, 27 }, // Max capacity ECC M, version 11, 14 numbers + /* 7*/ { 2, 11, "123456789012345", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 8*/ { 4, 11, "ABCDEF", 0, 0, 11, 27 }, // Max capacity ECC H, version 11, 6 letters + /* 9*/ { 4, 11, "ABCDEFG", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 10*/ { 2, 11, "ABCDEFGH", 0, 0, 11, 27 }, // Max capacity ECC M, version 11, 8 letters + /* 11*/ { 2, 11, "ABCDEFGHI", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 12*/ { 4, 11, "\177\177\177\177", 0, 0, 11, 27 }, // Max capacity ECC H, version 11, 4 bytes + /* 13*/ { 4, 11, "\177\177\177\177\177", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 14*/ { 2, 11, "\177\177\177\177\177\177", 0, 0, 11, 27 }, // Max capacity ECC M, version 11, 6 bytes + /* 15*/ { 2, 11, "\177\177\177\177\177\177\177", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 16*/ { 4, 11, "点茗", ZINT_WARN_NONCOMPLIANT, 0, 11, 27 }, // Max capacity ECC H, version 11, 2 kanji + /* 17*/ { 4, 11, "点茗点", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 18*/ { 2, 11, "点茗点", ZINT_WARN_NONCOMPLIANT, 0, 11, 27 }, // Max capacity ECC M, version 11, 3 kanji + /* 19*/ { 2, 11, "点茗点茗", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 20*/ { -1, 1, "12345", 0, 0, 7, 43 }, // ECC auto-set to M, version 1 (R7x43) + /* 21*/ { 2, 1, "12345", 0, 0, 7, 43 }, + /* 22*/ { 4, 1, "12345", 0, 0, 7, 43 }, // Max capacity ECC H, version 1, 5 numbers + /* 23*/ { 4, 1, "123456", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 24*/ { 2, 1, "123456789012", 0, 0, 7, 43 }, // Max capacity ECC M, version 1, 12 numbers + /* 25*/ { 2, 1, "1234567890123", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 26*/ { 4, 1, "ABC", 0, 0, 7, 43 }, // Max capacity ECC H, version 1, 3 letters + /* 27*/ { 4, 1, "ABCD", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 28*/ { 2, 1, "ABCDEFG", 0, 0, 7, 43 }, // Max capacity ECC M, version 1, 7 letters + /* 29*/ { 2, 1, "ABCDEFGH", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 30*/ { 4, 1, "\177\177", 0, 0, 7, 43 }, // Max capacity ECC H, version 1, 2 bytes + /* 31*/ { 4, 1, "\177\177\177", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 32*/ { 2, 1, "\177\177\177\177\177", 0, 0, 7, 43 }, // Max capacity ECC M, version 1, 5 bytes + /* 33*/ { 2, 1, "\177\177\177\177\177\177", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 34*/ { 4, 1, "点", ZINT_WARN_NONCOMPLIANT, 0, 7, 43 }, // Max capacity ECC H, version 1, 1 kanji + /* 35*/ { 4, 1, "点茗", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 36*/ { 2, 1, "点茗点", ZINT_WARN_NONCOMPLIANT, 0, 7, 43 }, // Max capacity ECC M, version 1, 3 kanji + /* 37*/ { 2, 1, "点茗点茗", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 38*/ { 4, 7, "12345678901234567890123", 0, 0, 9, 59 }, // Max capacity ECC H, version 7 (R9x59), 23 numbers + /* 39*/ { 4, 7, "123456789012345678901234", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 40*/ { 4, 7, "点茗点茗点茗", ZINT_WARN_NONCOMPLIANT, 0, 9, 59 }, // Max capacity ECC H, version 7, 6 kanji + /* 41*/ { 4, 7, "点茗点茗点茗点", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 42*/ { 4, 13, "点茗点茗点茗点茗", ZINT_WARN_NONCOMPLIANT, 0, 11, 59 }, // Max capacity ECC H, version 13 (R11x59), 8 kanji + /* 43*/ { 4, 13, "点茗点茗点茗点茗点", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 44*/ { 4, 20, "点茗点茗点茗点茗点茗点茗点茗点茗点", ZINT_WARN_NONCOMPLIANT, 0, 13, 77 }, // Max capacity ECC H, version 20 (R13x77), 17 kanji + /* 45*/ { 4, 20, "点茗点茗点茗点茗点茗点茗点茗点茗点茗", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 46*/ { 4, 26, "点茗点茗点茗点茗点茗点茗点茗点茗点点茗点茗点茗点点茗点茗", ZINT_WARN_NONCOMPLIANT, 0, 15, 99 }, // Max capacity ECC H, version 26 (R15x99), 28 kanji + /* 47*/ { 4, 26, "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 48*/ { 4, 32, "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗", ZINT_WARN_NONCOMPLIANT, 0, 17, 139 }, // Max capacity ECC H, version 32 (R17x139), 46 kanji + /* 49*/ { 4, 32, "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 50*/ { -1, 32, "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗", ZINT_WARN_NONCOMPLIANT, 0, 17, 139 }, // Max capacity ECC M, version 32, 92 kanji + /* 51*/ { 4, 32, "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点", ZINT_ERROR_TOO_LONG, -1, 0, 0 }, + /* 52*/ { -1, 33, "点茗点", ZINT_WARN_NONCOMPLIANT, 0, 7, 43 }, // ECC auto-set to M, version 33 (R7xAuto-width) auto-sets R7x43 + /* 53*/ { 4, 33, "点茗点", ZINT_WARN_NONCOMPLIANT, 0, 7, 59 }, // ECC set to H, version 33 (R7xAuto-width) auto-sets R7x59 + /* 54*/ { -1, 34, "点茗点", ZINT_WARN_NONCOMPLIANT, 0, 9, 43 }, // ECC auto-set to H, version 34 (R9xAuto-width) auto-sets R9x43 + /* 55*/ { -1, 35, "点茗点", ZINT_WARN_NONCOMPLIANT, 0, 11, 27 }, // ECC auto-set to M, version 35 (R11xAuto-width) auto-sets R11x27 + /* 56*/ { 4, 35, "点茗点茗点茗点", ZINT_WARN_NONCOMPLIANT, 0, 11, 59 }, // ECC set to H, version 35 (R11xAuto-width) auto-sets R11x59 + /* 57*/ { -1, 35, "点茗点茗点茗点", ZINT_WARN_NONCOMPLIANT, 0, 11, 43 }, // ECC auto-set to M, version 35 (R11xAuto-width) auto-sets R11x43 + /* 58*/ { -1, 36, "点茗点茗点茗点茗", ZINT_WARN_NONCOMPLIANT, 0, 13, 43 }, // ECC auto-set to M, version 36 (R13xAuto-width) auto-sets R13x43 + /* 59*/ { 4, 36, "点茗点茗点茗点茗", ZINT_WARN_NONCOMPLIANT, 0, 13, 59 }, // ECC set to H, version 36 (R13xAuto-width) auto-sets R13x59 + /* 60*/ { -1, 37, "点茗点茗点茗点茗点", ZINT_WARN_NONCOMPLIANT, 0, 15, 43 }, // ECC auto-set to M, version 37 (R15xAuto-width) auto-sets R15x43 + /* 61*/ { 4, 37, "点茗点茗点茗点茗点", ZINT_WARN_NONCOMPLIANT, 0, 15, 59 }, // ECC set to H, version 37 (R15xAuto-width) auto-sets R15x59 + /* 62*/ { -1, 38, "点茗点茗点茗点茗点茗点茗点茗点茗点茗", ZINT_WARN_NONCOMPLIANT, 0, 17, 43 }, // ECC auto-set to M, version 38 (R17xAuto-width) auto-sets R17x43 + /* 63*/ { 4, 38, "点茗点茗点茗点茗点茗点茗点茗点茗点茗", ZINT_WARN_NONCOMPLIANT, 0, 17, 77 }, // ECC set to H, version 38 (R17xAuto-width) auto-sets R17x77 + /* 64*/ { -1, 39, "点茗点", ZINT_ERROR_INVALID_OPTION, -1, 0, 0 }, + /* 65*/ { 4, -1, "点茗点", ZINT_WARN_NONCOMPLIANT, 0, 13, 27 }, // ECC set to H, auto-sets R13x27 + /* 66*/ { 4, -1, "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗", ZINT_WARN_NONCOMPLIANT, 0, 15, 99 }, // ECC set to H, auto-sets R15x99 (max capacity) + /* 67*/ { 4, -1, "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点", ZINT_WARN_NONCOMPLIANT, 0, 17, 99 }, // ECC set to H, auto-sets R17x99 + /* 68*/ { 4, -1, "点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗点茗", ZINT_WARN_NONCOMPLIANT, 0, 17, 139 }, // ECC set to H, auto-sets R17x139 (max capacity) }; int data_size = ARRAY_SIZE(data); int i, length, ret; @@ -4288,135 +5558,145 @@ static void test_rmqr_input(int index, int generate, int debug) { struct item { int input_mode; int eci; + int option_1; + int option_2; int option_3; char *data; int ret; int expected_eci; char *expected; + int bwipp_cmp; char *comment; }; // See test_qr_input() for details about test characters struct item data[] = { - /* 0*/ { UNICODE_MODE, 0, -1, "é", 0, 0, "67 A4 00 EC 11", "B1 (ISO 8859-1)" }, - /* 1*/ { UNICODE_MODE, 3, -1, "é", 0, 3, "70 36 7A 40 EC", "ECI-3 B1 (ISO 8859-1)" }, - /* 2*/ { UNICODE_MODE, 20, -1, "é", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", "é not in Shift JIS" }, - /* 3*/ { UNICODE_MODE, 26, -1, "é", 0, 26, "71 A6 B0 EA 40", "ECI-26 B2 (UTF-8)" }, - /* 4*/ { DATA_MODE, 0, -1, "é", 0, 0, "6B 0E A4 00 EC", "B2 (UTF-8)" }, - /* 5*/ { DATA_MODE, 0, -1, "\351", 0, 0, "67 A4 00 EC 11", "B1 (ISO 8859-1)" }, - /* 6*/ { UNICODE_MODE, 0, -1, "β", ZINT_WARN_NONCOMPLIANT, 0, "Warning 88 80 00 EC 11", "K1 (Shift JIS)" }, - /* 7*/ { UNICODE_MODE, 9, -1, "β", 0, 9, "70 96 78 80 EC", "ECI-9 B1 (ISO 8859-7)" }, - /* 8*/ { UNICODE_MODE, 20, -1, "β", 0, 20, "71 48 88 00 00", "ECI-20 K1 (Shift JIS)" }, - /* 9*/ { UNICODE_MODE, 26, -1, "β", 0, 26, "71 A6 B3 AC 80", "ECI-26 B2 (UTF-8)" }, - /* 10*/ { DATA_MODE, 0, -1, "β", 0, 0, "6B 3A C8 00 EC", "B2 (UTF-8)" }, - /* 11*/ { UNICODE_MODE, 0, -1, "ก", ZINT_WARN_USES_ECI, 13, "Warning 70 D6 68 40 EC", "ECI-13 B1 (ISO 8859-11)" }, - /* 12*/ { UNICODE_MODE, 13, -1, "ก", 0, 13, "70 D6 68 40 EC", "ECI-13 B1 (ISO 8859-11)" }, - /* 13*/ { UNICODE_MODE, 20, -1, "ก", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", "ก not in Shift JIS" }, - /* 14*/ { UNICODE_MODE, 26, -1, "ก", 0, 26, "71 A6 F8 2E 20 40 EC", "ECI-26 B3 (UTF-8)" }, - /* 15*/ { DATA_MODE, 0, -1, "ก", 0, 0, "6F 82 E2 04 00", "B3 (UTF-8)" }, - /* 16*/ { UNICODE_MODE, 0, -1, "Ж", ZINT_WARN_NONCOMPLIANT, 0, "Warning 88 91 C0 EC 11", "K1 (Shift JIS)" }, - /* 17*/ { UNICODE_MODE, 7, -1, "Ж", 0, 7, "70 76 6D 80 EC", "ECI-7 B1 (ISO 8859-5)" }, - /* 18*/ { UNICODE_MODE, 20, -1, "Ж", 0, 20, "71 48 89 1C 00", "ECI-20 K1 (Shift JIS)" }, - /* 19*/ { UNICODE_MODE, 26, -1, "Ж", 0, 26, "71 A6 B4 25 80", "ECI-26 B2 (UTF-8)" }, - /* 20*/ { DATA_MODE, 0, -1, "Ж", 0, 0, "6B 42 58 00 EC", "B2 (UTF-8)" }, - /* 21*/ { UNICODE_MODE, 0, -1, "ກ", ZINT_WARN_USES_ECI, 26, "Warning 71 A6 F8 2E A0 40 EC", "ECI-26 B3 (UTF-8)" }, - /* 22*/ { UNICODE_MODE, 20, -1, "ກ", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", "ກ not in Shift JIS" }, - /* 23*/ { UNICODE_MODE, 26, -1, "ກ", 0, 26, "71 A6 F8 2E A0 40 EC", "ECI-26 B3 (UTF-8)" }, - /* 24*/ { DATA_MODE, 0, -1, "ກ", 0, 0, "6F 82 EA 04 00", "B3 (UTF-8)" }, - /* 25*/ { UNICODE_MODE, 0, -1, "\\", 0, 0, "65 70 00 EC 11", "B1 (ASCII)" }, - /* 26*/ { UNICODE_MODE, 20, -1, "\\", 0, 20, "71 48 80 7C 00", "ECI-20 K1 (Shift JIS)" }, - /* 27*/ { UNICODE_MODE, 20, -1, "[", 0, 20, "71 46 56 C0 EC", "B1 (ASCII)" }, - /* 28*/ { UNICODE_MODE, 20, -1, "\177", 0, 20, "71 46 5F C0 EC", "ECI-20 B1 (ASCII)" }, - /* 29*/ { UNICODE_MODE, 0, -1, "¥", 0, 0, "66 94 00 EC 11", "B1 (ISO 8859-1) (same bytes as ・ Shift JIS below, so ambiguous)" }, - /* 30*/ { UNICODE_MODE, 3, -1, "¥", 0, 3, "70 36 69 40 EC", "ECI-3 B1 (ISO 8859-1)" }, - /* 31*/ { UNICODE_MODE, 20, -1, "¥", 0, 20, "71 46 57 00 EC", "ECI-20 B1 (Shift JIS) (to single-byte backslash codepoint 5C, so byte mode)" }, - /* 32*/ { UNICODE_MODE, 26, -1, "¥", 0, 26, "71 A6 B0 A9 40", "ECI-26 B2 (UTF-8)" }, - /* 33*/ { DATA_MODE, 0, -1, "¥", 0, 0, "6B 0A 94 00 EC", "B2 (UTF-8)" }, - /* 34*/ { UNICODE_MODE, 0, -1, "・", ZINT_WARN_NONCOMPLIANT, 0, "Warning 66 94 00 EC 11", "B1 (Shift JIS) single-byte codepoint A5 (same bytes as ¥ ISO 8859-1 above, so ambiguous)" }, - /* 35*/ { UNICODE_MODE, 3, -1, "・", ZINT_ERROR_INVALID_DATA, -1, "Error 564: Invalid character in input data for ECI 3", "" }, - /* 36*/ { UNICODE_MODE, 20, -1, "・", 0, 20, "71 46 69 40 EC", "ECI-20 B1 (Shift JIS) single-byte codepoint A5" }, - /* 37*/ { UNICODE_MODE, 26, -1, "・", 0, 26, "71 A6 FB EF 69 40 EC", "ECI-26 B3 (UTF-8)" }, - /* 38*/ { DATA_MODE, 0, -1, "・", 0, 0, "6F BE F6 94 00", "B3 (UTF-8)" }, - /* 39*/ { UNICODE_MODE, 0, -1, "¿", 0, 0, "66 FC 00 EC 11", "B1 (ISO 8859-1) (same bytes as ソ Shift JIS below, so ambiguous)" }, - /* 40*/ { UNICODE_MODE, 3, -1, "¿", 0, 3, "70 36 6F C0 EC", "ECI-3 B1 (ISO 8859-1)" }, - /* 41*/ { UNICODE_MODE, 20, -1, "¿", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", "¿ not in Shift JIS" }, - /* 42*/ { UNICODE_MODE, 26, -1, "¿", 0, 26, "71 A6 B0 AF C0", "ECI-26 B2 (UTF-8)" }, - /* 43*/ { DATA_MODE, 0, -1, "¿", 0, 0, "6B 0A FC 00 EC", "B2 (UTF-8)" }, - /* 44*/ { UNICODE_MODE, 0, -1, "ソ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 66 FC 00 EC 11", "B1 (Shift JIS) single-byte codepoint BF (same bytes as ¿ ISO 8859-1 above, so ambiguous)" }, - /* 45*/ { UNICODE_MODE, 3, -1, "ソ", ZINT_ERROR_INVALID_DATA, -1, "Error 564: Invalid character in input data for ECI 3", "" }, - /* 46*/ { UNICODE_MODE, 20, -1, "ソ", 0, 20, "71 46 6F C0 EC", "ECI-20 B1 (Shift JIS) single-byte codepoint BF" }, - /* 47*/ { UNICODE_MODE, 26, -1, "ソ", 0, 26, "71 A6 FB EF 6F C0 EC", "ECI-26 B3 (UTF-8)" }, - /* 48*/ { DATA_MODE, 0, -1, "ソ", 0, 0, "6F BE F6 FC 00", "B3 (UTF-8)" }, - /* 49*/ { UNICODE_MODE, 0, -1, "~", 0, 0, "65 F8 00 EC 11", "B1 (ASCII) (same bytes as ‾ Shift JIS below, so ambiguous)" }, - /* 50*/ { UNICODE_MODE, 3, -1, "~", 0, 3, "70 36 5F 80 EC", "ECI-3 B1 (ASCII)" }, - /* 51*/ { UNICODE_MODE, 20, -1, "~", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", "tilde not in Shift JIS (codepoint used for overline)" }, - /* 52*/ { UNICODE_MODE, 0, -1, "‾", ZINT_WARN_NONCOMPLIANT, 0, "Warning 65 F8 00 EC 11", "B1 (Shift JIS) single-byte codepoint 7E (same bytes as ~ ASCII above, so ambiguous)" }, - /* 53*/ { UNICODE_MODE, 3, -1, "‾", ZINT_ERROR_INVALID_DATA, -1, "Error 564: Invalid character in input data for ECI 3", "" }, - /* 54*/ { UNICODE_MODE, 20, -1, "‾", 0, 20, "71 46 5F 80 EC", "ECI-20 B1 (Shift JIS) (to single-byte tilde codepoint 7E, so byte mode)" }, - /* 55*/ { UNICODE_MODE, 26, -1, "‾", 0, 26, "71 A6 F8 A0 2F 80 EC", "ECI-26 B3 (UTF-8)" }, - /* 56*/ { DATA_MODE, 0, -1, "‾", 0, 0, "6F 8A 02 F8 00", "B3 (UTF-8)" }, - /* 57*/ { UNICODE_MODE, 0, -1, "点", ZINT_WARN_NONCOMPLIANT, 0, "Warning 8B 67 C0 EC 11", "K1 (Shift JIS)" }, - /* 58*/ { UNICODE_MODE, 3, -1, "点", ZINT_ERROR_INVALID_DATA, -1, "Error 564: Invalid character in input data for ECI 3", "" }, - /* 59*/ { UNICODE_MODE, 20, -1, "点", 0, 20, "71 48 B6 7C 00", "ECI-20 K1 (Shift JIS)" }, - /* 60*/ { UNICODE_MODE, 26, -1, "点", 0, 26, "71 A6 F9 E0 AE 40 EC", "ECI-26 B3 (UTF-8)" }, - /* 61*/ { DATA_MODE, 0, -1, "点", 0, 0, "6F 9E 0A E4 00", "B3 (UTF-8)" }, - /* 62*/ { DATA_MODE, 0, -1, "\223\137", 0, 0, "6A 4D 7C 00 EC", "B2 (Shift JIS) (not full multibyte)" }, - /* 63*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "\223\137", 0, 0, "8B 67 C0 EC 11", "K1 (Shift JIS)" }, - /* 64*/ { UNICODE_MODE, 0, -1, "¥・点", ZINT_WARN_NONCOMPLIANT, 0, "Warning 71 72 96 4D 7C", "B4 (Shift JIS) (optimized to byte mode only)" }, - /* 65*/ { UNICODE_MODE, 3, -1, "¥・点", ZINT_ERROR_INVALID_DATA, -1, "Error 564: Invalid character in input data for ECI 3", "" }, - /* 66*/ { UNICODE_MODE, 20, -1, "¥・点", 0, 20, "71 47 17 29 64 D7 C0", "ECI-20 B4 (Shift JIS)" }, - /* 67*/ { UNICODE_MODE, 26, -1, "¥・点", 0, 26, "71 A7 18 54 BD F7 B4 BC F0 57 20 EC", "ECI-26 B8 (UTF-8)" }, - /* 68*/ { DATA_MODE, 0, -1, "\134\245\223\137", 0, 0, "71 72 96 4D 7C", "B8 (Shift JIS)" }, - /* 69*/ { DATA_MODE, 0, -1, "¥・点", 0, 0, "71 85 4B DF 7B 4B CF 05 72 00 EC 11", "B8 (UTF-8)" }, - /* 70*/ { UNICODE_MODE, 0, -1, "点茗", ZINT_WARN_NONCOMPLIANT, 0, "Warning 93 67 F5 54 00", "K2 (Shift JIS)" }, - /* 71*/ { UNICODE_MODE, 0, -1, "点茗テ点茗テソ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 8C D9 FD 55 06 95 B3 FA AA 0D 2B 0D F8 EC 11 EC 11 EC 11", "K6 B1 (Shift JIS)" }, - /* 72*/ { DATA_MODE, 0, -1, "\223\137\344\252\203\145\223\137\344\252\203\145\277", 0, 0, "6D 93 5F E4 AA 83 65 93 5F E4 AA 83 65 BF 00 EC 11 EC 11", "B13 (Shift JIS)" }, - /* 73*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "\223\137\344\252\203\145\223\137\344\252\203\145\277", 0, 0, "8C D9 FD 55 06 95 B3 FA AA 0D 2B 0D F8 EC 11 EC 11 EC 11", "K6 B1 (Shift JIS) (full multibyte)" }, - /* 74*/ { UNICODE_MODE, 0, -1, "áA", 0, 0, "6B 85 04 00 EC", "B2 (ISO 8859-1)" }, - /* 75*/ { UNICODE_MODE, 0, ZINT_FULL_MULTIBYTE, "áA", 0, 0, "8E 00 40 EC 11", "K1 (ISO 8859-1) (full multibyte)" }, - /* 76*/ { UNICODE_MODE, 0, -1, "A0B1C2D3E4F5G6H7I8J9KLMNOPQRSTUVWXYZ $%*+-./:", 0, 0, "(33) 56 9C 23 E0 87 92 62 7A 55 0B 59 82 33 26 C0 E6 5F AC 51 95 B4 26 B2 DC 1C 3B 9E 76", "A45" }, - /* 77*/ { UNICODE_MODE, 0, -1, "˘", ZINT_WARN_USES_ECI, 4, "Warning 70 46 68 80 EC", "ECI-4 B1 (ISO 8859-2)" }, - /* 78*/ { UNICODE_MODE, 4, -1, "˘", 0, 4, "70 46 68 80 EC", "ECI-4 B1 (ISO 8859-2)" }, - /* 79*/ { UNICODE_MODE, 0, -1, "Ħ", ZINT_WARN_USES_ECI, 5, "Warning 70 56 68 40 EC", "ECI-5 B1 (ISO 8859-3)" }, - /* 80*/ { UNICODE_MODE, 5, -1, "Ħ", 0, 5, "70 56 68 40 EC", "ECI-5 B1 (ISO 8859-3)" }, - /* 81*/ { UNICODE_MODE, 0, -1, "ĸ", ZINT_WARN_USES_ECI, 6, "Warning 70 66 68 80 EC", "ECI-6 B1 (ISO 8859-4)" }, - /* 82*/ { UNICODE_MODE, 6, -1, "ĸ", 0, 6, "70 66 68 80 EC", "ECI-6 B1 (ISO 8859-4)" }, - /* 83*/ { UNICODE_MODE, 0, -1, "Ș", ZINT_WARN_USES_ECI, 18, "Warning 71 26 6A 80 EC", "ECI-18 B1 (ISO 8859-16)" }, - /* 84*/ { UNICODE_MODE, 18, -1, "Ș", 0, 18, "71 26 6A 80 EC", "ECI-18 B1 (ISO 8859-16)" }, - /* 85*/ { UNICODE_MODE, 0, -1, "テ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 88 69 40 EC 11", "K1 (SHIFT JIS)" }, - /* 86*/ { UNICODE_MODE, 20, -1, "テ", 0, 20, "71 48 86 94 00", "ECI-20 K1 (SHIFT JIS)" }, - /* 87*/ { UNICODE_MODE, 20, -1, "テテ", 0, 20, "71 49 06 94 34 A0 EC", "ECI-20 K2 (SHIFT JIS)" }, - /* 88*/ { UNICODE_MODE, 20, -1, "\\\\", 0, 20, "71 49 00 7C 03 E0 EC", "ECI-20 K2 (SHIFT JIS)" }, - /* 89*/ { UNICODE_MODE, 0, -1, "…", ZINT_WARN_NONCOMPLIANT, 0, "Warning 88 08 C0 EC 11", "K1 (SHIFT JIS)" }, - /* 90*/ { UNICODE_MODE, 21, -1, "…", 0, 21, "71 56 61 40 EC", "ECI-21 B1 (Win 1250)" }, - /* 91*/ { UNICODE_MODE, 0, -1, "Ґ", ZINT_WARN_USES_ECI, 22, "Warning 71 66 69 40 EC", "ECI-22 B1 (Win 1251)" }, - /* 92*/ { UNICODE_MODE, 22, -1, "Ґ", 0, 22, "71 66 69 40 EC", "ECI-22 B1 (Win 1251)" }, - /* 93*/ { UNICODE_MODE, 0, -1, "˜", ZINT_WARN_USES_ECI, 23, "Warning 71 76 66 00 EC", "ECI-23 B1 (Win 1252)" }, - /* 94*/ { UNICODE_MODE, 23, -1, "˜", 0, 23, "71 76 66 00 EC", "ECI-23 B1 (Win 1252)" }, - /* 95*/ { UNICODE_MODE, 24, -1, "پ", 0, 24, "71 86 60 40 EC", "ECI-24 B1 (Win 1256)" }, - /* 96*/ { UNICODE_MODE, 0, -1, "က", ZINT_WARN_USES_ECI, 26, "Warning 71 A6 F8 60 20 00 EC", "ECI-26 B3 (UTF-8)" }, - /* 97*/ { UNICODE_MODE, 25, -1, "က", 0, 25, "71 96 84 00 00", "ECI-25 B2 (UCS-2BE)" }, - /* 98*/ { UNICODE_MODE, 25, -1, "ကက", 0, 25, "71 97 04 00 04 00 00", "ECI-25 B4 (UCS-2BE)" }, - /* 99*/ { UNICODE_MODE, 25, -1, "12", 0, 25, "71 97 00 0C 40 0C 80", "ECI-25 B4 (UCS-2BE ASCII)" }, - /*100*/ { UNICODE_MODE, 27, -1, "@", 0, 27, "71 B6 50 00 EC", "ECI-27 B1 (ASCII)" }, - /*101*/ { UNICODE_MODE, 0, -1, "龘", ZINT_WARN_USES_ECI, 26, "Warning 71 A6 FA 6F A6 00 EC", "ECI-26 B3 (UTF-8)" }, - /*102*/ { UNICODE_MODE, 28, -1, "龘", 0, 28, "71 C6 BE 75 40", "ECI-28 B2 (Big5)" }, - /*103*/ { UNICODE_MODE, 28, -1, "龘龘", 0, 28, "71 C7 3E 75 7E 75 40", "ECI-28 B4 (Big5)" }, - /*104*/ { UNICODE_MODE, 0, -1, "齄", ZINT_WARN_USES_ECI, 26, "Warning 71 A6 FA 6F 61 00 EC", "ECI-26 B3 (UTF-8)" }, - /*105*/ { UNICODE_MODE, 29, -1, "齄", 0, 29, "71 D6 BD FF 80", "ECI-29 B2 (GB 2312)" }, - /*106*/ { UNICODE_MODE, 29, -1, "齄齄", 0, 29, "71 D7 3D FF BD FF 80", "ECI-29 B4 (GB 2312)" }, - /*107*/ { UNICODE_MODE, 0, -1, "가", ZINT_WARN_USES_ECI, 26, "Warning 71 A6 FA AC 20 00 EC", "ECI-26 B3 (UTF-8)" }, - /*108*/ { UNICODE_MODE, 30, -1, "가", 0, 30, "71 E6 AC 28 40", "ECI-30 B2 (EUC-KR)" }, - /*109*/ { UNICODE_MODE, 30, -1, "가가", 0, 30, "71 E7 2C 28 6C 28 40", "ECI-30 B4 (EUC-KR)" }, - /*110*/ { UNICODE_MODE, 170, -1, "?", 0, 170, "78 0A A6 4F C0", "ECI-170 B1 (ASCII invariant)" }, - /*111*/ { DATA_MODE, 899, -1, "\200", 0, 899, "78 38 36 60 00", "ECI-899 B1 (8-bit binary)" }, - /*112*/ { UNICODE_MODE, 900, -1, "é", 0, 900, "78 38 46 B0 EA 40 EC", "ECI-900 B2 (no conversion)" }, - /*113*/ { UNICODE_MODE, 16384, -1, "é", 0, 16384, "7C 04 00 06 B0 EA 40", "ECI-16384 B2 (no conversion)" }, + /* 0*/ { UNICODE_MODE, 0, 4, 11, -1, "é", 0, 0, "67 A4 00 EC 11", 1, "B1 (ISO 8859-1)" }, + /* 1*/ { UNICODE_MODE, 3, 4, 11, -1, "é", 0, 3, "E0 6C F4 80 EC", 1, "ECI-3 B1 (ISO 8859-1)" }, + /* 2*/ { UNICODE_MODE, 20, -1, -1, -1, "é", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", 1, "é not in Shift JIS" }, + /* 3*/ { UNICODE_MODE, 26, 4, 11, -1, "é", 0, 26, "E3 4D 61 D4 80", 1, "ECI-26 B2 (UTF-8)" }, + /* 4*/ { DATA_MODE, 0, 4, 11, -1, "é", 0, 0, "6B 0E A4 00 EC", 1, "B2 (UTF-8)" }, + /* 5*/ { DATA_MODE, 0, 4, 11, -1, "\351", 0, 0, "67 A4 00 EC 11", 1, "B1 (ISO 8859-1)" }, + /* 6*/ { UNICODE_MODE, 0, 4, 11, -1, "β", ZINT_WARN_NONCOMPLIANT, 0, "Warning 88 80 00 EC 11", 1, "K1 (Shift JIS)" }, + /* 7*/ { UNICODE_MODE, 9, 4, 11, -1, "β", 0, 9, "E1 2C F1 00 EC", 1, "ECI-9 B1 (ISO 8859-7)" }, + /* 8*/ { UNICODE_MODE, 20, 4, 11, -1, "β", 0, 20, "E2 91 10 00 EC", 1, "ECI-20 K1 (Shift JIS)" }, + /* 9*/ { UNICODE_MODE, 26, 4, 11, -1, "β", 0, 26, "E3 4D 67 59 00", 1, "ECI-26 B2 (UTF-8)" }, + /* 10*/ { DATA_MODE, 0, 4, 11, -1, "β", 0, 0, "6B 3A C8 00 EC", 1, "B2 (UTF-8)" }, + /* 11*/ { UNICODE_MODE, 0, 4, 11, -1, "ก", ZINT_WARN_USES_ECI, 13, "Warning E1 AC D0 80 EC", 1, "ECI-13 B1 (ISO 8859-11)" }, + /* 12*/ { UNICODE_MODE, 13, 4, 11, -1, "ก", 0, 13, "E1 AC D0 80 EC", 1, "ECI-13 B1 (ISO 8859-11)" }, + /* 13*/ { UNICODE_MODE, 20, -1, -1, -1, "ก", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", 1, "ก not in Shift JIS" }, + /* 14*/ { UNICODE_MODE, 26, 2, 11, -1, "ก", 0, 26, "E3 4D F0 5C 40 80 EC", 1, "ECI-26 B3 (UTF-8)" }, + /* 15*/ { DATA_MODE, 0, 4, 11, -1, "ก", 0, 0, "6F 82 E2 04 00", 1, "B3 (UTF-8)" }, + /* 16*/ { UNICODE_MODE, 0, 4, 11, -1, "Ж", ZINT_WARN_NONCOMPLIANT, 0, "Warning 88 91 C0 EC 11", 1, "K1 (Shift JIS)" }, + /* 17*/ { UNICODE_MODE, 7, 4, 11, -1, "Ж", 0, 7, "E0 EC DB 00 EC", 1, "ECI-7 B1 (ISO 8859-5)" }, + /* 18*/ { UNICODE_MODE, 20, 4, 11, -1, "Ж", 0, 20, "E2 91 12 38 EC", 1, "ECI-20 K1 (Shift JIS)" }, + /* 19*/ { UNICODE_MODE, 26, 4, 11, -1, "Ж", 0, 26, "E3 4D 68 4B 00", 1, "ECI-26 B2 (UTF-8)" }, + /* 20*/ { DATA_MODE, 0, 4, 11, -1, "Ж", 0, 0, "6B 42 58 00 EC", 1, "B2 (UTF-8)" }, + /* 21*/ { UNICODE_MODE, 0, 2, 11, -1, "ກ", ZINT_WARN_USES_ECI, 26, "Warning E3 4D F0 5D 40 80 EC", 1, "ECI-26 B3 (UTF-8)" }, + /* 22*/ { UNICODE_MODE, 20, -1, -1, -1, "ກ", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", 1, "ກ not in Shift JIS" }, + /* 23*/ { UNICODE_MODE, 26, 2, 11, -1, "ກ", 0, 26, "E3 4D F0 5D 40 80 EC", 1, "ECI-26 B3 (UTF-8)" }, + /* 24*/ { DATA_MODE, 0, 4, 11, -1, "ກ", 0, 0, "6F 82 EA 04 00", 1, "B3 (UTF-8)" }, + /* 25*/ { UNICODE_MODE, 0, 4, 11, -1, "\\", 0, 0, "65 70 00 EC 11", 1, "B1 (ASCII)" }, + /* 26*/ { UNICODE_MODE, 20, 4, 11, -1, "\\", 0, 20, "E2 91 00 F8 EC", 1, "ECI-20 K1 (Shift JIS)" }, + /* 27*/ { UNICODE_MODE, 20, 4, 11, -1, "[", 0, 20, "E2 8C AD 80 EC", 1, "B1 (ASCII)" }, + /* 28*/ { UNICODE_MODE, 20, 4, 11, -1, "\177", 0, 20, "E2 8C BF 80 EC", 1, "ECI-20 B1 (ASCII)" }, + /* 29*/ { UNICODE_MODE, 0, 4, 11, -1, "¥", 0, 0, "66 94 00 EC 11", 1, "B1 (ISO 8859-1) (same bytes as ・ Shift JIS below, so ambiguous)" }, + /* 30*/ { UNICODE_MODE, 3, 4, 11, -1, "¥", 0, 3, "E0 6C D2 80 EC", 1, "ECI-3 B1 (ISO 8859-1)" }, + /* 31*/ { UNICODE_MODE, 20, 4, 11, -1, "¥", 0, 20, "E2 8C AE 00 EC", 1, "ECI-20 B1 (Shift JIS) (to single-byte backslash codepoint 5C, so byte mode)" }, + /* 32*/ { UNICODE_MODE, 26, 4, 11, -1, "¥", 0, 26, "E3 4D 61 52 80", 1, "ECI-26 B2 (UTF-8)" }, + /* 33*/ { DATA_MODE, 0, 4, 11, -1, "¥", 0, 0, "6B 0A 94 00 EC", 1, "B2 (UTF-8)" }, + /* 34*/ { UNICODE_MODE, 0, 4, 11, -1, "・", ZINT_WARN_NONCOMPLIANT, 0, "Warning 66 94 00 EC 11", 1, "B1 (Shift JIS) single-byte codepoint A5 (same bytes as ¥ ISO 8859-1 above, so ambiguous)" }, + /* 35*/ { UNICODE_MODE, 3, -1, -1, -1, "・", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", 1, "" }, + /* 36*/ { UNICODE_MODE, 20, 4, 11, -1, "・", 0, 20, "E2 8C D2 80 EC", 1, "ECI-20 B1 (Shift JIS) single-byte codepoint A5" }, + /* 37*/ { UNICODE_MODE, 26, 2, 11, -1, "・", 0, 26, "E3 4D F7 DE D2 80 EC", 1, "ECI-26 B3 (UTF-8)" }, + /* 38*/ { DATA_MODE, 0, 4, 11, -1, "・", 0, 0, "6F BE F6 94 00", 1, "B3 (UTF-8)" }, + /* 39*/ { UNICODE_MODE, 0, 4, 11, -1, "¿", 0, 0, "66 FC 00 EC 11", 1, "B1 (ISO 8859-1) (same bytes as ソ Shift JIS below, so ambiguous)" }, + /* 40*/ { UNICODE_MODE, 3, 4, 11, -1, "¿", 0, 3, "E0 6C DF 80 EC", 1, "ECI-3 B1 (ISO 8859-1)" }, + /* 41*/ { UNICODE_MODE, 20, 4, 11, -1, "¿", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", 1, "¿ not in Shift JIS" }, + /* 42*/ { UNICODE_MODE, 26, 4, 11, -1, "¿", 0, 26, "E3 4D 61 5F 80", 1, "ECI-26 B2 (UTF-8)" }, + /* 43*/ { DATA_MODE, 0, 4, 11, -1, "¿", 0, 0, "6B 0A FC 00 EC", 1, "B2 (UTF-8)" }, + /* 44*/ { UNICODE_MODE, 0, 4, 11, -1, "ソ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 66 FC 00 EC 11", 1, "B1 (Shift JIS) single-byte codepoint BF (same bytes as ¿ ISO 8859-1 above, so ambiguous)" }, + /* 45*/ { UNICODE_MODE, 3, 4, 11, -1, "ソ", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", 1, "" }, + /* 46*/ { UNICODE_MODE, 20, 4, 11, -1, "ソ", 0, 20, "E2 8C DF 80 EC", 1, "ECI-20 B1 (Shift JIS) single-byte codepoint BF" }, + /* 47*/ { UNICODE_MODE, 26, 2, 11, -1, "ソ", 0, 26, "E3 4D F7 DE DF 80 EC", 1, "ECI-26 B3 (UTF-8)" }, + /* 48*/ { DATA_MODE, 0, 4, 11, -1, "ソ", 0, 0, "6F BE F6 FC 00", 1, "B3 (UTF-8)" }, + /* 49*/ { UNICODE_MODE, 0, 4, 11, -1, "~", 0, 0, "65 F8 00 EC 11", 1, "B1 (ASCII) (same bytes as ‾ Shift JIS below, so ambiguous)" }, + /* 50*/ { UNICODE_MODE, 3, 4, 11, -1, "~", 0, 3, "E0 6C BF 00 EC", 1, "ECI-3 B1 (ASCII)" }, + /* 51*/ { UNICODE_MODE, 20, 4, 11, -1, "~", ZINT_ERROR_INVALID_DATA, -1, "Error 800: Invalid character in input data", 1, "tilde not in Shift JIS (codepoint used for overline)" }, + /* 52*/ { UNICODE_MODE, 0, 4, 11, -1, "‾", ZINT_WARN_NONCOMPLIANT, 0, "Warning 65 F8 00 EC 11", 1, "B1 (Shift JIS) single-byte codepoint 7E (same bytes as ~ ASCII above, so ambiguous)" }, + /* 53*/ { UNICODE_MODE, 3, 4, 11, -1, "‾", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", 1, "" }, + /* 54*/ { UNICODE_MODE, 20, 4, 11, -1, "‾", 0, 20, "E2 8C BF 00 EC", 1, "ECI-20 B1 (Shift JIS) (to single-byte tilde codepoint 7E, so byte mode)" }, + /* 55*/ { UNICODE_MODE, 26, 2, 11, -1, "‾", 0, 26, "E3 4D F1 40 5F 00 EC", 1, "ECI-26 B3 (UTF-8)" }, + /* 56*/ { DATA_MODE, 0, 4, 11, -1, "‾", 0, 0, "6F 8A 02 F8 00", 1, "B3 (UTF-8)" }, + /* 57*/ { UNICODE_MODE, 0, 4, 11, -1, "点", ZINT_WARN_NONCOMPLIANT, 0, "Warning 8B 67 C0 EC 11", 1, "K1 (Shift JIS)" }, + /* 58*/ { UNICODE_MODE, 3, 4, 11, -1, "点", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", 1, "" }, + /* 59*/ { UNICODE_MODE, 20, 4, 11, -1, "点", 0, 20, "E2 91 6C F8 EC", 1, "ECI-20 K1 (Shift JIS)" }, + /* 60*/ { UNICODE_MODE, 26, 2, 11, -1, "点", 0, 26, "E3 4D F3 C1 5C 80 EC", 1, "ECI-26 B3 (UTF-8)" }, + /* 61*/ { DATA_MODE, 0, 4, 11, -1, "点", 0, 0, "6F 9E 0A E4 00", 1, "B3 (UTF-8)" }, + /* 62*/ { DATA_MODE, 0, 4, 11, -1, "\223\137", 0, 0, "6A 4D 7C 00 EC", 0, "B2 (Shift JIS) (not full multibyte); BWIPP uses Kanji (ZINT_FULL_MULTIBYTE) mode, see below)" }, + /* 63*/ { DATA_MODE, 0, 4, 11, ZINT_FULL_MULTIBYTE, "\223\137", 0, 0, "8B 67 C0 EC 11", 1, "K1 (Shift JIS)" }, + /* 64*/ { UNICODE_MODE, 0, 4, 11, -1, "¥・点", ZINT_WARN_NONCOMPLIANT, 0, "Warning 71 72 96 4D 7C", 1, "B4 (Shift JIS) (optimized to byte mode only)" }, + /* 65*/ { UNICODE_MODE, 3, -1, -1, -1, "¥・点", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid character in input data for ECI 3", 1, "" }, + /* 66*/ { UNICODE_MODE, 20, 2, 11, -1, "¥・点", 0, 20, "E2 8E 2E 52 C9 AF 80", 1, "ECI-20 B4 (Shift JIS)" }, + /* 67*/ { UNICODE_MODE, 26, 2, 17, -1, "¥・点", 0, 26, "E3 4E 30 A9 7B EF 69 79 E0 AE 40 EC", 1, "ECI-26 B8 (UTF-8)" }, + /* 68*/ { DATA_MODE, 0, 4, 11, -1, "\134\245\223\137", 0, 0, "71 72 96 4D 7C", 1, "B8 (Shift JIS)" }, + /* 69*/ { DATA_MODE, 0, 2, 17, -1, "¥・点", 0, 0, "71 85 4B DF 7B 4B CF 05 72 00 EC 11", 1, "B8 (UTF-8)" }, + /* 70*/ { UNICODE_MODE, 0, 4, 11, -1, "点茗", ZINT_WARN_NONCOMPLIANT, 0, "Warning 93 67 F5 54 00", 1, "K2 (Shift JIS)" }, + /* 71*/ { UNICODE_MODE, 0, 2, 12, -1, "点茗テ点茗テソ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 8C D9 FD 55 06 95 B3 FA AA 0D 2B 0D F8 EC 11 EC 11 EC 11", 1, "K6 B1 (Shift JIS)" }, + /* 72*/ { DATA_MODE, 0, 2, 12, -1, "\223\137\344\252\203\145\223\137\344\252\203\145\277", 0, 0, "6D 93 5F E4 AA 83 65 93 5F E4 AA 83 65 BF 00 EC 11 EC 11", 0, "B13 (Shift JIS); BWIPP uses Kanji (ZINT_FULL_MULTIBYTE) mode, see below)" }, + /* 73*/ { DATA_MODE, 0, 2, 12, ZINT_FULL_MULTIBYTE, "\223\137\344\252\203\145\223\137\344\252\203\145\277", 0, 0, "8C D9 FD 55 06 95 B3 FA AA 0D 2B 0D F8 EC 11 EC 11 EC 11", 1, "K6 B1 (Shift JIS) (full multibyte)" }, + /* 74*/ { UNICODE_MODE, 0, 4, 11, -1, "áA", 0, 0, "6B 85 04 00 EC", 0, "B2 (ISO 8859-1); BWIPP uses Kanji (ZINT_FULL_MULTIBYTE) mode, see below)" }, + /* 75*/ { UNICODE_MODE, 0, 4, 11, ZINT_FULL_MULTIBYTE, "áA", 0, 0, "8E 00 40 EC 11", 1, "K1 (ISO 8859-1) (full multibyte)" }, + /* 76*/ { UNICODE_MODE, 0, 2, 23, -1, "A0B1C2D3E4F5G6H7I8J9KLMNOPQRSTUVWXYZ $%*+-./:", 0, 0, "(33) 56 9C 23 E0 87 92 62 7A 55 0B 59 82 33 26 C0 E6 5F AC 51 95 B4 26 B2 DC 1C 3B 9E 76", 1, "A45" }, + /* 77*/ { UNICODE_MODE, 0, 4, 11, -1, "˘", ZINT_WARN_USES_ECI, 4, "Warning E0 8C D1 00 EC", 1, "ECI-4 B1 (ISO 8859-2)" }, + /* 78*/ { UNICODE_MODE, 4, 4, 11, -1, "˘", 0, 4, "E0 8C D1 00 EC", 1, "ECI-4 B1 (ISO 8859-2)" }, + /* 79*/ { UNICODE_MODE, 0, 4, 11, -1, "Ħ", ZINT_WARN_USES_ECI, 5, "Warning E0 AC D0 80 EC", 1, "ECI-5 B1 (ISO 8859-3)" }, + /* 80*/ { UNICODE_MODE, 5, 4, 11, -1, "Ħ", 0, 5, "E0 AC D0 80 EC", 1, "ECI-5 B1 (ISO 8859-3)" }, + /* 81*/ { UNICODE_MODE, 0, 4, 11, -1, "ĸ", ZINT_WARN_USES_ECI, 6, "Warning E0 CC D1 00 EC", 1, "ECI-6 B1 (ISO 8859-4)" }, + /* 82*/ { UNICODE_MODE, 6, 4, 11, -1, "ĸ", 0, 6, "E0 CC D1 00 EC", 1, "ECI-6 B1 (ISO 8859-4)" }, + /* 83*/ { UNICODE_MODE, 0, 4, 11, -1, "Ș", ZINT_WARN_USES_ECI, 18, "Warning E2 4C D5 00 EC", 1, "ECI-18 B1 (ISO 8859-16)" }, + /* 84*/ { UNICODE_MODE, 18, 4, 11, -1, "Ș", 0, 18, "E2 4C D5 00 EC", 1, "ECI-18 B1 (ISO 8859-16)" }, + /* 85*/ { UNICODE_MODE, 0, 4, 11, -1, "テ", ZINT_WARN_NONCOMPLIANT, 0, "Warning 88 69 40 EC 11", 1, "K1 (SHIFT JIS)" }, + /* 86*/ { UNICODE_MODE, 20, 4, 11, -1, "テ", 0, 20, "E2 91 0D 28 EC", 1, "ECI-20 K1 (SHIFT JIS)" }, + /* 87*/ { UNICODE_MODE, 20, 2, 11, -1, "テテ", 0, 20, "E2 92 0D 28 69 40 EC", 1, "ECI-20 K2 (SHIFT JIS)" }, + /* 88*/ { UNICODE_MODE, 20, 2, 11, -1, "\\\\", 0, 20, "E2 92 00 F8 07 C0 EC", 1, "ECI-20 K2 (SHIFT JIS)" }, + /* 89*/ { UNICODE_MODE, 0, 4, 11, -1, "…", ZINT_WARN_NONCOMPLIANT, 0, "Warning 88 08 C0 EC 11", 1, "K1 (SHIFT JIS)" }, + /* 90*/ { UNICODE_MODE, 21, 4, 11, -1, "…", 0, 21, "E2 AC C2 80 EC", 1, "ECI-21 B1 (Win 1250)" }, + /* 91*/ { UNICODE_MODE, 0, 4, 11, -1, "Ґ", ZINT_WARN_USES_ECI, 22, "Warning E2 CC D2 80 EC", 1, "ECI-22 B1 (Win 1251)" }, + /* 92*/ { UNICODE_MODE, 22, 4, 11, -1, "Ґ", 0, 22, "E2 CC D2 80 EC", 1, "ECI-22 B1 (Win 1251)" }, + /* 93*/ { UNICODE_MODE, 0, 4, 11, -1, "˜", ZINT_WARN_USES_ECI, 23, "Warning E2 EC CC 00 EC", 1, "ECI-23 B1 (Win 1252)" }, + /* 94*/ { UNICODE_MODE, 23, 4, 11, -1, "˜", 0, 23, "E2 EC CC 00 EC", 1, "ECI-23 B1 (Win 1252)" }, + /* 95*/ { UNICODE_MODE, 24, 4, 11, -1, "پ", 0, 24, "E3 0C C0 80 EC", 1, "ECI-24 B1 (Win 1256)" }, + /* 96*/ { UNICODE_MODE, 0, 2, 11, -1, "က", ZINT_WARN_USES_ECI, 26, "Warning E3 4D F0 C0 40 00 EC", 1, "ECI-26 B3 (UTF-8)" }, + /* 97*/ { UNICODE_MODE, 25, 4, 11, -1, "က", 0, 25, "E3 2D 08 00 00", 1, "ECI-25 B2 (UCS-2BE)" }, + /* 98*/ { UNICODE_MODE, 25, 2, 11, -1, "ကက", 0, 25, "E3 2E 08 00 08 00 00", 1, "ECI-25 B4 (UCS-2BE)" }, + /* 99*/ { UNICODE_MODE, 25, 2, 11, -1, "12", 0, 25, "E3 2E 00 18 80 19 00", 1, "ECI-25 B4 (UCS-2BE ASCII)" }, + /*100*/ { UNICODE_MODE, 27, 4, 11, -1, "@", 0, 27, "E3 6C A0 00 EC", 1, "ECI-27 B1 (ASCII)" }, + /*101*/ { UNICODE_MODE, 0, 2, 11, -1, "龘", ZINT_WARN_USES_ECI, 26, "Warning E3 4D F4 DF 4C 00 EC", 1, "ECI-26 B3 (UTF-8)" }, + /*102*/ { UNICODE_MODE, 28, 4, 11, -1, "龘", 0, 28, "E3 8D 7C EA 80", 1, "ECI-28 B2 (Big5)" }, + /*103*/ { UNICODE_MODE, 28, 2, 11, -1, "龘龘", 0, 28, "E3 8E 7C EA FC EA 80", 1, "ECI-28 B4 (Big5)" }, + /*104*/ { UNICODE_MODE, 0, 2, 11, -1, "齄", ZINT_WARN_USES_ECI, 26, "Warning E3 4D F4 DE C2 00 EC", 1, "ECI-26 B3 (UTF-8)" }, + /*105*/ { UNICODE_MODE, 29, 4, 11, -1, "齄", 0, 29, "E3 AD 7B FF 00", 1, "ECI-29 B2 (GB 2312)" }, + /*106*/ { UNICODE_MODE, 29, 2, 11, -1, "齄齄", 0, 29, "E3 AE 7B FF 7B FF 00", 1, "ECI-29 B4 (GB 2312)" }, + /*107*/ { UNICODE_MODE, 0, 2, 11, -1, "가", ZINT_WARN_USES_ECI, 26, "Warning E3 4D F5 58 40 00 EC", 1, "ECI-26 B3 (UTF-8)" }, + /*108*/ { UNICODE_MODE, 30, 4, 11, -1, "가", 0, 30, "E3 CD 58 50 80", 1, "ECI-30 B2 (EUC-KR)" }, + /*109*/ { UNICODE_MODE, 30, 2, 11, -1, "가가", 0, 30, "E3 CE 58 50 D8 50 80", 1, "ECI-30 B4 (EUC-KR)" }, + /*110*/ { UNICODE_MODE, 170, 4, 11, -1, "?", 0, 170, "F0 15 4C 9F 80", 1, "ECI-170 B1 (ASCII invariant)" }, + /*111*/ { DATA_MODE, 899, 4, 11, -1, "\200", 0, 899, "F0 70 6C C0 00", 1, "ECI-899 B1 (8-bit binary)" }, + /*112*/ { UNICODE_MODE, 900, 2, 11, -1, "é", 0, 900, "F0 70 8D 61 D4 80 EC", 1, "ECI-900 B2 (no conversion)" }, + /*113*/ { UNICODE_MODE, 16384, 2, 11, -1, "é", 0, 16384, "F8 08 00 0D 61 D4 80", 1, "ECI-16384 B2 (no conversion)" }, + /*114*/ { UNICODE_MODE, 3, 2, 14, -1, "Google Pixel 4a 128 GB Black;price:$439.97", 0, 3, "(43) E0 6C F4 76 F6 F6 76 C6 52 05 06 97 86 56 C2 03 46 14 4E 55 0C 59 91 09 96 CA 6C 61", 0, "ECI-3 B15 A9 B10 A8; BWIPP different encodation (B42) & doesn't fit)" }, + /*115*/ { UNICODE_MODE, 29, 2, 20, -1, "Google 谷歌 Pixel 4a 128 GB黑色;零售价:¥3149.79", 0, 29, "(53) E3 AE 94 76 F6 F6 76 C6 52 0B 9C 8B 8E 82 05 06 97 86 56 C2 03 46 12 03 13 23 82 04", 0, "ECI-29 B41 A7; BWIPP different encodation (B48) & doesn't fit)" }, + /*116*/ { UNICODE_MODE, 17, 2, 24, -1, "Google Pixel 4a 128 GB Schwarz;Preis:444,90 €", 0, 17, "(48) E2 2C F4 76 F6 F6 76 C6 52 05 06 97 86 56 C2 03 46 14 27 2A 86 2C C8 84 DC 6A B1 B4", 0, "ECI-17 B15 A9 B21; BWIPP different encodation (B46)" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol; char escaped[4096]; + 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 testStart("test_rmqr_input"); @@ -4429,21 +5709,40 @@ static void test_rmqr_input(int index, int generate, int debug) { debug |= ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - length = testUtilSetSymbol(symbol, BARCODE_RMQR, data[i].input_mode, data[i].eci, -1 /*option_1*/, -1, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, BARCODE_RMQR, data[i].input_mode, data[i].eci, data[i].option_1, data[i].option_2, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, %d, %s, \"%s\", %s, %d, \"%s\", \"%s\" },\n", - i, testUtilInputModeName(data[i].input_mode), data[i].eci, testUtilOption3Name(data[i].option_3), + printf(" /*%3d*/ { %s, %d, %d, %d, %s, \"%s\", %s, %d, \"%s\", %d, \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), data[i].eci, + data[i].option_1, data[i].option_2, testUtilOption3Name(data[i].option_3), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), - testUtilErrorName(data[i].ret), ret < ZINT_ERROR ? symbol->eci : -1, symbol->errtxt, data[i].comment); + testUtilErrorName(data[i].ret), ret < ZINT_ERROR ? symbol->eci : -1, + symbol->errtxt, data[i].bwipp_cmp, data[i].comment); } else { if (ret < ZINT_ERROR) { assert_equal(symbol->eci, data[i].expected_eci, "i:%d eci %d != %d\n", i, symbol->eci, data[i].expected_eci); } assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + + if (ret < ZINT_ERROR) { + if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_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[17 * 139 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilBwipp(i, symbol, data[i].option_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); + } + } + } } ZBarcode_Delete(symbol); @@ -4515,41 +5814,47 @@ static void test_rmqr_optimize(int index, int generate, int debug) { struct item { int input_mode; - char *data; int option_1; + int option_2; + char *data; int ret; char *expected; + int bwipp_cmp; char *comment; }; struct item data[] = { - /* 0*/ { UNICODE_MODE, "1", -1, 0, "22 20 EC 11 EC", "N1" }, - /* 1*/ { UNICODE_MODE, "AAA", -1, 0, "46 73 0A 00 EC", "A3" }, - /* 2*/ { UNICODE_MODE, "0123456789", -1, 0, "34 06 2B 35 34 80 EC", "N10 (nayuki.io - pure numeric)" }, - /* 3*/ { UNICODE_MODE, "ABCDEF", -1, 0, "4C 73 51 4A 85 00 EC", "A6 (nayuki.io - pure alphanumeric)" }, - /* 4*/ { UNICODE_MODE, "wxyz", -1, 0, "71 DD E1 E5 E8", "B4 (nayuki.io - pure byte)" }, - /* 5*/ { UNICODE_MODE, "「魔法少女まどか☆マギカ」って、 ИАИ desu κα?", -1, ZINT_WARN_NONCOMPLIANT, "Warning (53) 8E 80 D6 00 4F C0 57 6A B5 C2 B8 14 70 94 81 64 37 A1 8D 0C 50 0D 82 82 14 40 00 80", "K29 (nayuki.io - pure kanji)" }, - /* 6*/ { UNICODE_MODE, "012A", -1, 0, "48 00 43 20 EC", "A4" }, - /* 7*/ { UNICODE_MODE, "0123A", -1, 0, "28 06 1A 12 80", "N4 A1 (nayuki.io - alpha/numeric)" }, - /* 8*/ { UNICODE_MODE, "0a", -1, 0, "68 C1 84 00 EC", "B2 (nayuki.io - numeric/byte)" }, - /* 9*/ { UNICODE_MODE, "01a", -1, 0, "24 05 96 10 EC", "N2 B1 (nayuki.io - numeric/byte)" }, - /* 10*/ { UNICODE_MODE, "ABCa", -1, 0, "71 05 09 0D 84", "B4 (nayuki.io - alphanumeric/byte)" }, - /* 11*/ { UNICODE_MODE, "ABCDa", -1, 0, "48 73 51 4B 2C 20 EC", "A4 B1 (same bits as B5)" }, - /* 12*/ { UNICODE_MODE, "THE SQUARE ROOT OF 2 IS 1.41421356237309504880168872420969807856967187537694807317667973799", -1, 0, "(48) 46 A9 52 9A A0 D5 42 66 E6 F8 A1 4F 62 3E 56 CC D4 40 2B 98 2C F1 AB 19 2E A2 F8 61", " A26 N65 (nayuki.io - alpha/numeric)" }, - /* 13*/ { UNICODE_MODE, "Golden ratio φ = 1.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374......", -1, ZINT_WARN_NONCOMPLIANT, "Warning (73) 65 11 DB DB 19 19 5B 88 1C 98 5D 1A 5B C8 20 F4 C8 0F 48 0C 4B 8B 24 D4 10 FB 97 6E", "B20 N100 A6 (nayuki.io - alpha/numeric/byte)" }, - /* 14*/ { UNICODE_MODE, "こんにちwa、世界! αβγδ", -1, ZINT_WARN_NONCOMPLIANT, "Warning 84 09 88 5C 42 92 13 F6 B7 76 18 14 19 0A 28 A4 58 14 92 08 40 FF 88 00 40 22 02", "K4 B7 K4 (nayuki.io - kanji/european)" }, - /* 15*/ { UNICODE_MODE, "6547861663com.acme35584af52fa3-88d0-093b-6c14-b37ddafb59c528908608sg.com.dash.www05303790265903SG.COM.NETS46967004B2AE13344004SG.SGQR209710339382.6359SG8236HELLO FOO2517Singapore3272B815", -1, 0, "(152) 20 AA 3B 12 29 8D 97 B1 B7 B6 97 30 B1 B6 B2 99 9A 9A 9C 1A 30 B3 1A 99 33 30 99 96", "N10 B47 N9 B15 N14 A38 N12 A25 B8 A8 (nayuki.io - SGQR alpha/numeric/byte)" }, - /* 16*/ { UNICODE_MODE, "2004年大西洋颶風季是有以来造成人失惨重的大季之一,于2004年6月1日正式始,同年11月30日束,上的日期界定了一年中大多数气旋在大西洋形成的段lll ku", -1, ZINT_WARN_NONCOMPLIANT, "Warning (127) 20 43 21 21 87 27 32 95 77 90 AD F0 33 D5 CF 0E BA 58 46 17 22 19 0C 62 5D 62 DB 14", "N4 K24 N4 B6 K7 B6 K26 B6 (nayuki.io - kanji/byte/numeric, non-Shift JIS removed)" }, - /* 17*/ { UNICODE_MODE, "AB1234567A", -1, 0, "4A 39 A0 BC 45 8E 72 8A 00 EC 11 EC", "A10" }, - /* 18*/ { UNICODE_MODE, "AB12345678A", -1, 0, "42 39 A5 03 DB 91 39 04 A0 EC 11 EC", "A2 N8 A1" }, - /* 19*/ { UNICODE_MODE, "テaA1", -1, ZINT_WARN_NONCOMPLIANT, "Warning 76 0D 95 85 04 C4 00", "B4" }, - /* 20*/ { UNICODE_MODE, "テaAB1", -1, ZINT_WARN_NONCOMPLIANT, "Warning 6E 0D 95 85 19 CD 04", "B3 A3" }, - /* 21*/ { UNICODE_MODE, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機", -1, ZINT_WARN_NONCOMPLIANT, "Warning (152) 82 0E A2 16 20 97 28 BD 02 C1 4F 09 12 61 08 04 A0 83 AA 3E 3D 43 4C 13 0D 68 73 1F", "K8 N1 K8 N1 K10 N2 K33 N2 K16 N1 K7" }, + /* 0*/ { UNICODE_MODE, 4, 11, "1", 0, "22 20 EC 11 EC", 1, "N1" }, + /* 1*/ { UNICODE_MODE, 4, 11, "AAA", 0, "46 73 0A 00 EC", 1, "A3" }, + /* 2*/ { UNICODE_MODE, 2, 11, "0123456789", 0, "34 06 2B 35 34 80 EC", 1, "N10 (nayuki.io - pure numeric)" }, + /* 3*/ { UNICODE_MODE, 2, 11, "ABCDEF", 0, "4C 73 51 4A 85 00 EC", 1, "A6 (nayuki.io - pure alphanumeric)" }, + /* 4*/ { UNICODE_MODE, 4, 11, "wxyz", 0, "71 DD E1 E5 E8", 1, "B4 (nayuki.io - pure byte)" }, + /* 5*/ { UNICODE_MODE, 2, 20, "「魔法少女まどか☆マギカ」って、 ИАИ desu κα?", ZINT_WARN_NONCOMPLIANT, "Warning (53) 8E 80 D6 00 4F C0 57 6A B5 C2 B8 14 70 94 81 64 37 A1 8D 0C 50 0D 82 82 14 40 00 80", 1, "K29 (nayuki.io - pure kanji)" }, + /* 6*/ { UNICODE_MODE, 4, 11, "012A", 0, "48 00 43 20 EC", 1, "A4" }, + /* 7*/ { UNICODE_MODE, 4, 11, "0123A", 0, "28 06 1A 12 80", 1, "N4 A1 (nayuki.io - alpha/numeric)" }, + /* 8*/ { UNICODE_MODE, 4, 11, "0a", 0, "68 C1 84 00 EC", 1, "B2 (nayuki.io - numeric/byte)" }, + /* 9*/ { UNICODE_MODE, 4, 11, "01a", 0, "24 05 96 10 EC", 1, "N2 B1 (nayuki.io - numeric/byte)" }, + /* 10*/ { UNICODE_MODE, 4, 11, "ABCa", 0, "71 05 09 0D 84", 1, "B4 (nayuki.io - alphanumeric/byte)" }, + /* 11*/ { UNICODE_MODE, 2, 11, "ABCDa", 0, "48 73 51 4B 2C 20 EC", 1, "A4 B1 (same bits as B5)" }, + /* 12*/ { UNICODE_MODE, 2, 24, "THE SQUARE ROOT OF 2 IS 1.41421356237309504880168872420969807856967187537694807317667973799", 0, "(48) 46 A9 52 9A A0 D5 42 66 E6 F8 A1 4F 62 3E 56 CC D4 40 2B 98 2C F1 AB 19 2E A2 F8 61", 1, " A26 N65 (nayuki.io - alpha/numeric)" }, + /* 13*/ { UNICODE_MODE, 2, 21, "Golden ratio φ = 1.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374......", ZINT_WARN_NONCOMPLIANT, "Warning (73) 65 11 DB DB 19 19 5B 88 1C 98 5D 1A 5B C8 20 F4 C8 0F 48 0C 4B 8B 24 D4 10 FB 97 6E", 1, "B20 N100 A6 (nayuki.io - alpha/numeric/byte)" }, + /* 14*/ { UNICODE_MODE, 2, 18, "こんにちwa、世界! αβγδ", ZINT_WARN_NONCOMPLIANT, "Warning 84 09 88 5C 42 92 13 F6 B7 76 18 14 19 0A 28 A4 58 14 92 08 40 FF 88 00 40 22 02", 1, "K4 B7 K4 (nayuki.io - kanji/european)" }, + /* 15*/ { UNICODE_MODE, 2, 32, "6547861663com.acme35584af52fa3-88d0-093b-6c14-b37ddafb59c528908608sg.com.dash.www05303790265903SG.COM.NETS46967004B2AE13344004SG.SGQR209710339382.6359SG8236HELLO FOO2517Singapore3272B815", 0, "(152) 20 AA 3B 12 29 8D 97 B1 B7 B6 97 30 B1 B6 B2 99 9A 9A 9C 1A 30 B3 1A 99 33 30 99 96", 0, "N10 B47 N9 B15 N14 A38 N12 A25 B8 A8 (nayuki.io - SGQR alpha/numeric/byte); BWIPP different encodation (N10 B47 N9 B15 N14 A38 N12 A25 B13 A3) & doesn't fit" }, + /* 16*/ { UNICODE_MODE, 2, 27, "2004年大西洋颶風季是有以来造成人失惨重的大季之一,于2004年6月1日正式始,同年11月30日束,上的日期界定了一年中大多数气旋在大西洋形成的段lll ku", ZINT_WARN_NONCOMPLIANT, "Warning (127) 20 43 21 21 87 27 32 95 77 90 AD F0 33 D5 CF 0E BA 58 46 17 22 19 0C 62 5D 62 DB 14", 0, "N4 K24 N4 B6 K7 B6 K26 B6 (nayuki.io - kanji/byte/numeric, non-Shift JIS removed; BWIPP different encodation (N4 K24 N4 B26 K26 B6)" }, + /* 17*/ { UNICODE_MODE, 2, 17, "AB1234567A", 0, "4A 39 A0 BC 45 8E 72 8A 00 EC 11 EC", 1, "A10" }, + /* 18*/ { UNICODE_MODE, 2, 17, "AB12345678A", 0, "42 39 A5 03 DB 91 39 04 A0 EC 11 EC", 1, "A2 N8 A1" }, + /* 19*/ { UNICODE_MODE, 2, 11, "テaA1", ZINT_WARN_NONCOMPLIANT, "Warning 76 0D 95 85 04 C4 00", 1, "B4" }, + /* 20*/ { UNICODE_MODE, 2, 11, "テaAB1", ZINT_WARN_NONCOMPLIANT, "Warning 6E 0D 95 85 19 CD 04", 0, "B3 A3; BWIPP different encodation (B6)" }, + /* 21*/ { UNICODE_MODE, 2, 32, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機", ZINT_WARN_NONCOMPLIANT, "Warning (152) 82 0E A2 16 20 97 28 BD 02 C1 4F 09 12 61 08 04 A0 83 AA 3E 3D 43 4C 13 0D 68 73 1F", 1, "K8 N1 K8 N1 K10 N2 K33 N2 K16 N1 K7" }, }; int data_size = ARRAY_SIZE(data); int i, length, ret; struct zint_symbol *symbol; char escaped[4096]; + 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 testStart("test_rmqr_optimize"); @@ -4562,17 +5867,33 @@ static void test_rmqr_optimize(int index, int generate, int debug) { debug |= ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - length = testUtilSetSymbol(symbol, BARCODE_RMQR, data[i].input_mode, -1 /*eci*/, data[i].option_1, -1, ZINT_FULL_MULTIBYTE, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, BARCODE_RMQR, data[i].input_mode, -1 /*eci*/, data[i].option_1, data[i].option_2, ZINT_FULL_MULTIBYTE, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, \"%s\", %d, %s, \"%s\", \"%s\" },\n", - i, testUtilInputModeName(data[i].input_mode), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].option_1, - testUtilErrorName(data[i].ret), symbol->errtxt, data[i].comment); + printf(" /*%3d*/ { %s, %d, %d, \"%s\", %s, \"%s\", %d, \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_2, + testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), + testUtilErrorName(data[i].ret), symbol->errtxt, data[i].bwipp_cmp, data[i].comment); } else { assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + + if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, data[i].option_2, -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[17 * 139 + 1]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, -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); + } + } } ZBarcode_Delete(symbol); @@ -4611,7 +5932,7 @@ static void test_rmqr_encode(int index, int generate, int debug) { "101010100110010100111010001" "111010101010101010101011111" }, - /* 1*/ { UNICODE_MODE, 2, 17, "12345678901234567890123456", 0, 13, 27, 1, "Draft ISO 2019-6-24 6.2 Figure 1, R13x27-M, same (note data as here not as given in draft)", + /* 1*/ { UNICODE_MODE, 2, 17, "12345678901234567890123456", 0, 13, 27, 1, "Draft ISO 2019-6-24 6.2 Figure 1, R13x27-M, same", "111111101010101010101010111" "100000100001001100010011001" "101110101100000011001110001" @@ -5009,7 +6330,7 @@ static void test_rmqr_encode(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, -1, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, -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, data[i].expected); @@ -5026,6 +6347,206 @@ static void test_rmqr_encode(int index, int generate, int debug) { testFinish(); } +static void test_rmqr_encode_segs(int index, int generate, int debug) { + + struct item { + int input_mode; + int option_1; + int option_2; + int option_3; + struct zint_seg segs[3]; + int ret; + + int expected_rows; + int expected_width; + int bwipp_cmp; + char *comment; + char *expected; + }; + struct item data[] = { + /* 0*/ { UNICODE_MODE, 2, 11, -1, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 7 }, { TU(""), 0, 0 } }, 0, 11, 27, 1, "Standard example", + "111111101010101010101010111" + "100000101110110001100111101" + "101110100111000001110101111" + "101110100010010000000110000" + "101110100000011010001111001" + "100000100110100000101110110" + "111111101001011111100111111" + "000000001011110111101010001" + "111010111010001000110110101" + "101111001111110001001010001" + "111010101010101010101011111" + }, + /* 1*/ { UNICODE_MODE, 2, 11, -1, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 11, 27, 1, "Standard example auto-ECI", + "111111101010101010101010111" + "100000101110110001100111101" + "101110100111000001110101111" + "101110100010010000000110000" + "101110100000011010001111001" + "100000100110100000101110110" + "111111101001011111100111111" + "000000001011110111101010001" + "111010111010001000110110101" + "101111001111110001001010001" + "111010101010101010101011111" + }, + /* 2*/ { UNICODE_MODE, 2, 11, -1, { { TU("Ж"), -1, 7 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, 0, 11, 27, 1, "Standard example inverted", + "111111101010101010101010111" + "100000101110111000010111101" + "101110100111011111110010001" + "101110100010111111001100000" + "101110100001001011110100001" + "100000100111111101101110100" + "111111100001000001000111111" + "000000001111000000101010001" + "111001110101001100010110101" + "101010011111101111101010001" + "111010101010101010101011111" + }, + /* 3*/ { UNICODE_MODE, 2, 11, -1, { { TU("Ж"), -1, 0 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 11, 27, 1, "Standard example inverted auto-ECI", + "111111101010101010101010111" + "100000101110111000010111101" + "101110100111011111110010001" + "101110100010111111001100000" + "101110100001001011110100001" + "100000100111111101101110100" + "111111100001000001000111111" + "000000001111000000101010001" + "111001110101001100010110101" + "101010011111101111101010001" + "111010101010101010101011111" + }, + /* 4*/ { UNICODE_MODE, 2, 32, -1, { { TU("Google Pixel 4a 128 GB Black;price:$439.97"), -1, 3 }, { TU("Google 谷歌 Pixel 4a 128 GB黑色;零售价:¥3149.79"), -1, 29 }, { TU("Google Pixel 4a 128 GB Schwarz;Preis:444,90 €"), -1, 17 } }, 0, 17, 139, 0, "AIM ITS/04-023:2022 Annex A example (shortened); BWIPP different encodation", + "1111111010101010101010101011101010101010101010101010101110101010101010101010101010111010101010101010101010101011101010101010101010101010111" + "1000001001000010100111001110100000111100110111111110001010100010000110011100101000101101010100111001001101110110110010000011110000101100101" + "1011101011101011111110110011100101100111101000001011111111110000100000111001000110111011000011100011000000100011101101100100110100110011011" + "1011101001001110000110100100001111011110111110111101000000100101001111110100111010000000011000101101110100000100011001000010001010101111110" + "1011101000010000111010100101101000100010100100110100011110111110001100101010001111110110111000000000101011100001101000001000110000000110111" + "1000001000001001100011001110100010110001011011011100110000111111011101011110010000000000000010001110010111000010001001110111010101011000110" + "1111111010100010010100110101101010100010001110001000100100011111111001000000111011111000110011111010000011011111100111011001000000011010001" + "0000000010010110010000100000000010101010110111110011010010110001100100001000010011000000110101111100010001000000100101100111011000011011110" + "1101110011111001110010000111111111101100100101001110001111101110010110101100001110110110001110100100111100000111111011110100100101011111001" + "0111111100100011001110011010010100110111101101010111000011001111100011011100001100100110011110110101111010101100010101100000010010110101000" + "1011000010101000110000001001010011101001100001111011001100010011011010010000101101110011000011010011011111110101101101100101110101100001001" + "0001110000010011000000110000010111111010010001010100100000101010000111111001110000000101100101110001010001010010011010001110101101111011100" + "1000101101011001001010000001111011100111100000100110101100101100110100100101001101110111101001100111001101111001111010001011011000110111111" + "0110100001110101010110010010100000111110011101011100100010111011000010010110001010000001001001001111000010011100111110010011000110100110001" + "1001000001100110110011100011111101010111100110100101011110010011101010100011101001111010100111010100110100011111110111100101000101010110101" + "1010011110111011011111000010111011001001010001011111011011101000100101110000010011101110110100011010110111010110110011110110000001000110001" + "1110101010101010101010101011101010101010101010101010101110101010101010101010101010111010101010101010101010101011101010101010101010101011111" + }, + /* 5*/ { DATA_MODE, 4, 3, -1, { { TU("\266"), 1, 0 }, { TU("\266"), 1, 7 }, { TU("\266"), 1, 0 } }, 0, 7, 77, 1, "Standard example + extra seg, data mode", + "11111110101010101010101011101010101010101010101010111010101010101010101010111" + "10000010000101011111110110101011011101110110100011101011010110001000110000001" + "10111010000101001001111111110011100001100010110011111100010111010001101011111" + "10111010001111110101010000111011110111000111100010101100011110001110101010001" + "10111010100010101100010111101010000111111001010110111000010010000000100110101" + "10000010011011101100010110100010100010101101100001101010000100011011101010001" + "11111110101010101010101011101010101010101010101010111010101010101010101011111" + }, + /* 6*/ { UNICODE_MODE, 2, 4, -1, { { TU("¿é"), -1, 0 }, { TU("กขฯ"), -1, 0 }, { TU("φχψω"), -1, 0 } }, ZINT_WARN_USES_ECI, 7, 99, 1, "Auto-ECI", + "111111101010101010101011101010101010101010101010111010101010101010101010101110101010101010101010111" + "100000100111110000101010111000010110100100000100101011100110111000000110101010111110010111111100101" + "101110100101001001110111111010010100110101100100111110111100100111111111101110010010111000100011111" + "101110100100110100000110011111110011101110010000000100000110000101011000100000111111001101100110001" + "101110101000100010000111100101110011010000111010111010110011110101110111101111111011111010100110101" + "100000101010100100010010111001101101000001111001101100011000001111001110111011001101000110110010001" + "111111101010101010101011101010101010101010101010111010101010101010101010101110101010101010101011111" + }, + }; + int data_size = ARRAY_SIZE(data); + int i, j, seg_count, ret; + struct zint_symbol *symbol; + + char escaped[4096]; + 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 + + testStart("test_rmqr_encode_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + testUtilSetSymbol(symbol, BARCODE_RMQR, data[i].input_mode, -1 /*eci*/, + data[i].option_1, data[i].option_2, data[i].option_3, -1 /*output_options*/, + NULL, 0, debug); + for (j = 0, seg_count = 0; j < 3 && data[i].segs[j].length; j++, seg_count++); + + ret = ZBarcode_Encode_Segs(symbol, data[i].segs, seg_count); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode_Segs ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + char escaped1[4096]; + char escaped2[4096]; + int length = data[i].segs[0].length == -1 ? (int) ustrlen(data[i].segs[0].source) : data[i].segs[0].length; + int length1 = data[i].segs[1].length == -1 ? (int) ustrlen(data[i].segs[1].source) : data[i].segs[1].length; + int length2 = data[i].segs[2].length == -1 ? (int) ustrlen(data[i].segs[2].source) : data[i].segs[2].length; + printf(" /*%3d*/ { %s, %d, %d, %d, { { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d } }, %s, %d, %d, %d, \"%s\",\n", + i, testUtilInputModeName(data[i].input_mode), + data[i].option_1, data[i].option_2, data[i].option_3, + testUtilEscape((const char *) data[i].segs[0].source, length, escaped, sizeof(escaped)), data[i].segs[0].length, data[i].segs[0].eci, + testUtilEscape((const char *) data[i].segs[1].source, length1, escaped1, sizeof(escaped1)), data[i].segs[1].length, data[i].segs[1].eci, + testUtilEscape((const char *) data[i].segs[2].source, length2, escaped2, sizeof(escaped2)), data[i].segs[2].length, data[i].segs[2].eci, + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].bwipp_cmp, data[i].comment); + testUtilModulesPrint(symbol, " ", "\n"); + printf(" },\n"); + } else { + if (ret < ZINT_ERROR) { + int width, row; + 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); + + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d\n", i, ret, width, row); + + if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_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 { + ret = testUtilBwippSegs(i, symbol, data[i].option_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); + 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, data[i].expected); + } + } + if (do_zxingcpp) { + if ((symbol->input_mode & 0x07) == DATA_MODE) { + if (debug & ZINT_DEBUG_TEST_PRINT) printf("i:%d multiple segments in DATA_MODE not currently supported for ZXing-C++ testing (%s)\n", i, testUtilBarcodeName(symbol->symbology)); + } else { + int length = data[i].segs[0].length == -1 ? (int) ustrlen(data[i].segs[0].source) : data[i].segs[0].length; + if (testUtilCanZXingCPP(i, symbol, (const char *) data[i].segs[0].source, length, debug)) { + int cmp_len, ret_len; + char modules_dump[32768]; + assert_notequal(testUtilModulesDump(symbol, modules_dump, sizeof(modules_dump)), -1, "i:%d testUtilModulesDump == -1\n", i); + ret = testUtilZXingCPP(i, symbol, (const char *) data[i].segs[0].source, 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 = testUtilZXingCPPCmpSegs(symbol, cmp_msg, cmp_buf, cmp_len, data[i].segs, seg_count, + NULL /*primary*/, escaped, &ret_len); + assert_zero(ret, "i:%d %s testUtilZXingCPPCmpSegs %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); + } + + testFinish(); +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ @@ -5034,6 +6555,7 @@ int main(int argc, char *argv[]) { { "test_qr_gs1", test_qr_gs1, 1, 1, 1 }, { "test_qr_optimize", test_qr_optimize, 1, 1, 1 }, { "test_qr_encode", test_qr_encode, 1, 1, 1 }, + { "test_qr_encode_segs", test_qr_encode_segs, 1, 1, 1 }, { "test_qr_perf", test_qr_perf, 1, 0, 1 }, { "test_microqr_options", test_microqr_options, 1, 0, 1 }, @@ -5051,6 +6573,7 @@ int main(int argc, char *argv[]) { { "test_rmqr_gs1", test_rmqr_gs1, 1, 1, 1 }, { "test_rmqr_optimize", test_rmqr_optimize, 1, 1, 1 }, { "test_rmqr_encode", test_rmqr_encode, 1, 1, 1 }, + { "test_rmqr_encode_segs", test_rmqr_encode_segs, 1, 1, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_rss.c b/backend/tests/test_rss.c index 0c78b7e1..bd1f037a 100644 --- a/backend/tests/test_rss.c +++ b/backend/tests/test_rss.c @@ -165,7 +165,7 @@ static void test_binary_div_modulo_divisor(int index, int generate, int debug) { assert_zero(ret, "i:%d ZBarcode_Buffer_Vector ret %d != 0\n", i, ret); if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) { - ret = testUtilBwipp(i, symbol, -1, -1, -1, text, length, symbol->primary, cmp_buf, sizeof(cmp_buf)); + ret = testUtilBwipp(i, symbol, -1, -1, -1, text, length, symbol->primary, cmp_buf, sizeof(cmp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmpRow(symbol, symbol->rows - 1, cmp_msg, cmp_buf, data[i].expected); @@ -904,7 +904,7 @@ static void test_examples(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, -1, data[i].option_2, data[i].option_3, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf)); + 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, data[i].expected); diff --git a/backend/tests/test_telepen.c b/backend/tests/test_telepen.c index 655318f1..64cb62e6 100644 --- a/backend/tests/test_telepen.c +++ b/backend/tests/test_telepen.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2020 - 2021 Robin Stuart + Copyright (C) 2020-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "testcommon.h" @@ -267,7 +266,7 @@ static void test_encode(int index, int generate, int debug) { assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) { - ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -403,3 +402,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_ultra.c b/backend/tests/test_ultra.c index 0c2d3fda..ac86455e 100644 --- a/backend/tests/test_ultra.c +++ b/backend/tests/test_ultra.c @@ -1,6 +1,6 @@ /* libzint - the open source barcode library - Copyright (C) 2020 - 2021 Robin Stuart + Copyright (C) 2020-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -27,7 +27,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ #include "testcommon.h" @@ -213,7 +212,7 @@ static void test_input(int index, int generate, int debug) { /* 16*/ { UNICODE_MODE, 0, -1, -1, -1, { 0, 0, "" }, "β", ZINT_WARN_USES_ECI, "Warning (2) 263 226", "" }, /* 17*/ { UNICODE_MODE, 9, -1, -1, -1, { 0, 0, "" }, "β", 0, "(2) 263 226", "" }, /* 18*/ { UNICODE_MODE, 9, -1, -1, -1, { 0, 0, "" }, "βAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 0, "(253) 263 226 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65", "249 chars EC2" }, - /* 19*/ { UNICODE_MODE, 9, -1, -1, ULTRA_COMPRESSION, { 0, 0, "" }, "A", 0, "(2) 272 65", "Note ECI ignored and not outputted if ULTRA_COMPRESSION and all ASCII" }, + /* 19*/ { UNICODE_MODE, 9, -1, -1, ULTRA_COMPRESSION, { 0, 0, "" }, "A", 0, "(2) 263 65", "Note previously ECI ignored and not outputted if ULTRA_COMPRESSION and all ASCII" }, /* 20*/ { UNICODE_MODE, 15, -1, -1, -1, { 0, 0, "" }, "Ŗ", 0, "(2) 268 170", "" }, /* 21*/ { DATA_MODE, 898, -1, -1, -1, { 0, 0, "" }, "\001\002\003\004\377", 0, "(7) 278 130 1 2 3 4 255", "" }, /* 22*/ { DATA_MODE, 899, -1, -1, -1, { 0, 0, "" }, "\001\002\003\004\377", 0, "(6) 280 1 2 3 4 255", "" }, @@ -280,13 +279,15 @@ static void test_input(int index, int generate, int debug) { symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - length = testUtilSetSymbol(symbol, BARCODE_ULTRA, data[i].input_mode, data[i].eci, data[i].option_1, data[i].option_2, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); + length = testUtilSetSymbol(symbol, BARCODE_ULTRA, data[i].input_mode, data[i].eci, + data[i].option_1, data[i].option_2, data[i].option_3, + -1 /*output_options*/, data[i].data, -1, debug); if (data[i].structapp.count) { symbol->structapp = data[i].structapp; } 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); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { printf(" /*%3d*/ { %s, %d, %d, %d, %s, { %d, %d, \"%s\" }, \"%s\", %s, \"%s\", \"%s\" },\n", @@ -818,7 +819,7 @@ static void test_encode(int index, int generate, int 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 { - ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, data[i].option_3, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf)); + ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, data[i].option_3, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf), NULL); assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); @@ -835,6 +836,255 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +static void test_encode_segs(int index, int generate, int debug) { + + struct item { + int input_mode; + int option_1; + int option_2; + int option_3; + struct zint_structapp structapp; + struct zint_seg segs[3]; + int ret; + + int expected_rows; + int expected_width; + int bwipp_cmp; + char *comment; + char *expected; + }; + // Based on AIMD/TSC15032-43 (v 0.99c), with values updated from BWIPP update 2021-07-14 + // https://github.com/bwipp/postscriptbarcode/commit/4255810845fa8d45c6192dd30aee1fdad1aaf0cc + struct item data[] = { + /* 0*/ { UNICODE_MODE, -1, -1, ULTRA_COMPRESSION, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 7 }, { TU(""), 0, 0 } }, 0, 13, 15, 0, "Standard example; BWIPP no ECI support for Ultracode", + "777777777777777" + "785786131155157" + "773783613563337" + "781786355656167" + "776785561363337" + "783781355651517" + "778787878787877" + "786781665116117" + "771783136335337" + "786785653613557" + "773781536165117" + "781786115333557" + "777777777777777" + }, + /* 1*/ { UNICODE_MODE, -1, -1, ULTRA_COMPRESSION, { 0, 0, "" }, { { TU("¶"), -1, 0 }, { TU("Ж"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 13, 15, 0, "Standard example auto-ECI; BWIPP no ECI support for Ultracode", + "777777777777777" + "785786131155157" + "773783613563337" + "781786355656167" + "776785561363337" + "783781355651517" + "778787878787877" + "786781665116117" + "771783136335337" + "786785653613557" + "773781536165117" + "781786115333557" + "777777777777777" + }, + /* 2*/ { UNICODE_MODE, -1, -1, ULTRA_COMPRESSION, { 0, 0, "" }, { { TU("Ж"), -1, 7 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, 0, 13, 15, 0, "Standard example inverted; BWIPP no ECI support for Ultracode", + "777777777777777" + "785786351355157" + "773785113663337" + "781781365356167" + "776783136163337" + "783786555651517" + "778787878787877" + "786781356116117" + "771783663335337" + "786785531613157" + "773781353165517" + "781786565333657" + "777777777777777" + }, + /* 3*/ { UNICODE_MODE, -1, -1, ULTRA_COMPRESSION, { 0, 0, "" }, { { TU("Ж"), -1, 0 }, { TU("¶"), -1, 0 }, { TU(""), 0, 0 } }, ZINT_WARN_USES_ECI, 13, 15, 0, "Standard example inverted auto-ECI; BWIPP no ECI support for Ultracode", + "777777777777777" + "785786351355157" + "773785113663337" + "781781365356167" + "776783136163337" + "783786555651517" + "778787878787877" + "786781356116117" + "771783663335337" + "786785531613157" + "773781353165517" + "781786565333657" + "777777777777777" + }, + /* 4*/ { UNICODE_MODE, -1, -1, ULTRA_COMPRESSION, { 0, 0, "" }, { { TU("product:Google Pixel 4a - 128 GB of Storage - Black;price:$439.97"), -1, 3 }, { TU("品名:Google 谷歌 Pixel 4a -128 GB的存储空间-黑色;零售价:¥3149.79"), -1, 29 }, { TU("Produkt:Google Pixel 4a - 128 GB Speicher - Schwarz;Preis:444,90 €"), -1, 17 } }, 0, 31, 51, 0, "AIM ITS/04-023:2022 Annex A example; BWIPP no ECI support for Ultracode", + "777777777777777777777777777777777777777777777777777" + "788786553615151313686615635315656568556155565633167" + "778783131336563655375536556151531317365661116315357" + "788786366163615166181363163533665138151555551131667" + "778785631636351311375511615351516667316663165656357" + "788781563115163655581635531513353338163331636363137" + "778787878787878787878787878787878787878787878787877" + "788785515563115631383565335311551158666513631316557" + "778786651356351315575153153566315667555156366135637" + "788781363513515166181666316333666318161633113513317" + "775783635365361331576153163515155637655155661351537" + "781785353136156566383335656633633318536616353136617" + "773787878787878787878787878787878787878787878787877" + "781781331535616631386565316331555568565666316651557" + "776786666356535565175656551655663617153515131366317" + "788783355511663311383331636113116138635136555113557" + "773785516665311566576556353555655567351513361555317" + "781783633336533155181333115131513638536365113131157" + "773787878787878787878787878787878787878787878787877" + "785786636561663636181316366313566618513136611663557" + "771781563655535363573133555551311167331655355551317" + "788783155566111151385315661133633538516533131135557" + "778786516633355666676136356651116667635356516556317" + "788785133151663353583553135516551118156615665661657" + "778787878787878787878787878787878787878787878787877" + "788781353515665533386611351311655558113366366156117" + "778783616631513151171356535556166617531115155365537" + "788785555563336315386533363665613368666653363516367" + "778781366656651133171316155153135557515516515663557" + "788786635535536351685531611336513668663633636555117" + "777777777777777777777777777777777777777777777777777" + }, + /* 5*/ { DATA_MODE, -1, -1, ULTRA_COMPRESSION, { 0, 0, "" }, { { TU("\266"), 1, 0 }, { TU("\266"), 1, 7 }, { TU("\266"), 1, 0 } }, 0, 13, 17, 0, "Standard example + extra seg, data mode; BWIPP no ECI support for Ultracode", + "77777777777777777" + "78578616315515157" + "77378361566333337" + "78578633115616167" + "77678566656333337" + "78378131365151517" + "77878787878787877" + "78678136111616117" + "77378361633535337" + "78178513161353157" + "77378656536515517" + "78178135353353657" + "77777777777777777" + }, + /* 6*/ { UNICODE_MODE, -1, -1, ULTRA_COMPRESSION, { 0, 0, "" }, { { TU("¿é"), -1, 0 }, { TU("กขฯ"), -1, 0 }, { TU("φχψω"), -1, 0 } }, ZINT_WARN_USES_ECI, 13, 20, 0, "Auto-ECI; BWIPP no ECI support for Ultracode", + "77777777777777777777" + "78578651555561561667" + "77678333166653153337" + "78178655335135635557" + "77578563166556553337" + "78378131655133331167" + "77878787878787878787" + "78678166111615516617" + "77378351653131633337" + "78578663311616515557" + "77378315636535131317" + "78178131363151656557" + "77777777777777777777" + }, + /* 7*/ { UNICODE_MODE, -1, -1, ULTRA_COMPRESSION, { 2, 3, "4" }, { { TU("¿é"), -1, 3 }, { TU("กขฯ"), -1, 13 }, { TU("φχψω"), -1, 9 } }, 0, 13, 23, 0, "Structured Append; BWIPP no ECI support for Ultracode", + "77777777777777777777777" + "78578613615616155168657" + "77678335366131316337317" + "78378666635516165158557" + "77578515156665351317317" + "78378163515131516568557" + "77878787878787878787877" + "78678151513156156168617" + "77578366351365315337337" + "78178633513113563558557" + "77378516666355655337317" + "78178133151513333118657" + "77777777777777777777777" + }, + /* 8*/ { UNICODE_MODE, -1, -1, ULTRA_COMPRESSION, { 0, 0, "" }, { { TU("çèéêëì"), -1, 0 }, { TU("òóô"), -1, 899 }, { TU("òóô"), -1, 10000 } }, 0, 13, 27, 0, "ECIs >= 899; BWIPP no ECI support for Ultracode", + "777777777777777777777777777" + "785786353555666665585335557" + "771783161616113513373663337" + "783786335335661355686335667" + "771785511666353666171656117" + "786781655535111113385163357" + "778787878787878787878787877" + "783781151511666355586355517" + "771785616353113666675666637" + "783781363635661511183311157" + "775786615561353366676566637" + "781785551653535633383633317" + "777777777777777777777777777" + }, + }; + int data_size = ARRAY_SIZE(data); + int i, j, seg_count, ret; + struct zint_symbol *symbol; + + char escaped[1024]; + char bwipp_buf[32768]; + char bwipp_msg[1024]; + + int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); // Only do BWIPP test if asked, too slow otherwise + + testStart("test_encode_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + if ((debug & ZINT_DEBUG_TEST_PRINT) && !(debug & ZINT_DEBUG_TEST_LESS_NOISY)) printf("i:%d\n", i); + + symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + testUtilSetSymbol(symbol, BARCODE_ULTRA, data[i].input_mode, -1 /*eci*/, + data[i].option_1, data[i].option_2, data[i].option_3, -1 /*output_options*/, NULL, 0, debug); + if (data[i].structapp.count) { + symbol->structapp = data[i].structapp; + } + for (j = 0, seg_count = 0; j < 3 && data[i].segs[j].length; j++, seg_count++); + + ret = ZBarcode_Encode_Segs(symbol, data[i].segs, seg_count); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode_Segs ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (generate) { + char escaped1[4096]; + char escaped2[4096]; + int length = data[i].segs[0].length == -1 ? (int) ustrlen(data[i].segs[0].source) : data[i].segs[0].length; + int length1 = data[i].segs[1].length == -1 ? (int) ustrlen(data[i].segs[1].source) : data[i].segs[1].length; + int length2 = data[i].segs[2].length == -1 ? (int) ustrlen(data[i].segs[2].source) : data[i].segs[2].length; + printf(" /*%3d*/ { %s, %d, %d, %s, { %d, %d, \"%s\" }, { { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d }, { TU(\"%s\"), %d, %d } }, %s, %d, %d, %d, \"%s\",\n", + i, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_2, testUtilOption3Name(data[i].option_3), + data[i].structapp.index, data[i].structapp.count, data[i].structapp.id, + testUtilEscape((const char *) data[i].segs[0].source, length, escaped, sizeof(escaped)), data[i].segs[0].length, data[i].segs[0].eci, + testUtilEscape((const char *) data[i].segs[1].source, length1, escaped1, sizeof(escaped1)), data[i].segs[1].length, data[i].segs[1].eci, + testUtilEscape((const char *) data[i].segs[2].source, length2, escaped2, sizeof(escaped2)), data[i].segs[2].length, data[i].segs[2].eci, + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].bwipp_cmp, data[i].comment); + testUtilModulesPrint(symbol, " ", "\n"); + printf(" },\n"); + } else { + if (ret < ZINT_ERROR) { + int width, row; + 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); + + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d\n", i, ret, width, row); + + if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_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 { + ret = testUtilBwippSegs(i, symbol, data[i].option_1, data[i].option_2, data[i].option_3, data[i].segs, seg_count, NULL, bwipp_buf, sizeof(bwipp_buf)); + assert_zero(ret, "i:%d %s testUtilBwippSegs ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); + + ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); + assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n actual: %s\nexpected: %s\n", + i, testUtilBarcodeName(symbol->symbology), ret, bwipp_msg, bwipp_buf, data[i].expected); + } + } + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ @@ -842,6 +1092,7 @@ int main(int argc, char *argv[]) { { "test_reader_init", test_reader_init, 1, 1, 1 }, { "test_input", test_input, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_encode_segs", test_encode_segs, 1, 1, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); @@ -850,3 +1101,5 @@ int main(int argc, char *argv[]) { return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/test_upcean.c b/backend/tests/test_upcean.c index cd7f4630..058e538c 100644 --- a/backend/tests/test_upcean.c +++ b/backend/tests/test_upcean.c @@ -121,7 +121,7 @@ static void test_upce_input(int index, int debug) { if (do_bwipp && testUtilCanBwipp(i, symbol, -1, -1, -1, debug)) { char modules_dump[8192 + 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].hrt, (int) strlen(data[i].hrt), NULL, cmp_buf, sizeof(cmp_buf)); + ret = testUtilBwipp(i, symbol, -1, -1, -1, data[i].hrt, (int) strlen(data[i].hrt), 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); @@ -952,7 +952,7 @@ static void test_encode(int index, int generate, int debug) { assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, -1, debug)) { - ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, cmp_buf, sizeof(cmp_buf)); + ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -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, data[i].expected); diff --git a/backend/tests/testcommon.c b/backend/tests/testcommon.c index 16e808b2..0ce21689 100644 --- a/backend/tests/testcommon.c +++ b/backend/tests/testcommon.c @@ -2010,7 +2010,7 @@ static const char *testUtilBwippName(int index, const struct zint_symbol *symbol { "", BARCODE_GRIDMATRIX, 142, 0, 0, 0, 0, 0, }, { "", BARCODE_UPNQR, 143, 0, 0, 0, 0, 0, }, { "ultracode", BARCODE_ULTRA, 144, 1, 1, 0, 0, 0, }, - { "rectangularmicroqrcode", BARCODE_RMQR, 145, 1, 1, 0, 0, 0, }, + { "rectangularmicroqrcode", BARCODE_RMQR, 145, 1, 1, 1, 0, 0, }, }; static const int data_size = ARRAY_SIZE(data); @@ -2153,14 +2153,13 @@ static void testUtilBwippCvtGS1Data(char *bwipp_data, int upcean, int *addon_pos /* Convert data to Ghostscript format for passing to bwipp_dump.ps */ static char *testUtilBwippEscape(char *bwipp_data, int bwipp_data_size, const char *data, int length, int zint_escape_mode, int eci, int *parse, int *parsefnc) { + const int init_parsefnc = *parsefnc == 1; char *b = bwipp_data; char *be = b + bwipp_data_size; unsigned char *d = (unsigned char *) data; unsigned char *de = (unsigned char *) data + length; - *parse = *parsefnc = 0; - - if (eci) { + if (eci && !init_parsefnc) { sprintf(bwipp_data, "^ECI%06d", eci); *parsefnc = 1; b = bwipp_data + 10; @@ -2169,7 +2168,8 @@ static char *testUtilBwippEscape(char *bwipp_data, int bwipp_data_size, const ch while (b < be && d < de) { /* Have to escape double quote otherwise Ghostscript gives "Unterminated quote in @-file" for some reason */ /* Escape single quote also to avoid having to do proper shell escaping TODO: proper shell escaping */ - if (*d < 0x20 || *d >= 0x7F || *d == '^' || *d == '"' || *d == '\'' || (!zint_escape_mode && *d == '\\')) { + if (*d < 0x20 || *d >= 0x7F || (*d == '^' && !init_parsefnc) || *d == '"' || *d == '\'' + || (*d == '\\' && !zint_escape_mode)) { if (b + 4 >= be) { fprintf(stderr, "testUtilBwippEscape: double quote bwipp_data buffer full (%d)\n", bwipp_data_size); return NULL; @@ -2238,11 +2238,53 @@ static void testUtilISBNHyphenate(char *bwipp_data, int addon_posn) { strcpy(bwipp_data, temp); } +/* Helper to convert UTF-8 data */ +static char *testUtilBwippUtf8Convert(const int index, const int symbology, const int try_sjis, int *p_eci, + const unsigned char *data, int *p_data_len, unsigned char *converted) { + int eci = *p_eci; + + if (eci == 0 && try_sjis + && (symbology == BARCODE_QRCODE || symbology == BARCODE_MICROQR || symbology == BARCODE_RMQR)) { + if (utf8_to_eci(0, data, converted, p_data_len) != 0) { + if (utf8_to_eci(20, data, converted, p_data_len) != 0) { + fprintf(stderr, "i:%d testUtilBwippUtf8Convert: failed to convert UTF-8 data for %s, ECI 0/20\n", + index, testUtilBarcodeName(symbology)); + return NULL; + } + // NOTE: not setting *p_eci = 20 + } + return (char *) converted; + } + if (ZBarcode_Cap(symbology, ZINT_CAP_ECI)) { + if (utf8_to_eci(eci, data, converted, p_data_len) != 0) { + if (eci != 0) { + fprintf(stderr, "i:%d testUtilBwippUtf8Convert: failed to convert UTF-8 data for %s, ECI %d\n", + index, testUtilBarcodeName(symbology), eci); + return NULL; + } + *p_eci = eci = get_best_eci(data, *p_data_len); + if (utf8_to_eci(eci, data, converted, p_data_len) != 0) { + fprintf(stderr, "i:%d testUtilBwippUtf8Convert: failed to convert UTF-8 data for %s, ECI %d\n", + index, testUtilBarcodeName(symbology), eci); + return NULL; + } + } + return (char *) converted; + } + if (eci != 0) { + fprintf(stderr, "i:%d testUtilBwippUtf8Convert: ECI %d but not supported for %s\n", + index, eci, testUtilBarcodeName(symbology)); + return NULL; + } + + return (char *) data; +} + #define GS_INITIAL_LEN 35 /* Length of cmd up to -q */ /* Create bwipp_dump.ps command and run */ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int option_2, int option_3, - const char *data, int length, const char *primary, char *buffer, int buffer_size) { + const char *data, int length, const char *primary, char *buffer, int buffer_size, int *p_parsefnc) { static const char cmd_fmt[] = "gs -dNOPAUSE -dBATCH -dNODISPLAY -q -sb=%s -sd='%s'" " backend/tests/tools/bwipp_dump.ps"; static const char cmd_opts_fmt[] = "gs -dNOPAUSE -dBATCH -dNODISPLAY -q -sb=%s -sd='%s' -so='%s'" @@ -2253,7 +2295,7 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int static const char cmd_opts_fmt2[] = "gs -dNOPAUSE -dBATCH -dNODISPLAY -q -sb=%s -sd='%.2043s' -sd2='%s' -so='%s'" " backend/tests/tools/bwipp_dump.ps"; - int symbology = symbol->symbology; + const int symbology = symbol->symbology; int data_len = length == -1 ? (int) strlen(data) : length; int primary_len = primary ? (int) strlen(primary) : 0; /* 4 AI prefix + primary + '|' + leading zero + escaped data + fudge */ @@ -2278,7 +2320,7 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int char *b = buffer; char *be = buffer + buffer_size; int r, h; - int parse, parsefnc; + int parse = 0, parsefnc = p_parsefnc ? *p_parsefnc : 0; int upcean = is_extendable(symbology); int upca = symbology == BARCODE_UPCA || symbology == BARCODE_UPCA_CHK || symbology == BARCODE_UPCA_CC; @@ -2311,36 +2353,12 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int eci = symbol->eci >= 3 && ZBarcode_Cap(symbology, ZINT_CAP_ECI) ? symbol->eci : 0; - if ((symbol->input_mode & 0x07) == UNICODE_MODE && is_eci_convertible(eci)) { - if (eci == 0 && (symbology == BARCODE_QRCODE || symbology == BARCODE_MICROQR || symbology == BARCODE_RMQR)) { - if (utf8_to_eci(0, (const unsigned char *) data, (unsigned char *) converted, &data_len) != 0 - && utf8_to_eci(20, (const unsigned char *) data, (unsigned char *) converted, &data_len) != 0) { - fprintf(stderr, "i:%d testUtilBwipp: failed to convert Unicode data for %s, ECI 0/20\n", - index, testUtilBarcodeName(symbology)); - return -1; - } - data = converted; - } else if (ZBarcode_Cap(symbology, ZINT_CAP_ECI)) { - if (utf8_to_eci(eci, (const unsigned char *) data, (unsigned char *) converted, &data_len) != 0) { - if (eci != 0) { - eci = get_best_eci((const unsigned char *) data, data_len); - if (utf8_to_eci(eci, (const unsigned char *) data, (unsigned char *) converted, &data_len) != 0) { - fprintf(stderr, "i:%d testUtilBwipp: failed to convert Unicode data for %s, ECI %d\n", - index, testUtilBarcodeName(symbology), eci); - return -1; - } - } else { - fprintf(stderr, "i:%d testUtilBwipp: failed to convert Unicode data for %s, no ECI specified\n", - index, testUtilBarcodeName(symbology)); - return -1; - } - } - data = converted; - } else if (eci != 0) { - fprintf(stderr, "i:%d testUtilBwipp: ECI %d but not supported for %s\n", - index, eci, testUtilBarcodeName(symbology)); - return -1; - } + if ((symbol->input_mode & 0x07) == UNICODE_MODE && is_eci_convertible(eci) + && (data = testUtilBwippUtf8Convert(index, symbology, 1 /*try_sjis*/, &eci, (const unsigned char *) data, + &data_len, (unsigned char *) converted)) == NULL) { + fprintf(stderr, "i:%d testUtilBwipp: failed to convert UTF-8 data for %s\n", + index, testUtilBarcodeName(symbology)); + return -1; } if (is_composite(symbology)) { @@ -2638,7 +2656,7 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int len += 4; } } - if (symbol->eci == 0) { /* If not already done for ECI */ + if (!parsefnc) { /* If not already done for ECI */ sprintf(bwipp_opts_buf + strlen(bwipp_opts_buf), "%sparsefnc", strlen(bwipp_opts_buf) ? " " : ""); bwipp_opts = bwipp_opts_buf; @@ -2785,6 +2803,20 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int bwipp_opts = bwipp_opts_buf; } } + /* Hack to place ECI after Macro header */ + if (eci && length > 5 && memcmp("[)>\036", data, 4) == 0) { + char macro_eci_buf[13]; + if (length > 6 && data[6] == 29 /*GS*/ && ((data[4] == '0' && data[5] == '5') + || (data[4] == '0' && data[5] == '6') || (data[4] == '1' && data[5] == '2'))) { + memcpy(macro_eci_buf, bwipp_data + 10, 13); /* Macro */ + memcpy(bwipp_data + 13, bwipp_data, 10); /* ECI */ + memcpy(bwipp_data, macro_eci_buf, 13); + } else if (data[4] >= '0' && data[4] <= '9' && data[5] >= '0' && data[5] <= '9') { + memcpy(macro_eci_buf, bwipp_data, 10); /* ECI */ + memcpy(bwipp_data, bwipp_data + 10, 9); /* Macro */ + memcpy(bwipp_data + 9, macro_eci_buf, 10); + } + } } else if (symbology == BARCODE_QRCODE || symbology == BARCODE_HIBC_QR || symbology == BARCODE_MICROQR || symbology == BARCODE_RMQR) { if (option_1 >= 1 && option_1 <= 4) { @@ -2972,6 +3004,94 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int return 0; } +int testUtilBwippSegs(int index, struct zint_symbol *symbol, int option_1, int option_2, int option_3, + const struct zint_seg segs[], const int seg_count, const char *primary, char *buffer, int buffer_size) { + const int symbology = symbol->symbology; + const int unicode_mode = (symbol->input_mode & 0x7) == UNICODE_MODE; + const int symbol_eci = symbol->eci; + struct zint_seg *local_segs = (struct zint_seg *) testutil_alloca(sizeof(struct zint_seg) * seg_count); + int total_len = 0; + char *data, *d; + int parsefnc = 1; + int ret; + int i; + + assert(ZBarcode_Cap(symbology, ZINT_CAP_ECI)); + + for (i = 0; i < seg_count; i++) { + local_segs[i] = segs[i]; + if (local_segs[i].length == -1) { + local_segs[i].length = (int) ustrlen(local_segs[i].source); + } + if (unicode_mode) { + total_len += get_eci_length(local_segs[i].eci, local_segs[i].source, local_segs[i].length); + } else { + total_len += local_segs[i].length; + } + } + total_len += 10 * seg_count; + d = data = (char *) testutil_alloca(total_len + 1); + + for (i = 0; i < seg_count; i++) { + if (unicode_mode && is_eci_convertible(local_segs[i].eci)) { + char *converted = testUtilBwippUtf8Convert(index, symbology, 0 /*try_sjis*/, &local_segs[i].eci, + local_segs[i].source, &local_segs[i].length, (unsigned char *) d); + if (converted == NULL) { + return -1; + } + if (converted == d) { + /* Ensure default ECI set if follows non-default ECI */ + if (i != 0 && local_segs[i].eci == 0 && local_segs[i - 1].eci > 3) { + local_segs[i].eci = 3; + } + if (local_segs[i].eci) { /* Note this will fail if have DotCode macro */ + char eci_str[10 + 1]; + sprintf(eci_str, "^ECI%06d", local_segs[i].eci); + memmove(d + 10, d, local_segs[i].length); + memcpy(d, eci_str, 10); + d += 10; + } + d += local_segs[i].length; + } else { + /* Ensure default ECI set if follows non-default ECI */ + if (i != 0 && local_segs[i].eci == 0 && local_segs[i - 1].eci > 3) { + local_segs[i].eci = 3; + } + if (local_segs[i].eci) { + d += sprintf(d, "^ECI%06d", local_segs[i].eci); + } + memcpy(d, local_segs[i].source, local_segs[i].length); + d += local_segs[i].length; + } + } else { + /* Ensure default ECI set if follows non-default ECI */ + if (i != 0 && local_segs[i].eci == 0 && local_segs[i - 1].eci > 3) { + local_segs[i].eci = 3; + } + if (local_segs[i].eci) { + d += sprintf(d, "^ECI%06d", local_segs[i].eci); + } + memcpy(d, local_segs[i].source, local_segs[i].length); + d += local_segs[i].length; + } + } + total_len = d - data; + + if (unicode_mode) { + symbol->input_mode = DATA_MODE; + } + symbol->eci = 0; + + ret = testUtilBwipp(index, symbol, option_1, option_2, option_3, data, total_len, primary, buffer, buffer_size, &parsefnc); + + if (unicode_mode) { + symbol->input_mode = UNICODE_MODE; + } + symbol->eci = symbol_eci; + + return ret; +} + /* Compare bwipp_dump.ps output to test suite module dump */ int testUtilBwippCmp(const struct zint_symbol *symbol, char *msg, char *cmp_buf, const char *expected) { int cmp_len = (int) strlen(cmp_buf); @@ -3039,7 +3159,7 @@ int testUtilBwippCmpRow(const struct zint_symbol *symbol, int row, char *msg, co /* Whether ZXing-C++ Decoder available on system */ /* Requires the "diagnostics2" branch from https://github.com/gitlost/zxing-cpp built with BUILD_EXAMPLE_DECODER - and "zintcppdecoder" placed in PATH, e.g.: + and "zxingcppdecoder" placed in PATH, e.g.: git clone --branch diagnostics2 https://github.com/gitlost/zxing-cpp zxing-cpp-diagnostics2 cd zxing-cpp-diagnostics2 mkdir build; cd build @@ -3261,9 +3381,9 @@ int testUtilCanZXingCPP(int index, const struct zint_symbol *symbol, const char int testUtilZXingCPP(int index, struct zint_symbol *symbol, const char *source, const int length, char *bits, char *buffer, const int buffer_size, int *p_cmp_len) { - static const char cmd_fmt[] = "zxingcppdecoder -width %d -textonly -format %s -zint '%d,%d' -bits '%s'"; - static const char cs_cmd_fmt[] = "zxingcppdecoder -width %d -textonly -format %s -zint '%d,%d' -bits '%s'" - " -charset %s"; + static const char cmd_fmt[] = "zxingcppdecoder -width %d -textonly -format %s -bits '%s'"; + static const char hint_cmd_fmt[] = "zxingcppdecoder -width %d -textonly -format %s -hint '%s' -bits '%s'"; + static const char cs_cmd_fmt[] = "zxingcppdecoder -width %d -textonly -format %s -bits '%s' -charset %s"; const int bits_len = (int) strlen(bits); const int width = symbol->width; @@ -3272,6 +3392,7 @@ int testUtilZXingCPP(int index, struct zint_symbol *symbol, const char *source, const char *zxingcpp_barcode = NULL; const int data_mode = (symbol->input_mode & 0x07) == DATA_MODE; int set_charset = 0; + const char *hint = NULL; FILE *fp = NULL; int cnt; @@ -3284,16 +3405,38 @@ int testUtilZXingCPP(int index, struct zint_symbol *symbol, const char *source, return -1; } - if (symbol->eci == 0 && symbol->symbology == BARCODE_HANXIN) { + if (symbology == BARCODE_EXCODE39) { + if (symbol->option_2 == 1) { + hint = "tryCode39ExtendedMode,validateCode39CheckSum"; + } else { + hint = "tryCode39ExtendedMode"; + } + } else if ((symbology == BARCODE_CODE39 || symbology == BARCODE_LOGMARS) && symbol->option_2 == 1) { + hint = "validateCode39CheckSum"; + } + + if ((symbol->input_mode & 0x07) == UNICODE_MODE && symbol->eci == 0 + && (symbology == BARCODE_QRCODE || symbology == BARCODE_HANXIN)) { int converted_len = length; unsigned char *converted_buf = (unsigned char *) testutil_alloca(converted_len + 1); - set_charset = utf8_to_eci(0, (const unsigned char *) source, converted_buf, &converted_len) != 0; + if (symbology == BARCODE_HANXIN) { + set_charset = utf8_to_eci(0, (const unsigned char *) source, converted_buf, &converted_len) != 0; + } else { + set_charset = utf8_to_eci(0, (const unsigned char *) source, converted_buf, &converted_len) == 0; + } } if (set_charset) { - static const char charset[] = "GB18030"; - sprintf(cmd, cs_cmd_fmt, width, zxingcpp_barcode, symbology, symbol->option_2, bits, charset); + const char *charset; + if (symbology == BARCODE_HANXIN) { + charset = "GB18030"; + } else { + charset = "ISO8859_1"; + } + sprintf(cmd, cs_cmd_fmt, width, zxingcpp_barcode, bits, charset); + } else if (hint) { + sprintf(cmd, hint_cmd_fmt, width, zxingcpp_barcode, hint, bits); } else { - sprintf(cmd, cmd_fmt, width, zxingcpp_barcode, symbology, symbol->option_2, bits); + sprintf(cmd, cmd_fmt, width, zxingcpp_barcode, bits); } if (symbol->debug & ZINT_DEBUG_TEST_PRINT) { @@ -3313,7 +3456,6 @@ int testUtilZXingCPP(int index, struct zint_symbol *symbol, const char *source, testutil_pclose(fp); return -1; } - buffer[cnt] = '\0'; if (fgetc(fp) != EOF) { fprintf(stderr, "i:%d testUtilZXingCPP: failed to read full stream (%s)\n", index, cmd); @@ -3323,8 +3465,8 @@ int testUtilZXingCPP(int index, struct zint_symbol *symbol, const char *source, testutil_pclose(fp); - if (data_mode && (is_eci_convertible(symbol->eci) || symbol->eci == 899)) { - const int eci = symbol->eci == 899 ? 3 : symbol->eci; + if (data_mode && (is_eci_convertible(symbol->eci) || symbol->eci >= 899)) { + const int eci = symbol->eci >= 899 ? 3 : symbol->eci; int error_number; const int eci_length = get_eci_length(eci, (const unsigned char *) buffer, cnt); unsigned char *preprocessed = (unsigned char *) testutil_alloca(eci_length + 1); @@ -3338,8 +3480,8 @@ int testUtilZXingCPP(int index, struct zint_symbol *symbol, const char *source, if (error_number == 0) { memcpy(buffer, preprocessed, cnt); } else { - if (eci != 0) { - fprintf(stderr, "i:%d testUtilZXingCPP: utf8_to_eci == %d (%s)\n", index, error_number, cmd); + if (eci != 0 && symbol->eci < 899) { + fprintf(stderr, "i:%d testUtilZXingCPP: utf8_to_eci(%d) == %d (%s)\n", index, eci, error_number, cmd); return -1; } else { int i; @@ -3383,17 +3525,17 @@ int testUtilZXingCPPCmp(struct zint_symbol *symbol, char *msg, char *cmp_buf, in const int is_dbar_exp = symbology == BARCODE_DBAR_EXP || symbology == BARCODE_DBAR_EXPSTK; const int is_upcean = is_extendable(symbology); - char *reduced = gs1 ? (char *) alloca(expected_len + 1) : NULL; - char *escaped = is_escaped ? (char *) alloca(expected_len + 1) : NULL; - char *hibc = is_hibc ? (char *) alloca(expected_len + 2 + 1) : NULL; + char *reduced = gs1 ? (char *) testutil_alloca(expected_len + 1) : NULL; + char *escaped = is_escaped ? (char *) testutil_alloca(expected_len + 1) : NULL; + char *hibc = is_hibc ? (char *) testutil_alloca(expected_len + 2 + 1) : NULL; char *maxi = symbology == BARCODE_MAXICODE && primary - ? (char *) alloca(expected_len + strlen(primary) + 6 + 9 + 1) : NULL; - char *vin = symbology == BARCODE_VIN && (symbol->option_2 & 1) ? (char *) alloca(expected_len + 1 + 1) : NULL; - char *c25inter = have_c25inter ? (char *) alloca(expected_len + 13 + 1 + 1) : NULL; - char *dbar_exp = is_dbar_exp ? (char *) alloca(expected_len + 1) : NULL; - char *upcean = is_upcean ? (char *) alloca(expected_len + 1 + 1) : NULL; + ? (char *) testutil_alloca(expected_len + strlen(primary) + 6 + 9 + 1) : NULL; + char *vin = symbology == BARCODE_VIN && (symbol->option_2 & 1) ? (char *) testutil_alloca(expected_len + 1 + 1) : NULL; + char *c25inter = have_c25inter ? (char *) testutil_alloca(expected_len + 13 + 1 + 1) : NULL; + char *dbar_exp = is_dbar_exp ? (char *) testutil_alloca(expected_len + 1) : NULL; + char *upcean = is_upcean ? (char *) testutil_alloca(expected_len + 1 + 1) : NULL; char *ean14_nve18 = symbology == BARCODE_EAN14 || symbology == BARCODE_NVE18 - ? (char *) alloca(expected_len + 3 + 1) : NULL; + ? (char *) testutil_alloca(expected_len + 3 + 1) : NULL; int ret; int ret_memcmp; @@ -3417,7 +3559,7 @@ int testUtilZXingCPPCmp(struct zint_symbol *symbol, char *msg, char *cmp_buf, in } if (gs1 && symbology != BARCODE_EAN14 && symbology != BARCODE_NVE18) { ret = gs1_verify(symbol, (const unsigned char *) expected, expected_len, (unsigned char *) reduced); - if (ret != 0) { + if (ret >= ZINT_ERROR) { sprintf(msg, "gs1_verify %d != 0", ret); return 4; } @@ -3451,15 +3593,26 @@ int testUtilZXingCPPCmp(struct zint_symbol *symbol, char *msg, char *cmp_buf, in expected = hibc; } if (symbology == BARCODE_MAXICODE) { - if (symbol->primary && symbol->primary[0]) { + if (primary && primary[0]) { int primary_len = (int) strlen(primary); int maxi_len = 0; if (symbol->option_2 >= 1 && symbol->option_2 <= 100) { sprintf(maxi, "[)>\03601\035%02d", symbol->option_2 - 1); maxi_len = (int) strlen(maxi); } - sprintf(maxi + maxi_len, "%-6.*s\035%.*s\035%.*s\035", primary_len - 6, primary, + #if 1 + if (primary[0] > '9') { + sprintf(maxi + maxi_len, "%-6.*s\035%.*s\035%.*s\035", primary_len - 6, primary, + 3, primary + primary_len - 6, 3, primary + primary_len - 3); + } else { + sprintf(maxi + maxi_len, "%.*s\035%.*s\035%.*s\035", primary_len - 6, primary, + 3, primary + primary_len - 6, 3, primary + primary_len - 3); + } + #else + sprintf(maxi + maxi_len, "%.*s\035%.*s\035%.*s\035", primary_len - 6, primary, 3, primary + primary_len - 6, 3, primary + primary_len - 3); + #endif + printf("primary %s, primary_len %d\n", primary, primary_len); maxi_len = (int) strlen(maxi); memcpy(maxi + maxi_len, expected, expected_len); expected = maxi; @@ -3683,4 +3836,21 @@ int testUtilZXingCPPCmp(struct zint_symbol *symbol, char *msg, char *cmp_buf, in return 0; } +int testUtilZXingCPPCmpSegs(struct zint_symbol *symbol, char *msg, char *cmp_buf, int cmp_len, + const struct zint_seg segs[], const int seg_count, const char *primary, char *ret_buf, int *p_ret_len) { + int expected_len = segs_length(segs, seg_count); + char *expected = (char *) testutil_alloca(expected_len + 1); + char *s = expected; + int i; + + for (i = 0; i < seg_count; i++) { + int len = segs[i].length == -1 ? (int) ustrlen(segs[i].source) : segs[i].length; + memcpy(s, segs[i].source, len); + s += len; + } + *s = '\0'; + + return testUtilZXingCPPCmp(symbol, msg, cmp_buf, cmp_len, expected, expected_len, primary, ret_buf, p_ret_len); +} + /* vim: set ts=4 sw=4 et : */ diff --git a/backend/tests/testcommon.h b/backend/tests/testcommon.h index d54bb77e..45385525 100644 --- a/backend/tests/testcommon.h +++ b/backend/tests/testcommon.h @@ -111,6 +111,8 @@ void assert_notequal(int e1, int e2, ...); #define assert_notequal(__e1__, __e2__, ...) assert_exp((__e1__) != (__e2__), __VA_ARGS__) #endif +#define TU(p) ((unsigned char *) (p)) + INTERNAL void vector_free(struct zint_symbol *symbol); /* Free vector structures */ int testUtilSetSymbol(struct zint_symbol *symbol, int symbology, int input_mode, int eci, @@ -170,7 +172,9 @@ int testUtilVerifyTiffInfo(const char *filename, int debug); int testUtilCanBwipp(int index, const struct zint_symbol *symbol, int option_1, int option_2, int option_3, int debug); int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int option_2, int option_3, - const char *data, int length, const char *primary, char *buffer, int buffer_size); + const char *data, int length, const char *primary, char *buffer, int buffer_size, int *p_parsefnc); +int testUtilBwippSegs(int index, struct zint_symbol *symbol, int option_1, int option_2, int option_3, + const struct zint_seg segs[], const int seg_count, const char *primary, char *buffer, int buffer_size); int testUtilBwippCmp(const struct zint_symbol *symbol, char *msg, char *cmp_buf, const char *expected); int testUtilBwippCmpRow(const struct zint_symbol *symbol, int row, char *msg, const char *cmp_buf, const char *expected); @@ -180,8 +184,12 @@ int testUtilCanZXingCPP(int index, const struct zint_symbol *symbol, const char const int debug); int testUtilZXingCPP(int index, struct zint_symbol *symbol, const char *source, const int length, char *bits, char *buffer, const int buffer_size, int *p_cmp_len); +int testUtilZXingCPPSegs(int index, struct zint_symbol *symbol, const struct zint_seg segs[], const int seg_count, char *bits, + char *buffer, const int buffer_size, int *p_cmp_len); int testUtilZXingCPPCmp(struct zint_symbol *symbol, char *msg, char *cmp_buf, int cmp_len, const char *expected, int expected_len, const char *primary, char *ret_buf, int *p_ret_len); +int testUtilZXingCPPCmpSegs(struct zint_symbol *symbol, char *msg, char *cmp_buf, int cmp_len, + const struct zint_seg segs[], const int seg_count, const char *primary, char *ret_buf, int *p_ret_len); #ifdef __cplusplus } diff --git a/backend/tests/tools/bwipp_dump-barcode.ps.diff b/backend/tests/tools/bwipp_dump-barcode.ps.diff index ef09d12c..1b8cb48e 100644 --- a/backend/tests/tools/bwipp_dump-barcode.ps.diff +++ b/backend/tests/tools/bwipp_dump-barcode.ps.diff @@ -1,5 +1,5 @@ ---- /home/mburke/code/bwipp/postscriptbarcode/build/monolithic/barcode.ps 2022-04-04 14:55:50.742795871 +0100 -+++ backend/tests/tools/bwipp_dump.ps 2022-04-09 18:28:15.057483295 +0100 +--- /home/mburke/code/bwipp/postscriptbarcode/build/monolithic/barcode.ps 2022-05-09 17:52:29.878548024 +0100 ++++ backend/tests/tools/bwipp_dump.ps 2022-05-09 18:09:55.849954110 +0100 @@ -15187,8 +15187,8 @@ } bind /fime { @@ -11,7 +11,7 @@ } bind >> def -@@ -26445,34 +26445,80 @@ +@@ -26479,34 +26479,80 @@ pop } ifelse @@ -111,7 +111,7 @@ end -@@ -26531,7 +26577,7 @@ +@@ -26565,7 +26611,7 @@ pop } ifelse @@ -120,7 +120,7 @@ % Get the result of encoding with ean8 and gs1-cc options (lintype) (ean8) put -@@ -26539,29 +26585,75 @@ +@@ -26573,29 +26619,75 @@ options (dontdraw) true put % Plot the linear part @@ -216,7 +216,7 @@ end -@@ -26620,34 +26712,80 @@ +@@ -26654,34 +26746,80 @@ pop } ifelse @@ -316,7 +316,7 @@ end -@@ -26721,34 +26859,80 @@ +@@ -26755,34 +26893,80 @@ /opt options >> def @@ -416,7 +416,7 @@ end -@@ -26807,7 +26991,7 @@ +@@ -26841,7 +27025,7 @@ pop } ifelse @@ -425,7 +425,7 @@ options (lintype) (databaromni) put options (linkage) true put -@@ -26818,7 +27002,7 @@ +@@ -26852,7 +27036,7 @@ linear options //databaromni exec dup (sbs) get /linsbs exch def dup (bhs) get 0 get 72 mul /linheight exch def @@ -434,7 +434,7 @@ % Plot the separator /sepfinder { -@@ -26849,20 +27033,66 @@ +@@ -26883,20 +27067,66 @@ sep 0 [0 0 0] putinterval sep sep length 4 sub [0 0 0 0] putinterval 18 sepfinder 64 sepfinder @@ -513,7 +513,7 @@ end -@@ -26920,7 +27150,7 @@ +@@ -26954,7 +27184,7 @@ pop } ifelse @@ -522,7 +522,7 @@ options (lintype) (databarstacked) put options (linkage) true put -@@ -26931,7 +27161,7 @@ +@@ -26965,7 +27195,7 @@ linear options //databarstacked exec dup (pixs) get 0 2 index (pixx) get getinterval /bot exch def dup (pixy) get /linheight exch def @@ -531,7 +531,7 @@ % Plot the separator /sepfinder { -@@ -26959,20 +27189,52 @@ +@@ -26993,20 +27223,52 @@ sep 0 [ 0 0 0 0 ] putinterval sep sep length 4 sub [ 0 0 0 0 ] putinterval 18 sepfinder @@ -596,7 +596,7 @@ end -@@ -27030,7 +27292,7 @@ +@@ -27064,7 +27326,7 @@ pop } ifelse @@ -605,7 +605,7 @@ options (lintype) (databarstackedomni) put options (linkage) true put -@@ -27041,7 +27303,7 @@ +@@ -27075,7 +27337,7 @@ linear options //databarstackedomni exec dup (pixs) get 0 2 index (pixx) get getinterval /bot exch def dup (pixy) get /linheight exch def @@ -614,7 +614,7 @@ % Plot the separator /sepfinder { -@@ -27069,20 +27331,52 @@ +@@ -27103,20 +27365,52 @@ sep 0 [ 0 0 0 0 ] putinterval sep sep length 4 sub [ 0 0 0 0 ] putinterval 18 sepfinder @@ -679,7 +679,7 @@ end -@@ -27255,7 +27549,7 @@ +@@ -27289,7 +27583,7 @@ pop } ifelse @@ -688,7 +688,7 @@ options (lintype) (databarlimited) put options (linkage) true put -@@ -27266,7 +27560,7 @@ +@@ -27300,7 +27594,7 @@ linear options //databarlimited exec dup (sbs) get /linsbs exch def dup (bhs) get 0 get 72 mul /linheight exch def @@ -697,7 +697,7 @@ % Plot the separator mark -@@ -27274,22 +27568,68 @@ +@@ -27308,22 +27602,68 @@ counttomark 1 sub array astore /sep exch def pop pop sep 0 [0 0 0] putinterval sep sep length 9 sub [0 0 0 0 0 0 0 0 0] putinterval % 4 + 5 right guard spaces @@ -780,7 +780,7 @@ end -@@ -27348,7 +27688,7 @@ +@@ -27382,7 +27722,7 @@ pop } ifelse @@ -789,7 +789,7 @@ options (lintype) (databarexpanded) put options (linkage) true put -@@ -27359,7 +27699,7 @@ +@@ -27393,7 +27733,7 @@ linear options //databarexpanded exec dup (sbs) get /linsbs exch def dup (bhs) get 0 get 72 mul /linheight exch def @@ -798,7 +798,7 @@ % Plot the separator /sepfinder { -@@ -27388,20 +27728,60 @@ +@@ -27422,20 +27762,60 @@ 18 98 bot length 13 sub {} for 69 98 bot length 13 sub {} for ] {sepfinder} forall @@ -871,7 +871,7 @@ end -@@ -27459,7 +27839,7 @@ +@@ -27493,7 +27873,7 @@ pop } ifelse @@ -880,7 +880,7 @@ options (lintype) (databarexpandedstacked) put options (linkage) true put -@@ -27470,7 +27850,7 @@ +@@ -27504,7 +27884,7 @@ linear options //databarexpandedstacked exec dup (pixs) get 0 2 index (pixx) get getinterval /bot exch def dup (pixy) get /linheight exch def @@ -889,7 +889,7 @@ % Plot the separator /sepfinder { -@@ -27496,21 +27876,49 @@ +@@ -27530,21 +27910,49 @@ 19 98 bot length 13 sub {} for 70 98 bot length 13 sub {} for ] {sepfinder} forall @@ -952,7 +952,7 @@ end -@@ -27569,7 +27977,7 @@ +@@ -27603,7 +28011,7 @@ pop } ifelse @@ -961,7 +961,7 @@ options (inkspread) (0) put options (dontdraw) true put -@@ -27596,35 +28004,87 @@ +@@ -27630,35 +28038,87 @@ linear << options {} forall >> //gs1-128 exec dup (sbs) get /linsbs exch def dup (bhs) get 0 get 72 mul /linheight exch def @@ -1063,7 +1063,7 @@ end -@@ -29057,3 +29517,189 @@ +@@ -29091,3 +29551,189 @@ % --END ENCODER hibcazteccode-- % --END TEMPLATE-- diff --git a/backend/tests/tools/bwipp_dump.ps.tar.xz b/backend/tests/tools/bwipp_dump.ps.tar.xz index f7d2a2c1259592e27f56dbceff421b887a0acfe8..1a7be66b847cfa45413b4a3e62eae4e26d80e038 100644 GIT binary patch literal 124608 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

vxwCeoYd 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 diff --git a/backend/tests/tools/run_bwipp_tests.sh b/backend/tests/tools/run_bwipp_tests.sh index 7249c3ca..ba9b1255 100755 --- a/backend/tests/tools/run_bwipp_tests.sh +++ b/backend/tests/tools/run_bwipp_tests.sh @@ -16,27 +16,33 @@ function run_bwipp_test() { run_bwipp_test "test_2of5" "encode" run_bwipp_test "test_auspost" "encode" run_bwipp_test "test_aztec" "encode" +run_bwipp_test "test_aztec" "encode_segs" run_bwipp_test "test_channel" "encode" run_bwipp_test "test_codablock" "encode" run_bwipp_test "test_code" "encode" run_bwipp_test "test_code1" "encode" +run_bwipp_test "test_code1" "encode_segs" run_bwipp_test "test_code128" "encode" run_bwipp_test "test_code16k" "encode" run_bwipp_test "test_code49" "encode" run_bwipp_test "test_composite" run_bwipp_test "test_dmatrix" "input" run_bwipp_test "test_dmatrix" "encode" +run_bwipp_test "test_dmatrix" "encode_segs" +run_bwipp_test "test_dotcode" "input" run_bwipp_test "test_dotcode" "encode" +run_bwipp_test "test_dotcode" "encode_segs" run_bwipp_test "test_gs1" "gs1_reduce" run_bwipp_test "test_imail" "encode" +run_bwipp_test "test_maxicode" "input" run_bwipp_test "test_maxicode" "encode" +run_bwipp_test "test_maxicode" "encode_segs" run_bwipp_test "test_medical" "encode" run_bwipp_test "test_pdf417" "encode" +run_bwipp_test "test_pdf417" "encode_segs" run_bwipp_test "test_plessey" "encode" run_bwipp_test "test_postal" "encode" -run_bwipp_test "test_qr" "qr_encode" -run_bwipp_test "test_qr" "microqr_encode" -run_bwipp_test "test_qr" "rmqr_encode" +run_bwipp_test "test_qr" run_bwipp_test "test_rss" run_bwipp_test "test_telepen" "encode" run_bwipp_test "test_upcean" "upce_input" diff --git a/backend/tests/tools/run_zxingcpp_tests.sh b/backend/tests/tools/run_zxingcpp_tests.sh index 0f261e02..fdc083a9 100755 --- a/backend/tests/tools/run_zxingcpp_tests.sh +++ b/backend/tests/tools/run_zxingcpp_tests.sh @@ -10,16 +10,28 @@ function run_zxingcpp_test() { run_zxingcpp_test "test_2of5" "encode" run_zxingcpp_test "test_aztec" "encode" +run_zxingcpp_test "test_aztec" "encode_segs" run_zxingcpp_test "test_code" "encode" run_zxingcpp_test "test_code128" "encode" run_zxingcpp_test "test_dmatrix" "input" run_zxingcpp_test "test_dmatrix" "encode" +run_zxingcpp_test "test_dmatrix" "encode_segs" +run_zxingcpp_test "test_dotcode" "input" run_zxingcpp_test "test_dotcode" "encode" +run_zxingcpp_test "test_dotcode" "encode_segs" +run_zxingcpp_test "test_hanxin" "input" run_zxingcpp_test "test_hanxin" "encode" +run_zxingcpp_test "test_hanxin" "encode_segs" +run_zxingcpp_test "test_maxicode" "input" run_zxingcpp_test "test_maxicode" "encode" +run_zxingcpp_test "test_maxicode" "encode_segs" run_zxingcpp_test "test_medical" "encode" run_zxingcpp_test "test_pdf417" "encode" +run_zxingcpp_test "test_pdf417" "encode_segs" +run_zxingcpp_test "test_qr" "qr_input" +run_zxingcpp_test "test_qr" "qr_optimize" run_zxingcpp_test "test_qr" "qr_encode" +run_zxingcpp_test "test_qr" "qr_encode_segs" run_zxingcpp_test "test_rss" "binary_div_modulo_divisor" run_zxingcpp_test "test_rss" "examples" run_zxingcpp_test "test_upcean" "upce_input" diff --git a/backend/ultra.c b/backend/ultra.c index 4fbc23c9..b9758c5c 100644 --- a/backend/ultra.c +++ b/backend/ultra.c @@ -1,7 +1,7 @@ /* ultra.c - Ultracode libzint - the open source barcode library - Copyright (C) 2020 - 2021 Robin Stuart + Copyright (C) 2020-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -28,7 +28,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ /* This version was developed using AIMD/TSC15032-43 v0.99c Edit 60, dated 4th Nov 2015 */ @@ -38,35 +37,35 @@ #include #include "common.h" -#define EIGHTBIT_MODE 10 -#define ASCII_MODE 20 -#define C43_MODE 30 +#define ULT_EIGHTBIT_MODE 10 +#define ULT_ASCII_MODE 20 +#define ULT_C43_MODE 30 -#define PREDICT_WINDOW 12 +#define ULT_PREDICT_WINDOW 12 -#define GFMUL(i, j) ((((i) == 0)||((j) == 0)) ? 0 : gfPwr[(gfLog[i] + gfLog[j])]) +#define ULT_GFMUL(i, j) ((((i) == 0)||((j) == 0)) ? 0 : gfPwr[(gfLog[i] + gfLog[j])]) -static const char fragment[27][13] = {"http://", "https://", "http://www.", "https://www.", +static const char ult_fragment[27][13] = {"http://", "https://", "http://www.", "https://www.", "ftp://", "www.", ".com", ".edu", ".gov", ".int", ".mil", ".net", ".org", ".mobi", ".coop", ".biz", ".info", "mailto:", "tel:", ".cgi", ".asp", ".aspx", ".php", ".htm", ".html", ".shtml", "file:"}; -static const char ultra_c43_set1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 .,%"; -static const char ultra_c43_set2[] = "abcdefghijklmnopqrstuvwxyz:/?#[]@=_~!.,-"; -static const char ultra_c43_set3[] = "{}`()\"+'<>|$;&\\^*"; -static const char ultra_digit[] = "0123456789,/"; -static const char ultra_colour[] = "0CBMRYGKW"; +static const char ult_c43_set1[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 .,%"; +static const char ult_c43_set2[] = "abcdefghijklmnopqrstuvwxyz:/?#[]@=_~!.,-"; +static const char ult_c43_set3[] = "{}`()\"+'<>|$;&\\^*"; +static const char ult_digit[] = "0123456789,/"; +static const char ult_colour[] = "0CBMRYGKW"; // Max size and min cols adjusted to BWIPP values as updated 2021-07-14 // https://github.com/bwipp/postscriptbarcode/commit/4255810845fa8d45c6192dd30aee1fdad1aaf0cc -static const int ultra_maxsize[] = {37, 84, 161, 282}; +static const int ult_maxsize[] = {37, 84, 161, 282}; -static const int ultra_mincols[] = {5, 13, 22, 29}; +static const int ult_mincols[] = {5, 13, 22, 29}; -static const int kec[] = {0, 1, 2, 4, 6, 8}; // Value K(EC) from Table 12 +static const int ult_kec[] = {0, 1, 2, 4, 6, 8}; // Value K(EC) from Table 12 /* Taken from BWIPP - change in DCCU/DCCL tiles for revision 2 2021-09-28 */ -static const unsigned short dccu[2][32] = { +static const unsigned short ult_dccu[2][32] = { { // Revision 1 051363, 051563, 051653, 053153, 053163, 053513, 053563, 053613, // 0-7 053653, 056153, 056163, 056313, 056353, 056363, 056513, 056563, // 8-15 @@ -81,7 +80,7 @@ static const unsigned short dccu[2][32] = { }, }; -static const unsigned short dccl[2][32] = { +static const unsigned short ult_dccl[2][32] = { { // Revision 1 061351, 061361, 061531, 061561, 061631, 061651, 063131, 063151, // 0-7 063161, 063531, 063561, 063631, 065131, 065161, 065351, 065631, // 8-15 @@ -96,7 +95,7 @@ static const unsigned short dccl[2][32] = { }, }; -static const int tiles[] = { +static const int ult_tiles[] = { 013135, 013136, 013153, 013156, 013163, 013165, 013513, 013515, 013516, 013531, // 0-9 013535, 013536, 013561, 013563, 013565, 013613, 013615, 013616, 013631, 013635, // 10-19 013636, 013651, 013653, 013656, 015135, 015136, 015153, 015163, 015165, 015313, // 20-29 @@ -147,7 +146,8 @@ static const int tiles[] = { */ /* Generate divisor polynomial gQ(x) for GF283() given the required ECC size, 3 to 101 */ -static void ultra_genPoly(short EccSize, unsigned short gPoly[], unsigned short gfPwr[], unsigned short gfLog[]) { +static void ult_genPoly(const short EccSize, unsigned short gPoly[], const unsigned short gfPwr[], + const unsigned short gfLog[]) { int i, j; gPoly[0] = 1; @@ -155,8 +155,8 @@ static void ultra_genPoly(short EccSize, unsigned short gPoly[], unsigned short for (i = 0; i < EccSize; i++) { for (j = i; j >= 0; j--) - gPoly[j + 1] = (gPoly[j] + GFMUL(gPoly[j + 1], gfPwr[i + 1])) % 283; - gPoly[0] = GFMUL(gPoly[0], gfPwr[i + 1]); + gPoly[j + 1] = (gPoly[j] + ULT_GFMUL(gPoly[j + 1], gfPwr[i + 1])) % 283; + gPoly[0] = ULT_GFMUL(gPoly[0], gfPwr[i + 1]); } for (i = EccSize - 1; i >= 0; i -= 2) gPoly[i] = 283 - gPoly[i]; @@ -164,20 +164,20 @@ static void ultra_genPoly(short EccSize, unsigned short gPoly[], unsigned short } /* Generate the log and antilog tables for GF283() multiplication & division */ -static void ultra_initLogTables(unsigned short gfPwr[], unsigned short gfLog[]) { +static void ult_initLogTables(unsigned short gfPwr[], unsigned short gfLog[]) { int i, j; for (j = 0; j < 283; j++) gfLog[j] = 0; i = 1; for (j = 0; j < 282; j++) { - /* j + 282 indices save doing the modulo operation in GFMUL */ + /* j + 282 indices save doing the modulo operation in ULT_GFMUL */ gfPwr[j + 282] = gfPwr[j] = (short) i; gfLog[i] = (short) j; i = (i * 3) % 283; } } -static void ultra_gf283(short DataSize, short EccSize, int Message[]) { +static void ult_gf283(const short DataSize, const short EccSize, int Message[]) { /* Input is complete message codewords in array Message[282] * DataSize is number of message codewords * EccSize is number of Reed-Solomon GF(283) check codewords to generate @@ -190,10 +190,10 @@ static void ultra_gf283(short DataSize, short EccSize, int Message[]) { unsigned short t; /* first build the log & antilog tables used in multiplication & division */ - ultra_initLogTables(gfPwr, gfLog); + ult_initLogTables(gfPwr, gfLog); /* then generate the division polynomial of length EccSize */ - ultra_genPoly(EccSize, gPoly, gfPwr, gfLog); + ult_genPoly(EccSize, gPoly, gfPwr, gfLog); /* zero all EccSize codeword values */ for (j = 281; (j > (281 - EccSize)); j--) Message[j] = 0; @@ -210,9 +210,9 @@ static void ultra_gf283(short DataSize, short EccSize, int Message[]) { t = (Message[j + DataSize] + Message[n]) % 283; for (i = 0; i < (EccSize - 1); i++) { Message[j + DataSize + i] = (Message[j + DataSize + i + 1] + 283 - - GFMUL(t, gPoly[EccSize - 1 - i])) % 283; + - ULT_GFMUL(t, gPoly[EccSize - 1 - i])) % 283; } - Message[j + DataSize + EccSize - 1] = (283 - GFMUL(t, gPoly[0])) % 283; + Message[j + DataSize + EccSize - 1] = (283 - ULT_GFMUL(t, gPoly[0])) % 283; } for (i = j + DataSize; i < (j + DataSize + EccSize); i++) Message[i] = (283 - Message[i]) % 283; @@ -220,17 +220,17 @@ static void ultra_gf283(short DataSize, short EccSize, int Message[]) { /* End of Ted Williams code */ -static int ultra_find_fragment(const unsigned char source[], int source_length, int position) { +static int ult_find_fragment(const unsigned char source[], const int length, const int position) { int retval = -1; int j, k, latch, fraglen; for (j = 0; j < 27; j++) { latch = 0; - fraglen = (int) strlen(fragment[j]); - if ((position + fraglen) <= source_length) { + fraglen = (int) strlen(ult_fragment[j]); + if ((position + fraglen) <= length) { latch = 1; for (k = 0; k < fraglen; k++) { - if (source[position + k] != fragment[j][k]) { + if (source[position + k] != ult_fragment[j][k]) { latch = 0; break; } @@ -246,19 +246,19 @@ static int ultra_find_fragment(const unsigned char source[], int source_length, } /* Encode characters in 8-bit mode */ -static float look_ahead_eightbit(unsigned char source[], int in_length, int in_locn, char current_mode, int end_char, - int cw[], int *cw_len, int gs1) { +static float ult_look_ahead_eightbit(const unsigned char source[], const int length, const int in_locn, + const int current_mode, const int end_char, int cw[], int *cw_len, const int gs1) { int codeword_count = 0; int i; int letters_encoded = 0; - if (current_mode != EIGHTBIT_MODE) { + if (current_mode != ULT_EIGHTBIT_MODE) { cw[codeword_count] = 282; // Unlatch codeword_count += 1; } i = in_locn; - while ((i < in_length) && (i < end_char)) { + while ((i < length) && (i < end_char)) { if ((source[i] == '[') && gs1) { cw[codeword_count] = 268; // FNC1 } else { @@ -279,22 +279,23 @@ static float look_ahead_eightbit(unsigned char source[], int in_length, int in_l } /* Encode character in the ASCII mode/submode (including numeric compression) */ -static float look_ahead_ascii(unsigned char source[], int in_length, int in_locn, char current_mode, int symbol_mode, - int end_char, int cw[], int *cw_len, int *encoded, int gs1) { +static float ult_look_ahead_ascii(unsigned char source[], const int length, const int in_locn, + const int current_mode, const int symbol_mode, const int end_char, int cw[], int *cw_len, int *encoded, + const int gs1) { int codeword_count = 0; int i; int first_digit, second_digit, done; int letters_encoded = 0; - if (current_mode == EIGHTBIT_MODE) { + if (current_mode == ULT_EIGHTBIT_MODE) { cw[codeword_count] = 267; // Latch ASCII Submode codeword_count++; } - if (current_mode == C43_MODE) { + if (current_mode == ULT_C43_MODE) { cw[codeword_count] = 282; // Unlatch codeword_count++; - if (symbol_mode == EIGHTBIT_MODE) { + if (symbol_mode == ULT_EIGHTBIT_MODE) { cw[codeword_count] = 267; // Latch ASCII Submode codeword_count++; } @@ -304,9 +305,9 @@ static float look_ahead_ascii(unsigned char source[], int in_length, int in_locn do { /* Check for double digits */ done = 0; - if (i + 1 < in_length) { - first_digit = posn(ultra_digit, source[i]); - second_digit = posn(ultra_digit, source[i + 1]); + if (i + 1 < length) { + first_digit = posn(ult_digit, source[i]); + second_digit = posn(ult_digit, source[i + 1]); if ((first_digit != -1) && (second_digit != -1)) { /* Double digit can be encoded */ if ((first_digit >= 0) && (first_digit <= 9) && (second_digit >= 0) && (second_digit <= 9)) { @@ -352,7 +353,7 @@ static float look_ahead_ascii(unsigned char source[], int in_length, int in_locn codeword_count++; i++; } - } while ((i < in_length) && (i < end_char) && (source[i] < 0x80)); + } while ((i < length) && (i < end_char) && (source[i] < 0x80)); letters_encoded = i - in_locn; if (encoded != NULL) { @@ -368,12 +369,12 @@ static float look_ahead_ascii(unsigned char source[], int in_length, int in_locn } /* Returns true if should latch to subset other than given `subset` */ -static int c43_should_latch_other(const unsigned char data[], const int length, const int locn, const int subset, - const int gs1) { +static int ult_c43_should_latch_other(const unsigned char source[], const int length, const int locn, + const int subset, const int gs1) { int i, fraglen, predict_window; int cnt, alt_cnt, fragno; - const char *const set = subset == 1 ? ultra_c43_set1 : ultra_c43_set2; - const char *const alt_set = subset == 2 ? ultra_c43_set1 : ultra_c43_set2; + const char *const set = subset == 1 ? ult_c43_set1 : ult_c43_set2; + const char *const alt_set = subset == 2 ? ult_c43_set1 : ult_c43_set2; if (locn + 3 > length) { return 0; @@ -381,23 +382,23 @@ static int c43_should_latch_other(const unsigned char data[], const int length, predict_window = locn + 3; for (i = locn, cnt = 0, alt_cnt = 0; i < predict_window; i++) { - if (data[i] <= 0x1F || data[i] >= 0x7F || (gs1 && data[i] == '[')) { + if (source[i] <= 0x1F || source[i] >= 0x7F || (gs1 && source[i] == '[')) { break; } - fragno = ultra_find_fragment(data, length, i); + fragno = ult_find_fragment(source, length, i); if (fragno != -1 && fragno != 26) { - fraglen = (int) strlen(fragment[fragno]); + fraglen = (int) strlen(ult_fragment[fragno]); predict_window += fraglen; if (predict_window > length) { predict_window = length; } i += fraglen - 1; } else { - if (posn(set, data[i]) != -1) { + if (posn(set, source[i]) != -1) { cnt++; } - if (posn(alt_set, data[i]) != -1) { + if (posn(alt_set, source[i]) != -1) { alt_cnt++; } } @@ -406,29 +407,30 @@ static int c43_should_latch_other(const unsigned char data[], const int length, return alt_cnt > cnt; } -static int get_subset(unsigned char source[], int in_length, int in_locn, int current_subset) { +static int ult_get_subset(const unsigned char source[], const int length, const int in_locn, + const int current_subset) { int fragno; int subset = 0; - fragno = ultra_find_fragment(source, in_length, in_locn); + fragno = ult_find_fragment(source, length, in_locn); if ((fragno != -1) && (fragno != 26)) { subset = 3; } else if (current_subset == 2) { - if (posn(ultra_c43_set2, source[in_locn]) != -1) { + if (posn(ult_c43_set2, source[in_locn]) != -1) { subset = 2; - } else if (posn(ultra_c43_set1, source[in_locn]) != -1) { + } else if (posn(ult_c43_set1, source[in_locn]) != -1) { subset = 1; } } else { - if (posn(ultra_c43_set1, source[in_locn]) != -1) { + if (posn(ult_c43_set1, source[in_locn]) != -1) { subset = 1; - } else if (posn(ultra_c43_set2, source[in_locn]) != -1) { + } else if (posn(ult_c43_set2, source[in_locn]) != -1) { subset = 2; } } if (subset == 0) { - if (posn(ultra_c43_set3, source[in_locn]) != -1) { + if (posn(ult_c43_set3, source[in_locn]) != -1) { subset = 3; } } @@ -437,8 +439,9 @@ static int get_subset(unsigned char source[], int in_length, int in_locn, int cu } /* Encode characters in the C43 compaction submode */ -static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, char current_mode, int end_char, - int subset, int cw[], int *cw_len, int *encoded, int gs1, int debug) { +static float ult_look_ahead_c43(const unsigned char source[], const int length, const int in_locn, + const int current_mode, const int end_char, int subset, int cw[], int *cw_len, int *encoded, + const int gs1, const int debug_print) { int codeword_count = 0; int subcodeword_count = 0; int i; @@ -451,14 +454,14 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, int pad; #ifndef _MSC_VER - int subcw[(in_length + 3) * 2]; + int subcw[(length + 3) * 2]; #else - int *subcw = (int *) _alloca((in_length + 3) * 2 * sizeof(int)); + int *subcw = (int *) _alloca((length + 3) * 2 * sizeof(int)); #endif /* _MSC_VER */ - if (current_mode == EIGHTBIT_MODE) { + if (current_mode == ULT_EIGHTBIT_MODE) { /* Check for permissable URL C43 macro sequences, otherwise encode directly */ - fragno = ultra_find_fragment(source, in_length, sublocn); + fragno = ult_find_fragment(source, length, sublocn); if ((fragno == 2) || (fragno == 3)) { // http://www. > http:// @@ -469,32 +472,32 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, switch (fragno) { case 17: // mailto: cw[codeword_count] = 276; - sublocn += (int) strlen(fragment[fragno]); + sublocn += (int) strlen(ult_fragment[fragno]); codeword_count++; break; case 18: // tel: cw[codeword_count] = 277; - sublocn += (int) strlen(fragment[fragno]); + sublocn += (int) strlen(ult_fragment[fragno]); codeword_count++; break; case 26: // file: cw[codeword_count] = 278; - sublocn += (int) strlen(fragment[fragno]); + sublocn += (int) strlen(ult_fragment[fragno]); codeword_count++; break; case 0: // http:// cw[codeword_count] = 279; - sublocn += (int) strlen(fragment[fragno]); + sublocn += (int) strlen(ult_fragment[fragno]); codeword_count++; break; case 1: // https:// cw[codeword_count] = 280; - sublocn += (int) strlen(fragment[fragno]); + sublocn += (int) strlen(ult_fragment[fragno]); codeword_count++; break; case 4: // ftp:// cw[codeword_count] = 281; - sublocn += (int) strlen(fragment[fragno]); + sublocn += (int) strlen(ult_fragment[fragno]); codeword_count++; break; default: @@ -508,7 +511,7 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, break; } - } else if (current_mode == ASCII_MODE) { + } else if (current_mode == ULT_ASCII_MODE) { if (subset == 1) { cw[codeword_count] = 278; // C43 Compaction Submode C1 codeword_count++; @@ -519,27 +522,27 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, } unshift_set = subset; - while ((sublocn < in_length) && (sublocn < end_char)) { + while ((sublocn < length) && (sublocn < end_char)) { /* Check for FNC1 */ if (gs1 && source[sublocn] == '[') { break; } - new_subset = get_subset(source, in_length, sublocn, subset); + new_subset = ult_get_subset(source, length, sublocn, subset); if (new_subset == 0) { break; } if ((new_subset != subset) && ((new_subset == 1) || (new_subset == 2))) { - if (c43_should_latch_other(source, in_length, sublocn, subset, gs1)) { + if (ult_c43_should_latch_other(source, length, sublocn, subset, gs1)) { subcw[subcodeword_count] = 42; // Latch to other C43 set subcodeword_count++; unshift_set = new_subset; } else { subcw[subcodeword_count] = 40; // Shift to other C43 set for 1 char subcodeword_count++; - subcw[subcodeword_count] = posn(new_subset == 1 ? ultra_c43_set1 : ultra_c43_set2, source[sublocn]); + subcw[subcodeword_count] = posn(new_subset == 1 ? ult_c43_set1 : ult_c43_set2, source[sublocn]); subcodeword_count++; sublocn++; continue; @@ -549,30 +552,30 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, subset = new_subset; if (subset == 1) { - subcw[subcodeword_count] = posn(ultra_c43_set1, source[sublocn]); + subcw[subcodeword_count] = posn(ult_c43_set1, source[sublocn]); subcodeword_count++; sublocn++; } else if (subset == 2) { - subcw[subcodeword_count] = posn(ultra_c43_set2, source[sublocn]); + subcw[subcodeword_count] = posn(ult_c43_set2, source[sublocn]); subcodeword_count++; sublocn++; } else if (subset == 3) { subcw[subcodeword_count] = 41; // Shift to set 3 subcodeword_count++; - fragno = ultra_find_fragment(source, in_length, sublocn); + fragno = ult_find_fragment(source, length, sublocn); if (fragno != -1 && fragno != 26) { if (fragno <= 18) { subcw[subcodeword_count] = fragno; // C43 Set 3 codewords 0 to 18 subcodeword_count++; - sublocn += (int) strlen(fragment[fragno]); + sublocn += (int) strlen(ult_fragment[fragno]); } else { subcw[subcodeword_count] = fragno + 17; // C43 Set 3 codewords 36 to 42 subcodeword_count++; - sublocn += (int) strlen(fragment[fragno]); + sublocn += (int) strlen(ult_fragment[fragno]); } } else { - subcw[subcodeword_count] = posn(ultra_c43_set3, source[sublocn]) + 19; // C43 Set 3 codewords 19 to 35 + subcw[subcodeword_count] = posn(ult_c43_set3, source[sublocn]) + 19; // C43 Set 3 codewords 19 to 35 subcodeword_count++; sublocn++; } @@ -590,8 +593,8 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, subcodeword_count++; } - if (debug & ZINT_DEBUG_PRINT) { - printf("C43 codewords %.*s: (%d)", in_length, source + in_locn, subcodeword_count); + if (debug_print) { + printf("C43 codewords %.*s: (%d)", length, source + in_locn, subcodeword_count); for (i = 0; i < subcodeword_count; i++) printf( " %d", subcw[i]); printf("\n"); } @@ -618,14 +621,13 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, } /* Produces a set of codewords which are "somewhat" optimised - this could be improved on */ -static int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned char source[], const int in_length, - int codewords[]) { +static int ult_generate_codewords(struct zint_symbol *symbol, const unsigned char source[], const int length, + const int eci, const int gs1, const int symbol_mode, int *p_current_mode, int codewords[], + int codeword_count) { int i; int crop_length; - int codeword_count = 0; int input_locn = 0; - char symbol_mode; - char current_mode; + int current_mode; int subset; float eightbit_score; float ascii_score; @@ -633,136 +635,43 @@ static int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned c int end_char; int block_length; int fragment_length; - int fragno; - int gs1 = 0; int ascii_encoded, c43_encoded; + const int debug_print = (symbol->debug & ZINT_DEBUG_PRINT); #ifndef _MSC_VER - unsigned char crop_source[in_length + 1]; - char mode[in_length + 1]; - int cw_fragment[in_length * 2 + 1]; + unsigned char crop_source[length + 1]; + char mode[length + 1]; + int cw_fragment[length * 2 + 1]; #else - unsigned char *crop_source = (unsigned char *) _alloca(in_length + 1); - char *mode = (char *) _alloca(in_length + 1); - int *cw_fragment = (int *) _alloca((in_length * 2 + 1) * sizeof(int)); + unsigned char *crop_source = (unsigned char *) _alloca(length + 1); + char *mode = (char *) _alloca(length + 1); + int *cw_fragment = (int *) _alloca((length * 2 + 1) * sizeof(int)); #endif /* _MSC_VER */ - if ((symbol->input_mode & 0x07) == GS1_MODE) { - gs1 = 1; - } - - // Decide start character codeword (from Table 5) - symbol_mode = ASCII_MODE; - for (i = 0; i < in_length; i++) { - if (source[i] >= 0x80) { - symbol_mode = EIGHTBIT_MODE; - break; - } - } - - if (symbol->option_3 != ULTRA_COMPRESSION && !gs1) { - // Force eight-bit mode by default as other modes are poorly documented - symbol_mode = EIGHTBIT_MODE; - } - - if (symbol->output_options & READER_INIT) { - /* Reader Initialisation mode */ - codeword_count = 2; - if (symbol_mode == ASCII_MODE) { - codewords[0] = 272; // 7-bit ASCII mode - codewords[1] = 271; // FNC3 - } else { - codewords[0] = 257; // 8859-1 - codewords[1] = 269; // FNC3 - } - } else { - /* Calculate start character codeword */ - codeword_count = 1; - if (symbol_mode == ASCII_MODE) { - if (gs1) { - codewords[0] = 273; - } else { - codewords[0] = 272; - } - } else { - if ((symbol->eci >= 3) && (symbol->eci <= 18) && (symbol->eci != 14)) { - // ECI indicates use of character set within ISO/IEC 8859 - codewords[0] = 257 + (symbol->eci - 3); - if (codewords[0] > 267) { - // Avoids ECI 14 for non-existant ISO/IEC 8859-12 - codewords[0]--; - } - } else if ((symbol->eci > 18) && (symbol->eci <= 898)) { - // ECI indicates use of character set outside ISO/IEC 8859 - codewords[0] = 275 + (symbol->eci / 256); - codewords[1] = symbol->eci % 256; - codeword_count = 2; - } else if (symbol->eci == 899) { - // Non-language byte data - codewords[0] = 280; - } else if ((symbol->eci > 899) && (symbol->eci <= 9999)) { - // ECI beyond 899 needs to use fixed length encodable ECI invocation (section 7.6.2) - // Encode as 3 codewords - codewords[0] = 257; // ISO/IEC 8859-1 used to enter 8-bit mode - codewords[1] = 274; // Encode ECI as 3 codewords - codewords[2] = (symbol->eci / 100) + 128; - codewords[3] = (symbol->eci % 100) + 128; - codeword_count = 4; - } else if (symbol->eci >= 10000) { - // Encode as 4 codewords - codewords[0] = 257; // ISO/IEC 8859-1 used to enter 8-bit mode - codewords[1] = 275; // Encode ECI as 4 codewords - codewords[2] = (symbol->eci / 10000) + 128; - codewords[3] = ((symbol->eci % 10000) / 100) + 128; - codewords[4] = (symbol->eci % 100) + 128; - codeword_count = 5; - } else { - codewords[0] = 257; // Default is assumed to be ISO/IEC 8859-1 (ECI 3) - } - } - - if ((codewords[0] == 257) || (codewords[0] == 272)) { - fragno = ultra_find_fragment(source, in_length, 0); - - // Check for http:// at start of input - if ((fragno == 0) || (fragno == 2)) { - codewords[0] = 281; - input_locn = 7; - symbol_mode = EIGHTBIT_MODE; - - // Check for https:// at start of input - } else if ((fragno == 1) || (fragno == 3)) { - codewords[0] = 282; - input_locn = 8; - symbol_mode = EIGHTBIT_MODE; - } - } - } - /* Check for 06 Macro Sequence and crop accordingly */ - if (in_length >= 9 + if (length >= 9 && source[0] == '[' && source[1] == ')' && source[2] == '>' && source[3] == '\x1e' && source[4] == '0' && source[5] == '6' && source[6] == '\x1d' - && source[in_length - 2] == '\x1e' && source[in_length - 1] == '\x04') { + && source[length - 2] == '\x1e' && source[length - 1] == '\x04') { - if (symbol_mode == EIGHTBIT_MODE) { + if (symbol_mode == ULT_EIGHTBIT_MODE) { codewords[codeword_count] = 271; // 06 Macro } else { codewords[codeword_count] = 273; // 06 Macro } codeword_count++; - for (i = 7; i < (in_length - 2); i++) { + for (i = 7; i < (length - 2); i++) { crop_source[i - 7] = source[i]; } - crop_length = in_length - 9; + crop_length = length - 9; crop_source[crop_length] = '\0'; } else { /* Make a cropped version of input data - removes http:// and https:// if needed */ - for (i = input_locn; i < in_length; i++) { + for (i = input_locn; i < length; i++) { crop_source[i - input_locn] = source[i]; } - crop_length = in_length - input_locn; + crop_length = length - input_locn; crop_source[crop_length] = '\0'; } @@ -771,24 +680,24 @@ static int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned c current_mode = symbol_mode; input_locn = 0; do { - end_char = input_locn + PREDICT_WINDOW; - eightbit_score = look_ahead_eightbit(crop_source, crop_length, input_locn, current_mode, end_char, + end_char = input_locn + ULT_PREDICT_WINDOW; + eightbit_score = ult_look_ahead_eightbit(crop_source, crop_length, input_locn, current_mode, end_char, cw_fragment, &fragment_length, gs1); - ascii_score = look_ahead_ascii(crop_source, crop_length, input_locn, current_mode, symbol_mode, + ascii_score = ult_look_ahead_ascii(crop_source, crop_length, input_locn, current_mode, symbol_mode, end_char, cw_fragment, &fragment_length, &ascii_encoded, gs1); - subset = c43_should_latch_other(crop_source, crop_length, input_locn, 1 /*subset*/, gs1) ? 2 : 1; - c43_score = look_ahead_c43(crop_source, crop_length, input_locn, current_mode, end_char, - subset, cw_fragment, &fragment_length, &c43_encoded, gs1, 0 /*debug*/); + subset = ult_c43_should_latch_other(crop_source, crop_length, input_locn, 1 /*subset*/, gs1) ? 2 : 1; + c43_score = ult_look_ahead_c43(crop_source, crop_length, input_locn, current_mode, end_char, + subset, cw_fragment, &fragment_length, &c43_encoded, gs1, 0 /*debug_print*/); mode[input_locn] = 'a'; - current_mode = ASCII_MODE; + current_mode = ULT_ASCII_MODE; if ((c43_score > ascii_score) && (c43_score > eightbit_score)) { mode[input_locn] = 'c'; - current_mode = C43_MODE; + current_mode = ULT_C43_MODE; } else if ((eightbit_score > ascii_score) && (eightbit_score > c43_score)) { mode[input_locn] = '8'; - current_mode = EIGHTBIT_MODE; + current_mode = ULT_EIGHTBIT_MODE; } if (mode[input_locn] == 'a') { for (i = 0; i < ascii_encoded; i++) { @@ -812,10 +721,31 @@ static int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned c } mode[crop_length] = '\0'; - if (symbol->debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Mode (%d): %s\n", (int) strlen(mode), mode); } + if (symbol_mode == ULT_EIGHTBIT_MODE && *p_current_mode != ULT_EIGHTBIT_MODE) { + codewords[codeword_count++] = 282; // Unlatch to 8-bit mode + } + + if (eci) { + if (eci < 899) { + codewords[codeword_count++] = 272; + codewords[codeword_count++] = eci / 256; + codewords[codeword_count++] = eci % 256; + } else if (eci < 10000) { + codewords[codeword_count++] = 274; + codewords[codeword_count++] = eci / 100 + 128; + codewords[codeword_count++] = eci % 100 + 128; + } else { + codewords[codeword_count++] = 275; + codewords[codeword_count++] = eci / 10000 + 128; + codewords[codeword_count++] = (eci % 10000) / 100 + 128; + codewords[codeword_count++] = eci % 100 + 128; + } + } + /* Use results from test to perform actual mode switching */ current_mode = symbol_mode; input_locn = 0; @@ -828,36 +758,33 @@ static int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned c switch (mode[input_locn]) { case 'a': - look_ahead_ascii(crop_source, crop_length, input_locn, current_mode, symbol_mode, - input_locn + block_length, cw_fragment, &fragment_length, NULL, gs1); - current_mode = ASCII_MODE; + ult_look_ahead_ascii(crop_source, crop_length, input_locn, current_mode, symbol_mode, + input_locn + block_length, cw_fragment, &fragment_length, NULL, gs1); + current_mode = ULT_ASCII_MODE; break; case 'c': - subset = c43_should_latch_other(crop_source, crop_length, input_locn, 1 /*subset*/, gs1) ? 2 : 1; - look_ahead_c43(crop_source, crop_length, input_locn, current_mode, input_locn + block_length, subset, - cw_fragment, &fragment_length, NULL, gs1, symbol->debug); + subset = ult_c43_should_latch_other(crop_source, crop_length, input_locn, 1 /*subset*/, gs1) ? 2 : 1; + ult_look_ahead_c43(crop_source, crop_length, input_locn, current_mode, input_locn + block_length, + subset, cw_fragment, &fragment_length, NULL, gs1, debug_print); /* Substitute temporary latch if possible */ - if ((current_mode == EIGHTBIT_MODE) && (cw_fragment[0] == 260) - && (fragment_length >= 5) && (fragment_length <= 11)) { - /* Temporary latch to submode 1 from Table 11 */ - cw_fragment[0] = 256 + ((fragment_length - 5) / 2); - } else if ((current_mode == EIGHTBIT_MODE) && (cw_fragment[0] == 266) - && (fragment_length >= 5) && (fragment_length <= 11)) { - /* Temporary latch to submode 2 from Table 11 */ - cw_fragment[0] = 262 + ((fragment_length - 5) / 2); - } else if ((current_mode == ASCII_MODE) && (cw_fragment[0] == 278) - && (fragment_length >= 5) && (fragment_length <= 11)) { - /* Temporary latch to submode 1 from Table 9 */ - cw_fragment[0] = 274 + ((fragment_length - 5) / 2); + if (current_mode == ULT_EIGHTBIT_MODE && cw_fragment[0] == 260 && fragment_length >= 5 + && fragment_length <= 11) { + cw_fragment[0] = 256 + (fragment_length - 5) / 2; /* Temporary latch to submode 1 from Table 11 */ + } else if (current_mode == ULT_EIGHTBIT_MODE && cw_fragment[0] == 266 && fragment_length >= 5 + && fragment_length <= 11) { + cw_fragment[0] = 262 + (fragment_length - 5) / 2; /* Temporary latch to submode 2 from Table 11 */ + } else if (current_mode == ULT_ASCII_MODE && cw_fragment[0] == 278 && fragment_length >= 5 + && fragment_length <= 11) { + cw_fragment[0] = 274 + (fragment_length - 5) / 2; /* Temporary latch to submode 1 from Table 9 */ } else { - current_mode = C43_MODE; + current_mode = ULT_C43_MODE; } break; case '8': - look_ahead_eightbit(crop_source, crop_length, input_locn, current_mode, input_locn + block_length, - cw_fragment, &fragment_length, gs1); - current_mode = EIGHTBIT_MODE; + ult_look_ahead_eightbit(crop_source, crop_length, input_locn, current_mode, input_locn + block_length, + cw_fragment, &fragment_length, gs1); + current_mode = ULT_EIGHTBIT_MODE; break; } @@ -869,10 +796,134 @@ static int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned c input_locn += block_length; } while (input_locn < crop_length); + *p_current_mode = current_mode; + return codeword_count; } -INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int length) { +/* Call `ult_generate_codewords()` for each segment, dealing with symbol mode and start codeword beforehand */ +static int ult_generate_codewords_segs(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count, + int codewords[]) { + int i; + int codeword_count = 0; + int symbol_mode; + int current_mode; + int have_eci = 0; + const unsigned char *source = segs[0].source; + int length = segs[0].length; + const int eci = segs[0].eci; + const int gs1 = (symbol->input_mode & 0x07) == GS1_MODE; + + for (i = 0; i < seg_count; i++) { + if (segs[i].eci) { + have_eci = 1; + break; + } + } + + if (have_eci || (symbol->option_3 != ULTRA_COMPRESSION && !gs1)) { + // Force eight-bit mode by default as other modes are poorly documented + symbol_mode = ULT_EIGHTBIT_MODE; + } else { + // Decide start character codeword (from Table 5) + symbol_mode = ULT_ASCII_MODE; + for (i = 0; i < length; i++) { + if (source[i] >= 0x80) { + symbol_mode = ULT_EIGHTBIT_MODE; + break; + } + } + } + + if (symbol->output_options & READER_INIT) { + /* Reader Initialisation mode */ + codeword_count = 2; + if (symbol_mode == ULT_ASCII_MODE) { + codewords[0] = 272; // 7-bit ASCII mode + codewords[1] = 271; // FNC3 + } else { + codewords[0] = 257; // 8859-1 + codewords[1] = 269; // FNC3 + } + } else { + /* Calculate start character codeword */ + codeword_count = 1; + if (symbol_mode == ULT_ASCII_MODE) { + if (gs1) { + codewords[0] = 273; + } else { + codewords[0] = 272; + } + } else { + if ((eci >= 3) && (eci <= 18) && (eci != 14)) { + // ECI indicates use of character set within ISO/IEC 8859 + codewords[0] = 257 + (eci - 3); + if (codewords[0] > 267) { + // Avoids ECI 14 for non-existant ISO/IEC 8859-12 + codewords[0]--; + } + } else if ((eci > 18) && (eci <= 898)) { + // ECI indicates use of character set outside ISO/IEC 8859 + codewords[0] = 275 + (eci / 256); + codewords[1] = eci % 256; + codeword_count = 2; + } else if (eci == 899) { + // Non-language byte data + codewords[0] = 280; + } else if ((eci > 899) && (eci <= 9999)) { + // ECI beyond 899 needs to use fixed length encodable ECI invocation (section 7.6.2) + // Encode as 3 codewords + codewords[0] = 257; // ISO/IEC 8859-1 used to enter 8-bit mode + codewords[1] = 274; // Encode ECI as 3 codewords + codewords[2] = (eci / 100) + 128; + codewords[3] = (eci % 100) + 128; + codeword_count = 4; + } else if (eci >= 10000) { + // Encode as 4 codewords + codewords[0] = 257; // ISO/IEC 8859-1 used to enter 8-bit mode + codewords[1] = 275; // Encode ECI as 4 codewords + codewords[2] = (eci / 10000) + 128; + codewords[3] = ((eci % 10000) / 100) + 128; + codewords[4] = (eci % 100) + 128; + codeword_count = 5; + } else { + codewords[0] = 257; // Default is assumed to be ISO/IEC 8859-1 (ECI 3) + } + } + + if ((codewords[0] == 257) || (codewords[0] == 272)) { + int fragno = ult_find_fragment(source, length, 0); + + // Check for http:// at start of input + if ((fragno == 0) || (fragno == 2)) { + codewords[0] = 281; + source += 7; + length -= 7; + symbol_mode = ULT_EIGHTBIT_MODE; + + // Check for https:// at start of input + } else if ((fragno == 1) || (fragno == 3)) { + codewords[0] = 282; + source += 8; + length -= 8; + symbol_mode = ULT_EIGHTBIT_MODE; + } + } + } + + current_mode = symbol_mode; + codeword_count = ult_generate_codewords(symbol, source, length, 0 /*eci*/, gs1, symbol_mode, ¤t_mode, + codewords, codeword_count); + + for (i = 1; i < seg_count; i++) { + codeword_count = ult_generate_codewords(symbol, segs[i].source, segs[i].length, segs[i].eci, gs1, symbol_mode, + ¤t_mode, codewords, codeword_count); + } + + return codeword_count; +} + +INTERNAL int ultra(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) { int data_cw_count = 0; int acc, qcc; int scr[3] = {0}, scr_cw_count = 0; /* Symbol Control Region (only if have Structured Append) */ @@ -890,11 +941,14 @@ INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int lengt int tilex, tiley; int dcc; int revision_idx = 0; + const int debug_print = (symbol->debug & ZINT_DEBUG_PRINT); #ifdef _MSC_VER int *data_codewords; char *pattern; #endif /* _MSC_VER */ + (void)seg_count; + if (symbol->eci > 811799) { strcpy(symbol->errtxt, "590: ECI value not supported by Ultracode"); return ZINT_ERROR_INVALID_OPTION; @@ -943,7 +997,7 @@ INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int lengt scr[0] = link2 * 70 + (symbol->structapp.count - 1) * 8 + symbol->structapp.index - 1; } - cw_memalloc = length * 2; + cw_memalloc = segs_length(segs, seg_count) * 2; if (cw_memalloc < 283) { cw_memalloc = 283; } @@ -954,9 +1008,9 @@ INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int lengt data_codewords = (int *) _alloca(cw_memalloc * sizeof(int)); #endif /* _MSC_VER */ - data_cw_count = ultra_generate_codewords(symbol, source, length, data_codewords); + data_cw_count = ult_generate_codewords_segs(symbol, segs, seg_count, data_codewords); - if (symbol->debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Codewords (%d):", data_cw_count); for (i = 0; i < data_cw_count; i++) { printf(" %d", data_codewords[i]); @@ -993,13 +1047,13 @@ INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int lengt qcc = 3; } else { if ((data_cw_count % 25) == 0) { - qcc = (kec[ecc_level] * (data_cw_count / 25)) + 3 + 2; + qcc = (ult_kec[ecc_level] * (data_cw_count / 25)) + 3 + 2; } else { - qcc = (kec[ecc_level] * ((data_cw_count / 25) + 1)) + 3 + 2; + qcc = (ult_kec[ecc_level] * ((data_cw_count / 25) + 1)) + 3 + 2; } } - if (symbol->debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("EC%d codewords: %d\n", ecc_level + 1, qcc); } @@ -1007,7 +1061,7 @@ INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int lengt if (scr_cw_count) { acc += 70; /* Link1 = 1 (* 70) means SCR present */ } - if (symbol->debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("MCC: %d, ACC: %d, SCR: %d", data_cw_count, acc, scr_cw_count); if (scr_cw_count) { printf(", SCR0: %d", scr[0]); @@ -1028,7 +1082,7 @@ INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int lengt rows = 5; for (i = 2; i >= 0; i--) { // Total codewords less 6 (+ SCR) overhead (Start + MCC + ACC (+ SCR) + 3 TCC/RSEC/QCC patterns) - if (total_cws - (6 + scr_cw_count) <= ultra_maxsize[i]) { + if (total_cws - (6 + scr_cw_count) <= ult_maxsize[i]) { rows--; } } @@ -1042,7 +1096,7 @@ INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int lengt } columns += columns / 15; // Secondary vertical clock tracks - if (symbol->debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Calculated size is %d rows by %d columns (pads %d)\n", rows, columns, pads); } @@ -1058,9 +1112,9 @@ INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int lengt /* Calculate error correction codewords (RSEC) */ - ultra_gf283((short) data_cw_count, (short) qcc, data_codewords); + ult_gf283((short) data_cw_count, (short) qcc, data_codewords); - if (symbol->debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("ECCs (%d):", qcc); for (i = 0; i < qcc; i++) { printf(" %d", data_codewords[(282 - qcc) + i]); @@ -1090,7 +1144,7 @@ INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int lengt } codeword[locn++] = qcc; // QCC - if (symbol->debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Rearranged codewords with ECC:\n"); for (i = 0; i < locn; i++) { printf("%d ", codeword[i]); @@ -1148,7 +1202,7 @@ INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int lengt tiley = 0; for (i = 0; i < locn; i++) { for (j = 0; j < 5; j++) { - tilepat[4 - j] = ultra_colour[(tiles[codeword[i]] >> (3 * j)) & 0x07]; + tilepat[4 - j] = ult_colour[(ult_tiles[codeword[i]] >> (3 * j)) & 0x07]; } if ((tiley + 1) >= total_height) { tiley = 0; @@ -1170,12 +1224,12 @@ INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int lengt } /* Add data column count */ - dcc = columns - ultra_mincols[rows - 2]; + dcc = columns - ult_mincols[rows - 2]; tilex = 2; tiley = (total_height - 11) / 2; /* DCCU */ for (j = 0; j < 5; j++) { - tilepat[4 - j] = ultra_colour[(dccu[revision_idx][dcc] >> (3 * j)) & 0x07]; + tilepat[4 - j] = ult_colour[(ult_dccu[revision_idx][dcc] >> (3 * j)) & 0x07]; } for (j = 0; j < 5; j++) { pattern[((tiley + j) * total_width) + tilex] = tilepat[j]; @@ -1183,13 +1237,13 @@ INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int lengt /* DCCL */ tiley += 6; for (j = 0; j < 5; j++) { - tilepat[4 - j] = ultra_colour[(dccl[revision_idx][dcc] >> (3 * j)) & 0x07]; + tilepat[4 - j] = ult_colour[(ult_dccl[revision_idx][dcc] >> (3 * j)) & 0x07]; } for (j = 0; j < 5; j++) { pattern[((tiley + j) * total_width) + tilex] = tilepat[j]; } - if (symbol->debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("DCC: %d\n", dcc); for (i = 0; i < (total_height * total_width); i++) { @@ -1207,10 +1261,12 @@ INTERNAL int ultra(struct zint_symbol *symbol, unsigned char source[], int lengt for (i = 0; i < total_height; i++) { symbol->row_height[i] = 1; for (j = 0; j < total_width; j++) { - set_module_colour(symbol, i, j, posn(ultra_colour, pattern[(i * total_width) + j])); + set_module_colour(symbol, i, j, posn(ult_colour, pattern[(i * total_width) + j])); } } symbol->height = total_height; return 0; } + +/* vim: set ts=4 sw=4 et : */ diff --git a/backend/zint.h b/backend/zint.h index 75205ac2..0abcbab7 100644 --- a/backend/zint.h +++ b/backend/zint.h @@ -1,7 +1,7 @@ /* zint.h - definitions for libzint libzint - the open source barcode library - Copyright (C) 2009-2021 Robin Stuart + Copyright (C) 2009-2022 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -28,7 +28,6 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/* vim: set ts=4 sw=4 et : */ /* * For version, see "zintconfig.h" * For documentation, see "../docs/manual.txt" @@ -83,7 +82,7 @@ extern "C" { /* Structured Append info - ignored unless `zint_structapp.count` is set to non-zero value */ struct zint_structapp { - int index; /* Position in Structured Append sequence, 1-based. Must be <= count */ + int index; /* Position in Structured Append sequence, 1-based. Must be <= `count` */ int count; /* Number of symbols in Structured Append sequence. Set >= 2 to add SA Info */ char id[32]; /* Optional ID to distinguish sequence, ASCII, NUL-terminated unless max 32 long */ }; @@ -129,6 +128,13 @@ extern "C" { struct zint_vector *vector; /* Pointer to vector header (vector output only) */ }; + /* Segment for use with `ZBarcode_Encode_Segs()` below */ + struct zint_seg { + unsigned char *source; /* Data to encode */ + int length; /* Length of `source`. If 0, `source` must be NUL-terminated */ + int eci; /* Extended Channel Interpretation */ + }; + /* Symbologies (`symbol->symbology`) */ /* Tbarcode 7 codes */ #define BARCODE_CODE11 1 /* Code 11 */ @@ -163,7 +169,7 @@ extern "C" { #define BARCODE_UPCA_CHK 35 /* UPC-A + Check Digit */ #define BARCODE_UPCE 37 /* UPC-E */ #define BARCODE_UPCE_CHK 38 /* UPC-E + Check Digit */ -#define BARCODE_POSTNET 40 /* USPS POSTNET */ +#define BARCODE_POSTNET 40 /* USPS (U.S. Postal Service) POSTNET */ #define BARCODE_MSI_PLESSEY 47 /* MSI Plessey */ #define BARCODE_FIM 49 /* Facing Identification Mark */ #define BARCODE_LOGMARS 50 /* LOGMARS */ @@ -211,7 +217,7 @@ extern "C" { #define BARCODE_MICROQR 97 /* Micro QR Code */ /* Tbarcode 9 codes */ -#define BARCODE_HIBC_128 98 /* HIBC Code 128 */ +#define BARCODE_HIBC_128 98 /* HIBC (Health Industry Barcode) Code 128 */ #define BARCODE_HIBC_39 99 /* HIBC Code 39 */ #define BARCODE_HIBC_DM 102 /* HIBC Data Matrix */ #define BARCODE_HIBC_QR 104 /* HIBC QR Code */ @@ -333,6 +339,8 @@ extern "C" { /* The largest amount of data that can be encoded is 4350 4-byte UTF-8 chars in Han Xin Code */ #define ZINT_MAX_DATA_LEN 17400 +/* Maximum number of segments allowed for (`seg_count`) */ +#define ZINT_MAX_SEG_COUNT 256 /* Debug flags (debug) */ #define ZINT_DEBUG_PRINT 0x0001 /* Print debug info (if any) to stdout */ @@ -360,9 +368,13 @@ extern "C" { ZINT_EXTERN void ZBarcode_Delete(struct zint_symbol *symbol); - /* Encode a barcode. If `length` is 0, `source` must be NUL-terminated. */ + /* Encode a barcode. If `length` is 0, `source` must be NUL-terminated */ ZINT_EXTERN int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int length); + /* Encode a barcode with multiple ECI segments */ + ZINT_EXTERN int ZBarcode_Encode_Segs(struct zint_symbol *symbol, const struct zint_seg segs[], + const int seg_count); + /* Encode a barcode using input data from file `filename` */ ZINT_EXTERN int ZBarcode_Encode_File(struct zint_symbol *symbol, const char *filename); @@ -374,6 +386,10 @@ extern "C" { ZINT_EXTERN int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, const unsigned char *source, int length, int rotate_angle); + /* Encode a symbol with multiple ECI segments and output to file `symbol->outfile` */ + ZINT_EXTERN int ZBarcode_Encode_Segs_and_Print(struct zint_symbol *symbol, const struct zint_seg segs[], + const int seg_count, int rotate_angle); + /* Encode a symbol using input data from file `filename` and output to file `symbol->outfile` */ ZINT_EXTERN int ZBarcode_Encode_File_and_Print(struct zint_symbol *symbol, const char *filename, int rotate_angle); @@ -386,6 +402,10 @@ extern "C" { ZINT_EXTERN int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, const unsigned char *source, int length, int rotate_angle); + /* Encode a symbol with multiple ECI segments and output to memory as raster (`symbol->bitmap`) */ + ZINT_EXTERN int ZBarcode_Encode_Segs_and_Buffer(struct zint_symbol *symbol, const struct zint_seg segs[], + const int seg_count, int rotate_angle); + /* Encode a symbol using input data from file `filename` and output to memory as raster (`symbol->bitmap`) */ ZINT_EXTERN int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol, const char *filename, int rotate_angle); @@ -398,6 +418,10 @@ extern "C" { ZINT_EXTERN int ZBarcode_Encode_and_Buffer_Vector(struct zint_symbol *symbol, const unsigned char *source, int length, int rotate_angle); + /* Encode a symbol with multiple ECI segments and output to memory as vector (`symbol->vector`) */ + ZINT_EXTERN int ZBarcode_Encode_Segs_and_Buffer_Vector(struct zint_symbol *symbol, const struct zint_seg segs[], + const int seg_count, int rotate_angle); + /* Encode a symbol using input data from file `filename` and output to memory as vector (`symbol->vector`) */ ZINT_EXTERN int ZBarcode_Encode_File_and_Buffer_Vector(struct zint_symbol *symbol, const char *filename, int rotate_angle); @@ -420,4 +444,5 @@ extern "C" { } #endif /* __cplusplus */ +/* vim: set ts=4 sw=4 et : */ #endif /* ZINT_H */ diff --git a/backend_qt/qzint.cpp b/backend_qt/qzint.cpp index e02a3e63..5423eb3b 100644 --- a/backend_qt/qzint.cpp +++ b/backend_qt/qzint.cpp @@ -34,10 +34,36 @@ #define QSL QStringLiteral namespace Zint { - static const char *fontStyle = "Helvetica"; - static const char *fontStyleError = "Helvetica"; + static const char fontStyle[] = "Helvetica"; + static const char fontStyleError[] = "Helvetica"; static const int fontSizeError = 14; /* Point size */ + static const int maxSegs = 256; + static const int maxCLISegs = 10; /* CLI restricted to 10 segments (including main data) */ + + /* Helper to convert ECI combo index to ECI value */ + static int ECIIndexToECI(const int ECIIndex) { + int ret; + if (ECIIndex >= 1 && ECIIndex <= 11) { + ret = ECIIndex + 2; + } else if (ECIIndex >= 12 && ECIIndex <= 15) { + ret = ECIIndex + 3; + } else if (ECIIndex >= 16 && ECIIndex <= 31) { + ret = ECIIndex + 4; + } else if (ECIIndex == 32) { + ret = 170; /* ISO 646 Invariant */ + } else if (ECIIndex == 33) { + ret = 899; /* 8-bit binary data */ + } else { + ret = 0; + } + return ret; + } + + /* Segment constructors */ + QZintSeg::QZintSeg() : m_eci(0) {} + QZintSeg::QZintSeg(const QString& text, const int ECIIndex) : m_text(text), m_eci(ECIIndexToECI(ECIIndex)) {} + QZint::QZint() : m_zintSymbol(NULL), m_symbol(BARCODE_CODE128), m_input_mode(UNICODE_MODE), m_height(0.0f), @@ -139,9 +165,17 @@ namespace Zint { void QZint::encode() { resetSymbol(); - QByteArray bstr = m_text.toUtf8(); - /* Note do our own rotation */ - m_error = ZBarcode_Encode_and_Buffer_Vector(m_zintSymbol, (unsigned char *) bstr.data(), bstr.length(), 0); + if (m_segs.empty()) { + QByteArray bstr = m_text.toUtf8(); + /* Note do our own rotation */ + m_error = ZBarcode_Encode_and_Buffer_Vector(m_zintSymbol, (unsigned char *) bstr.data(), bstr.length(), 0); + } else { + struct zint_seg segs[maxSegs]; + std::vector bstrs; + int seg_count = convertSegs(segs, bstrs); + /* Note do our own rotation */ + m_error = ZBarcode_Encode_Segs_and_Buffer_Vector(m_zintSymbol, segs, seg_count, 0); + } m_lastError = m_zintSymbol->errtxt; if (m_error < ZINT_ERROR) { @@ -182,6 +216,19 @@ namespace Zint { void QZint::setText(const QString& text) { m_text = text; + m_segs.clear(); + } + + std::vector QZint::segs() const { + return m_segs; + } + + void QZint::setSegs(const std::vector& segs) { + m_segs = segs; + m_text.clear(); + if (m_segs.size()) { /* Make sure `symbol->eci` synced */ + m_eci = m_segs[0].m_eci; + } } QString QZint::primaryMessage() const { @@ -454,19 +501,7 @@ namespace Zint { } void QZint::setECI(int ECIIndex) { // Sets from comboBox index - if (ECIIndex >= 1 && ECIIndex <= 11) { - m_eci = ECIIndex + 2; - } else if (ECIIndex >= 12 && ECIIndex <= 15) { - m_eci = ECIIndex + 3; - } else if (ECIIndex >= 16 && ECIIndex <= 31) { - m_eci = ECIIndex + 4; - } else if (ECIIndex == 32) { - m_eci = 170; /* ISO 646 Invariant */ - } else if (ECIIndex == 33) { - m_eci = 899; /* 8-bit binary data */ - } else { - m_eci = 0; - } + m_eci = ECIIndexToECI(ECIIndex); } void QZint::setECIValue(int eci) { // Sets literal value @@ -611,12 +646,19 @@ namespace Zint { return ZBarcode_Version(); } - bool QZint::save_to_file(const QString &filename) { + bool QZint::save_to_file(const QString& filename) { resetSymbol(); strcpy(m_zintSymbol->outfile, filename.toLatin1().left(255)); - QByteArray bstr = m_text.toUtf8(); - m_error = ZBarcode_Encode_and_Print(m_zintSymbol, (unsigned char *) bstr.data(), bstr.length(), - m_rotate_angle); + if (m_segs.empty()) { + QByteArray bstr = m_text.toUtf8(); + m_error = ZBarcode_Encode_and_Print(m_zintSymbol, (unsigned char *) bstr.data(), bstr.length(), + m_rotate_angle); + } else { + struct zint_seg segs[maxSegs]; + std::vector bstrs; + int seg_count = convertSegs(segs, bstrs); + m_error = ZBarcode_Encode_Segs_and_Print(m_zintSymbol, segs, seg_count, m_rotate_angle); + } if (m_error >= ZINT_ERROR) { m_lastError = m_zintSymbol->errtxt; m_encodedWidth = 0; @@ -657,6 +699,19 @@ namespace Zint { } } + /* Helper to convert `m_segs` to `struct zint_seg[]` */ + int QZint::convertSegs(struct zint_seg segs[], std::vector& bstrs) { + bstrs.reserve(m_segs.size()); + int i; + for (i = 0; i < (int) m_segs.size() && i < maxSegs && !m_segs[i].m_text.isEmpty(); i++) { + segs[i].eci = m_segs[i].m_eci; + bstrs.push_back(m_segs[i].m_text.toUtf8()); + segs[i].source = (unsigned char *) bstrs.back().data(); + segs[i].length = bstrs.back().length(); + } + return i; + } + /* Note: legacy argument `mode` is not used */ void QZint::render(QPainter& painter, const QRectF& paintRect, AspectRatioMode /*mode*/) { struct zint_vector_rect *rect; @@ -824,7 +879,7 @@ namespace Zint { If HEIGHTPERROW_MODE set and non-zero `heightPerRow` given then use that for height instead of internal height */ QString QZint::getAsCLI(const bool win, const bool longOptOnly, const bool barcodeNames, - const bool autoHeight, const float heightPerRow, const QString &outfile) const { + const bool autoHeight, const float heightPerRow, const QString& outfile) const { QString cmd(win ? QSL("zint.exe") : QSL("zint")); char name_buf[32]; @@ -859,7 +914,18 @@ namespace Zint { arg_bool(cmd, "--compliantheight", hasCompliantHeight() && compliantHeight()); - arg_data(cmd, longOptOnly ? "--data=" : "-d ", text(), win); + if (m_segs.empty()) { + if (supportsECI()) { + arg_int(cmd, "--eci=", eci()); + } + arg_data(cmd, longOptOnly ? "--data=" : "-d ", m_text, win); + } else { + arg_int(cmd, "--eci=", m_segs.front().m_eci); + arg_data(cmd, longOptOnly ? "--data=" : "-d ", m_segs.front().m_text, win); + for (int i = 1; i < (int) m_segs.size() && i < maxCLISegs && !m_segs[i].m_text.isEmpty(); i++) { + arg_seg(cmd, i, m_segs[i], win); + } + } if (m_symbol == BARCODE_DATAMATRIX || m_symbol == BARCODE_HIBC_DM) { arg_bool(cmd, "--dmre", option3() == DM_DMRE); @@ -872,10 +938,6 @@ namespace Zint { arg_bool(cmd, "--dotty", dotty()); } - if (supportsECI()) { - arg_int(cmd, "--eci=", eci()); - } - arg_bool(cmd, "--esc", inputMode() & ESCAPE_MODE); arg_bool(cmd, "--fast", inputMode() & FAST_MODE); @@ -992,26 +1054,26 @@ namespace Zint { } /* `getAsCLI()` helpers */ - void QZint::arg_str(QString &cmd, const char *const opt, const QString &val) { + void QZint::arg_str(QString& cmd, const char *const opt, const QString& val) { if (!val.isEmpty()) { QByteArray bstr = val.toUtf8(); cmd += QString::asprintf(" %s%.*s", opt, bstr.length(), bstr.data()); } } - void QZint::arg_int(QString &cmd, const char *const opt, const int val, const bool allowZero) { + void QZint::arg_int(QString& cmd, const char *const opt, const int val, const bool allowZero) { if (val > 0 || (val == 0 && allowZero)) { cmd += QString::asprintf(" %s%d", opt, val); } } - void QZint::arg_bool(QString &cmd, const char *const opt, const bool val) { + void QZint::arg_bool(QString& cmd, const char *const opt, const bool val) { if (val) { cmd += QString::asprintf(" %s", opt); } } - void QZint::arg_color(QString &cmd, const char *const opt, const QColor val) { + void QZint::arg_color(QString& cmd, const char *const opt, const QColor val) { if (val.alpha() != 0xFF) { cmd += QString::asprintf(" %s%02X%02X%02X%02X", opt, val.red(), val.green(), val.blue(), val.alpha()); } else { @@ -1019,33 +1081,43 @@ namespace Zint { } } - void QZint::arg_data(QString &cmd, const char *const opt, const QString &val, const bool win) { + void QZint::arg_data(QString& cmd, const char *const opt, const QString& val, const bool win) { if (!val.isEmpty()) { QString text(val); - const char delim = win ? '"' : '\''; - if (win) { - // Difficult (impossible?) to fully escape strings on Windows, e.g. "blah%PATH%" will substitute - // env var PATH, so just doing basic escaping here - text.replace("\\\\", "\\\\\\\\"); // Double-up backslashed backslash `\\` -> `\\\\` - text.replace("\"", "\\\""); // Backslash quote `"` -> `\"` - QByteArray bstr = text.toUtf8(); - cmd += QString::asprintf(" %s%c%.*s%c", opt, delim, bstr.length(), bstr.data(), delim); - } else { - text.replace("'", "'\\''"); // Single quote `'` -> `'\''` - QByteArray bstr = text.toUtf8(); - cmd += QString::asprintf(" %s%c%.*s%c", opt, delim, bstr.length(), bstr.data(), delim); - } + arg_data_esc(cmd, opt, text, win); } } - void QZint::arg_float(QString &cmd, const char *const opt, const float val, const bool allowZero) { + void QZint::arg_seg(QString& cmd, const int seg_no, const QZintSeg& val, const bool win) { + QString text(val.m_text); + QString opt = QString::asprintf("--seg%d=%d,", seg_no, val.m_eci); + arg_data_esc(cmd, opt.toUtf8(), text, win); + } + + void QZint::arg_data_esc(QString& cmd, const char *const opt, QString& text, const bool win) { + const char delim = win ? '"' : '\''; + if (win) { + // Difficult (impossible?) to fully escape strings on Windows, e.g. "blah%PATH%" will substitute + // env var PATH, so just doing basic escaping here + text.replace("\\\\", "\\\\\\\\"); // Double-up backslashed backslash `\\` -> `\\\\` + text.replace("\"", "\\\""); // Backslash quote `"` -> `\"` + QByteArray bstr = text.toUtf8(); + cmd += QString::asprintf(" %s%c%.*s%c", opt, delim, bstr.length(), bstr.data(), delim); + } else { + text.replace("'", "'\\''"); // Single quote `'` -> `'\''` + QByteArray bstr = text.toUtf8(); + cmd += QString::asprintf(" %s%c%.*s%c", opt, delim, bstr.length(), bstr.data(), delim); + } + } + + void QZint::arg_float(QString& cmd, const char *const opt, const float val, const bool allowZero) { if (val > 0 || (val == 0 && allowZero)) { cmd += QString::asprintf(" %s%g", opt, val); } } - void QZint::arg_structapp(QString &cmd, const char *const opt, const int count, const int index, - const QString &id, const bool win) { + void QZint::arg_structapp(QString& cmd, const char *const opt, const int count, const int index, + const QString& id, const bool win) { if (count >= 2 && index >= 1) { if (id.isEmpty()) { cmd += QString::asprintf(" %s%d,%d", opt, index, count); diff --git a/backend_qt/qzint.h b/backend_qt/qzint.h index ce7832e6..0bbf6c73 100644 --- a/backend_qt/qzint.h +++ b/backend_qt/qzint.h @@ -1,7 +1,7 @@ /*************************************************************************** * Copyright (C) 2008 by BogDan Vatra * * bogdan@licentia.eu * - * Copyright (C) 2010-2021 Robin Stuart * + * Copyright (C) 2010-2022 Robin Stuart * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -14,7 +14,6 @@ * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ -/* vim: set ts=4 sw=4 et : */ #ifndef QZINT_H #define QZINT_H @@ -26,6 +25,17 @@ namespace Zint { +/* QString version of `struct zint_seg` */ +class QZintSeg { +public: + QString m_text; + int m_eci; + + QZintSeg(); + QZintSeg(const QString& text, const int ECIIndex = 0); // `ECIIndex` is comboBox index (not ECI value) +}; + +/* Interface */ class QZint : public QObject { Q_OBJECT @@ -44,7 +54,10 @@ public: void setInputMode(int input_mode); QString text() const; - void setText(const QString& text); + void setText(const QString& text); // Clears segs + + std::vector segs() const; + void setSegs(const std::vector& segs); // Clears text and sets eci QString primaryMessage() const; void setPrimaryMessage(const QString& primaryMessage); @@ -177,7 +190,7 @@ public: const QString& lastError() const; bool hasErrors() const; - bool save_to_file(const QString &filename); + bool save_to_file(const QString& filename); /* Note: legacy argument `mode` is not used */ void render(QPainter& painter, const QRectF& paintRect, AspectRatioMode mode = IgnoreAspectRatio); @@ -189,7 +202,7 @@ public: If HEIGHTPERROW_MODE set and non-zero `heightPerRow` given then use that for height instead of internal height */ QString getAsCLI(const bool win, const bool longOptOnly = false, const bool barcodeNames = false, - const bool autoHeight = false, const float heightPerRow = 0.0f, const QString &outfile = "") const; + const bool autoHeight = false, const float heightPerRow = 0.0f, const QString& outfile = "") const; signals: void encoded(); @@ -198,17 +211,22 @@ signals: private: void resetSymbol(); void encode(); + + int convertSegs(struct zint_seg segs[], std::vector& bstrs); + static Qt::GlobalColor colourToQtColor(int colour); /* `getAsCLI()` helpers */ - static void arg_str(QString &cmd, const char *const opt, const QString &val); - static void arg_int(QString &cmd, const char *const opt, const int val, const bool allowZero = false); - static void arg_bool(QString &cmd, const char *const opt, const bool val); - static void arg_color(QString &cmd, const char *const opt, const QColor val); - static void arg_data(QString &cmd, const char *const opt, const QString &val, const bool win); - static void arg_float(QString &cmd, const char *const opt, const float val, const bool allowZero = false); - static void arg_structapp(QString &cmd, const char *const opt, const int count, const int index, - const QString &id, const bool win); + static void arg_str(QString& cmd, const char *const opt, const QString& val); + static void arg_int(QString& cmd, const char *const opt, const int val, const bool allowZero = false); + static void arg_bool(QString& cmd, const char *const opt, const bool val); + static void arg_color(QString& cmd, const char *const opt, const QColor val); + static void arg_data(QString& cmd, const char *const opt, const QString& val, const bool win); + static void arg_seg(QString& cmd, const int seg_no, const QZintSeg& val, const bool win); + static void arg_data_esc(QString& cmd, const char *const opt, QString& text, const bool win); + static void arg_float(QString& cmd, const char *const opt, const float val, const bool allowZero = false); + static void arg_structapp(QString& cmd, const char *const opt, const int count, const int index, + const QString& id, const bool win); private: zint_symbol *m_zintSymbol; @@ -216,6 +234,7 @@ private: int m_input_mode; QString m_text; QString m_primaryMessage; + std::vector m_segs; float m_height; int m_option_1; int m_option_2; @@ -256,4 +275,5 @@ private: } /* namespace Zint */ +/* vim: set ts=4 sw=4 et : */ #endif /* QZINT_H */ diff --git a/backend_qt/tests/test_qzint.cpp b/backend_qt/tests/test_qzint.cpp index 6de3ec9b..3f7527ec 100644 --- a/backend_qt/tests/test_qzint.cpp +++ b/backend_qt/tests/test_qzint.cpp @@ -60,6 +60,35 @@ private slots: QString text("text"); bc.setText(text); QCOMPARE(bc.text(), text); + QCOMPARE(bc.segs().empty(), true); + + std::vector segTexts; + std::vector segECIs; + segTexts.push_back(QString("Τεχτ")); + segECIs.push_back(9); + segTexts.push_back(QString("貫やぐ禁")); + segECIs.push_back(20); + segTexts.push_back(QString("กขฯ")); + segECIs.push_back(13); + + std::vector segs; + for (int i = 0; i < (int) segTexts.size(); i++) { + segs.push_back(Zint::QZintSeg(segTexts[i])); + segs.back().m_eci = segECIs[i]; + } + + bc.setSegs(segs); + QCOMPARE(bc.segs().size(), segs.size()); + for (int i = 0; i < (int) segs.size(); i++) { + QCOMPARE(bc.segs()[i].m_text, segTexts[i]); + QCOMPARE(bc.segs()[i].m_eci, segECIs[i]); + } + QCOMPARE(bc.text().isEmpty(), true); + QCOMPARE(bc.eci(), segECIs[0]); + + bc.setText(text); + QCOMPARE(bc.text(), text); + QCOMPARE(bc.segs().empty(), true); QString primaryMessage("primary message"); bc.setPrimaryMessage(primaryMessage); @@ -343,7 +372,7 @@ private slots: QTest::newRow("BARCODE_QRCODE") << BARCODE_QRCODE << "1234" << 0 << "" << 21 << 21; if (!m_skipIfFontUsed) { - QTest::newRow("BARCODE_QRCODE no text") << BARCODE_QRCODE << "" << ZINT_ERROR_INVALID_DATA << "Error 205: No input data" << 0 << 0; + QTest::newRow("BARCODE_QRCODE no text") << BARCODE_QRCODE << "" << ZINT_ERROR_INVALID_DATA << "Error 773: Input segment 0 length zero" << 0 << 0; } } @@ -499,9 +528,9 @@ private slots: << true << 0 << 0 << 2 << 3 << 0 // cmyk-fontSetting << true << false << false << false << false << 0 // showText-rotateAngle << 7 << false << false << false << WARN_DEFAULT << false // eci-debug - << "zint -b 92 --cmyk -d '12345678Ж0%var%' --dotsize=0.9 --dotty --eci=7 --fg=0000FF --scale=4" + << "zint -b 92 --cmyk --eci=7 -d '12345678Ж0%var%' --dotsize=0.9 --dotty --fg=0000FF --scale=4" " --secure=1 --structapp='1,2,as\"dfa'\\''sdf' --vwhitesp=3 -w 2" - << "zint.exe -b 92 --cmyk -d \"12345678Ж0%var%\" --dotsize=0.9 --dotty --eci=7 --fg=0000FF --scale=4" + << "zint.exe -b 92 --cmyk --eci=7 -d \"12345678Ж0%var%\" --dotsize=0.9 --dotty --fg=0000FF --scale=4" " --secure=1 --structapp=\"1,2,as\\\"dfa'sdf\" --vwhitesp=3 -w 2" << "" << ""; @@ -679,8 +708,8 @@ private slots: << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 0 // showText-rotateAngle << 29 << false << false << false << WARN_DEFAULT << false // eci-debug - << "zint -b 116 -d 'éβÿ啊\\e\"'\\''' --eci=29 --esc --mask=0 --secure=2 --vers=5" - << "zint.exe -b 116 -d \"éβÿ啊\\e\\\"'\" --eci=29 --esc --mask=0 --secure=2 --vers=5" + << "zint -b 116 --eci=29 -d 'éβÿ啊\\e\"'\\''' --esc --mask=0 --secure=2 --vers=5" + << "zint.exe -b 116 --eci=29 -d \"éβÿ啊\\e\\\"'\" --esc --mask=0 --secure=2 --vers=5" << "" << ""; QTest::newRow("BARCODE_HIBC_DM") << false << 10.0f << "" @@ -770,8 +799,8 @@ private slots: << false << 0 << 0 << 0 << 0 << 0 // cmyk-fontSetting << true << false << false << false << true << 180 // showText-rotateAngle << 20 << false << false << false << WARN_DEFAULT << false // eci-debug - << "zint -b 145 -d 'テ' --eci=20 --rotate=180 --vers=8" - << "zint.exe -b 145 -d \"テ\" --eci=20 --rotate=180 --vers=8" + << "zint -b 145 --eci=20 -d 'テ' --rotate=180 --vers=8" + << "zint.exe -b 145 --eci=20 -d \"テ\" --rotate=180 --vers=8" << "" << ""; QTest::newRow("BARCODE_ULTRA") << false << 0.0f << "" @@ -926,6 +955,44 @@ private slots: } } + void getAsCLISegsTest() + { + Zint::QZint bc; + + QString cmd; + QString expected_cmd; + QString expected_win; + + std::vector segTexts; + std::vector segECIs; + segTexts.push_back(QString("Τεχτ")); + segECIs.push_back(9); + segTexts.push_back(QString("Téxt")); + segECIs.push_back(3); + segTexts.push_back(QString("กขฯ")); + segECIs.push_back(13); + segTexts.push_back(QString("貫やぐ禁")); + segECIs.push_back(20); + + std::vector segs; + for (int i = 0; i < (int) segTexts.size(); i++) { + segs.push_back(Zint::QZintSeg(segTexts[i])); + segs.back().m_eci = segECIs[i]; + } + + bc.setSymbol(BARCODE_QRCODE); + bc.setSegs(segs); + bc.setDotty(true); + + expected_cmd = "zint -b 58 --eci=9 -d 'Τεχτ' --seg1=3,'Téxt' --seg2=13,'กขฯ' --seg3=20,'貫やぐ禁' --dotty"; + cmd = bc.getAsCLI(false /*win*/); + QCOMPARE(cmd, expected_cmd); + + expected_win = "zint.exe -b 58 --eci=9 -d \"Τεχτ\" --seg1=3,\"Téxt\" --seg2=13,\"กขฯ\" --seg3=20,\"貫やぐ禁\" --dotty"; + cmd = bc.getAsCLI(true /*win*/); + QCOMPARE(cmd, expected_win); + } + void qZintAndLibZintEqual_data() { QTest::addColumn("symbology"); diff --git a/backend_tcl/zint.c b/backend_tcl/zint.c index 5e849436..617e8633 100644 --- a/backend_tcl/zint.c +++ b/backend_tcl/zint.c @@ -141,6 +141,10 @@ 2022-04-08 GL - Updated ECIs to AIM ITS/04-023:2022 Note changed names "unicode" -> "utf-16be", "euc-cn" -> "gb2312" +2022-04-24 GL +- Added -segN options +- Added "invariant" and "binary" ECIs +- Tcl_GetIndexFromObj() flags arg -> 0 */ #if defined(__WIN32__) || defined(_WIN32) || defined(WIN32) @@ -431,7 +435,7 @@ static const char *s_eci_list[] = { "cp1256", /*24: Windows-1256*/ "utf-16be", /*25: UTF-16BE (High order byte first) Unicode*/ "utf-8", /*26: Unicode (UTF-8)*/ - "ascii", /*27: ISO-646:1991 7-bit character set*/ + "ascii", /*27: ISO-646:1991 7-bit character set ASCII*/ "big5", /*28: Big5 (Taiwan) Chinese Character Set*/ "gb2312", /*29: GB 2312 (PRC) Chinese Character Set*/ "iso2022-kr", /*30: Korean Character Set EUC-KR (KS X 1001:2002)*/ @@ -440,13 +444,15 @@ static const char *s_eci_list[] = { "utf-16le", /*33: UTF-16LE (Low order byte first) Unicode*/ "utf-32be", /*34: UTF-32BE (High order byte first) Unicode*/ "utf-32le", /*35: UTF-32BE (Low order byte first) Unicode*/ + "invariant", /*170: ISO-646:1991 7-bit character set invariant*/ + "binary", /*899: 8-bit binary*/ NULL }; /* The ECI numerical number to pass to ZINT */ static const int s_eci_number[] = { 3,4,5,6,7,8,9,10,11,12,13,15,16,17,18,20,21,22,23,24,25,26,27,28,29,30, - 31,32,33,34,35 + 31,32,33,34,35,170,899 }; /* Version information */ @@ -460,7 +466,7 @@ static const char help_message[] = "zint tcl(stub,obj) dll\n" " photo: a tcl photo image handle ('p' after 'image create photo p')\n" " Available options:\n" " -barcode choice: symbology, use 'zint symbology' to get a list\n" - " -addongap number: (7..12, default: 9) set add-on gap in multiple of module size (UPC/EAN-CC)\n" + " -addongap integer: (7..12, default: 9) set add-on gap in multiple of module size (UPC/EAN-CC)\n" " -bg color: set background color as 6 or 8 hex rrggbbaa\n" /* cli option --binary internally handled */ " -bind bool: bars above/below the code, size set by -border\n" @@ -476,7 +482,7 @@ static const char help_message[] = "zint tcl(stub,obj) dll\n" " -dotty bool: use dots instead of boxes for matrix codes\n" /* cli option --dump not supported */ /* cli option --ecinos not supported */ - " -eci number: ECI to use\n" + " -eci choice: ECI to use\n" /* cli option --esc not supported */ " -fast bool: use fast encodation (Data Matrix)\n" " -fg color: set foreground color as 6 or 8 hex rrggbbaa\n" @@ -492,9 +498,9 @@ static const char help_message[] = "zint tcl(stub,obj) dll\n" " -heightperrow bool: treat height as per-row\n" /* cli option --input not supported */ " -init bool: Create reader initialisation symbol (Code 128, Data Matrix)\n" - " -mask number: set masking pattern to use (QR/MicroQR/HanXin/DotCode)\n" + " -mask integer: set masking pattern to use (QR/MicroQR/HanXin/DotCode)\n" /* cli option --mirror not supported */ - " -mode number: set encoding mode (MaxiCode, Composite)\n" + " -mode integer: set encoding mode (MaxiCode, Composite)\n" " -nobackground bool: set background transparent\n" " -noquietzones bool: disable default quiet zones\n" " -notext bool: no interpretation line\n" @@ -505,8 +511,9 @@ static const char help_message[] = "zint tcl(stub,obj) dll\n" " -rotate angle: Image rotation by 0,90 or 270 degrees\n" " -rows integer: Codablock F, PDF417: number of rows\n" " -scale double: Scale the image to this factor\n" - " -scmvv number: Prefix SCM with [)>\\R01\\Gvv (vv is NUMBER) (MaxiCode)\n" + " -scmvv integer: Prefix SCM with [)>\\R01\\Gvv (vv is integer) (MaxiCode)\n" " -secure integer: EC Level (Aztec, GridMatrix, HanXin, PDF417, QR, UltraCode)\n" + " -segN {eci data}: Set the ECI & data content for segment N where N is 1 to 9\n" " -separator 0..4 (default: 1) : Stacked symbologies: separator width\n" /* cli option --small replaced by -smalltext */ " -smalltext bool: tiny interpretation line font\n" @@ -710,6 +717,11 @@ static int Encode(Tcl_Interp *interp, int objc, int Mask = 0; int rows = 0; unsigned int cap; + int seg_count = 0; + int seg_no; + Tcl_Obj *pSegDataObjs[10] = {0}; + Tcl_DString segInputs[10]; + struct zint_seg segs[10]; /*------------------------------------------------------------------------*/ /* >> Check if at least data and object is given and a pair number of */ /* >> options */ @@ -741,8 +753,9 @@ static int Encode(Tcl_Interp *interp, int objc, "-gs1nocheck", "-gs1parens", "-gssep", "-guarddescent", "-height", "-heightperrow", "-init", "-mask", "-mode", "-nobackground", "-noquietzones", "-notext", "-primary", "-quietzones", - "-reverse", "-rotate", "-rows", "-scale", "-scmvv", - "-secure", "-separator", "-smalltext", "-square", "-structapp", + "-reverse", "-rotate", "-rows", "-scale", "-scmvv", "-secure", + "-seg1", "-seg2", "-seg3", "-seg4", "-seg5", "-seg6", "-seg7", "-seg8", "-seg9", + "-separator", "-smalltext", "-square", "-structapp", "-to", "-vers", "-vwhitesp", "-werror", "-whitesp", NULL}; enum iOption { @@ -752,8 +765,9 @@ static int Encode(Tcl_Interp *interp, int objc, iGS1NoCheck, iGS1Parens, iGSSep, iGuardDescent, iHeight, iHeightPerRow, iInit, iMask, iMode, iNoBackground, iNoQuietZones, iNoText, iPrimary, iQuietZones, - iReverse, iRotate, iRows, iScale, iSCMvv, - iSecure, iSeparator, iSmallText, iSquare, iStructApp, + iReverse, iRotate, iRows, iScale, iSCMvv, iSecure, + iSeg1, iSeg2, iSeg3, iSeg4, iSeg5, iSeg6, iSeg7, iSeg8, iSeg9, + iSeparator, iSmallText, iSquare, iStructApp, iTo, iVers, iVWhiteSp, iWError, iWhiteSp }; int optionIndex; @@ -762,7 +776,7 @@ static int Encode(Tcl_Interp *interp, int objc, /*--------------------------------------------------------------------*/ if(Tcl_GetIndexFromObj(interp, objv[optionPos], (const char **) optionList, - "zint option", optionPos-1, &optionIndex) + "zint option", 0, &optionIndex) == TCL_ERROR) { fError = 1; @@ -852,6 +866,38 @@ static int Encode(Tcl_Interp *interp, int objc, fError = 1; } break; + case iSeg1: case iSeg2: case iSeg3: case iSeg4: case iSeg5: + case iSeg6: case iSeg7: case iSeg8: case iSeg9: + seg_no = optionIndex - iSeg1 + 1; + if (pSegDataObjs[seg_no]) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("duplicate segment", -1)); + fError = 1; + } else { + Tcl_Obj *poParam; + if (TCL_OK != Tcl_ListObjLength(interp, objv[optionPos+1], &lStr)) { + Tcl_SetObjResult(interp, Tcl_Format(interp, "option %s not a list", 1, objv + optionPos)); + fError = 1; + } else if (lStr != 2) { + Tcl_SetObjResult(interp, Tcl_Format(interp, "option %s not a list of 2", 1, objv + optionPos)); + fError = 1; + } else if (TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1], + 0, &poParam) + || TCL_OK != Tcl_ListObjIndex(interp, objv[optionPos+1], + 1, &pSegDataObjs[seg_no])) { + Tcl_SetObjResult(interp, Tcl_Format(interp, "option %s list format is {eci data}", 1, objv + optionPos)); + fError = 1; + } else if (Tcl_GetIndexFromObj(interp, poParam, + (const char **) s_eci_list, Tcl_GetString(objv[optionPos]), 0, &ECIIndex) + == TCL_ERROR) { + fError = 1; + } else { + segs[seg_no].eci = s_eci_number[ECIIndex]; + if (seg_no >= seg_count) { + seg_count = seg_no + 1; + } + } + } + break; } if (fError) { break; @@ -944,7 +990,7 @@ static int Encode(Tcl_Interp *interp, int objc, break; case iECI: if(Tcl_GetIndexFromObj(interp, objv[optionPos+1], - (const char **) s_eci_list,"-eci", optionPos, &ECIIndex) + (const char **) s_eci_list, "-eci", 0, &ECIIndex) == TCL_ERROR) { fError = 1; @@ -1129,7 +1175,7 @@ static int Encode(Tcl_Interp *interp, int objc, /*------------------------------------------------------------*/ if(Tcl_GetIndexFromObj(interp, objv[optionPos+1], (const char **) rotateList, - "rotate", optionPos, &intValue) + "-rotate", 0, &intValue) == TCL_ERROR) { fError = 1; @@ -1145,7 +1191,7 @@ static int Encode(Tcl_Interp *interp, int objc, break; case iBarcode: if(Tcl_GetIndexFromObj(interp, objv[optionPos+1], - (const char **) s_code_list,"-barcode", optionPos, &intValue) + (const char **) s_code_list, "-barcode", 0, &intValue) == TCL_ERROR) { fError = 1; @@ -1255,7 +1301,7 @@ static int Encode(Tcl_Interp *interp, int objc, /*------------------------------------------------------------*/ if(Tcl_GetIndexFromObj(interp, objv[optionPos+1], (const char **) formatList, - "format", optionPos, &intValue) + "-format", 0, &intValue) == TCL_ERROR) { fError = 1; @@ -1325,6 +1371,32 @@ static int Encode(Tcl_Interp *interp, int objc, pStr = Tcl_DStringValue( &dsInput ); lStr = Tcl_DStringLength( &dsInput ); } + if (seg_count) { + segs[0].source = (unsigned char *) pStr; + segs[0].length = lStr; + segs[0].eci = my_symbol->eci; + for (seg_no = 1; seg_no < seg_count; seg_no++) { + if (!pSegDataObjs[seg_no]) { + Tcl_SetObjResult(interp, Tcl_NewStringObj("Segments must be consecutive", -1)); + fError = 1; + break; + } + } + if (!fError) { + for (seg_no = 1; seg_no < seg_count; seg_no++) { + if ((my_symbol->input_mode & 0x07) == DATA_MODE) { + segs[seg_no].source = (unsigned char *) Tcl_GetByteArrayFromObj(pSegDataObjs[seg_no], + &segs[seg_no].length); + } else { + pStr = Tcl_GetStringFromObj(pSegDataObjs[seg_no], &lStr); + Tcl_DStringInit(& segInputs[seg_no]); + Tcl_UtfToExternalDString( hZINTEncoding, pStr, lStr, &segInputs[seg_no]); + segs[seg_no].source = (unsigned char *) Tcl_DStringValue( &segInputs[seg_no] ); + segs[seg_no].length = Tcl_DStringLength( &segInputs[seg_no] ); + } + } + } + } } /*------------------------------------------------------------------------*/ /* >>> Build symbol graphic */ @@ -1333,8 +1405,13 @@ static int Encode(Tcl_Interp *interp, int objc, Tk_PhotoHandle hPhoto; /*--------------------------------------------------------------------*/ /* call zint graphic creation to buffer */ - ErrorNumber = ZBarcode_Encode_and_Buffer(my_symbol, - (unsigned char *) pStr, lStr, rotate_angle); + if (seg_count) { + ErrorNumber = ZBarcode_Encode_Segs_and_Buffer(my_symbol, + segs, seg_count, rotate_angle); + } else { + ErrorNumber = ZBarcode_Encode_and_Buffer(my_symbol, + (unsigned char *) pStr, lStr, rotate_angle); + } /*--------------------------------------------------------------------*/ /* >> Show a message */ if( 0 != ErrorNumber ) diff --git a/docs/manual.txt b/docs/manual.txt index c6f82d8e..5f7b4927 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -40,7 +40,7 @@ symbol: A symbol is an image which encodes data according to one of the symbology: A method of encoding data to create a certain type of symbol. linear: A linear symbol is one which consists of bars and spaces, and is what - most people associate with the term "barcode". Examples include EAN. + most people associate with the term 'barcode'. Examples include EAN. stacked: A stacked symbol consists of multiple linear symbols placed one above another and which together hold the message, usually alongside some @@ -58,12 +58,12 @@ X-dimension: The X-dimension of a symbol is the size (usually the width) of the composite: A composite symbology is one which is made up of elements which are both linear and stacked. Those currently supported are made up of a - linear "primary" message above which is printed a stacked component + linear 'primary' message above which is printed a stacked component based on the PDF417 symbology. These symbols also have a separator which separates the linear and the stacked components. GS1 data: This is a structured way of representing information which consists - of "chunks" of data, each of which starts with an Application + of 'chunks' of data, each of which starts with an Application Identifier. The AI identifies what type of information is being encoded. @@ -136,7 +136,7 @@ qtZint.exe - Zint Barcode Studio zint.exe - Command Line Interface For fresh releases you will get a warning message from Microsoft Defender -SmartScreen that this is an "unrecognised app". This happens because Zint is +SmartScreen that this is an 'unrecognised app'. This happens because Zint is a free and open-source software project with no advertising and hence no income, meaning we are not able to afford the $664 per year to have the application digitally signed by Microsoft. @@ -559,8 +559,8 @@ The maximum scale for both raster and vector is 100. 4.9.1 Scaling Example --------------------- -The GS1 General Specifications Section 5.2.6.6 "Symbol dimensions at nominal -size" gives an example of an EAN-13 barcode using the X-dimension of 0.33mm. +The GS1 General Specifications Section 5.2.6.6 'Symbol dimensions at nominal +size' gives an example of an EAN-13 barcode using the X-dimension of 0.33mm. To print that example as a PNG at 12 dots per mm (dpmm), the equivalent of 300 dots per inch (dpi = dpmm * 25.4), specify a scale of 2, since 0.33 * 12 = 3.96 pixels, or 4 pixels rounding to the nearest pixel: @@ -641,7 +641,7 @@ Health Industry Barcode (HIBC) data may also be encoded in the symbologies Code Code. Within this mode, the leading '+' and the check character are automatically added, conforming to HIBC Labeler Identification Code (HIBC LIC). For HIBC Provider Applications Standard (HIBC PAS), preface the data with a -slash "/". +slash '/'. The --binary option encodes the input data as given. Automatic code page translation to an ECI page is disabled, and no validation of the data's encoding @@ -650,25 +650,35 @@ switch plays together with the built-in ECI logic and examples may be found below. The --fullmultibyte option uses the multibyte modes of QR Code, Micro QR Code, -Rectangular Micro QR Code, Han Xin Code and Grid Matrix for binary and Latin -data, maximizing density. This is achieved by using compression designed for -Kanji/Hanzi characters, however some decoders take blocks which are encoded this -way and interpret them as Kanji/Hanzi characters, typically by applying a +Rectangular Micro QR Code (rMQR), Han Xin Code and Grid Matrix for binary and +Latin data, maximizing density. This is achieved by using compression designed +for Kanji/Hanzi characters, however some decoders take blocks which are encoded +this way and interpret them as Kanji/Hanzi characters, typically by applying a transformation to UTF-8 and thus causing data corruption. Symbols encoded with this option should be checked against decoders before they are used. The popular open-source ZXing decoder is known to exhibit this behaviour. If your data contains non-Latin-1 characters, you may encode it using an ECI-aware symbology and an ECI value from the table below. The ECI information -is added to your code symbol as prefix data. +is added to your code symbol as prefix data. The symbologies that support ECI +are Aztec Code, Code One, Data Matrix, DotCode, Grid Matrix, Han Xin Code, +MaxiCode, PDF417 and MicroPDF417, QR Code and rMQR, and Ultracode. The ECI value may be specified with the --eci switch, followed by the value in the column "ECI Code". The input data should be UTF-8 formatted. Zint automatically translates the data into the target encoding. -The ECI value of 0 does not encode any ECI information in the code symbol. In -this case, the default encoding applies for the data which is "ISO/IEC 8859-1 - -Latin alphabet No. 1". +An ECI value of 0 does not encode any ECI information in the code symbol (unless +the data contains non-Latin-1 characters). In this case, the default encoding +applies, which is "ISO/IEC 8859-1 - Latin alphabet No. 1". + +If no ECI is specified or a value of 0 is given, and the data does contain +characters other than Latin-1, then Zint will automatically insert the +appropriate single-byte ECI if possible (ECIs 4 to 24, excluding ECI 20), or +failing that ECI 26 (UTF-8). A warning will be generated. This mechanism is not +applied if the --binary option is given. + +Multiple ECIs can be specified using the --segN= options - see section 4.15. Note: the "--eci=3" specification should only be used for special purposes. Using this parameter, the ECI information is explicitly added to the code @@ -775,7 +785,7 @@ Input Character | Interpretation --------------------------------------------- ~ | Insert a number or '0' # | Insert a number or space -@ | Insert a number or "*" +@ | Insert a number or '*' Any other | Insert literally --------------------------------------------- @@ -847,7 +857,26 @@ minimum dot size is 0.01, the maximum is 20. The default size is 0.8. The default and minimum scale for raster output in dotty mode is 1. -4.15 Structured Append +4.15 Multiple Segments +---------------------- +If you need to specify different ECIs for different sections of the input data, +the --seg1= to --seg9= options can be used. Each option is of the form +--segN=ECI,data where "ECI" is the ECI code (see table in section 4.10) and +"data" is the data to which this applies. This is in addition to the ECI and +data specified using the --eci= and -d options which must still be present and +which in effect constitute segment 0. For instance + +zint -b AZTEC_CODE --eci=9 -d "Κείμενο" --seg1=13,"Текст" --seg2=20,"文章" + +specifies 3 segments: segment 0 with ECI 9 (Greek), segment 1 with ECI 7 +(Cyrillic), and segment 2 with ECI 20 (Shift JIS). Segments must be consecutive. + +ECIs of zero may be given, in which case Zint will automatically determine an +ECI if necessary, as described in section 4.10. + +Multiple segments are not currently supported for use with GS1 data. + +4.16 Structured Append ---------------------- Structured Append is a method of splitting data among several symbols so that they form a sequence that can be scanned and re-assembled in the correct order @@ -1557,7 +1586,62 @@ For HEIGHTPERROW_MODE, see --heightperrow in section 4.4. The height variable should be set to the desired per-row value on input (it will be set to the overall height on output). -5.11 Verifying Symbology Availability +5.11 Multiple Segments +---------------------- +For input data requiring multiple ECIs, the following functions may be used: + +int ZBarcode_Encode_Segs(struct zint_symbol *symbol, + const struct zint_seg segs[], const int seg_count); + +int ZBarcode_Encode_Segs_and_Print(struct zint_symbol *symbol, + const struct zint_seg segs[], const int seg_count, int rotate_angle); + +int ZBarcode_Encode_Segs_and_Buffer(struct zint_symbol *symbol, + const struct zint_seg segs[], const int seg_count, int rotate_angle); + +int ZBarcode_Encode_Segs_and_Buffer_Vector(struct zint_symbol *symbol, + const struct zint_seg segs[], const int seg_count, int rotate_angle); + +These are direct analogues of ZBarcode_Encode(), ZBarcode_Encode_and_Print(), +ZBarcode_Encode_and_Buffer() and ZBarcode_Encode_and_Buffer_Vector() +respectively, where in place of a "source, length" pair you have a "segs, +seg_count" pair, with "segs" being an array of zint_seg structures and +"seg_count" being the number of elements it contains. The zint_seg structure is +of the form: + +struct zint_seg { + unsigned char *source; /* Data to encode */ + int length; /* Length of `source`. If 0, `source` must be + NUL-terminated */ + int eci; /* Extended Channel Interpretation */ +}; + +The symbology must of course support ECIs, i.e. be Aztec Code, Code One, Data +Matrix, DotCode, Grid Matrix, Han Xin Code, MaxiCode, PDF417, MicroPDF417, QR +Code, rMQR, or Ultracode. For example: + +#include +int main(int argc, char **argv) +{ + struct zint_seg segs[] = { + { "Κείμενο", 0, 9 }, + { "Текст", 0, 7 }, + { "文章", 0, 20 } + }; + struct zint_symbol *my_symbol; + my_symbol = ZBarcode_Create(); + my_symbol->symbology = BARCODE_AZTEC; + my_symbol->input_mode = UNICODE_MODE; + ZBarcode_Encode_Segs(my_symbol, segs, 3); + ZBarcode_Print(my_symbol, 0); + ZBarcode_Delete(my_symbol); + return 0; +} + +A maximum of 256 segments may be specified. Use of multiple segments with GS1 +data is not currently supported. + +5.12 Verifying Symbology Availability ------------------------------------- An additional function available in the API is defined as: @@ -1588,7 +1672,7 @@ if (ZBarcode_BarcodeName(BARCODE_PDF417, name) == 0) { will print "BARCODE_PDF417". -5.12 Checking Symbology Capabilities +5.13 Checking Symbology Capabilities ------------------------------------ It can be useful for frontend programs to know the capabilities of a symbology. This can be determined using another additional function: @@ -1600,7 +1684,7 @@ see which are set. -------------------------------------------------------------------------------- Value | Meaning ---------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- ZINT_CAP_HRT | Can the symbology print Human Readable Text? ZINT_CAP_STACKABLE | Is the symbology stackable? ZINT_CAP_EXTENDABLE | Is the symbology extendable with add-on data? @@ -1635,7 +1719,7 @@ if (cap & ZINT_CAP_ECI) { printf("PDF417 does not support ECI\n"); } -5.13 Zint Version +5.14 Zint Version ----------------- Lastly, the version of the Zint library linked to is returned by: @@ -2003,7 +2087,7 @@ required. The GTIN check digit and AI (01) are added by Zint. 6.1.11.5 NVE-18 (SSCC-18) ------------------------- -A variation of Code 128 the "Nummer der Versandeinheit" standard, also known as +A variation of Code 128 the 'Nummer der Versandeinheit' standard, also known as SSCC-18 (Serial Shipping Container Code), includes both modulo-10 and modulo-103 check digits. NVE-18 requires a 17 digit numerical input. Check digits and AI (00) are added by Zint. @@ -2149,23 +2233,25 @@ or by setting option_1, with values from 2 to 16. Heavily used in the parcel industry, the PDF417 symbology can encode a vast amount of data into a small space. Zint supports encoding up to the ISO standard maximum symbol size of 925 codewords which (at error correction level -0) allows a maximum data size of 1850 text characters, or 2710 digits. The -width of the generated PDF417 symbol can be specified at the command line using -the --cols switch followed by a number between 1 and 30, the number of rows -using the --rows switch followed by a number between 3 and 90, and the amount of -error correction information can be specified by using the --secure switch -followed by a number between 0 and 8 where the number of codewords used for -error correction is determined by 2^(value + 1). If using the API these values -are assigned to option_2, option_3 and option_1 respectively. The default level -of error correction is determined by the amount of data being encoded. This -symbology uses Latin-1 character encoding by default but also supports the ECI -encoding mechanism. A separate symbology ID can be used to encode Health +0) allows a maximum data size of 1850 text characters, or 2710 digits. + +The width of the generated PDF417 symbol can be specified at the command line +using the --cols switch followed by a number between 1 and 30, the number of +rows using the --rows switch followed by a number between 3 and 90, and the +amount of error correction information can be specified by using the --secure +switch followed by a number between 0 and 8 where the number of codewords used +for error correction is determined by 2^(value + 1). If using the API these +values are assigned to option_2, option_3 and option_1 respectively. The default +level of error correction is determined by the amount of data being encoded. + +This symbology uses Latin-1 character encoding by default but also supports the +ECI encoding mechanism. A separate symbology ID can be used to encode Health Industry Barcode (HIBC) data which adds a leading '+' character and a modulo-49 check digit to the encoded data. PDF417 supports Structured Append of up to a 99,999 symbols and an optional numeric ID of up to 30 digits, which can be set by using the --structapp option -(see section 4.15) or the API structapp variable. The ID consists of up to 10 +(see section 4.16) or the API structapp variable. The ID consists of up to 10 triplets, each ranging from "000" to "899". For instance "123456789" would be a valid ID of 3 triplets. However "123456900" would not, as the last triplet "900" exceeds "899". The triplets are 0-filled, for instance "1234" becomes "123004". @@ -2184,9 +2270,10 @@ where symbol size needs to be kept to a minimum. 34 predefined symbol sizes are available with 1 - 4 columns and 4 - 44 rows. The maximum size a MicroPDF417 symbol can hold is 250 alphanumeric characters or 366 digits. The amount of error correction used is dependent on symbol size. The number of columns used -can be determined using the --cols switch or option_2 as with PDF417. This -symbology uses Latin-1 character encoding by default but also supports the ECI -encoding mechanism. A separate symbology ID can be used to encode Health +can be determined using the --cols switch or option_2 as with PDF417. + +This symbology uses Latin-1 character encoding by default but also supports the +ECI encoding mechanism. A separate symbology ID can be used to encode Health Industry Barcode (HIBC) data which adds a leading '+' character and a modulo-49 check digit to the encoded data. MicroPDF417 supports Structured Append the same as PDF417, for which see details. @@ -2440,40 +2527,20 @@ Barcode (HIBC) data which adds a leading '+' character and a modulo-49 check digit to the encoded data. Note that only ECC200 encoding is supported, the older standards have now been removed from Zint. ---------------------- -Input | Symbol Size ---------------------- -1 | 10 x 10 -2 | 12 x 12 -3 | 14 x 14 -4 | 16 x 16 -5 | 18 x 18 -6 | 20 x 20 -7 | 22 x 22 -8 | 24 x 24 -9 | 26 x 26 -10 | 32 x 32 -11 | 36 x 36 -12 | 40 x 40 -13 | 44 x 44 -14 | 48 x 48 -15 | 52 x 52 -16 | 64 x 64 -17 | 72 x 72 -18 | 80 x 80 -19 | 88 x 88 -20 | 96 x 96 -21 | 104 x 104 -22 | 120 x 120 -23 | 132 x 132 -24 | 144 x 144 -25 | 8 x 18 -26 | 8 x 32 -28 | 12 x 26 -28 | 12 x 36 -29 | 16 x 36 -30 | 16 x 48 ---------------------- +------------------------------------------------------------------------------- +Input | Symbol Size | Input | Symbol Size | Input | Symbol Size +------------------------------------------------------------------------------- +1 | 10 x 10 | 11 | 36 x 36 | 21 | 104 x 104 +2 | 12 x 12 | 12 | 40 x 40 | 22 | 120 x 120 +3 | 14 x 14 | 13 | 44 x 44 | 23 | 132 x 132 +4 | 16 x 16 | 14 | 48 x 48 | 24 | 144 x 144 +5 | 18 x 18 | 15 | 52 x 52 | 25 | 8 x 18 +6 | 20 x 20 | 16 | 64 x 64 | 26 | 8 x 32 +7 | 22 x 22 | 17 | 72 x 72 | 28 | 12 x 26 +8 | 24 x 24 | 18 | 80 x 80 | 28 | 12 x 36 +9 | 26 x 26 | 19 | 88 x 88 | 29 | 16 x 36 +10 | 32 x 32 | 20 | 96 x 96 | 30 | 16 x 48 +------------------------------------------------------------------------------- When using automatic symbol sizes you can force Zint to use square symbols (versions 1-24) at the command line by using the option --square and when @@ -2482,28 +2549,19 @@ using the API by setting the value option_3 = DM_SQUARE. Data Matrix Rectangular Extension (ISO/IEC 21471) codes may be generated with the following values as before: ---------------------- -Input | Symbol Size ---------------------- -31 | 8 x 48 -32 | 8 x 64 -33 | 8 x 80 -34 | 8 x 96 -35 | 8 x 120 -36 | 8 x 144 -37 | 12 x 64 -38 | 12 x 88 -39 | 16 x 64 -40 | 20 x 36 -41 | 20 x 44 -42 | 20 x 64 -43 | 22 x 48 -44 | 24 x 48 -45 | 24 x 64 -46 | 26 x 40 -47 | 26 x 48 -48 | 26 x 64 ---------------------- +--------------------------------------------------- +Input | Symbol Size | Input | Symbol Size +--------------------------------------------------- +31 | 8 x 48 | 40 | 20 x 36 +32 | 8 x 64 | 41 | 20 x 44 +33 | 8 x 80 | 42 | 20 x 64 +34 | 8 x 96 | 43 | 22 x 48 +35 | 8 x 120 | 44 | 24 x 48 +36 | 8 x 144 | 45 | 24 x 64 +37 | 12 x 64 | 46 | 26 x 40 +38 | 12 x 88 | 47 | 26 x 48 +39 | 16 x 64 | 48 | 26 x 64 +--------------------------------------------------- DMRE symbol sizes may be activated in automatic size mode using the option --dmre or by the API option_3 = DM_DMRE @@ -2516,7 +2574,7 @@ FAST_MODE) may be used. Data Matrix supports Structured Append of up to 16 symbols and a numeric ID (file identifications), which can be set by using the --structapp option (see -section 4.15) or the API structapp variable. The ID consists of 2 numbers ID1 +section 4.16) or the API structapp variable. The ID consists of 2 numbers ID1 and ID2, each of which can range from 1 to 254, and is specified as the single number ID1 * 1000 + ID2, so for instance ID1 "123" and ID2 "234" would be given as "123234". Note that both ID1 and ID2 must be non-zero, so e.g. "123000" or @@ -2528,63 +2586,37 @@ Also known as Quick Response Code this symbology was developed by Denso. Four levels of error correction are available using the --secure= option or by setting option_1 as shown in the following table. -------------------------------------------------------------------------- -Input | ECC Level | Error Correction Capacity | Recovery Capacity -------------------------------------------------------------------------- -1 | L (default) | Approx 20% of symbol | Approx 7% -2 | M | Approx 37% of symbol | Approx 15% -3 | Q | Approx 55% of symbol | Approx 25% -4 | H | Approx 65% of symbol | Approx 30% -------------------------------------------------------------------------- +----------------------------------------------------------------------- +Input | ECC Level | Error Correction Capacity | Recovery Capacity +----------------------------------------------------------------------- +1 | L | Approx 20% of symbol | Approx 7% +2 | M | Approx 37% of symbol | Approx 15% +3 | Q | Approx 55% of symbol | Approx 25% +4 | H | Approx 65% of symbol | Approx 30% +----------------------------------------------------------------------- The size of the symbol can be set by using the --vers= option or setting option_2 to the QR Code version required (1-40). The size of symbol generated is shown in the table below. ---------------------- -Input | Symbol Size ---------------------- -1 | 21 x 21 -2 | 25 x 25 -3 | 29 x 29 -4 | 33 x 33 -5 | 37 x 37 -6 | 41 x 41 -7 | 45 x 45 -8 | 49 x 49 -9 | 53 x 53 -10 | 57 x 57 -11 | 61 x 61 -12 | 65 x 65 -13 | 69 x 69 -14 | 73 x 73 -15 | 77 x 77 -16 | 81 x 81 -17 | 85 x 85 -18 | 89 x 89 -19 | 93 x 93 -20 | 97 x 97 -21 | 101 x 101 -22 | 105 x 105 -23 | 109 x 109 -24 | 113 x 113 -25 | 117 x 117 -26 | 121 x 121 -28 | 125 x 125 -28 | 129 x 129 -29 | 133 x 133 -30 | 137 x 137 -31 | 141 x 141 -32 | 145 x 145 -33 | 149 x 149 -34 | 153 x 153 -35 | 157 x 157 -36 | 161 x 161 -38 | 165 x 165 -38 | 169 x 169 -39 | 173 x 173 -40 | 177 x 177 ---------------------- +------------------------------------------------------------------------------- +Input | Symbol Size | Input | Symbol Size | Input | Symbol Size +------------------------------------------------------------------------------- +1 | 21 x 21 | 15 | 77 x 77 | 29 | 133 x 133 +2 | 25 x 25 | 16 | 81 x 81 | 30 | 137 x 137 +3 | 29 x 29 | 17 | 85 x 85 | 31 | 141 x 141 +4 | 33 x 33 | 18 | 89 x 89 | 32 | 145 x 145 +5 | 37 x 37 | 19 | 93 x 93 | 33 | 149 x 149 +6 | 41 x 41 | 20 | 97 x 97 | 34 | 153 x 153 +7 | 45 x 45 | 21 | 101 x 101 | 35 | 157 x 157 +8 | 49 x 49 | 22 | 105 x 105 | 36 | 161 x 161 +9 | 53 x 53 | 23 | 109 x 109 | 37 | 165 x 165 +10 | 57 x 57 | 24 | 113 x 113 | 38 | 169 x 169 +11 | 61 x 61 | 25 | 117 x 117 | 39 | 173 x 173 +12 | 65 x 65 | 26 | 121 x 121 | 40 | 177 x 177 +13 | 69 x 69 | 27 | 125 x 125 | +14 | 73 x 73 | 28 | 129 x 129 | +------------------------------------------------------------------------------- The maximum capacity of a (version 40) QR Code symbol is 7089 numeric digits, 4296 alphanumeric characters or 2953 bytes of data. QR Code symbols can also be @@ -2607,7 +2639,7 @@ by using the --mask= switch with values 0-7, or by setting option_3 to ZINT_FULL_MULTIBYTE | (N + 1) << 8. QR Code supports Structured Append of up to 16 symbols and a numeric ID -(parity), which can be set by using the --structapp option (see section 4.15) or +(parity), which can be set by using the --structapp option (see section 4.16) or the API structapp variable. The parity ID ranges from 0 (default) to 255, and for full compliance should be set to the value obtained by XOR-ing together each byte of the complete data forming the sequence. Currently this calculation must @@ -2615,23 +2647,40 @@ be done outside of Zint. 6.6.3 Micro QR Code (ISO 18004) ------------------------------- -A miniature version of the QR Code symbol for short messages. ECC levels can be -selected as for QR Code (above). QR Code symbols can encode characters in the -Latin-1 set and Kanji characters which are members of the Shift JIS encoding -scheme. Input should be entered as a UTF-8 stream with conversion to Shift JIS -being carried out automatically by Zint. A preferred symbol size can be -selected by using the --vers= option or by setting option_2 although the actual -version used by Zint may be different if required by the input data. The table -below shows the possible sizes: +A miniature version of the QR Code symbol for short messages, Micro QR Code +symbols can encode characters in the Latin-1 set and Kanji characters which are +members of the Shift JIS encoding scheme. Input should be entered as a UTF-8 +stream with conversion to Latin-1 or Shift JIS being carried out automatically +by Zint. A preferred symbol size can be selected by using the --vers= option or +by setting option_2, as shown in the table below. Note that versions M1 and M2 +have restrictions on what characters can be encoded. ---------------------------------- -Input | Version | Symbol Size ---------------------------------- -1 | M1 | 11 x 11 -2 | M2 | 13 x 13 -3 | M3 | 15 x 15 -4 | M4 | 17 x 17 ---------------------------------- +------------------------------------------------------------------------ +Input | Version | Symbol Size | Allowed Characters +------------------------------------------------------------------------ +1 | M1 | 11 x 11 | Numeric only +2 | M2 | 13 x 13 | Numeric, uppercase letters, space, + | | | and the characters "$%*+-./:" +3 | M3 | 15 x 15 | Latin-1 and Kanji +4 | M4 | 17 x 17 | Latin-1 and Kanji +------------------------------------------------------------------------ + +Except for version M1, which is always ECC level L, the amount of ECC codewords +can be adjusted using the --secure= option (API option_1); however ECC level H +is not available for any version, and ECC level Q is only available for version +M4: + +---------------------------------------------------------------------------- +Input | ECC | Error Correction | Recovery | Available for + | Level | Capacity | Capacity | Versions +---------------------------------------------------------------------------- +1 | L | Approx 20% of symbol | Approx 7% | M1, M2, M3, M4 +2 | M | Approx 37% of symbol | Approx 15% | M2, M3, M4 +3 | Q | Approx 55% of symbol | Approx 25% | M4 +--------------------------------------------------------------------------- + +The defaults for symbol size and ECC level depend on the input and whether +either of them is specified. For barcode readers that support it, non-ASCII data density may be maximized by using the --fullmultibyte switch or by setting option_3 to ZINT_FULL_MULTIBYTE. @@ -2653,60 +2702,40 @@ entered as UTF-8 with conversion being handled by Zint. The amount of ECC codewords can be adjusted using the --secure= option (API option_1), however only ECC levels M and H are valid for this type of symbol. -------------------------------------------------------------------------- -Input | ECC Level | Error Correction Capacity | Recovery Capacity -------------------------------------------------------------------------- -2 | M (default) | Approx 37% of symbol | Approx 15% -4 | H | Approx 65% of symbol | Approx 30% -------------------------------------------------------------------------- +----------------------------------------------------------------------- +Input | ECC Level | Error Correction Capacity | Recovery Capacity +----------------------------------------------------------------------- +2 | M | Approx 37% of symbol | Approx 15% +4 | H | Approx 65% of symbol | Approx 30% +----------------------------------------------------------------------- The preferred symbol sizes can be selected using the --vers= option (API option_2) as shown in the table below. Input values between 33 and 38 fix the height of the symbol while allowing Zint to determine the minimum symbol width. ---------------------------------------- -Input | Version | Symbol Size (HxW) ---------------------------------------- -1 | R7x43 | 7 x 73 -2 | R7x59 | 7 x 59 -3 | R7x77 | 7 x 77 -4 | R7x99 | 7 x 99 -5 | R7x139 | 7 x 139 -6 | R9x43 | 9 x 43 -7 | R9x59 | 9 x 59 -8 | R9x77 | 9 x 77 -9 | R9x99 | 9 x 99 -10 | R9x139 | 9 x 139 -11 | R11x27 | 11 x 27 -12 | R11x43 | 11 x 43 -13 | R11x59 | 11 x 59 -14 | R11x77 | 11 x 77 -15 | R11x99 | 11 x 99 -16 | R11x139 | 11 x 139 -17 | R13x27 | 13 x 27 -18 | R13x43 | 13 x 43 -19 | R13x59 | 13 x 59 -20 | R13x77 | 13 x 77 -21 | R13x99 | 13 x 99 -22 | R13x139 | 13 x 139 -23 | R15x43 | 15 x 43 -24 | R15x59 | 15 x 59 -25 | R15x77 | 15 x 77 -26 | R15x99 | 15 x 99 -27 | R15x139 | 15 x 139 -28 | R17x43 | 17 x 43 -29 | R17x59 | 17 x 59 -30 | R17x77 | 17 x 77 -31 | R17x99 | 17 x 99 -32 | R17x139 | 17 x 139 ---------------------------------------- -33 | R7 x automatic width -34 | R9 x automatic width -35 | R11 x automatic width -36 | R13 x automatic width -37 | R15 x automatic width -38 | R17 x automatic width ---------------------------------------- +-------------------------------------------------------------------------------- +Input | Version | Symbol Size (HxW) | Input | Version | Symbol Size (HxW) +-------------------------------------------------------------------------------- +1 | R7x43 | 7 x 73 | 20 | R13x77 | 13 x 77 +2 | R7x59 | 7 x 59 | 21 | R13x99 | 13 x 99 +3 | R7x77 | 7 x 77 | 22 | R13x139 | 13 x 139 +4 | R7x99 | 7 x 99 | 23 | R15x43 | 15 x 43 +5 | R7x139 | 7 x 139 | 24 | R15x59 | 15 x 59 +6 | R9x43 | 9 x 43 | 25 | R15x77 | 15 x 77 +7 | R9x59 | 9 x 59 | 26 | R15x99 | 15 x 99 +8 | R9x77 | 9 x 77 | 27 | R15x139 | 15 x 139 +9 | R9x99 | 9 x 99 | 28 | R17x43 | 17 x 43 +10 | R9x139 | 9 x 139 | 29 | R17x59 | 17 x 59 +11 | R11x27 | 11 x 27 | 30 | R17x77 | 17 x 77 +12 | R11x43 | 11 x 43 | 31 | R17x99 | 17 x 99 +13 | R11x59 | 11 x 59 | 32 | R17x139 | 17 x 139 +14 | R11x77 | 11 x 77 | 33 | R7xW | 7 x automatic width +15 | R11x99 | 11 x 99 | 34 | R9xW | 9 x automatic width +16 | R11x139 | 11 x 139 | 35 | R11xW | 11 x automatic width +17 | R13x27 | 13 x 27 | 36 | R13xW | 13 x automatic width +18 | R13x43 | 13 x 43 | 37 | R15xW | 15 x automatic width +19 | R13x59 | 13 x 59 | 38 | R17xW | 17 x automatic width +-------------------------------------------------------------------------------- For barcode readers that support it, non-ASCII data density may be maximized by using the --fullmultibyte switch or by setting option_3 to ZINT_FULL_MULTIBYTE. @@ -2797,7 +2826,7 @@ Mode | Maximum Data Length | Maximum Data Length | Number of Error * - secondary only MaxiCode supports Structured Append of up to 8 symbols, which can be set by -using the --structapp option (see section 4.15) or the API structapp variable. +using the --structapp option (see section 4.16) or the API structapp variable. It does not support specifying an ID. MaxiCode uses a different scaling than other symbols for raster output, see @@ -2808,7 +2837,7 @@ instead of 2. ---------------------------- Invented by Andrew Longacre at Welch Allyn Inc in 1995 the Aztec Code symbol is a matrix symbol with a distinctive bulls-eye finder pattern. Zint can generate -Compact Aztec Code (sometimes called Small Aztec Code) as well as "full-range" +Compact Aztec Code (sometimes called Small Aztec Code) as well as 'full-range' Aztec Code symbols and by default will automatically select symbol type and size dependent on the length of the data to be encoded. Error correction codewords will normally be generated to fill at least 23% of the symbol. Two @@ -2816,49 +2845,25 @@ options are available to change this behaviour: The size of the symbol can be specified using the --vers= option or setting option_2 to a value between 1 and 36 according to the following table. The -symbols marked with an asterisk (*) in the table below are "compact" symbols, +symbols marked with an asterisk (*) in the table below are 'compact' symbols, meaning they have a smaller bulls-eye pattern at the centre of the symbol. ---------------------- -Input | Symbol Size ---------------------- -1 | 15 x 15* -2 | 19 x 19* -3 | 23 x 23* -4 | 27 x 27* -5 | 19 x 19 -6 | 23 x 23 -7 | 27 x 27 -8 | 31 x 31 -9 | 37 x 37 -10 | 41 x 41 -11 | 45 x 45 -12 | 49 x 49 -13 | 53 x 53 -14 | 57 x 57 -15 | 61 x 61 -16 | 67 x 67 -17 | 71 x 71 -18 | 75 x 75 -19 | 79 x 79 -20 | 83 x 83 -21 | 87 x 87 -22 | 91 x 91 -23 | 95 x 95 -24 | 101 x 101 -25 | 105 x 105 -26 | 109 x 109 -27 | 113 x 113 -28 | 117 x 117 -29 | 121 x 121 -30 | 125 x 125 -31 | 131 x 131 -32 | 135 x 135 -33 | 139 x 139 -34 | 143 x 143 -35 | 147 x 147 -36 | 151 x 151 ---------------------- +------------------------------------------------------------------------------- +Input | Symbol Size | Input | Symbol Size | Input | Symbol Size +------------------------------------------------------------------------------- +1 | 15 x 15* | 13 | 53 x 53 | 25 | 105 x 105 +2 | 19 x 19* | 14 | 57 x 57 | 26 | 109 x 109 +3 | 23 x 23* | 15 | 61 x 61 | 27 | 113 x 113 +4 | 27 x 27* | 16 | 67 x 67 | 28 | 117 x 117 +5 | 19 x 19 | 17 | 71 x 71 | 29 | 121 x 121 +6 | 23 x 23 | 18 | 75 x 75 | 30 | 125 x 125 +7 | 27 x 27 | 19 | 79 x 79 | 31 | 131 x 131 +8 | 31 x 31 | 20 | 83 x 83 | 32 | 135 x 135 +9 | 37 x 37 | 21 | 87 x 87 | 33 | 139 x 139 +10 | 41 x 41 | 22 | 91 x 91 | 34 | 143 x 143 +11 | 45 x 45 | 23 | 95 x 95 | 35 | 147 x 147 +12 | 49 x 49 | 24 | 101 x 101 | 36 | 151 x 151 +------------------------------------------------------------------------------- Note that in symbols which have a specified size the amount of error correction is dependent on the length of the data input and Zint will allow error @@ -2888,7 +2893,7 @@ encoded data. Aztec Code supports Structured Append of up to 26 symbols and an optional alphanumeric ID of up to 32 characters, which can be set by using the ---structapp option (see section 4.15) or the API structapp variable. The ID +--structapp option (see section 4.16) or the API structapp variable. The ID cannot contain spaces. If an ID is not given, no ID is encoded. 6.6.8 Aztec Runes @@ -2926,7 +2931,7 @@ Version S symbols can only encode numeric data. The width of version S and version T symbols is determined by the length of the input data. Code One supports Structured Append of up to 128 symbols, which can be set by -using the --structapp option (see section 4.15) or the API structapp variable. +using the --structapp option (see section 4.16) or the API structapp variable. It does not support specifying an ID. Structured Append is not supported with GS1 data nor for Version S symbols. @@ -2945,23 +2950,17 @@ option or by setting option_2, and the error correction capacity can be specified by using the --secure= option or by setting option_1 according to the following tables: ---------------------- -Input | Symbol Size ---------------------- -1 | 18 x 18 -2 | 30 x 30 -3 | 42 x 42 -4 | 54 x 54 -5 | 66 x 66 -6 | 78 x 78 +---------------------------------------------------- +Input | Symbol Size | Input | Symbol Size +---------------------------------------------------- +1 | 18 x 18 | 8 | 102 x 102 +2 | 30 x 30 | 9 | 114 x 114 +3 | 42 x 42 | 10 | 126 x 126 +4 | 54 x 54 | 11 | 138 x 138 +5 | 66 x 66 | 12 | 150 x 150 +6 | 78 x 78 | 13 | 162 x 162 7 | 90 x 90 -8 | 102 x 102 -9 | 114 x 114 -10 | 126 x 126 -11 | 138 x 138 -12 | 150 x 150 -13 | 162 x 162 ---------------------- +---------------------------------------------------- ---------------------------------- Mode | Error Correction Capacity @@ -2979,7 +2978,7 @@ supports this before using. Grid Matrix supports Structured Append of up to 16 symbols and a numeric ID (file signature), which can be set by using the --structapp option (see section -4.15) or the API structapp variable. The ID ranges from 0 (default) to 255. +4.16) or the API structapp variable. The ID ranges from 0 (default) to 255. 6.6.11 DotCode -------------- @@ -2993,116 +2992,58 @@ setting the scale of the image to a larger value than the default (e.g. approx 10) for the dots to be plotted correctly. Approximately 33% of the resulting symbol is comprised of error correction codewords. -DotCode has two sets of 4 masks, designated 0-3 and 0'-3', the second "prime" +DotCode has two sets of 4 masks, designated 0-3 and 0'-3', the second 'prime' set being the same as the first with corners lit. The best mask to use is selected automatically by Zint but may be manually specified by using the --mask= switch with values 0-7, where 4-7 denote 0'-3', or by setting option_3 to (N + 1) << 8 where N is 0-7. DotCode supports Structured Append of up to 35 symbols, which can be set by -using the --structapp option (see section 4.15) or the API structapp variable. +using the --structapp option (see section 4.16) or the API structapp variable. It does not support specifying an ID. 6.6.12 Han Xin Code ------------------- -Also known as Chinese Sensible Code, Han Xin is a symbology which is still under -development, so it is recommended it should not yet be used for a production -environment. The symbology is capable of encoding characters in the GB 18030 -character set (which includes all Unicode characters) and is also able to -support the ECI mechanism. Support for the encoding of GS1 data has not yet been -implemented. +Also known as Chinese Sensible Code, Han Xin is capable of encoding characters +in the GB 18030 character set (which includes all Unicode characters) and is +also able to support the ECI mechanism. Support for the encoding of GS1 data has +not yet been implemented. The size of the symbol can be specified using the --vers= option or setting option_2 to a value between 1 and 84 according to the following table. ---------------------- -Input | Symbol Size ---------------------- -1 | 23 x 23 -2 | 25 x 25 -3 | 27 x 27 -4 | 29 x 29 -5 | 31 x 31 -6 | 33 x 33 -7 | 35 x 35 -8 | 37 x 37 -9 | 39 x 39 -10 | 41 x 41 -11 | 43 x 43 -12 | 45 x 45 -13 | 47 x 47 -14 | 49 x 49 -15 | 51 x 51 -16 | 53 x 53 -17 | 55 x 55 -18 | 57 x 57 -19 | 59 x 59 -20 | 61 x 61 -21 | 63 x 63 -22 | 65 x 65 -23 | 67 x 67 -24 | 69 x 69 -25 | 71 x 71 -26 | 73 x 73 -28 | 75 x 75 -28 | 77 x 77 -29 | 79 x 79 -30 | 81 x 81 -31 | 83 x 83 -32 | 85 x 85 -33 | 87 x 87 -34 | 89 x 89 -35 | 91 x 91 -36 | 93 x 93 -37 | 95 x 95 -38 | 97 x 97 -39 | 99 x 99 -40 | 101 x 101 -41 | 103 x 103 -42 | 105 x 105 -43 | 107 x 107 -44 | 109 x 109 -45 | 111 x 111 -46 | 113 x 113 -47 | 115 x 115 -48 | 117 x 117 -49 | 119 x 119 -50 | 121 x 121 -51 | 123 x 123 -52 | 125 x 125 -53 | 127 x 127 -54 | 129 x 129 -55 | 131 x 131 -56 | 133 x 133 -57 | 135 x 135 -58 | 137 x 137 -59 | 139 x 139 -60 | 141 x 141 -61 | 143 x 143 -62 | 145 x 145 -63 | 147 x 147 -64 | 149 x 149 -65 | 151 x 151 -66 | 153 x 153 -67 | 155 x 155 -68 | 157 x 157 -69 | 159 x 159 -70 | 161 x 161 -71 | 163 x 163 -72 | 165 x 165 -73 | 167 x 167 -74 | 169 x 169 -75 | 171 x 171 -76 | 173 x 173 -77 | 175 x 175 -78 | 177 x 177 -79 | 179 x 179 -80 | 181 x 181 -81 | 183 x 183 -82 | 185 x 185 -83 | 187 x 187 -84 | 189 x 189 ---------------------- +------------------------------------------------------------------------------- +Input | Symbol Size | Input | Symbol Size | Input | Symbol Size +------------------------------------------------------------------------------- +1 | 23 x 23 | 29 | 79 x 79 | 57 | 135 x 135 +2 | 25 x 25 | 30 | 81 x 81 | 58 | 137 x 137 +3 | 27 x 27 | 31 | 83 x 83 | 59 | 139 x 139 +4 | 29 x 29 | 32 | 85 x 85 | 60 | 141 x 141 +5 | 31 x 31 | 33 | 87 x 87 | 61 | 143 x 143 +6 | 33 x 33 | 34 | 89 x 89 | 62 | 145 x 145 +7 | 35 x 35 | 35 | 91 x 91 | 63 | 147 x 147 +8 | 37 x 37 | 36 | 93 x 93 | 64 | 149 x 149 +9 | 39 x 39 | 37 | 95 x 95 | 65 | 151 x 151 +10 | 41 x 41 | 38 | 97 x 97 | 66 | 153 x 153 +11 | 43 x 43 | 39 | 99 x 99 | 67 | 155 x 155 +12 | 45 x 45 | 40 | 101 x 101 | 68 | 157 x 157 +13 | 47 x 47 | 41 | 103 x 103 | 69 | 159 x 159 +14 | 49 x 49 | 42 | 105 x 105 | 70 | 161 x 161 +15 | 51 x 51 | 43 | 107 x 107 | 71 | 163 x 163 +16 | 53 x 53 | 44 | 109 x 109 | 72 | 165 x 165 +17 | 55 x 55 | 45 | 111 x 111 | 73 | 167 x 167 +18 | 57 x 57 | 46 | 113 x 113 | 74 | 169 x 169 +19 | 59 x 59 | 47 | 115 x 115 | 75 | 171 x 171 +20 | 61 x 61 | 48 | 117 x 117 | 76 | 173 x 173 +21 | 63 x 63 | 49 | 119 x 119 | 77 | 175 x 175 +22 | 65 x 65 | 50 | 121 x 121 | 78 | 177 x 177 +23 | 67 x 67 | 51 | 123 x 123 | 79 | 179 x 179 +24 | 69 x 69 | 52 | 125 x 125 | 80 | 181 x 181 +25 | 71 x 71 | 53 | 127 x 127 | 81 | 183 x 183 +26 | 73 x 73 | 54 | 129 x 129 | 82 | 185 x 185 +27 | 75 x 75 | 55 | 131 x 131 | 83 | 187 x 187 +28 | 77 x 77 | 56 | 133 x 133 | 84 | 189 x 189 +------------------------------------------------------------------------------- There are four levels of error correction capacity available for Han Xin Code which can be set by using the --secure= option or by setting option_1 to a value @@ -3159,7 +3100,7 @@ option_2 to 2. Ultracode supports Structured Append of up to 8 symbols and an optional numeric ID (File Number), which can be set by using the --structapp option (see section -4.15) or the API structapp variable. The ID ranges from 1 to 80088. If an ID is +4.16) or the API structapp variable. The ID ranges from 1 to 80088. If an ID is not given, no ID is encoded. 6.7 Other Barcode-Like Markings diff --git a/frontend/main.c b/frontend/main.c index d1e767b8..3cea7966 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -127,14 +127,14 @@ static void usage(void) { " --cmyk Use CMYK colour space in EPS/TIF symbols\n" " --cols=NUMBER Set the number of data columns in symbol\n" " --compliantheight Warn if height not compliant, and use standard default\n" - " -d, --data=DATA Set the symbol content\n" + " -d, --data=DATA Set the symbol data content (segment 0)\n" " --direct Send output to stdout\n" " --dmre Allow Data Matrix Rectangular Extended\n" " --dotsize=NUMBER Set radius of dots in dotty mode\n" " --dotty Use dots instead of squares for matrix symbols\n" " --dump Dump hexadecimal representation to stdout\n" - " -e, --ecinos Display table of ECI character encodings\n" - " --eci=NUMBER Set the ECI (Extended Channel Interpretation) code\n" + " -e, --ecinos Display ECI (Extended Channel Interpretation) table\n" + " --eci=NUMBER Set the ECI code for the data (segment 0)\n" " --esc Process escape characters in input data\n" " --fast Use faster encodation (Data Matrix)\n" " --fg=COLOUR Specify a foreground colour (in hex RGB/RGBA)\n" @@ -165,6 +165,7 @@ static void usage(void) { " --scale=NUMBER Adjust size of X-dimension\n" " --scmvv=NUMBER Prefix SCM with \"[)>\\R01\\Gvv\" (vv is NUMBER) (MaxiCode)\n" " --secure=NUMBER Set error correction level (ECC)\n" + " --segN=ECI,DATA Set the ECI & data content for segment N where N is 1 to 9\n" " --separator=NUMBER Set height of row separator bars (stacked symbologies)\n" " --small Use small text\n" " --square Force Data Matrix symbols to be square\n" @@ -561,6 +562,28 @@ int validate_structapp(const char *optarg, struct zint_structapp *structapp) { return 1; } +/* Parse and validate the segment argument "ECI,DATA" to "--segN" */ +static int validate_seg(const char *optarg, const int N, struct zint_seg segs[10]) { + char eci[10] = {0}; + const char *comma = strchr(optarg, ','); + if (!comma || comma == optarg || comma - optarg > 9 || *(comma + 1) == '\0') { + fprintf(stderr, "Error 166: Invalid segment argument, expect \"ECI,DATA\"\n"); + return 0; + } + strncpy(eci, optarg, comma - optarg); + if (!validate_int(eci, &segs[N].eci)) { + fprintf(stderr, "Error 167: Invalid segment ECI (digits only)\n"); + return 0; + } + if (segs[N].eci > 999999) { + fprintf(stderr, "Error 168: Segment ECI code out of range (0 to 999999)\n"); + return 0; + } + segs[N].length = (int) strlen(comma + 1); + segs[N].source = (unsigned char *) (comma + 1); + return 1; +} + /* Batch mode - output symbol for each line of text in `filename` */ static int batch_process(struct zint_symbol *symbol, const char *filename, const int mirror_mode, const char *filetype, const int rotate_angle) { @@ -819,6 +842,7 @@ typedef struct { char *arg; int opt; } arg_opt; int main(int argc, char **argv) { struct zint_symbol *my_symbol; + struct zint_seg segs[10] = {0}; int error_number = 0; int rotate_angle = 0; int help = 0; @@ -839,6 +863,7 @@ int main(int argc, char **argv) { int ret; char *outfile_extension; int data_arg_num = 0; + int seg_count = 0; float float_opt; #ifndef _MSC_VER arg_opt arg_opts[argc]; @@ -872,8 +897,9 @@ int main(int argc, char **argv) { OPT_GS1, OPT_GS1NOCHECK, OPT_GS1PARENS, OPT_GSSEP, OPT_GUARDDESCENT, OPT_HEIGHT, OPT_HEIGHTPERROW, OPT_INIT, OPT_MIRROR, OPT_MASK, OPT_MODE, OPT_NOBACKGROUND, OPT_NOQUIETZONES, OPT_NOTEXT, OPT_PRIMARY, OPT_QUIETZONES, - OPT_ROTATE, OPT_ROWS, OPT_SCALE, OPT_SCMVV, - OPT_SECURE, OPT_SEPARATOR, OPT_SMALL, OPT_SQUARE, OPT_STRUCTAPP, + OPT_ROTATE, OPT_ROWS, OPT_SCALE, OPT_SCMVV, OPT_SECURE, + OPT_SEG1, OPT_SEG2, OPT_SEG3, OPT_SEG4, OPT_SEG5, OPT_SEG6, OPT_SEG7, OPT_SEG8, OPT_SEG9, + OPT_SEPARATOR, OPT_SMALL, OPT_SQUARE, OPT_STRUCTAPP, OPT_VERBOSE, OPT_VERS, OPT_VWHITESP, OPT_WERROR, }; int option_index = 0; @@ -929,6 +955,15 @@ int main(int argc, char **argv) { {"scale", 1, NULL, OPT_SCALE}, {"scmvv", 1, NULL, OPT_SCMVV}, {"secure", 1, NULL, OPT_SECURE}, + {"seg1", 1, NULL, OPT_SEG1}, + {"seg2", 1, NULL, OPT_SEG2}, + {"seg3", 1, NULL, OPT_SEG3}, + {"seg4", 1, NULL, OPT_SEG4}, + {"seg5", 1, NULL, OPT_SEG5}, + {"seg6", 1, NULL, OPT_SEG6}, + {"seg7", 1, NULL, OPT_SEG7}, + {"seg8", 1, NULL, OPT_SEG8}, + {"seg9", 1, NULL, OPT_SEG9}, {"separator", 1, NULL, OPT_SEPARATOR}, {"small", 0, NULL, OPT_SMALL}, {"square", 0, NULL, OPT_SQUARE}, @@ -1241,6 +1276,32 @@ int main(int argc, char **argv) { fflush(stderr); } break; + case OPT_SEG1: + case OPT_SEG2: + case OPT_SEG3: + case OPT_SEG4: + case OPT_SEG5: + case OPT_SEG6: + case OPT_SEG7: + case OPT_SEG8: + case OPT_SEG9: + if (batch_mode == 0) { + val = c - OPT_SEG1 + 1; /* Segment number */ + if (segs[val].source) { + fprintf(stderr, "Error 164: Duplicate segment %d\n", val); + return do_exit(1); + } + if (!validate_seg(optarg, c - OPT_SEG1 + 1, segs)) { + return do_exit(1); + } + if (val >= seg_count) { + seg_count = val + 1; + } + } else { + fprintf(stderr, "Warning 165: Can't define segments in batch mode, ignoring '%s'\n", optarg); + fflush(stderr); + } + break; case OPT_SEPARATOR: if (!validate_int(optarg, &val)) { fprintf(stderr, "Error 128: Invalid separator value (digits only)\n"); @@ -1419,6 +1480,10 @@ int main(int argc, char **argv) { fprintf(stderr, "Warning 144: Processing first input file '%s' only\n", arg_opts[0].arg); fflush(stderr); } + if (seg_count) { + fprintf(stderr, "Warning 169: Ignoring segment arguments\n"); + fflush(stderr); + } if (filetype[0] == '\0') { outfile_extension = get_extension(my_symbol->outfile); if (outfile_extension && supported_filetype(outfile_extension, no_png, NULL)) { @@ -1440,6 +1505,25 @@ int main(int argc, char **argv) { fflush(stderr); } } else { + if (seg_count) { + if (data_arg_num > 1) { + fprintf(stderr, "Error 170: Cannot specify segments and multiple data arguments together\n"); + return do_exit(1); + } + if (arg_opts[0].opt != 'd') { /* For simplicity disallow input args for now */ + fprintf(stderr, "Error 171: Cannot use input argument with segment arguments\n"); + return do_exit(1); + } + segs[0].eci = my_symbol->eci; + segs[0].source = (unsigned char *) arg_opts[0].arg; + segs[0].length = (int) strlen(arg_opts[0].arg); + for (i = 0; i < seg_count; i++) { + if (segs[i].source == NULL) { + fprintf(stderr, "Error 172: Segments must be consecutive - segment %d missing\n", i); + return do_exit(1); + } + } + } if (filetype[0] != '\0') { set_extension(my_symbol->outfile, filetype); } @@ -1452,8 +1536,12 @@ int main(int argc, char **argv) { } for (i = 0; i < data_arg_num; i++) { if (arg_opts[i].opt == 'd') { - ret = ZBarcode_Encode(my_symbol, (unsigned char *) arg_opts[i].arg, - (int) strlen(arg_opts[i].arg)); + if (seg_count) { + ret = ZBarcode_Encode_Segs(my_symbol, segs, seg_count); + } else { + ret = ZBarcode_Encode(my_symbol, (unsigned char *) arg_opts[i].arg, + (int) strlen(arg_opts[i].arg)); + } } else { ret = ZBarcode_Encode_File(my_symbol, arg_opts[i].arg); } diff --git a/frontend/tests/test_args.c b/frontend/tests/test_args.c index 9954c0ca..a11ad5c8 100644 --- a/frontend/tests/test_args.c +++ b/frontend/tests/test_args.c @@ -150,6 +150,14 @@ static void arg_data(char *cmd, const char *opt, const char *data) { } } +static void arg_seg(char *cmd, const char *opt, const char *data, const int eci) { + if (data != NULL) { + sprintf(cmd + (int) strlen(cmd), "%s%s%d,\"%s\"", strlen(cmd) ? " " : "", opt, eci, data); + } else { + sprintf(cmd + (int) strlen(cmd), "%s%s%d", strlen(cmd) ? " " : "", opt, eci); + } +} + static int arg_input(char *cmd, const char *filename, const char *input) { FILE *fp; int cnt; @@ -369,6 +377,77 @@ static void test_dump_args(int index, int debug) { testFinish(); } +// Tests segs +static void test_dump_segs(int index, int debug) { + + struct item { + int b; + char *data; + char *data_seg1; + char *data_seg2; + int eci; + int eci_seg1; + int eci_seg2; + + char *expected; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { -1, "123", NULL, NULL, -1, -1, -1, "D2 13 9B 39 65 C8 C9 8E B" }, + /* 1*/ { -1, "123", NULL, NULL, -1, 3, -1, "Error 166: Invalid segment argument, expect \"ECI,DATA\"" }, + /* 2*/ { -1, "123", "456", NULL, -1, -1, -1, "Error 167: Invalid segment ECI (digits only)" }, + /* 3*/ { -1, "123", "456", NULL, -1, 1000000, -1, "Error 168: Segment ECI code out of range (0 to 999999)" }, + /* 4*/ { -1, "123", "456", NULL, -1, 3, -1, "Error 775: Symbology does not support multiple segments" }, + /* 5*/ { BARCODE_AZTEC, "123", "456", NULL, -1, 3, -1, "2B 7A\nC7 02\nF0 6E\n3F FE\n70 1C\nB7 D6\nB4 58\n15 54\n94 56\nB7 DC\n30 1A\n1F FC\n4C 66\n22 DA\n1E C6" }, + /* 6*/ { BARCODE_AZTEC, "123", NULL, "789", -1, -1, 3, "Error 172: Segments must be consecutive - segment 1 missing" }, + }; + int data_size = ARRAY_SIZE(data); + int i; + + char cmd[4096]; + char buf[4096]; + + testStart("test_dump_segs"); + + for (i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + strcpy(cmd, "zint --dump"); + if (debug & ZINT_DEBUG_PRINT) { + strcat(cmd, " --verbose"); + } + + arg_int(cmd, "-b ", data[i].b); + + if (data[i].data && data[i].data[0]) { + arg_data(cmd, "-d ", data[i].data); + } + if (data[i].eci > 0) { + arg_int(cmd, "--eci=", data[i].eci); + } + + if (data[i].data_seg1 && data[i].data_seg1[0]) { + arg_seg(cmd, "--seg1=", data[i].data_seg1, data[i].eci_seg1); + } else if (data[i].eci_seg1 >= 0) { + arg_seg(cmd, "--seg1=", NULL, data[i].eci_seg1); + } + + if (data[i].data_seg2 && data[i].data_seg2[0]) { + arg_seg(cmd, "--seg2=", data[i].data_seg2, data[i].eci_seg2); + } else if (data[i].eci_seg2 >= 0) { + arg_seg(cmd, "--seg2=", NULL, data[i].eci_seg2); + } + + strcat(cmd, " 2>&1"); + + assert_nonnull(exec(cmd, buf, sizeof(buf) - 1, debug, i), "i:%d exec(%s) NULL\n", i, cmd); + assert_zero(strcmp(buf, data[i].expected), "i:%d buf (%s) != expected (%s) (%s)\n", i, buf, data[i].expected, cmd); + } + + testFinish(); +} + static void test_input(int index, int debug) { #define TEST_INPUT_LONG "test_67890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" @@ -997,6 +1076,7 @@ int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ { "test_dump_args", test_dump_args, 1, 0, 1 }, + { "test_dump_segs", test_dump_segs, 1, 0, 1 }, { "test_input", test_input, 1, 0, 1 }, { "test_stdin_input", test_stdin_input, 1, 0, 1 }, { "test_batch_input", test_batch_input, 1, 0, 1 }, diff --git a/frontend_qt/main.cpp b/frontend_qt/main.cpp index 85412770..23f77888 100644 --- a/frontend_qt/main.cpp +++ b/frontend_qt/main.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * Copyright (C) 2008 by BogDan Vatra * - * Copyright (C) 2009-2021 by Robin Stuart * + * Copyright (C) 2009-2022 by Robin Stuart * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * @@ -13,7 +13,6 @@ * You should have received a copy of the GNU General Public License * * along with this program. If not, see . * ***************************************************************************/ -/* vim: set ts=4 sw=4 et : */ #include #include "mainwindow.h" @@ -38,3 +37,5 @@ int main(int argc, char *argv[]) w.show(); return app.exec(); } + +/* vim: set ts=4 sw=4 et : */ diff --git a/frontend_qt/mainWindow.ui b/frontend_qt/mainWindow.ui index b9844af2..5a674839 100644 --- a/frontend_qt/mainWindow.ui +++ b/frontend_qt/mainWindow.ui @@ -186,49 +186,294 @@ Input data - + - - - Input data - - - Your Data Here! - - - - - - - - 0 - 24 - - - - Encode more data + + + + + Input data + + + Your Data Here! + + + + + + + + 0 + 24 + + + + Encode more data or import from file - - - &... - - + + + &... + + + + + + + Encode a sequence + + + 123&4.. + + + + 60 + 16777215 + + + + + - - - - 0 - 24 - - - - Encode a sequence - - - &123.. - - + + + + + + 40 + 16777215 + + + + Set the ECI (Extended Channel Interpretation) code +(ignored if disabled) + + + EC&I: + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + cmbECI + + + + + + + + 64 + 0 + + + + 34 + + + Set the ECI (Extended Channel Interpretation) code +(ignored if disabled) + + + + None + + + + + 3: ISO 8859-1 Latin-1 + + + + + 4: ISO 8859-2 Latin-2 + + + + + 5: ISO 8859-3 Latin-3 + + + + + 6: ISO 8859-4 Latin-4 + + + + + 7: ISO 8859-5 Cyrillic + + + + + 8: ISO 8859-6 Arabic + + + + + 9: ISO 8859-7 Greek + + + + + 10: ISO 8859-8 Hebrew + + + + + 11: ISO 8859-9 Turkish + + + + + 12: ISO 8859-10 Nordic + + + + + 13: ISO 8859-11 Thai + + + + + 15: ISO 8859-13 Baltic + + + + + 16: ISO 8859-14 Celtic + + + + + 17: ISO 8859-15 Latin-9 + + + + + 18: ISO 8859-16 Latin-10 + + + + + 20: Shift JIS + + + + + 21: Windows 1250 Latin-2 + + + + + 22: Windows 1251 Cyrillic + + + + + 23: Windows 1252 Latin-1 + + + + + 24: Windows 1256 Arabic + + + + + 25: UTF-16BE + + + + + 26: UTF-8 + + + + + 27: ISO 646 ASCII + + + + + 28: Big5 (Taiwan) + + + + + 29: GB 2312 (PRC) + + + + + 30: Korean EUC-KR + + + + + 31: GBK + + + + + 32: GB 18030 + + + + + 33: UTF-16LE + + + + + 34: UTF-32BE + + + + + 35: UTF-32LE + + + + + 170: ISO 646 Invariant + + + + + 899: 8-bit binary data + + + + + + + + Qt::Horizontal + + + + 10 + 20 + + + + + + + + Create reader initialisation/programming symbol +(ignored if disabled) + + + &Reader Init + + + false + + + + @@ -393,245 +638,786 @@ Remember to place [square brackets] around AI identifiers - - - - - - 40 - 16777215 - - - - Set the ECI (Extended Channel Interpretation) code -(ignored if disabled) - - - EC&I: - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - cmbECI - - - - - - - - 64 - 0 - - - - 34 - - - Set the ECI (Extended Channel Interpretation) code -(ignored if disabled) - - - - None - - - - - 3: ISO 8859-1 Latin-1 - - - - - 4: ISO 8859-2 Latin-2 - - - - - 5: ISO 8859-3 Latin-3 - - - - - 6: ISO 8859-4 Latin-4 - - - - - 7: ISO 8859-5 Cyrillic - - - - - 8: ISO 8859-6 Arabic - - - - - 9: ISO 8859-7 Greek - - - - - 10: ISO 8859-8 Hebrew - - - - - 11: ISO 8859-9 Turkish - - - - - 12: ISO 8859-10 Nordic - - - - - 13: ISO 8859-11 Thai - - - - - 15: ISO 8859-13 Baltic - - - - - 16: ISO 8859-14 Celtic - - - - - 17: ISO 8859-15 Latin-9 - - - - - 18: ISO 8859-16 Latin-10 - - - - - 20: Shift JIS - - - - - 21: Windows 1250 Latin-2 - - - - - 22: Windows 1251 Cyrillic - - - - - 23: Windows 1252 Latin-1 - - - - - 24: Windows 1256 Arabic - - - - - 25: UTF-16BE - - - - - 26: UTF-8 - - - - - 27: ISO 646 ASCII - - - - - 28: Big5 (Taiwan) - - - - - 29: GB 2312 (PRC) - - - - - 30: Korean EUC-KR - - - - - 31: GBK - - - - - 32: GB 18030 - - - - - 33: UTF-16LE - - - - - 34: UTF-32BE - - - - - 35: UTF-32LE - - - - - 170: ISO 646 Invariant - - - - - 899: 8-bit binary data - - - - - - - - Qt::Horizontal - - - - 10 - 20 - - - - - - - - Create reader initialisation/programming symbol -(ignored if disabled) - - - &Reader Init - - - false - - - - + + + true + + + + 0 + 0 + + + + + 0 + 0 + + + + + 16777215 + 400 + + + + Additional ECI/Data Segments + + + Additional data segments with their own +Extended Channel Interpretation (ECI) + + + + + + + + true + + + Segment 1 + + + &1: + + + txtDataSeg1 + + + + + + + + 64 + 0 + + + + + 160 + 16777215 + + + + 34 + + + ECI for segment 1 + + + + None + + + + + 3: ISO 8859-1 Latin-1 + + + + + 4: ISO 8859-2 Latin-2 + + + + + 5: ISO 8859-3 Latin-3 + + + + + 6: ISO 8859-4 Latin-4 + + + + + 7: ISO 8859-5 Cyrillic + + + + + 8: ISO 8859-6 Arabic + + + + + 9: ISO 8859-7 Greek + + + + + 10: ISO 8859-8 Hebrew + + + + + 11: ISO 8859-9 Turkish + + + + + 12: ISO 8859-10 Nordic + + + + + 13: ISO 8859-11 Thai + + + + + 15: ISO 8859-13 Baltic + + + + + 16: ISO 8859-14 Celtic + + + + + 17: ISO 8859-15 Latin-9 + + + + + 18: ISO 8859-16 Latin-10 + + + + + 20: Shift JIS + + + + + 21: Windows 1250 Latin-2 + + + + + 22: Windows 1251 Cyrillic + + + + + 23: Windows 1252 Latin-1 + + + + + 24: Windows 1256 Arabic + + + + + 25: UTF-16BE + + + + + 26: UTF-8 + + + + + 27: ISO 646 ASCII + + + + + 28: Big5 (Taiwan) + + + + + 29: GB 2312 (PRC) + + + + + 30: Korean EUC-KR + + + + + 31: GBK + + + + + 32: GB 18030 + + + + + 33: UTF-16LE + + + + + 34: UTF-32BE + + + + + 35: UTF-32LE + + + + + 170: ISO 646 Invariant + + + + + 899: 8-bit binary data + + + + + + + + + 200 + 0 + + + + Data for segment 1 + + + + + + + + + + + 0 + 24 + + + + Encode more segment 1 data +or import from file + + + ... + + + + + + + + + + + true + + + Segment 2 + + + &2: + + + txtDataSeg2 + + + + + + + + 64 + 0 + + + + + 160 + 16777215 + + + + 34 + + + ECI for segment 2 + + + + None + + + + + 3: ISO 8859-1 Latin-1 + + + + + 4: ISO 8859-2 Latin-2 + + + + + 5: ISO 8859-3 Latin-3 + + + + + 6: ISO 8859-4 Latin-4 + + + + + 7: ISO 8859-5 Cyrillic + + + + + 8: ISO 8859-6 Arabic + + + + + 9: ISO 8859-7 Greek + + + + + 10: ISO 8859-8 Hebrew + + + + + 11: ISO 8859-9 Turkish + + + + + 12: ISO 8859-10 Nordic + + + + + 13: ISO 8859-11 Thai + + + + + 15: ISO 8859-13 Baltic + + + + + 16: ISO 8859-14 Celtic + + + + + 17: ISO 8859-15 Latin-9 + + + + + 18: ISO 8859-16 Latin-10 + + + + + 20: Shift JIS + + + + + 21: Windows 1250 Latin-2 + + + + + 22: Windows 1251 Cyrillic + + + + + 23: Windows 1252 Latin-1 + + + + + 24: Windows 1256 Arabic + + + + + 25: UTF-16BE + + + + + 26: UTF-8 + + + + + 27: ISO 646 ASCII + + + + + 28: Big5 (Taiwan) + + + + + 29: GB 2312 (PRC) + + + + + 30: Korean EUC-KR + + + + + 31: GBK + + + + + 32: GB 18030 + + + + + 33: UTF-16LE + + + + + 34: UTF-32BE + + + + + 35: UTF-32LE + + + + + 170: ISO 646 Invariant + + + + + 899: 8-bit binary data + + + + + + + + + 200 + 0 + + + + Data for segment 2 + + + + + + + + + + + 0 + 24 + + + + Encode more segment 2 data +or import from file + + + ... + + + + + + + + + + + true + + + Segment 3 + + + &3: + + + txtDataSeg3 + + + + + + + + 64 + 0 + + + + + 160 + 16777215 + + + + 34 + + + ECI for segment 3 + + + + None + + + + + 3: ISO 8859-1 Latin-1 + + + + + 4: ISO 8859-2 Latin-2 + + + + + 5: ISO 8859-3 Latin-3 + + + + + 6: ISO 8859-4 Latin-4 + + + + + 7: ISO 8859-5 Cyrillic + + + + + 8: ISO 8859-6 Arabic + + + + + 9: ISO 8859-7 Greek + + + + + 10: ISO 8859-8 Hebrew + + + + + 11: ISO 8859-9 Turkish + + + + + 12: ISO 8859-10 Nordic + + + + + 13: ISO 8859-11 Thai + + + + + 15: ISO 8859-13 Baltic + + + + + 16: ISO 8859-14 Celtic + + + + + 17: ISO 8859-15 Latin-9 + + + + + 18: ISO 8859-16 Latin-10 + + + + + 20: Shift JIS + + + + + 21: Windows 1250 Latin-2 + + + + + 22: Windows 1251 Cyrillic + + + + + 23: Windows 1252 Latin-1 + + + + + 24: Windows 1256 Arabic + + + + + 25: UTF-16BE + + + + + 26: UTF-8 + + + + + 27: ISO 646 ASCII + + + + + 28: Big5 (Taiwan) + + + + + 29: GB 2312 (PRC) + + + + + 30: Korean EUC-KR + + + + + 31: GBK + + + + + 32: GB 18030 + + + + + 33: UTF-16LE + + + + + 34: UTF-32BE + + + + + 35: UTF-32LE + + + + + 170: ISO 646 Invariant + + + + + 899: 8-bit binary data + + + + + + + + + 200 + 0 + + + + Data for segment 3 + + + + + + + + + + + 0 + 24 + + + + Encode more segment 3 data +or import from file + + + ... + + + + + + + + + + + + Qt::Vertical + + + + 40 + 10 + + + diff --git a/frontend_qt/mainwindow.cpp b/frontend_qt/mainwindow.cpp index 7864e662..b04fa9f5 100644 --- a/frontend_qt/mainwindow.cpp +++ b/frontend_qt/mainwindow.cpp @@ -171,10 +171,12 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags fl) bstyle->setCurrentIndex(settings.value(QSL("studio/symbology"), 10).toInt()); txtData->setText(settings.value(QSL("studio/data"), tr("Your Data Here!")).toString()); + /* Don't save seg data */ txtComposite->setText(settings.value(QSL("studio/composite_text"), tr("Your Data Here!")).toString()); chkComposite->setChecked(settings.value(QSL("studio/chk_composite")).toInt() ? true : false); cmbCompType->setCurrentIndex(settings.value(QSL("studio/comp_type"), 0).toInt()); - cmbECI->setCurrentIndex(settings.value(QSL("studio/appearance/eci"), 0).toInt()); + cmbECI->setCurrentIndex(settings.value(QSL("studio/eci"), 0).toInt()); + /* Don't save seg ECIs */ chkEscape->setChecked(settings.value(QSL("studio/chk_escape")).toInt() ? true : false); chkData->setChecked(settings.value(QSL("studio/chk_data")).toInt() ? true : false); chkRInit->setChecked(settings.value(QSL("studio/chk_rinit")).toInt() ? true : false); @@ -209,11 +211,20 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags fl) connect(btype, SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(cmbFontSetting, SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(txtData, SIGNAL(textChanged( const QString& )), SLOT(update_preview())); + connect(txtDataSeg1, SIGNAL(textChanged( const QString& )), SLOT(data_ui_set())); + connect(txtDataSeg1, SIGNAL(textChanged( const QString& )), SLOT(update_preview())); + connect(txtDataSeg2, SIGNAL(textChanged( const QString& )), SLOT(data_ui_set())); + connect(txtDataSeg2, SIGNAL(textChanged( const QString& )), SLOT(update_preview())); + connect(txtDataSeg3, SIGNAL(textChanged( const QString& )), SLOT(data_ui_set())); + connect(txtDataSeg3, SIGNAL(textChanged( const QString& )), SLOT(update_preview())); connect(txtComposite, SIGNAL(textChanged()), SLOT(update_preview())); connect(chkComposite, SIGNAL(toggled( bool )), SLOT(composite_ui_set())); connect(chkComposite, SIGNAL(toggled( bool )), SLOT(update_preview())); connect(cmbCompType, SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(cmbECI, SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); + connect(cmbECISeg1, SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); + connect(cmbECISeg2, SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); + connect(cmbECISeg3, SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(chkEscape, SIGNAL(toggled( bool )), SLOT(update_preview())); connect(chkData, SIGNAL(toggled( bool )), SLOT(update_preview())); connect(chkRInit, SIGNAL(toggled( bool )), SLOT(update_preview())); @@ -227,6 +238,9 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags fl) connect(btnExit, SIGNAL(clicked( bool )), SLOT(quit_now())); connect(btnReset, SIGNAL(clicked( bool )), SLOT(reset_colours())); connect(btnMoreData, SIGNAL(clicked( bool )), SLOT(open_data_dialog())); + connect(btnMoreDataSeg1, SIGNAL(clicked( bool )), SLOT(open_data_dialog_seg1())); + connect(btnMoreDataSeg2, SIGNAL(clicked( bool )), SLOT(open_data_dialog_seg2())); + connect(btnMoreDataSeg3, SIGNAL(clicked( bool )), SLOT(open_data_dialog_seg3())); connect(btnSequence, SIGNAL(clicked( bool )), SLOT(open_sequence_dialog())); connect(chkAutoHeight, SIGNAL(toggled( bool )), SLOT(autoheight_ui_set())); connect(chkAutoHeight, SIGNAL(toggled( bool )), SLOT(update_preview())); @@ -258,6 +272,9 @@ MainWindow::MainWindow(QWidget *parent, Qt::WindowFlags fl) createActions(); createMenu(); + bstyle->setFocus(); + + tabMain->installEventFilter(this); } MainWindow::~MainWindow() @@ -279,10 +296,12 @@ MainWindow::~MainWindow() settings.setValue(QSL("studio/paper/blue"), m_bgcolor.blue()); settings.setValue(QSL("studio/paper/alpha"), m_bgcolor.alpha()); settings.setValue(QSL("studio/data"), txtData->text()); + /* Seg data not saved so don't restore */ settings.setValue(QSL("studio/composite_text"), txtComposite->toPlainText()); settings.setValue(QSL("studio/chk_composite"), chkComposite->isChecked() ? 1 : 0); settings.setValue(QSL("studio/comp_type"), cmbCompType->currentIndex()); settings.setValue(QSL("studio/eci"), cmbECI->currentIndex()); + /* Seg ECIs not saved so don't restore */ settings.setValue(QSL("studio/chk_escape"), chkEscape->isChecked() ? 1 : 0); settings.setValue(QSL("studio/chk_data"), chkData->isChecked() ? 1 : 0); settings.setValue(QSL("studio/chk_rinit"), chkRInit->isChecked() ? 1 : 0); @@ -350,6 +369,20 @@ bool MainWindow::event(QEvent *event) return QWidget::event(event); } +bool MainWindow::eventFilter(QObject *watched, QEvent *event) +{ + if (event->type() == QEvent::ShortcutOverride) { + QKeyEvent *keyEvent = static_cast(event); + if (keyEvent->modifiers().testFlag(Qt::AltModifier) && keyEvent->key() == 'O') { + event->ignore(); + txtData->setFocus(); + return true; + } + } + + return QWidget::eventFilter(watched, event); +} + void MainWindow::reset_colours() { m_fgcolor.setRgb(0, 0, 0, 0xff); @@ -471,11 +504,11 @@ void MainWindow::about() "

Currently supported standards include:
" "EN 797:1996, EN 798:1996, EN 12323:2005, ISO/IEC 15417:2007,
" "ISO/IEC 15438:2015, ISO/IEC 16022:2006, ISO/IEC 16023:2000,
" - "ISO/IEC 16388:2007, ISO/IEC 18004:2015, ISO/IEC 24723:2010,
" - "ISO/IEC 24724:2011, ISO/IEC 24728:2006, ISO/IEC 24778:2008,
" - "ISO/IEC 16390:2007, ISO/IEC 21471:2019, ANSI-HIBC 2.6-2016,
" - "ANSI/AIM BC6-2000, ANSI/AIM BC12-1998, ANSI/AIM BC5-1995,
" - "AIM ISS-X-24, AIMD014 (v 1.63), USPS-B-3200" + "ISO/IEC 16388:2007, ISO/IEC 18004:2015, ISO/IEC 20830:2021,
" + "ISO/IEC 24723:2010, ISO/IEC 24724:2011, ISO/IEC 24728:2006,
" + "ISO/IEC 24778:2008, ISO/IEC 16390:2007, ISO/IEC 21471:2019,
" + "ANSI-HIBC 2.6-2016, ANSI/AIM BC12-1998, ANSI/AIM BC6-2000,
" + "ANSI/AIM BC5-1995, AIM ISS-X-24, AIMD014 (v 1.63), USPS-B-3200" "

").arg(zint_version).arg(QT_VERSION_STR)); } @@ -484,24 +517,62 @@ void MainWindow::help() QDesktopServices::openUrl(QSL("https://zint.org.uk/manual")); // TODO: manual.md } -void MainWindow::open_data_dialog() +void MainWindow::open_data_dialog_seg(const int seg_no) { - DataWindow dlg(txtData->text(), chkEscape->isChecked()); + if (seg_no < 0 || seg_no > 3) { + return; + } + static QLineEdit *edits[4] = { + txtData, txtDataSeg1, txtDataSeg2, txtDataSeg3 + }; + DataWindow dlg(edits[seg_no]->text(), chkEscape->isChecked()); (void) dlg.exec(); if (dlg.Valid) { - const bool updated = txtData->text() != dlg.DataOutput; - txtData->setText(dlg.DataOutput); + const bool updated = edits[seg_no]->text() != dlg.DataOutput; + edits[seg_no]->setText(dlg.DataOutput); if (updated) { + static const QString updatedEscTxts[4] = { + tr("Set \"Parse Escapes\", updated data"), + tr("Set \"Parse Escapes\", updated segment 1 data"), + tr("Set \"Parse Escapes\", updated segment 2 data"), + tr("Set \"Parse Escapes\", updated segment 3 data"), + }; + static const QString updatedTxts[4] = { + tr("Updated data"), + tr("Updated segment 1 data"), + tr("Updated segment 2 data"), + tr("Updated segment 3 data"), + }; if (dlg.Escaped && !chkEscape->isChecked()) { chkEscape->setChecked(true); - statusBar->showMessage(tr("Set \"Parse Escapes\", updated data"), tempMessageTimeout); + statusBar->showMessage(updatedEscTxts[seg_no], tempMessageTimeout); } else { - statusBar->showMessage(tr("Updated data"), tempMessageTimeout); + statusBar->showMessage(updatedTxts[seg_no], tempMessageTimeout); } } } } +void MainWindow::open_data_dialog() +{ + open_data_dialog_seg(0); +} + +void MainWindow::open_data_dialog_seg1() +{ + open_data_dialog_seg(1); +} + +void MainWindow::open_data_dialog_seg2() +{ + open_data_dialog_seg(2); +} + +void MainWindow::open_data_dialog_seg3() +{ + open_data_dialog_seg(3); +} + void MainWindow::open_sequence_dialog() { SequenceWindow dlg(&m_bc); @@ -1523,9 +1594,27 @@ void MainWindow::change_options() case BARCODE_DBAR_OMNSTK: case BARCODE_DBAR_EXPSTK: grpComposite->show(); + grpSegs->hide(); + break; + case BARCODE_AZTEC: + case BARCODE_DATAMATRIX: + case BARCODE_MAXICODE: + case BARCODE_MICROPDF417: + case BARCODE_PDF417: + case BARCODE_PDF417COMP: + case BARCODE_QRCODE: + case BARCODE_DOTCODE: + case BARCODE_CODEONE: + case BARCODE_GRIDMATRIX: + case BARCODE_HANXIN: + case BARCODE_ULTRA: + case BARCODE_RMQR: + grpComposite->hide(); + grpSegs->show(); break; default: grpComposite->hide(); + grpSegs->hide(); break; } @@ -1536,6 +1625,7 @@ void MainWindow::change_options() chkQuietZones->setEnabled(!m_bc.bc.hasDefaultQuietZones(symbology)); chkDotty->setEnabled(m_bc.bc.isDotty(symbology)); + data_ui_set(); composite_ui_set(); autoheight_ui_set(); HRTShow_ui_set(); @@ -1552,6 +1642,46 @@ void MainWindow::change_options() } } +void MainWindow::data_ui_set() +{ + if (grpSegs->isHidden()) { + return; + } + if (txtDataSeg1->text().isEmpty()) { + cmbECISeg1->setEnabled(false); + lblSeg2->setEnabled(false); + cmbECISeg2->setEnabled(false); + txtDataSeg2->setEnabled(false); + btnMoreDataSeg2->setEnabled(false); + lblSeg3->setEnabled(false); + cmbECISeg3->setEnabled(false); + txtDataSeg3->setEnabled(false); + btnMoreDataSeg3->setEnabled(false); + } else { + cmbECISeg1->setEnabled(true); + lblSeg2->setEnabled(true); + txtDataSeg2->setEnabled(true); + btnMoreDataSeg2->setEnabled(true); + if (txtDataSeg2->text().isEmpty()) { + cmbECISeg2->setEnabled(false); + lblSeg3->setEnabled(false); + cmbECISeg3->setEnabled(false); + txtDataSeg3->setEnabled(false); + btnMoreDataSeg3->setEnabled(false); + } else { + cmbECISeg2->setEnabled(true); + lblSeg3->setEnabled(true); + txtDataSeg3->setEnabled(true); + btnMoreDataSeg3->setEnabled(true); + if (txtDataSeg3->text().isEmpty()) { + cmbECISeg3->setEnabled(false); + } else { + cmbECISeg3->setEnabled(true); + } + } + } +} + void MainWindow::composite_ui_set() { bool enabled = !grpComposite->isHidden() && chkComposite->isChecked(); @@ -1715,7 +1845,20 @@ void MainWindow::update_preview() m_bc.bc.setPrimaryMessage(txtData->text()); m_bc.bc.setText(txtComposite->toPlainText()); } else { - m_bc.bc.setText(txtData->text()); + if (!grpSegs->isHidden() && !txtDataSeg1->text().isEmpty()) { + std::vector segs; + segs.push_back(Zint::QZintSeg(txtData->text(), cmbECI->currentIndex())); + segs.push_back(Zint::QZintSeg(txtDataSeg1->text(), cmbECISeg1->currentIndex())); + if (!txtDataSeg2->text().isEmpty()) { + segs.push_back(Zint::QZintSeg(txtDataSeg2->text(), cmbECISeg2->currentIndex())); + if (!txtDataSeg3->text().isEmpty()) { + segs.push_back(Zint::QZintSeg(txtDataSeg3->text(), cmbECISeg3->currentIndex())); + } + } + m_bc.bc.setSegs(segs); + } else { + m_bc.bc.setText(txtData->text()); + } } m_bc.bc.setOption1(-1); m_bc.bc.setOption2(0); @@ -2689,6 +2832,11 @@ void MainWindow::save_sub_settings(QSettings &settings, int symbology) QString name = get_setting_name(symbology); if (!name.isEmpty()) { settings.setValue(QSL("studio/bc/%1/data").arg(name), txtData->text()); + if (!grpSegs->isHidden()) { + settings.setValue(QSL("studio/bc/%1/data_seg1").arg(name), txtDataSeg1->text()); + settings.setValue(QSL("studio/bc/%1/data_seg2").arg(name), txtDataSeg2->text()); + settings.setValue(QSL("studio/bc/%1/data_seg3").arg(name), txtDataSeg3->text()); + } if (!grpComposite->isHidden()) { settings.setValue(QSL("studio/bc/%1/composite_text").arg(name), txtComposite->toPlainText()); settings.setValue(QSL("studio/bc/%1/chk_composite").arg(name), chkComposite->isChecked() ? 1 : 0); @@ -2696,6 +2844,9 @@ void MainWindow::save_sub_settings(QSettings &settings, int symbology) } if (cmbECI->isEnabled()) { settings.setValue(QSL("studio/bc/%1/eci").arg(name), cmbECI->currentIndex()); + settings.setValue(QSL("studio/bc/%1/eci_seg1").arg(name), cmbECISeg1->currentIndex()); + settings.setValue(QSL("studio/bc/%1/eci_seg2").arg(name), cmbECISeg2->currentIndex()); + settings.setValue(QSL("studio/bc/%1/eci_seg3").arg(name), cmbECISeg3->currentIndex()); } settings.setValue(QSL("studio/bc/%1/chk_escape").arg(name), chkEscape->isChecked() ? 1 : 0); settings.setValue(QSL("studio/bc/%1/chk_data").arg(name), chkData->isChecked() ? 1 : 0); @@ -3050,6 +3201,11 @@ void MainWindow::load_sub_settings(QSettings &settings, int symbology) if (!tdata.isEmpty()) { txtData->setText(tdata); } + if (!grpSegs->isHidden()) { + txtDataSeg1->setText(settings.value(QSL("studio/bc/%1/data_seg1").arg(name), QSL("")).toString()); + txtDataSeg2->setText(settings.value(QSL("studio/bc/%1/data_seg2").arg(name), QSL("")).toString()); + txtDataSeg3->setText(settings.value(QSL("studio/bc/%1/data_seg3").arg(name), QSL("")).toString()); + } if (!grpComposite->isHidden()) { const QString &composite_text = settings.value( QSL("studio/bc/%1/composite_text").arg(name), QSL("")).toString(); @@ -3062,6 +3218,9 @@ void MainWindow::load_sub_settings(QSettings &settings, int symbology) } if (cmbECI->isEnabled()) { cmbECI->setCurrentIndex(settings.value(QSL("studio/bc/%1/eci").arg(name), 0).toInt()); + cmbECISeg1->setCurrentIndex(settings.value(QSL("studio/bc/%1/eci_seg1").arg(name), 0).toInt()); + cmbECISeg2->setCurrentIndex(settings.value(QSL("studio/bc/%1/eci_seg2").arg(name), 0).toInt()); + cmbECISeg3->setCurrentIndex(settings.value(QSL("studio/bc/%1/eci_seg3").arg(name), 0).toInt()); } chkEscape->setChecked(settings.value(QSL("studio/bc/%1/chk_escape").arg(name)).toInt() ? true : false); chkData->setChecked(settings.value(QSL("studio/bc/%1/chk_data").arg(name)).toInt() ? true : false); diff --git a/frontend_qt/mainwindow.h b/frontend_qt/mainwindow.h index 9742bc8b..b8e104cb 100644 --- a/frontend_qt/mainwindow.h +++ b/frontend_qt/mainwindow.h @@ -47,6 +47,7 @@ public slots: void change_options(); void on_fgcolor_clicked(); void on_bgcolor_clicked(); + void data_ui_set(); void composite_ui_set(); void composite_ean_check(); void maxi_scm_ui_set(); @@ -70,6 +71,9 @@ public slots: void reset_colours(); void open_data_dialog(); + void open_data_dialog_seg1(); + void open_data_dialog_seg2(); + void open_data_dialog_seg3(); void open_sequence_dialog(); void open_cli_dialog(); @@ -98,6 +102,7 @@ public slots: protected: void resizeEvent(QResizeEvent *event); bool event(QEvent *event) override; + bool eventFilter(QObject *watched, QEvent *event); void combobox_item_enabled(QComboBox *comboBox, int index, bool enabled); void upcean_addon_gap(const QString &comboBoxName, const QString &labelName, int base); @@ -106,6 +111,8 @@ protected: void set_gs1_mode(bool gs1_mode); void set_smaller_font(const QString &labelName); + void open_data_dialog_seg(const int seg_no); + void createActions(); void createMenu(); void enableActions(bool enabled);