From 7be63a00b6dbe02c136180ec8cc481d033d51538 Mon Sep 17 00:00:00 2001 From: gitlost Date: Thu, 21 May 2020 18:22:28 +0100 Subject: [PATCH] CODE16K fixes; separator default 1; raster/vector.c quiet_zones, output.c; #191 --- backend/CMakeLists.txt | 2 +- backend/codablock.c | 5 +- backend/code128.c | 69 ++-- backend/code128.h | 57 ++++ backend/code16k.c | 348 ++++---------------- backend/code49.c | 33 +- backend/imail.c | 18 +- backend/library.c | 10 +- backend/mailmark.c | 8 +- backend/output.c | 114 +++++++ backend/output.h | 47 +++ backend/raster.c | 182 +++++----- backend/tests/CMakeLists.txt | 2 + backend/tests/data/png/codablockf_3rows.png | Bin 347 -> 347 bytes backend/tests/data/svg/codablockf_3rows.svg | 106 +++--- backend/tests/test_codablock.c | 8 +- backend/tests/test_code128.c | 87 ++++- backend/tests/test_code16k.c | 301 +++++++++++++++++ backend/tests/test_code49.c | 234 +++++++++++++ backend/tests/test_library.c | 21 +- backend/tests/test_raster.c | 331 ++++++++++++++++++- backend/tests/test_vector.c | 91 ++++- backend/tests/testcommon.c | 74 +++++ backend/tests/testcommon.h | 2 + backend/vector.c | 57 +--- backend_qt/backend_qt.pro | 3 + backend_tcl/configure.in | 1 + backend_tcl/zint_tcl.dsp | 4 + docs/manual.txt | 44 +-- frontend/main.c | 37 ++- frontend_qt/grpC16k.ui | 64 +++- frontend_qt/grpC49.ui | 68 +++- frontend_qt/grpCodablockF.ui | 17 +- frontend_qt/mainwindow.cpp | 14 +- win32/libzint.vcxproj | 3 + win32/zint_cmdline_vc6/zint_cmdline_vc6.dsp | 4 + 36 files changed, 1791 insertions(+), 675 deletions(-) create mode 100644 backend/code128.h create mode 100644 backend/output.c create mode 100644 backend/output.h create mode 100644 backend/tests/test_code16k.c create mode 100644 backend/tests/test_code49.c diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt index 0649dcc2..a0fdfd5a 100644 --- a/backend/CMakeLists.txt +++ b/backend/CMakeLists.txt @@ -8,7 +8,7 @@ set(zint_COMMON_SRCS common.c library.c large.c reedsol.c gs1.c eci.c general_fi set(zint_ONEDIM_SRCS code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c) set(zint_POSTAL_SRCS postal.c auspost.c imail.c mailmark.c) set(zint_TWODIM_SRCS code16k.c codablock.c dmatrix.c pdf417.c qr.c maxicode.c composite.c aztec.c code49.c code1.c gridmtx.c hanxin.c dotcode.c ultra.c) -set(zint_OUTPUT_SRCS vector.c ps.c svg.c emf.c bmp.c pcx.c gif.c png.c tif.c raster.c) +set(zint_OUTPUT_SRCS vector.c ps.c svg.c emf.c bmp.c pcx.c gif.c png.c tif.c raster.c output.c) set(zint_SRCS ${zint_OUTPUT_SRCS} ${zint_COMMON_SRCS} ${zint_ONEDIM_SRCS} ${zint_POSTAL_SRCS} ${zint_TWODIM_SRCS}) if(PNG_FOUND) diff --git a/backend/codablock.c b/backend/codablock.c index 09646b99..2eef2a70 100644 --- a/backend/codablock.c +++ b/backend/codablock.c @@ -656,7 +656,7 @@ INTERNAL int codablock(struct zint_symbol *symbol,const unsigned char source[], if (Error < 5) { symbol->output_options |= BARCODE_BIND; if (symbol->border_width == 0) { /* Allow override if non-zero */ - symbol->border_width = 2; + symbol->border_width = 1; /* AIM ISS-X-24 Section 4.6.1 b) (note change from previous default 2) */ } } return Error; @@ -981,7 +981,8 @@ INTERNAL int codablock(struct zint_symbol *symbol,const unsigned char source[], symbol->output_options |= BARCODE_BIND; if (symbol->border_width == 0) { /* Allow override if non-zero */ - symbol->border_width = 2; + symbol->border_width = 1; /* AIM ISS-X-24 Section 4.6.1 b) (note change from previous default 2) */ } + return 0; } diff --git a/backend/code128.c b/backend/code128.c index a9ee19c1..b69613ab 100644 --- a/backend/code128.c +++ b/backend/code128.c @@ -37,20 +37,11 @@ #ifdef _MSC_VER #include #endif +#include #include "common.h" +#include "code128.h" #include "gs1.h" -#define SHIFTA 90 -#define LATCHA 91 -#define SHIFTB 92 -#define LATCHB 93 -#define SHIFTC 94 -#define LATCHC 95 -#define AORB 96 -#define ABORC 97 - -static int list[2][170]; - /* Code 128 tables checked against ISO/IEC 15417:2007 */ static const char *C128Table[107] = { @@ -96,7 +87,7 @@ INTERNAL int parunmodd(const unsigned char llyth) { /** * bring together same type blocks */ -static void grwp(int *indexliste) { +static void grwp(int list[2][C128_MAX], int *indexliste) { /* bring together same type blocks */ if (*(indexliste) > 1) { @@ -125,7 +116,7 @@ static void grwp(int *indexliste) { /** * Implements rules from ISO 15417 Annex E */ -static void dxsmooth(int *indexliste) { +INTERNAL void dxsmooth(int list[2][C128_MAX], int *indexliste) { int i, last, next; for (i = 0; i < *(indexliste); i++) { @@ -213,7 +204,7 @@ static void dxsmooth(int *indexliste) { } /* Rule 2 is implemented elsewhere, Rule 6 is implied */ } - grwp(indexliste); + grwp(list, indexliste); } /** @@ -272,13 +263,17 @@ static void c128_set_c(unsigned char source_a, unsigned char source_b, char dest /* Handle Code 128, 128B and HIBC 128 */ INTERNAL int code_128(struct zint_symbol *symbol, const unsigned char source[], const size_t length) { - int i, j, k, values[170] = {0}, bar_characters, read, total_sum; + int i, j, k, values[C128_MAX] = {0}, bar_characters, read, total_sum; int error_number, indexchaine, indexliste, f_state; int sourcelen; - char set[170] = {0}, fset[170], mode, last_set, current_set = ' '; + int list[2][C128_MAX] = {{0}}; + char set[C128_MAX] = {0}, fset[C128_MAX], mode, last_set, current_set = ' '; float glyph_count; char dest[1000]; + /* Suppresses clang-analyzer-core.UndefinedBinaryOperatorResult warning on fset which is fully set */ + assert(length > 0); + error_number = 0; strcpy(dest, ""); @@ -287,7 +282,7 @@ INTERNAL int code_128(struct zint_symbol *symbol, const unsigned char source[], bar_characters = 0; f_state = 0; - if (sourcelen > 160) { + if (sourcelen > C128_MAX) { /* This only blocks ridiculously long input - the actual length of the resulting barcode depends on the type of data, so this is trapped later */ strcpy(symbol->errtxt, "340: Input too long"); @@ -298,7 +293,6 @@ INTERNAL int code_128(struct zint_symbol *symbol, const unsigned char source[], for (i = 0; i < sourcelen; i++) { fset[i] = source[i] >= 128 ? 'f' : ' '; } - fset[i] = '\0'; /* Decide when to latch to extended mode - Annex E note 3 */ j = 0; @@ -351,15 +345,14 @@ INTERNAL int code_128(struct zint_symbol *symbol, const unsigned char source[], mode = AORB; } - for (i = 0; i < 170; i++) { - list[0][i] = 0; - } - do { list[1][indexliste] = mode; while ((list[1][indexliste] == mode) && (indexchaine < sourcelen)) { list[0][indexliste]++; indexchaine++; + if (indexchaine == sourcelen) { + break; + } mode = parunmodd(source[indexchaine]); if ((symbol->symbology == BARCODE_CODE128B) && (mode == ABORC)) { mode = AORB; @@ -368,7 +361,7 @@ INTERNAL int code_128(struct zint_symbol *symbol, const unsigned char source[], indexliste++; } while (indexchaine < sourcelen); - dxsmooth(&indexliste); + dxsmooth(list, &indexliste); /* Resolve odd length LATCHC blocks */ if ((list[1][0] == LATCHC) && (list[0][0] & 1)) { @@ -413,8 +406,9 @@ INTERNAL int code_128(struct zint_symbol *symbol, const unsigned char source[], } if (symbol->debug & ZINT_DEBUG_PRINT) { - printf(" Set: %s (%d)\n", set, (int) strlen(set)); - printf("FSet: %s (%d)\n", fset, (int) strlen(fset)); + printf("Data: %.*s (%d)\n", sourcelen, source, sourcelen); + printf(" Set: %.*s\n", sourcelen, set); + printf("FSet: %.*s\n", sourcelen, fset); } /* Now we can calculate how long the barcode is going to be - and stop it from @@ -668,9 +662,10 @@ INTERNAL int code_128(struct zint_symbol *symbol, const unsigned char source[], /* Handle EAN-128 (Now known as GS1-128) */ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const size_t length) { - int i, j, values[170], bar_characters, read, total_sum; + int i, j, values[C128_MAX] = {0}, bar_characters, read, total_sum; int error_number, indexchaine, indexliste; - char set[170], mode, last_set; + int list[2][C128_MAX] = {{0}}; + char set[C128_MAX] = {0}, mode, last_set; float glyph_count; char dest[1000]; int separator_row, linkage_flag, c_count; @@ -680,16 +675,14 @@ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const s #else char* reduced = (char*) _alloca(length + 1); #endif + strcpy(dest, ""); linkage_flag = 0; bar_characters = 0; separator_row = 0; - memset(values, 0, sizeof (values)); - memset(set, ' ', sizeof (set)); - - if (length > 160) { + if (length > C128_MAX) { /* This only blocks ridiculously long input - the actual length of the resulting barcode depends on the type of data, so this is trapped later */ strcpy(symbol->errtxt, "342: Input too long"); @@ -718,15 +711,14 @@ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const s mode = ABORC; } - for (i = 0; i < 170; i++) { - list[0][i] = 0; - } - do { list[1][indexliste] = mode; while ((list[1][indexliste] == mode) && (indexchaine < reduced_length)) { list[0][indexliste]++; indexchaine++; + if (indexchaine == reduced_length) { + break; + } mode = parunmodd(reduced[indexchaine]); if (reduced[indexchaine] == '[') { mode = ABORC; @@ -735,7 +727,7 @@ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const s indexliste++; } while (indexchaine < reduced_length); - dxsmooth(&indexliste); + dxsmooth(list, &indexliste); /* Put set data into set[] */ read = 0; @@ -961,6 +953,11 @@ INTERNAL int ean_128(struct zint_symbol *symbol, unsigned char source[], const s } printf("\n"); } +#ifdef ZINT_TEST + if (symbol->debug & ZINT_DEBUG_TEST) { + debug_test_codeword_dump_int(symbol, values, bar_characters); + } +#endif expand(symbol, dest); diff --git a/backend/code128.h b/backend/code128.h new file mode 100644 index 00000000..0b1f0425 --- /dev/null +++ b/backend/code128.h @@ -0,0 +1,57 @@ +/* + libzint - the open source barcode library + Copyright (C) 2020 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + */ +/* vim: set ts=4 sw=4 et : */ + +#ifndef CODE128_H +#define CODE128_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#define C128_MAX 160 + +#define SHIFTA 90 +#define LATCHA 91 +#define SHIFTB 92 +#define LATCHB 93 +#define SHIFTC 94 +#define LATCHC 95 +#define AORB 96 +#define ABORC 97 + +INTERNAL int parunmodd(const unsigned char llyth); +INTERNAL void dxsmooth(int list[2][C128_MAX], int *indexliste); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CODE128_H */ diff --git a/backend/code16k.c b/backend/code16k.c index 7a018c97..c7394c5d 100644 --- a/backend/code16k.c +++ b/backend/code16k.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2008-2017 Robin Stuart + Copyright (C) 2008 - 2020 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -37,25 +37,9 @@ #include #include -#include +#include #include "common.h" - -#define TRUE 1 -#define FALSE 0 -#define SHIFTA 90 -#define LATCHA 91 -#define SHIFTB 92 -#define LATCHB 93 -#define SHIFTC 94 -#define LATCHC 95 -#define AORB 96 -#define ABORC 97 -#define CANDB 98 -#define CANDBB 99 - -INTERNAL int parunmodd(const unsigned char llyth); - -static int list[2][170]; +#include "code128.h" static const char *C16KTable[107] = { /* EN 12323 Table 1 - "Code 16K" character encodations */ @@ -89,141 +73,7 @@ static const int C16KStopValues[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 0, 1, 2, 3 }; -static void grwp16(unsigned int *indexliste) { - - /* bring together same type blocks */ - if (*(indexliste) > 1) { - int i = 1; - while(i < (int)*(indexliste)) { - if (list[1][i - 1] == list[1][i]) { - int j; - /* bring together */ - list[0][i - 1] = list[0][i - 1] + list[0][i]; - j = i + 1; - - /* decreace the list */ - while(j < (int)*(indexliste)) { - list[0][j - 1] = list[0][j]; - list[1][j - 1] = list[1][j]; - j++; - } - *(indexliste) = *(indexliste) - 1; - i--; - } - i++; - } - } -} - -/* Implements rules from ISO 15417 Annex E */ -static void dxsmooth16(unsigned int *indexliste) { - int i, last, next; - - for(i = 0; i < (int)*(indexliste); i++) { - int current = list[1][i]; - int length = list[0][i]; - if (i != 0) { - last = list[1][i - 1]; - } else { - last = FALSE; - } - if (i != *(indexliste) - 1) { - next = list[1][i + 1]; - } else { - next = FALSE; - } - - if (i == 0) { - /* first block */ - if ((*(indexliste) == 1) && ((length == 2) && (current == ABORC))) { - /* Rule 1a */ - list[1][i] = LATCHC; - } - if (current == ABORC) { - if (length >= 4) { - /* Rule 1b */ - list[1][i] = LATCHC; - } else { - list[1][i] = AORB; - current = AORB; - } - } - if (current == SHIFTA) { - /* Rule 1c */ - list[1][i] = LATCHA; - } - if ((current == AORB) && (next == SHIFTA)) { - /* Rule 1c */ - list[1][i] = LATCHA; - current = LATCHA; - } - if (current == AORB) { - /* Rule 1d */ - list[1][i] = LATCHB; - } - } else { - if ((current == ABORC) && (length >= 4)) { - /* Rule 3 */ - list[1][i] = LATCHC; - current = LATCHC; - } - if (current == ABORC) { - list[1][i] = AORB; - current = AORB; - } - if ((current == AORB) && (last == LATCHA)) { - list[1][i] = LATCHA; - current = LATCHA; - } - if ((current == AORB) && (last == LATCHB)) { - list[1][i] = LATCHB; - current = LATCHB; - } - if ((current == AORB) && (next == SHIFTA)) { - list[1][i] = LATCHA; - current = LATCHA; - } - if ((current == AORB) && (next == SHIFTB)) { - list[1][i] = LATCHB; - current = LATCHB; - } - if (current == AORB) { - list[1][i] = LATCHB; - current = LATCHB; - } - if ((current == SHIFTA) && (length > 1)) { - /* Rule 4 */ - list[1][i] = LATCHA; - current = LATCHA; - } - if ((current == SHIFTB) && (length > 1)) { - /* Rule 5 */ - list[1][i] = LATCHB; - current = LATCHB; - } - if ((current == SHIFTA) && (last == LATCHA)) { - list[1][i] = LATCHA; - current = LATCHA; - } - if ((current == SHIFTB) && (last == LATCHB)) { - list[1][i] = LATCHB; - current = LATCHB; - } - if ((current == SHIFTA) && (last == LATCHC)) { - list[1][i] = LATCHA; - current = LATCHA; - } - if ((current == SHIFTB) && (last == LATCHC)) { - list[1][i] = LATCHB; - current = LATCHB; - } - } /* Rule 2 is implimented elsewhere, Rule 6 is implied */ - } - grwp16(indexliste); - -} - -static void c16k_set_a(const unsigned char source, unsigned int values[], unsigned int *bar_chars) { +static void c16k_set_a(const unsigned char source, int values[], int *bar_chars) { if (source > 127) { if (source < 160) { values[(*bar_chars)] = source + 64 - 128; @@ -240,7 +90,7 @@ static void c16k_set_a(const unsigned char source, unsigned int values[], unsign (*bar_chars)++; } -static void c16k_set_b(const unsigned char source, unsigned int values[], unsigned int *bar_chars) { +static void c16k_set_b(const unsigned char source, int values[], int *bar_chars) { if (source > 127) { values[(*bar_chars)] = source - 32 - 128; } else { @@ -249,7 +99,7 @@ static void c16k_set_b(const unsigned char source, unsigned int values[], unsign (*bar_chars)++; } -static void c16k_set_c(const unsigned char source_a, unsigned char source_b, unsigned int values[], unsigned int *bar_chars) { +static void c16k_set_c(const unsigned char source_a, unsigned char source_b, int values[], int *bar_chars) { int weight; weight = (10 * ctoi(source_a)) + ctoi(source_b); @@ -260,16 +110,20 @@ static void c16k_set_c(const unsigned char source_a, unsigned char source_b, uns INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const size_t length) { char width_pattern[100]; int current_row, rows_needed, looper, first_check, second_check; - int indexchaine, f_state; - char set[160] = {' '}, fset[160] = {' '}, mode, last_set, current_set; - unsigned int pads_needed, indexliste, i, j, k, m, read, mx_reader; - unsigned int values[160] = {0}; - unsigned int bar_characters; + int indexchaine; + int list[2][C128_MAX] = {{0}}; + char set[C128_MAX] = {0}, fset[C128_MAX], mode, last_set, current_set; + int pads_needed, indexliste, i, j, m, read, mx_reader; + int values[C128_MAX] = {0}; + int bar_characters; float glyph_count; int errornum, first_sum, second_sum; - size_t input_length; + int input_length; int gs1, c_count; + /* Suppresses clang-analyzer-core.UndefinedBinaryOperatorResult warning on fset which is fully set */ + assert(length > 0); + errornum = 0; strcpy(width_pattern, ""); input_length = length; @@ -280,7 +134,7 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s gs1 = 0; } - if (input_length > 157) { + if (input_length > C128_MAX) { strcpy(symbol->errtxt, "420: Input too long"); return ZINT_ERROR_TOO_LONG; } @@ -288,43 +142,11 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s bar_characters = 0; /* Detect extended ASCII characters */ - for (i = 0; i < (unsigned int) input_length; i++) { - if (source[i] >= 128) { - fset[i] = 'f'; - } + for (i = 0; i < input_length; i++) { + fset[i] = source[i] >= 128 ? 'f' : ' '; } - fset[i] = '\0'; + /* Note to be safe not using extended ASCII latch as not mentioned in BS EN 12323:2005 */ - /* Decide when to latch to extended mode */ - for (i = 0; i < (unsigned int) input_length; i++) { - j = 0; - if (fset[i] == 'f') { - do { - j++; - } while (fset[i + j] == 'f'); - if ((j >= 5) || ((j >= 3) && ((i + j) == (input_length - 1)))) { - for (k = 0; k <= j; k++) { - fset[i + k] = 'F'; - } - } - } - } - - /* Decide if it is worth reverting to 646 encodation for a few characters */ - if (input_length > 1) { - for (i = 1; i < (unsigned int) input_length; i++) { - if ((fset[i - 1] == 'F') && (fset[i] == ' ')) { - /* Detected a change from 8859-1 to 646 - count how long for */ - for (j = 0; (fset[i + j] == ' ') && ((i + j) < (unsigned int) input_length); j++); - if ((j < 5) || ((j < 3) && ((i + j) == (input_length - 1)))) { - /* Change to shifting back rather than latching back */ - for (k = 0; k < j; k++) { - fset[i + k] = 'n'; - } - } - } - } - } /* Detect mode A, B and C characters */ indexliste = 0; indexchaine = 0; @@ -334,15 +156,14 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s mode = ABORC; } /* FNC1 */ - for (i = 0; i < 160; i++) { - list[0][i] = 0; - } - do { list[1][indexliste] = mode; while ((list[1][indexliste] == mode) && (indexchaine < input_length)) { list[0][indexliste]++; indexchaine++; + if (indexchaine == input_length) { + break; + } mode = parunmodd(source[indexchaine]); if ((gs1) && (source[indexchaine] == '[')) { mode = ABORC; @@ -351,7 +172,7 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s indexliste++; } while (indexchaine < input_length); - dxsmooth16(&indexliste); + dxsmooth(list, &indexliste); /* Put set data into set[] */ read = 0; @@ -373,23 +194,6 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s } } - /* Adjust for strings which start with shift characters - make them latch instead */ - if (set[0] == 'a') { - i = 0; - do { - set[i] = 'A'; - i++; - } while (set[i] == 'a'); - } - - if (set[0] == 'b') { - i = 0; - do { - set[i] = 'B'; - i++; - } while (set[i] == 'b'); - } - /* Watch out for odd-length Mode C blocks */ c_count = 0; for (i = 0; i < read; i++) { @@ -430,14 +234,20 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s } } + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf("Data: %.*s\n", input_length, source); + printf(" Set: %.*s\n", input_length, set); + printf("FSet: %.*s\n", input_length, fset); + } + /* Make sure the data will fit in the symbol */ - last_set = ' '; + last_set = set[0]; glyph_count = 0.0; for (i = 0; i < input_length; i++) { if ((set[i] == 'a') || (set[i] == 'b')) { glyph_count = glyph_count + 1.0; } - if ((fset[i] == 'f') || (fset[i] == 'n')) { + if (fset[i] == 'f') { glyph_count = glyph_count + 1.0; } if (((set[i] == 'A') || (set[i] == 'B')) || (set[i] == 'C')) { @@ -455,16 +265,6 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s glyph_count = glyph_count - 1.0; } } - if (fset[i] == 'F') { - glyph_count = glyph_count + 2.0; - } - } else { - if ((fset[i] == 'F') && (fset[i - 1] != 'F')) { - glyph_count = glyph_count + 2.0; - } - if ((fset[i] != 'F') && (fset[i - 1] == 'F')) { - glyph_count = glyph_count + 2.0; - } } if ((set[i] == 'C') && (!((gs1) && (source[i] == '[')))) { @@ -544,24 +344,6 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s } current_set = set[0]; - f_state = 0; - /* f_state remembers if we are in Extended ASCII mode (value 1) or - in ISO/IEC 646 mode (value 0) */ - if (fset[0] == 'F') { - switch (current_set) { - case 'A': - values[bar_characters] = 101; - values[bar_characters + 1] = 101; - break; - case 'B': - values[bar_characters] = 100; - values[bar_characters + 1] = 100; - break; - } - bar_characters += 2; - f_state = 1; - } - read = 0; /* Encode the data */ @@ -594,40 +376,7 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s } } - if (read != 0) { - if ((fset[read] == 'F') && (f_state == 0)) { - /* Latch beginning of extended mode */ - switch (current_set) { - case 'A': - values[bar_characters] = 101; - values[bar_characters + 1] = 101; - break; - case 'B': - values[bar_characters] = 100; - values[bar_characters + 1] = 100; - break; - } - bar_characters += 2; - f_state = 1; - } - if ((fset[read] == ' ') && (f_state == 1)) { - /* Latch end of extended mode */ - switch (current_set) { - case 'A': - values[bar_characters] = 101; - values[bar_characters + 1] = 101; - break; - case 'B': - values[bar_characters] = 100; - values[bar_characters + 1] = 100; - break; - } - bar_characters += 2; - f_state = 0; - } - } - - if ((fset[i] == 'f') || (fset[i] == 'n')) { + if (fset[read] == 'f') { /* Shift extended mode */ switch (current_set) { case 'A': @@ -640,7 +389,7 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s bar_characters++; } - if ((set[i] == 'a') || (set[i] == 'b')) { + if ((set[read] == 'a') || (set[read] == 'b')) { /* Insert shift character */ values[bar_characters] = 98; bar_characters++; @@ -667,7 +416,7 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s bar_characters++; read++; } - } while (read < ustrlen(source)); + } while (read < input_length); pads_needed = 5 - ((bar_characters + 2) % 5); if (pads_needed == 5) { @@ -677,7 +426,7 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s pads_needed += 8 - (bar_characters + pads_needed); } for (i = 0; i < pads_needed; i++) { - values[bar_characters] = 106; + values[bar_characters] = 103; bar_characters++; } @@ -695,9 +444,23 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s values[bar_characters + 1] = second_check; bar_characters += 2; + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf("Codewords:"); + for (i = 0; i < bar_characters; i++) { + printf(" %d", values[i]); + } + printf("\n"); + } +#ifdef ZINT_TEST + if (symbol->debug & ZINT_DEBUG_TEST) { + debug_test_codeword_dump_int(symbol, values, bar_characters); /* Missing row start/stop */ + } +#endif + for (current_row = 0; current_row < rows_needed; current_row++) { - unsigned int writer; + int writer; int flip_flop; + int len; strcpy(width_pattern, ""); strcat(width_pattern, C16KStartStop[C16KStartValues[current_row]]); @@ -710,7 +473,7 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s /* Write the information into the symbol */ writer = 0; flip_flop = 1; - for (mx_reader = 0; mx_reader < strlen(width_pattern); mx_reader++) { + for (mx_reader = 0, len = strlen(width_pattern); mx_reader < len; mx_reader++) { for (looper = 0; looper < ctoi(width_pattern[mx_reader]); looper++) { if (flip_flop == 1) { set_module(symbol, current_row, writer); @@ -730,5 +493,12 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], const s symbol->rows = rows_needed; symbol->width = 70; + + symbol->output_options |= BARCODE_BIND; + + if (symbol->border_width == 0) { /* Allow override if non-zero */ + symbol->border_width = 1; /* BS EN 12323:2005 Section 4.3.7 minimum (note change from previous default 2) */ + } + return errornum; } diff --git a/backend/code49.c b/backend/code49.c index 3d015298..3d7aebff 100644 --- a/backend/code49.c +++ b/backend/code49.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2009-2017 Robin Stuart + Copyright (C) 2009 - 2020 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -33,11 +33,10 @@ #include #include -#include #include "common.h" #include "code49.h" -#define INSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%!&*" +#define INSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%!&*" /* "!" represents Shift 1 and "&" represents Shift 2, "*" represents FNC1 */ @@ -50,7 +49,7 @@ INTERNAL int code_49(struct zint_symbol *symbol, unsigned char source[], const i int pad_count = 0; char pattern[80]; int gs1; - size_t h; + int h, len; if (length > 81) { strcpy(symbol->errtxt, "430: Input too long"); @@ -299,6 +298,21 @@ INTERNAL int code_49(struct zint_symbol *symbol, unsigned char source[], const i } c_grid[rows - 1][7] = j % 49; + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf("Codewords:\n"); + for (i = 0; i < rows; i++) { + for (j = 0; j < 8; j++) { + printf(" %2d", c_grid[i][j]); + } + printf("\n"); + } + } +#ifdef ZINT_TEST + if (symbol->debug & ZINT_DEBUG_TEST) { + debug_test_codeword_dump_int(symbol, (int *)c_grid, rows * 8); + } +#endif + /* Transfer data to symbol character array (w grid) */ for (i = 0; i < rows; i++) { for (j = 0; j < 4; j++) { @@ -327,7 +341,7 @@ INTERNAL int code_49(struct zint_symbol *symbol, unsigned char source[], const i /* Expand into symbol */ symbol->row_height[i] = 10; - for (j = 0; j < strlen(pattern); j++) { + for (j = 0, len = strlen(pattern); j < len; j++) { if (pattern[j] == '1') { set_module(symbol, i, j); } @@ -336,11 +350,12 @@ INTERNAL int code_49(struct zint_symbol *symbol, unsigned char source[], const i symbol->rows = rows; symbol->width = strlen(pattern); - symbol->whitespace_width = 10; - if (!(symbol->output_options & BARCODE_BIND)) { - symbol->output_options += BARCODE_BIND; + + symbol->output_options |= BARCODE_BIND; + + if (symbol->border_width == 0) { /* Allow override if non-zero */ + symbol->border_width = 1; /* ANSI/AIM BC6-2000 Section 2.1 (note change from previous default 2) */ } - symbol->border_width = 2; return 0; } diff --git a/backend/imail.c b/backend/imail.c index 18b2a06a..a5fb0780 100644 --- a/backend/imail.c +++ b/backend/imail.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2008-2017 Robin Stuart + Copyright (C) 2008 - 2020 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -35,12 +35,11 @@ is Copyright (C) 2006 United States Postal Service */ #include -#include #include #include "common.h" #include "large.h" -#define SODIUM "0123456789-" +#define SODIUM "0123456789-" /* The following lookup tables were generated using the code in Appendix C */ @@ -203,7 +202,7 @@ static const unsigned short int AppxD_IV[130] = { ** USPS_MSB_Math_CRC11GenerateFrameCheckSequence ** ** Inputs: - ** ByteAttayPtr is the address of a 13 byte array holding 102 bytes which + ** ByteAttayPtr is the address of a 13 byte array holding 102 bits which ** are right justified - ie: the leftmost 2 bits of the first byte do not ** hold data and must be set to zero. ** @@ -255,9 +254,7 @@ INTERNAL int imail(struct zint_symbol *symbol, unsigned char source[], int lengt int codeword[10]; unsigned short characters[10]; short int bar_map[130]; - int zip_len; - - error_number = 0; + int zip_len, len; if (length > 32) { strcpy(symbol->errtxt, "450: Input too long"); @@ -358,7 +355,7 @@ INTERNAL int imail(struct zint_symbol *symbol, unsigned char source[], int lengt accum[i] = 0; } - for (read = 0; read < strlen(zip_adder); read++) { + for (read = 0, len = strlen(zip_adder); read < len; read++) { binary_multiply(accum, "10"); binary_load(y_reg, "0", 1); @@ -398,7 +395,7 @@ INTERNAL int imail(struct zint_symbol *symbol, unsigned char source[], int lengt /* and then the rest */ - for (read = 2; read < strlen(tracker); read++) { + for (read = 2, len = strlen(tracker); read < len; read++) { binary_multiply(accum, "10"); binary_load(y_reg, "0", 1); @@ -415,7 +412,6 @@ INTERNAL int imail(struct zint_symbol *symbol, unsigned char source[], int lengt accum[103] = 0; accum[102] = 0; - memset(byte_array, 0, 13); for (j = 0; j < 13; j++) { i = 96 - (8 * j); byte_array[j] = 0; @@ -547,7 +543,7 @@ INTERNAL int imail(struct zint_symbol *symbol, unsigned char source[], int lengt /* Translate 4-state data pattern to symbol */ read = 0; - for (i = 0; i < strlen(data_pattern); i++) { + for (i = 0, len = strlen(data_pattern); i < len; i++) { if ((data_pattern[i] == '1') || (data_pattern[i] == '0')) { set_module(symbol, 0, read); } diff --git a/backend/library.c b/backend/library.c index 50281346..bbe1ed33 100644 --- a/backend/library.c +++ b/backend/library.c @@ -675,15 +675,7 @@ static int reduced_charset(struct zint_symbol *symbol, const unsigned char *sour unsigned char* preprocessed = (unsigned char*) _alloca(in_length + 1); #endif - if (symbol->symbology == BARCODE_CODE16K) { - symbol->whitespace_width = 16; - symbol->border_width = 2; - if (!(symbol->output_options & BARCODE_BIND)) { - symbol->output_options += BARCODE_BIND; - } - } - else - if (symbol->symbology == BARCODE_ITF14) { + if (symbol->symbology == BARCODE_ITF14) { symbol->whitespace_width = 20; symbol->border_width = 8; if (!(symbol->output_options & BARCODE_BOX)) { diff --git a/backend/mailmark.c b/backend/mailmark.c index 29fb6b10..97fec4e8 100644 --- a/backend/mailmark.c +++ b/backend/mailmark.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2008-2018 Robin Stuart + Copyright (C) 2008 - 2020 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -40,7 +40,6 @@ */ #include -#include #include #ifdef _MSC_VER #include @@ -145,7 +144,7 @@ INTERNAL int mailmark(struct zint_symbol *symbol, const unsigned char source[], short int extender[27]; char bar[80]; int check_count; - int i, j; + int i, j, len; int length = (int) in_length; if (length > 26) { @@ -243,7 +242,6 @@ INTERNAL int mailmark(struct zint_symbol *symbol, const unsigned char source[], * 7 = International designation */ - postcode_type = 0; if (strcmp(postcode, "XY11 ") == 0) { postcode_type = 7; } else { @@ -573,7 +571,7 @@ INTERNAL int mailmark(struct zint_symbol *symbol, const unsigned char source[], /* Translate 4-state data pattern to symbol */ j = 0; - for (i = 0; i < strlen(bar); i++) { + for (i = 0, len = strlen(bar); i < len; i++) { if ((bar[i] == 'F') || (bar[i] == 'A')) { set_module(symbol, 0, j); } diff --git a/backend/output.c b/backend/output.c new file mode 100644 index 00000000..07c98858 --- /dev/null +++ b/backend/output.c @@ -0,0 +1,114 @@ +/* output.c - Common routines for raster/vector + + libzint - the open source barcode library + Copyright (C) 2020 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + */ +/* vim: set ts=4 sw=4 et : */ + +#include +#include "common.h" +#include "output.h" + +#define SSET "0123456789ABCDEF" + +/* Check colour options are good. Note: using raster.c error nos 651-654 */ +INTERNAL int check_colour_options(struct zint_symbol *symbol) { + int error_number; + + if (strlen(symbol->fgcolour) != 6) { + strcpy(symbol->errtxt, "651: Malformed foreground colour target"); + return ZINT_ERROR_INVALID_OPTION; + } + if (strlen(symbol->bgcolour) != 6) { + strcpy(symbol->errtxt, "652: Malformed background colour target"); + return ZINT_ERROR_INVALID_OPTION; + } + + to_upper((unsigned char *) symbol->fgcolour); + to_upper((unsigned char *) symbol->bgcolour); + + error_number = is_sane(SSET, (unsigned char *) symbol->fgcolour, strlen(symbol->fgcolour)); + if (error_number == ZINT_ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "653: Malformed foreground colour target"); + return ZINT_ERROR_INVALID_OPTION; + } + + error_number = is_sane(SSET, (unsigned char *) symbol->bgcolour, strlen(symbol->fgcolour)); + if (error_number == ZINT_ERROR_INVALID_DATA) { + strcpy(symbol->errtxt, "654: Malformed background colour target"); + return ZINT_ERROR_INVALID_OPTION; + } + + return 0; +} + +/* Return minimum quiet zones for each symbology */ +static void quiet_zones(struct zint_symbol *symbol, int *left, int *right, int *top, int *bottom) { + *left = *right = *top = *bottom = 0; + + switch (symbol->symbology) { + case BARCODE_CODE16K: + /* BS EN 12323:2005 Section 4.5 c) */ + *left = 10; + *right = 1; + break; + case BARCODE_CODE49: + /* ANSI/AIM BC6-2000 Section 2.4 */ + *left = 10; + *right = 1; + break; + case BARCODE_CODABLOCKF: + case BARCODE_HIBC_BLOCKF: + /* AIM ISS-X-24 Section 4.6.1 */ + *left = 10; + *right = 10; + break; + /* TODO: others */ + } +} + +/* Set left (x), top (y), right and bottom offsets for whitespace */ +INTERNAL void set_whitespace_offsets(struct zint_symbol *symbol, int *xoffset, int *yoffset, int *roffset, int *boffset) { + int qz_left, qz_right, qz_top, qz_bottom; + + quiet_zones(symbol, &qz_left, &qz_right, &qz_top, &qz_bottom); + + *xoffset = symbol->whitespace_width + qz_left; + *roffset = symbol->whitespace_width + qz_right; + if (symbol->output_options & BARCODE_BOX) { + *xoffset += symbol->border_width; + *roffset += symbol->border_width; + } + + *yoffset = qz_top; + *boffset = qz_bottom; + if (symbol->output_options & (BARCODE_BOX | BARCODE_BIND)) { + *yoffset += symbol->border_width; + *boffset += symbol->border_width; + } +} diff --git a/backend/output.h b/backend/output.h new file mode 100644 index 00000000..7e5ecd6c --- /dev/null +++ b/backend/output.h @@ -0,0 +1,47 @@ +/* output.h - Common routines for raster/vector + + libzint - the open source barcode library + Copyright (C) 2020 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + */ +/* vim: set ts=4 sw=4 et : */ + +#ifndef OUTPUT_H +#define OUTPUT_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +INTERNAL int check_colour_options(struct zint_symbol *symbol); +INTERNAL void set_whitespace_offsets(struct zint_symbol *symbol, int *xoffset, int *yoffset, int *roffset, int *boffset); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* OUTPUT_H */ diff --git a/backend/raster.c b/backend/raster.c index d7373830..2af51ed6 100644 --- a/backend/raster.c +++ b/backend/raster.c @@ -38,6 +38,7 @@ #endif #include #include "common.h" +#include "output.h" #ifdef _MSC_VER #include @@ -138,12 +139,7 @@ static int save_raster_image_to_file(struct zint_symbol *symbol, int image_heigh int error_number; int row, column; - char *rotated_pixbuf; - - if (!(rotated_pixbuf = (char *) malloc(image_width * image_height))) { - strcpy(symbol->errtxt, "650: Insufficient memory for pixel buffer"); - return ZINT_ERROR_ENCODING_PROBLEM; - } + char *rotated_pixbuf = pixelbuf; switch (rotate_angle) { case 0: @@ -158,42 +154,17 @@ static int save_raster_image_to_file(struct zint_symbol *symbol, int image_heigh break; } - /* sort out colour options */ - to_upper((unsigned char*) symbol->fgcolour); - to_upper((unsigned char*) symbol->bgcolour); - - if (strlen(symbol->fgcolour) != 6) { - strcpy(symbol->errtxt, "651: Malformed foreground colour target"); - free(rotated_pixbuf); - return ZINT_ERROR_INVALID_OPTION; - } - if (strlen(symbol->bgcolour) != 6) { - strcpy(symbol->errtxt, "652: Malformed background colour target"); - free(rotated_pixbuf); - return ZINT_ERROR_INVALID_OPTION; - } - error_number = is_sane(SSET, (unsigned char*) symbol->fgcolour, strlen(symbol->fgcolour)); - if (error_number == ZINT_ERROR_INVALID_DATA) { - strcpy(symbol->errtxt, "653: Malformed foreground colour target"); - free(rotated_pixbuf); - return ZINT_ERROR_INVALID_OPTION; - } - error_number = is_sane(SSET, (unsigned char*) symbol->bgcolour, strlen(symbol->fgcolour)); - if (error_number == ZINT_ERROR_INVALID_DATA) { - strcpy(symbol->errtxt, "654: Malformed background colour target"); - free(rotated_pixbuf); - return ZINT_ERROR_INVALID_OPTION; + if (rotate_angle) { + if (!(rotated_pixbuf = (char *) malloc(image_width * image_height))) { + strcpy(symbol->errtxt, "650: Insufficient memory for pixel buffer"); + return ZINT_ERROR_ENCODING_PROBLEM; + } } /* Rotate image before plotting */ switch (rotate_angle) { case 0: /* Plot the right way up */ - for (row = 0; row < image_height; row++) { - for (column = 0; column < image_width; column++) { - rotated_pixbuf[(row * image_width) + column] = - pixelbuf[(image_width * row) + column]; - } - } + /* Nothing to do */ break; case 90: /* Plot 90 degrees clockwise */ for (row = 0; row < image_width; row++) { @@ -230,7 +201,9 @@ static int save_raster_image_to_file(struct zint_symbol *symbol, int image_heigh #ifndef NO_PNG error_number = png_pixel_plot(symbol, rotated_pixbuf); #else - free(rotated_pixbuf); + if (rotate_angle) { + free(rotated_pixbuf); + } return ZINT_ERROR_INVALID_OPTION; #endif break; @@ -248,7 +221,9 @@ static int save_raster_image_to_file(struct zint_symbol *symbol, int image_heigh break; } - free(rotated_pixbuf); + if (rotate_angle) { + free(rotated_pixbuf); + } return error_number; } @@ -382,7 +357,7 @@ static void draw_letter(char *pixelbuf, unsigned char letter, int xposn, int ypo for (y = 0; y < max_y; y++) { char * pixelPtr = linePtr; int extra_dot = 0; - for (x = 0; x < 7; x++) { + for (x = 0; x < max_x; x++) { if (ascii_font[(glyph_no * 14) + y] & (0x40 >> x)) { *pixelPtr = DEFAULT_INK; extra_dot = 1; @@ -406,7 +381,7 @@ static void draw_letter(char *pixelbuf, unsigned char letter, int xposn, int ypo } break; - default: // regular font 7x15 + default: // regular font 7x14 max_x = 7; max_y = 14; @@ -419,7 +394,7 @@ static void draw_letter(char *pixelbuf, unsigned char letter, int xposn, int ypo } for (y = 0; y < max_y; y++) { - for (x = 0; x < 7; x++) { + for (x = 0; x < max_x; x++) { if (ascii_font[(glyph_no * 14) + y] & (0x40 >> x)) { *(pixelbuf + (y * image_width) + (yposn * image_width) + xposn + x) = DEFAULT_INK; } @@ -452,6 +427,7 @@ static void draw_string(char *pixbuf, char input_string[], int xposn, int yposn, string_left_hand = xposn - ((letter_width * string_length) / 2); for (i = 0; i < string_length; i++) { + // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) suppress false positive about 2nd arg input_string[i] being uninitialized draw_letter(pixbuf, input_string[i], string_left_hand + (i * letter_width), yposn, textflags, image_width, image_height); } @@ -532,28 +508,30 @@ static void plot_hexagon(char *scaled_hexagon, int hexagon_size) { static int plot_raster_maxicode(struct zint_symbol *symbol, int rotate_angle, int data_type) { /* Plot a MaxiCode symbol with hexagons and bullseye */ - int i, row, column, xposn; + int row, column, xposn; int image_height, image_width; char *pixelbuf; int error_number; int xoffset, yoffset; + int roffset, boffset; float scaler = symbol->scale; char *scaled_hexagon; int hexagon_size; - xoffset = symbol->border_width + symbol->whitespace_width; - yoffset = symbol->border_width; - image_width = (300 + (2 * xoffset * 2)) * scaler; - image_height = (300 + (2 * yoffset * 2)) * scaler; + if (scaler <= 0) { + scaler = 0.5; + } + + set_whitespace_offsets(symbol, &xoffset, &yoffset, &roffset, &boffset); + + image_width = (300 + 2 * (xoffset + roffset)) * scaler; + image_height = (300 + 2 * (yoffset + boffset)) * scaler; if (!(pixelbuf = (char *) malloc(image_width * image_height))) { strcpy(symbol->errtxt, "655: Insufficient memory for pixel buffer"); return ZINT_ERROR_ENCODING_PROBLEM; - } else { - for (i = 0; i < (image_width * image_height); i++) { - *(pixelbuf + i) = DEFAULT_PAPER; - } } + memset(pixelbuf, DEFAULT_PAPER, image_width * image_height); hexagon_size = (int)(scaler * 10); @@ -561,11 +539,8 @@ static int plot_raster_maxicode(struct zint_symbol *symbol, int rotate_angle, in strcpy(symbol->errtxt, "656: Insufficient memory for pixel buffer"); free(pixelbuf); return ZINT_ERROR_ENCODING_PROBLEM; - } else { - for (i = 0; i < (hexagon_size * hexagon_size); i++) { - *(scaled_hexagon + i) = DEFAULT_PAPER; - } } + memset(scaled_hexagon, DEFAULT_PAPER, hexagon_size * hexagon_size); plot_hexagon(scaled_hexagon, hexagon_size); @@ -655,13 +630,14 @@ static int plot_raster_dotty(struct zint_symbol *symbol, int rotate_angle, int d int scale_width, scale_height; int error_number = 0; int xoffset, yoffset, image_width, image_height; + int roffset, boffset; symbol->height = symbol->rows; // This is true because only 2d matrix symbols are processed here - xoffset = symbol->border_width + symbol->whitespace_width; - yoffset = symbol->border_width; - image_width = symbol->width + xoffset + xoffset; - image_height = symbol->height + yoffset + yoffset; + set_whitespace_offsets(symbol, &xoffset, &yoffset, &roffset, &boffset); + + image_width = symbol->width + xoffset + roffset; + image_height = symbol->height + yoffset + boffset; if (scaler < 2.0) { scaler = 2.0; @@ -673,11 +649,8 @@ static int plot_raster_dotty(struct zint_symbol *symbol, int rotate_angle, int d if (!(scaled_pixelbuf = (char *) malloc(scale_width * scale_height))) { strcpy(symbol->errtxt, "657: Insufficient memory for pixel buffer"); return ZINT_ERROR_ENCODING_PROBLEM; - } else { - for (i = 0; i < (scale_width * scale_height); i++) { - *(scaled_pixelbuf + i) = DEFAULT_PAPER; - } } + memset(scaled_pixelbuf, DEFAULT_PAPER, scale_width * scale_height); /* Plot the body of the symbol to the pixel buffer */ for (r = 0; r < symbol->rows; r++) { @@ -703,6 +676,7 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int char textpart[10], addon[6]; float addon_text_posn, preset_height, large_bar_height; int i, r, textoffset, yoffset, xoffset, latch, image_width, image_height; + int roffset, boffset; char *pixelbuf; int addon_latch = 0, textflags = 0; int block_width, textpos; @@ -720,7 +694,6 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int unsigned char* local_text = (unsigned char*) _alloca(ustrlen(symbol->text) + 1); #endif - memset(local_text, 0, ustrlen(symbol->text) + 1); if (symbol->show_hrt != 0) { /* Copy text from symbol */ to_latin1(symbol->text, local_text); @@ -739,7 +712,7 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int local_text[ustrlen(symbol->text)] = '\0'; } else { /* For everything else, just remove the text */ - local_text[0] = '\0'; + memset(local_text, 0, ustrlen(symbol->text) + 1); /* Note using memset() here to suppress clang-tidy false positives */ } } @@ -747,7 +720,6 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int main_width = symbol->width; comp_offset = 0; addon_text_posn = 0.0; - row_height = 0; if (symbol->output_options & SMALL_TEXT) { textflags = 1; } else if (symbol->output_options & BOLD_TEXT) { @@ -831,19 +803,16 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int textoffset = 0; } - xoffset = symbol->border_width + symbol->whitespace_width; - yoffset = symbol->border_width; - image_width = 2 * (symbol->width + xoffset + xoffset); - image_height = 2 * (symbol->height + textoffset + yoffset + yoffset); + set_whitespace_offsets(symbol, &xoffset, &yoffset, &roffset, &boffset); + + image_width = 2 * (symbol->width + xoffset + roffset); + image_height = 2 * (symbol->height + textoffset + yoffset + boffset); if (!(pixelbuf = (char *) malloc(image_width * image_height))) { strcpy(symbol->errtxt, "658: Insufficient memory for pixel buffer"); return ZINT_ERROR_ENCODING_PROBLEM; - } else { - for (i = 0; i < (image_width * image_height); i++) { - *(pixelbuf + i) = DEFAULT_PAPER; - } } + memset(pixelbuf, DEFAULT_PAPER, image_width * image_height); if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) { default_text_posn = image_height - 17; @@ -1095,16 +1064,16 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int /* Put boundary bars or box around symbol */ if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) { /* boundary bars */ - if (symbol->symbology != BARCODE_CODABLOCKF && symbol->symbology != BARCODE_HIBC_BLOCKF) { - draw_bar(pixelbuf, 0, (symbol->width + xoffset + xoffset) * 2, textoffset * 2, symbol->border_width * 2, image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, 0, (symbol->width + xoffset + xoffset) * 2, (textoffset + symbol->height + symbol->border_width) * 2, symbol->border_width * 2, image_width, image_height, DEFAULT_INK); + if ((symbol->output_options & BARCODE_BOX) || (symbol->symbology != BARCODE_CODABLOCKF && symbol->symbology != BARCODE_HIBC_BLOCKF)) { + draw_bar(pixelbuf, 0, (symbol->width + xoffset + roffset) * 2, textoffset * 2, symbol->border_width * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, 0, (symbol->width + xoffset + roffset) * 2, (textoffset + symbol->height + symbol->border_width) * 2, symbol->border_width * 2, image_width, image_height, DEFAULT_INK); } else { draw_bar(pixelbuf, xoffset * 2, symbol->width * 2, textoffset * 2, symbol->border_width * 2, image_width, image_height, DEFAULT_INK); draw_bar(pixelbuf, xoffset * 2, symbol->width * 2, (textoffset + symbol->height + symbol->border_width) * 2, symbol->border_width * 2, image_width, image_height, DEFAULT_INK); } if ((symbol->output_options & BARCODE_BIND) != 0) { if ((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) { - double sep_height = 2; + double sep_height = 1; if (symbol->option_3 > 0 && symbol->option_3 <= 4) { sep_height = symbol->option_3; } @@ -1115,8 +1084,8 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int } } else { for (r = 1; r < symbol->rows; r++) { - /* Avoid 11-module start and stop chars */ - draw_bar(pixelbuf, (xoffset + 11) * 2, (symbol->width - 22) * 2, ((r * row_height) + textoffset + yoffset - sep_height / 2) * 2, sep_height * 2, image_width, image_height, DEFAULT_INK); + /* Avoid 11-module start and 13-module stop chars */ + draw_bar(pixelbuf, (xoffset + 11) * 2, (symbol->width - 24) * 2, ((r * row_height) + textoffset + yoffset - sep_height / 2) * 2, sep_height * 2, image_width, image_height, DEFAULT_INK); } } } @@ -1126,7 +1095,7 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int if (symbol->output_options & BARCODE_BOX) { /* side bars */ draw_bar(pixelbuf, 0, symbol->border_width * 2, textoffset * 2, (symbol->height + (2 * symbol->border_width)) * 2, image_width, image_height, DEFAULT_INK); - draw_bar(pixelbuf, (symbol->width + xoffset + xoffset - symbol->border_width) * 2, symbol->border_width * 2, textoffset * 2, (symbol->height + (2 * symbol->border_width)) * 2, image_width, image_height, DEFAULT_INK); + draw_bar(pixelbuf, (symbol->width + xoffset + roffset - symbol->border_width) * 2, symbol->border_width * 2, textoffset * 2, (symbol->height + (2 * symbol->border_width)) * 2, image_width, image_height, DEFAULT_INK); } /* Put the human readable text at the bottom */ @@ -1136,31 +1105,33 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int } - if (scaler == 0) { + if (scaler <= 0) { scaler = 0.5; } - scale_width = image_width * scaler; - scale_height = image_height * scaler; - /* Apply scale options by creating another pixel buffer */ - if (!(scaled_pixelbuf = (char *) malloc(scale_width * scale_height))) { - free(pixelbuf); - strcpy(symbol->errtxt, "659: Insufficient memory for pixel buffer"); - return ZINT_ERROR_ENCODING_PROBLEM; + if (scaler != 1.0) { + scale_width = image_width * scaler; + scale_height = image_height * scaler; + + /* Apply scale options by creating another pixel buffer */ + if (!(scaled_pixelbuf = (char *) malloc(scale_width * scale_height))) { + free(pixelbuf); + strcpy(symbol->errtxt, "659: Insufficient memory for pixel buffer"); + return ZINT_ERROR_ENCODING_PROBLEM; + } + memset(scaled_pixelbuf, DEFAULT_PAPER, scale_width * scale_height); + + for (vert = 0; vert < scale_height; vert++) { + for (horiz = 0; horiz < scale_width; horiz++) { + *(scaled_pixelbuf + (vert * scale_width) + horiz) = *(pixelbuf + ((int) (vert / scaler) * image_width) + (int) (horiz / scaler)); + } + } + + error_number = save_raster_image_to_file(symbol, scale_height, scale_width, scaled_pixelbuf, rotate_angle, data_type); + free(scaled_pixelbuf); } else { - for (i = 0; i < (scale_width * scale_height); i++) { - *(scaled_pixelbuf + i) = DEFAULT_PAPER; - } + error_number = save_raster_image_to_file(symbol, image_height, image_width, pixelbuf, rotate_angle, data_type); } - - for (vert = 0; vert < scale_height; vert++) { - for (horiz = 0; horiz < scale_width; horiz++) { - *(scaled_pixelbuf + (vert * scale_width) + horiz) = *(pixelbuf + ((int) (vert / scaler) * image_width) + (int) (horiz / scaler)); - } - } - - error_number = save_raster_image_to_file(symbol, scale_height, scale_width, scaled_pixelbuf, rotate_angle, data_type); - free(scaled_pixelbuf); free(pixelbuf); return error_number; } @@ -1169,12 +1140,17 @@ INTERNAL int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_ int error; #ifdef NO_PNG - if (file_type == OUT_PNG_FILE) { - strcpy(symbol->errtxt, "660: PNG format disabled on compile time"); + if (file_type == OUT_PNG_FILE) { + strcpy(symbol->errtxt, "660: PNG format disabled at compile time"); return ZINT_ERROR_INVALID_OPTION; } #endif /* NO_PNG */ + error = check_colour_options(symbol); + if (error != 0) { + return error; + } + if (symbol->output_options & BARCODE_DOTTY_MODE) { error = plot_raster_dotty(symbol, rotate_angle, file_type); } else { diff --git a/backend/tests/CMakeLists.txt b/backend/tests/CMakeLists.txt index 7638ee2e..88d9b9c4 100644 --- a/backend/tests/CMakeLists.txt +++ b/backend/tests/CMakeLists.txt @@ -56,6 +56,8 @@ zint_add_test(channel, test_channel) zint_add_test(codablock, test_codablock) zint_add_test(code1, test_code1) zint_add_test(code128, test_code128) +zint_add_test(code16k, test_code16k) +zint_add_test(code49, test_code49) zint_add_test(common, test_common) zint_add_test(composite, test_composite) zint_add_test(dmatrix, test_dmatrix) diff --git a/backend/tests/data/png/codablockf_3rows.png b/backend/tests/data/png/codablockf_3rows.png index d2b191840ed92c746b9b7d6456b78242688e5f06..cc18fc8b37eb41ecee6f70594e377ee7ca503f97 100644 GIT binary patch literal 347 zcmeAS@N?(olHy`uVBq!ia0vp^pMcnbg9%8k=h)lJz`&^F>EaktaqI2fgR7bi1RMf` z|NM{N)}5!7c<4gU(PhtdMAx*f-nU&M=Xhbx{H(RP1-&zk1~$58Vx*g1;xxf7U8B=8{@bK&*EaktaqI2fXs%`h5eLWM zJO8I$?hoQ)_wc5%wYbT39|na<@=A!zZqw( zwf)!Lx6?9~NxbddXK0o7Y|Wz2^779;-8?Y=$Aj(_o@pjMty|HIL&#B*iH{Q=?pA%_mHqYPX^{HRFVST;t z>z`HIzBM?}gfItc0GPV5W~su-C@!8&3f6Up7G-OG`Y$E?c5j*N;hC#XpP6So-=^&C z% - Zint Generated Symbol - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/backend/tests/test_codablock.c b/backend/tests/test_codablock.c index b2046ec3..7b757540 100644 --- a/backend/tests/test_codablock.c +++ b/backend/tests/test_codablock.c @@ -169,8 +169,8 @@ static void test_reader_init(int index, int generate, int debug) { char *comment; }; struct item data[] = { - /* 0*/ { BARCODE_CODABLOCKF, UNICODE_MODE, 16, "1234", 0, 2, 101, "67 64 40 60 63 0C 22 2B 6A 67 64 0B 63 64 3A 1C 29 6A", "CodeB FNC3 CodeC 12 34 / CodeB Pads" }, - /* 1*/ { BARCODE_HIBC_BLOCKF, UNICODE_MODE, 16, "123456", 0, 3, 101, "67 64 41 60 0B 11 12 22 6A 67 63 2B 22 38 64 2A 1B 6A 67 64 0C 63 64 2B 2F 52 6A", "CodeB FNC3 + 1 2 / CodeC 34 56 CodeB J" }, + /* 0*/ { BARCODE_CODABLOCKF, UNICODE_MODE, READER_INIT, "1234", 0, 2, 101, "67 64 40 60 63 0C 22 2B 6A 67 64 0B 63 64 3A 1C 29 6A", "CodeB FNC3 CodeC 12 34 / CodeB Pads" }, + /* 1*/ { BARCODE_HIBC_BLOCKF, UNICODE_MODE, READER_INIT, "123456", 0, 3, 101, "67 64 41 60 0B 11 12 22 6A 67 63 2B 22 38 64 2A 1B 6A 67 64 0C 63 64 2B 2F 52 6A", "CodeB FNC3 + 1 2 / CodeC 34 56 CodeB J" }, }; int data_size = ARRAY_SIZE(data); @@ -191,8 +191,8 @@ static void test_reader_init(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, \"%s\", %s, %d, %d, \"%s\", \"%s\" },\n", - i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), data[i].output_options, + printf(" /*%3d*/ { %s, %s, %s, \"%s\", %s, %d, %d, \"%s\", \"%s\" },\n", + i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), testUtilOutputOptionsName(data[i].output_options), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), testUtilErrorName(data[i].ret), symbol->rows, symbol->width, symbol->errtxt, data[i].comment); } else { diff --git a/backend/tests/test_code128.c b/backend/tests/test_code128.c index 837ffd6d..878d2f7b 100644 --- a/backend/tests/test_code128.c +++ b/backend/tests/test_code128.c @@ -165,12 +165,12 @@ static void test_reader_init(int index, int generate, int debug) { char *comment; }; struct item data[] = { - /* 0*/ { BARCODE_CODE128, UNICODE_MODE, 16, "A", 0, 1, 57, "(5) 104 96 33 60 106", "StartA FNC3 A" }, - /* 1*/ { BARCODE_CODE128, UNICODE_MODE, 16, "12", 0, 1, 68, "(6) 104 96 99 12 22 106", "StartB FNC3 CodeC 12" }, - /* 2*/ { BARCODE_CODE128B, UNICODE_MODE, 16, "\0371234", 0, 1, 101, "(9) 103 96 95 17 18 19 20 6 106", "StartA FNC3 US 1 2 3 4" }, - /* 3*/ { BARCODE_EAN128, GS1_MODE, 16, "[90]12", 0, 1, 68, "", "Reader Initialise not supported by GS1 barcodes (use CODE128)" }, - /* 4*/ { BARCODE_EAN14, GS1_MODE, 16, "12", 0, 1, 134, "", "Reader Initialise not supported by GS1 barcodes (use CODE128)" }, - /* 5*/ { BARCODE_NVE18, GS1_MODE, 16, "12", 0, 1, 156, "", "Reader Initialise not supported by GS1 barcodes (use CODE128)" }, + /* 0*/ { BARCODE_CODE128, UNICODE_MODE, READER_INIT, "A", 0, 1, 57, "(5) 104 96 33 60 106", "StartA FNC3 A" }, + /* 1*/ { BARCODE_CODE128, UNICODE_MODE, READER_INIT, "12", 0, 1, 68, "(6) 104 96 99 12 22 106", "StartB FNC3 CodeC 12" }, + /* 2*/ { BARCODE_CODE128B, UNICODE_MODE, READER_INIT, "\0371234", 0, 1, 101, "(9) 103 96 95 17 18 19 20 6 106", "StartA FNC3 US 1 2 3 4" }, + /* 3*/ { BARCODE_EAN128, GS1_MODE, READER_INIT, "[90]12", 0, 1, 68, "(6) 105 102 90 12 11 106", "StartC FNC1 90 12 (Reader Initialise not supported by GS1 barcodes (use CODE128))" }, + /* 4*/ { BARCODE_EAN14, GS1_MODE, READER_INIT, "12", 0, 1, 134, "(12) 105 102 1 0 0 0 0 0 1 25 30 106", "StartC FNC1 01 00 (5) 01 (Reader Initialise not supported by GS1 barcodes (use CODE128))" }, + /* 5*/ { BARCODE_NVE18, GS1_MODE, READER_INIT, "12", 0, 1, 156, "(14) 105 102 0 0 0 0 0 0 0 0 1 25 80 106", "StartC FNC1 00 (8) 01 (Reader Initialise not supported by GS1 barcodes (use CODE128))" }, }; int data_size = ARRAY_SIZE(data); @@ -191,8 +191,8 @@ static void test_reader_init(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, \"%s\", %s, %d, %d, \"%s\", \"%s\" },\n", - i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), data[i].output_options, + printf(" /*%3d*/ { %s, %s, %s, \"%s\", %s, %d, %d, \"%s\", \"%s\" },\n", + i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), testUtilOutputOptionsName(data[i].output_options), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), testUtilErrorName(data[i].ret), symbol->rows, symbol->width, symbol->errtxt, data[i].comment); } else { @@ -302,6 +302,76 @@ static void test_input(int index, int generate, int debug) { testFinish(); } +static void test_ean128_input(int index, int generate, int debug) { + + testStart(""); + + int ret; + struct item { + unsigned char *data; + int ret; + int expected_width; + char *expected; + char *comment; + }; + struct item data[] = { + /* 0*/ { "[90]1[90]1", 0, 123, "(11) 105 102 90 100 17 102 25 99 1 56 106", "StartC FNC1 90 CodeB 1 FNC1 9" }, + /* 1*/ { "[90]1[90]12", 0, 123, "(11) 105 102 90 100 17 99 102 90 12 13 106", "StartC FNC1 90 CodeB 1 CodeC FNC1 90 12" }, + /* 2*/ { "[90]1[90]123", 0, 134, "(12) 105 102 90 100 17 102 25 99 1 23 57 106", "StartC FNC1 90 CodeB 1 FNC1 9 CodeC 01 23" }, + /* 3*/ { "[90]12[90]1", 0, 123, "(11) 105 102 90 12 102 100 25 99 1 19 106", "StartC FNC1 90 12 FNC1 CodeB 9 CodeC 01" }, + /* 4*/ { "[90]12[90]12", 0, 101, "(9) 105 102 90 12 102 90 12 14 106", "StartC FNC1 90 12 FNC1 90 12" }, + /* 5*/ { "[90]12[90]123", 0, 134, "(12) 105 102 90 12 102 100 25 99 1 23 20 106", "StartC FNC1 90 12 FNC1 CodeB 9 CodeC 01 23" }, + /* 6*/ { "[90]123[90]1", 0, 134, "(12) 105 102 90 12 100 19 102 25 99 1 34 106", "StartC FNC1 90 12 CodeB 3 FNC1 9 CodeC 01" }, + /* 7*/ { "[90]123[90]1234", 0, 145, "(13) 105 102 90 12 100 19 99 102 90 12 34 98 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 12 34" }, + /* 8*/ { "[90]1[90]1[90]1", 0, 178, "(16) 105 102 90 100 17 102 25 99 1 102 100 25 99 1 51 106", "StartC FNC1 90 CodeB 1 FNC1 9 CodeC 01 FNC1 CodeB 9 CodeC 01" }, + /* 9*/ { "[90]1[90]12[90]1", 0, 178, "(16) 105 102 90 100 17 99 102 90 12 102 100 25 99 1 8 106", "StartC FNC1 90 CodeB 1 CodeC FNC1 90 12 FNC1 CodeB 9 CodeC 01" }, + /* 10*/ { "[90]1[90]123[90]1", 0, 189, "(17) 105 102 90 100 17 102 25 99 1 23 102 100 25 99 1 70 106", "StartC FNC1 90 CodeB 1 FNC1 9 CodeC 01 23 FNC1 CodeB 9 CodeC 01" }, + /* 11*/ { "[90]12[90]123[90]1", 0, 189, "(17) 105 102 90 12 102 100 25 99 1 23 102 100 25 99 1 33 106", "StartC FNC1 90 12 FNC1 CodeB 9 CodeC 01 23 FNC1 CodeB 9 CodeC 01" }, + /* 12*/ { "[90]12[90]123[90]12", 0, 167, "(15) 105 102 90 12 102 100 25 99 1 23 102 90 12 11 106", "StartC FNC1 90 12 FNC1 CodeB 9 CodeC 01 23 FNC1 90 12" }, + /* 13*/ { "[90]123[90]1[90]1", 0, 189, "(17) 105 102 90 12 100 19 102 25 99 1 102 100 25 99 1 47 106", "StartC FNC1 90 12 CodeB 3 FNC1 9 CodeC 01 FNC1 CodeB 9 CodeC 01" }, + /* 14*/ { "[90]123[90]12[90]1", 0, 189, "(17) 105 102 90 12 100 19 99 102 90 12 102 100 25 99 1 80 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 12 FNC1 CodeB 9 CodeC 01" }, + /* 15*/ { "[90]123[90]123[90]12", 0, 178, "(16) 105 102 90 12 100 19 102 25 99 1 23 102 90 12 47 106", "StartC FNC1 90 12 CodeB 3 FNC1 9 CodeC 01 23 FNC1 90 12" }, + /* 16*/ { "[90]123[90]1234[90]1", 0, 200, "(18) 105 102 90 12 100 19 99 102 90 12 34 102 100 25 99 1 26 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 12 34 FNC1 CodeB 9 CodeC 01" }, + /* 17*/ { "[90]123[90]1234[90]123", 0, 211, "(19) 105 102 90 12 100 19 99 102 90 12 34 102 100 25 99 1 23 85 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 12 34 FNC1 CodeB 9 CodeC 01 23" }, + /* 18*/ { "[90]12345[90]1234[90]1", 0, 211, "(19) 105 102 90 12 34 100 21 99 102 90 12 34 102 100 25 99 1 30 106", "StartC FNC1 90 12 34 CodeB 5 CodeC FNC1 90 12 34 FNC1 CodeB 9 CodeC 01" }, + /* 19*/ { "[90]1A[90]1", 0, 134, "(12) 104 102 25 16 17 33 102 25 99 1 65 106", "StartB FNC1 9 0 1 A FNC1 9 CodeC 01" }, + /* 20*/ { "[90]12A[90]123", 0, 145, "(13) 105 102 90 12 100 33 102 25 99 1 23 25 106", "StartC FNC1 90 12 CodeB A FNC1 9 CodeC 01 23" }, + /* 21*/ { "[90]123[90]A234[90]123", 0, 244, "(22) 105 102 90 12 100 19 99 102 90 100 33 18 99 34 102 100 25 99 1 23 37 106", "StartC FNC1 90 12 CodeB 3 CodeC FNC1 90 CodeB A 2 CodeC 34 FNC1 CodeB 9 CodeC 01 23" } }; + int data_size = sizeof(data) / sizeof(struct item); + + char escaped[1024]; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt + + int length = testUtilSetSymbol(symbol, BARCODE_EAN128, GS1_MODE, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + + ret = ZBarcode_Encode(symbol, 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\" },\n", + i, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), + testUtilErrorName(data[i].ret), symbol->width, symbol->errtxt, data[i].comment); + } else { + if (ret < 5) { + 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); + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + static void test_encode(int index, int generate, int debug) { testStart(""); @@ -444,6 +514,7 @@ int main(int argc, char *argv[]) { { "test_hrt", test_hrt, 1, 0, 1 }, { "test_reader_init", test_reader_init, 1, 1, 1 }, { "test_input", test_input, 1, 1, 1 }, + { "test_ean128_input", test_ean128_input, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 }, }; diff --git a/backend/tests/test_code16k.c b/backend/tests/test_code16k.c new file mode 100644 index 00000000..916707a7 --- /dev/null +++ b/backend/tests/test_code16k.c @@ -0,0 +1,301 @@ +/* + libzint - the open source barcode library + Copyright (C) 2020 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + */ +/* vim: set ts=4 sw=4 et : */ + +#include "testcommon.h" + +static void test_large(int index, int debug) { + + testStart(""); + + int ret; + struct item { + unsigned char *pattern; + int length; + int ret; + int expected_rows; + int expected_width; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { "A", 77, 0, 16, 70 }, // BS EN 12323:2005 4.1 (l) + /* 1*/ { "A", 78, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 2*/ { "0", 154, 0, 16, 70 }, // BS EN 12323:2005 4.1 (l) + /* 3*/ { "0", 155, ZINT_ERROR_TOO_LONG, -1, -1 }, + }; + int data_size = ARRAY_SIZE(data); + + char data_buf[4096]; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + 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)); + + int length = testUtilSetSymbol(symbol, BARCODE_CODE16K, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data_buf, data[i].length, debug); + + ret = ZBarcode_Encode(symbol, 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); + + if (ret < 5) { + 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); + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_reader_init(int index, int generate, int debug) { + + testStart(""); + + int ret; + struct item { + int input_mode; + int output_options; + unsigned char *data; + int ret; + int expected_rows; + int expected_width; + char *expected; + char *comment; + }; + struct item data[] = { + /* 0*/ { UNICODE_MODE, READER_INIT, "A", 0, 2, 70, "(10) 1 96 33 103 103 103 103 103 68 35", "ModeB FNC3 A Pad (5)" }, + /* 1*/ { UNICODE_MODE, READER_INIT, "12", 0, 2, 70, "(10) 5 96 12 103 103 103 103 103 99 41", "ModeC1SB FNC3 12 Pad (5)" }, + /* 2*/ { UNICODE_MODE, READER_INIT, "A1234", 0, 2, 70, "(10) 6 96 33 12 34 103 103 103 65 53", "ModeC2SB FNC3 A 12 34 Pad (3)" }, + /* 3*/ { GS1_MODE, READER_INIT, "[90]1", ZINT_ERROR_INVALID_OPTION, 0, 0, "Error 422: Cannot use both GS1 mode and Reader Initialisation", "" }, + }; + int data_size = ARRAY_SIZE(data); + + char escaped[1024]; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt + + int length = testUtilSetSymbol(symbol, BARCODE_CODE16K, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1 /*option_2*/, -1, data[i].output_options, data[i].data, -1, debug); + + ret = ZBarcode_Encode(symbol, 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, %d, %d, \"%s\", \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), testUtilOutputOptionsName(data[i].output_options), + testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, symbol->errtxt, data[i].comment); + } else { + if (ret < 5) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_input(int index, int generate, int debug) { + + testStart(""); + + int ret; + struct item { + int input_mode; + unsigned char *data; + int length; + int ret; + int expected_rows; + int expected_width; + char *expected; + char *comment; + }; + // NUL U+0000, CodeA-only + // US U+001F (\037, 31), CodeA-only + // a U+0061 (\141, 97), CodeB-only + // b U+0062 (\142, 98), CodeB-only + // APC U+009F (\237, 159), UTF-8 C29F, CodeA-only extended ASCII, not in ISO 8859-1 + // ß U+00DF (\337, 223), UTF-8 C39F, CodeA and CodeB extended ASCII + // é U+00E9 (\351, 233), UTF-8 C3A9, CodeB-only extended ASCII + struct item data[] = { + /* 0*/ { UNICODE_MODE, "\037", -1, 0, 2, 70, "(10) 0 95 103 103 103 103 103 103 22 42", "ModeA US Pad (6)" }, + /* 1*/ { UNICODE_MODE, "A", -1, 0, 2, 70, "(10) 1 33 103 103 103 103 103 103 52 82", "ModeB A Pad (6)" }, + /* 2*/ { UNICODE_MODE, "12", -1, 0, 2, 70, "(10) 2 12 103 103 103 103 103 103 98 27", "ModeC 12 Pad (6)" }, + /* 3*/ { GS1_MODE, "[90]A", -1, 0, 2, 70, "(10) 3 25 16 33 103 103 103 103 83 20", "ModeBFNC1 9 0 A Pad (4)" }, + /* 4*/ { GS1_MODE, "[90]12", -1, 0, 2, 70, "(10) 4 90 12 103 103 103 103 103 79 62", "ModeCFNC1 90 12 Pad (5)" }, + /* 5*/ { UNICODE_MODE, "a0123456789", -1, 0, 2, 70, "(10) 5 65 1 23 45 67 89 103 27 86", "ModeC1SB a 01 23 45 67 89 Pad" }, + /* 6*/ { UNICODE_MODE, "ab0123456789", -1, 0, 2, 70, "(10) 6 65 66 1 23 45 67 89 19 42", "ModeC2SB a b 01 23 45 67 89" }, + /* 7*/ { UNICODE_MODE, "1234\037a", -1, 0, 2, 70, "(10) 2 12 34 101 95 98 65 103 67 53", "ModeC 12 34 CodeA US 1SB a Pad" }, + /* 8*/ { UNICODE_MODE, "\000\037ß", 4, 0, 2, 70, "(10) 0 64 95 101 63 103 103 103 75 11", "ModeA NUL US FNC4 ß Pad (3)" }, + /* 9*/ { UNICODE_MODE, "\000\037é", 4, 0, 2, 70, "(10) 0 64 95 101 98 73 103 103 75 6", "ModeA NUL US FNC4 1SB é Pad (2)" }, + /* 10*/ { UNICODE_MODE, "\000\037éa", 5, 0, 2, 70, "(10) 0 64 95 100 100 73 65 103 99 69", "ModeA NUL US CodeB FNC4 é a Pad" }, + /* 11*/ { UNICODE_MODE, "abß", -1, 0, 2, 70, "(10) 1 65 66 100 63 103 103 103 66 56", "ModeB a b FNC4 ß Pad (3)" }, + /* 12*/ { DATA_MODE, "\141\142\237", -1, 0, 2, 70, "(10) 1 65 66 100 98 95 103 103 6 71", "ModeB a b FNC4 1SA APC Pad (2)" }, + /* 13*/ { DATA_MODE, "\141\142\237\037", -1, 0, 2, 70, "(10) 1 65 66 101 101 95 95 103 72 93", "ModeB a b CodeA FNC4 APC US Pad" }, + /* 14*/ { UNICODE_MODE, "ééé", -1, 0, 2, 70, "(10) 1 100 73 100 73 100 73 103 105 106", "ModeB FNC4 é FNC4 é FNC4 é Pad" }, + /* 15*/ { UNICODE_MODE, "aééééb", -1, 0, 3, 70, "(15) 8 65 100 73 100 73 100 73 100 73 66 103 103 39 83", "ModeB a FNC4 é (4) b Pad (2)" }, + /* 16*/ { UNICODE_MODE, "aéééééb", -1, 0, 3, 70, "(15) 8 65 100 73 100 73 100 73 100 73 100 73 66 74 106", "ModeB a FNC4 é (5) b" }, + /* 17*/ { UNICODE_MODE, "aééééébcdeé", -1, 0, 4, 70, "(20) 15 65 100 73 100 73 100 73 100 73 100 73 66 67 68 69 100 73 14 69", "ModeB a FNC4 é (5) b c d e FNC4 é" }, + }; + int data_size = ARRAY_SIZE(data); + + char escaped[1024]; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt + + int length = testUtilSetSymbol(symbol, BARCODE_CODE16K, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + + ret = ZBarcode_Encode(symbol, 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, %d, %d, \"%s\", \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].length, + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, symbol->errtxt, data[i].comment); + } else { + if (ret < 5) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_encode(int index, int generate, int debug) { + + testStart(""); + + int ret; + struct item { + int input_mode; + unsigned char *data; + int ret; + + int expected_rows; + int expected_width; + char *comment; + char *expected; + }; + struct item data[] = { + /* 0*/ { UNICODE_MODE, "ab0123456789", 0, 2, 70, "BS EN 12323:2005 Figure 3", + "1110010101100110111011010011110110111100100110010011000100100010001101" + "1100110101000100111011110100110010010000100110100011010010001110011001" + }, + /* 1*/ { UNICODE_MODE, "www.wikipedia.de", 0, 4, 70, "Verified manually against bwipp", + "1110010101000110011000011010110000110101100001101011011001100010001101" + "1100110100001101011011110010110011110110101111001011010110000110011001" + "1101100101001101111011110110010111100101101101001111011001100010010011" + "1000010101111011001010011011110010111101101100001011010001001110111101" + }, + }; + int data_size = ARRAY_SIZE(data); + + char escaped[1024]; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + int length = testUtilSetSymbol(symbol, BARCODE_CODE16K, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + + ret = ZBarcode_Encode(symbol, 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, %d, %d, \"%s\",\n", + i, testUtilInputModeName(data[i].input_mode), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment); + testUtilModulesDump(symbol, " ", "\n"); + printf(" },\n"); + } else { + if (ret < 5) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + + if (ret == 0) { + int width, row; + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); + } + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +int main(int argc, char *argv[]) { + + testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ + { "test_large", test_large, 1, 0, 1 }, + { "test_reader_init", test_reader_init, 1, 1, 1 }, + { "test_input", test_input, 1, 1, 1 }, + { "test_encode", test_encode, 1, 1, 1 }, + }; + + testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); + + testReport(); + + return 0; +} diff --git a/backend/tests/test_code49.c b/backend/tests/test_code49.c new file mode 100644 index 00000000..55bf0ead --- /dev/null +++ b/backend/tests/test_code49.c @@ -0,0 +1,234 @@ +/* + libzint - the open source barcode library + Copyright (C) 2020 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + */ +/* vim: set ts=4 sw=4 et : */ + +#include "testcommon.h" + +static void test_large(int index, int debug) { + + testStart(""); + + int ret; + struct item { + unsigned char *pattern; + int length; + int ret; + int expected_rows; + int expected_width; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { "A", 49, 0, 8, 70 }, // ANSI/AIM BC6-2000 Table 1 + /* 1*/ { "A", 50, ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 2*/ { "0", 81, 0, 8, 70 }, // ANSI/AIM BC6-2000 Table 1 + /* 3*/ { "0", 82, ZINT_ERROR_TOO_LONG, -1, -1 }, + }; + int data_size = ARRAY_SIZE(data); + + char data_buf[4096]; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + 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)); + + int length = testUtilSetSymbol(symbol, BARCODE_CODE49, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data_buf, data[i].length, debug); + + ret = ZBarcode_Encode(symbol, 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); + + if (ret < 5) { + 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); + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_input(int index, int generate, int debug) { + + testStart(""); + + int ret; + struct item { + int input_mode; + unsigned char *data; + int length; + int ret; + int expected_rows; + int expected_width; + char *expected; + char *comment; + }; + // NUL U+0000, S1 SP (39) + // US U+001F (\037, 31), S1 5 + struct item data[] = { + /* 0*/ { UNICODE_MODE, "é", -1, ZINT_ERROR_INVALID_DATA, 0, 0, "Error 431: Invalid characters in input data", "ASCII only" }, + /* 1*/ { UNICODE_MODE, "EXAMPLE 2", -1, 0, 2, 70, "(16) 14 33 10 22 25 21 14 41 38 2 35 14 18 13 0 22", "2.3.7 Symbol Example" }, + /* 2*/ { UNICODE_MODE, "12345", -1, 0, 2, 70, "(16) 5 17 9 48 48 48 48 27 48 48 13 23 0 13 2 0", "2.3 Example 1: Numeric Encodation (Start 2, Numeric)" }, + /* 3*/ { UNICODE_MODE, "123456", -1, 0, 2, 70, "(16) 5 17 9 6 48 48 48 34 48 48 36 9 23 41 2 11", "2.3 Example 1: Numeric Encodation" }, + /* 4*/ { UNICODE_MODE, "12345678", -1, 0, 2, 70, "(16) 5 17 9 14 6 48 48 0 48 48 25 42 2 17 2 37", "2.3 Example 1: Numeric Encodation" }, + /* 5*/ { UNICODE_MODE, "123456789", -1, 0, 2, 70, "(16) 5 17 9 46 16 37 48 31 48 48 7 26 9 39 2 32", "2.3 Example 1: Numeric Encodation" }, + /* 6*/ { UNICODE_MODE, "1234567", -1, 0, 2, 70, "(16) 43 45 2 11 39 48 48 40 48 48 33 36 38 6 2 15", "2.3 Example 1: Numeric Encodation" }, + /* 7*/ { UNICODE_MODE, "\037", -1, 0, 2, 70, "(16) 5 48 48 48 48 48 48 48 48 48 4 33 13 15 4 18", "US (Start 4, Alphanumeric S1)" }, + /* 8*/ { UNICODE_MODE, "\000\037", 2, 0, 2, 70, "(16) 38 43 5 48 48 48 48 33 48 48 45 7 38 43 4 37", "NUL S1 US (Start 4, Alphanumeric S1)" }, + /* 9*/ { UNICODE_MODE, "a\000", 2, 0, 2, 70, "(16) 10 43 38 48 48 48 48 38 48 48 32 33 14 15 5 48", "a S1 NUL (Start 5, Alphanumeric S2)" }, + /* 10*/ { UNICODE_MODE, "ab", -1, 0, 2, 70, "(16) 10 44 11 48 48 48 48 12 48 48 27 39 42 0 5 13", "a S2 b (Start 5, Alphanumeric S2)" }, + /* 11*/ { UNICODE_MODE, "\000A\000a\000", 5, 0, 2, 70, "(16) 38 10 43 38 44 10 43 30 38 48 25 23 38 32 4 12", "NUL A S1 NUL S2 a S1 (C18 30) NUL (Start 4, Alphanumeric S1)" }, + /* 12*/ { UNICODE_MODE, "1234\037aA12345A", -1, 0, 3, 70, "(24) 1 2 3 4 43 5 44 4 10 10 48 5 17 9 48 0 10 48 19 2 13 32 7 33", "1 2 3 4 S1 US S2 (C18 4) a A NS 12345 NS (C28 0) A (Start 0, Alpha)" }, + /* 13*/ { GS1_MODE, "[90]12345[91]AB12345", -1, 0, 4, 70, "(32) 45 48 47 15 4 7 9 28 48 45 9 1 10 11 48 25 5 17 9 48 48 48 48 27 48 48 37 39 26 8 14", "FNC1 NS 9012345 (C18 28) NS FNC1 9 1 A B NS (C28 25) 12345 Pad (4) (C38 27) (Start 0, Alpha)" }, + }; + int data_size = ARRAY_SIZE(data); + + char escaped[1024]; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt + + int length = testUtilSetSymbol(symbol, BARCODE_CODE49, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, data[i].length, debug); + + ret = ZBarcode_Encode(symbol, 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, %d, %d, \"%s\", \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].length, + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, symbol->errtxt, data[i].comment); + } else { + if (ret < 5) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_encode(int index, int generate, int debug) { + + testStart(""); + + int ret; + struct item { + int input_mode; + unsigned char *data; + int ret; + + int expected_rows; + int expected_width; + char *comment; + char *expected; + }; + struct item data[] = { + /* 0*/ { UNICODE_MODE, "MULTIPLE ROWS IN CODE 49", 0, 5, 70, "ANSI/AIM BC6-2000 Figure 1", + "1011111011001011101011100110000110111101011011111010111101000100001111" + "1010100001000010001001111000101110100110001111010010001011100011001111" + "1011001100000101101101110111000010110010110000111011101011110001101111" + "1010011001100100001111010010001100101011101111110011010001001111101111" + "1011001111001011101000000101001110111110111010001011010001101111101111" + }, + /* 1*/ { UNICODE_MODE, "EXAMPLE 2", 0, 2, 70, "ANSI/AIM BC6-2000 Figure 3", + "1011000111011100101111001001000110110011110010100010001111000100101111" + "1011000100110010001100010110010000100001101001111010000001001011101111" + }, + }; + int data_size = ARRAY_SIZE(data); + + char escaped[1024]; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + int length = testUtilSetSymbol(symbol, BARCODE_CODE49, data[i].input_mode, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + + ret = ZBarcode_Encode(symbol, 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, %d, %d, \"%s\",\n", + i, testUtilInputModeName(data[i].input_mode), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment); + testUtilModulesDump(symbol, " ", "\n"); + printf(" },\n"); + } else { + if (ret < 5) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + + if (ret == 0) { + int width, row; + ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); + assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); + } + } + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +int main(int argc, char *argv[]) { + + testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ + { "test_large", test_large, 1, 0, 1 }, + { "test_input", test_input, 1, 1, 1 }, + { "test_encode", test_encode, 1, 1, 1 }, + }; + + testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); + + testReport(); + + return 0; +} diff --git a/backend/tests/test_library.c b/backend/tests/test_library.c index d2331543..93591377 100644 --- a/backend/tests/test_library.c +++ b/backend/tests/test_library.c @@ -159,6 +159,7 @@ static void test_escape_char_process(int index, int generate, int debug) { int ret; struct item { + int input_mode; unsigned char *data; int ret; int expected_width; @@ -166,12 +167,13 @@ static void test_escape_char_process(int index, int generate, int debug) { char *comment; }; struct item data[] = { - /* 0*/ { "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\e\\G\\R\\x81\\\\", 0, 200, "(18) 103 64 68 71 72 73 74 75 76 77 91 93 94 101 65 60 44 106", "" }, - /* 1*/ { "\\c", ZINT_ERROR_INVALID_DATA, 0, "Error 234: Unrecognised escape character in input data", "" }, - /* 2*/ { "\\", ZINT_ERROR_INVALID_DATA, 0, "Error 236: Incomplete escape character in input data", "" }, - /* 3*/ { "\\x", ZINT_ERROR_INVALID_DATA, 0, "Error 232: Incomplete escape character in input data", "" }, - /* 4*/ { "\\x1", ZINT_ERROR_INVALID_DATA, 0, "Error 232: Incomplete escape character in input data", "" }, - /* 5*/ { "\\x1g", ZINT_ERROR_INVALID_DATA, 0, "Error 233: Corrupt escape character in input data", "" }, + /* 0*/ { DATA_MODE, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\e\\G\\R\\x81\\\\", 0, 200, "(18) 103 64 68 71 72 73 74 75 76 77 91 93 94 101 65 60 44 106", "" }, + /* 1*/ { DATA_MODE, "\\c", ZINT_ERROR_INVALID_DATA, 0, "Error 234: Unrecognised escape character in input data", "" }, + /* 2*/ { DATA_MODE, "\\", ZINT_ERROR_INVALID_DATA, 0, "Error 236: Incomplete escape character in input data", "" }, + /* 3*/ { DATA_MODE, "\\x", ZINT_ERROR_INVALID_DATA, 0, "Error 232: Incomplete escape character in input data", "" }, + /* 4*/ { DATA_MODE, "\\x1", ZINT_ERROR_INVALID_DATA, 0, "Error 232: Incomplete escape character in input data", "" }, + /* 5*/ { DATA_MODE, "\\x1g", ZINT_ERROR_INVALID_DATA, 0, "Error 233: Corrupt escape character in input data", "" }, + /* 6*/ { UNICODE_MODE, "\\xA01\\xFF", 0, 90, "(8) 104 100 0 17 100 95 100 106", "" }, }; int data_size = ARRAY_SIZE(data); @@ -186,14 +188,15 @@ static void test_escape_char_process(int index, int generate, int debug) { symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - int length = testUtilSetSymbol(symbol, BARCODE_CODE128, DATA_MODE | ESCAPE_MODE, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + int length = testUtilSetSymbol(symbol, BARCODE_CODE128, data[i].input_mode | ESCAPE_MODE, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, 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\" },\n", - i, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), testUtilErrorName(data[i].ret), symbol->width, symbol->errtxt, data[i].comment); + printf(" /*%3d*/ { %s, \"%s\", %s, %d, \"%s\", \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), + testUtilErrorName(data[i].ret), symbol->width, symbol->errtxt, data[i].comment); } else { if (ret < 5) { 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); diff --git a/backend/tests/test_raster.c b/backend/tests/test_raster.c index be6cca2e..f01bac31 100644 --- a/backend/tests/test_raster.c +++ b/backend/tests/test_raster.c @@ -36,6 +36,231 @@ static int is_row_column_black(struct zint_symbol *symbol, int row, int column) return symbol->bitmap[i] == 0 && symbol->bitmap[i + 1] == 0 && symbol->bitmap[i + 2] == 0; // Black } +static void test_options(int index, int debug) { + + testStart(""); + + int ret; + struct item { + int symbology; + char *fgcolour; + char *bgcolour; + int rotate_angle; + unsigned char *data; + int ret; + int expected_rows; + int expected_width; + int expected_bitmap_width; + int expected_bitmap_height; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { BARCODE_CODE128, "123456", "7890AB", 0, "A", 0, 1, 46, 92, 118 }, + /* 1*/ { BARCODE_CODE128, "123456", "7890ab", 90, "A", 0, 1, 46, 118, 92 }, + /* 2*/ { BARCODE_CODE128, NULL, NULL, 180, "A", 0, 1, 46, 92, 118 }, + /* 3*/ { BARCODE_CODE128, NULL, NULL, 270, "A", 0, 1, 46, 118, 92 }, + /* 4*/ { BARCODE_CODE128, NULL, NULL, 181, "A", ZINT_ERROR_INVALID_OPTION, -1, -1, -1, -1 }, + /* 5*/ { BARCODE_CODE128, "12345", NULL, 0, "A", ZINT_ERROR_INVALID_OPTION, -1, -1, -1, -1 }, + /* 6*/ { BARCODE_CODE128, NULL, "1234567", 0, "A", ZINT_ERROR_INVALID_OPTION, -1, -1, -1, -1 }, + /* 7*/ { BARCODE_CODE128, "12345 ", NULL, 0, "A", ZINT_ERROR_INVALID_OPTION, -1, -1, -1, -1 }, + /* 8*/ { BARCODE_CODE128, NULL, "EEFFGG", 0, "A", ZINT_ERROR_INVALID_OPTION, -1, -1, -1, -1 }, + }; + int data_size = ARRAY_SIZE(data); + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + int length = testUtilSetSymbol(symbol, BARCODE_CODE128, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + + if (data[i].fgcolour) { + strcpy(symbol->fgcolour, data[i].fgcolour); + } + if (data[i].bgcolour) { + strcpy(symbol->bgcolour, data[i].bgcolour); + } + + ret = ZBarcode_Encode_and_Buffer(symbol, data[i].data, length, data[i].rotate_angle); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (ret < 5) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + assert_equal(symbol->bitmap_width, data[i].expected_bitmap_width, "i:%d symbol->bitmap_width %d != %d\n", i, symbol->bitmap_width, data[i].expected_bitmap_width); + assert_equal(symbol->bitmap_height, data[i].expected_bitmap_height, "i:%d symbol->bitmap_height %d != %d\n", i, symbol->bitmap_height, data[i].expected_bitmap_height); + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + +static void test_buffer(int index, int generate, int debug) { + + testStart(""); + + int ret; + struct item { + int symbology; + unsigned char *data; + char *composite; + + int expected_height; + int expected_rows; + int expected_width; + int expected_bitmap_width; + int expected_bitmap_height; + }; + struct item data[] = { + /* 0*/ { BARCODE_CODE11, "0000000000", "", 50, 1, 99, 198, 118 }, + /* 1*/ { BARCODE_C25MATRIX, "0000000000", "", 50, 1, 117, 234, 118 }, + /* 2*/ { BARCODE_C25INTER, "0000000000", "", 50, 1, 99, 198, 118 }, + /* 3*/ { BARCODE_C25IATA, "0000000000", "", 50, 1, 149, 298, 118 }, + /* 4*/ { BARCODE_C25LOGIC, "0000000000", "", 50, 1, 109, 218, 118 }, + /* 5*/ { BARCODE_C25IND, "0000000000", "", 50, 1, 159, 318, 118 }, + /* 6*/ { BARCODE_CODE39, "0000000000", "", 50, 1, 155, 310, 118 }, + /* 7*/ { BARCODE_EXCODE39, "0000000000", "", 50, 1, 155, 310, 118 }, + /* 8*/ { BARCODE_EANX, "123456789012", "", 50, 1, 95, 230, 118 }, + /* 9*/ { BARCODE_EANX_CHK, "1234567890128", "", 50, 1, 95, 230, 118 }, + /* 10*/ { BARCODE_EAN128, "[01]12345678901234", "", 50, 1, 134, 268, 118 }, + /* 11*/ { BARCODE_CODABAR, "A00000000B", "", 50, 1, 102, 204, 118 }, + /* 12*/ { BARCODE_CODE128, "0000000000", "", 50, 1, 90, 180, 118 }, + /* 13*/ { BARCODE_DPLEIT, "1234567890123", "", 50, 1, 135, 270, 118 }, + /* 14*/ { BARCODE_DPIDENT, "12345678901", "", 50, 1, 117, 234, 118 }, + /* 15*/ { BARCODE_CODE16K, "0000000000", "", 20, 2, 70, 162, 44 }, + /* 16*/ { BARCODE_CODE49, "0000000000", "", 20, 2, 70, 162, 44 }, + /* 17*/ { BARCODE_CODE93, "0000000000", "", 50, 1, 127, 254, 118 }, + /* 18*/ { BARCODE_FLAT, "1234567890", "", 50, 1, 90, 180, 100 }, + /* 19*/ { BARCODE_RSS14, "1234567890123", "", 50, 1, 96, 192, 118 }, + /* 20*/ { BARCODE_RSS_LTD, "1234567890123", "", 50, 1, 74, 148, 118 }, + /* 21*/ { BARCODE_RSS_EXP, "[01]12345678901234", "", 34, 1, 134, 268, 86 }, + /* 22*/ { BARCODE_TELEPEN, "0000000000", "", 50, 1, 208, 416, 118 }, + /* 23*/ { BARCODE_UPCA, "12345678904", "", 50, 1, 95, 230, 118 }, + /* 24*/ { BARCODE_UPCA_CHK, "12345678905", "", 50, 1, 95, 230, 118 }, + /* 25*/ { BARCODE_UPCE, "1234567", "", 50, 1, 51, 142, 118 }, + /* 26*/ { BARCODE_UPCE_CHK, "12345670", "", 50, 1, 51, 142, 118 }, + /* 27*/ { BARCODE_POSTNET, "00000000000", "", 12, 2, 185, 370, 24 }, + /* 28*/ { BARCODE_MSI_PLESSEY, "0000000000", "", 50, 1, 127, 254, 118 }, + /* 29*/ { BARCODE_FIM, "A", "", 50, 1, 17, 34, 100 }, + /* 30*/ { BARCODE_LOGMARS, "0000000000", "", 50, 1, 207, 414, 118 }, + /* 31*/ { BARCODE_PHARMA, "123456", "", 50, 1, 58, 116, 100 }, + /* 32*/ { BARCODE_PZN, "123456", "", 50, 1, 142, 284, 118 }, + /* 33*/ { BARCODE_PHARMA_TWO, "12345678", "", 10, 2, 29, 58, 20 }, + /* 34*/ { BARCODE_PDF417, "0000000000", "", 21, 7, 103, 206, 42 }, + /* 35*/ { BARCODE_PDF417TRUNC, "0000000000", "", 21, 7, 68, 136, 42 }, + /* 36*/ { BARCODE_MAXICODE, "0000000000", "", 165, 33, 30, 300, 300 }, + /* 37*/ { BARCODE_QRCODE, "1234567890AB", "", 21, 21, 21, 42, 42 }, + /* 38*/ { BARCODE_CODE128B, "0000000000", "", 50, 1, 145, 290, 118 }, + /* 39*/ { BARCODE_AUSPOST, "12345678901234567890123", "", 8, 3, 133, 266, 16 }, + /* 40*/ { BARCODE_AUSREPLY, "12345678", "", 8, 3, 73, 146, 16 }, + /* 41*/ { BARCODE_AUSROUTE, "12345678", "", 8, 3, 73, 146, 16 }, + /* 42*/ { BARCODE_AUSREDIRECT, "12345678", "", 8, 3, 73, 146, 16 }, + /* 43*/ { BARCODE_ISBNX, "123456789", "", 50, 1, 95, 230, 118 }, + /* 44*/ { BARCODE_RM4SCC, "0000000000", "", 8, 3, 91, 182, 16 }, + /* 45*/ { BARCODE_DATAMATRIX, "ABC", "", 10, 10, 10, 20, 20 }, + /* 46*/ { BARCODE_EAN14, "1234567890123", "", 50, 1, 134, 268, 118 }, + /* 47*/ { BARCODE_VIN, "00000000000000000", "", 50, 1, 246, 492, 118 }, + /* 48*/ { BARCODE_CODABLOCKF, "0000000000", "", 20, 2, 101, 242, 44 }, + /* 49*/ { BARCODE_NVE18, "12345678901234567", "", 50, 1, 156, 312, 118 }, + /* 50*/ { BARCODE_JAPANPOST, "0000000000", "", 8, 3, 133, 266, 16 }, + /* 51*/ { BARCODE_KOREAPOST, "123456", "", 50, 1, 167, 334, 118 }, + /* 52*/ { BARCODE_RSS14STACK, "0000000000000", "", 13, 3, 50, 100, 26 }, + /* 53*/ { BARCODE_RSS14STACK_OMNI, "0000000000000", "", 69, 5, 50, 100, 138 }, + /* 54*/ { BARCODE_RSS_EXPSTACK, "[01]12345678901234", "", 71, 5, 102, 204, 142 }, + /* 55*/ { BARCODE_PLANET, "00000000000", "", 12, 2, 185, 370, 24 }, + /* 56*/ { BARCODE_MICROPDF417, "0000000000", "", 12, 6, 82, 164, 24 }, + /* 57*/ { BARCODE_ONECODE, "12345678901234567890", "", 8, 3, 129, 258, 16 }, + /* 58*/ { BARCODE_PLESSEY, "0000000000", "", 50, 1, 227, 454, 118 }, + /* 59*/ { BARCODE_TELEPEN_NUM, "0000000000", "", 50, 1, 128, 256, 118 }, + /* 60*/ { BARCODE_ITF14, "0000000000", "", 50, 1, 135, 382, 150 }, + /* 61*/ { BARCODE_KIX, "123456ABCDE", "", 8, 3, 87, 174, 16 }, + /* 62*/ { BARCODE_AZTEC, "1234567890AB", "", 15, 15, 15, 30, 30 }, + /* 63*/ { BARCODE_DAFT, "DAFTDAFTDAFTDAFT", "", 8, 3, 31, 62, 16 }, + /* 64*/ { BARCODE_MICROQR, "12345", "", 11, 11, 11, 22, 22 }, + /* 65*/ { BARCODE_HIBC_128, "0000000000", "", 50, 1, 134, 268, 118 }, + /* 66*/ { BARCODE_HIBC_39, "0000000000", "", 50, 1, 223, 446, 118 }, + /* 67*/ { BARCODE_HIBC_DM, "ABC", "", 12, 12, 12, 24, 24 }, + /* 68*/ { BARCODE_HIBC_QR, "1234567890AB", "", 21, 21, 21, 42, 42 }, + /* 69*/ { BARCODE_HIBC_PDF, "0000000000", "", 27, 9, 103, 206, 54 }, + /* 70*/ { BARCODE_HIBC_MICPDF, "0000000000", "", 34, 17, 38, 76, 68 }, + /* 71*/ { BARCODE_HIBC_BLOCKF, "0000000000", "", 30, 3, 101, 242, 64 }, + /* 72*/ { BARCODE_HIBC_AZTEC, "1234567890AB", "", 19, 19, 19, 38, 38 }, + /* 73*/ { BARCODE_DOTCODE, "ABC", "", 11, 11, 16, 33, 23 }, + /* 74*/ { BARCODE_HANXIN, "1234567890AB", "", 23, 23, 23, 46, 46 }, + /* 75*/ { BARCODE_MAILMARK, "01000000000000000AA00AA0A", "", 10, 3, 155, 310, 20 }, + /* 76*/ { BARCODE_AZRUNE, "255", "", 11, 11, 11, 22, 22 }, + /* 77*/ { BARCODE_CODE32, "12345678", "", 50, 1, 103, 206, 118 }, + /* 78*/ { BARCODE_EANX_CC, "123456789012", "[20]01", 50, 7, 99, 238, 118 }, + /* 79*/ { BARCODE_EAN128_CC, "[01]12345678901234", "[20]01", 50, 5, 145, 290, 118 }, + /* 80*/ { BARCODE_RSS14_CC, "1234567890123", "[20]01", 21, 5, 100, 200, 60 }, + /* 81*/ { BARCODE_RSS_LTD_CC, "1234567890123", "[20]01", 19, 6, 74, 148, 56 }, + /* 82*/ { BARCODE_RSS_EXP_CC, "[01]12345678901234", "[20]01", 41, 5, 134, 268, 100 }, + /* 83*/ { BARCODE_UPCA_CC, "12345678901", "[20]01", 50, 7, 99, 238, 118 }, + /* 84*/ { BARCODE_UPCE_CC, "1234567", "[20]01", 50, 9, 55, 150, 118 }, + /* 85*/ { BARCODE_RSS14STACK_CC, "0000000000000", "[20]01", 24, 9, 56, 112, 48 }, + /* 86*/ { BARCODE_RSS14_OMNI_CC, "0000000000000", "[20]01", 80, 11, 56, 112, 160 }, + /* 87*/ { BARCODE_RSS_EXPSTACK_CC, "[01]12345678901234", "[20]01", 78, 9, 102, 204, 156 }, + /* 88*/ { BARCODE_CHANNEL, "00", "", 50, 1, 19, 38, 118 }, + /* 89*/ { BARCODE_CODEONE, "12345678901234567890", "", 22, 22, 22, 44, 44 }, + /* 90*/ { BARCODE_GRIDMATRIX, "ABC", "", 18, 18, 18, 36, 36 }, + /* 91*/ { BARCODE_UPNQR, "1234567890AB", "", 77, 77, 77, 154, 154 }, + /* 92*/ { BARCODE_ULTRA, "0000000000", "", 13, 13, 18, 36, 26 }, + /* 93*/ { BARCODE_RMQR, "12345", "", 11, 11, 27, 54, 22 }, + }; + int data_size = ARRAY_SIZE(data); + + char *text; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + symbol->symbology = data[i].symbology; + symbol->input_mode = UNICODE_MODE; + symbol->debug |= debug; + + if (strlen(data[i].composite)) { + text = data[i].composite; + strcpy(symbol->primary, data[i].data); + } else { + text = data[i].data; + } + int length = strlen(text); + + ret = ZBarcode_Encode(symbol, text, length); + assert_zero(ret, "i:%d ZBarcode_Encode(%d) ret %d != 0 %s\n", i, data[i].symbology, ret, symbol->errtxt); + + ret = ZBarcode_Buffer(symbol, 0); + assert_zero(ret, "i:%d ZBarcode_Buffer(%d) ret %d != 0\n", i, data[i].symbology, ret); + assert_nonnull(symbol->bitmap, "i:%d ZBarcode_Buffer(%d) bitmap NULL\n", i, data[i].symbology); + + if (generate) { + printf(" /*%3d*/ { %s, \"%s\", \"%s\", %d, %d, %d, %d, %d },\n", + i, testUtilBarcodeName(data[i].symbology), data[i].data, data[i].composite, + symbol->height, symbol->rows, symbol->width, symbol->bitmap_width, symbol->bitmap_height); + } else { + assert_equal(symbol->height, data[i].expected_height, "i:%d (%s) symbol->height %d != %d\n", i, testUtilBarcodeName(data[i].symbology), symbol->height, data[i].expected_height); + assert_equal(symbol->rows, data[i].expected_rows, "i:%d (%s) symbol->rows %d != %d\n", i, testUtilBarcodeName(data[i].symbology), symbol->rows, data[i].expected_rows); + assert_equal(symbol->width, data[i].expected_width, "i:%d (%s) symbol->width %d != %d\n", i, testUtilBarcodeName(data[i].symbology), symbol->width, data[i].expected_width); + assert_equal(symbol->bitmap_width, data[i].expected_bitmap_width, "i:%d (%s) symbol->bitmap_width %d != %d\n", + i, testUtilBarcodeName(data[i].symbology), symbol->bitmap_width, data[i].expected_bitmap_width); + assert_equal(symbol->bitmap_height, data[i].expected_bitmap_height, "i:%d (%s) symbol->bitmap_height %d != %d\n", + i, testUtilBarcodeName(data[i].symbology), symbol->bitmap_height, data[i].expected_bitmap_height); + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + static void test_chk_extendable(int index, int debug) { testStart(""); @@ -116,6 +341,7 @@ static void test_row_separator(int index, int debug) { int ret; struct item { int symbology; + int option_1; int option_3; unsigned char *data; int ret; @@ -131,13 +357,14 @@ static void test_row_separator(int index, int debug) { }; // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { BARCODE_CODABLOCKF, -1, "A", 0, 20, 2, 101, 210, 48, 22, 28, 4 }, // Col 28 TODO: investigate extra 2 compared to vector 26 - /* 1*/ { BARCODE_CODABLOCKF, 0, "A", 0, 20, 2, 101, 210, 48, 22, 28, 4 }, // Same as default - /* 2*/ { BARCODE_CODABLOCKF, 1, "A", 0, 20, 2, 101, 210, 48, 23, 28, 2 }, - /* 3*/ { BARCODE_CODABLOCKF, 2, "A", 0, 20, 2, 101, 210, 48, 22, 28, 4 }, // Same as default - /* 4*/ { BARCODE_CODABLOCKF, 3, "A", 0, 20, 2, 101, 210, 48, 21, 28, 6 }, - /* 5*/ { BARCODE_CODABLOCKF, 4, "A", 0, 20, 2, 101, 210, 48, 20, 28, 8 }, - /* 6*/ { BARCODE_CODABLOCKF, 5, "A", 0, 20, 2, 101, 210, 48, 22, 28, 4 }, // > 4 ignored, same as default + /* 0*/ { BARCODE_CODABLOCKF, -1, -1, "A", 0, 20, 2, 101, 242, 44, 21, 42, 2 }, + /* 1*/ { BARCODE_CODABLOCKF, -1, 0, "A", 0, 20, 2, 101, 242, 44, 21, 42, 2 }, // Same as default + /* 2*/ { BARCODE_CODABLOCKF, -1, 1, "A", 0, 20, 2, 101, 242, 44, 21, 42, 2 }, // Same as default + /* 3*/ { BARCODE_CODABLOCKF, -1, 2, "A", 0, 20, 2, 101, 242, 44, 20, 42, 4 }, + /* 4*/ { BARCODE_CODABLOCKF, -1, 3, "A", 0, 20, 2, 101, 242, 44, 19, 42, 6 }, + /* 5*/ { BARCODE_CODABLOCKF, -1, 4, "A", 0, 20, 2, 101, 242, 44, 18, 42, 8 }, + /* 6*/ { BARCODE_CODABLOCKF, -1, 5, "A", 0, 20, 2, 101, 242, 44, 21, 42, 2 }, // > 4 ignored, same as default + /* 7*/ { BARCODE_CODABLOCKF, 1, -1, "A", 0, 5, 1, 46, 132, 14, 0, 20 + 2, 2 }, // CODE128 top separator, add 2 to skip over end of start char }; int data_size = ARRAY_SIZE(data); @@ -148,7 +375,7 @@ static void test_row_separator(int index, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - int length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); + int length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, data[i].option_1, -1, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode_and_Buffer(symbol, data[i].data, length, 0); assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); @@ -162,17 +389,21 @@ static void test_row_separator(int index, int debug) { int j, separator_bits_set; + //testUtilBitmapPrint(symbol); + for (j = data[i].expected_separator_row; j < data[i].expected_separator_row + data[i].expected_separator_height; j++) { separator_bits_set = is_row_column_black(symbol, j, data[i].expected_separator_col); assert_nonzero(separator_bits_set, "i:%d (%d) separator_bits_set (%d, %d) zero\n", i, data[i].symbology, j, data[i].expected_separator_col); } - j = data[i].expected_separator_row - 1; - separator_bits_set = is_row_column_black(symbol, j, data[i].expected_separator_col); - assert_zero(separator_bits_set, "i:%d (%d) separator_bits_set (%d, %d) before non-zero\n", i, data[i].symbology, j, data[i].expected_separator_col); + if (symbol->rows > 1) { + j = data[i].expected_separator_row - 1; + separator_bits_set = is_row_column_black(symbol, j, data[i].expected_separator_col + 2); // Need to add 2 to skip to 1st blank of start row character + assert_zero(separator_bits_set, "i:%d (%d) separator_bits_set (%d, %d) before non-zero\n", i, data[i].symbology, j, data[i].expected_separator_col); + } j = data[i].expected_separator_row + data[i].expected_separator_height; - separator_bits_set = is_row_column_black(symbol, j, data[i].expected_separator_col); + separator_bits_set = is_row_column_black(symbol, j, data[i].expected_separator_col + 2); // Need to add 2 to skip to 1st blank of start row character assert_zero(separator_bits_set, "i:%d (%d) separator_bits_set (%d, %d) after non-zero\n", i, data[i].symbology, j, data[i].expected_separator_col); ZBarcode_Delete(symbol); @@ -181,11 +412,87 @@ static void test_row_separator(int index, int debug) { testFinish(); } +static void test_draw_string_wrap(int index, int debug) { + + testStart(""); + + int ret; + struct item { + int symbology; + int output_options; + unsigned char *data; + unsigned char* text; + + int expected_height; + int expected_rows; + int expected_width; + int expected_bitmap_width; + int expected_bitmap_height; + int expected_no_text_row; + int expected_no_text_col; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { BARCODE_CODE128, -1, "12", " E", 50, 1, 46, 92, 118, 104, 0 }, + /* 1*/ { BARCODE_CODE128, BOLD_TEXT, "12", " E", 50, 1, 46, 92, 118, 104, 0 }, + /* 2*/ { BARCODE_CODE128, SMALL_TEXT, "12", " E", 50, 1, 46, 92, 118, 103, 0 }, + }; + int data_size = sizeof(data) / sizeof(struct item); + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + int length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, data[i].output_options, data[i].data, -1, debug); + + ret = ZBarcode_Encode(symbol, data[i].data, length); + assert_zero(ret, "i:%d ZBarcode_Encode(%d) ret %d != 0 %s\n", i, data[i].symbology, ret, symbol->errtxt); + + // Cheat by overwriting text + strcpy(symbol->text, data[i].text); + + ret = ZBarcode_Buffer(symbol, 0); + assert_zero(ret, "i:%d ZBarcode_Buffer(%d) ret %d != 0\n", i, data[i].symbology, ret); + assert_nonnull(symbol->bitmap, "i:%d (%d) symbol->bitmap NULL\n", i, data[i].symbology); + + assert_equal(symbol->height, data[i].expected_height, "i:%d (%d) symbol->height %d != %d\n", i, data[i].symbology, symbol->height, data[i].expected_height); + assert_equal(symbol->rows, data[i].expected_rows, "i:%d (%d) symbol->rows %d != %d\n", i, data[i].symbology, symbol->rows, data[i].expected_rows); + assert_equal(symbol->width, data[i].expected_width, "i:%d (%d) symbol->width %d != %d\n", i, data[i].symbology, symbol->width, data[i].expected_width); + assert_equal(symbol->bitmap_width, data[i].expected_bitmap_width, "i:%d (%d) symbol->bitmap_width %d != %d\n", i, data[i].symbology, symbol->bitmap_width, data[i].expected_bitmap_width); + assert_equal(symbol->bitmap_height, data[i].expected_bitmap_height, "i:%d (%d) symbol->bitmap_height %d != %d\n", i, data[i].symbology, symbol->bitmap_height, data[i].expected_bitmap_height); + + //testUtilBitmapPrint(symbol); + + ret = ZBarcode_Print(symbol, 0); + assert_zero(ret, "i:%d ZBarcode_Print(%d) ret %d != 0\n", i, data[i].symbology, ret); + + int text_bits_set = 0; + int row = data[i].expected_no_text_row; + for (int column = data[i].expected_no_text_col; column < data[i].expected_no_text_col + 16; column++) { + if (is_row_column_black(symbol, row, column)) { + text_bits_set = 1; + break; + } + } + assert_zero(text_bits_set, "i:%d (%d) text_bits_set non-zero\n", i, data[i].symbology); + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ + { "test_options", test_options, 1, 0, 1 }, + { "test_buffer", test_buffer, 1, 1, 1 }, { "test_chk_extendable", test_chk_extendable, 1, 0, 1 }, { "test_row_separator", test_row_separator, 1, 0, 1 }, + { "test_draw_string_wrap", test_draw_string_wrap, 1, 0, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_vector.c b/backend/tests/test_vector.c index ef0b2fd5..ab495c5b 100644 --- a/backend/tests/test_vector.c +++ b/backend/tests/test_vector.c @@ -60,6 +60,67 @@ static struct zint_vector_rect *find_rect(struct zint_symbol *symbol, int x, int return rect; } +static void test_options(int index, int debug) { + + testStart(""); + + int ret; + struct item { + int symbology; + char *fgcolour; + char *bgcolour; + int rotate_angle; + unsigned char *data; + int ret; + int expected_rows; + int expected_width; + float expected_vector_width; + float expected_vector_height; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { BARCODE_CODE128, "123456", "7890ab", 0, "A", 0, 1, 46, 92, 118 }, + /* 1*/ { BARCODE_CODE128, "12345", NULL, 0, "A", ZINT_ERROR_INVALID_OPTION, -1, -1, -1, -1 }, + /* 2*/ { BARCODE_CODE128, NULL, "1234567", 0, "A", ZINT_ERROR_INVALID_OPTION, -1, -1, -1, -1 }, + /* 3*/ { BARCODE_CODE128, "12345 ", NULL, 0, "A", ZINT_ERROR_INVALID_OPTION, -1, -1, -1, -1 }, + /* 4*/ { BARCODE_CODE128, NULL, "EEFFGG", 0, "A", ZINT_ERROR_INVALID_OPTION, -1, -1, -1, -1 }, + }; + int data_size = ARRAY_SIZE(data); + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + int length = testUtilSetSymbol(symbol, BARCODE_CODE128, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); + + if (data[i].fgcolour) { + strcpy(symbol->fgcolour, data[i].fgcolour); + } + if (data[i].bgcolour) { + strcpy(symbol->bgcolour, data[i].bgcolour); + } + + ret = ZBarcode_Encode_and_Buffer_Vector(symbol, data[i].data, length, data[i].rotate_angle); + assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); + + if (ret < 5) { + assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); + assert_equal(symbol->width, data[i].expected_width, "i:%d symbol->width %d != %d (%s)\n", i, symbol->width, data[i].expected_width, data[i].data); + assert_equal(symbol->vector->width, data[i].expected_vector_width, "i:%d (%s) symbol->vector->width %f != %f\n", + i, testUtilBarcodeName(data[i].symbology), symbol->vector->width, data[i].expected_vector_width); + assert_equal(symbol->vector->height, data[i].expected_vector_height, "i:%d (%s) symbol->vector->height %f != %f\n", + i, testUtilBarcodeName(data[i].symbology), symbol->vector->height, data[i].expected_vector_height); + } + + ZBarcode_Delete(symbol); + } + + testFinish(); +} + static void test_buffer_vector(int index, int generate, int debug) { testStart(""); @@ -92,8 +153,8 @@ static void test_buffer_vector(int index, int generate, int debug) { /* 12*/ { BARCODE_CODE128, "0000000000", "", 50, 1, 90, 180.0, 118.0 }, /* 13*/ { BARCODE_DPLEIT, "1234567890123", "", 50, 1, 135, 270.0, 118.0 }, /* 14*/ { BARCODE_DPIDENT, "12345678901", "", 50, 1, 117, 234.0, 118.0 }, - /* 15*/ { BARCODE_CODE16K, "0000000000", "", 20, 2, 70, 212.0, 48.0 }, - /* 16*/ { BARCODE_CODE49, "0000000000", "", 20, 2, 70, 188.0, 48.0 }, + /* 15*/ { BARCODE_CODE16K, "0000000000", "", 20, 2, 70, 162.0, 44.0 }, + /* 16*/ { BARCODE_CODE49, "0000000000", "", 20, 2, 70, 162.0, 44.0 }, /* 17*/ { BARCODE_CODE93, "0000000000", "", 50, 1, 127, 254.0, 118.0 }, /* 18*/ { BARCODE_FLAT, "1234567890", "", 50, 1, 90, 180.0, 100.0 }, /* 19*/ { BARCODE_RSS14, "1234567890123", "", 50, 1, 96, 192.0, 118.0 }, @@ -125,7 +186,7 @@ static void test_buffer_vector(int index, int generate, int debug) { /* 45*/ { BARCODE_DATAMATRIX, "ABC", "", 10, 10, 10, 20.0, 20.0 }, /* 46*/ { BARCODE_EAN14, "1234567890123", "", 50, 1, 134, 268.0, 118.0 }, /* 47*/ { BARCODE_VIN, "00000000000000000", "", 50, 1, 246, 492.0, 118.0 }, - /* 48*/ { BARCODE_CODABLOCKF, "0000000000", "", 20, 2, 101, 210.0, 48.0 }, + /* 48*/ { BARCODE_CODABLOCKF, "0000000000", "", 20, 2, 101, 242.0, 44.0 }, /* 49*/ { BARCODE_NVE18, "12345678901234567", "", 50, 1, 156, 312.0, 118.0 }, /* 50*/ { BARCODE_JAPANPOST, "0000000000", "", 8, 3, 133, 266.0, 16.0 }, /* 51*/ { BARCODE_KOREAPOST, "123456", "", 50, 1, 167, 334.0, 118.0 }, @@ -148,7 +209,7 @@ static void test_buffer_vector(int index, int generate, int debug) { /* 68*/ { BARCODE_HIBC_QR, "1234567890AB", "", 21, 21, 21, 42.0, 42.0 }, /* 69*/ { BARCODE_HIBC_PDF, "0000000000", "", 27, 9, 103, 206.0, 54.0 }, /* 70*/ { BARCODE_HIBC_MICPDF, "0000000000", "", 34, 17, 38, 76.0, 68.0 }, - /* 71*/ { BARCODE_HIBC_BLOCKF, "0000000000", "", 30, 3, 101, 210.0, 68.0 }, + /* 71*/ { BARCODE_HIBC_BLOCKF, "0000000000", "", 30, 3, 101, 242.0, 64.0 }, /* 72*/ { BARCODE_HIBC_AZTEC, "1234567890AB", "", 19, 19, 19, 38.0, 38.0 }, /* 73*/ { BARCODE_DOTCODE, "ABC", "", 11, 11, 16, 32.0, 22.0 }, /* 74*/ { BARCODE_HANXIN, "1234567890AB", "", 23, 23, 23, 46.0, 46.0 }, @@ -169,7 +230,8 @@ static void test_buffer_vector(int index, int generate, int debug) { /* 89*/ { BARCODE_CODEONE, "12345678901234567890", "", 22, 22, 22, 44.0, 44.0 }, /* 90*/ { BARCODE_GRIDMATRIX, "ABC", "", 18, 18, 18, 36.0, 36.0 }, /* 91*/ { BARCODE_UPNQR, "1234567890AB", "", 77, 77, 77, 154.0, 154.0 }, - /* 92*/ { BARCODE_RMQR, "12345", "", 11, 11, 27, 54.0, 22.0 }, + /* 92*/ { BARCODE_ULTRA, "0000000000", "", 13, 13, 18, 36.0, 26.0 }, + /* 93*/ { BARCODE_RMQR, "12345", "", 11, 11, 27, 54.0, 22.0 }, }; int data_size = sizeof(data) / sizeof(struct item); @@ -347,6 +409,7 @@ static void test_row_separator(int index, int debug) { int ret; struct item { int symbology; + int option_1; int option_3; unsigned char *data; int ret; @@ -360,13 +423,14 @@ static void test_row_separator(int index, int debug) { }; // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { BARCODE_CODABLOCKF, -1, "A", 0, 20, 2, 101, 22, 26, 4 }, - /* 1*/ { BARCODE_CODABLOCKF, 0, "A", 0, 20, 2, 101, 22, 26, 4 }, // Same as default - /* 2*/ { BARCODE_CODABLOCKF, 1, "A", 0, 20, 2, 101, 23, 26, 2 }, - /* 3*/ { BARCODE_CODABLOCKF, 2, "A", 0, 20, 2, 101, 22, 26, 4 }, // Same as default - /* 4*/ { BARCODE_CODABLOCKF, 3, "A", 0, 20, 2, 101, 21, 26, 6 }, - /* 5*/ { BARCODE_CODABLOCKF, 4, "A", 0, 20, 2, 101, 20, 26, 8 }, - /* 6*/ { BARCODE_CODABLOCKF, 5, "A", 0, 20, 2, 101, 22, 26, 4 }, // > 4 ignored, same as default + /* 0*/ { BARCODE_CODABLOCKF, -1, -1, "A", 0, 20, 2, 101, 21, 42, 2 }, + /* 1*/ { BARCODE_CODABLOCKF, -1, 0, "A", 0, 20, 2, 101, 21, 42, 2 }, // Same as default + /* 2*/ { BARCODE_CODABLOCKF, -1, 1, "A", 0, 20, 2, 101, 21, 42, 2 }, // Same as default + /* 3*/ { BARCODE_CODABLOCKF, -1, 2, "A", 0, 20, 2, 101, 20, 42, 4 }, + /* 4*/ { BARCODE_CODABLOCKF, -1, 3, "A", 0, 20, 2, 101, 19, 42, 6 }, + /* 5*/ { BARCODE_CODABLOCKF, -1, 4, "A", 0, 20, 2, 101, 18, 42, 8 }, + /* 6*/ { BARCODE_CODABLOCKF, -1, 5, "A", 0, 20, 2, 101, 21, 42, 2 }, // > 4 ignored, same as default + /* 7*/ { BARCODE_CODABLOCKF, 1, -1, "A", 0, 5, 1, 46, 0, 20, 2 }, // CODE128 top separator }; int data_size = ARRAY_SIZE(data); @@ -379,7 +443,7 @@ static void test_row_separator(int index, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - int length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); + int length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*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, data[i].data, length); assert_zero(ret, "i:%d ZBarcode_Encode(%d) ret %d != 0 %s\n", i, data[i].symbology, ret, symbol->errtxt); @@ -404,6 +468,7 @@ static void test_row_separator(int index, int debug) { int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ + { "test_options", test_options, 1, 0, 1 }, { "test_buffer_vector", test_buffer_vector, 1, 1, 1 }, { "test_noncomposite_string_x", test_noncomposite_string_x, 1, 0, 1 }, { "test_upcean_whitespace_width", test_upcean_whitespace_width, 1, 0, 1 }, diff --git a/backend/tests/testcommon.c b/backend/tests/testcommon.c index daa96d13..635f7bb9 100644 --- a/backend/tests/testcommon.c +++ b/backend/tests/testcommon.c @@ -490,6 +490,53 @@ char *testUtilOption3Name(int option_3) { return "-1"; } +char *testUtilOutputOptionsName(int output_options) { + static char buf[512]; + + struct item { + char *name; + int define; + int val; + }; + struct item data[] = { + { "BARCODE_NO_ASCII", BARCODE_NO_ASCII, 1 }, + { "BARCODE_BIND", BARCODE_BIND, 2 }, + { "BARCODE_BOX", BARCODE_BOX, 4 }, + { "BARCODE_STDOUT", BARCODE_STDOUT, 8 }, + { "READER_INIT", READER_INIT, 16 }, + { "SMALL_TEXT", SMALL_TEXT, 32 }, + { "BOLD_TEXT", BOLD_TEXT, 64 }, + { "CMYK_COLOUR", CMYK_COLOUR, 128 }, + { "BARCODE_DOTTY_MODE", BARCODE_DOTTY_MODE, 256 }, + { "GS1_GS_SEPARATOR", GS1_GS_SEPARATOR, 512 }, + }; + int data_size = ARRAY_SIZE(data); + int set = 0; + int i; + + if (output_options == -1) { + return "-1"; + } + if (output_options == 0) { + return "0"; + } + buf[0] = '\0'; + for (i = 0; i < data_size; i++) { + if (data[i].define != data[i].val) { // Self-check + fprintf(stderr, "testUtilOutputOptionsName data table out of sync (%d)\n", i); + abort(); + } + if (output_options & data[i].define) { + if (set) { + strcat(buf, " | "); + } + strcat(buf, data[i].name); + set = 1; + } + } + return buf; +} + int testUtilDAFTConvert(const struct zint_symbol *symbol, char *buffer, int buffer_size) { buffer[0] = '\0'; char *b = buffer; @@ -911,6 +958,33 @@ int testUtilModulesDumpHex(const struct zint_symbol *symbol, char dump[], int du return d - dump; } +void testUtilBitmapPrint(const struct zint_symbol *symbol) { + static char colour[] = { '0', 'C', 'B', 'M', 'R', 'Y', 'G', '1' }; + int row, column, i, j; + + fputs(" ", stdout); + for (column = 0; column < symbol->bitmap_width; column += 10) printf("%-3d ", column); + fputs("\n ", stdout); + for (column = 0; column < symbol->bitmap_width; column++) printf("%d", column % 10); + putchar('\n'); + + for (row = 0; row < symbol->bitmap_height; row++) { + printf("%3d: ", row); + for (column = 0; column < symbol->bitmap_width; column++) { + i = ((row * symbol->bitmap_width) + column) * 3; + j = (symbol->bitmap[i] == 0) + (symbol->bitmap[i + 1] == 0) * 2 + (symbol->bitmap[i + 2] == 0) * 4; + putchar(colour[j]); + } + putchar('\n'); + } + + fputs(" ", stdout); + for (column = 0; column < symbol->bitmap_width; column++) printf("%d", column % 10); + fputs("\n ", stdout); + for (column = 0; column < symbol->bitmap_width; column += 10) printf("%-3d ", column); + putchar('\n'); +} + int testUtilExists(char *filename) { FILE *fp = fopen(filename, "r"); if (fp == NULL) { diff --git a/backend/tests/testcommon.h b/backend/tests/testcommon.h index 6d642dc2..cb697887 100644 --- a/backend/tests/testcommon.h +++ b/backend/tests/testcommon.h @@ -77,6 +77,7 @@ char *testUtilBarcodeName(int symbology); char *testUtilErrorName(int error_number); char *testUtilInputModeName(int input_mode); char *testUtilOption3Name(int option_3); +char *testUtilOutputOptionsName(int output_options); int testUtilDAFTConvert(const struct zint_symbol *symbol, char *buffer, int buffer_size); char *testUtilEscape(char *buffer, int length, char *escaped, int escaped_size); char *testUtilReadCSVField(char *buffer, char *field, int field_size); @@ -88,6 +89,7 @@ void testUtilLargeDump(const char *name, const short reg[]); void testUtilModulesDump(const struct zint_symbol *symbol, char *prefix, char *postfix); int testUtilModulesCmp(const struct zint_symbol *symbol, const char *expected, int *row, int *width); int testUtilModulesDumpHex(const struct zint_symbol *symbol, char dump[], int dump_size); +void testUtilBitmapPrint(const struct zint_symbol *symbol); int testUtilExists(char *filename); int testUtilCmpPngs(char *file1, char *file2); int testUtilCmpTxts(char *txt1, char *txt2); diff --git a/backend/vector.c b/backend/vector.c index a341ae07..0af880a8 100644 --- a/backend/vector.c +++ b/backend/vector.c @@ -39,8 +39,7 @@ #endif #include "common.h" - -#define SSET "0123456789ABCDEF" +#include "output.h" INTERNAL int ps_plot(struct zint_symbol *symbol); INTERNAL int svg_plot(struct zint_symbol *symbol); @@ -281,6 +280,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ float textpos, large_bar_height, preset_height, row_height, row_posn = 0.0; float text_offset, text_height; int xoffset, yoffset, textdone, main_symbol_width_x; + int roffset, boffset; char addon[6]; int large_bar_count, symbol_lead_in; float addon_text_posn; @@ -295,26 +295,9 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ (void)rotate_angle; /* Not currently implemented */ // Sanity check colours - to_upper((unsigned char*) symbol->fgcolour); - to_upper((unsigned char*) symbol->bgcolour); - - if (strlen(symbol->fgcolour) != 6) { - strcpy(symbol->errtxt, "661: Malformed foreground colour target"); - return ZINT_ERROR_INVALID_OPTION; - } - if (strlen(symbol->bgcolour) != 6) { - strcpy(symbol->errtxt, "662: Malformed background colour target"); - return ZINT_ERROR_INVALID_OPTION; - } - error_number = is_sane(SSET, (unsigned char*) symbol->fgcolour, strlen(symbol->fgcolour)); - if (error_number == ZINT_ERROR_INVALID_DATA) { - strcpy(symbol->errtxt, "663: Malformed foreground colour target"); - return ZINT_ERROR_INVALID_OPTION; - } - error_number = is_sane(SSET, (unsigned char*) symbol->bgcolour, strlen(symbol->bgcolour)); - if (error_number == ZINT_ERROR_INVALID_DATA) { - strcpy(symbol->errtxt, "664: Malformed background colour target"); - return ZINT_ERROR_INVALID_OPTION; + error_number = check_colour_options(symbol); + if (error_number != 0) { + return error_number; } // Free any previous rendering structures @@ -330,7 +313,6 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ row_height = 0; textdone = 0; - textpos = 0.0; main_symbol_width_x = symbol->width; strcpy(addon, ""); symbol_lead_in = 0; @@ -421,9 +403,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ if (symbol->output_options & SMALL_TEXT) text_height *= 0.8f; - xoffset = symbol->border_width + symbol->whitespace_width; - yoffset = symbol->border_width; - + set_whitespace_offsets(symbol, &xoffset, &yoffset, &roffset, &boffset); // Determine if height should be overridden large_bar_count = 0; @@ -435,8 +415,8 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ } } - vector->width = (float)ceil(symbol->width + (2.0f * xoffset)); - vector->height = (float)ceil(symbol->height + text_offset + (2.0f * yoffset)); + vector->width = (float)ceil(symbol->width + (xoffset + roffset)); + vector->height = (float)ceil(symbol->height + text_offset + (yoffset + boffset)); large_bar_height = large_bar_count ? (symbol->height - preset_height) / large_bar_count : 0 /*Not used if large_bar_count zero*/; @@ -467,11 +447,6 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ row_posn += yoffset; i = 0; - if (module_is_set(symbol, this_row, 0)) { - latch = 1; - } else { - latch = 0; - } do { int block_width = 0; @@ -504,8 +479,8 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ // Plot Maxicode symbols if (symbol->symbology == BARCODE_MAXICODE) { struct zint_vector_circle *circle; - vector->width = 37.0f + (2.0f * xoffset); - vector->height = 36.0f + (2.0f * yoffset); + vector->width = 37.0f + (xoffset + roffset); + vector->height = 36.0f + (yoffset + boffset); // Bullseye circle = vector_plot_create_circle(17.88f + xoffset, 17.8f + yoffset, 10.85f, 0); @@ -785,8 +760,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ // Binding and boxes if ((symbol->output_options & BARCODE_BIND) != 0) { if ((symbol->rows > 1) && (is_stackable(symbol->symbology) == 1)) { - double sep_height = 2; - + double sep_height = 1; if (symbol->option_3 > 0 && symbol->option_3 <= 4) { sep_height = symbol->option_3; } @@ -796,8 +770,8 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ rectangle = vector_plot_create_rect((float)xoffset, (r * row_height) + yoffset - sep_height / 2, (float)symbol->width, sep_height); vector_plot_add_rect(symbol, rectangle, &last_rectangle); } else { - /* Avoid 11-module start and stop chars */ - rectangle = vector_plot_create_rect(xoffset + 11, (r * row_height) + yoffset - sep_height / 2, symbol->width - 22, sep_height); + /* Avoid 11-module start and 13-module stop chars */ + rectangle = vector_plot_create_rect(xoffset + 11, (r * row_height) + yoffset - sep_height / 2, symbol->width - 24, sep_height); vector_plot_add_rect(symbol, rectangle, &last_rectangle); } } @@ -806,14 +780,14 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ if ((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND)) { // Top rectangle = vector_plot_create_rect(0.0f, 0.0f, vector->width, (float)symbol->border_width); - if (symbol->symbology == BARCODE_CODABLOCKF || symbol->symbology == BARCODE_HIBC_BLOCKF) { + if (!(symbol->output_options & BARCODE_BOX) && (symbol->symbology == BARCODE_CODABLOCKF || symbol->symbology == BARCODE_HIBC_BLOCKF)) { rectangle->x = (float)xoffset; rectangle->width -= (2.0f * xoffset); } vector_plot_add_rect(symbol, rectangle, &last_rectangle); // Bottom rectangle = vector_plot_create_rect(0.0f, vector->height - symbol->border_width - text_offset, vector->width, (float)symbol->border_width); - if (symbol->symbology == BARCODE_CODABLOCKF || symbol->symbology == BARCODE_HIBC_BLOCKF) { + if (!(symbol->output_options & BARCODE_BOX) && (symbol->symbology == BARCODE_CODABLOCKF || symbol->symbology == BARCODE_HIBC_BLOCKF)) { rectangle->x = (float)xoffset; rectangle->width -= (2.0f * xoffset); } @@ -846,5 +820,4 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_ } return error_number; - } diff --git a/backend_qt/backend_qt.pro b/backend_qt/backend_qt.pro index 3cc6b13d..81009497 100644 --- a/backend_qt/backend_qt.pro +++ b/backend_qt/backend_qt.pro @@ -54,6 +54,7 @@ SOURCES += qrencode/bitstream.c \ HEADERS += ../backend/aztec.h \ ../backend/bmp.h \ + ../backend/code128.h \ ../backend/code49.h \ ../backend/common.h \ ../backend/composite.h \ @@ -67,6 +68,7 @@ HEADERS += ../backend/aztec.h \ ../backend/hanxin.h \ ../backend/large.h \ ../backend/maxicode.h \ + ../backend/output.h \ ../backend/pcx.h \ ../backend/pdf417.h \ ../backend/reedsol.h \ @@ -104,6 +106,7 @@ SOURCES += ../backend/2of5.c \ ../backend/mailmark.c \ ../backend/maxicode.c \ ../backend/medical.c \ + ../backend/output.c \ ../backend/pcx.c \ ../backend/pdf417.c \ ../backend/plessey.c \ diff --git a/backend_tcl/configure.in b/backend_tcl/configure.in index fc99baf0..a9a78663 100644 --- a/backend_tcl/configure.in +++ b/backend_tcl/configure.in @@ -97,6 +97,7 @@ TEA_ADD_SOURCES([ ../backend/mailmark.c ../backend/maxicode.c ../backend/medical.c + ../backend/output.c ../backend/pcx.c ../backend/pdf417.c ../backend/plessey.c diff --git a/backend_tcl/zint_tcl.dsp b/backend_tcl/zint_tcl.dsp index bdabcac9..aac19eff 100644 --- a/backend_tcl/zint_tcl.dsp +++ b/backend_tcl/zint_tcl.dsp @@ -208,6 +208,10 @@ SOURCE=..\backend\medical.c # End Source File # Begin Source File +SOURCE=..\backend\output.c +# End Source File +# Begin Source File + SOURCE=..\backend\pcx.c # End Source File # Begin Source File diff --git a/docs/manual.txt b/docs/manual.txt index 4613d4cf..1b79b81c 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -49,11 +49,11 @@ matrix: A matrix symbol is one based on a (usually square) grid of elements. Examples include Data Matrix, but Maxicode and DotCode are also considered matrix symbologies. -x-dimension: The x-dimension of a symbol is size (usually the width) of the +X-dimension: The X-dimension of a symbol is size (usually the width) of the smallest element. For a linear symbology this is the width of the - smallest bar. The default size of the x-dimension in a raster image + smallest bar. The default size of the X-dimension in a raster image is 2 pixels. Many symbologies have a fixed width-to-height ratio where - the height is expressed as a multiple of the x-dimension. + the height is expressed as a multiple of the X-dimension. 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 @@ -211,6 +211,7 @@ Escape Character | ASCII Equivalent | Interpretation \e | 0x1B | Escape \G | 0x1D | Group Selector \R | 0x1E | Record Selector +\\ | 0x5C | Backslash \xNN | 0xNN | Any other 8-bit character | | where NN is hexadecimal -------------------------------------------------------------------- @@ -411,8 +412,8 @@ with raster image (PNG, BMP, GIF and PCX) output. 4.9 Adjusting image size ------------------------ The scale of the image can be altered using the --scale= option followed by a -multiple of the default x-dimension. The default x-dimension is 2 pixels. For -example for PNG images a scale of 5 will increase the x-dimension to 10 pixels. +multiple of the default X-dimension. The default X-dimension is 2 pixels. For +example for PNG images a scale of 5 will increase the X-dimension to 10 pixels. 4.10 Input modes ---------------- @@ -451,7 +452,7 @@ 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 characters, however some decoders take blocks which are encoded this way and interpret them as Kanji characters, typically by applying a -transformation to UTF8 and thus causing data corruption. Symbols encoded +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. @@ -517,8 +518,8 @@ ECI Code | Character Encoding Scheme Three examples: Ex1: The Euro sign can be encoded in ISO-8859-15. -The Euro-Sign has the ISO8859-15 codepoint hex A4. -It is encoded in utf-8 as the hex sequence: e2 82 ac +The Euro-Sign has the ISO-8859-15 codepoint hex A4. +It is encoded in UTF-8 as the hex sequence: e2 82 ac Those 3 bytes are contained in the file "utf8euro.txt" This command will generate the corresponding code: @@ -626,7 +627,7 @@ Matrix codes can be rendered as a series of dots or circles rather than the normal squares by using the --dotty option. This option is only available for matrix symbologies, and is automatically selected for DotCode. The size of the dots can be adjusted using the --dotsize= option followed by the radius -of the dot, where that radius is given as a multiple of the x-dimension. +of the dot, where that radius is given as a multiple of the X-dimension. 4.15 Help options ----------------- @@ -817,7 +818,7 @@ whitespace_width | integer | Whtespace width. | 0 border_width | integer | Border width. | 0 output_options | integer | Set various output file | (none) | | parameters (see section | - | | 5.8). [2] | + | | 5.8). | fgcolour | character | Foreground (ink) colour as | "000000" | string | RGB hexadecimal string. | | | Must be 6 characters | @@ -832,7 +833,8 @@ outfile | character | Contains the name of the | "out.png" | string | file to output a result- | | | ing barcode symbol to. | | | Must end in .png, .gif, | - | | .eps, .pcx, .svg or .txt | + | | .bmp, .emf, .eps, .pcx, | + | | .svg, .tif or .txt | option_1 | integer | Symbol specific options. | (automatic) option_2 | integer | Symbol specific options. | (automatic) option_3 | integer | Symbol specific options. | (automatic) @@ -840,8 +842,8 @@ scale | float | Scale factor for adjusting | 1.0 | | size of image. | input_mode | integer | Set encoding of input data | UNICODE_MODE | | (see section 5.9) | -eci | integer | Extended Channel Interpre- | 3 - | | tation mode. | +eci | integer | Extended Channel Interpre- | 0 (none) + | | tation code. | primary | character | Primary message data for | NULL | string | more complex symbols. | text | unsigned | Human readable text, which | NULL @@ -1084,10 +1086,10 @@ Value | 5.8 Adjusting other output options ---------------------------------- The output_options variable can be used to adjust various aspects of the output -file. To select more than one option from the table below simply add them +file. To select more than one option from the table below simply or them together when adjusting this value: -my_symbol->output_options += BARCODE_BIND + READER_INIT; +my_symbol->output_options |= BARCODE_BIND | READER_INIT; -------------------------------------------------------------------------------- Value | Effect @@ -1104,7 +1106,7 @@ BOLD_TEXT | Embolden the human readable text. CMYK_COLOUR | Select the CMYK colour space option for encapsulated | PostScript files. BARCODE_DOTTY_MODE | Plot a matrix symbol using dots rather than squares. -GS1_GS_SEPARATOR | Use GS instead FNC1 as GS1 separator. +GS1_GS_SEPARATOR | Use GS instead FNC1 as GS1 separator (Data Matrix). -------------------------------------------------------------------------------- 5.9 Setting the Input Mode @@ -1546,11 +1548,11 @@ error = ZBarcode_Encode(my_symbol, "That"); error = ZBarcode_Print(my_symbol); The stacked barcode rows can be separated by row separator bars by specifying ---bind (output_options |= BARCODE_BIND). The height of the row separator bars -in x-dimension multiples (default 2, minimum 1, maximum 4) can be set by +--bind (output_options |= BARCODE_BIND). The height of the row separator bars in +multiples of the X-dimension (minimum and default 1, maximum 4) can be set by --separator= (option_3): -zind --bind --separator=1 -d 'This' -d 'That' +zind --bind --separator=2 -d 'This' -d 'That' A more sophisticated method is to use some type of line indexing which indicates to the barcode reader which order the symbols should be read. This is @@ -1919,9 +1921,9 @@ Input | Symbol Size DMRE symbol sizes may be activated in automatic size mode using the option --dmre or by the API option_3 = DM_DMRE -GS1 symbology may use FNC1 (preferred) or GS as separator. +GS1 data may be encoded using FNC1 (preferred) or GS as separator. Use the option --gssep to change to GS or use the API -output_options+=GS1_GS_SEPARATOR +output_options |= GS1_GS_SEPARATOR 6.6.2 QR Code (ISO 18004) ------------------------- diff --git a/frontend/main.c b/frontend/main.c index 969b9952..174737ff 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -37,7 +37,7 @@ #endif /* Print list of supported symbologies */ -void types(void) { +static void types(void) { printf( " 1: Code 11 52: PZN 97: Micro QR Code\n" " 2: Standard 2of5 53: Pharma Two-Track 98: HIBC Code 128\n" " 3: Interleaved 2of5 55: PDF417 99: HIBC Code 39\n" @@ -74,16 +74,16 @@ void types(void) { } /* Output usage information */ -void usage(void) { +static void usage(void) { printf( "Zint version %d.%d.%d\n" - "Encode input data in a barcode and save as BMP/EMF/EPS/GIF/PCX/PNG/SVG/TIF\n\n" + "Encode input data in a barcode and save as BMP/EMF/EPS/GIF/PCX/PNG/SVG/TIF/TXT\n\n" " -b, --barcode=NUMBER Number of barcode type (default is 20 (=Code128)).\n" " --batch Treat each line of input file as a separate data set\n" " --bg=COLOUR Specify a background colour (in hex)\n" " --binary Treat input as raw binary data\n" " --bind Add boundary bars\n" " --bold Use bold text\n" - " --border=NUMBER Set width of border in multiples of x-dimension\n" + " --border=NUMBER Set width of border in multiples of X-dimension\n" " --box Add a box around the symbol\n" " --cmyk Use CMYK colour space in EPS symbols\n" " --cols=NUMBER Set the number of data columns in symbol\n" @@ -94,15 +94,15 @@ void usage(void) { " --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 mode for raw data\n" + " --eci=NUMBER Set the ECI (Extended Channel Interpretation) code\n" " --esc Process escape characters in input data\n" " --fg=COLOUR Specify a foreground colour (in hex)\n" - " --filetype=TYPE Set output file type (PNG/EPS/SVG/PNG/EPS/GIF/TXT)\n" + " --filetype=TYPE Set output file type BMP/EMF/EPS/GIF/PCX/PNG/SVG/TIF/TXT\n" " --fullmultibyte Use multibyte for binary/Latin (QR/Han Xin/Grid Matrix)\n" " --gs1 Treat input as GS1 compatible data\n" - " --gssep Use separator GS for GS1\n" + " --gssep Use separator GS for GS1 (Data Matrix)\n" " -h, --help Display help message\n" - " --height=NUMBER Set height of symbol in multiples of x-dimension\n" + " --height=NUMBER Set height of symbol in multiples of X-dimension\n" " -i, --input=FILE Read input data from FILE\n" " --init Create reader initialisation/programming symbol\n" " --mirror Use batch data to determine filename\n" @@ -110,22 +110,22 @@ void usage(void) { " --notext Remove human readable text\n" " -o, --output=FILE Send output to FILE. (default is out.png)\n" " --primary=STRING Set structured primary message (Maxicode/Composite)\n" - " --scale=NUMBER Adjust size of x-dimension\n" + " --scale=NUMBER Adjust size of X-dimension\n" " --secure=NUMBER Set error correction level\n" " --separator=NUMBER Set height of row separator bars (stacked symbologies)\n" - " --small Use half-size text in PNG images\n" + " --small Use small text\n" " --square Force Data Matrix symbols to be square\n" " -r, --reverse Reverse colours (white on black)\n" - " --rotate=NUMBER Rotate symbol by NUMBER degrees (PNG/BMP/PCX)\n" + " --rotate=NUMBER Rotate symbol by NUMBER degrees (BMP/GIF/PCX/PNG/TIF)\n" " --rows=NUMBER Set number of rows (Codablock-F)\n" " -t, --types Display table of barcode types\n" " --vers=NUMBER Set symbol version (QR Code/Han Xin)\n" - " -w, --whitesp=NUMBER Set Width of whitespace in multiples of x-dimension\n" + " -w, --whitesp=NUMBER Set width of whitespace in multiples of X-dimension\n" , ZINT_VERSION_MAJOR, ZINT_VERSION_MINOR, ZINT_VERSION_RELEASE); } /* Display supported ECI codes */ -void show_eci(void) { +static void show_eci(void) { printf( " 3: ISO-8859-1 - Latin alphabet No. 1 (default)\n" " 4: ISO-8859-2 - Latin alphabet No. 2\n" " 5: ISO-8859-3 - Latin alphabet No. 3\n" @@ -157,7 +157,7 @@ void show_eci(void) { } /* Verifies that a string only uses valid characters */ -int validator(char test_string[], char source[]) { +static int validator(char test_string[], char source[]) { unsigned int i, j; for (i = 0; i < strlen(source); i++) { @@ -195,7 +195,7 @@ static void concat(char dest[], char source[]) { } } -int batch_process(struct zint_symbol *symbol, char *filename, int mirror_mode, char *filetype, int rotate_angle) { +static int batch_process(struct zint_symbol *symbol, char *filename, int mirror_mode, char *filetype, int rotate_angle) { FILE *file; unsigned char buffer[7100]; unsigned char character = 0; @@ -381,7 +381,7 @@ int batch_process(struct zint_symbol *symbol, char *filename, int mirror_mode, c return error_number; } -int is_fullmultibyte(struct zint_symbol* symbol) { +static int is_fullmultibyte(struct zint_symbol* symbol) { switch (symbol->symbology) { case BARCODE_QRCODE: case BARCODE_MICROQR: @@ -578,6 +578,11 @@ int main(int argc, char **argv) { } } if (!strcmp(long_options[option_index].name, "separator")) { + error_number = validator(NESET, optarg); + if (error_number == ZINT_ERROR_INVALID_DATA) { + fprintf(stderr, "Error 128: Invalid separator value\n"); + exit(1); + } separator = atoi(optarg); if (separator < 0 || separator > 4) { /* Negative and greater than 4 values are not permitted */ diff --git a/frontend_qt/grpC16k.ui b/frontend_qt/grpC16k.ui index 6330d46b..c57dd0d1 100644 --- a/frontend_qt/grpC16k.ui +++ b/frontend_qt/grpC16k.ui @@ -17,24 +17,70 @@ - + - S&tandard Mode + Row Separator Height: - - true + + cmbC16kRowSepHeight - - - - &GS-1 Data Mode - + + + + + Default (1 X) + + + + + 2 X + + + + + 3 X + + + + + 4 X + + + + + + Encoding Mode + + + + QLayout::SetMinimumSize + + + + + S&tandard Mode + + + true + + + + + + + &GS-1 Data Mode + + + + + + diff --git a/frontend_qt/grpC49.ui b/frontend_qt/grpC49.ui index abea4f22..4148bbed 100644 --- a/frontend_qt/grpC49.ui +++ b/frontend_qt/grpC49.ui @@ -1,7 +1,7 @@ - grpC16k - + grpC49 + 0 @@ -17,24 +17,70 @@ - + - S&tandard Mode + Row Separator Height: - - true + + cmbC49RowSepHeight - - - - &GS-1 Data Mode - + + + + + Default (1 X) + + + + + 2 X + + + + + 3 X + + + + + 4 X + + + + + + Encoding Mode + + + + QLayout::SetMinimumSize + + + + + S&tandard Mode + + + true + + + + + + + &GS-1 Data Mode + + + + + + diff --git a/frontend_qt/grpCodablockF.ui b/frontend_qt/grpCodablockF.ui index 8663bb28..95b4c269 100644 --- a/frontend_qt/grpCodablockF.ui +++ b/frontend_qt/grpCodablockF.ui @@ -19,7 +19,7 @@ - S&ymbol Width (Columns) + S&ymbol Width (Columns): cmbCbfWidth @@ -30,7 +30,7 @@ - Default + Automatic @@ -333,7 +333,7 @@ - Symbo&l Height (Rows) + Symbo&l Height (Rows): cmbCbfHeight @@ -344,7 +344,7 @@ - Default + Automatic @@ -572,7 +572,7 @@ - Row Separator Height + Row Separator Height: cmbCbfRowSepHeight @@ -583,12 +583,7 @@ - Default (2 X) - - - - - 1 X + Default (1 X) diff --git a/frontend_qt/mainwindow.cpp b/frontend_qt/mainwindow.cpp index 27c4b2f5..3dd63662 100644 --- a/frontend_qt/mainwindow.cpp +++ b/frontend_qt/mainwindow.cpp @@ -516,6 +516,7 @@ void MainWindow::change_options() m_optionWidget=uiload.load(&file); file.close(); tabMain->insertTab(1,m_optionWidget,tr("Code 16K")); + connect(m_optionWidget->findChild("cmbC16kRowSepHeight"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(m_optionWidget->findChild("radC16kStand"), SIGNAL(toggled( bool )), SLOT(update_preview())); } @@ -674,6 +675,7 @@ void MainWindow::change_options() m_optionWidget=uiload.load(&file); file.close(); tabMain->insertTab(1,m_optionWidget,tr("Code 49")); + connect(m_optionWidget->findChild("cmbC49RowSepHeight"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(m_optionWidget->findChild("radC49GS1"), SIGNAL(toggled( bool )), SLOT(update_preview())); } @@ -946,6 +948,11 @@ void MainWindow::update_preview() m_bc.bc.setInputMode(UNICODE_MODE); else m_bc.bc.setInputMode(GS1_MODE); + // Row separator height selection uses option 3 in zint_symbol + item_val = m_optionWidget->findChild("cmbC16kRowSepHeight")->currentIndex(); + if (item_val) { + m_bc.bc.setOption3(item_val + 1); // Zero-based + } break; case BARCODE_CODABLOCKF: @@ -966,7 +973,7 @@ void MainWindow::update_preview() // Row separator height selection uses option 3 in zint_symbol item_val = m_optionWidget->findChild("cmbCbfRowSepHeight")->currentIndex(); if (item_val) { - m_bc.bc.setOption3(item_val); + m_bc.bc.setOption3(item_val + 1); // Zero-based } break; @@ -1078,6 +1085,11 @@ void MainWindow::update_preview() m_bc.bc.setSymbol(BARCODE_CODE49); if(m_optionWidget->findChild("radC49GS1")->isChecked()) m_bc.bc.setInputMode(GS1_MODE); + // Row separator height selection uses option 3 in zint_symbol + item_val = m_optionWidget->findChild("cmbC49RowSepHeight")->currentIndex(); + if (item_val) { + m_bc.bc.setOption3(item_val + 1); // Zero-based + } break; case BARCODE_HANXIN: diff --git a/win32/libzint.vcxproj b/win32/libzint.vcxproj index da8f0769..3d8da2d9 100644 --- a/win32/libzint.vcxproj +++ b/win32/libzint.vcxproj @@ -332,6 +332,7 @@ + @@ -354,6 +355,7 @@ + @@ -372,6 +374,7 @@ + diff --git a/win32/zint_cmdline_vc6/zint_cmdline_vc6.dsp b/win32/zint_cmdline_vc6/zint_cmdline_vc6.dsp index d45a4d0d..e71b8f54 100644 --- a/win32/zint_cmdline_vc6/zint_cmdline_vc6.dsp +++ b/win32/zint_cmdline_vc6/zint_cmdline_vc6.dsp @@ -216,6 +216,10 @@ SOURCE=..\..\backend\medical.c # End Source File # Begin Source File +SOURCE=..\..\backend\output.c +# End Source File +# Begin Source File + SOURCE=..\..\backend\pcx.c # End Source File # Begin Source File