Performance improvements for linear encoding and raster output

- use fixed-length string tables (mostly) instead of (char *) pointer ones
   (saves ~40K)
 - re-use C128Table for CODABLOCKF and CODE16K
   (required removal of Stop character and extra CODE16K-only entry)
 - use pointer to destination and copy (memcpy/strcpy(), bin_append_posn())
   instead of concatenating (strcat()) (mostly)
 - replace last remaining bin_append()s with bin_append_posn();
   bin_append() removed
 - add length arg to toupper() and expand() (avoids strlen())
 - change is_sane() to use table-based flags (avoids an iteration)
 - rename lookup() to is_sane_lookup() and change to check and return posns
   and use in pointer to destination loops (avoids strcat()s)
 - remove special case PHARMA in expand() (dealt with in pharma())
 - make #define SILVER/CALCIUM/TECHNETIUM/KRSET etc static strings
 - replace strchr() -> posn()
 - CODE128: populate destination once in checksum loop; re-use and export
   some more routines (c128_set_a/b/c(), c128_put_in_set()) for sharing;
   prefix defines (SHIFTA -> C128_SHIFTA etc) and existing exported routines
 - use factor XOR toggle trick in checksum calcs (avoids branch)
 - raster.c: fill out single 1-pixel row and copy using new draw_bar_line(),
   copy_bar_line() routines; similarly in buffer_plot compare previous line &
   copy if same (same technique as used to improve non-half-integer scaling,
   significant performance increase, (c) codemonkey82);
   also done for PNG (BMP/GIF/PCX/TIFF not done)
 - raster/vector/output.c: shorten "output_" prefix -> "out_";
   sync vector to other raster changes to try to keep source files similar
 - 2of5.c: prefix "c25_"
JAPANPOST: return error if input data truncated (backward incompatible)
DAFT: max chars 50 -> 100
common.c: istwodigit() -> is_twodigit()
common.c/emf.c/output.c: use some further stripf()s (MSVC6 float variations)
library.c: new check_output_args() helper
zint.h: add BARCODE_LAST marker and use in library.c
QRCODE: remove a NOLINT (requires clang-tidy-13), one remaining
CMake: separate no-optimize from ZINT_DEBUG into new ZINT_NOOPT option
This commit is contained in:
gitlost 2021-10-20 23:05:30 +01:00
parent e8b59aa696
commit fab7435fac
72 changed files with 3501 additions and 2380 deletions

View File

@ -18,6 +18,7 @@ add_definitions(-DZINT_VERSION=\"${ZINT_VERSION}\")
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules") set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules")
option(ZINT_DEBUG "Set debug compile flags" OFF) option(ZINT_DEBUG "Set debug compile flags" OFF)
option(ZINT_NOOPT "Set no optimize compile flags" OFF)
option(ZINT_SANITIZE "Set sanitize compile/link flags" OFF) option(ZINT_SANITIZE "Set sanitize compile/link flags" OFF)
option(ZINT_TEST "Set test compile flag" OFF) option(ZINT_TEST "Set test compile flag" OFF)
option(ZINT_COVERAGE "Set code coverage flags" OFF) option(ZINT_COVERAGE "Set code coverage flags" OFF)
@ -52,32 +53,15 @@ if(ZINT_DEBUG)
if(CXX_COMPILER_FLAG_G) if(CXX_COMPILER_FLAG_G)
add_compile_options("-g") add_compile_options("-g")
endif() endif()
endif()
if(ZINT_NOOPT)
check_cxx_compiler_flag("-O0" CXX_COMPILER_FLAG_O0) check_cxx_compiler_flag("-O0" CXX_COMPILER_FLAG_O0)
if(CXX_COMPILER_FLAG_O0) if(CXX_COMPILER_FLAG_O0)
add_compile_options("-O0") add_compile_options("-O0")
endif() endif()
endif() endif()
if(ZINT_TEST)
enable_testing()
endif()
if(ZINT_COVERAGE)
set(CMAKE_REQUIRED_LIBRARIES -fprofile-arcs)
check_cxx_compiler_flag(--coverage CXX_COMPILER_FLAG_COVERAGE)
unset(CMAKE_REQUIRED_LIBRARIES)
if(CXX_COMPILER_FLAG_COVERAGE)
add_compile_options(--coverage)
link_libraries(-fprofile-arcs)
check_cxx_compiler_flag(-O0 CXX_COMPILER_FLAG_O0)
if(CXX_COMPILER_FLAG_O0)
add_compile_options(-O0)
endif()
endif()
endif()
if(ZINT_SANITIZE) if(ZINT_SANITIZE)
if(MSVC) if(MSVC)
if(MSVC_VERSION GREATER_EQUAL 1920) if(MSVC_VERSION GREATER_EQUAL 1920)
@ -105,6 +89,25 @@ if(ZINT_SANITIZE)
endif() endif()
endif() endif()
if(ZINT_TEST)
enable_testing()
endif()
if(ZINT_COVERAGE)
set(CMAKE_REQUIRED_LIBRARIES -fprofile-arcs)
check_cxx_compiler_flag(--coverage CXX_COMPILER_FLAG_COVERAGE)
unset(CMAKE_REQUIRED_LIBRARIES)
if(CXX_COMPILER_FLAG_COVERAGE)
add_compile_options(--coverage)
link_libraries(-fprofile-arcs)
check_cxx_compiler_flag(-O0 CXX_COMPILER_FLAG_O0)
if(CXX_COMPILER_FLAG_O0)
add_compile_options(-O0)
endif()
endif()
endif()
if(APPLE) if(APPLE)
if(UNIVERSAL) # TODO: make universal binary if(UNIVERSAL) # TODO: make universal binary
if(NOT ZINT_HAS_BEEN_RUN_BEFORE) if(NOT ZINT_HAS_BEEN_RUN_BEFORE)

View File

@ -9,6 +9,8 @@ Version 2.10.0.9 (dev) not released yet
NOTE: will return error if values outside ranges NOTE: will return error if values outside ranges
- raster.c: Bug fix for heap-buffer-overflow (#204 ARM-Cortex) - raster.c: Bug fix for heap-buffer-overflow (#204 ARM-Cortex)
NOTE: may cause single-pixel changes to height depending on height/scale used NOTE: may cause single-pixel changes to height depending on height/scale used
- JAPANPOST: return error if input data would be truncated
NOTE: previously was silently truncated
Changes Changes
------- -------
@ -31,6 +33,8 @@ Changes
- GUI: add Menu, copy to clipboard EMF/GIF/PNG/TIF, errtxt bar and status bar, - GUI: add Menu, copy to clipboard EMF/GIF/PNG/TIF, errtxt bar and status bar,
icons (feathericons) icons (feathericons)
- CODABAR: add show check digit option - CODABAR: add show check digit option
- DAFT: max chars 50 -> 100
- CMake: separate no-optimize from ZINT_DEBUG into new ZINT_NOOPT option
Bugs Bugs
---- ----
@ -43,7 +47,7 @@ Bugs
also ceilf(large_bar_height * si); also ceilf(large_bar_height * si);
also avoid distributive multiplication with floats to lessen chances of also avoid distributive multiplication with floats to lessen chances of
platform variation (#204 ARM-Cortex crash) platform variation (#204 ARM-Cortex crash)
- raster/vector.c: use new stripf() func to workaround gcc 32-bit - common/emf/output/raster/vector.c: use new stripf() func to workaround
float variations float variations
- raster.c: Don't add height offset for text if scale < 1.0 (as won't print) - raster.c: Don't add height offset for text if scale < 1.0 (as won't print)
- ISBNX: fix not returning error number (warning) correctly - ISBNX: fix not returning error number (warning) correctly

View File

@ -35,38 +35,42 @@
#include "common.h" #include "common.h"
#include "gs1.h" #include "gs1.h"
static const char *C25MatrixTable[10] = { static const char C25MatrixTable[10][6] = {
"113311", "311131", "131131", "331111", "113131", {'1','1','3','3','1','1'}, {'3','1','1','1','3','1'}, {'1','3','1','1','3','1'}, {'3','3','1','1','1','1'},
"313111", "133111", "111331", "311311", "131311" {'1','1','3','1','3','1'}, {'3','1','3','1','1','1'}, {'1','3','3','1','1','1'}, {'1','1','1','3','3','1'},
{'3','1','1','3','1','1'}, {'1','3','1','3','1','1'}
}; };
static const char C25IndustTable[10][10] = {
{'1','1','1','1','3','1','3','1','1','1'}, {'3','1','1','1','1','1','1','1','3','1'},
{'1','1','3','1','1','1','1','1','3','1'}, {'3','1','3','1','1','1','1','1','1','1'},
{'1','1','1','1','3','1','1','1','3','1'}, {'3','1','1','1','3','1','1','1','1','1'},
{'1','1','3','1','3','1','1','1','1','1'}, {'1','1','1','1','1','1','3','1','3','1'},
{'3','1','1','1','1','1','3','1','1','1'}, {'1','1','3','1','1','1','3','1','1','1'}
};
/* Note `c25_common()` assumes Stop string length one less than Start */
static const char *C25MatrixStartStop[2] = { "411111", "41111" }; static const char *C25MatrixStartStop[2] = { "411111", "41111" };
static const char *C25IndustTable[10] = {
"1111313111", "3111111131", "1131111131", "3131111111", "1111311131",
"3111311111", "1131311111", "1111113131", "3111113111", "1131113111"
};
static const char *C25IndustStartStop[2] = { "313111", "31113" }; static const char *C25IndustStartStop[2] = { "313111", "31113" };
static const char *C25IataLogicStartStop[2] = { "1111", "311" }; static const char *C25IataLogicStartStop[2] = { "1111", "311" };
static const char *C25InterTable[10] = { static const char C25InterTable[10][5] = {
"11331", "31113", "13113", "33111", "11313", {'1','1','3','3','1'}, {'3','1','1','1','3'}, {'1','3','1','1','3'}, {'3','3','1','1','1'}, {'1','1','3','1','3'},
"31311", "13311", "11133", "31131", "13131" {'3','1','3','1','1'}, {'1','3','3','1','1'}, {'1','1','1','3','3'}, {'3','1','1','3','1'}, {'1','3','1','3','1'}
}; };
static char check_digit(const unsigned int count) { static char c25_check_digit(const unsigned int count) {
return itoc((10 - (count % 10)) % 10); return itoc((10 - (count % 10)) % 10);
} }
/* Common to Standard (Matrix), Industrial, IATA, and Data Logic */ /* Common to Standard (Matrix), Industrial, IATA, and Data Logic */
static int c25_common(struct zint_symbol *symbol, const unsigned char source[], int length, const int max, static int c25_common(struct zint_symbol *symbol, const unsigned char source[], int length, const int max,
const char *table[10], const char *start_stop[2], const int error_base) { const int is_matrix, const char *start_stop[2], const int start_length, const int error_base) {
int i; int i;
char dest[512]; /* Largest destination 6 + (80 + 1) * 6 + 5 + 1 = 498 */ char dest[500]; /* Largest destination 6 + (80 + 1) * 6 + 5 + 1 = 498 */
unsigned char temp[80 + 1 + 1]; /* Largest maximum 80 */ char *d = dest;
unsigned char temp[80 + 1 + 1]; /* Largest maximum 80 + optional check digit */
int have_checkdigit = symbol->option_2 == 1 || symbol->option_2 == 2; int have_checkdigit = symbol->option_2 == 1 || symbol->option_2 == 2;
if (length > max) { if (length > max) {
@ -74,7 +78,7 @@ static int c25_common(struct zint_symbol *symbol, const unsigned char source[],
sprintf(symbol->errtxt, "%d: Input too long (%d character maximum)", error_base, max); sprintf(symbol->errtxt, "%d: Input too long (%d character maximum)", error_base, max);
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
/* errtxt 302: 304: 306: 308: */ /* errtxt 302: 304: 306: 308: */
sprintf(symbol->errtxt, "%d: Invalid character in data (digits only)", error_base + 1); sprintf(symbol->errtxt, "%d: Invalid character in data (digits only)", error_base + 1);
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
@ -88,17 +92,25 @@ static int c25_common(struct zint_symbol *symbol, const unsigned char source[],
temp[++length] = '\0'; temp[++length] = '\0';
} }
/* start character */ /* Start character */
strcpy(dest, start_stop[0]); memcpy(d, start_stop[0], start_length);
d += start_length;
for (i = 0; i < length; i++) { if (is_matrix) {
lookup(NEON, table, temp[i], dest); for (i = 0; i < length; i++, d += 6) {
memcpy(d, C25MatrixTable[temp[i] - '0'], 6);
}
} else {
for (i = 0; i < length; i++, d += 10) {
memcpy(d, C25IndustTable[temp[i] - '0'], 10);
}
} }
/* Stop character */ /* Stop character */
strcat(dest, start_stop[1]); memcpy(d, start_stop[1], start_length - 1);
d += start_length - 1;
expand(symbol, dest); expand(symbol, dest, d - dest);
ustrcpy(symbol->text, temp); ustrcpy(symbol->text, temp);
if (symbol->option_2 == 2) { if (symbol->option_2 == 2) {
@ -111,29 +123,30 @@ static int c25_common(struct zint_symbol *symbol, const unsigned char source[],
/* Code 2 of 5 Standard (Code 2 of 5 Matrix) */ /* Code 2 of 5 Standard (Code 2 of 5 Matrix) */
INTERNAL int c25standard(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int c25standard(struct zint_symbol *symbol, unsigned char source[], int length) {
return c25_common(symbol, source, length, 80, C25MatrixTable, C25MatrixStartStop, 301); return c25_common(symbol, source, length, 80, 1 /*is_matrix*/, C25MatrixStartStop, 6, 301);
} }
/* Code 2 of 5 Industrial */ /* Code 2 of 5 Industrial */
INTERNAL int c25ind(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int c25ind(struct zint_symbol *symbol, unsigned char source[], int length) {
return c25_common(symbol, source, length, 45, C25IndustTable, C25IndustStartStop, 303); return c25_common(symbol, source, length, 45, 0 /*is_matrix*/, C25IndustStartStop, 6, 303);
} }
/* Code 2 of 5 IATA */ /* Code 2 of 5 IATA */
INTERNAL int c25iata(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int c25iata(struct zint_symbol *symbol, unsigned char source[], int length) {
return c25_common(symbol, source, length, 45, C25IndustTable, C25IataLogicStartStop, 305); return c25_common(symbol, source, length, 45, 0 /*is_matrix*/, C25IataLogicStartStop, 4, 305);
} }
/* Code 2 of 5 Data Logic */ /* Code 2 of 5 Data Logic */
INTERNAL int c25logic(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int c25logic(struct zint_symbol *symbol, unsigned char source[], int length) {
return c25_common(symbol, source, length, 80, C25MatrixTable, C25IataLogicStartStop, 307); return c25_common(symbol, source, length, 80, 1 /*is_matrix*/, C25IataLogicStartStop, 4, 307);
} }
/* Common to Interleaved, ITF-14, DP Leitcode, DP Identcode */ /* Common to Interleaved, ITF-14, DP Leitcode, DP Identcode */
static int c25inter_common(struct zint_symbol *symbol, unsigned char source[], int length, static int c25_inter_common(struct zint_symbol *symbol, unsigned char source[], int length,
const int dont_set_height) { const int dont_set_height) {
int i, j, error_number = 0; int i, j, error_number = 0;
char bars[7], spaces[7], mixed[14], dest[512]; /* 4 + (90 + 2) * 5 + 3 + 1 = 468 */ char dest[468]; /* 4 + (90 + 2) * 5 + 3 + 1 = 468 */
char *d = dest;
unsigned char temp[90 + 2 + 1]; unsigned char temp[90 + 2 + 1];
int have_checkdigit = symbol->option_2 == 1 || symbol->option_2 == 2; int have_checkdigit = symbol->option_2 == 1 || symbol->option_2 == 2;
@ -141,7 +154,7 @@ static int c25inter_common(struct zint_symbol *symbol, unsigned char source[], i
strcpy(symbol->errtxt, "309: Input too long (90 character maximum)"); strcpy(symbol->errtxt, "309: Input too long (90 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "310: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "310: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -163,31 +176,26 @@ static int c25inter_common(struct zint_symbol *symbol, unsigned char source[], i
} }
/* start character */ /* start character */
strcpy(dest, "1111"); memcpy(d, "1111", 4);
d += 4;
for (i = 0; i < length; i += 2) { for (i = 0; i < length; i += 2) {
int k = 0; /* look up the bars and the spaces */
/* look up the bars and the spaces and put them in two strings */ const char *const bars = C25InterTable[temp[i] - '0'];
bars[0] = '\0'; const char *const spaces = C25InterTable[temp[i + 1] - '0'];
lookup(NEON, C25InterTable, temp[i], bars);
spaces[0] = '\0';
lookup(NEON, C25InterTable, temp[i + 1], spaces);
/* then merge (interlace) the strings together */ /* then merge (interlace) the strings together */
for (j = 0; j <= 4; j++) { for (j = 0; j < 5; j++) {
mixed[k] = bars[j]; *d++ = bars[j];
k++; *d++ = spaces[j];
mixed[k] = spaces[j];
k++;
} }
mixed[k] = '\0';
strcat(dest, mixed);
} }
/* Stop character */ /* Stop character */
strcat(dest, "311"); memcpy(d, "311", 3);
d += 3;
expand(symbol, dest); expand(symbol, dest, d - dest);
ustrcpy(symbol->text, temp); ustrcpy(symbol->text, temp);
if (symbol->option_2 == 2) { if (symbol->option_2 == 2) {
@ -219,7 +227,7 @@ static int c25inter_common(struct zint_symbol *symbol, unsigned char source[], i
/* Code 2 of 5 Interleaved ISO/IEC 16390:2007 */ /* Code 2 of 5 Interleaved ISO/IEC 16390:2007 */
INTERNAL int c25inter(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int c25inter(struct zint_symbol *symbol, unsigned char source[], int length) {
return c25inter_common(symbol, source, length, 0 /*dont_set_height*/); return c25_inter_common(symbol, source, length, 0 /*dont_set_height*/);
} }
/* Interleaved 2-of-5 (ITF-14) */ /* Interleaved 2-of-5 (ITF-14) */
@ -232,7 +240,7 @@ INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int lengt
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "312: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "312: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -247,7 +255,7 @@ INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int lengt
/* Calculate the check digit - the same method used for EAN-13 */ /* Calculate the check digit - the same method used for EAN-13 */
localstr[13] = gs1_check_digit(localstr, 13); localstr[13] = gs1_check_digit(localstr, 13);
localstr[14] = '\0'; localstr[14] = '\0';
error_number = c25inter_common(symbol, localstr, 14, 1 /*dont_set_height*/); error_number = c25_inter_common(symbol, localstr, 14, 1 /*dont_set_height*/);
ustrcpy(symbol->text, localstr); ustrcpy(symbol->text, localstr);
if (!((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND))) { if (!((symbol->output_options & BARCODE_BOX) || (symbol->output_options & BARCODE_BIND))) {
@ -277,6 +285,7 @@ INTERNAL int itf14(struct zint_symbol *symbol, unsigned char source[], int lengt
INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int length) {
int i, error_number; int i, error_number;
unsigned int count; unsigned int count;
int factor;
unsigned char localstr[16] = {0}; unsigned char localstr[16] = {0};
int zeroes; int zeroes;
@ -285,7 +294,7 @@ INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int leng
strcpy(symbol->errtxt, "313: Input wrong length (13 character maximum)"); strcpy(symbol->errtxt, "313: Input wrong length (13 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "314: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "314: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -295,16 +304,14 @@ INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int leng
localstr[i] = '0'; localstr[i] = '0';
ustrcpy(localstr + zeroes, source); ustrcpy(localstr + zeroes, source);
factor = 4;
for (i = 12; i >= 0; i--) { for (i = 12; i >= 0; i--) {
count += 4 * ctoi(localstr[i]); count += factor * ctoi(localstr[i]);
factor ^= 0x0D; /* Toggles 4 and 9 */
if (i & 1) {
count += 5 * ctoi(localstr[i]);
}
} }
localstr[13] = check_digit(count); localstr[13] = c25_check_digit(count);
localstr[14] = '\0'; localstr[14] = '\0';
error_number = c25inter_common(symbol, localstr, 14, 1 /*dont_set_height*/); error_number = c25_inter_common(symbol, localstr, 14, 1 /*dont_set_height*/);
ustrcpy(symbol->text, localstr); ustrcpy(symbol->text, localstr);
// TODO: Find documentation on BARCODE_DPLEIT dimensions/height // TODO: Find documentation on BARCODE_DPLEIT dimensions/height
@ -316,6 +323,7 @@ INTERNAL int dpleit(struct zint_symbol *symbol, unsigned char source[], int leng
INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int length) {
int i, error_number, zeroes; int i, error_number, zeroes;
unsigned int count; unsigned int count;
int factor;
unsigned char localstr[16] = {0}; unsigned char localstr[16] = {0};
count = 0; count = 0;
@ -323,7 +331,7 @@ INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int len
strcpy(symbol->errtxt, "315: Input wrong length (11 character maximum)"); strcpy(symbol->errtxt, "315: Input wrong length (11 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "316: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "316: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -333,16 +341,14 @@ INTERNAL int dpident(struct zint_symbol *symbol, unsigned char source[], int len
localstr[i] = '0'; localstr[i] = '0';
ustrcpy(localstr + zeroes, source); ustrcpy(localstr + zeroes, source);
factor = 4;
for (i = 10; i >= 0; i--) { for (i = 10; i >= 0; i--) {
count += 4 * ctoi(localstr[i]); count += factor * ctoi(localstr[i]);
factor ^= 0x0D; /* Toggles 4 and 9 */
if (i & 1) {
count += 5 * ctoi(localstr[i]);
}
} }
localstr[11] = check_digit(count); localstr[11] = c25_check_digit(count);
localstr[12] = '\0'; localstr[12] = '\0';
error_number = c25inter_common(symbol, localstr, 12, 1 /*dont_set_height*/); error_number = c25_inter_common(symbol, localstr, 12, 1 /*dont_set_height*/);
ustrcpy(symbol->text, localstr); ustrcpy(symbol->text, localstr);
// TODO: Find documentation on BARCODE_DPIDENT dimensions/height // TODO: Find documentation on BARCODE_DPIDENT dimensions/height

View File

@ -31,61 +31,74 @@
*/ */
/* vim: set ts=4 sw=4 et : */ /* vim: set ts=4 sw=4 et : */
#define GDSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #" static const char GDSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #";
#define GDSET_F (IS_NUM_F | IS_UPR_F | IS_LWR_F | IS_SPC_F | IS_HSH_F)
static const char *AusNTable[10] = { static const char AusNTable[10][2] = {
"00", "01", "02", "10", "11", "12", "20", "21", "22", "30" {'0','0'}, {'0','1'}, {'0','2'}, {'1','0'}, {'1','1'}, {'1','2'}, {'2','0'}, {'2','1'}, {'2','2'}, {'3','0'}
}; };
static const char *AusCTable[64] = { static const char AusCTable[64][3] = {
"222", "300", "301", "302", "310", "311", "312", "320", "321", "322", {'2','2','2'}, {'3','0','0'}, {'3','0','1'}, {'3','0','2'}, {'3','1','0'}, {'3','1','1'},
"000", "001", "002", "010", "011", "012", "020", "021", "022", "100", "101", "102", "110", {'3','1','2'}, {'3','2','0'}, {'3','2','1'}, {'3','2','2'}, {'0','0','0'}, {'0','0','1'},
"111", "112", "120", "121", "122", "200", "201", "202", "210", "211", "212", "220", "221", {'0','0','2'}, {'0','1','0'}, {'0','1','1'}, {'0','1','2'}, {'0','2','0'}, {'0','2','1'},
"023", "030", "031", "032", "033", "103", "113", "123", "130", "131", "132", "133", "203", {'0','2','2'}, {'1','0','0'}, {'1','0','1'}, {'1','0','2'}, {'1','1','0'}, {'1','1','1'},
"213", "223", "230", "231", "232", "233", "303", "313", "323", "330", "331", "332", "333", {'1','1','2'}, {'1','2','0'}, {'1','2','1'}, {'1','2','2'}, {'2','0','0'}, {'2','0','1'},
"003", "013" {'2','0','2'}, {'2','1','0'}, {'2','1','1'}, {'2','1','2'}, {'2','2','0'}, {'2','2','1'},
{'0','2','3'}, {'0','3','0'}, {'0','3','1'}, {'0','3','2'}, {'0','3','3'}, {'1','0','3'},
{'1','1','3'}, {'1','2','3'}, {'1','3','0'}, {'1','3','1'}, {'1','3','2'}, {'1','3','3'},
{'2','0','3'}, {'2','1','3'}, {'2','2','3'}, {'2','3','0'}, {'2','3','1'}, {'2','3','2'},
{'2','3','3'}, {'3','0','3'}, {'3','1','3'}, {'3','2','3'}, {'3','3','0'}, {'3','3','1'},
{'3','3','2'}, {'3','3','3'}, {'0','0','3'}, {'0','1','3'}
}; };
static const char *AusBarTable[64] = { static const char AusBarTable[64][3] = {
"000", "001", "002", "003", "010", "011", "012", "013", "020", "021", {'0','0','0'}, {'0','0','1'}, {'0','0','2'}, {'0','0','3'}, {'0','1','0'}, {'0','1','1'},
"022", "023", "030", "031", "032", "033", "100", "101", "102", "103", "110", "111", "112", {'0','1','2'}, {'0','1','3'}, {'0','2','0'}, {'0','2','1'}, {'0','2','2'}, {'0','2','3'},
"113", "120", "121", "122", "123", "130", "131", "132", "133", "200", "201", "202", "203", {'0','3','0'}, {'0','3','1'}, {'0','3','2'}, {'0','3','3'}, {'1','0','0'}, {'1','0','1'},
"210", "211", "212", "213", "220", "221", "222", "223", "230", "231", "232", "233", "300", {'1','0','2'}, {'1','0','3'}, {'1','1','0'}, {'1','1','1'}, {'1','1','2'}, {'1','1','3'},
"301", "302", "303", "310", "311", "312", "313", "320", "321", "322", "323", "330", "331", {'1','2','0'}, {'1','2','1'}, {'1','2','2'}, {'1','2','3'}, {'1','3','0'}, {'1','3','1'},
"332", "333" {'1','3','2'}, {'1','3','3'}, {'2','0','0'}, {'2','0','1'}, {'2','0','2'}, {'2','0','3'},
{'2','1','0'}, {'2','1','1'}, {'2','1','2'}, {'2','1','3'}, {'2','2','0'}, {'2','2','1'},
{'2','2','2'}, {'2','2','3'}, {'2','3','0'}, {'2','3','1'}, {'2','3','2'}, {'2','3','3'},
{'3','0','0'}, {'3','0','1'}, {'3','0','2'}, {'3','0','3'}, {'3','1','0'}, {'3','1','1'},
{'3','1','2'}, {'3','1','3'}, {'3','2','0'}, {'3','2','1'}, {'3','2','2'}, {'3','2','3'},
{'3','3','0'}, {'3','3','1'}, {'3','3','2'}, {'3','3','3'}
}; };
#include <stdio.h> #include <stdio.h>
#include "common.h" #include "common.h"
#include "reedsol.h" #include "reedsol.h"
static char convert_pattern(char data, int shift) { static char aus_convert_pattern(char data, int shift) {
return (data - '0') << shift; return (data - '0') << shift;
} }
/* Adds Reed-Solomon error correction to auspost */ /* Adds Reed-Solomon error correction to auspost */
static void rs_error(char data_pattern[]) { static char *aus_rs_error(char data_pattern[], char *d) {
int reader, len, triple_writer = 0; int reader, length, triple_writer = 0;
unsigned char triple[31]; unsigned char triple[31];
unsigned char result[5]; unsigned char result[5];
rs_t rs; rs_t rs;
for (reader = 2, len = (int) strlen(data_pattern); reader < len; reader += 3, triple_writer++) { for (reader = 2, length = d - data_pattern; reader < length; reader += 3, triple_writer++) {
triple[triple_writer] = convert_pattern(data_pattern[reader], 4) triple[triple_writer] = aus_convert_pattern(data_pattern[reader], 4)
+ convert_pattern(data_pattern[reader + 1], 2) + aus_convert_pattern(data_pattern[reader + 1], 2)
+ convert_pattern(data_pattern[reader + 2], 0); + aus_convert_pattern(data_pattern[reader + 2], 0);
} }
rs_init_gf(&rs, 0x43); rs_init_gf(&rs, 0x43);
rs_init_code(&rs, 4, 1); rs_init_code(&rs, 4, 1);
rs_encode(&rs, triple_writer, triple, result); rs_encode(&rs, triple_writer, triple, result);
for (reader = 4; reader > 0; reader--) { for (reader = 4; reader > 0; reader--, d += 3) {
strcat(data_pattern, AusBarTable[(int) result[reader - 1]]); memcpy(d, AusBarTable[(int) result[reader - 1]], 3);
} }
return d;
} }
INTERNAL int daft_set_height(struct zint_symbol *symbol, float min_height, float max_height); INTERNAL int daft_set_height(struct zint_symbol *symbol, const float min_height, const float max_height);
/* Handles Australia Posts's 4 State Codes */ /* Handles Australia Posts's 4 State Codes */
INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int length) {
@ -104,17 +117,29 @@ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int len
int h; int h;
char data_pattern[200]; char data_pattern[200];
char fcc[3] = {0, 0, 0}, dpid[10]; char *d = data_pattern;
char fcc[3] = {0}, dpid[10];
char localstr[30]; char localstr[30];
/* Do all of the length checking first to avoid stack smashing */
if (symbol->symbology == BARCODE_AUSPOST) {
if (length != 8 && length != 13 && length != 16 && length != 18 && length != 23) {
strcpy(symbol->errtxt, "401: Auspost input is wrong length (8, 13, 16, 18 or 23 characters only)");
return ZINT_ERROR_TOO_LONG;
}
} else if (length > 8) {
strcpy(symbol->errtxt, "403: Auspost input is too long (8 character maximum)");
return ZINT_ERROR_TOO_LONG;
}
/* Check input immediately to catch nuls */ /* Check input immediately to catch nuls */
if (is_sane(GDSET, source, length) != 0) { if (!is_sane(GDSET_F, source, length)) {
strcpy(symbol->errtxt, "404: Invalid character in data (alphanumerics, space and \"#\" only)"); strcpy(symbol->errtxt, "404: Invalid character in data (alphanumerics, space and \"#\" only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
strcpy(localstr, "");
/* Do all of the length checking first to avoid stack smashing */ localstr[0] = '\0';
if (symbol->symbology == BARCODE_AUSPOST) { if (symbol->symbology == BARCODE_AUSPOST) {
/* Format control code (FCC) */ /* Format control code (FCC) */
switch (length) { switch (length) {
@ -126,7 +151,7 @@ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int len
break; break;
case 16: case 16:
strcpy(fcc, "59"); strcpy(fcc, "59");
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "402: Invalid character in data (digits only for length 16)"); strcpy(symbol->errtxt, "402: Invalid character in data (digits only for length 16)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -136,21 +161,14 @@ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int len
break; break;
case 23: case 23:
strcpy(fcc, "62"); strcpy(fcc, "62");
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "406: Invalid character in data (digits only for length 23)"); strcpy(symbol->errtxt, "406: Invalid character in data (digits only for length 23)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
break; break;
default:
strcpy(symbol->errtxt, "401: Auspost input is wrong length (8, 13, 16, 18 or 23 characters only)");
return ZINT_ERROR_TOO_LONG;
} }
} else { } else {
int zeroes; int zeroes;
if (length > 8) {
strcpy(symbol->errtxt, "403: Auspost input is too long (8 character maximum)");
return ZINT_ERROR_TOO_LONG;
}
switch (symbol->symbology) { switch (symbol->symbology) {
case BARCODE_AUSREPLY: strcpy(fcc, "45"); case BARCODE_AUSREPLY: strcpy(fcc, "45");
break; break;
@ -175,58 +193,60 @@ INTERNAL int auspost(struct zint_symbol *symbol, unsigned char source[], int len
/* Verify that the first 8 characters are numbers */ /* Verify that the first 8 characters are numbers */
memcpy(dpid, localstr, 8); memcpy(dpid, localstr, 8);
dpid[8] = '\0'; dpid[8] = '\0';
if (is_sane(NEON, (unsigned char *) dpid, 8) != 0) { if (!is_sane(NEON_F, (unsigned char *) dpid, 8)) {
strcpy(symbol->errtxt, "405: Invalid character in DPID (first 8 characters) (digits only)"); strcpy(symbol->errtxt, "405: Invalid character in DPID (first 8 characters) (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
/* Start character */ /* Start character */
strcpy(data_pattern, "13"); memcpy(d, "13", 2);
d += 2;
/* Encode the FCC */ /* Encode the FCC */
for (reader = 0; reader < 2; reader++) { for (reader = 0; reader < 2; reader++, d += 2) {
lookup(NEON, AusNTable, fcc[reader], data_pattern); memcpy(d, AusNTable[fcc[reader] - '0'], 2);
} }
/* Delivery Point Identifier (DPID) */ /* Delivery Point Identifier (DPID) */
for (reader = 0; reader < 8; reader++) { for (reader = 0; reader < 8; reader++, d += 2) {
lookup(NEON, AusNTable, dpid[reader], data_pattern); memcpy(d, AusNTable[dpid[reader] - '0'], 2);
} }
/* Customer Information */ /* Customer Information */
if (h > 8) { if (h > 8) {
if ((h == 13) || (h == 18)) { if ((h == 13) || (h == 18)) {
for (reader = 8; reader < h; reader++) { for (reader = 8; reader < h; reader++, d += 3) {
lookup(GDSET, AusCTable, localstr[reader], data_pattern); memcpy(d, AusCTable[posn(GDSET, localstr[reader])], 3);
} }
} else if ((h == 16) || (h == 23)) { } else if ((h == 16) || (h == 23)) {
for (reader = 8; reader < h; reader++) { for (reader = 8; reader < h; reader++, d += 2) {
lookup(NEON, AusNTable, localstr[reader], data_pattern); memcpy(d, AusNTable[localstr[reader] - '0'], 2);
} }
} }
} }
/* Filler bar */ /* Filler bar */
h = (int) strlen(data_pattern); h = d - data_pattern;
switch (h) { switch (h) {
case 22: case 22:
case 37: case 37:
case 52: case 52:
strcat(data_pattern, "3"); *d++ = '3';
break; break;
default: default:
break; break;
} }
/* Reed Solomon error correction */ /* Reed Solomon error correction */
rs_error(data_pattern); d = aus_rs_error(data_pattern, d);
/* Stop character */ /* Stop character */
strcat(data_pattern, "13"); memcpy(d, "13", 2);
d += 2;
/* Turn the symbol into a bar pattern ready for plotting */ /* Turn the symbol into a bar pattern ready for plotting */
writer = 0; writer = 0;
h = (int) strlen(data_pattern); h = d - data_pattern;
for (loopey = 0; loopey < h; loopey++) { for (loopey = 0; loopey < h; loopey++) {
if ((data_pattern[loopey] == '1') || (data_pattern[loopey] == '0')) { if ((data_pattern[loopey] == '1') || (data_pattern[loopey] == '0')) {
set_module(symbol, 0, writer); set_module(symbol, 0, writer);

View File

@ -1447,7 +1447,7 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], int lengt
/* Encodes Aztec runes as specified in ISO/IEC 24778:2008 Annex A */ /* Encodes Aztec runes as specified in ISO/IEC 24778:2008 Annex A */
INTERNAL int azrune(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int azrune(struct zint_symbol *symbol, unsigned char source[], int length) {
unsigned int input_value; unsigned int input_value;
int error_number, i, y, x, r; int i, y, x, r;
char binary_string[28]; char binary_string[28];
unsigned char data_codewords[3], ecc_codewords[6]; unsigned char data_codewords[3], ecc_codewords[6];
int bp = 0; int bp = 0;
@ -1459,8 +1459,7 @@ INTERNAL int azrune(struct zint_symbol *symbol, unsigned char source[], int leng
strcpy(symbol->errtxt, "507: Input too large (3 character maximum)"); strcpy(symbol->errtxt, "507: Input too large (3 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
error_number = is_sane(NEON, source, length); if (!is_sane(NEON_F, source, length)) {
if (error_number != 0) {
strcpy(symbol->errtxt, "508: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "508: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }

View File

@ -38,8 +38,7 @@
#endif #endif
#include <assert.h> #include <assert.h>
#include "common.h" #include "common.h"
#include "code128.h"
INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int length);
#define uchar unsigned char #define uchar unsigned char
@ -65,23 +64,6 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
#define aCodeC (uchar)(134) #define aCodeC (uchar)(134)
#define aShift (uchar)(135) #define aShift (uchar)(135)
static const char *C128Table[107] = {
/* Code 128 character encodation - Table 1 */
"212222", "222122", "222221", "121223", "121322", "131222", "122213",
"122312", "132212", "221213", "221312", "231212", "112232", "122132", "122231", "113222",
"123122", "123221", "223211", "221132", "221231", "213212", "223112", "312131", "311222",
"321122", "321221", "312212", "322112", "322211", "212123", "212321", "232121", "111323",
"131123", "131321", "112313", "132113", "132311", "211313", "231113", "231311", "112133",
"112331", "132131", "113123", "113321", "133121", "313121", "211331", "231131", "213113",
"213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111", "314111",
"221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214",
"112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112",
"134111", "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112",
"421211", "212141", "214121", "412121", "111143", "111341", "131141", "114113", "114311",
"411113", "411311", "113141", "114131", "311141", "411131", "211412", "211214", "211232",
"2331112"
};
/* Code F Analysing-Chart */ /* Code F Analysing-Chart */
typedef struct sCharacterSetTable typedef struct sCharacterSetTable
{ {
@ -953,11 +935,14 @@ INTERNAL int codablockf(struct zint_symbol *symbol, unsigned char source[], int
/* Paint the C128 patterns */ /* Paint the C128 patterns */
for (r = 0; r < rows; r++) { for (r = 0; r < rows; r++) {
strcpy(dest, ""); const int rc = r * columns;
for(c = 0; c < columns; c++) { char *d = dest;
strcat(dest, C128Table[pOutput[r * columns + c]]); for (c = 0; c < columns - 1; c++, d += 6) {
memcpy(d, C128Table[pOutput[rc + c]], 6);
} }
expand(symbol, dest); memcpy(d, "2331112", 7); /* Stop character (106, not in C128Table) */
d += 7;
expand(symbol, dest, d - dest);
} }
if (symbol->output_options & COMPLIANT_HEIGHT) { if (symbol->output_options & COMPLIANT_HEIGHT) {

View File

@ -1,8 +1,4 @@
/* code.c - Handles Code 11, 39, 39+, 93, PZN, Channel and VIN */ /* code.c - Handles Code 11, 39, 39+, 93, PZN, Channel and VIN */
/* LOGMARS MIL-STD-1189 Rev. B https://apps.dtic.mil/dtic/tr/fulltext/u2/a473534.pdf */
/* PZN https://www.ifaffm.de/mandanten/1/documents/04_ifa_coding_system/IFA_Info_Code_39_EN.pdf */
/* PZN https://www.ifaffm.de/mandanten/1/documents/04_ifa_coding_system/
IFA-Info_Check_Digit_Calculations_PZN_PPN_UDI_EN.pdf */
/* /*
libzint - the open source barcode library libzint - the open source barcode library
@ -41,61 +37,95 @@
#include <assert.h> #include <assert.h>
#include "common.h" #include "common.h"
#define SODIUM "0123456789-" #define SODIUM_MNS_F (IS_NUM_F | IS_MNS_F) /* SODIUM "0123456789-" */
#define SILVER "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd"
#define ARSENIC "0123456789ABCDEFGHJKLMNPRSTUVWXYZ"
static const char *C11Table[11] = { /* Same as TECHNETIUM (HIBC) with "abcd" added for CODE93 */
"111121", "211121", "121121", "221111", "112121", "212111", "122111", static const char SILVER[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd";
"111221", "211211", "211111", "112111"
#define ARSENIC_F (IS_NUM_F | IS_ARS_F) /* ARSENIC "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" */
static const char C11Table[11][6] = {
{'1','1','1','1','2','1'}, {'2','1','1','1','2','1'}, {'1','2','1','1','2','1'}, {'2','2','1','1','1','1'},
{'1','1','2','1','2','1'}, {'2','1','2','1','1','1'}, {'1','2','2','1','1','1'}, {'1','1','1','2','2','1'},
{'2','1','1','2','1','1'}, {'2','1','1','1','1','1'}, {'1','1','2','1','1','1'}
}; };
/* Code 39 tables checked against ISO/IEC 16388:2007 */ /* Code 39 tables checked against ISO/IEC 16388:2007 */
/* Incorporates Table A1 */ /* Incorporates Table A1 */
static const char *C39Table[43] = { static const char C39Table[43][10] = {
/* Code 39 character assignments (Table 1) */ /* Code 39 character assignments (Table 1) */
"1112212111", "2112111121", "1122111121", "2122111111", "1112211121", {'1','1','1','2','2','1','2','1','1','1'}, {'2','1','1','2','1','1','1','1','2','1'},
"2112211111", "1122211111", "1112112121", "2112112111", "1122112111", "2111121121", {'1','1','2','2','1','1','1','1','2','1'}, {'2','1','2','2','1','1','1','1','1','1'},
"1121121121", "2121121111", "1111221121", "2111221111", "1121221111", "1111122121", {'1','1','1','2','2','1','1','1','2','1'}, {'2','1','1','2','2','1','1','1','1','1'},
"2111122111", "1121122111", "1111222111", "2111111221", "1121111221", "2121111211", {'1','1','2','2','2','1','1','1','1','1'}, {'1','1','1','2','1','1','2','1','2','1'},
"1111211221", "2111211211", "1121211211", "1111112221", "2111112211", "1121112211", {'2','1','1','2','1','1','2','1','1','1'}, {'1','1','2','2','1','1','2','1','1','1'},
"1111212211", "2211111121", "1221111121", "2221111111", "1211211121", "2211211111", {'2','1','1','1','1','2','1','1','2','1'}, {'1','1','2','1','1','2','1','1','2','1'},
"1221211111", "1211112121", "2211112111", "1221112111", "1212121111", "1212111211", {'2','1','2','1','1','2','1','1','1','1'}, {'1','1','1','1','2','2','1','1','2','1'},
"1211121211", "1112121211" {'2','1','1','1','2','2','1','1','1','1'}, {'1','1','2','1','2','2','1','1','1','1'},
{'1','1','1','1','1','2','2','1','2','1'}, {'2','1','1','1','1','2','2','1','1','1'},
{'1','1','2','1','1','2','2','1','1','1'}, {'1','1','1','1','2','2','2','1','1','1'},
{'2','1','1','1','1','1','1','2','2','1'}, {'1','1','2','1','1','1','1','2','2','1'},
{'2','1','2','1','1','1','1','2','1','1'}, {'1','1','1','1','2','1','1','2','2','1'},
{'2','1','1','1','2','1','1','2','1','1'}, {'1','1','2','1','2','1','1','2','1','1'},
{'1','1','1','1','1','1','2','2','2','1'}, {'2','1','1','1','1','1','2','2','1','1'},
{'1','1','2','1','1','1','2','2','1','1'}, {'1','1','1','1','2','1','2','2','1','1'},
{'2','2','1','1','1','1','1','1','2','1'}, {'1','2','2','1','1','1','1','1','2','1'},
{'2','2','2','1','1','1','1','1','1','1'}, {'1','2','1','1','2','1','1','1','2','1'},
{'2','2','1','1','2','1','1','1','1','1'}, {'1','2','2','1','2','1','1','1','1','1'},
{'1','2','1','1','1','1','2','1','2','1'}, {'2','2','1','1','1','1','2','1','1','1'},
{'1','2','2','1','1','1','2','1','1','1'}, {'1','2','1','2','1','2','1','1','1','1'},
{'1','2','1','2','1','1','1','2','1','1'}, {'1','2','1','1','1','2','1','2','1','1'},
{'1','1','1','2','1','2','1','2','1','1'}
}; };
static const char *EC39Ctrl[128] = { static const char EC39Ctrl[128][2] = {
/* Encoding the full ASCII character set in Code 39 (Table A2) */ /* Encoding the full ASCII character set in Code 39 (Table A2) */
"%U", "$A", "$B", "$C", "$D", "$E", "$F", "$G", "$H", "$I", "$J", "$K", {'%','U'}, {'$','A'}, {'$','B'}, {'$','C'}, {'$','D'}, {'$','E'}, {'$','F'}, {'$','G'}, {'$','H'}, {'$','I'},
"$L", "$M", "$N", "$O", "$P", "$Q", "$R", "$S", "$T", "$U", "$V", "$W", "$X", "$Y", "$Z", {'$','J'}, {'$','K'}, {'$','L'}, {'$','M'}, {'$','N'}, {'$','O'}, {'$','P'}, {'$','Q'}, {'$','R'}, {'$','S'},
"%A", "%B", "%C", "%D", "%E", " ", "/A", "/B", "/C", "/D", "/E", "/F", "/G", "/H", "/I", "/J", {'$','T'}, {'$','U'}, {'$','V'}, {'$','W'}, {'$','X'}, {'$','Y'}, {'$','Z'}, {'%','A'}, {'%','B'}, {'%','C'},
"/K", "/L", "-", ".", "/O", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "/Z", "%F", {'%','D'}, {'%','E'}, { " " }, {'/','A'}, {'/','B'}, {'/','C'}, {'/','D'}, {'/','E'}, {'/','F'}, {'/','G'},
"%G", "%H", "%I", "%J", "%V", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", {'/','H'}, {'/','I'}, {'/','J'}, {'/','K'}, {'/','L'}, { "-" }, { "." }, {'/','O'}, { "0" }, { "1" },
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "%K", "%L", "%M", "%N", "%O", { "2" }, { "3" }, { "4" }, { "5" }, { "6" }, { "7" }, { "8" }, { "9" }, {'/','Z'}, {'%','F'},
"%W", "+A", "+B", "+C", "+D", "+E", "+F", "+G", "+H", "+I", "+J", "+K", "+L", "+M", "+N", "+O", {'%','G'}, {'%','H'}, {'%','I'}, {'%','J'}, {'%','V'}, { "A" }, { "B" }, { "C" }, { "D" }, { "E" },
"+P", "+Q", "+R", "+S", "+T", "+U", "+V", "+W", "+X", "+Y", "+Z", "%P", "%Q", "%R", "%S", "%T" { "F" }, { "G" }, { "H" }, { "I" }, { "J" }, { "K" }, { "L" }, { "M" }, { "N" }, { "O" },
{ "P" }, { "Q" }, { "R" }, { "S" }, { "T" }, { "U" }, { "V" }, { "W" }, { "X" }, { "Y" },
{ "Z" }, {'%','K'}, {'%','L'}, {'%','M'}, {'%','N'}, {'%','O'}, {'%','W'}, {'+','A'}, {'+','B'}, {'+','C'},
{'+','D'}, {'+','E'}, {'+','F'}, {'+','G'}, {'+','H'}, {'+','I'}, {'+','J'}, {'+','K'}, {'+','L'}, {'+','M'},
{'+','N'}, {'+','O'}, {'+','P'}, {'+','Q'}, {'+','R'}, {'+','S'}, {'+','T'}, {'+','U'}, {'+','V'}, {'+','W'},
{'+','X'}, {'+','Y'}, {'+','Z'}, {'%','P'}, {'%','Q'}, {'%','R'}, {'%','S'}, {'%','T'}
}; };
static const char *C93Ctrl[128] = { static const char C93Ctrl[128][2] = {
"bU", "aA", "aB", "aC", "aD", "aE", "aF", "aG", "aH", "aI", "aJ", "aK", {'b','U'}, {'a','A'}, {'a','B'}, {'a','C'}, {'a','D'}, {'a','E'}, {'a','F'}, {'a','G'}, {'a','H'}, {'a','I'},
"aL", "aM", "aN", "aO", "aP", "aQ", "aR", "aS", "aT", "aU", "aV", "aW", "aX", "aY", "aZ", {'a','J'}, {'a','K'}, {'a','L'}, {'a','M'}, {'a','N'}, {'a','O'}, {'a','P'}, {'a','Q'}, {'a','R'}, {'a','S'},
"bA", "bB", "bC", "bD", "bE", " ", "cA", "cB", "cC", "$", "%", "cF", "cG", "cH", "cI", "cJ", {'a','T'}, {'a','U'}, {'a','V'}, {'a','W'}, {'a','X'}, {'a','Y'}, {'a','Z'}, {'b','A'}, {'b','B'}, {'b','C'},
"+", "cL", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "cZ", "bF", {'b','D'}, {'b','E'}, { " " }, {'c','A'}, {'c','B'}, {'c','C'}, { "$" }, { "%" }, {'c','F'}, {'c','G'},
"bG", "bH", "bI", "bJ", "bV", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", {'c','H'}, {'c','I'}, {'c','J'}, { "+" }, {'c','L'}, { "-" }, { "." }, { "/" }, { "0" }, { "1" },
"N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "bK", "bL", "bM", "bN", "bO", { "2" }, { "3" }, { "4" }, { "5" }, { "6" }, { "7" }, { "8" }, { "9" }, {'c','Z'}, {'b','F'},
"bW", "dA", "dB", "dC", "dD", "dE", "dF", "dG", "dH", "dI", "dJ", "dK", "dL", "dM", "dN", "dO", {'b','G'}, {'b','H'}, {'b','I'}, {'b','J'}, {'b','V'}, { "A" }, { "B" }, { "C" }, { "D" }, { "E" },
"dP", "dQ", "dR", "dS", "dT", "dU", "dV", "dW", "dX", "dY", "dZ", "bP", "bQ", "bR", "bS", "bT" { "F" }, { "G" }, { "H" }, { "I" }, { "J" }, { "K" }, { "L" }, { "M" }, { "N" }, { "O" },
{ "P" }, { "Q" }, { "R" }, { "S" }, { "T" }, { "U" }, { "V" }, { "W" }, { "X" }, { "Y" },
{ "Z" }, {'b','K'}, {'b','L'}, {'b','M'}, {'b','N'}, {'b','O'}, {'b','W'}, {'d','A'}, {'d','B'}, {'d','C'},
{'d','D'}, {'d','E'}, {'d','F'}, {'d','G'}, {'d','H'}, {'d','I'}, {'d','J'}, {'d','K'}, {'d','L'}, {'d','M'},
{'d','N'}, {'d','O'}, {'d','P'}, {'d','Q'}, {'d','R'}, {'d','S'}, {'d','T'}, {'d','U'}, {'d','V'}, {'d','W'},
{'d','X'}, {'d','Y'}, {'d','Z'}, {'b','P'}, {'b','Q'}, {'b','R'}, {'b','S'}, {'b','T'}
}; };
static const char *C93Table[47] = { static const char C93Table[47][6] = {
"131112", "111213", "111312", "111411", "121113", "121212", "121311", {'1','3','1','1','1','2'}, {'1','1','1','2','1','3'}, {'1','1','1','3','1','2'}, {'1','1','1','4','1','1'},
"111114", "131211", "141111", "211113", "211212", "211311", "221112", "221211", "231111", {'1','2','1','1','1','3'}, {'1','2','1','2','1','2'}, {'1','2','1','3','1','1'}, {'1','1','1','1','1','4'},
"112113", "112212", "112311", "122112", "132111", "111123", "111222", "111321", "121122", {'1','3','1','2','1','1'}, {'1','4','1','1','1','1'}, {'2','1','1','1','1','3'}, {'2','1','1','2','1','2'},
"131121", "212112", "212211", "211122", "211221", "221121", "222111", "112122", "112221", {'2','1','1','3','1','1'}, {'2','2','1','1','1','2'}, {'2','2','1','2','1','1'}, {'2','3','1','1','1','1'},
"122121", "123111", "121131", "311112", "311211", "321111", "112131", "113121", "211131", {'1','1','2','1','1','3'}, {'1','1','2','2','1','2'}, {'1','1','2','3','1','1'}, {'1','2','2','1','1','2'},
"121221", "312111", "311121", "122211" {'1','3','2','1','1','1'}, {'1','1','1','1','2','3'}, {'1','1','1','2','2','2'}, {'1','1','1','3','2','1'},
{'1','2','1','1','2','2'}, {'1','3','1','1','2','1'}, {'2','1','2','1','1','2'}, {'2','1','2','2','1','1'},
{'2','1','1','1','2','2'}, {'2','1','1','2','2','1'}, {'2','2','1','1','2','1'}, {'2','2','2','1','1','1'},
{'1','1','2','1','2','2'}, {'1','1','2','2','2','1'}, {'1','2','2','1','2','1'}, {'1','2','3','1','1','1'},
{'1','2','1','1','3','1'}, {'3','1','1','1','1','2'}, {'3','1','1','2','1','1'}, {'3','2','1','1','1','1'},
{'1','1','2','1','3','1'}, {'1','1','3','1','2','1'}, {'2','1','1','1','3','1'}, {'1','2','1','2','2','1'},
{'3','1','2','1','1','1'}, {'3','1','1','1','2','1'}, {'1','2','2','2','1','1'}
}; };
/* *********************** CODE 11 ******************** */ /* *********************** CODE 11 ******************** */
@ -105,8 +135,10 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng
int h, c_digit, c_weight, c_count, k_digit, k_weight, k_count; int h, c_digit, c_weight, c_count, k_digit, k_weight, k_count;
int weight[122], error_number = 0; int weight[122], error_number = 0;
char dest[750]; /* 6 + 121 * 6 + 2 * 6 + 5 + 1 == 750 */ char dest[750]; /* 6 + 121 * 6 + 2 * 6 + 5 + 1 == 750 */
char checkstr[3]; char *d = dest;
int num_check_digits; int num_check_digits;
char checkstr[3] = {0};
static char checkchrs[11] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-' };
/* Suppresses clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult warning */ /* Suppresses clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult warning */
assert(length > 0); assert(length > 0);
@ -115,7 +147,7 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng
strcpy(symbol->errtxt, "320: Input too long (121 character maximum)"); strcpy(symbol->errtxt, "320: Input too long (121 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(SODIUM, source, length) != 0) { if (!is_sane(SODIUM_MNS_F, source, length)) {
strcpy(symbol->errtxt, "321: Invalid character in data (digits and \"-\" only)"); strcpy(symbol->errtxt, "321: Invalid character in data (digits and \"-\" only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -138,15 +170,16 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng
k_count = 0; k_count = 0;
/* start character */ /* start character */
strcpy(dest, "112211"); memcpy(d, "112211", 6);
d += 6;
/* Draw main body of barcode */ /* Draw main body of barcode */
for (i = 0; i < length; i++) { for (i = 0; i < length; i++, d += 6) {
lookup(SODIUM, C11Table, source[i], dest);
if (source[i] == '-') if (source[i] == '-')
weight[i] = 10; weight[i] = 10;
else else
weight[i] = ctoi(source[i]); weight[i] = ctoi(source[i]);
memcpy(d, C11Table[weight[i]], 6);
} }
if (num_check_digits) { if (num_check_digits) {
@ -161,14 +194,11 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng
} }
c_digit = c_count % 11; c_digit = c_count % 11;
if (num_check_digits == 1) { checkstr[0] = checkchrs[c_digit];
checkstr[0] = itoc(c_digit); memcpy(d, C11Table[c_digit], 6);
if (checkstr[0] == 'A') { d += 6;
checkstr[0] = '-';
} if (num_check_digits == 2) {
checkstr[1] = '\0';
lookup(SODIUM, C11Table, checkstr[0], dest);
} else {
weight[length] = c_digit; weight[length] = c_digit;
/* Calculate K checksum */ /* Calculate K checksum */
@ -182,17 +212,9 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng
} }
k_digit = k_count % 11; k_digit = k_count % 11;
checkstr[0] = itoc(c_digit); checkstr[1] = checkchrs[k_digit];
checkstr[1] = itoc(k_digit); memcpy(d, C11Table[k_digit], 6);
if (checkstr[0] == 'A') { d += 6;
checkstr[0] = '-';
}
if (checkstr[1] == 'A') {
checkstr[1] = '-';
}
checkstr[2] = '\0';
lookup(SODIUM, C11Table, checkstr[0], dest);
lookup(SODIUM, C11Table, checkstr[1], dest);
} }
} }
@ -201,9 +223,10 @@ INTERNAL int code11(struct zint_symbol *symbol, unsigned char source[], int leng
} }
/* Stop character */ /* Stop character */
strcat(dest, "11221"); memcpy(d, "11221", 5);
d += 5;
expand(symbol, dest); expand(symbol, dest, d - dest);
// TODO: Find documentation on BARCODE_CODE11 dimensions/height // TODO: Find documentation on BARCODE_CODE11 dimensions/height
@ -219,7 +242,9 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng
int i; int i;
int counter; int counter;
int error_number = 0; int error_number = 0;
int posns[85];
char dest[880]; /* 10 (Start) + 85 * 10 + 10 (Check) + 9 (Stop) + 1 = 880 */ char dest[880]; /* 10 (Start) + 85 * 10 + 10 (Check) + 9 (Stop) + 1 = 880 */
char *d = dest;
char localstr[2] = {0}; char localstr[2] = {0};
counter = 0; counter = 0;
@ -228,6 +253,7 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng
symbol->option_2 = 0; symbol->option_2 = 0;
} }
/* LOGMARS MIL-STD-1189 Rev. B https://apps.dtic.mil/dtic/tr/fulltext/u2/a473534.pdf */
if ((symbol->symbology == BARCODE_LOGMARS) && (length > 30)) { /* MIL-STD-1189 Rev. B Section 5.2.6.2 */ if ((symbol->symbology == BARCODE_LOGMARS) && (length > 30)) { /* MIL-STD-1189 Rev. B Section 5.2.6.2 */
strcpy(symbol->errtxt, "322: Input too long (30 character maximum)"); strcpy(symbol->errtxt, "322: Input too long (30 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
@ -240,18 +266,20 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng
strcpy(symbol->errtxt, "323: Input too long (85 character maximum)"); strcpy(symbol->errtxt, "323: Input too long (85 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
to_upper(source);
if (is_sane(SILVER, source, length) != 0) { to_upper(source, length);
if (!is_sane_lookup(SILVER, 43, source, length, posns)) {
strcpy(symbol->errtxt, "324: Invalid character in data (alphanumerics, space and \"-.$/+%\" only)"); strcpy(symbol->errtxt, "324: Invalid character in data (alphanumerics, space and \"-.$/+%\" only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
/* Start character */ /* Start character */
strcpy(dest, "1211212111"); memcpy(d, "1211212111", 10);
d += 10;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++, d += 10) {
lookup(SILVER, C39Table, source[i], dest); memcpy(d, C39Table[posns[i]], 10);
counter += posn(SILVER, source[i]); counter += posns[i];
} }
if (symbol->option_2 == 1) { if (symbol->option_2 == 1) {
@ -259,7 +287,8 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng
char check_digit; char check_digit;
counter %= 43; counter %= 43;
check_digit = SILVER[counter]; check_digit = SILVER[counter];
lookup(SILVER, C39Table, check_digit, dest); memcpy(d, C39Table[counter], 10);
d += 10;
/* Display a space check digit as _, otherwise it looks like an error */ /* Display a space check digit as _, otherwise it looks like an error */
if (check_digit == ' ') { if (check_digit == ' ') {
@ -271,11 +300,12 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng
} }
/* Stop character */ /* Stop character */
strcat(dest, "121121211"); memcpy(d, "121121211", 9);
d += 9;
if ((symbol->symbology == BARCODE_LOGMARS) || (symbol->symbology == BARCODE_HIBC_39)) { if ((symbol->symbology == BARCODE_LOGMARS) || (symbol->symbology == BARCODE_HIBC_39)) {
/* LOGMARS uses wider 'wide' bars than normal Code 39 */ /* LOGMARS uses wider 'wide' bars than normal Code 39 */
counter = (int) strlen(dest); counter = d - dest;
for (i = 0; i < counter; i++) { for (i = 0; i < counter; i++) {
if (dest[i] == '2') { if (dest[i] == '2') {
dest[i] = '3'; dest[i] = '3';
@ -283,11 +313,11 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng
} }
} }
if (symbol->debug & ZINT_DEBUG_PRINT) { if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("Barspaces: %s\n", dest); printf("Barspaces: %.*s\n", (int) (d - dest), dest);
} }
expand(symbol, dest); expand(symbol, dest, d - dest);
if (symbol->output_options & COMPLIANT_HEIGHT) { if (symbol->output_options & COMPLIANT_HEIGHT) {
if (symbol->symbology == BARCODE_LOGMARS) { if (symbol->symbology == BARCODE_LOGMARS) {
@ -324,6 +354,9 @@ INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int leng
} }
/* Pharmazentral Nummer (PZN) */ /* Pharmazentral Nummer (PZN) */
/* PZN https://www.ifaffm.de/mandanten/1/documents/04_ifa_coding_system/IFA_Info_Code_39_EN.pdf */
/* PZN https://www.ifaffm.de/mandanten/1/documents/04_ifa_coding_system/
IFA-Info_Check_Digit_Calculations_PZN_PPN_UDI_EN.pdf */
INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length) {
int i, error_number, zeroes; int i, error_number, zeroes;
@ -334,7 +367,7 @@ INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length)
strcpy(symbol->errtxt, "325: Input wrong length (7 character maximum)"); strcpy(symbol->errtxt, "325: Input wrong length (7 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "326: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "326: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -387,6 +420,7 @@ INTERNAL int pzn(struct zint_symbol *symbol, unsigned char source[], int length)
INTERNAL int excode39(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int excode39(struct zint_symbol *symbol, unsigned char source[], int length) {
unsigned char buffer[85 * 2 + 1] = {0}; unsigned char buffer[85 * 2 + 1] = {0};
unsigned char *b = buffer;
int i; int i;
int error_number; int error_number;
@ -402,11 +436,17 @@ INTERNAL int excode39(struct zint_symbol *symbol, unsigned char source[], int le
strcpy(symbol->errtxt, "329: Invalid character in data, extended ASCII not allowed"); strcpy(symbol->errtxt, "329: Invalid character in data, extended ASCII not allowed");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
ustrcat(buffer, EC39Ctrl[source[i]]); memcpy(b, EC39Ctrl[source[i]], 2);
b += EC39Ctrl[source[i]][1] ? 2 : 1;
} }
if (b - buffer > 85) {
strcpy(symbol->errtxt, "317: Expanded input too long (85 symbol character maximum)");
return ZINT_ERROR_TOO_LONG;
}
*b = '\0';
/* Then sends the buffer to the C39 function */ /* Then sends the buffer to the C39 function */
error_number = code39(symbol, buffer, (int) ustrlen(buffer)); error_number = code39(symbol, buffer, b - buffer);
for (i = 0; i < length; i++) for (i = 0; i < length; i++)
symbol->text[i] = source[i] >= ' ' && source[i] != 0x7F ? source[i] : ' '; symbol->text[i] = source[i] >= ' ' && source[i] != 0x7F ? source[i] : ' ';
@ -424,10 +464,11 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng
int i; int i;
int h, weight, c, k, error_number = 0; int h, weight, c, k, error_number = 0;
int values[108]; /* 107 + 1 (1st check) */ int values[110]; /* 107 + 2 (Checks) */
char buffer[216]; /* 107*2 (107 full ASCII) + 1 = 215 */ char buffer[216]; /* 107*2 (107 full ASCII) + 1 = 215 */
char *b = buffer;
char dest[668]; /* 6 (Start) + 107*6 + 2*6 (Checks) + 7 (Stop) + 1 (NUL) = 668 */ char dest[668]; /* 6 (Start) + 107*6 + 2*6 (Checks) + 7 (Stop) + 1 (NUL) = 668 */
char set_copy[] = SILVER; char *d = dest;
/* Suppresses clang-tidy clang-analyzer-core.CallAndMessage warning */ /* Suppresses clang-tidy clang-analyzer-core.CallAndMessage warning */
assert(length > 0); assert(length > 0);
@ -437,8 +478,6 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
*buffer = '\0';
/* Message Content */ /* Message Content */
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
if (source[i] > 127) { if (source[i] > 127) {
@ -446,14 +485,15 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng
strcpy(symbol->errtxt, "331: Invalid character in data, extended ASCII not allowed"); strcpy(symbol->errtxt, "331: Invalid character in data, extended ASCII not allowed");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
strcat(buffer, C93Ctrl[source[i]]); memcpy(b, C93Ctrl[source[i]], 2);
b += C93Ctrl[source[i]][1] ? 2 : 1;
symbol->text[i] = source[i] >= ' ' && source[i] != 0x7F ? source[i] : ' '; symbol->text[i] = source[i] >= ' ' && source[i] != 0x7F ? source[i] : ' ';
} }
/* Now we can check the true length of the barcode */ /* Now we can check the true length of the barcode */
h = (int) strlen(buffer); h = b - buffer;
if (h > 107) { if (h > 107) {
strcpy(symbol->errtxt, "332: Input too long (107 symbol character maximum)"); strcpy(symbol->errtxt, "332: Expanded input too long (107 symbol character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
@ -474,7 +514,6 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng
} }
c = c % 47; c = c % 47;
values[h] = c; values[h] = c;
buffer[h] = set_copy[c];
/* Check digit K */ /* Check digit K */
k = 0; k = 0;
@ -486,19 +525,26 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng
weight = 1; weight = 1;
} }
k = k % 47; k = k % 47;
buffer[++h] = set_copy[k]; values[h + 1] = k;
buffer[++h] = '\0'; h += 2;
if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("Check digit c: %d, k: %d\n", c, k);
}
/* Start character */ /* Start character */
strcpy(dest, "111141"); memcpy(d, "111141", 6);
d += 6;
for (i = 0; i < h; i++) { for (i = 0; i < h; i++, d += 6) {
lookup(SILVER, C93Table, buffer[i], dest); memcpy(d, C93Table[values[i]], 6);
} }
/* Stop character */ /* Stop character */
strcat(dest, "1111411"); memcpy(d, "1111411", 7);
expand(symbol, dest); d += 7;
expand(symbol, dest, d - dest);
if (symbol->output_options & COMPLIANT_HEIGHT) { if (symbol->output_options & COMPLIANT_HEIGHT) {
/* ANSI/AIM BC5-1995 Section 2.6 minimum height 0.2" or 15% of symbol length, whichever is greater /* ANSI/AIM BC5-1995 Section 2.6 minimum height 0.2" or 15% of symbol length, whichever is greater
@ -511,8 +557,8 @@ INTERNAL int code93(struct zint_symbol *symbol, unsigned char source[], int leng
} }
if (symbol->option_2 == 1) { if (symbol->option_2 == 1) {
symbol->text[length] = set_copy[c]; symbol->text[length] = SILVER[c];
symbol->text[length + 1] = set_copy[k]; symbol->text[length + 1] = SILVER[k];
symbol->text[length + 2] = '\0'; symbol->text[length + 2] = '\0';
} }
@ -658,16 +704,16 @@ INTERNAL int channel(struct zint_symbol *symbol, unsigned char source[], int len
static int max_ranges[] = { -1, -1, -1, 26, 292, 3493, 44072, 576688, 7742862 }; static int max_ranges[] = { -1, -1, -1, 26, 292, 3493, 44072, 576688, 7742862 };
int S[8] = {0}, B[8] = {0}; int S[8] = {0}, B[8] = {0};
long target_value = 0; long target_value = 0;
char pattern[30]; char dest[30];
char *d = dest;
int channels, i; int channels, i;
int error_number = 0, zeroes; int error_number = 0, zeroes;
char hrt[9];
if (length > 7) { if (length > 7) {
strcpy(symbol->errtxt, "333: Input too long (7 character maximum)"); strcpy(symbol->errtxt, "333: Input too long (7 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "334: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "334: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -713,24 +759,23 @@ INTERNAL int channel(struct zint_symbol *symbol, unsigned char source[], int len
CHNCHR(channels, target_value, B, S); CHNCHR(channels, target_value, B, S);
strcpy(pattern, "111111111"); /* Finder pattern */ memcpy(d, "111111111", 9); /* Finder pattern */
d += 9;
for (i = 8 - channels; i < 8; i++) { for (i = 8 - channels; i < 8; i++) {
char part[3]; *d++ = itoc(S[i]);
part[0] = itoc(S[i]); *d++ = itoc(B[i]);
part[1] = itoc(B[i]);
part[2] = '\0';
strcat(pattern, part);
} }
zeroes = channels - 1 - length; zeroes = channels - 1 - length;
if (zeroes < 0) { if (zeroes < 0) {
zeroes = 0; zeroes = 0;
} }
memset(hrt, '0', zeroes); if (zeroes) {
ustrcpy(hrt + zeroes, source); memset(symbol->text, '0', zeroes);
ustrcpy(symbol->text, hrt); }
ustrcpy(symbol->text + zeroes, source);
expand(symbol, pattern); expand(symbol, dest, d - dest);
if (symbol->output_options & COMPLIANT_HEIGHT) { if (symbol->output_options & COMPLIANT_HEIGHT) {
/* ANSI/AIM BC12-1998 gives min height as 5mm or 15% of length; X left as application specification so use /* ANSI/AIM BC12-1998 gives min height as 5mm or 15% of length; X left as application specification so use
@ -750,11 +795,10 @@ INTERNAL int vin(struct zint_symbol *symbol, unsigned char source[], int length)
/* This code verifies the check digit present in North American VIN codes */ /* This code verifies the check digit present in North American VIN codes */
char local_source[18];
char dest[200]; /* 10 + 10 + 17 * 10 + 9 + 1 = 200 */ char dest[200]; /* 10 + 10 + 17 * 10 + 9 + 1 = 200 */
char *d = dest;
char input_check; char input_check;
char output_check; char output_check;
int value[17];
int weight[17] = {8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2}; int weight[17] = {8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2};
int sum; int sum;
int i; int i;
@ -766,34 +810,30 @@ INTERNAL int vin(struct zint_symbol *symbol, unsigned char source[], int length)
} }
// Check input characters, I, O and Q are not allowed // Check input characters, I, O and Q are not allowed
if (is_sane(ARSENIC, source, length) != 0) { if (!is_sane(ARSENIC_F, source, length)) {
sprintf(symbol->errtxt, "337: Invalid character in data (\"%s\" only)", ARSENIC); strcpy(symbol->errtxt, "337: Invalid character in data (alphanumerics only, excluding \"I\", \"O\" and \"Q\")");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
ustrcpy(local_source, source); to_upper(source, length);
to_upper((unsigned char *) local_source);
// Check digit only valid for North America // Check digit only valid for North America
if (local_source[0] >= '1' && local_source[0] <= '5') { if (source[0] >= '1' && source[0] <= '5') {
input_check = local_source[8]; input_check = source[8];
for (i = 0; i < 17; i++) {
if ((local_source[i] >= '0') && (local_source[i] <= '9')) {
value[i] = local_source[i] - '0';
} else if ((local_source[i] >= 'A') && (local_source[i] <= 'I')) {
value[i] = (local_source[i] - 'A') + 1;
} else if ((local_source[i] >= 'J') && (local_source[i] <= 'R')) {
value[i] = (local_source[i] - 'J') + 1;
} else if ((local_source[i] >= 'S') && (local_source[i] <= 'Z')) {
value[i] = (local_source[i] - 'S') + 2;
}
}
sum = 0; sum = 0;
for (i = 0; i < 17; i++) { for (i = 0; i < 17; i++) {
sum += value[i] * weight[i]; int value;
if (source[i] <= '9') {
value = source[i] - '0';
} else if (source[i] <= 'H') {
value = (source[i] - 'A') + 1;
} else if (source[i] <= 'R') {
value = (source[i] - 'J') + 1;
} else { /* (source[i] >= 'S') && (source[i] <= 'Z') */
value = (source[i] - 'S') + 2;
}
sum += value * weight[i];
} }
output_check = '0' + (sum % 11); output_check = '0' + (sum % 11);
@ -804,33 +844,39 @@ INTERNAL int vin(struct zint_symbol *symbol, unsigned char source[], int length)
} }
if (symbol->debug & ZINT_DEBUG_PRINT) { if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("Producing VIN code: %s\n", local_source); printf("Producing VIN code: %s\n", source);
printf("Input check was %c, calculated check is %c\n", input_check, output_check); printf("Input check was %c, calculated check is %c\n", input_check, output_check);
} }
if (input_check != output_check) { if (input_check != output_check) {
sprintf(symbol->errtxt, "338: Invalid check digit '%c', expecting '%c'", input_check, output_check); sprintf(symbol->errtxt, "338: Invalid check digit '%c' (position 9), expecting '%c'",
input_check, output_check);
return ZINT_ERROR_INVALID_CHECK; return ZINT_ERROR_INVALID_CHECK;
} }
} }
/* Start character */ /* Start character */
strcpy(dest, "1211212111"); memcpy(d, "1211212111", 10);
d += 10;
/* Import character 'I' prefix? */ /* Import character 'I' prefix? */
if (symbol->option_2 & 1) { if (symbol->option_2 & 1) {
strcat(dest, "1121122111"); memcpy(d, C39Table[18], 10);
d += 10;
} }
// Copy glyphs to symbol // Copy glyphs to symbol
for (i = 0; i < 17; i++) { for (i = 0; i < 17; i++, d += 10) {
lookup(SILVER, C39Table, local_source[i], dest); memcpy(d, C39Table[posn(SILVER, source[i])], 10);
} }
strcat(dest, "121121211"); /* Stop character */
memcpy(d, "121121211", 9);
d += 9;
ustrcpy(symbol->text, local_source); expand(symbol, dest, d - dest);
expand(symbol, dest);
ustrcpy(symbol->text, source);
/* Specification of dimensions/height for BARCODE_VIN unlikely */ /* Specification of dimensions/height for BARCODE_VIN unlikely */

View File

@ -319,7 +319,7 @@ static int is_last_single_ascii(const unsigned char string[], const int length,
if (length - sp == 1 && string[sp] <= 127) { if (length - sp == 1 && string[sp] <= 127) {
return 1; return 1;
} }
if (length - sp == 2 && istwodigits(string, length, sp)) { if (length - sp == 2 && is_twodigits(string, length, sp)) {
return 1; return 1;
} }
return 0; return 0;
@ -591,7 +591,7 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne
} }
if (next_mode == C1_ASCII) { if (next_mode == C1_ASCII) {
if (istwodigits(source, length, sp)) { if (is_twodigits(source, length, sp)) {
if (debug_print) printf("ASCII double-digits "); if (debug_print) printf("ASCII double-digits ");
/* Step B3 */ /* Step B3 */
@ -753,7 +753,7 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne
if (codewords_remaining(symbol, tp) == 1 && (can_ascii || (num_digits[sp] == 1 && bits_left >= 4))) { if (codewords_remaining(symbol, tp) == 1 && (can_ascii || (num_digits[sp] == 1 && bits_left >= 4))) {
if (can_ascii) { if (can_ascii) {
/* Encode last character or last 2 digits as ASCII */ /* Encode last character or last 2 digits as ASCII */
if (istwodigits(source, length, sp)) { if (is_twodigits(source, length, sp)) {
target[tp++] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130; target[tp++] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130;
sp += 2; sp += 2;
} else { } else {
@ -864,7 +864,7 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne
target[tp++] = 255; /* Unlatch */ target[tp++] = 255; /* Unlatch */
for (; sp < length; sp++) { for (; sp < length; sp++) {
if (istwodigits(source, length, sp)) { if (is_twodigits(source, length, sp)) {
target[tp++] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130; target[tp++] = (10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130;
sp++; sp++;
} else if (source[sp] & 0x80) { } else if (source[sp] & 0x80) {
@ -1005,7 +1005,7 @@ INTERNAL int codeone(struct zint_symbol *symbol, unsigned char source[], int len
strcpy(symbol->errtxt, "514: Input data too long for Version S"); strcpy(symbol->errtxt, "514: Input data too long for Version S");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "515: Invalid input data (Version S encodes numeric input only)"); strcpy(symbol->errtxt, "515: Invalid input data (Version S encodes numeric input only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }

View File

@ -2,7 +2,7 @@
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2009-2017 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2009-2021 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -29,6 +29,7 @@
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE. SUCH DAMAGE.
*/ */
/* vim: set ts=4 sw=4 et : */
static const char c40_shift[] = { static const char c40_shift[] = {
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@ -94,9 +95,9 @@ static const unsigned short int c1_grid_height[] = {
5, 7, 10, 15, 21, 30, 46, 68 5, 7, 10, 15, 21, 30, 46, 68
}; };
#define C1_ASCII 1 #define C1_ASCII 1
#define C1_C40 2 #define C1_C40 2
#define C1_DECIMAL 3 #define C1_DECIMAL 3
#define C1_TEXT 4 #define C1_TEXT 4
#define C1_EDI 5 #define C1_EDI 5
#define C1_BYTE 6 #define C1_BYTE 6

View File

@ -41,42 +41,60 @@
#include "code128.h" #include "code128.h"
#include "gs1.h" #include "gs1.h"
static const char KRSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
#define KRSET_F (IS_NUM_F | IS_UPR_F)
/* Code 128 tables checked against ISO/IEC 15417:2007 */ /* Code 128 tables checked against ISO/IEC 15417:2007 */
static const char *C128Table[107] = { INTERNAL_DATA const char C128Table[107][6] = { /* Used by CODABLOCKF and CODE16K also */
/* Code 128 character encodation - Table 1 */ /* Code 128 character encodation - Table 1 (with final CODE16K-only character in place of Stop character) */
/* 0 1 2 3 4 5 6 7 8 9 */ {'2','1','2','2','2','2'}, {'2','2','2','1','2','2'}, {'2','2','2','2','2','1'}, {'1','2','1','2','2','3'},
"212222", "222122", "222221", "121223", "121322", "131222", "122213", "122312", "132212", "221213", /* 0 */ {'1','2','1','3','2','2'}, {'1','3','1','2','2','2'}, {'1','2','2','2','1','3'}, {'1','2','2','3','1','2'},
"221312", "231212", "112232", "122132", "122231", "113222", "123122", "123221", "223211", "221132", /* 10 */ {'1','3','2','2','1','2'}, {'2','2','1','2','1','3'}, {'2','2','1','3','1','2'}, {'2','3','1','2','1','2'},
"221231", "213212", "223112", "312131", "311222", "321122", "321221", "312212", "322112", "322211", /* 20 */ {'1','1','2','2','3','2'}, {'1','2','2','1','3','2'}, {'1','2','2','2','3','1'}, {'1','1','3','2','2','2'},
"212123", "212321", "232121", "111323", "131123", "131321", "112313", "132113", "132311", "211313", /* 30 */ {'1','2','3','1','2','2'}, {'1','2','3','2','2','1'}, {'2','2','3','2','1','1'}, {'2','2','1','1','3','2'},
"231113", "231311", "112133", "112331", "132131", "113123", "113321", "133121", "313121", "211331", /* 40 */ {'2','2','1','2','3','1'}, {'2','1','3','2','1','2'}, {'2','2','3','1','1','2'}, {'3','1','2','1','3','1'},
"231131", "213113", "213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111", /* 50 */ {'3','1','1','2','2','2'}, {'3','2','1','1','2','2'}, {'3','2','1','2','2','1'}, {'3','1','2','2','1','2'},
"314111", "221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214", /* 60 */ {'3','2','2','1','1','2'}, {'3','2','2','2','1','1'}, {'2','1','2','1','2','3'}, {'2','1','2','3','2','1'},
"112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112", "134111", /* 70 */ {'2','3','2','1','2','1'}, {'1','1','1','3','2','3'}, {'1','3','1','1','2','3'}, {'1','3','1','3','2','1'},
"111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112", "421211", "212141", /* 80 */ {'1','1','2','3','1','3'}, {'1','3','2','1','1','3'}, {'1','3','2','3','1','1'}, {'2','1','1','3','1','3'},
"214121", "412121", "111143", "111341", "131141", "114113", "114311", "411113", "411311", "113141", /* 90 */ {'2','3','1','1','1','3'}, {'2','3','1','3','1','1'}, {'1','1','2','1','3','3'}, {'1','1','2','3','3','1'},
"114131", "311141", "411131", "211412", "211214", "211232", "2331112" /*100 */ {'1','3','2','1','3','1'}, {'1','1','3','1','2','3'}, {'1','1','3','3','2','1'}, {'1','3','3','1','2','1'},
{'3','1','3','1','2','1'}, {'2','1','1','3','3','1'}, {'2','3','1','1','3','1'}, {'2','1','3','1','1','3'},
{'2','1','3','3','1','1'}, {'2','1','3','1','3','1'}, {'3','1','1','1','2','3'}, {'3','1','1','3','2','1'},
{'3','3','1','1','2','1'}, {'3','1','2','1','1','3'}, {'3','1','2','3','1','1'}, {'3','3','2','1','1','1'},
{'3','1','4','1','1','1'}, {'2','2','1','4','1','1'}, {'4','3','1','1','1','1'}, {'1','1','1','2','2','4'},
{'1','1','1','4','2','2'}, {'1','2','1','1','2','4'}, {'1','2','1','4','2','1'}, {'1','4','1','1','2','2'},
{'1','4','1','2','2','1'}, {'1','1','2','2','1','4'}, {'1','1','2','4','1','2'}, {'1','2','2','1','1','4'},
{'1','2','2','4','1','1'}, {'1','4','2','1','1','2'}, {'1','4','2','2','1','1'}, {'2','4','1','2','1','1'},
{'2','2','1','1','1','4'}, {'4','1','3','1','1','1'}, {'2','4','1','1','1','2'}, {'1','3','4','1','1','1'},
{'1','1','1','2','4','2'}, {'1','2','1','1','4','2'}, {'1','2','1','2','4','1'}, {'1','1','4','2','1','2'},
{'1','2','4','1','1','2'}, {'1','2','4','2','1','1'}, {'4','1','1','2','1','2'}, {'4','2','1','1','1','2'},
{'4','2','1','2','1','1'}, {'2','1','2','1','4','1'}, {'2','1','4','1','2','1'}, {'4','1','2','1','2','1'},
{'1','1','1','1','4','3'}, {'1','1','1','3','4','1'}, {'1','3','1','1','4','1'}, {'1','1','4','1','1','3'},
{'1','1','4','3','1','1'}, {'4','1','1','1','1','3'}, {'4','1','1','3','1','1'}, {'1','1','3','1','4','1'},
{'1','1','4','1','3','1'}, {'3','1','1','1','4','1'}, {'4','1','1','1','3','1'}, {'2','1','1','4','1','2'},
{'2','1','1','2','1','4'}, {'2','1','1','2','3','2'}, {/* Only used by CODE16K */ '2','1','1','1','3','3'}
}; };
/* Determine appropriate mode for a given character */ /* Determine appropriate mode for a given character */
INTERNAL int parunmodd(const unsigned char llyth) { INTERNAL int c128_parunmodd(const unsigned char llyth) {
int modd; int modd;
if (llyth <= 31) { if (llyth <= 31) {
modd = SHIFTA; modd = C128_SHIFTA;
} else if ((llyth >= 48) && (llyth <= 57)) { } else if ((llyth >= 48) && (llyth <= 57)) {
modd = ABORC; modd = C128_ABORC;
} else if (llyth <= 95) { } else if (llyth <= 95) {
modd = AORB; modd = C128_AORB;
} else if (llyth <= 127) { } else if (llyth <= 127) {
modd = SHIFTB; modd = C128_SHIFTB;
} else if (llyth <= 159) { } else if (llyth <= 159) {
modd = SHIFTA; modd = C128_SHIFTA;
} else if (llyth <= 223) { } else if (llyth <= 223) {
modd = AORB; modd = C128_AORB;
} else { } else {
modd = SHIFTB; modd = C128_SHIFTB;
} }
return modd; return modd;
@ -114,11 +132,11 @@ static void grwp(int list[2][C128_MAX], int *indexliste) {
/** /**
* Implements rules from ISO 15417 Annex E * Implements rules from ISO 15417 Annex E
*/ */
INTERNAL void dxsmooth(int list[2][C128_MAX], int *indexliste) { INTERNAL void c128_dxsmooth(int list[2][C128_MAX], int *indexliste) {
int i, last, next; int i, last, next;
for (i = 0; i < *(indexliste); i++) { for (i = 0; i < *(indexliste); i++) {
int current = list[1][i]; /* Either ABORC, AORB, SHIFTA or SHIFTB */ int current = list[1][i]; /* Either C128_ABORC, C128_AORB, C128_SHIFTA or C128_SHIFTB */
int length = list[0][i]; int length = list[0][i];
if (i != 0) { if (i != 0) {
last = list[1][i - 1]; last = list[1][i - 1];
@ -132,71 +150,71 @@ INTERNAL void dxsmooth(int list[2][C128_MAX], int *indexliste) {
} }
if (i == 0) { /* first block */ if (i == 0) { /* first block */
if (current == ABORC) { if (current == C128_ABORC) {
if ((*(indexliste) == 1) && (length == 2)) { if ((*(indexliste) == 1) && (length == 2)) {
/* Rule 1a */ /* Rule 1a */
list[1][i] = LATCHC; list[1][i] = C128_LATCHC;
current = LATCHC; current = C128_LATCHC;
} else if (length >= 4) { } else if (length >= 4) {
/* Rule 1b */ /* Rule 1b */
list[1][i] = LATCHC; list[1][i] = C128_LATCHC;
current = LATCHC; current = C128_LATCHC;
} else { } else {
current = AORB; /* Determine below */ current = C128_AORB; /* Determine below */
} }
} }
if (current == AORB) { if (current == C128_AORB) {
if (next == SHIFTA) { if (next == C128_SHIFTA) {
/* Rule 1c */ /* Rule 1c */
list[1][i] = LATCHA; list[1][i] = C128_LATCHA;
} else { } else {
/* Rule 1d */ /* Rule 1d */
list[1][i] = LATCHB; list[1][i] = C128_LATCHB;
} }
} else if (current == SHIFTA) { } else if (current == C128_SHIFTA) {
/* Rule 1c */ /* Rule 1c */
list[1][i] = LATCHA; list[1][i] = C128_LATCHA;
} else if (current == SHIFTB) { /* Unless LATCHC set above, can only be SHIFTB */ } else if (current == C128_SHIFTB) { /* Unless C128_LATCHC set above, can only be C128_SHIFTB */
/* Rule 1d */ /* Rule 1d */
list[1][i] = LATCHB; list[1][i] = C128_LATCHB;
} }
} else { } else {
if (current == ABORC) { if (current == C128_ABORC) {
if (length >= 4) { if (length >= 4) {
/* Rule 3 */ /* Rule 3 */
list[1][i] = LATCHC; list[1][i] = C128_LATCHC;
current = LATCHC; current = C128_LATCHC;
} else { } else {
current = AORB; /* Determine below */ current = C128_AORB; /* Determine below */
} }
} }
if (current == AORB) { if (current == C128_AORB) {
if (last == LATCHA || last == SHIFTB) { /* Maintain state */ if (last == C128_LATCHA || last == C128_SHIFTB) { /* Maintain state */
list[1][i] = LATCHA; list[1][i] = C128_LATCHA;
} else if (last == LATCHB || last == SHIFTA) { /* Maintain state */ } else if (last == C128_LATCHB || last == C128_SHIFTA) { /* Maintain state */
list[1][i] = LATCHB; list[1][i] = C128_LATCHB;
} else if (next == SHIFTA) { } else if (next == C128_SHIFTA) {
list[1][i] = LATCHA; list[1][i] = C128_LATCHA;
} else { } else {
list[1][i] = LATCHB; list[1][i] = C128_LATCHB;
} }
} else if (current == SHIFTA) { } else if (current == C128_SHIFTA) {
if (length > 1) { if (length > 1) {
/* Rule 4 */ /* Rule 4 */
list[1][i] = LATCHA; list[1][i] = C128_LATCHA;
} else if (last == LATCHA || last == SHIFTB) { /* Maintain state */ } else if (last == C128_LATCHA || last == C128_SHIFTB) { /* Maintain state */
list[1][i] = LATCHA; list[1][i] = C128_LATCHA;
} else if (last == LATCHC) { } else if (last == C128_LATCHC) {
list[1][i] = LATCHA; list[1][i] = C128_LATCHA;
} }
} else if (current == SHIFTB) { /* Unless LATCHC set above, can only be SHIFTB */ } else if (current == C128_SHIFTB) { /* Unless C128_LATCHC set above, can only be C128_SHIFTB */
if (length > 1) { if (length > 1) {
/* Rule 5 */ /* Rule 5 */
list[1][i] = LATCHB; list[1][i] = C128_LATCHB;
} else if (last == LATCHB || last == SHIFTA) { /* Maintain state */ } else if (last == C128_LATCHB || last == C128_SHIFTA) { /* Maintain state */
list[1][i] = LATCHB; list[1][i] = C128_LATCHB;
} else if (last == LATCHC) { } else if (last == C128_LATCHC) {
list[1][i] = LATCHB; list[1][i] = C128_LATCHB;
} }
} }
} /* Rule 2 is implemented elsewhere, Rule 6 is implied */ } /* Rule 2 is implemented elsewhere, Rule 6 is implied */
@ -209,22 +227,18 @@ INTERNAL void dxsmooth(int list[2][C128_MAX], int *indexliste) {
* Translate Code 128 Set A characters into barcodes. * Translate Code 128 Set A characters into barcodes.
* This set handles all control characters NUL to US. * This set handles all control characters NUL to US.
*/ */
static void c128_set_a(const unsigned char source, char dest[], int values[], int *bar_chars) { INTERNAL void c128_set_a(const unsigned char source, int values[], int *bar_chars) {
if (source > 127) { if (source > 127) {
if (source < 160) { if (source < 160) {
strcat(dest, C128Table[(source - 128) + 64]);
values[(*bar_chars)] = (source - 128) + 64; values[(*bar_chars)] = (source - 128) + 64;
} else { } else {
strcat(dest, C128Table[(source - 128) - 32]);
values[(*bar_chars)] = (source - 128) - 32; values[(*bar_chars)] = (source - 128) - 32;
} }
} else { } else {
if (source < 32) { if (source < 32) {
strcat(dest, C128Table[source + 64]);
values[(*bar_chars)] = source + 64; values[(*bar_chars)] = source + 64;
} else { } else {
strcat(dest, C128Table[source - 32]);
values[(*bar_chars)] = source - 32; values[(*bar_chars)] = source - 32;
} }
} }
@ -236,14 +250,12 @@ static void c128_set_a(const unsigned char source, char dest[], int values[], in
* This set handles all characters which are not part of long numbers and not * This set handles all characters which are not part of long numbers and not
* control characters. * control characters.
*/ */
static int c128_set_b(const unsigned char source, char dest[], int values[], int *bar_chars) { INTERNAL int c128_set_b(const unsigned char source, int values[], int *bar_chars) {
if (source >= 128 + 32) { if (source >= 128 + 32) {
strcat(dest, C128Table[source - 32 - 128]);
values[(*bar_chars)] = source - 32 - 128; values[(*bar_chars)] = source - 32 - 128;
} else if (source >= 128) { /* Should never happen */ } else if (source >= 128) { /* Should never happen */
return 0; /* Not reached */ return 0; /* Not reached */
} else if (source >= 32) { } else if (source >= 32) {
strcat(dest, C128Table[source - 32]);
values[(*bar_chars)] = source - 32; values[(*bar_chars)] = source - 32;
} else { /* Should never happen */ } else { /* Should never happen */
return 0; /* Not reached */ return 0; /* Not reached */
@ -255,16 +267,80 @@ static int c128_set_b(const unsigned char source, char dest[], int values[], int
/* Translate Code 128 Set C characters into barcodes /* Translate Code 128 Set C characters into barcodes
* This set handles numbers in a compressed form * This set handles numbers in a compressed form
*/ */
static void c128_set_c(const unsigned char source_a, const unsigned char source_b, char dest[], int values[], INTERNAL void c128_set_c(const unsigned char source_a, const unsigned char source_b, int values[], int *bar_chars) {
int *bar_chars) {
int weight; int weight;
weight = (10 * ctoi(source_a)) + ctoi(source_b); weight = (10 * ctoi(source_a)) + ctoi(source_b);
strcat(dest, C128Table[weight]);
values[(*bar_chars)] = weight; values[(*bar_chars)] = weight;
(*bar_chars)++; (*bar_chars)++;
} }
/* Put set data into set[]. If source given (GS1_MODE) then resolves odd C blocks */
INTERNAL void c128_put_in_set(int list[2][C128_MAX], const int indexliste, char set[C128_MAX],
unsigned char *source) {
int read = 0;
int i, j;
for (i = 0; i < indexliste; i++) {
for (j = 0; j < list[0][i]; j++) {
switch (list[1][i]) {
case C128_SHIFTA: set[read] = 'a';
break;
case C128_LATCHA: set[read] = 'A';
break;
case C128_SHIFTB: set[read] = 'b';
break;
case C128_LATCHB: set[read] = 'B';
break;
case C128_LATCHC: set[read] = 'C';
break;
}
read++;
}
}
if (source) {
/* Watch out for odd-length Mode C blocks */
int c_count = 0;
for (i = 0; i < read; i++) {
if (set[i] == 'C') {
if (source[i] == '[') {
if (c_count & 1) {
if ((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
c_count = 0;
} else {
c_count++;
}
} else {
if (c_count & 1) {
if ((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
c_count = 0;
}
}
if (c_count & 1) {
if ((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
for (i = 1; i < read - 1; i++) {
if ((set[i] == 'C') && ((set[i - 1] == 'B') && (set[i + 1] == 'B'))) {
set[i] = 'B';
}
}
}
}
/* Treats source as ISO 8859-1 and copies into symbol->text, converting to UTF-8. Returns length of symbol->text */ /* Treats source as ISO 8859-1 and copies into symbol->text, converting to UTF-8. Returns length of symbol->text */
STATIC_UNLESS_ZINT_TEST int hrt_cpy_iso8859_1(struct zint_symbol *symbol, const unsigned char *source, STATIC_UNLESS_ZINT_TEST int hrt_cpy_iso8859_1(struct zint_symbol *symbol, const unsigned char *source,
const int source_len) { const int source_len) {
@ -308,12 +384,12 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
char set[C128_MAX] = {0}, fset[C128_MAX], mode, last_set, current_set = ' '; char set[C128_MAX] = {0}, fset[C128_MAX], mode, last_set, current_set = ' ';
float glyph_count; float glyph_count;
char dest[1000]; char dest[1000];
char *d = dest;
/* Suppresses clang-analyzer-core.UndefinedBinaryOperatorResult warning on fset which is fully set */ /* Suppresses clang-analyzer-core.UndefinedBinaryOperatorResult warning on fset which is fully set */
assert(length > 0); assert(length > 0);
error_number = 0; error_number = 0;
strcpy(dest, "");
sourcelen = length; sourcelen = length;
@ -378,9 +454,9 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
indexliste = 0; indexliste = 0;
indexchaine = 0; indexchaine = 0;
mode = parunmodd(source[indexchaine]); mode = c128_parunmodd(source[indexchaine]);
if ((symbol->symbology == BARCODE_CODE128B) && (mode == ABORC)) { if ((symbol->symbology == BARCODE_CODE128B) && (mode == C128_ABORC)) {
mode = AORB; mode = C128_AORB;
} }
do { do {
@ -391,30 +467,30 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
if (indexchaine == sourcelen) { if (indexchaine == sourcelen) {
break; break;
} }
mode = parunmodd(source[indexchaine]); mode = c128_parunmodd(source[indexchaine]);
if ((symbol->symbology == BARCODE_CODE128B) && (mode == ABORC)) { if ((symbol->symbology == BARCODE_CODE128B) && (mode == C128_ABORC)) {
mode = AORB; mode = C128_AORB;
} }
} }
indexliste++; indexliste++;
} while (indexchaine < sourcelen); } while (indexchaine < sourcelen);
dxsmooth(list, &indexliste); c128_dxsmooth(list, &indexliste);
/* Resolve odd length LATCHC blocks */ /* Resolve odd length C128_LATCHC blocks */
if ((list[1][0] == LATCHC) && (list[0][0] & 1)) { if ((list[1][0] == C128_LATCHC) && (list[0][0] & 1)) {
/* Rule 2 */ /* Rule 2 */
list[0][1]++; list[0][1]++;
list[0][0]--; list[0][0]--;
if (indexliste == 1) { if (indexliste == 1) {
list[0][1] = 1; list[0][1] = 1;
list[1][1] = LATCHB; list[1][1] = C128_LATCHB;
indexliste = 2; indexliste = 2;
} }
} }
if (indexliste > 1) { if (indexliste > 1) {
for (i = 1; i < indexliste; i++) { for (i = 1; i < indexliste; i++) {
if ((list[1][i] == LATCHC) && (list[0][i] & 1)) { if ((list[1][i] == C128_LATCHC) && (list[0][i] & 1)) {
/* Rule 3b */ /* Rule 3b */
list[0][i - 1]++; list[0][i - 1]++;
list[0][i]--; list[0][i]--;
@ -422,26 +498,8 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
} }
} }
/* Put set data into set[] */ /* Put set data into set[]. Giving NULL as source as used to resolve odd C blocks which has been done above */
c128_put_in_set(list, indexliste, set, NULL /*source*/);
read = 0;
for (i = 0; i < indexliste; i++) {
for (j = 0; j < list[0][i]; j++) {
switch (list[1][i]) {
case SHIFTA: set[read] = 'a';
break;
case LATCHA: set[read] = 'A';
break;
case SHIFTB: set[read] = 'b';
break;
case LATCHB: set[read] = 'B';
break;
case LATCHC: set[read] = 'C';
break;
}
read++;
}
}
if (symbol->debug & ZINT_DEBUG_PRINT) { if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("Data: %.*s (%d)\n", sourcelen, source, sourcelen); printf("Data: %.*s (%d)\n", sourcelen, source, sourcelen);
@ -495,29 +553,19 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
/* Reader Initialisation mode */ /* Reader Initialisation mode */
switch (set[0]) { switch (set[0]) {
case 'A': /* Start A */ case 'A': /* Start A */
strcat(dest, C128Table[103]); values[bar_characters++] = 103;
values[0] = 103;
current_set = 'A'; current_set = 'A';
strcat(dest, C128Table[96]); /* FNC3 */ values[bar_characters++] = 96; /* FNC3 */
values[1] = 96;
bar_characters++;
break; break;
case 'B': /* Start B */ case 'B': /* Start B */
strcat(dest, C128Table[104]); values[bar_characters++] = 104;
values[0] = 104;
current_set = 'B'; current_set = 'B';
strcat(dest, C128Table[96]); /* FNC3 */ values[bar_characters++] = 96; /* FNC3 */
values[1] = 96;
bar_characters++;
break; break;
case 'C': /* Start C */ case 'C': /* Start C */
strcat(dest, C128Table[104]); /* Start B */ values[bar_characters++] = 104; /* Start B */
values[0] = 104; values[bar_characters++] = 96; /* FNC3 */
strcat(dest, C128Table[96]); /* FNC3 */ values[bar_characters++] = 99; /* Code C */
values[1] = 96;
strcat(dest, C128Table[99]); /* Code C */
values[2] = 99;
bar_characters += 2;
current_set = 'C'; current_set = 'C';
break; break;
} }
@ -525,40 +573,31 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
/* Normal mode */ /* Normal mode */
switch (set[0]) { switch (set[0]) {
case 'A': /* Start A */ case 'A': /* Start A */
strcat(dest, C128Table[103]); values[bar_characters++] = 103;
values[0] = 103;
current_set = 'A'; current_set = 'A';
break; break;
case 'B': /* Start B */ case 'B': /* Start B */
strcat(dest, C128Table[104]); values[bar_characters++] = 104;
values[0] = 104;
current_set = 'B'; current_set = 'B';
break; break;
case 'C': /* Start C */ case 'C': /* Start C */
strcat(dest, C128Table[105]); values[bar_characters++] = 105;
values[0] = 105;
current_set = 'C'; current_set = 'C';
break; break;
} }
} }
bar_characters++;
if (fset[0] == 'F') { if (fset[0] == 'F') {
switch (current_set) { switch (current_set) {
case 'A': case 'A':
strcat(dest, C128Table[101]); values[bar_characters++] = 101;
strcat(dest, C128Table[101]); values[bar_characters++] = 101;
values[bar_characters] = 101;
values[bar_characters + 1] = 101;
break; break;
case 'B': case 'B':
strcat(dest, C128Table[100]); values[bar_characters++] = 100;
strcat(dest, C128Table[100]); values[bar_characters++] = 100;
values[bar_characters] = 100;
values[bar_characters + 1] = 100;
break; break;
} }
bar_characters += 2;
f_state = 1; f_state = 1;
} }
@ -569,19 +608,16 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
if ((read != 0) && (set[read] != current_set)) { if ((read != 0) && (set[read] != current_set)) {
/* Latch different code set */ /* Latch different code set */
switch (set[read]) { switch (set[read]) {
case 'A': strcat(dest, C128Table[101]); case 'A':
values[bar_characters] = 101; values[bar_characters++] = 101;
bar_characters++;
current_set = 'A'; current_set = 'A';
break; break;
case 'B': strcat(dest, C128Table[100]); case 'B':
values[bar_characters] = 100; values[bar_characters++] = 100;
bar_characters++;
current_set = 'B'; current_set = 'B';
break; break;
case 'C': strcat(dest, C128Table[99]); case 'C':
values[bar_characters] = 99; values[bar_characters++] = 99;
bar_characters++;
current_set = 'C'; current_set = 'C';
break; break;
} }
@ -592,38 +628,28 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
/* Latch beginning of extended mode */ /* Latch beginning of extended mode */
switch (current_set) { switch (current_set) {
case 'A': case 'A':
strcat(dest, C128Table[101]); values[bar_characters++] = 101;
strcat(dest, C128Table[101]); values[bar_characters++] = 101;
values[bar_characters] = 101;
values[bar_characters + 1] = 101;
break; break;
case 'B': case 'B':
strcat(dest, C128Table[100]); values[bar_characters++] = 100;
strcat(dest, C128Table[100]); values[bar_characters++] = 100;
values[bar_characters] = 100;
values[bar_characters + 1] = 100;
break; break;
} }
bar_characters += 2;
f_state = 1; f_state = 1;
} }
if ((fset[read] == ' ') && (f_state == 1)) { if ((fset[read] == ' ') && (f_state == 1)) {
/* Latch end of extended mode */ /* Latch end of extended mode */
switch (current_set) { switch (current_set) {
case 'A': case 'A':
strcat(dest, C128Table[101]); values[bar_characters++] = 101;
strcat(dest, C128Table[101]); values[bar_characters++] = 101;
values[bar_characters] = 101;
values[bar_characters + 1] = 101;
break; break;
case 'B': case 'B':
strcat(dest, C128Table[100]); values[bar_characters++] = 100;
strcat(dest, C128Table[100]); values[bar_characters++] = 100;
values[bar_characters] = 100;
values[bar_characters + 1] = 100;
break; break;
} }
bar_characters += 2;
f_state = 0; f_state = 0;
} }
} }
@ -632,54 +658,53 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
/* Shift to or from extended mode */ /* Shift to or from extended mode */
switch (current_set) { switch (current_set) {
case 'A': case 'A':
strcat(dest, C128Table[101]); /* FNC 4 */ values[bar_characters++] = 101; /* FNC 4 */
values[bar_characters] = 101;
break; break;
case 'B': case 'B':
strcat(dest, C128Table[100]); /* FNC 4 */ values[bar_characters++] = 100; /* FNC 4 */
values[bar_characters] = 100;
break; break;
} }
bar_characters++;
} }
if ((set[read] == 'a') || (set[read] == 'b')) { if ((set[read] == 'a') || (set[read] == 'b')) {
/* Insert shift character */ /* Insert shift character */
strcat(dest, C128Table[98]); values[bar_characters++] = 98;
values[bar_characters] = 98;
bar_characters++;
} }
switch (set[read]) { /* Encode data characters */ switch (set[read]) { /* Encode data characters */
case 'a': case 'a':
case 'A': c128_set_a(source[read], dest, values, &bar_characters); case 'A': c128_set_a(source[read], values, &bar_characters);
read++; read++;
break; break;
case 'b': case 'b':
case 'B': (void) c128_set_b(source[read], dest, values, &bar_characters); case 'B': (void) c128_set_b(source[read], values, &bar_characters);
read++; read++;
break; break;
case 'C': c128_set_c(source[read], source[read + 1], dest, values, &bar_characters); case 'C': c128_set_c(source[read], source[read + 1], values, &bar_characters);
read += 2; read += 2;
break; break;
} }
} while (read < sourcelen); } while (read < sourcelen);
/* check digit calculation */ /* Destination setting and check digit calculation */
total_sum = values[0] % 103; /* Mod as we go along to avoid overflow */ memcpy(d, C128Table[values[0]], 6);
d += 6;
total_sum = values[0];
for (i = 1; i < bar_characters; i++) { for (i = 1; i < bar_characters; i++, d += 6) {
total_sum = (total_sum + values[i] * i) % 103; memcpy(d, C128Table[values[i]], 6);
total_sum += values[i] * i; /* Note can't overflow as 106 * 60 * 60 = 381600 */
} }
strcat(dest, C128Table[total_sum]); total_sum %= 103;
values[bar_characters] = total_sum; memcpy(d, C128Table[total_sum], 6);
bar_characters++; d += 6;
values[bar_characters++] = total_sum;
/* Stop character */ /* Stop character */
strcat(dest, C128Table[106]); memcpy(d, "2331112", 7);
values[bar_characters] = 106; d += 7;
bar_characters++; values[bar_characters++] = 106;
if (symbol->debug & ZINT_DEBUG_PRINT) { if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("Codewords:"); printf("Codewords:");
@ -695,7 +720,7 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
} }
#endif #endif
expand(symbol, dest); expand(symbol, dest, d - dest);
/* ISO/IEC 15417:2007 leaves dimensions/height as application specification */ /* ISO/IEC 15417:2007 leaves dimensions/height as application specification */
@ -707,13 +732,14 @@ INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int len
/* Handle EAN-128 (Now known as GS1-128), and composite version if `cc_mode` set */ /* Handle EAN-128 (Now known as GS1-128), and composite version if `cc_mode` set */
INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_mode, INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_mode,
const int cc_rows) { const int cc_rows) {
int i, j, values[C128_MAX] = {0}, bar_characters, read, total_sum; int i, values[C128_MAX] = {0}, bar_characters, read, total_sum;
int error_number, warn_number = 0, indexchaine, indexliste; int error_number, warn_number = 0, indexchaine, indexliste;
int list[2][C128_MAX] = {{0}}; int list[2][C128_MAX] = {{0}};
char set[C128_MAX] = {0}, mode, last_set; char set[C128_MAX] = {0}, mode, last_set;
float glyph_count; float glyph_count;
char dest[1000]; char dest[1000];
int separator_row, linkage_flag, c_count; char *d = dest;
int separator_row, linkage_flag;
int reduced_length; int reduced_length;
#ifndef _MSC_VER #ifndef _MSC_VER
unsigned char reduced[length + 1]; unsigned char reduced[length + 1];
@ -721,7 +747,6 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int
unsigned char *reduced = (unsigned char *) _alloca(length + 1); unsigned char *reduced = (unsigned char *) _alloca(length + 1);
#endif #endif
strcpy(dest, "");
linkage_flag = 0; linkage_flag = 0;
bar_characters = 0; bar_characters = 0;
@ -752,7 +777,7 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int
indexliste = 0; indexliste = 0;
indexchaine = 0; indexchaine = 0;
mode = parunmodd(reduced[indexchaine]); mode = c128_parunmodd(reduced[indexchaine]);
do { do {
list[1][indexliste] = mode; list[1][indexliste] = mode;
@ -762,76 +787,18 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int
if (indexchaine == reduced_length) { if (indexchaine == reduced_length) {
break; break;
} }
mode = parunmodd(reduced[indexchaine]); mode = c128_parunmodd(reduced[indexchaine]);
if (reduced[indexchaine] == '[') { if (reduced[indexchaine] == '[') {
mode = ABORC; mode = C128_ABORC;
} }
} }
indexliste++; indexliste++;
} while (indexchaine < reduced_length); } while (indexchaine < reduced_length);
dxsmooth(list, &indexliste); c128_dxsmooth(list, &indexliste);
/* Put set data into set[] */ /* Put set data into set[], resolving odd C blocks */
/* Note as control chars not permitted in GS1, no reason to ever be in Set A, but cases left in anyway */ c128_put_in_set(list, indexliste, set, reduced);
read = 0;
for (i = 0; i < indexliste; i++) {
for (j = 0; j < list[0][i]; j++) {
switch (list[1][i]) {
case SHIFTA: set[read] = 'a'; /* Not reached */
break;
case LATCHA: set[read] = 'A'; /* Not reached */
break;
case SHIFTB: set[read] = 'b'; /* Not reached */
break;
case LATCHB: set[read] = 'B';
break;
case LATCHC: set[read] = 'C';
break;
}
read++;
}
}
/* Watch out for odd-length Mode C blocks */
c_count = 0;
for (i = 0; i < read; i++) {
if (set[i] == 'C') {
if (reduced[i] == '[') {
if (c_count & 1) {
if ((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
c_count = 0;
} else {
c_count++;
}
} else {
if (c_count & 1) {
if ((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
c_count = 0;
}
}
if (c_count & 1) {
if ((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
for (i = 1; i < read - 1; i++) {
if ((set[i] == 'C') && ((set[i - 1] == 'B') && (set[i + 1] == 'B'))) {
set[i] = 'B';
}
}
if (symbol->debug & ZINT_DEBUG_PRINT) { if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("Data: %s (%d)\n", reduced, reduced_length); printf("Data: %s (%d)\n", reduced, reduced_length);
@ -866,23 +833,17 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int
/* So now we know what start character to use - we can get on with it! */ /* So now we know what start character to use - we can get on with it! */
switch (set[0]) { switch (set[0]) {
case 'A': /* Start A */ case 'A': /* Start A */
strcat(dest, C128Table[103]); /* Not reached */ values[bar_characters++] = 103; /* Not reached */
values[0] = 103;
break; break;
case 'B': /* Start B */ case 'B': /* Start B */
strcat(dest, C128Table[104]); values[bar_characters++] = 104;
values[0] = 104;
break; break;
case 'C': /* Start C */ case 'C': /* Start C */
strcat(dest, C128Table[105]); values[bar_characters++] = 105;
values[0] = 105;
break; break;
} }
bar_characters++;
strcat(dest, C128Table[102]); values[bar_characters++] = 102;
values[1] = 102;
bar_characters++;
/* Encode the data */ /* Encode the data */
read = 0; read = 0;
@ -890,49 +851,42 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int
if ((read != 0) && (set[read] != set[read - 1])) { /* Latch different code set */ if ((read != 0) && (set[read] != set[read - 1])) { /* Latch different code set */
switch (set[read]) { switch (set[read]) {
case 'A': strcat(dest, C128Table[101]); /* Not reached */ case 'A':
values[bar_characters] = 101; values[bar_characters++] = 101; /* Not reached */
bar_characters++;
break; break;
case 'B': strcat(dest, C128Table[100]); case 'B':
values[bar_characters] = 100; values[bar_characters++] = 100;
bar_characters++;
break; break;
case 'C': strcat(dest, C128Table[99]); case 'C':
values[bar_characters] = 99; values[bar_characters++] = 99;
bar_characters++;
break; break;
} }
} }
if ((set[read] == 'a') || (set[read] == 'b')) { if ((set[read] == 'a') || (set[read] == 'b')) {
/* Insert shift character */ /* Insert shift character */
strcat(dest, C128Table[98]); /* Not reached */ values[bar_characters++] = 98; /* Not reached */
values[bar_characters] = 98;
bar_characters++;
} }
if (reduced[read] != '[') { if (reduced[read] != '[') {
switch (set[read]) { /* Encode data characters */ switch (set[read]) { /* Encode data characters */
case 'A': case 'A':
case 'a': case 'a':
c128_set_a(reduced[read], dest, values, &bar_characters); /* Not reached */ c128_set_a(reduced[read], values, &bar_characters); /* Not reached */
read++; read++;
break; break;
case 'B': case 'B':
case 'b': case 'b':
(void) c128_set_b(reduced[read], dest, values, &bar_characters); (void) c128_set_b(reduced[read], values, &bar_characters);
read++; read++;
break; break;
case 'C': case 'C':
c128_set_c(reduced[read], reduced[read + 1], dest, values, &bar_characters); c128_set_c(reduced[read], reduced[read + 1], values, &bar_characters);
read += 2; read += 2;
break; break;
} }
} else { } else {
strcat(dest, C128Table[102]); values[bar_characters++] = 102;
values[bar_characters] = 102;
bar_characters++;
read++; read++;
} }
} while (read < reduced_length); } while (read < reduced_length);
@ -969,25 +923,27 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int
} }
if (linkage_flag != 0) { if (linkage_flag != 0) {
strcat(dest, C128Table[linkage_flag]); values[bar_characters++] = linkage_flag;
values[bar_characters] = linkage_flag;
bar_characters++;
} }
/* check digit calculation */ /* Destination setting and check digit calculation */
total_sum = values[0] % 103; /* Mod as we go along to avoid overflow */ memcpy(d, C128Table[values[0]], 6);
d += 6;
total_sum = values[0];
for (i = 1; i < bar_characters; i++) { for (i = 1; i < bar_characters; i++, d += 6) {
total_sum = (total_sum + values[i] * i) % 103; memcpy(d, C128Table[values[i]], 6);
total_sum += values[i] * i; /* Note can't overflow as 106 * 60 * 60 = 381600 */
} }
strcat(dest, C128Table[total_sum]); total_sum %= 103;
values[bar_characters] = total_sum; memcpy(d, C128Table[total_sum], 6);
bar_characters++; d += 6;
values[bar_characters++] = total_sum;
/* Stop character */ /* Stop character */
strcat(dest, C128Table[106]); memcpy(d, "2331112", 7);
values[bar_characters] = 106; d += 7;
bar_characters++; values[bar_characters++] = 106;
if (symbol->debug & ZINT_DEBUG_PRINT) { if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("Codewords:"); printf("Codewords:");
@ -1003,7 +959,7 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int
} }
#endif #endif
expand(symbol, dest); expand(symbol, dest, d - dest);
/* Add the separator pattern for composite symbols */ /* Add the separator pattern for composite symbols */
if (symbol->symbology == BARCODE_GS1_128_CC) { if (symbol->symbology == BARCODE_GS1_128_CC) {
@ -1057,6 +1013,7 @@ INTERNAL int gs1_128(struct zint_symbol *symbol, unsigned char source[], int len
INTERNAL int nve18(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int nve18(struct zint_symbol *symbol, unsigned char source[], int length) {
int i, count, check_digit; int i, count, check_digit;
int error_number, zeroes; int error_number, zeroes;
int factor;
unsigned char ean128_equiv[23]; unsigned char ean128_equiv[23];
if (length > 17) { if (length > 17) {
@ -1064,7 +1021,7 @@ INTERNAL int nve18(struct zint_symbol *symbol, unsigned char source[], int lengt
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "346: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "346: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -1075,8 +1032,10 @@ INTERNAL int nve18(struct zint_symbol *symbol, unsigned char source[], int lengt
ustrcpy(ean128_equiv + 4 + zeroes, source); ustrcpy(ean128_equiv + 4 + zeroes, source);
count = 0; count = 0;
factor = 3;
for (i = 20; i >= 4; i--) { for (i = 20; i >= 4; i--) {
count += i & 1 ? ctoi(ean128_equiv[i]) : 3 * ctoi(ean128_equiv[i]); count += ctoi(ean128_equiv[i]) * factor;
factor ^= 2; /* Toggles 1 and 3 */
} }
check_digit = 10 - count % 10; check_digit = 10 - count % 10;
if (check_digit == 10) { if (check_digit == 10) {
@ -1101,7 +1060,7 @@ INTERNAL int ean14(struct zint_symbol *symbol, unsigned char source[], int lengt
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "348: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "348: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -1144,8 +1103,8 @@ INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length)
identifier = source[0]; identifier = source[0];
to_upper(source + 1); to_upper(source + 1, length - 1);
if (is_sane(KRSET, source + 1, length - 1) != 0) { if (!is_sane(KRSET_F, source + 1, length - 1)) {
strcpy(symbol->errtxt, "300: Invalid character in DPD data (alphanumerics only)"); strcpy(symbol->errtxt, "300: Invalid character in DPD data (alphanumerics only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }

View File

@ -38,19 +38,26 @@ extern "C" {
#define C128_MAX 160 #define C128_MAX 160
#define SHIFTA 90 #define C128_SHIFTA 90
#define LATCHA 91 #define C128_LATCHA 91
#define SHIFTB 92 #define C128_SHIFTB 92
#define LATCHB 93 #define C128_LATCHB 93
#define SHIFTC 94 #define C128_SHIFTC 94
#define LATCHC 95 #define C128_LATCHC 95
#define AORB 96 #define C128_AORB 96
#define ABORC 97 #define C128_ABORC 97
#define KRSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int length);
INTERNAL int parunmodd(const unsigned char llyth); INTERNAL int c128_parunmodd(const unsigned char llyth);
INTERNAL void dxsmooth(int list[2][C128_MAX], int *indexliste); INTERNAL void c128_dxsmooth(int list[2][C128_MAX], int *indexliste);
INTERNAL void c128_set_a(const unsigned char source, int values[], int *bar_chars);
INTERNAL int c128_set_b(const unsigned char source, int values[], int *bar_chars);
INTERNAL void c128_set_c(const unsigned char source_a, const unsigned char source_b, int values[], int *bar_chars);
INTERNAL void c128_put_in_set(int list[2][C128_MAX], const int indexliste, char set[C128_MAX],
unsigned char *source);
INTERNAL_DATA_EXTERN const char C128Table[107][6];
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -40,27 +40,12 @@
#include "common.h" #include "common.h"
#include "code128.h" #include "code128.h"
static const char *C16KTable[107] = { /* Note using C128Table with extra entry at 106 (Triple Shift) for C16KTable */
/* EN 12323 Table 1 - "Code 16K" character encodations */
"212222", "222122", "222221", "121223", "121322", "131222", "122213",
"122312", "132212", "221213", "221312", "231212", "112232", "122132", "122231", "113222",
"123122", "123221", "223211", "221132", "221231", "213212", "223112", "312131", "311222",
"321122", "321221", "312212", "322112", "322211", "212123", "212321", "232121", "111323",
"131123", "131321", "112313", "132113", "132311", "211313", "231113", "231311", "112133",
"112331", "132131", "113123", "113321", "133121", "313121", "211331", "231131", "213113",
"213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111", "314111",
"221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214",
"112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112",
"134111", "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112",
"421211", "212141", "214121", "412121", "111143", "111341", "131141", "114113", "114311",
"411113", "411311", "113141", "114131", "311141", "411131", "211412", "211214", "211232",
"211133"
};
static const char C16KStartStop[8][4] = {
static const char *C16KStartStop[8] = {
/* EN 12323 Table 3 and Table 4 - Start patterns and stop patterns */ /* EN 12323 Table 3 and Table 4 - Start patterns and stop patterns */
"3211", "2221", "2122", "1411", "1132", "1231", "1114", "3112" {'3','2','1','1'}, {'2','2','2','1'}, {'2','1','2','2'}, {'1','4','1','1'},
{'1','1','3','2'}, {'1','2','3','1'}, {'1','1','1','4'}, {'3','1','1','2'}
}; };
/* EN 12323 Table 5 - Start and stop values defining row numbers */ /* EN 12323 Table 5 - Start and stop values defining row numbers */
@ -72,58 +57,23 @@ static const int C16KStopValues[16] = {
0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 0, 1, 2, 3 0, 1, 2, 3, 4, 5, 6, 7, 4, 5, 6, 7, 0, 1, 2, 3
}; };
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;
} else {
values[(*bar_chars)] = source - 32 - 128;
}
} else {
if (source < 32) {
values[(*bar_chars)] = source + 64;
} else {
values[(*bar_chars)] = source - 32;
}
}
(*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 {
values[(*bar_chars)] = source - 32;
}
(*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);
values[(*bar_chars)] = weight;
(*bar_chars)++;
}
INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int length) {
char width_pattern[100]; char width_pattern[100];
int current_row, rows, looper, first_check, second_check; int current_row, rows, looper, first_check, second_check;
int indexchaine; int indexchaine;
int list[2][C128_MAX] = {{0}}; int list[2][C128_MAX] = {{0}};
char set[C128_MAX] = {0}, fset[C128_MAX], mode, last_set, current_set; char set[C128_MAX] = {0}, fset[C128_MAX], mode, last_set, current_set;
int pads_needed, indexliste, i, j, m, read, mx_reader; int pads_needed, indexliste, i, m, read, mx_reader;
int values[C128_MAX] = {0}; int values[C128_MAX] = {0};
int bar_characters; int bar_characters;
float glyph_count; float glyph_count;
int error_number = 0, first_sum, second_sum; int error_number = 0, first_sum, second_sum;
int input_length; int input_length;
int gs1, c_count; int gs1;
/* Suppresses clang-analyzer-core.UndefinedBinaryOperatorResult warning on fset which is fully set */ /* Suppresses clang-analyzer-core.UndefinedBinaryOperatorResult warning on fset which is fully set */
assert(length > 0); assert(length > 0);
strcpy(width_pattern, "");
input_length = length; input_length = length;
if ((symbol->input_mode & 0x07) == GS1_MODE) { if ((symbol->input_mode & 0x07) == GS1_MODE) {
@ -149,7 +99,7 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int len
indexliste = 0; indexliste = 0;
indexchaine = 0; indexchaine = 0;
mode = parunmodd(source[indexchaine]); mode = c128_parunmodd(source[indexchaine]);
do { do {
list[1][indexliste] = mode; list[1][indexliste] = mode;
@ -159,75 +109,18 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int len
if (indexchaine == input_length) { if (indexchaine == input_length) {
break; break;
} }
mode = parunmodd(source[indexchaine]); mode = c128_parunmodd(source[indexchaine]);
if ((gs1) && (source[indexchaine] == '[')) { if ((gs1) && (source[indexchaine] == '[')) {
mode = ABORC; mode = C128_ABORC;
} /* FNC1 */ } /* FNC1 */
} }
indexliste++; indexliste++;
} while (indexchaine < input_length); } while (indexchaine < input_length);
dxsmooth(list, &indexliste); c128_dxsmooth(list, &indexliste);
/* Put set data into set[] */ /* Put set data into set[], resolving odd C blocks */
read = 0; c128_put_in_set(list, indexliste, set, source);
for (i = 0; i < indexliste; i++) {
for (j = 0; j < list[0][i]; j++) {
switch (list[1][i]) {
case SHIFTA: set[read] = 'a';
break;
case LATCHA: set[read] = 'A';
break;
case SHIFTB: set[read] = 'b';
break;
case LATCHB: set[read] = 'B';
break;
case LATCHC: set[read] = 'C';
break;
}
read++;
}
}
/* Watch out for odd-length Mode C blocks */
c_count = 0;
for (i = 0; i < read; i++) {
if (set[i] == 'C') {
if (source[i] == '[') {
if (c_count & 1) {
if ((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
c_count = 0;
} else {
c_count++;
}
} else {
if (c_count & 1) {
if ((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
c_count = 0;
}
}
if (c_count & 1) {
if ((i - c_count) != 0) {
set[i - c_count] = 'B';
} else {
set[i - 1] = 'B';
}
}
for (i = 1; i < read - 1; i++) {
if ((set[i] == 'C') && ((set[i - 1] == 'B') && (set[i + 1] == 'B'))) {
set[i] = 'B';
}
}
if (symbol->debug & ZINT_DEBUG_PRINT) { if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("Data: %.*s\n", input_length, source); printf("Data: %.*s\n", input_length, source);
@ -394,15 +287,15 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int len
switch (set[read]) { /* Encode data characters */ switch (set[read]) { /* Encode data characters */
case 'A': case 'A':
case 'a': case 'a':
c16k_set_a(source[read], values, &bar_characters); c128_set_a(source[read], values, &bar_characters);
read++; read++;
break; break;
case 'B': case 'B':
case 'b': case 'b':
c16k_set_b(source[read], values, &bar_characters); c128_set_b(source[read], values, &bar_characters);
read++; read++;
break; break;
case 'C': c16k_set_c(source[read], source[read + 1], values, &bar_characters); case 'C': c128_set_c(source[read], source[read + 1], values, &bar_characters);
read += 2; read += 2;
break; break;
} }
@ -456,19 +349,21 @@ INTERNAL int code16k(struct zint_symbol *symbol, unsigned char source[], int len
int writer; int writer;
int flip_flop; int flip_flop;
int len; int len;
char *d = width_pattern;
strcpy(width_pattern, ""); memcpy(d, C16KStartStop[C16KStartValues[current_row]], 4);
strcat(width_pattern, C16KStartStop[C16KStartValues[current_row]]); d += 4;
strcat(width_pattern, "1"); *d++ = '1';
for (i = 0; i < 5; i++) { for (i = 0; i < 5; i++, d += 6) {
strcat(width_pattern, C16KTable[values[(current_row * 5) + i]]); memcpy(d, C128Table[values[(current_row * 5) + i]], 6);
} }
strcat(width_pattern, C16KStartStop[C16KStopValues[current_row]]); memcpy(d, C16KStartStop[C16KStopValues[current_row]], 4);
d += 4;
/* Write the information into the symbol */ /* Write the information into the symbol */
writer = 0; writer = 0;
flip_flop = 1; flip_flop = 1;
for (mx_reader = 0, len = (int) strlen(width_pattern); mx_reader < len; mx_reader++) { for (mx_reader = 0, len = d - width_pattern; mx_reader < len; mx_reader++) {
for (looper = 0; looper < ctoi(width_pattern[mx_reader]); looper++) { for (looper = 0; looper < ctoi(width_pattern[mx_reader]); looper++) {
if (flip_flop == 1) { if (flip_flop == 1) {
set_module(symbol, current_row, writer); set_module(symbol, current_row, writer);

View File

@ -35,20 +35,22 @@
#include "common.h" #include "common.h"
#include "code49.h" #include "code49.h"
#define INSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%!&*" static const char C49_INSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%!&*";
/* "!" represents Shift 1 and "&" represents Shift 2, "*" represents FNC1 */ /* "!" represents Shift 1 and "&" represents Shift 2, "*" represents FNC1 */
INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int length) {
int i, j, rows, M, x_count, y_count, z_count, posn_val, local_value; int i, j, rows, M, x_count, y_count, z_count, posn_val, local_value;
char intermediate[170] = ""; char intermediate[170] = "";
char *d = intermediate;
int codewords[170], codeword_count; int codewords[170], codeword_count;
int c_grid[8][8]; /* Refers to table 3 */ int c_grid[8][8]; /* Refers to table 3 */
int w_grid[8][4]; /* Refets to table 2 */ int w_grid[8][4]; /* Refets to table 2 */
int pad_count = 0; int pad_count = 0;
char pattern[80]; char pattern[80];
int bp;
int gs1; int gs1;
int h, len; int h;
int error_number = 0; int error_number = 0;
if (length > 81) { if (length > 81) {
@ -57,7 +59,7 @@ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int leng
} }
if ((symbol->input_mode & 0x07) == GS1_MODE) { if ((symbol->input_mode & 0x07) == GS1_MODE) {
gs1 = 1; gs1 = 1;
strcpy(intermediate, "*"); /* FNC1 */ *d++ = '*'; /* FNC1 */
} else { } else {
gs1 = 0; gs1 = 0;
} }
@ -67,15 +69,18 @@ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int leng
strcpy(symbol->errtxt, "431: Invalid character in input data, extended ASCII not allowed"); strcpy(symbol->errtxt, "431: Invalid character in input data, extended ASCII not allowed");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
if (gs1 && (source[i] == '[')) if (gs1 && (source[i] == '[')) {
strcat(intermediate, "*"); /* FNC1 */ *d++ = '*'; /* FNC1 */
else } else {
strcat(intermediate, c49_table7[source[i]]); const char *const entry = c49_table7[source[i]];
memcpy(d, entry, 2);
d += entry[1] ? 2 : 1;
}
} }
codeword_count = 0; codeword_count = 0;
i = 0; i = 0;
h = (int) strlen(intermediate); h = d - intermediate;
do { do {
if ((intermediate[i] >= '0') && (intermediate[i] <= '9')) { if ((intermediate[i] >= '0') && (intermediate[i] <= '9')) {
/* Numeric data */ /* Numeric data */
@ -142,7 +147,7 @@ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int leng
switch (block_remain) { switch (block_remain) {
case 1: case 1:
/* Rule (a) */ /* Rule (a) */
codewords[codeword_count] = posn(INSET, intermediate[i]); codewords[codeword_count] = posn(C49_INSET, intermediate[i]);
codeword_count++; codeword_count++;
i++; i++;
break; break;
@ -184,12 +189,12 @@ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int leng
codeword_count++; codeword_count++;
} }
} else { } else {
codewords[codeword_count] = posn(INSET, intermediate[i]); codewords[codeword_count] = posn(C49_INSET, intermediate[i]);
codeword_count++; codeword_count++;
i++; i++;
} }
} else { } else {
codewords[codeword_count] = posn(INSET, intermediate[i]); codewords[codeword_count] = posn(C49_INSET, intermediate[i]);
codeword_count++; codeword_count++;
i++; i++;
} }
@ -321,25 +326,26 @@ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int leng
} }
for (i = 0; i < rows; i++) { for (i = 0; i < rows; i++) {
strcpy(pattern, "10"); /* Start character */ bp = 0;
bp = bin_append_posn(2, 2, pattern, bp); /* Start character "10" */
for (j = 0; j < 4; j++) { for (j = 0; j < 4; j++) {
if (i != (rows - 1)) { if (i != (rows - 1)) {
if (c49_table4[i][j] == 'E') { if (c49_table4[i][j] == 'E') {
/* Even Parity */ /* Even Parity */
bin_append(c49_even_bitpattern[w_grid[i][j]], 16, pattern); bp = bin_append_posn(c49_even_bitpattern[w_grid[i][j]], 16, pattern, bp);
} else { } else {
/* Odd Parity */ /* Odd Parity */
bin_append(c49_odd_bitpattern[w_grid[i][j]], 16, pattern); bp = bin_append_posn(c49_odd_bitpattern[w_grid[i][j]], 16, pattern, bp);
} }
} else { } else {
/* Last row uses all even parity */ /* Last row uses all even parity */
bin_append(c49_even_bitpattern[w_grid[i][j]], 16, pattern); bp = bin_append_posn(c49_even_bitpattern[w_grid[i][j]], 16, pattern, bp);
} }
} }
strcat(pattern, "1111"); /* Stop character */ bp = bin_append_posn(15, 4, pattern, bp); /* Stop character "1111" */
/* Expand into symbol */ /* Expand into symbol */
for (j = 0, len = (int) strlen(pattern); j < len; j++) { for (j = 0; j < bp; j++) {
if (pattern[j] == '1') { if (pattern[j] == '1') {
set_module(symbol, i, j); set_module(symbol, i, j);
} }
@ -347,7 +353,7 @@ INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int leng
} }
symbol->rows = rows; symbol->rows = rows;
symbol->width = (int) strlen(pattern); symbol->width = bp;
if (symbol->output_options & COMPLIANT_HEIGHT) { if (symbol->output_options & COMPLIANT_HEIGHT) {
/* ANSI/AIM BC6-2000 Section 2.6 minimum 8X; use 10X as default /* ANSI/AIM BC6-2000 Section 2.6 minimum 8X; use 10X as default

View File

@ -2,7 +2,7 @@
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2009-2017 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2009-2021 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -29,21 +29,25 @@
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE. SUCH DAMAGE.
*/ */
/* vim: set ts=4 sw=4 et : */
/* This data set taken from ANSI/AIM-BC6-2000, 4th April 2000 */ /* This data set taken from ANSI/AIM-BC6-2000, 4th April 2000 */
static const char *c49_table7[128] = { static const char c49_table7[128][2] = {
/* Table 7: Code 49 ASCII Chart */ /* Table 7: Code 49 ASCII Chart */
"! ", "!A", "!B", "!C", "!D", "!E", "!F", "!G", "!H", "!I", "!J", "!K", "!L", {'!',' '}, {'!','A'}, {'!','B'}, {'!','C'}, {'!','D'}, {'!','E'}, {'!','F'}, {'!','G'}, {'!','H'}, {'!','I'},
"!M", "!N", "!O", "!P", "!Q", "!R", "!S", "!T", "!U", "!V", "!W", "!X", "!Y", {'!','J'}, {'!','K'}, {'!','L'}, {'!','M'}, {'!','N'}, {'!','O'}, {'!','P'}, {'!','Q'}, {'!','R'}, {'!','S'},
"!Z", "!1", "!2", "!3", "!4", "!5", " ", "!6", "!7", "!8", "$", "%", "!9", "!0", {'!','T'}, {'!','U'}, {'!','V'}, {'!','W'}, {'!','X'}, {'!','Y'}, {'!','Z'}, {'!','1'}, {'!','2'}, {'!','3'},
"!-", "!.", "!$", "+", "!/", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", {'!','4'}, {'!','5'}, { " " }, {'!','6'}, {'!','7'}, {'!','8'}, { "$" }, { "%" }, {'!','9'}, {'!','0'},
"7", "8", "9", "!+", "&1", "&2", "&3", "&4", "&5", "&6", "A", "B", "C", "D", "E", {'!','-'}, {'!','.'}, {'!','$'}, { "+" }, {'!','/'}, { "-" }, { "." }, { "/" }, { "0" }, { "1" },
"F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", { "2" }, { "3" }, { "4" }, { "5" }, { "6" }, { "7" }, { "8" }, { "9" }, {'!','+'}, {'&','1'},
"V", "W", "X", "Y", "Z", "&7", "&8", "&9", "&0", "&-", "&.", "&A", "&B", "&C", {'&','2'}, {'&','3'}, {'&','4'}, {'&','5'}, {'&','6'}, { "A" }, { "B" }, { "C" }, { "D" }, { "E" },
"&D", "&E", "&F", "&G", "&H", "&I", "&J", "&K", "&L", "&M", "&N", "&O", "&P", { "F" }, { "G" }, { "H" }, { "I" }, { "J" }, { "K" }, { "L" }, { "M" }, { "N" }, { "O" },
"&Q", "&R", "&S", "&T", "&U", "&V", "&W", "&X", "&Y", "&Z", "&$", "&/", "&+", { "P" }, { "Q" }, { "R" }, { "S" }, { "T" }, { "U" }, { "V" }, { "W" }, { "X" }, { "Y" },
"&%", "& " { "Z" }, {'&','7'}, {'&','8'}, {'&','9'}, {'&','0'}, {'&','-'}, {'&','.'}, {'&','A'}, {'&','B'}, {'&','C'},
{'&','D'}, {'&','E'}, {'&','F'}, {'&','G'}, {'&','H'}, {'&','I'}, {'&','J'}, {'&','K'}, {'&','L'}, {'&','M'},
{'&','N'}, {'&','O'}, {'&','P'}, {'&','Q'}, {'&','R'}, {'&','S'}, {'&','T'}, {'&','U'}, {'&','V'}, {'&','W'},
{'&','X'}, {'&','Y'}, {'&','Z'}, {'&','$'}, {'&','/'}, {'&','+'}, {'&','%'}, {'&',' '}
}; };
/* Table 5: Check Character Weighting Values */ /* Table 5: Check Character Weighting Values */
@ -62,9 +66,10 @@ static const char c49_z_weight[] = {
13, 5, 41, 33, 36, 8, 4, 32, 3, 19, 40, 25, 29, 10, 24, 30 13, 5, 41, 33, 36, 8, 4, 32, 3, 19, 40, 25, 29, 10, 24, 30
}; };
static const char *c49_table4[8] = { static const char c49_table4[8][4] = {
/* Table 4: Row Parity Pattern for Code 49 Symbols */ /* Table 4: Row Parity Pattern for Code 49 Symbols */
"OEEO", "EOEO", "OOEE", "EEOO", "OEOE", "EOOE", "OOOO", "EEEE" {'O','E','E','O'}, {'E','O','E','O'}, {'O','O','E','E'}, {'E','E','O','O'},
{'O','E','O','E'}, {'E','O','O','E'}, {'O','O','O','O'}, {'E','E','E','E'}
}; };
static const unsigned short int c49_even_bitpattern[] = { static const unsigned short int c49_even_bitpattern[] = {

View File

@ -75,10 +75,10 @@ INTERNAL int to_int(const unsigned char source[], const int length) {
} }
/* Converts lower case characters to upper case in a string source[] */ /* Converts lower case characters to upper case in a string source[] */
INTERNAL void to_upper(unsigned char source[]) { INTERNAL void to_upper(unsigned char source[], const int length) {
int i, src_len = (int) ustrlen(source); int i;
for (i = 0; i < src_len; i++) { for (i = 0; i < length; i++) {
if ((source[i] >= 'a') && (source[i] <= 'z')) { if ((source[i] >= 'a') && (source[i] <= 'z')) {
source[i] = (source[i] - 'a') + 'A'; source[i] = (source[i] - 'a') + 'A';
} }
@ -98,59 +98,80 @@ INTERNAL int chr_cnt(const unsigned char string[], const int length, const unsig
} }
/* Verifies that a string only uses valid characters */ /* Verifies that a string only uses valid characters */
INTERNAL int is_sane(const char test_string[], const unsigned char source[], const int length) { INTERNAL int is_sane(const unsigned int flg, const unsigned char source[], const int length) {
int i, j, lt = (int) strlen(test_string); #define IS_CLS_F (IS_CLI_F | IS_SIL_F)
static unsigned short flgs[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*00-1F*/
IS_SPC_F, IS_C82_F, IS_C82_F, IS_HSH_F, /*20-23*/ /* !"# */
IS_CLS_F, IS_SIL_F | IS_C82_F, IS_C82_F, IS_C82_F, /*24-27*/ /* $%&' */
IS_C82_F, IS_C82_F, IS_C82_F, IS_PLS_F, /*28-2B*/ /* ()*+ */
IS_C82_F, IS_MNS_F, IS_CLS_F | IS_C82_F, IS_CLS_F | IS_C82_F, /*2B-2F*/ /* ,-./ */
IS_NUM_F, IS_NUM_F, IS_NUM_F, IS_NUM_F, /*30-33*/ /* 0123 */
IS_NUM_F, IS_NUM_F, IS_NUM_F, IS_NUM_F, /*34-37*/ /* 4567 */
IS_NUM_F, IS_NUM_F, IS_CLI_F | IS_C82_F, IS_C82_F, /*38-3B*/ /* 89:; */
IS_C82_F, IS_C82_F, IS_C82_F, IS_C82_F, /*3B-3F*/ /* <=>? */
0, IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, /*40-43*/ /* @ABC */
IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, IS_UHX_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*44-47*/ /* DEFG */
IS_UPO_F | IS_ARS_F, IS_UPO_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*48-4B*/ /* HIJK */
IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F, /*4B-4F*/ /* LMNO */
IS_UPO_F | IS_ARS_F, IS_UPO_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*50-53*/ /* PQRS */
IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, /*53-57*/ /* TUVW */
IS_UX__F | IS_ARS_F, IS_UPO_F | IS_ARS_F, IS_UPO_F | IS_ARS_F, 0, /*58-5B*/ /* XYZ[ */
0, 0, 0, IS_C82_F, /*5B-5F*/ /* \]^_ */
0, IS_LHX_F, IS_LHX_F, IS_LHX_F, /*60-63*/ /* `abc */
IS_LHX_F, IS_LHX_F, IS_LHX_F, IS_LWO_F, /*64-67*/ /* defg */
IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*68-6B*/ /* hijk */
IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*6B-6F*/ /* lmno */
IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*70-73*/ /* pqrs */
IS_LWO_F, IS_LWO_F, IS_LWO_F, IS_LWO_F, /*74-77*/ /* tuvw */
IS_LX__F, IS_LWO_F, IS_LWO_F, 0, /*78-7B*/ /* xyz{ */
0, 0, 0, 0, /*7B-7F*/ /* |}~D */
};
int i;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
unsigned int latch = FALSE; if (!(flgs[source[i]] & flg)) {
for (j = 0; j < lt; j++) { return 0;
if (source[i] == test_string[j]) {
latch = TRUE;
break;
}
}
if (!(latch)) {
return ZINT_ERROR_INVALID_DATA;
} }
} }
return 1;
return 0;
} }
/* Replaces huge switch statements for looking up in tables */ /* Replaces huge switch statements for looking up in tables */
INTERNAL void lookup(const char set_string[], const char *table[], const char data, char dest[]) { /* Verifies that a string only uses valid characters, and returns `test_string` position of each in `posns` array */
int i, n = (int) strlen(set_string); INTERNAL int is_sane_lookup(const char test_string[], const int test_length, const unsigned char source[],
const int length, int *posns) {
int i, j;
for (i = 0; i < n; i++) { for (i = 0; i < length; i++) {
if (data == set_string[i]) { posns[i] = -1;
strcat(dest, table[i]); for (j = 0; j < test_length; j++) {
break; if (source[i] == test_string[j]) {
posns[i] = j;
break;
}
}
if (posns[i] == -1) {
return 0;
} }
} }
return 1;
} }
/* Returns the position of data in set_string */ /* Returns the position of data in set_string */
INTERNAL int posn(const char set_string[], const char data) { INTERNAL int posn(const char set_string[], const char data) {
int i, n = (int) strlen(set_string); const char *s;
for (i = 0; i < n; i++) { for (s = set_string; *s; s++) {
if (data == set_string[i]) { if (data == *s) {
return i; return s - set_string;
} }
} }
return -1; return -1;
} }
/* Convert an integer value to a string representing its binary equivalent */ /* Convert an integer value to a string representing its binary equivalent and place at a given position */
INTERNAL void bin_append(const int arg, const int length, char *binary) {
int bin_posn = (int) strlen(binary);
bin_append_posn(arg, length, binary, bin_posn);
binary[bin_posn + length] = '\0';
}
/* Convert an integer value to a string representing its binary equivalent at a set position */
INTERNAL int bin_append_posn(const int arg, const int length, char *binary, const int bin_posn) { INTERNAL int bin_append_posn(const int arg, const int length, char *binary, const int bin_posn) {
int i; int i;
int start; int start;
@ -195,20 +216,23 @@ INTERNAL void unset_module(struct zint_symbol *symbol, const int y_coord, const
} }
/* Expands from a width pattern to a bit pattern */ /* Expands from a width pattern to a bit pattern */
INTERNAL void expand(struct zint_symbol *symbol, const char data[]) { INTERNAL void expand(struct zint_symbol *symbol, const char data[], const int length) {
int reader, n = (int) strlen(data); int reader;
int writer, i; int writer, i;
int latch, num; int latch, num;
int row = symbol->rows;
symbol->rows++;
writer = 0; writer = 0;
latch = 1; latch = 1;
for (reader = 0; reader < n; reader++) { for (reader = 0; reader < length; reader++) {
num = ctoi(data[reader]); num = ctoi(data[reader]);
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
if (latch) { if (latch) {
set_module(symbol, symbol->rows, writer); set_module(symbol, row, writer);
} }
writer++; writer++;
} }
@ -216,17 +240,9 @@ INTERNAL void expand(struct zint_symbol *symbol, const char data[]) {
latch = !latch; latch = !latch;
} }
if (symbol->symbology != BARCODE_PHARMA) { if (writer > symbol->width) {
if (writer > symbol->width) { symbol->width = writer;
symbol->width = writer;
}
} else {
/* Pharmacode One ends with a space - adjust for this */
if (writer > symbol->width + 2) {
symbol->width = writer - 2;
}
} }
symbol->rows = symbol->rows + 1;
} }
/* Indicates which symbologies can have row binding */ /* Indicates which symbologies can have row binding */
@ -281,7 +297,7 @@ INTERNAL int is_composite(const int symbology) {
} }
/* Whether next two characters are digits */ /* Whether next two characters are digits */
INTERNAL int istwodigits(const unsigned char source[], const int length, const int position) { INTERNAL int is_twodigits(const unsigned char source[], const int length, const int position) {
if ((position + 1 < length) && (source[position] >= '0') && (source[position] <= '9') if ((position + 1 < length) && (source[position] >= '0') && (source[position] <= '9')
&& (source[position + 1] >= '0') && (source[position + 1] <= '9')) { && (source[position + 1] >= '0') && (source[position + 1] <= '9')) {
return 1; return 1;
@ -415,7 +431,7 @@ INTERNAL int set_height(struct zint_symbol *symbol, const float min_row_height,
if (row_height < 0.5f) { /* Absolute minimum */ if (row_height < 0.5f) { /* Absolute minimum */
row_height = 0.5f; row_height = 0.5f;
} }
if (min_row_height && row_height < min_row_height) { if (min_row_height && stripf(row_height) < stripf(min_row_height)) {
error_number = ZINT_WARN_NONCOMPLIANT; error_number = ZINT_WARN_NONCOMPLIANT;
if (!no_errtxt) { if (!no_errtxt) {
strcpy(symbol->errtxt, "247: Height not compliant with standards"); strcpy(symbol->errtxt, "247: Height not compliant with standards");
@ -425,7 +441,7 @@ INTERNAL int set_height(struct zint_symbol *symbol, const float min_row_height,
} else { } else {
symbol->height = stripf(fixed_height); /* Ignore any given height */ symbol->height = stripf(fixed_height); /* Ignore any given height */
} }
if (max_height && symbol->height > max_height) { if (max_height && stripf(symbol->height) > stripf(max_height)) {
error_number = ZINT_WARN_NONCOMPLIANT; error_number = ZINT_WARN_NONCOMPLIANT;
if (!no_errtxt) { if (!no_errtxt) {
strcpy(symbol->errtxt, "248: Height not compliant with standards"); strcpy(symbol->errtxt, "248: Height not compliant with standards");

View File

@ -42,8 +42,28 @@
#define TRUE 1 #define TRUE 1
#endif #endif
/* `is_sane()` flags */
#define IS_SPC_F 0x0001 /* Space */
#define IS_HSH_F 0x0002 /* Hash sign # */
#define IS_PLS_F 0x0004 /* Plus sign + */
#define IS_MNS_F 0x0008 /* Minus sign - */
#define IS_NUM_F 0x0010 /* Number 0-9 */
#define IS_UPO_F 0x0020 /* Uppercase letter, apart from A-F and X */
#define IS_UHX_F 0x0040 /* Uppercase hex A-F */
#define IS_UX__F 0x0080 /* Uppercase X */
#define IS_LWO_F 0x0100 /* Lowercase letter, apart from a-f and x */
#define IS_LHX_F 0x0200 /* Lowercase hex a-f */
#define IS_LX__F 0x0400 /* Lowercase x */
#define IS_C82_F 0x0800 /* CSET82 punctuation (apart from - and +) */
#define IS_SIL_F 0x1000 /* SILVER/TECHNETIUM punctuation .$/% (apart from space, - and +) */
#define IS_CLI_F 0x2000 /* CALCIUM INNER punctuation $:/. (apart from - and +) (Codabar) */
#define IS_ARS_F 0x4000 /* ARSENIC uppercase subset (VIN) */
#define IS_UPR_F (IS_UPO_F | IS_UHX_F | IS_UX__F) /* Uppercase letters */
#define IS_LWR_F (IS_LWO_F | IS_LHX_F | IS_LX__F) /* Lowercase letters */
/* The most commonly used set */ /* The most commonly used set */
#define NEON "0123456789" #define NEON_F IS_NUM_F /* NEON "0123456789" */
#include "zint.h" #include "zint.h"
#include "zintconfig.h" #include "zintconfig.h"
@ -83,6 +103,14 @@
# define INTERNAL # define INTERNAL
#endif #endif
#if (defined(__GNUC__) || defined(__clang__)) && !defined(__MINGW32__)
# define INTERNAL_DATA_EXTERN __attribute__ ((visibility ("hidden"))) extern
# define INTERNAL_DATA __attribute__ ((visibility ("hidden")))
#else
# define INTERNAL_DATA_EXTERN extern
# define INTERNAL_DATA
#endif
#ifdef ZINT_TEST #ifdef ZINT_TEST
#define STATIC_UNLESS_ZINT_TEST INTERNAL #define STATIC_UNLESS_ZINT_TEST INTERNAL
#else #else
@ -112,14 +140,14 @@ extern "C" {
INTERNAL int ctoi(const char source); INTERNAL int ctoi(const char source);
INTERNAL char itoc(const int source); INTERNAL char itoc(const int source);
INTERNAL int to_int(const unsigned char source[], const int length); INTERNAL int to_int(const unsigned char source[], const int length);
INTERNAL void to_upper(unsigned char source[]); INTERNAL void to_upper(unsigned char source[], const int length);
INTERNAL int chr_cnt(const unsigned char string[], const int length, const unsigned char c); INTERNAL int chr_cnt(const unsigned char string[], const int length, const unsigned char c);
INTERNAL int is_sane(const char test_string[], const unsigned char source[], const int length); INTERNAL int is_sane(const unsigned int flg, const unsigned char source[], const int length);
INTERNAL void lookup(const char set_string[], const char *table[], const char data, char dest[]); INTERNAL int is_sane_lookup(const char test_string[], const int test_length, const unsigned char source[],
const int length, int *posns);
INTERNAL int posn(const char set_string[], const char data); INTERNAL int posn(const char set_string[], const char data);
INTERNAL void bin_append(const int arg, const int length, char *binary);
INTERNAL int bin_append_posn(const int arg, const int length, char *binary, const int bin_posn); INTERNAL int bin_append_posn(const int arg, const int length, char *binary, const int bin_posn);
#ifndef COMMON_INLINE #ifndef COMMON_INLINE
@ -130,12 +158,14 @@ extern "C" {
const int colour); const int colour);
#endif #endif
INTERNAL void unset_module(struct zint_symbol *symbol, const int y_coord, const int x_coord); INTERNAL void unset_module(struct zint_symbol *symbol, const int y_coord, const int x_coord);
INTERNAL void expand(struct zint_symbol *symbol, const char data[]);
INTERNAL void expand(struct zint_symbol *symbol, const char data[], const int length);
INTERNAL int is_stackable(const int symbology); INTERNAL int is_stackable(const int symbology);
INTERNAL int is_extendable(const int symbology); INTERNAL int is_extendable(const int symbology);
INTERNAL int is_composite(const int symbology); INTERNAL int is_composite(const int symbology);
INTERNAL int istwodigits(const unsigned char source[], const int length, const int position);
INTERNAL int is_twodigits(const unsigned char source[], const int length, const int position);
INTERNAL unsigned int decode_utf8(unsigned int *state, unsigned int *codep, const unsigned char byte); INTERNAL unsigned int decode_utf8(unsigned int *state, unsigned int *codep, const unsigned char byte);
INTERNAL int is_valid_utf8(const unsigned char source[], const int length); INTERNAL int is_valid_utf8(const unsigned char source[], const int length);

View File

@ -68,7 +68,8 @@ INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int
INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows); INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows);
INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char source[], INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char source[],
unsigned char local_source[], int *p_with_addon); unsigned char local_source[], int *p_with_addon, unsigned char *zfirst_part,
unsigned char *zsecond_part);
INTERNAL int dbar_omnstk_set_height(struct zint_symbol *symbol, const int first_row); INTERNAL int dbar_omnstk_set_height(struct zint_symbol *symbol, const int first_row);
INTERNAL int dbar_omn_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows); INTERNAL int dbar_omn_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows);
@ -1331,8 +1332,8 @@ INTERNAL int composite(struct zint_symbol *symbol, unsigned char source[], int l
int padded_pri_len; int padded_pri_len;
int with_addon; int with_addon;
unsigned char padded_pri[21]; unsigned char padded_pri[21];
padded_pri[0] = '\0'; if (!ean_leading_zeroes(symbol, (unsigned char *) symbol->primary, padded_pri, &with_addon, NULL,
if (!ean_leading_zeroes(symbol, (unsigned char *) symbol->primary, padded_pri, &with_addon)) { NULL)) {
sprintf(symbol->errtxt, "448: Input too long (%s) in linear component", sprintf(symbol->errtxt, "448: Input too long (%s) in linear component",
with_addon ? "5 character maximum for add-on" : "13 character maximum"); with_addon ? "5 character maximum for add-on" : "13 character maximum");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;

View File

@ -1,4 +1,35 @@
/* Sed: http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersguide/versions.asp */ /* Sed: http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/programmersguide/versions.asp */
/*
libzint - the open source barcode library
Copyright (C) 2008 - 2021 Robin Stuart <rstuart114@gmail.com>
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 : */
#if defined (_WIN32) && (defined(_USRDLL) || defined(DLL_EXPORT) || defined(PIC)) #if defined (_WIN32) && (defined(_USRDLL) || defined(DLL_EXPORT) || defined(PIC))
#include <windows.h> #include <windows.h>
#include <shlwapi.h> #include <shlwapi.h>
@ -17,17 +48,18 @@ __declspec(dllexport) HRESULT DllGetVersion (DLLVERSIONINFO2* pdvi);
HRESULT DllGetVersion (DLLVERSIONINFO2* pdvi) HRESULT DllGetVersion (DLLVERSIONINFO2* pdvi)
{ {
if (!pdvi || (sizeof(*pdvi) != pdvi->info1.cbSize)) if (!pdvi || (sizeof(*pdvi) != pdvi->info1.cbSize))
return (E_INVALIDARG); return (E_INVALIDARG);
pdvi->info1.dwMajorVersion = ZINT_VERSION_MAJOR; pdvi->info1.dwMajorVersion = ZINT_VERSION_MAJOR;
pdvi->info1.dwMinorVersion = ZINT_VERSION_MINOR; pdvi->info1.dwMinorVersion = ZINT_VERSION_MINOR;
pdvi->info1.dwBuildNumber = ZINT_VERSION_RELEASE; pdvi->info1.dwBuildNumber = ZINT_VERSION_RELEASE;
pdvi->info1.dwPlatformID = DLLVER_PLATFORM_WINDOWS; pdvi->info1.dwPlatformID = DLLVER_PLATFORM_WINDOWS;
if (sizeof(DLLVERSIONINFO2) == pdvi->info1.cbSize) if (sizeof(DLLVERSIONINFO2) == pdvi->info1.cbSize)
pdvi->ullVersion = MAKEDLLVERULL(ZINT_VERSION_MAJOR, ZINT_VERSION_MINOR, ZINT_VERSION_RELEASE, ZINT_VERSION_BUILD); pdvi->ullVersion = MAKEDLLVERULL(ZINT_VERSION_MAJOR, ZINT_VERSION_MINOR, ZINT_VERSION_RELEASE,
ZINT_VERSION_BUILD);
return S_OK; return S_OK;
} }
#else #else
/* https://stackoverflow.com/a/26541331 Suppresses gcc warning ISO C forbids an empty translation unit */ /* https://stackoverflow.com/a/26541331 Suppresses gcc warning ISO C forbids an empty translation unit */

View File

@ -779,7 +779,7 @@ static int dm200encode(struct zint_symbol *symbol, const unsigned char source[],
if (current_mode == DM_ASCII) { if (current_mode == DM_ASCII) {
next_mode = DM_ASCII; next_mode = DM_ASCII;
if (istwodigits(source, inputlen, sp)) { if (is_twodigits(source, inputlen, sp)) {
target[tp] = (unsigned char) ((10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130); target[tp] = (unsigned char) ((10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130);
if (debug) printf("N%02d ", target[tp] - 130); if (debug) printf("N%02d ", target[tp] - 130);
tp++; tp++;
@ -1029,7 +1029,7 @@ static int dm200encode(struct zint_symbol *symbol, const unsigned char source[],
target[tp++] = 254; // Unlatch target[tp++] = 254; // Unlatch
if (debug) printf("ASC "); if (debug) printf("ASC ");
for (; sp < inputlen; sp++) { for (; sp < inputlen; sp++) {
if (istwodigits(source, inputlen, sp)) { if (is_twodigits(source, inputlen, sp)) {
target[tp++] = (unsigned char) ((10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130); target[tp++] = (unsigned char) ((10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130);
if (debug) printf("N%02d ", target[tp - 1] - 130); if (debug) printf("N%02d ", target[tp - 1] - 130);
sp++; sp++;

View File

@ -584,7 +584,7 @@ static int dotcode_encode_message(struct zint_symbol *symbol, const unsigned cha
} }
// Prevent encodation as a macro if a special character is in first position // Prevent encodation as a macro if a special character is in first position
if (strchr(lead_specials, source[input_position]) != NULL) { if (posn(lead_specials, source[input_position]) != -1) {
codeword_array[array_length] = 101; // Latch A codeword_array[array_length] = 101; // Latch A
array_length++; array_length++;
codeword_array[array_length] = source[input_position] + 64; codeword_array[array_length] = source[input_position] + 64;

View File

@ -46,7 +46,7 @@
#include "emf.h" #include "emf.h"
/* Multiply truncating to 3 decimal places (avoids rounding differences on various platforms) */ /* Multiply truncating to 3 decimal places (avoids rounding differences on various platforms) */
#define mul3dpf(m, arg) (roundf(m * arg * 1000.0) / 1000.0f) #define mul3dpf(m, arg) stripf(roundf(m * arg * 1000.0) / 1000.0f)
static int count_rectangles(struct zint_symbol *symbol) { static int count_rectangles(struct zint_symbol *symbol) {
int rectangles = 0; int rectangles = 0;
@ -453,9 +453,9 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
rectangle[this_rectangle].type = 0x0000002b; // EMR_RECTANGLE rectangle[this_rectangle].type = 0x0000002b; // EMR_RECTANGLE
rectangle[this_rectangle].size = 24; rectangle[this_rectangle].size = 24;
rectangle[this_rectangle].box.top = (int32_t) rect->y; rectangle[this_rectangle].box.top = (int32_t) rect->y;
rectangle[this_rectangle].box.bottom = (int32_t) (rect->y + rect->height); rectangle[this_rectangle].box.bottom = (int32_t) stripf(rect->y + rect->height);
rectangle[this_rectangle].box.left = (int32_t) rect->x; rectangle[this_rectangle].box.left = (int32_t) rect->x;
rectangle[this_rectangle].box.right = (int32_t) (rect->x + rect->width); rectangle[this_rectangle].box.right = (int32_t) stripf(rect->x + rect->width);
this_rectangle++; this_rectangle++;
bytecount += 24; bytecount += 24;
recordcount++; recordcount++;
@ -475,10 +475,10 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
} }
circle[this_circle].type = 0x0000002a; // EMR_ELLIPSE circle[this_circle].type = 0x0000002a; // EMR_ELLIPSE
circle[this_circle].size = 24; circle[this_circle].size = 24;
circle[this_circle].box.top = (int32_t) (circ->y - radius); circle[this_circle].box.top = (int32_t) stripf(circ->y - radius);
circle[this_circle].box.bottom = (int32_t) (circ->y + radius); circle[this_circle].box.bottom = (int32_t) stripf(circ->y + radius);
circle[this_circle].box.left = (int32_t) (circ->x - radius); circle[this_circle].box.left = (int32_t) stripf(circ->x - radius);
circle[this_circle].box.right = (int32_t) (circ->x + radius); circle[this_circle].box.right = (int32_t) stripf(circ->x + radius);
this_circle++; this_circle++;
bytecount += 24; bytecount += 24;
recordcount++; recordcount++;
@ -487,10 +487,10 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
float inner_radius = radius - circ->width; float inner_radius = radius - circ->width;
circle[this_circle].type = 0x0000002a; // EMR_ELLIPSE circle[this_circle].type = 0x0000002a; // EMR_ELLIPSE
circle[this_circle].size = 24; circle[this_circle].size = 24;
circle[this_circle].box.top = (int32_t) (circ->y - inner_radius); circle[this_circle].box.top = (int32_t) stripf(circ->y - inner_radius);
circle[this_circle].box.bottom = (int32_t) (circ->y + inner_radius); circle[this_circle].box.bottom = (int32_t) stripf(circ->y + inner_radius);
circle[this_circle].box.left = (int32_t) (circ->x - inner_radius); circle[this_circle].box.left = (int32_t) stripf(circ->x - inner_radius);
circle[this_circle].box.right = (int32_t) (circ->x + inner_radius); circle[this_circle].box.right = (int32_t) stripf(circ->x + inner_radius);
this_circle++; this_circle++;
bytecount += 24; bytecount += 24;
recordcount++; recordcount++;
@ -516,18 +516,18 @@ INTERNAL int emf_plot(struct zint_symbol *symbol, int rotate_angle) {
} }
/* Note rotation done via world transform */ /* Note rotation done via world transform */
hexagon[this_hexagon].a_points_a.x = (int32_t) (hex->x); hexagon[this_hexagon].a_points_a.x = (int32_t) hex->x;
hexagon[this_hexagon].a_points_a.y = (int32_t) (hex->y + radius); hexagon[this_hexagon].a_points_a.y = (int32_t) stripf(hex->y + radius);
hexagon[this_hexagon].a_points_b.x = (int32_t) (hex->x + half_sqrt3_radius); hexagon[this_hexagon].a_points_b.x = (int32_t) stripf(hex->x + half_sqrt3_radius);
hexagon[this_hexagon].a_points_b.y = (int32_t) (hex->y + half_radius); hexagon[this_hexagon].a_points_b.y = (int32_t) stripf(hex->y + half_radius);
hexagon[this_hexagon].a_points_c.x = (int32_t) (hex->x + half_sqrt3_radius); hexagon[this_hexagon].a_points_c.x = (int32_t) stripf(hex->x + half_sqrt3_radius);
hexagon[this_hexagon].a_points_c.y = (int32_t) (hex->y - half_radius); hexagon[this_hexagon].a_points_c.y = (int32_t) stripf(hex->y - half_radius);
hexagon[this_hexagon].a_points_d.x = (int32_t) (hex->x); hexagon[this_hexagon].a_points_d.x = (int32_t) hex->x;
hexagon[this_hexagon].a_points_d.y = (int32_t) (hex->y - radius); hexagon[this_hexagon].a_points_d.y = (int32_t) stripf(hex->y - radius);
hexagon[this_hexagon].a_points_e.x = (int32_t) (hex->x - half_sqrt3_radius); hexagon[this_hexagon].a_points_e.x = (int32_t) stripf(hex->x - half_sqrt3_radius);
hexagon[this_hexagon].a_points_e.y = (int32_t) (hex->y - half_radius); hexagon[this_hexagon].a_points_e.y = (int32_t) stripf(hex->y - half_radius);
hexagon[this_hexagon].a_points_f.x = (int32_t) (hex->x - half_sqrt3_radius); hexagon[this_hexagon].a_points_f.x = (int32_t) stripf(hex->x - half_sqrt3_radius);
hexagon[this_hexagon].a_points_f.y = (int32_t) (hex->y + half_radius); hexagon[this_hexagon].a_points_f.y = (int32_t) stripf(hex->y + half_radius);
hexagon[this_hexagon].bounds.top = hexagon[this_hexagon].a_points_d.y; hexagon[this_hexagon].bounds.top = hexagon[this_hexagon].a_points_d.y;
hexagon[this_hexagon].bounds.bottom = hexagon[this_hexagon].a_points_a.y; hexagon[this_hexagon].bounds.bottom = hexagon[this_hexagon].a_points_a.y;

View File

@ -28,11 +28,12 @@
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE. SUCH DAMAGE.
*/ */
/* vim: set ts=4 sw=4 et : */
#ifndef EMF_H #ifndef EMF_H
#define EMF_H #define EMF_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -243,10 +244,8 @@ extern "C" {
#pragma pack() #pragma pack()
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* EMF_H */ #endif /* EMF_H */

View File

@ -448,7 +448,8 @@ static font_item small_font[] = {
* release of ocr-b only granted rights for non-commercial use; that * release of ocr-b only granted rights for non-commercial use; that
* restriction is now lifted." * restriction is now lifted."
* *
* Used OCRB.otf with FontForge to create OCRB-18.bdf (normal) and OCRB-16.bdf (small) and then touched up using gbdfed * Used OCRB.otf with FontForge to create OCRB-18.bdf (normal) and OCRB-16.bdf (small) and then touched up
* using gbdfed
* Note there's no bold version of OCR-B. * Note there's no bold version of OCR-B.
*/ */

View File

@ -36,16 +36,17 @@
static const char alphanum_puncs[] = "*,-./"; static const char alphanum_puncs[] = "*,-./";
static const char isoiec_puncs[] = "!\"%&'()*+,-./:;<=>?_ "; /* Note contains space, not in cset82 */ static const char isoiec_puncs[] = "!\"%&'()*+,-./:;<=>?_ "; /* Note contains space, not in cset82 */
#define IS_ISOIEC_F (IS_LWR_F | IS_C82_F | IS_PLS_F | IS_MNS_F | IS_SPC_F)
/* Returns type of char at `i`. FNC1 counted as NUMERIC. Returns 0 if invalid char */ /* Returns type of char at `i`. FNC1 counted as NUMERIC. Returns 0 if invalid char */
static int general_field_type(const char *general_field, const int i) { static int general_field_type(const char *general_field, const int i) {
if (general_field[i] == '[' || (general_field[i] >= '0' && general_field[i] <= '9')) { if (general_field[i] == '[' || (general_field[i] >= '0' && general_field[i] <= '9')) {
return NUMERIC; return NUMERIC;
} }
if ((general_field[i] >= 'A' && general_field[i] <= 'Z') || strchr(alphanum_puncs, general_field[i])) { if ((general_field[i] >= 'A' && general_field[i] <= 'Z') || posn(alphanum_puncs, general_field[i]) != -1) {
return ALPHANUMERIC; return ALPHANUMERIC;
} }
if ((general_field[i] >= 'a' && general_field[i] <= 'z') || strchr(isoiec_puncs, general_field[i])) { if (is_sane(IS_ISOIEC_F, (const unsigned char *) general_field + i, 1)) {
return ISOIEC; return ISOIEC;
} }
return 0; return 0;

View File

@ -43,6 +43,10 @@
#include "gb2312.h" #include "gb2312.h"
#include "eci.h" #include "eci.h"
static const char EUROPIUM[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ";
static const char EUROPIUM_UPR[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
static const char EUROPIUM_LWR[] = "abcdefghijklmnopqrstuvwxyz ";
/* define_mode() stuff */ /* define_mode() stuff */
/* Bits multiplied by this for costs, so as to be whole integer divisible by 2 and 3 */ /* Bits multiplied by this for costs, so as to be whole integer divisible by 2 and 3 */
@ -68,7 +72,7 @@ static int in_numeral(const unsigned int gbdata[], const int length, const int i
i++) { i++) {
if (gbdata[i] >= '0' && gbdata[i] <= '9') { if (gbdata[i] >= '0' && gbdata[i] <= '9') {
digit_cnt++; digit_cnt++;
} else if (strchr(numeral_nondigits, gbdata[i])) { } else if (posn(numeral_nondigits, (const char) gbdata[i]) != -1) {
if (nondigit) { if (nondigit) {
break; break;
} }
@ -282,7 +286,7 @@ static void define_mode(char *mode, const unsigned int gbdata[], const int lengt
/* Get optimal mode for each code point by tracing backwards */ /* Get optimal mode for each code point by tracing backwards */
for (i = length - 1, cm_i = i * GM_NUM_MODES; i >= 0; i--, cm_i -= GM_NUM_MODES) { for (i = length - 1, cm_i = i * GM_NUM_MODES; i >= 0; i--, cm_i -= GM_NUM_MODES) {
j = strchr(mode_types, cur_mode) - mode_types; j = posn(mode_types, cur_mode);
cur_mode = char_modes[cm_i + j]; cur_mode = char_modes[cm_i + j];
mode[i] = cur_mode; mode[i] = cur_mode;
} }
@ -308,7 +312,7 @@ static int add_shift_char(char binary[], int bp, int shifty, int debug) {
glyph = shifty; glyph = shifty;
} else { } else {
for (i = 32; i < 64; i++) { for (i = 32; i < 64; i++) {
if (shift_set[i] == shifty) { if (gm_shift_set[i] == shifty) {
glyph = i; glyph = i;
break; break;
} }
@ -577,7 +581,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con
if ((gbdata[sp] >= '0') && (gbdata[sp] <= '9')) { if ((gbdata[sp] >= '0') && (gbdata[sp] <= '9')) {
numbuf[p] = gbdata[sp]; numbuf[p] = gbdata[sp];
p++; p++;
} else if (strchr(numeral_nondigits, gbdata[sp])) { } else if (posn(numeral_nondigits, (const char) gbdata[sp]) != -1) {
if (ppos != -1) { if (ppos != -1) {
break; break;
} }
@ -701,7 +705,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con
if (shift == 0) { if (shift == 0) {
/* Upper Case character */ /* Upper Case character */
glyph = posn("ABCDEFGHIJKLMNOPQRSTUVWXYZ ", (const char) gbdata[sp]); glyph = posn(EUROPIUM_UPR, (const char) gbdata[sp]);
if (debug & ZINT_DEBUG_PRINT) { if (debug & ZINT_DEBUG_PRINT) {
printf("[%d] ", (int) glyph); printf("[%d] ", (int) glyph);
} }
@ -726,7 +730,7 @@ static int gm_encode(unsigned int gbdata[], const int length, char binary[], con
if (shift == 0) { if (shift == 0) {
/* Lower Case character */ /* Lower Case character */
glyph = posn("abcdefghijklmnopqrstuvwxyz ", (const char) gbdata[sp]); glyph = posn(EUROPIUM_LWR, (const char) gbdata[sp]);
if (debug & ZINT_DEBUG_PRINT) { if (debug & ZINT_DEBUG_PRINT) {
printf("[%d] ", (int) glyph); printf("[%d] ", (int) glyph);
} }

View File

@ -1,7 +1,7 @@
/* gridmtx.h - definitions for Grid Matrix /* gridmtx.h - definitions for Grid Matrix
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2009-2017 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2009-2021 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -30,9 +30,7 @@
*/ */
/* vim: set ts=4 sw=4 et : */ /* vim: set ts=4 sw=4 et : */
#define EUROPIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz " static const char gm_shift_set[] = {
static const char shift_set[] = {
/* From Table 7 - Encoding of control characters */ /* From Table 7 - Encoding of control characters */
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* NULL -> SI */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* NULL -> SI */
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* DLE -> US */ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* DLE -> US */

View File

@ -52,7 +52,7 @@ static int numeric(const unsigned char *data, int data_len, int offset, int min,
if (data_len) { if (data_len) {
const unsigned char *d = data + offset; const unsigned char *d = data + offset;
const unsigned char *de = d + (data_len > max ? max : data_len); const unsigned char *const de = d + (data_len > max ? max : data_len);
for (; d < de; d++) { for (; d < de; d++) {
if (*d < '0' || *d > '9') { if (*d < '0' || *d > '9') {
@ -90,7 +90,7 @@ static int cset82(const unsigned char *data, int data_len, int offset, int min,
if (data_len) { if (data_len) {
const unsigned char *d = data + offset; const unsigned char *d = data + offset;
const unsigned char *de = d + (data_len > max ? max : data_len); const unsigned char *const de = d + (data_len > max ? max : data_len);
for (; d < de; d++) { for (; d < de; d++) {
if (*d < '!' || *d > 'z' || c82[*d - '!'] == 82) { if (*d < '!' || *d > 'z' || c82[*d - '!'] == 82) {
@ -117,7 +117,7 @@ static int cset39(const unsigned char *data, int data_len, int offset, int min,
if (data_len) { if (data_len) {
const unsigned char *d = data + offset; const unsigned char *d = data + offset;
const unsigned char *de = d + (data_len > max ? max : data_len); const unsigned char *const de = d + (data_len > max ? max : data_len);
for (; d < de; d++) { for (; d < de; d++) {
/* 0-9, A-Z and "#", "-", "/" */ /* 0-9, A-Z and "#", "-", "/" */
@ -145,13 +145,13 @@ static int csum(const unsigned char *data, int data_len, int offset, int min, in
if (!length_only && data_len) { if (!length_only && data_len) {
const unsigned char *d = data + offset; const unsigned char *d = data + offset;
const unsigned char *de = d + (data_len > max ? max : data_len) - 1; /* Note less last character */ const unsigned char *const de = d + (data_len > max ? max : data_len) - 1; /* Note less last character */
int checksum = 0; int checksum = 0;
int factor = (min & 1) ? 1 : 3; int factor = (min & 1) ? 1 : 3;
for (; d < de; d++) { for (; d < de; d++) {
checksum += (*d - '0') * factor; checksum += (*d - '0') * factor;
factor = factor == 3 ? 1 : 3; factor ^= 2; /* Toggles 1 and 3 */
} }
checksum = 10 - checksum % 10; checksum = 10 - checksum % 10;
if (checksum == 10) { if (checksum == 10) {
@ -189,7 +189,7 @@ static int csumalpha(const unsigned char *data, int data_len, int offset, int mi
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83
}; };
const unsigned char *d = data + offset; const unsigned char *d = data + offset;
const unsigned char *de = d + (data_len > max ? max : data_len) - 2; /* Note less last 2 characters */ const unsigned char *const de = d + (data_len > max ? max : data_len) - 2; /* Note less last 2 characters */
int checksum = 0, c1, c2; int checksum = 0, c1, c2;
for (; d < de; d++) { for (; d < de; d++) {
@ -549,7 +549,7 @@ static int pcenc(const unsigned char *data, int data_len, int offset, int min, i
if (!length_only && data_len) { if (!length_only && data_len) {
const unsigned char *d = data + offset; const unsigned char *d = data + offset;
const unsigned char *de = d + (data_len > max ? max : data_len); const unsigned char *const de = d + (data_len > max ? max : data_len);
for (; d < de; d++) { for (; d < de; d++) {
if (*d == '%') { if (*d == '%') {
@ -746,7 +746,7 @@ static int iban(const unsigned char *data, int data_len, int offset, int min, in
if (!length_only && data_len) { if (!length_only && data_len) {
const unsigned char *d = data + offset; const unsigned char *d = data + offset;
const unsigned char *de = d + (data_len > max ? max : data_len); const unsigned char *const de = d + (data_len > max ? max : data_len);
int checksum = 0; int checksum = 0;
int given_checksum; int given_checksum;
@ -1394,7 +1394,7 @@ INTERNAL char gs1_check_digit(const unsigned char source[], const int length) {
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
count += factor * ctoi(source[i]); count += factor * ctoi(source[i]);
factor = factor == 1 ? 3 : 1; factor ^= 2; /* Toggles 1 and 3 */
} }
return itoc((10 - (count % 10)) % 10); return itoc((10 - (count % 10)) % 10);

View File

@ -474,7 +474,7 @@ static void hx_define_mode(char *mode, const unsigned int gbdata[], const int le
/* Get optimal mode for each code point by tracing backwards */ /* Get optimal mode for each code point by tracing backwards */
for (i = length - 1, cm_i = i * HX_NUM_MODES; i >= 0; i--, cm_i -= HX_NUM_MODES) { for (i = length - 1, cm_i = i * HX_NUM_MODES; i >= 0; i--, cm_i -= HX_NUM_MODES) {
j = strchr(mode_types, cur_mode) - mode_types; j = posn(mode_types, cur_mode);
cur_mode = char_modes[cm_i + j]; cur_mode = char_modes[cm_i + j];
mode[i] = cur_mode; mode[i] = cur_mode;
} }
@ -535,17 +535,17 @@ static void calculate_binary(char binary[], const char mode[], unsigned int sour
while (i < block_length) { while (i < block_length) {
int first = 0; int first = 0;
first = posn(NEON, (char) source[position + i]); first = ctoi((const char) source[position + i]);
count = 1; count = 1;
encoding_value = first; encoding_value = first;
if (i + 1 < block_length && mode[position + i + 1] == 'n') { if (i + 1 < block_length && mode[position + i + 1] == 'n') {
int second = posn(NEON, (char) source[position + i + 1]); int second = ctoi((const char) source[position + i + 1]);
count = 2; count = 2;
encoding_value = (encoding_value * 10) + second; encoding_value = (encoding_value * 10) + second;
if (i + 2 < block_length && mode[position + i + 2] == 'n') { if (i + 2 < block_length && mode[position + i + 2] == 'n') {
int third = posn(NEON, (char) source[position + i + 2]); int third = ctoi((const char) source[position + i + 2]);
count = 3; count = 3;
encoding_value = (encoding_value * 10) + third; encoding_value = (encoding_value * 10) + third;
} }

View File

@ -38,7 +38,7 @@
#include "common.h" #include "common.h"
#include "large.h" #include "large.h"
#define SODIUM "0123456789-" #define SODIUM_MNS_F (IS_NUM_F | IS_MNS_F) /* SODIUM "0123456789-" */
/* The following lookup tables were generated using the code in Appendix C */ /* The following lookup tables were generated using the code in Appendix C */
@ -242,11 +242,11 @@ static unsigned short USPS_MSB_Math_CRC11GenerateFrameCheckSequence(unsigned cha
return FrameCheckSequence; return FrameCheckSequence;
} }
INTERNAL int daft_set_height(struct zint_symbol *symbol, float min_height, float max_height); INTERNAL int daft_set_height(struct zint_symbol *symbol, const float min_height, const float max_height);
INTERNAL int usps_imail(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int usps_imail(struct zint_symbol *symbol, unsigned char source[], int length) {
char data_pattern[200]; char data_pattern[200];
int error_number; int error_number = 0;
int i, j, read; int i, j, read;
char zip[35], tracker[35], temp[2]; char zip[35], tracker[35], temp[2];
large_int accum; large_int accum;
@ -262,10 +262,9 @@ INTERNAL int usps_imail(struct zint_symbol *symbol, unsigned char source[], int
strcpy(symbol->errtxt, "450: Input too long (32 character maximum)"); strcpy(symbol->errtxt, "450: Input too long (32 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
error_number = is_sane(SODIUM, source, length); if (!is_sane(SODIUM_MNS_F, source, length)) {
if (error_number == ZINT_ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "451: Invalid character in data (digits and \"-\" only)"); strcpy(symbol->errtxt, "451: Invalid character in data (digits and \"-\" only)");
return error_number; return ZINT_ERROR_INVALID_DATA;
} }
strcpy(zip, ""); strcpy(zip, "");

View File

@ -57,7 +57,7 @@
/* Convert decimal string `s` of (at most) length `length` to 64-bit and place in 128-bit `t` */ /* Convert decimal string `s` of (at most) length `length` to 64-bit and place in 128-bit `t` */
INTERNAL void large_load_str_u64(large_int *t, const unsigned char *s, const int length) { INTERNAL void large_load_str_u64(large_int *t, const unsigned char *s, const int length) {
uint64_t val = 0; uint64_t val = 0;
const unsigned char *se = s + length; const unsigned char *const se = s + length;
for (; s < se && *s >= '0' && *s <= '9'; s++) { for (; s < se && *s >= '0' && *s <= '9'; s++) {
val *= 10; val *= 10;
val += *s - '0'; val += *s - '0';

View File

@ -41,8 +41,6 @@
#include "gs1.h" #include "gs1.h"
#include "zfiletypes.h" #include "zfiletypes.h"
#define TECHNETIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"
/* It's assumed that int is at least 32 bits, the following will compile-time fail if not /* It's assumed that int is at least 32 bits, the following will compile-time fail if not
* https://stackoverflow.com/a/1980056 */ * https://stackoverflow.com/a/1980056 */
typedef int static_assert_int_at_least_32bits[CHAR_BIT != 8 || sizeof(int) < 4 ? -1 : 1]; typedef int static_assert_int_at_least_32bits[CHAR_BIT != 8 || sizeof(int) < 4 ? -1 : 1];
@ -51,11 +49,9 @@ typedef int static_assert_int_at_least_32bits[CHAR_BIT != 8 || sizeof(int) < 4 ?
struct zint_symbol *ZBarcode_Create() { struct zint_symbol *ZBarcode_Create() {
struct zint_symbol *symbol; struct zint_symbol *symbol;
symbol = (struct zint_symbol *) malloc(sizeof(*symbol)); symbol = (struct zint_symbol *) calloc(1, sizeof(*symbol));
if (!symbol) return NULL; if (!symbol) return NULL;
memset(symbol, 0, sizeof(*symbol));
symbol->symbology = BARCODE_CODE128; symbol->symbology = BARCODE_CODE128;
symbol->scale = 1.0f; symbol->scale = 1.0f;
strcpy(symbol->fgcolour, "000000"); strcpy(symbol->fgcolour, "000000");
@ -86,14 +82,12 @@ INTERNAL void vector_free(struct zint_symbol *symbol); /* Free vector structures
/* Free any output buffers that may have been created and initialize output fields */ /* Free any output buffers that may have been created and initialize output fields */
void ZBarcode_Clear(struct zint_symbol *symbol) { void ZBarcode_Clear(struct zint_symbol *symbol) {
int i, j; int i;
if (!symbol) return; if (!symbol) return;
for (i = 0; i < symbol->rows; i++) { for (i = 0; i < symbol->rows; i++) {
for (j = 0; j < symbol->width; j++) { memset(symbol->encoded_data[i], 0, sizeof(symbol->encoded_data[0]));
unset_module(symbol, i, j);
}
} }
symbol->rows = 0; symbol->rows = 0;
symbol->width = 0; symbol->width = 0;
@ -209,8 +203,8 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
STATIC_UNLESS_ZINT_TEST int error_tag(struct zint_symbol *symbol, int error_number, const char *error_string) { STATIC_UNLESS_ZINT_TEST int error_tag(struct zint_symbol *symbol, int error_number, const char *error_string) {
if (error_number != 0) { if (error_number != 0) {
static const char *error_fmt = "Error %.93s"; /* Truncate if too long */ static const char error_fmt[] = "Error %.93s"; /* Truncate if too long */
static const char *warn_fmt = "Warning %.91s"; /* Truncate if too long */ static const char warn_fmt[] = "Warning %.91s"; /* Truncate if too long */
const char *fmt = error_number >= ZINT_ERROR ? error_fmt : warn_fmt; const char *fmt = error_number >= ZINT_ERROR ? error_fmt : warn_fmt;
char error_buffer[100]; char error_buffer[100];
@ -291,61 +285,36 @@ static int dump_plot(struct zint_symbol *symbol) {
return 0; return 0;
} }
static const char TECHNETIUM[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"; /* Same as SILVER (CODE39) */
/* Process health industry bar code data */ /* Process health industry bar code data */
static int hibc(struct zint_symbol *symbol, unsigned char source[], int length) { static int hibc(struct zint_symbol *symbol, unsigned char source[], int length) {
int i; int i;
int counter, error_number = 0; int counter, error_number = 0;
char to_process[113], check_digit; char to_process[110 + 2 + 1];
int posns[110];
/* without "+" and check: max 110 characters in HIBC 2.6 */ /* without "+" and check: max 110 characters in HIBC 2.6 */
if (length > 110) { if (length > 110) {
strcpy(symbol->errtxt, "202: Data too long for HIBC LIC (110 character maximum)"); strcpy(symbol->errtxt, "202: Data too long for HIBC LIC (110 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
to_upper(source); to_upper(source, length);
if (is_sane(TECHNETIUM, source, length) != 0) { if (!is_sane_lookup(TECHNETIUM, sizeof(TECHNETIUM) - 1, source, length, posns)) {
strcpy(symbol->errtxt, "203: Invalid character in data (alphanumerics, space and \"-.$/+%\" only)"); strcpy(symbol->errtxt, "203: Invalid character in data (alphanumerics, space and \"-.$/+%\" only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
counter = 41; counter = 41;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
counter += posn(TECHNETIUM, source[i]); counter += posns[i];
} }
counter = counter % 43; counter = counter % 43;
if (counter < 10) {
check_digit = itoc(counter);
} else {
if (counter < 36) {
check_digit = (counter - 10) + 'A';
} else {
switch (counter) {
case 36: check_digit = '-';
break;
case 37: check_digit = '.';
break;
case 38: check_digit = ' ';
break;
case 39: check_digit = '$';
break;
case 40: check_digit = '/';
break;
case 41: check_digit = '+';
break;
case 42: check_digit = '%';
break;
default: check_digit = ' ';
break; /* Keep compiler happy */
}
}
}
to_process[0] = '+'; to_process[0] = '+';
memcpy(to_process + 1, source, length); memcpy(to_process + 1, source, length);
to_process[length + 1] = check_digit; to_process[++length] = TECHNETIUM[counter];
length += 2; to_process[++length] = '\0';
to_process[length] = '\0';
switch (symbol->symbology) { switch (symbol->symbology) {
case BARCODE_HIBC_128: case BARCODE_HIBC_128:
@ -538,7 +507,7 @@ static int has_hrt(const int symbology) {
/* Used for dispatching barcodes and for whether symbol id valid */ /* Used for dispatching barcodes and for whether symbol id valid */
typedef int (*barcode_func_t)(struct zint_symbol *, unsigned char *, int); typedef int (*barcode_func_t)(struct zint_symbol *, unsigned char *, int);
static const barcode_func_t barcode_funcs[146] = { static const barcode_func_t barcode_funcs[BARCODE_LAST + 1] = {
NULL, code11, c25standard, c25inter, c25iata, /*0-4*/ NULL, code11, c25standard, c25inter, c25iata, /*0-4*/
NULL, c25logic, c25ind, code39, excode39, /*5-9*/ NULL, c25logic, c25ind, code39, excode39, /*5-9*/
NULL, NULL, NULL, eanx, eanx, /*10-14*/ NULL, NULL, NULL, eanx, eanx, /*10-14*/
@ -895,7 +864,7 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
symbol->symbology = BARCODE_CODE128; symbol->symbology = BARCODE_CODE128;
} }
/* Everything from 128 up is Zint-specific */ /* Everything from 128 up is Zint-specific */
} else if (symbol->symbology > 145) { } else if (symbol->symbology > BARCODE_LAST) {
warn_number = error_tag(symbol, ZINT_WARN_INVALID_OPTION, "216: Symbology out of range"); warn_number = error_tag(symbol, ZINT_WARN_INVALID_OPTION, "216: Symbology out of range");
if (warn_number >= ZINT_ERROR) { if (warn_number >= ZINT_ERROR) {
return warn_number; return warn_number;
@ -1033,10 +1002,8 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
return error_number; return error_number;
} }
/* Output a previously encoded symbol to file `symbol->outfile` */ /* Helper for output routines to check `rotate_angle` and dottiness */
int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) { static int check_output_args(struct zint_symbol *symbol, int rotate_angle) {
int error_number;
int len;
if (!symbol) return ZINT_ERROR_INVALID_DATA; if (!symbol) return ZINT_ERROR_INVALID_DATA;
@ -1051,10 +1018,20 @@ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) {
break; break;
} }
if (symbol->output_options & BARCODE_DOTTY_MODE) { if ((symbol->output_options & BARCODE_DOTTY_MODE) && !(is_dotty(symbol->symbology))) {
if (!(is_dotty(symbol->symbology))) { return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "224: Selected symbology cannot be rendered as dots");
return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "224: Selected symbology cannot be rendered as dots"); }
}
return 0;
}
/* Output a previously encoded symbol to file `symbol->outfile` */
int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) {
int error_number;
int len;
if ((error_number = check_output_args(symbol, rotate_angle))) { /* >= ZINT_ERROR only */
return error_number; /* Already tagged */
} }
len = (int) strlen(symbol->outfile); len = (int) strlen(symbol->outfile);
@ -1064,7 +1041,7 @@ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) {
output[1] = symbol->outfile[len - 2]; output[1] = symbol->outfile[len - 2];
output[2] = symbol->outfile[len - 1]; output[2] = symbol->outfile[len - 1];
output[3] = '\0'; output[3] = '\0';
to_upper((unsigned char *) output); to_upper((unsigned char *) output, 3);
if (!(strcmp(output, "PNG"))) { if (!(strcmp(output, "PNG"))) {
error_number = plot_raster(symbol, rotate_angle, OUT_PNG_FILE); error_number = plot_raster(symbol, rotate_angle, OUT_PNG_FILE);
@ -1107,23 +1084,8 @@ int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) {
int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle) { int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle) {
int error_number; int error_number;
if (!symbol) return ZINT_ERROR_INVALID_DATA; if ((error_number = check_output_args(symbol, rotate_angle))) { /* >= ZINT_ERROR only */
return error_number; /* Already tagged */
switch (rotate_angle) {
case 0:
case 90:
case 180:
case 270:
break;
default:
return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "228: Invalid rotation angle");
break;
}
if (symbol->output_options & BARCODE_DOTTY_MODE) {
if (!(is_dotty(symbol->symbology))) {
return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "237: Selected symbology cannot be rendered as dots");
}
} }
error_number = plot_raster(symbol, rotate_angle, OUT_BUFFER); error_number = plot_raster(symbol, rotate_angle, OUT_BUFFER);
@ -1134,23 +1096,8 @@ int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle) {
int ZBarcode_Buffer_Vector(struct zint_symbol *symbol, int rotate_angle) { int ZBarcode_Buffer_Vector(struct zint_symbol *symbol, int rotate_angle) {
int error_number; int error_number;
if (!symbol) return ZINT_ERROR_INVALID_DATA; if ((error_number = check_output_args(symbol, rotate_angle))) { /* >= ZINT_ERROR only */
return error_number; /* Already tagged */
switch (rotate_angle) {
case 0:
case 90:
case 180:
case 270:
break;
default:
return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "219: Invalid rotation angle");
break;
}
if (symbol->output_options & BARCODE_DOTTY_MODE) {
if (!(is_dotty(symbol->symbology))) {
return error_tag(symbol, ZINT_ERROR_INVALID_OPTION, "238: Selected symbology cannot be rendered as dots");
}
} }
error_number = plot_vector(symbol, rotate_angle, OUT_BUFFER); error_number = plot_vector(symbol, rotate_angle, OUT_BUFFER);
@ -1350,7 +1297,7 @@ int ZBarcode_Encode_File_and_Buffer_Vector(struct zint_symbol *symbol, const cha
/* Checks whether a symbology is supported */ /* Checks whether a symbology is supported */
int ZBarcode_ValidID(int symbol_id) { int ZBarcode_ValidID(int symbol_id) {
if (symbol_id <= 0 || symbol_id > 145) { if (symbol_id <= 0 || symbol_id > BARCODE_LAST) {
return 0; return 0;
} }
@ -1387,7 +1334,7 @@ unsigned int ZBarcode_Cap(int symbol_id, unsigned int cap_flag) {
result |= ZINT_CAP_DOTTY; result |= ZINT_CAP_DOTTY;
} }
if (cap_flag & ZINT_CAP_QUIET_ZONES) { if (cap_flag & ZINT_CAP_QUIET_ZONES) {
switch (symbol_id) { /* See `quiet_zones()` in "output.c" */ switch (symbol_id) { /* See `out_quiet_zones()` in "output.c" */
case BARCODE_CODE16K: case BARCODE_CODE16K:
case BARCODE_CODE49: case BARCODE_CODE49:
case BARCODE_CODABLOCKF: case BARCODE_CODABLOCKF:

View File

@ -49,7 +49,7 @@
#include "large.h" #include "large.h"
#include "reedsol.h" #include "reedsol.h"
#define RUBIDIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " #define RUBIDIUM_F (IS_NUM_F | IS_UPR_F | IS_SPC_F) /* RUBIDIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " */
// Allowed character values from Table 3 // Allowed character values from Table 3
#define SET_F "ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define SET_F "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@ -57,8 +57,10 @@
#define SET_N "0123456789" #define SET_N "0123456789"
#define SET_S " " #define SET_S " "
static const char *postcode_format[6] = { static const char postcode_format[6][9] = {
"FNFNLLNLS", "FFNNLLNLS", "FFNNNLLNL", "FFNFNLLNL", "FNNLLNLSS", "FNNNLLNLS" {'F','N','F','N','L','L','N','L','S'}, {'F','F','N','N','L','L','N','L','S'},
{'F','F','N','N','N','L','L','N','L'}, {'F','F','N','F','N','L','L','N','L'},
{'F','N','N','L','L','N','L','S','S'}, {'F','N','N','N','L','L','N','L','S'}
}; };
// Data/Check Symbols from Table 5 // Data/Check Symbols from Table 5
@ -109,9 +111,7 @@ static int verify_character(char input, char type) {
static int verify_postcode(char *postcode, int type) { static int verify_postcode(char *postcode, int type) {
int i; int i;
char pattern[11]; const char *const pattern = postcode_format[type - 1];
strcpy(pattern, postcode_format[type - 1]);
for (i = 0; i < 9; i++) { for (i = 0; i < 9; i++) {
if (!(verify_character(postcode[i], pattern[i]))) { if (!(verify_character(postcode[i], pattern[i]))) {
@ -122,7 +122,7 @@ static int verify_postcode(char *postcode, int type) {
return 0; return 0;
} }
INTERNAL int daft_set_height(struct zint_symbol *symbol, float min_height, float max_height); INTERNAL int daft_set_height(struct zint_symbol *symbol, const float min_height, const float max_height);
/* Royal Mail Mailmark */ /* Royal Mail Mailmark */
INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int length) {
@ -135,7 +135,7 @@ INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int le
unsigned int item_id; unsigned int item_id;
char postcode[10]; char postcode[10];
int postcode_type; int postcode_type;
char pattern[10]; const char *pattern;
large_int destination_postcode; large_int destination_postcode;
large_int b; large_int b;
large_int cdv; large_int cdv;
@ -144,6 +144,7 @@ INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int le
unsigned char check[7]; unsigned char check[7];
unsigned int extender[27]; unsigned int extender[27];
char bar[80]; char bar[80];
char *d = bar;
int check_count; int check_count;
int i, j, len; int i, j, len;
rs_t rs; rs_t rs;
@ -170,13 +171,13 @@ INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int le
length = 26; length = 26;
} }
to_upper((unsigned char *) local_source); to_upper((unsigned char *) local_source, length);
if (symbol->debug & ZINT_DEBUG_PRINT) { if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("Producing Mailmark %s\n", local_source); printf("Producing Mailmark %s\n", local_source);
} }
if (is_sane(RUBIDIUM, (unsigned char *) local_source, length) != 0) { if (!is_sane(RUBIDIUM_F, (unsigned char *) local_source, length)) {
strcpy(symbol->errtxt, "581: Invalid character in data (alphanumerics and space only)"); strcpy(symbol->errtxt, "581: Invalid character in data (alphanumerics and space only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -285,7 +286,7 @@ INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int le
large_load_u64(&destination_postcode, 0); large_load_u64(&destination_postcode, 0);
if (postcode_type != 7) { if (postcode_type != 7) {
strcpy(pattern, postcode_format[postcode_type - 1]); pattern = postcode_format[postcode_type - 1];
large_load_u64(&b, 0); large_load_u64(&b, 0);
@ -440,45 +441,42 @@ INTERNAL int mailmark(struct zint_symbol *symbol, unsigned char source[], int le
} }
// Conversion from Extender Groups to Bar Identifiers // Conversion from Extender Groups to Bar Identifiers
strcpy(bar, "");
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
for (j = 0; j < 3; j++) { for (j = 0; j < 3; j++) {
switch (extender[i] & 0x24) { switch (extender[i] & 0x24) {
case 0x24: case 0x24:
strcat(bar, "F"); *d++ = 'F';
break; break;
case 0x20: case 0x20:
if (i % 2) { if (i % 2) {
strcat(bar, "D"); *d++ = 'D';
} else { } else {
strcat(bar, "A"); *d++ = 'A';
} }
break; break;
case 0x04: case 0x04:
if (i % 2) { if (i % 2) {
strcat(bar, "A"); *d++ = 'A';
} else { } else {
strcat(bar, "D"); *d++ = 'D';
} }
break; break;
default: default:
strcat(bar, "T"); *d++ = 'T';
break; break;
} }
extender[i] = extender[i] << 1; extender[i] = extender[i] << 1;
} }
} }
bar[(length * 3)] = '\0';
if (symbol->debug & ZINT_DEBUG_PRINT) { if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("Bar pattern: %s\n", bar); printf("Bar pattern: %.*s\n", (int) (d - bar), bar);
} }
/* Translate 4-state data pattern to symbol */ /* Translate 4-state data pattern to symbol */
j = 0; j = 0;
for (i = 0, len = (int) strlen(bar); i < len; i++) { for (i = 0, len = d - bar; i < len; i++) {
if ((bar[i] == 'F') || (bar[i] == 'A')) { if ((bar[i] == 'F') || (bar[i] == 'A')) {
set_module(symbol, 0, j); set_module(symbol, 0, j);
} }

View File

@ -612,7 +612,7 @@ INTERNAL int maxicode(struct zint_symbol *symbol, unsigned char source[], int le
postcode[i] = ' '; postcode[i] = ' ';
} }
/* Upper-case and check for Code Set A characters only */ /* Upper-case and check for Code Set A characters only */
to_upper(postcode); to_upper(postcode, postcode_len);
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
/* Don't allow Code Set A control characters CR, RS, GS and RS */ /* Don't allow Code Set A control characters CR, RS, GS and RS */
if (postcode[i] < ' ' || maxiCodeSet[postcode[i]] > 1) { if (postcode[i] < ' ' || maxiCodeSet[postcode[i]] > 1) {

View File

@ -36,15 +36,18 @@
INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int length); INTERNAL int code39(struct zint_symbol *symbol, unsigned char source[], int length);
static const char CALCIUM[] = "0123456789-$:/.+ABCD";
#define CALCIUM_INNER_F (IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F) /* CALCIUM_INNER "0123456789-$:/.+" */
/* Codabar table checked against EN 798:1995 */ /* Codabar table checked against EN 798:1995 */
static const char CodaTable[20][8] = {
#define CALCIUM "0123456789-$:/.+ABCD" {'1','1','1','1','1','2','2','1'}, {'1','1','1','1','2','2','1','1'}, {'1','1','1','2','1','1','2','1'},
#define CALCIUM_INNER "0123456789-$:/.+" {'2','2','1','1','1','1','1','1'}, {'1','1','2','1','1','2','1','1'}, {'2','1','1','1','1','2','1','1'},
{'1','2','1','1','1','1','2','1'}, {'1','2','1','1','2','1','1','1'}, {'1','2','2','1','1','1','1','1'},
static const char *CodaTable[20] = { {'2','1','1','2','1','1','1','1'}, {'1','1','1','2','2','1','1','1'}, {'1','1','2','2','1','1','1','1'},
"11111221", "11112211", "11121121", "22111111", "11211211", "21111211", {'2','1','1','1','2','1','2','1'}, {'2','1','2','1','1','1','2','1'}, {'2','1','2','1','2','1','1','1'},
"12111121", "12112111", "12211111", "21121111", "11122111", "11221111", "21112121", "21211121", {'1','1','2','1','2','1','2','1'}, {'1','1','2','2','1','2','1','1'}, {'1','2','1','2','1','1','2','1'},
"21212111", "11212121", "11221211", "12121121", "11121221", "11122211" {'1','1','1','2','1','2','2','1'}, {'1','1','1','2','2','2','1','1'}
}; };
INTERNAL int pharma(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int pharma(struct zint_symbol *symbol, unsigned char source[], int length) {
@ -61,22 +64,23 @@ INTERNAL int pharma(struct zint_symbol *symbol, unsigned char source[], int leng
the specification at http://www.laetus.com/laetus.php?request=file&id=69 the specification at http://www.laetus.com/laetus.php?request=file&id=69
(http://www.gomaro.ch/ftproot/Laetus_PHARMA-CODE.pdf) */ (http://www.gomaro.ch/ftproot/Laetus_PHARMA-CODE.pdf) */
unsigned long int tester; int tester;
int counter, error_number = 0, h; int counter, error_number = 0, h;
char inter[18] = {0}; /* 131070 -> 17 bits */ char inter[18] = {0}; /* 131070 -> 17 bits */
char *in = inter;
char dest[64]; /* 17 * 2 + 1 */ char dest[64]; /* 17 * 2 + 1 */
char *d = dest;
if (length > 6) { if (length > 6) {
strcpy(symbol->errtxt, "350: Input too long (6 character maximum)"); strcpy(symbol->errtxt, "350: Input too long (6 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { tester = to_int(source, length);
if (tester == -1) {
strcpy(symbol->errtxt, "351: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "351: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
tester = atoi((char *) source);
if ((tester < 3) || (tester > 131070)) { if ((tester < 3) || (tester > 131070)) {
strcpy(symbol->errtxt, "352: Data out of range (3 to 131070)"); strcpy(symbol->errtxt, "352: Data out of range (3 to 131070)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
@ -84,25 +88,22 @@ INTERNAL int pharma(struct zint_symbol *symbol, unsigned char source[], int leng
do { do {
if (!(tester & 1)) { if (!(tester & 1)) {
strcat(inter, "W"); *in++ = 'W';
tester = (tester - 2) / 2; tester = (tester - 2) / 2;
} else { } else {
strcat(inter, "N"); *in++ = 'N';
tester = (tester - 1) / 2; tester = (tester - 1) / 2;
} }
} while (tester != 0); } while (tester != 0);
h = (int) strlen(inter) - 1; h = in - inter;
*dest = '\0'; for (counter = h - 1; counter >= 0; counter--) {
for (counter = h; counter >= 0; counter--) { *d++ = inter[counter] == 'W' ? '3' : '1';
if (inter[counter] == 'W') { *d++ = '2';
strcat(dest, "32");
} else {
strcat(dest, "12");
}
} }
*--d = '\0'; /* Chop off final bar */
expand(symbol, dest); expand(symbol, dest, d - dest);
if (symbol->output_options & COMPLIANT_HEIGHT) { if (symbol->output_options & COMPLIANT_HEIGHT) {
/* Laetus Pharmacode Guide 1.2 Standard one-track height 8mm / 0.5mm (X) */ /* Laetus Pharmacode Guide 1.2 Standard one-track height 8mm / 0.5mm (X) */
@ -114,75 +115,66 @@ INTERNAL int pharma(struct zint_symbol *symbol, unsigned char source[], int leng
return error_number; return error_number;
} }
static int pharma_two_calc(struct zint_symbol *symbol, unsigned char source[], char dest[]) { static int pharma_two_calc(int tester, char *d) {
/* This code uses the Two Track Pharamacode defined in the document at /* This code uses the Two Track Pharamacode defined in the document at
http://www.laetus.com/laetus.php?request=file&id=69 and using a modified http://www.laetus.com/laetus.php?request=file&id=69 and using a modified
algorithm from the One Track system. This standard accepts integet values algorithm from the One Track system. This standard accepts integet values
from 4 to 64570080. */ from 4 to 64570080. */
unsigned long int tester;
int counter, h; int counter, h;
char inter[17]; char inter[17];
int error_number; char *in = inter;
tester = atoi((char *) source);
if ((tester < 4) || (tester > 64570080)) {
strcpy(symbol->errtxt, "353: Data out of range (4 to 64570080)");
return ZINT_ERROR_INVALID_DATA;
}
error_number = 0;
strcpy(inter, "");
do { do {
switch (tester % 3) { switch (tester % 3) {
case 0: case 0:
strcat(inter, "3"); *in++ = '3';
tester = (tester - 3) / 3; tester = (tester - 3) / 3;
break; break;
case 1: case 1:
strcat(inter, "1"); *in++ = '1';
tester = (tester - 1) / 3; tester = (tester - 1) / 3;
break; break;
case 2: case 2:
strcat(inter, "2"); *in++ = '2';
tester = (tester - 2) / 3; tester = (tester - 2) / 3;
break; break;
} }
} while (tester != 0); } while (tester != 0);
h = (int) strlen(inter) - 1; h = in - inter;
for (counter = h; counter >= 0; counter--) { for (counter = h - 1; counter >= 0; counter--) {
dest[h - counter] = inter[counter]; *d++ = inter[counter];
} }
dest[h + 1] = '\0'; *d = '\0';
return error_number; return h;
} }
INTERNAL int pharma_two(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int pharma_two(struct zint_symbol *symbol, unsigned char source[], int length) {
/* Draws the patterns for two track pharmacode */ /* Draws the patterns for two track pharmacode */
int tester;
char height_pattern[200]; char height_pattern[200];
unsigned int loopey, h; unsigned int loopey, h;
int writer; int writer;
int error_number; int error_number = 0;
strcpy(height_pattern, "");
if (length > 8) { if (length > 8) {
strcpy(symbol->errtxt, "354: Input too long (8 character maximum"); strcpy(symbol->errtxt, "354: Input too long (8 character maximum");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { tester = to_int(source, length);
if (tester == -1) {
strcpy(symbol->errtxt, "355: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "355: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
error_number = pharma_two_calc(symbol, source, height_pattern); if ((tester < 4) || (tester > 64570080)) {
if (error_number != 0) { strcpy(symbol->errtxt, "353: Data out of range (4 to 64570080)");
return error_number; return ZINT_ERROR_INVALID_DATA;
} }
h = pharma_two_calc(tester, height_pattern);
writer = 0; writer = 0;
h = (int) strlen(height_pattern);
for (loopey = 0; loopey < h; loopey++) { for (loopey = 0; loopey < h; loopey++) {
if ((height_pattern[loopey] == '2') || (height_pattern[loopey] == '3')) { if ((height_pattern[loopey] == '2') || (height_pattern[loopey] == '3')) {
set_module(symbol, 0, writer); set_module(symbol, 0, writer);
@ -209,14 +201,13 @@ INTERNAL int pharma_two(struct zint_symbol *symbol, unsigned char source[], int
/* The Codabar system consisting of simple substitution */ /* The Codabar system consisting of simple substitution */
INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int length) {
static const char calcium[] = CALCIUM;
int i, error_number = 0; int i, error_number = 0;
int posns[60];
char dest[512]; char dest[512];
char *d = dest;
int add_checksum, count = 0, checksum = 0; int add_checksum, count = 0, checksum = 0;
int d_chars = 0; int d_chars = 0;
strcpy(dest, "");
if (length > 60) { /* No stack smashing please */ if (length > 60) { /* No stack smashing please */
strcpy(symbol->errtxt, "356: Input too long (60 character maximum)"); strcpy(symbol->errtxt, "356: Input too long (60 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
@ -227,7 +218,7 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len
strcpy(symbol->errtxt, "362: Input too short (3 character minimum)"); strcpy(symbol->errtxt, "362: Input too short (3 character minimum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
to_upper(source); to_upper(source, length);
/* Codabar must begin and end with the characters A, B, C or D */ /* Codabar must begin and end with the characters A, B, C or D */
if ((source[0] != 'A') && (source[0] != 'B') && (source[0] != 'C') if ((source[0] != 'A') && (source[0] != 'B') && (source[0] != 'C')
@ -240,14 +231,13 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len
strcpy(symbol->errtxt, "359: Does not end with \"A\", \"B\", \"C\" or \"D\""); strcpy(symbol->errtxt, "359: Does not end with \"A\", \"B\", \"C\" or \"D\"");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
if (!is_sane_lookup(CALCIUM, sizeof(CALCIUM) - 1, source, length, posns)) {
sprintf(symbol->errtxt, "357: Invalid character in data (\"%s\" only)", CALCIUM);
return ZINT_ERROR_INVALID_DATA;
}
/* And must not use A, B, C or D otherwise (BS EN 798:1995 4.3.2) */ /* And must not use A, B, C or D otherwise (BS EN 798:1995 4.3.2) */
if (is_sane(CALCIUM_INNER, source + 1, length - 2) != 0) { if (!is_sane(CALCIUM_INNER_F, source + 1, length - 2)) {
if (is_sane(calcium, source + 1, length - 2) == 0) { strcpy(symbol->errtxt, "363: Cannot contain \"A\", \"B\", \"C\" or \"D\"");
strcpy(symbol->errtxt, "363: Cannot contain \"A\", \"B\", \"C\" or \"D\"");
} else {
sprintf(symbol->errtxt, "357: Invalid character in data (\"%s\" only)", calcium);
}
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -255,29 +245,30 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len
(unfortunately to maintain back-compatibility, this is reverse of C25) */ (unfortunately to maintain back-compatibility, this is reverse of C25) */
add_checksum = symbol->option_2 == 1 || symbol->option_2 == 2; add_checksum = symbol->option_2 == 1 || symbol->option_2 == 2;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++, d += 8) {
if (add_checksum) { if (add_checksum) {
/* BS EN 798:1995 A.3 suggests using ISO 7064 algorithm but leaves it application defined. /* BS EN 798:1995 A.3 suggests using ISO 7064 algorithm but leaves it application defined.
Following BWIPP and TEC-IT, use this simple mod-16 algorithm (not in ISO 7064) */ Following BWIPP and TEC-IT, use this simple mod-16 algorithm (not in ISO 7064) */
count += strchr(calcium, source[i]) - calcium; count += posns[i];
if (i + 1 == length) { if (i + 1 == length) {
checksum = count % 16; checksum = count % 16;
if (checksum) { if (checksum) {
checksum = 16 - checksum; checksum = 16 - checksum;
} }
if (symbol->debug & ZINT_DEBUG_PRINT) { if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("Codabar: %s, count %d, checksum %d (%c)\n", source, count, checksum, calcium[checksum]); printf("Codabar: %s, count %d, checksum %d (%c)\n", source, count, checksum, CALCIUM[checksum]);
} }
strcat(dest, CodaTable[checksum]); memcpy(d, CodaTable[checksum], 8);
d += 8;
} }
} }
lookup(calcium, CodaTable, source[i], dest); memcpy(d, CodaTable[posns[i]], 8);
if (source[i] == '/' || source[i] == ':' || source[i] == '.' || source[i] == '+') { /* Wide data characters */ if (source[i] == '/' || source[i] == ':' || source[i] == '.' || source[i] == '+') { /* Wide data characters */
d_chars++; d_chars++;
} }
} }
expand(symbol, dest); expand(symbol, dest, d - dest);
if (symbol->output_options & COMPLIANT_HEIGHT) { if (symbol->output_options & COMPLIANT_HEIGHT) {
/* BS EN 798:1995 4.4.1 (d) max of 5mm / 0.191mm (X) ~ 26.178 or 15% of width where (taking N = narrow/wide /* BS EN 798:1995 4.4.1 (d) max of 5mm / 0.191mm (X) ~ 26.178 or 15% of width where (taking N = narrow/wide
@ -297,7 +288,7 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len
ustrcpy(symbol->text, source); ustrcpy(symbol->text, source);
if (symbol->option_2 == 2) { if (symbol->option_2 == 2) {
symbol->text[length - 1] = calcium[checksum]; /* Place before final A/B/C/D character (BS EN 798:1995 A.3) */ symbol->text[length - 1] = CALCIUM[checksum]; /* Place before final A/B/C/D character (BS EN 798:1995 A.3) */
symbol->text[length] = source[length - 1]; symbol->text[length] = source[length - 1];
symbol->text[length + 1] = '\0'; symbol->text[length + 1] = '\0';
} }
@ -307,18 +298,18 @@ INTERNAL int codabar(struct zint_symbol *symbol, unsigned char source[], int len
/* Italian Pharmacode */ /* Italian Pharmacode */
INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int length) {
static const char TABELLA[] = "0123456789BCDFGHJKLMNPQRSTUVWXYZ";
int i, zeroes, error_number = 0, checksum, checkpart, checkdigit; int i, zeroes, error_number = 0, checksum, checkpart, checkdigit;
char localstr[10], risultante[7]; char localstr[10], risultante[7];
long int pharmacode, devisor; long int pharmacode, devisor;
int codeword[6]; int codeword[6];
char tabella[34];
/* Validate the input */ /* Validate the input */
if (length > 8) { if (length > 8) {
strcpy(symbol->errtxt, "360: Input too long (8 character maximum)"); strcpy(symbol->errtxt, "360: Input too long (8 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "361: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "361: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -360,13 +351,12 @@ INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int leng
} }
/* Look up values in 'Tabella di conversione' */ /* Look up values in 'Tabella di conversione' */
strcpy(tabella, "0123456789BCDFGHJKLMNPQRSTUVWXYZ");
for (i = 5; i >= 0; i--) { for (i = 5; i >= 0; i--) {
risultante[5 - i] = tabella[codeword[i]]; risultante[5 - i] = TABELLA[codeword[i]];
} }
risultante[6] = '\0'; risultante[6] = '\0';
/* Plot the barcode using Code 39 */ /* Plot the barcode using Code 39 */
error_number = code39(symbol, (unsigned char *) risultante, (int) strlen(risultante)); error_number = code39(symbol, (unsigned char *) risultante, 6);
if (error_number != 0) { /* Should never happen */ if (error_number != 0) { /* Should never happen */
return error_number; /* Not reached */ return error_number; /* Not reached */
} }

View File

@ -35,32 +35,31 @@
#include "output.h" #include "output.h"
#include "font.h" #include "font.h"
#define SSET "0123456789ABCDEF" #define SSET_F (IS_NUM_F | IS_UHX_F) /* SSET "0123456789ABCDEF" */
/* Check colour options are good. Note: using raster.c error nos 651-654 */ /* Check colour options are good. Note: using raster.c error nos 651-654 */
INTERNAL int output_check_colour_options(struct zint_symbol *symbol) { INTERNAL int out_check_colour_options(struct zint_symbol *symbol) {
int error_number; int fg_len = (int) strlen(symbol->fgcolour);
int bg_len = (int) strlen(symbol->bgcolour);
if ((strlen(symbol->fgcolour) != 6) && (strlen(symbol->fgcolour) != 8)) { if ((fg_len != 6) && (fg_len != 8)) {
strcpy(symbol->errtxt, "651: Malformed foreground colour target"); strcpy(symbol->errtxt, "651: Malformed foreground colour target");
return ZINT_ERROR_INVALID_OPTION; return ZINT_ERROR_INVALID_OPTION;
} }
if ((strlen(symbol->bgcolour) != 6) && (strlen(symbol->bgcolour) != 8)) { if ((bg_len != 6) && (bg_len != 8)) {
strcpy(symbol->errtxt, "652: Malformed background colour target"); strcpy(symbol->errtxt, "652: Malformed background colour target");
return ZINT_ERROR_INVALID_OPTION; return ZINT_ERROR_INVALID_OPTION;
} }
to_upper((unsigned char *) symbol->fgcolour); to_upper((unsigned char *) symbol->fgcolour, fg_len);
to_upper((unsigned char *) symbol->bgcolour); to_upper((unsigned char *) symbol->bgcolour, bg_len);
error_number = is_sane(SSET, (unsigned char *) symbol->fgcolour, (int) strlen(symbol->fgcolour)); if (!is_sane(SSET_F, (unsigned char *) symbol->fgcolour, fg_len)) {
if (error_number == ZINT_ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "653: Malformed foreground colour target"); strcpy(symbol->errtxt, "653: Malformed foreground colour target");
return ZINT_ERROR_INVALID_OPTION; return ZINT_ERROR_INVALID_OPTION;
} }
error_number = is_sane(SSET, (unsigned char *) symbol->bgcolour, (int) strlen(symbol->bgcolour)); if (!is_sane(SSET_F, (unsigned char *) symbol->bgcolour, bg_len)) {
if (error_number == ZINT_ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "654: Malformed background colour target"); strcpy(symbol->errtxt, "654: Malformed background colour target");
return ZINT_ERROR_INVALID_OPTION; return ZINT_ERROR_INVALID_OPTION;
} }
@ -69,7 +68,7 @@ INTERNAL int output_check_colour_options(struct zint_symbol *symbol) {
} }
/* Return minimum quiet zones for each symbology */ /* Return minimum quiet zones for each symbology */
STATIC_UNLESS_ZINT_TEST int quiet_zones(const struct zint_symbol *symbol, const int hide_text, STATIC_UNLESS_ZINT_TEST int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text,
float *left, float *right, float *top, float *bottom) { float *left, float *right, float *top, float *bottom) {
int done = 0; int done = 0;
@ -192,7 +191,7 @@ STATIC_UNLESS_ZINT_TEST int quiet_zones(const struct zint_symbol *symbol, const
/* Only do others if flag set */ /* Only do others if flag set */
if (!(symbol->output_options & BARCODE_QUIET_ZONES) || (symbol->output_options & BARCODE_NO_QUIET_ZONES)) { if (!(symbol->output_options & BARCODE_QUIET_ZONES) || (symbol->output_options & BARCODE_NO_QUIET_ZONES)) {
return done; return 0;
} }
switch (symbol->symbology) { switch (symbol->symbology) {
@ -471,12 +470,12 @@ STATIC_UNLESS_ZINT_TEST int quiet_zones(const struct zint_symbol *symbol, const
} }
/* Set left (x), top (y), right and bottom offsets for whitespace */ /* Set left (x), top (y), right and bottom offsets for whitespace */
INTERNAL void output_set_whitespace_offsets(const struct zint_symbol *symbol, const int hide_text, INTERNAL void out_set_whitespace_offsets(const struct zint_symbol *symbol, const int hide_text,
float *xoffset, float *yoffset, float *roffset, float *boffset, const float scaler, float *xoffset, float *yoffset, float *roffset, float *boffset, const float scaler,
int *xoffset_si, int *yoffset_si, int *roffset_si, int *boffset_si) { int *xoffset_si, int *yoffset_si, int *roffset_si, int *boffset_si) {
float qz_left, qz_right, qz_top, qz_bottom; float qz_left, qz_right, qz_top, qz_bottom;
quiet_zones(symbol, hide_text, &qz_left, &qz_right, &qz_top, &qz_bottom); out_quiet_zones(symbol, hide_text, &qz_left, &qz_right, &qz_top, &qz_bottom);
*xoffset = symbol->whitespace_width + qz_left; *xoffset = symbol->whitespace_width + qz_left;
*roffset = symbol->whitespace_width + qz_right; *roffset = symbol->whitespace_width + qz_right;
@ -510,7 +509,7 @@ INTERNAL void output_set_whitespace_offsets(const struct zint_symbol *symbol, co
/* Set composite offset and main width excluding addon (for start of addon calc) and addon text, returning /* Set composite offset and main width excluding addon (for start of addon calc) and addon text, returning
UPC/EAN type */ UPC/EAN type */
INTERNAL int output_process_upcean(const struct zint_symbol *symbol, int *p_main_width, int *p_comp_xoffset, INTERNAL int out_process_upcean(const struct zint_symbol *symbol, int *p_main_width, int *p_comp_xoffset,
unsigned char addon[6], int *p_addon_gap) { unsigned char addon[6], int *p_addon_gap) {
int main_width; /* Width of main linear symbol, excluding addon */ int main_width; /* Width of main linear symbol, excluding addon */
int comp_xoffset; /* Whitespace offset (if any) of main linear symbol due to having composite */ int comp_xoffset; /* Whitespace offset (if any) of main linear symbol due to having composite */
@ -588,9 +587,9 @@ INTERNAL int output_process_upcean(const struct zint_symbol *symbol, int *p_main
} }
/* Calculate large bar height i.e. linear bars with zero row height that respond to the symbol height. /* Calculate large bar height i.e. linear bars with zero row height that respond to the symbol height.
If scaler `si` non-zero (raster), then large_bar_height if non-zero or else row heights will be rounded to nearest If scaler `si` non-zero (raster), then large_bar_height if non-zero or else row heights will be rounded
pixel and symbol height adjusted */ to nearest pixel and symbol height adjusted */
INTERNAL float output_large_bar_height(struct zint_symbol *symbol, int si) { INTERNAL float out_large_bar_height(struct zint_symbol *symbol, int si) {
float fixed_height = 0.0f; float fixed_height = 0.0f;
int zero_count = 0; int zero_count = 0;
int round_rows = 0; int round_rows = 0;
@ -609,15 +608,14 @@ INTERNAL float output_large_bar_height(struct zint_symbol *symbol, int si) {
} }
if (zero_count) { if (zero_count) {
large_bar_height = (symbol->height - fixed_height) / zero_count; large_bar_height = stripf((symbol->height - fixed_height) / zero_count);
if (large_bar_height <= 0.0f) { /* Shouldn't happen but protect against memory access violations */ if (large_bar_height <= 0.0f) { /* Shouldn't happen but protect against memory access violations */
large_bar_height = 0.0078125f; /* Token positive value (exact float 2**-6) */ large_bar_height = 0.0078125f; /* Token positive value (exact float 2**-6) */
symbol->height = large_bar_height * zero_count + fixed_height;
} }
if (si && !isfintf(large_bar_height * si)) { if (si && !isfintf(large_bar_height * si)) {
large_bar_height = roundf(large_bar_height * si) / si; large_bar_height = stripf(roundf(large_bar_height * si) / si);
symbol->height = large_bar_height * zero_count + fixed_height;
} }
symbol->height = stripf(large_bar_height * zero_count + fixed_height);
/* Note should never happen that have both zero_count and round_rows */ /* Note should never happen that have both zero_count and round_rows */
} else { } else {
large_bar_height = 0.0f; /* Not used if zero_count zero */ large_bar_height = 0.0f; /* Not used if zero_count zero */
@ -629,7 +627,7 @@ INTERNAL float output_large_bar_height(struct zint_symbol *symbol, int si) {
} }
fixed_height += symbol->row_height[i]; fixed_height += symbol->row_height[i];
} }
symbol->height = fixed_height; symbol->height = stripf(fixed_height);
} }
} }
@ -637,7 +635,7 @@ INTERNAL float output_large_bar_height(struct zint_symbol *symbol, int si) {
} }
/* Split UPC/EAN add-on text into various constituents */ /* Split UPC/EAN add-on text into various constituents */
INTERNAL void output_upcean_split_text(int upceanflag, unsigned char text[], INTERNAL void out_upcean_split_text(int upceanflag, unsigned char text[],
unsigned char textpart1[5], unsigned char textpart2[7], unsigned char textpart3[7], unsigned char textpart1[5], unsigned char textpart2[7], unsigned char textpart3[7],
unsigned char textpart4[2]) { unsigned char textpart4[2]) {
int i; int i;

View File

@ -37,14 +37,14 @@
extern "C" { extern "C" {
#endif /* __cplusplus */ #endif /* __cplusplus */
INTERNAL int output_check_colour_options(struct zint_symbol *symbol); INTERNAL int out_check_colour_options(struct zint_symbol *symbol);
INTERNAL void output_set_whitespace_offsets(const struct zint_symbol *symbol, const int hide_text, INTERNAL void out_set_whitespace_offsets(const struct zint_symbol *symbol, const int hide_text,
float *xoffset, float *yoffset, float *roffset, float *boffset, const float scaler, float *xoffset, float *yoffset, float *roffset, float *boffset, const float scaler,
int *xoffset_si, int *yoffset_si, int *roffset_si, int *boffset_si); int *xoffset_si, int *yoffset_si, int *roffset_si, int *boffset_si);
INTERNAL int output_process_upcean(const struct zint_symbol *symbol, int *p_main_width, int *p_comp_xoffset, INTERNAL int out_process_upcean(const struct zint_symbol *symbol, int *p_main_width, int *p_comp_xoffset,
unsigned char addon[6], int *p_addon_gap); unsigned char addon[6], int *p_addon_gap);
INTERNAL float output_large_bar_height(struct zint_symbol *symbol, int si); INTERNAL float out_large_bar_height(struct zint_symbol *symbol, int si);
INTERNAL void output_upcean_split_text(int upceanflag, unsigned char text[], INTERNAL void out_upcean_split_text(int upceanflag, unsigned char text[],
unsigned char textpart1[5], unsigned char textpart2[7], unsigned char textpart3[7], unsigned char textpart1[5], unsigned char textpart2[7], unsigned char textpart3[7],
unsigned char textpart4[2]); unsigned char textpart4[2]);

View File

@ -34,50 +34,51 @@
#include <stdio.h> #include <stdio.h>
#include "common.h" #include "common.h"
#define SSET "0123456789ABCDEF" #define SSET_F (IS_NUM_F | IS_UHX_F) /* SSET "0123456789ABCDEF" */
static const char *PlessTable[16] = { static const char PlessTable[16][8] = {
"13131313", "31131313", "13311313", "31311313", {'1','3','1','3','1','3','1','3'}, {'3','1','1','3','1','3','1','3'}, {'1','3','3','1','1','3','1','3'},
"13133113", "31133113", "13313113", "31313113", {'3','1','3','1','1','3','1','3'}, {'1','3','1','3','3','1','1','3'}, {'3','1','1','3','3','1','1','3'},
"13131331", "31131331", "13311331", "31311331", {'1','3','3','1','3','1','1','3'}, {'3','1','3','1','3','1','1','3'}, {'1','3','1','3','1','3','3','1'},
"13133131", "31133131", "13313131", "31313131" {'3','1','1','3','1','3','3','1'}, {'1','3','3','1','1','3','3','1'}, {'3','1','3','1','1','3','3','1'},
{'1','3','1','3','3','1','3','1'}, {'3','1','1','3','3','1','3','1'}, {'1','3','3','1','3','1','3','1'},
{'3','1','3','1','3','1','3','1'}
}; };
static const char *MSITable[10] = { static const char MSITable[10][8] = {
"12121212", "12121221", "12122112", "12122121", "12211212", {'1','2','1','2','1','2','1','2'}, {'1','2','1','2','1','2','2','1'}, {'1','2','1','2','2','1','1','2'},
"12211221", "12212112", "12212121", "21121212", "21121221" {'1','2','1','2','2','1','2','1'}, {'1','2','2','1','1','2','1','2'}, {'1','2','2','1','1','2','2','1'},
{'1','2','2','1','2','1','1','2'}, {'1','2','2','1','2','1','2','1'}, {'2','1','1','2','1','2','1','2'},
{'2','1','1','2','1','2','2','1'}
}; };
/* Not MSI/Plessey but the older Plessey standard */ /* Not MSI/Plessey but the older Plessey standard */
INTERNAL int plessey(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int plessey(struct zint_symbol *symbol, unsigned char source[], int length) {
int i; int i;
unsigned char *checkptr; unsigned char checkptr[65 * 4 + 8] = {0};
static const char grid[9] = {1, 1, 1, 1, 0, 1, 0, 0, 1}; static const char grid[9] = {1, 1, 1, 1, 0, 1, 0, 0, 1};
char dest[554]; /* 8 + 65 * 8 + 8 * 2 + 9 + 1 = 554 */ char dest[554]; /* 8 + 65 * 8 + 8 * 2 + 9 + 1 = 554 */
char *d = dest;
int error_number = 0; int error_number = 0;
if (length > 65) { if (length > 65) {
strcpy(symbol->errtxt, "370: Input too long (65 character maximum)"); strcpy(symbol->errtxt, "370: Input too long (65 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(SSET, source, length) != 0) { if (!is_sane(SSET_F, source, length)) {
strcpy(symbol->errtxt, "371: Invalid character in data (digits and \"ABCDEF\" only)"); strcpy(symbol->errtxt, "371: Invalid character in data (digits and \"ABCDEF\" only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
if (!(checkptr = (unsigned char *) calloc(1, length * 4 + 8))) {
strcpy(symbol->errtxt, "373: Insufficient memory for check digit CRC buffer");
return ZINT_ERROR_MEMORY;
}
/* Start character */ /* Start character */
strcpy(dest, "31311331"); memcpy(d, "31311331", 8);
d += 8;
/* Data area */ /* Data area */
for (i = 0; i < length; i++) { for (i = 0; i < length; i++, d += 8) {
unsigned int check = posn(SSET, source[i]); unsigned int check = source[i] - '0' - (source[i] >> 6) * 7;
lookup(SSET, PlessTable, source[i], dest); memcpy(d, PlessTable[check], 8);
checkptr[4 * i] = check & 1; checkptr[4 * i] = check & 1;
checkptr[4 * i + 1] = (check >> 1) & 1; checkptr[4 * i + 1] = (check >> 1) & 1;
checkptr[4 * i + 2] = (check >> 2) & 1; checkptr[4 * i + 2] = (check >> 2) & 1;
@ -97,24 +98,26 @@ INTERNAL int plessey(struct zint_symbol *symbol, unsigned char source[], int len
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
switch (checkptr[length * 4 + i]) { switch (checkptr[length * 4 + i]) {
case 0: strcat(dest, "13"); case 0: memcpy(d, "13", 2);
d += 2;
break; break;
case 1: strcat(dest, "31"); case 1: memcpy(d, "31", 2);
d += 2;
break; break;
} }
} }
/* Stop character */ /* Stop character */
strcat(dest, "331311313"); memcpy(d, "331311313", 9);
d += 9;
expand(symbol, dest); expand(symbol, dest, d - dest);
// TODO: Find documentation on BARCODE_PLESSEY dimensions/height // TODO: Find documentation on BARCODE_PLESSEY dimensions/height
symbol->text[0] = '\0'; symbol->text[0] = '\0';
ustrncat(symbol->text, source, length); ustrncat(symbol->text, source, length);
free(checkptr);
return error_number; return error_number;
} }
@ -154,35 +157,38 @@ static char msi_check_digit_mod11(const unsigned char source[], const int length
} }
/* Plain MSI Plessey - does not calculate any check character */ /* Plain MSI Plessey - does not calculate any check character */
static void msi_plessey_nomod(struct zint_symbol *symbol, const unsigned char source[], const int length, static char *msi_plessey_nomod(struct zint_symbol *symbol, const unsigned char source[], const int length,
char dest[]) { char *d) {
int i; int i;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++, d += 8) {
lookup(NEON, MSITable, source[i], dest); memcpy(d, MSITable[source[i] - '0'], 8);
} }
symbol->text[0] = '\0'; symbol->text[0] = '\0';
ustrncat(symbol->text, source, length); ustrncat(symbol->text, source, length);
return d;
} }
/* MSI Plessey with Modulo 10 check digit */ /* MSI Plessey with Modulo 10 check digit */
static void msi_plessey_mod10(struct zint_symbol *symbol, const unsigned char source[], const int length, static char *msi_plessey_mod10(struct zint_symbol *symbol, const unsigned char source[], const int length,
const int no_checktext, char dest[]) { const int no_checktext, char *d) {
int i; int i;
char check_digit; char check_digit;
/* draw data section */ /* draw data section */
for (i = 0; i < length; i++) { for (i = 0; i < length; i++, d += 8) {
lookup(NEON, MSITable, source[i], dest); memcpy(d, MSITable[source[i] - '0'], 8);
} }
/* calculate check digit */ /* calculate check digit */
check_digit = msi_check_digit_mod10(source, length); check_digit = msi_check_digit_mod10(source, length);
/* draw check digit */ /* draw check digit */
lookup(NEON, MSITable, check_digit, dest); memcpy(d, MSITable[check_digit - '0'], 8);
d += 8;
symbol->text[0] = '\0'; symbol->text[0] = '\0';
ustrncat(symbol->text, source, length); ustrncat(symbol->text, source, length);
@ -190,11 +196,13 @@ static void msi_plessey_mod10(struct zint_symbol *symbol, const unsigned char so
symbol->text[length] = check_digit; symbol->text[length] = check_digit;
symbol->text[length + 1] = '\0'; symbol->text[length + 1] = '\0';
} }
return d;
} }
/* MSI Plessey with two Modulo 10 check digits */ /* MSI Plessey with two Modulo 10 check digits */
static void msi_plessey_mod1010(struct zint_symbol *symbol, const unsigned char source[], const int length, static char *msi_plessey_mod1010(struct zint_symbol *symbol, const unsigned char source[], const int length,
const int no_checktext, char dest[]) { const int no_checktext, char *d) {
int i; int i;
unsigned char temp[65 + 2 + 1]; unsigned char temp[65 + 2 + 1];
@ -207,8 +215,8 @@ static void msi_plessey_mod1010(struct zint_symbol *symbol, const unsigned char
temp[length + 2] = '\0'; temp[length + 2] = '\0';
/* draw data section */ /* draw data section */
for (i = 0; i < length + 2; i++) { for (i = 0; i < length + 2; i++, d += 8) {
lookup(NEON, MSITable, temp[i], dest); memcpy(d, MSITable[temp[i] - '0'], 8);
} }
if (no_checktext) { if (no_checktext) {
@ -217,27 +225,32 @@ static void msi_plessey_mod1010(struct zint_symbol *symbol, const unsigned char
} else { } else {
ustrcpy(symbol->text, temp); ustrcpy(symbol->text, temp);
} }
return d;
} }
/* MSI Plessey with Modulo 11 check digit */ /* MSI Plessey with Modulo 11 check digit */
static void msi_plessey_mod11(struct zint_symbol *symbol, const unsigned char source[], const int length, static char *msi_plessey_mod11(struct zint_symbol *symbol, const unsigned char source[], const int length,
const int no_checktext, const int wrap, char dest[]) { const int no_checktext, const int wrap, char *d) {
/* Uses the IBM weight system if wrap = 7, and the NCR system if wrap = 9 */ /* Uses the IBM weight system if wrap = 7, and the NCR system if wrap = 9 */
int i; int i;
char check_digit; char check_digit;
/* draw data section */ /* draw data section */
for (i = 0; i < length; i++) { for (i = 0; i < length; i++, d += 8) {
lookup(NEON, MSITable, source[i], dest); memcpy(d, MSITable[source[i] - '0'], 8);
} }
/* Append check digit */ /* Append check digit */
check_digit = msi_check_digit_mod11(source, length, wrap); check_digit = msi_check_digit_mod11(source, length, wrap);
if (check_digit == 'A') { if (check_digit == 'A') {
lookup(NEON, MSITable, '1', dest); memcpy(d, MSITable[1], 8);
lookup(NEON, MSITable, '0', dest); d += 8;
memcpy(d, MSITable[0], 8);
d += 8;
} else { } else {
lookup(NEON, MSITable, check_digit, dest); memcpy(d, MSITable[check_digit - '0'], 8);
d += 8;
} }
symbol->text[0] = '\0'; symbol->text[0] = '\0';
@ -250,11 +263,13 @@ static void msi_plessey_mod11(struct zint_symbol *symbol, const unsigned char so
symbol->text[length + 1] = '\0'; symbol->text[length + 1] = '\0';
} }
} }
return d;
} }
/* MSI Plessey with Modulo 11 check digit and Modulo 10 check digit */ /* MSI Plessey with Modulo 11 check digit and Modulo 10 check digit */
static void msi_plessey_mod1110(struct zint_symbol *symbol, const unsigned char source[], const int length, static char *msi_plessey_mod1110(struct zint_symbol *symbol, const unsigned char source[], const int length,
const int no_checktext, const int wrap, char dest[]) { const int no_checktext, const int wrap, char *d) {
/* Uses the IBM weight system if wrap = 7, and the NCR system if wrap = 9 */ /* Uses the IBM weight system if wrap = 7, and the NCR system if wrap = 9 */
int i; int i;
char check_digit; char check_digit;
@ -278,8 +293,8 @@ static void msi_plessey_mod1110(struct zint_symbol *symbol, const unsigned char
temp[++temp_len] = '\0'; temp[++temp_len] = '\0';
/* draw data section */ /* draw data section */
for (i = 0; i < temp_len; i++) { for (i = 0; i < temp_len; i++, d += 8) {
lookup(NEON, MSITable, temp[i], dest); memcpy(d, MSITable[temp[i] - '0'], 8);
} }
if (no_checktext) { if (no_checktext) {
@ -288,11 +303,14 @@ static void msi_plessey_mod1110(struct zint_symbol *symbol, const unsigned char
} else { } else {
ustrcpy(symbol->text, temp); ustrcpy(symbol->text, temp);
} }
return d;
} }
INTERNAL int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int length) {
int error_number = 0; int error_number = 0;
char dest[550]; /* 2 + 65 * 8 + 3 * 8 + 3 + 1 = 550 */ char dest[550]; /* 2 + 65 * 8 + 3 * 8 + 3 + 1 = 550 */
char *d = dest;
int check_option = symbol->option_2; int check_option = symbol->option_2;
int no_checktext = 0; int no_checktext = 0;
@ -300,7 +318,7 @@ INTERNAL int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int
strcpy(symbol->errtxt, "372: Input too long (65 character maximum)"); strcpy(symbol->errtxt, "372: Input too long (65 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "377: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "377: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -314,29 +332,31 @@ INTERNAL int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int
} }
/* Start character */ /* Start character */
strcpy(dest, "21"); memcpy(d, "21", 2);
d += 2;
switch (check_option) { switch (check_option) {
case 0: msi_plessey_nomod(symbol, source, length, dest); case 0: d = msi_plessey_nomod(symbol, source, length, d);
break; break;
case 1: msi_plessey_mod10(symbol, source, length, no_checktext, dest); case 1: d = msi_plessey_mod10(symbol, source, length, no_checktext, d);
break; break;
case 2: msi_plessey_mod1010(symbol, source, length, no_checktext, dest); case 2: d = msi_plessey_mod1010(symbol, source, length, no_checktext, d);
break; break;
case 3: msi_plessey_mod11(symbol, source, length, no_checktext, 7 /*IBM wrap*/, dest); case 3: d = msi_plessey_mod11(symbol, source, length, no_checktext, 7 /*IBM wrap*/, d);
break; break;
case 4: msi_plessey_mod1110(symbol, source, length, no_checktext, 7 /*IBM wrap*/, dest); case 4: d = msi_plessey_mod1110(symbol, source, length, no_checktext, 7 /*IBM wrap*/, d);
break; break;
case 5: msi_plessey_mod11(symbol, source, length, no_checktext, 9 /*NCR wrap*/, dest); case 5: d = msi_plessey_mod11(symbol, source, length, no_checktext, 9 /*NCR wrap*/, d);
break; break;
case 6: msi_plessey_mod1110(symbol, source, length, no_checktext, 9 /*NCR wrap*/, dest); case 6: d = msi_plessey_mod1110(symbol, source, length, no_checktext, 9 /*NCR wrap*/, d);
break; break;
} }
/* Stop character */ /* Stop character */
strcat(dest, "121"); memcpy(d, "121", 3);
d += 3;
expand(symbol, dest); expand(symbol, dest, d - dest);
// TODO: Find documentation on BARCODE_MSI_PLESSEY dimensions/height // TODO: Find documentation on BARCODE_MSI_PLESSEY dimensions/height

View File

@ -46,8 +46,6 @@
#include <zlib.h> #include <zlib.h>
#include <setjmp.h> #include <setjmp.h>
#define SSET "0123456789ABCDEF"
/* Note if change this need to change "backend/tests/test_png.c" definition also */ /* Note if change this need to change "backend/tests/test_png.c" definition also */
struct wpng_error_type { struct wpng_error_type {
struct zint_symbol *symbol; struct zint_symbol *symbol;
@ -300,26 +298,34 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
pb = pixelbuf; pb = pixelbuf;
if (bit_depth == 1) { if (bit_depth == 1) {
for (row = 0; row < symbol->bitmap_height; row++) { for (row = 0; row < symbol->bitmap_height; row++) {
unsigned char *image_data = outdata; if (row && memcmp(pb, pb - symbol->bitmap_width, symbol->bitmap_width) == 0) {
for (column = 0; column < symbol->bitmap_width; column += 8, image_data++) { pb += symbol->bitmap_width;
unsigned char byte = 0; } else {
for (i = 0; i < 8 && column + i < symbol->bitmap_width; i++, pb++) { unsigned char *image_data = outdata;
byte |= map[*pb] << (7 - i); for (column = 0; column < symbol->bitmap_width; column += 8, image_data++) {
unsigned char byte = 0;
for (i = 0; i < 8 && column + i < symbol->bitmap_width; i++, pb++) {
byte |= map[*pb] << (7 - i);
}
*image_data = byte;
} }
*image_data = byte;
} }
/* write row contents to file */ /* write row contents to file */
png_write_row(png_ptr, outdata); png_write_row(png_ptr, outdata);
} }
} else { /* Bit depth 4 */ } else { /* Bit depth 4 */
for (row = 0; row < symbol->bitmap_height; row++) { for (row = 0; row < symbol->bitmap_height; row++) {
unsigned char *image_data = outdata; if (row && memcmp(pb, pb - symbol->bitmap_width, symbol->bitmap_width) == 0) {
for (column = 0; column < symbol->bitmap_width; column += 2, image_data++) { pb += symbol->bitmap_width;
unsigned char byte = map[*pb++] << 4; } else {
if (column + 1 < symbol->bitmap_width) { unsigned char *image_data = outdata;
byte |= map[*pb++]; for (column = 0; column < symbol->bitmap_width; column += 2, image_data++) {
unsigned char byte = map[*pb++] << 4;
if (column + 1 < symbol->bitmap_width) {
byte |= map[*pb++];
}
*image_data = byte;
} }
*image_data = byte;
} }
/* write row contents to file */ /* write row contents to file */
png_write_row(png_ptr, outdata); png_write_row(png_ptr, outdata);

View File

@ -38,49 +38,58 @@
#endif #endif
#include "common.h" #include "common.h"
#define DAFTSET "DAFT" static const char DAFTSET[] = "FADT";
#define KRSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" static const char KRSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
#define KASUTSET "1234567890-abcdefgh" static const char KASUTSET[] = "1234567890-abcdefgh";
#define CHKASUTSET "0123456789-abcdefgh" static const char CHKASUTSET[] = "0123456789-abcdefgh";
#define SHKASUTSET "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ" #define SHKASUTSET_F (IS_NUM_F | IS_MNS_F | IS_UPR_F) /* SHKASUTSET "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ" */
/* PostNet number encoding table - In this table L is long as S is short */ /* PostNet number encoding table - In this table L is long as S is short */
static const char *PNTable[10] = { static const char PNTable[10][5] = {
"LLSSS", "SSSLL", "SSLSL", "SSLLS", "SLSSL", "SLSLS", "SLLSS", "LSSSL", {'L','L','S','S','S'}, {'S','S','S','L','L'}, {'S','S','L','S','L'}, {'S','S','L','L','S'}, {'S','L','S','S','L'},
"LSSLS", "LSLSS" {'S','L','S','L','S'}, {'S','L','L','S','S'}, {'L','S','S','S','L'}, {'L','S','S','L','S'}, {'L','S','L','S','S'}
}; };
static const char *PLTable[10] = { static const char PLTable[10][5] = {
"SSLLL", "LLLSS", "LLSLS", "LLSSL", "LSLLS", "LSLSL", "LSSLL", "SLLLS", {'S','S','L','L','L'}, {'L','L','L','S','S'}, {'L','L','S','L','S'}, {'L','L','S','S','L'}, {'L','S','L','L','S'},
"SLLSL", "SLSLL" {'L','S','L','S','L'}, {'L','S','S','L','L'}, {'S','L','L','L','S'}, {'S','L','L','S','L'}, {'S','L','S','L','L'}
}; };
static const char *RoyalValues[36] = { static const char RoyalValues[36][2] = {
"11", "12", "13", "14", "15", "10", "21", "22", "23", "24", "25", { 1, 1 }, { 1, 2 }, { 1, 3 }, { 1, 4 }, { 1, 5 }, { 1, 0 }, { 2, 1 }, { 2, 2 }, { 2, 3 }, { 2, 4 },
"20", "31", "32", "33", "34", "35", "30", "41", "42", "43", "44", "45", "40", "51", "52", { 2, 5 }, { 2, 0 }, { 3, 1 }, { 3, 2 }, { 3, 3 }, { 3, 4 }, { 3, 5 }, { 3, 0 }, { 4, 1 }, { 4, 2 },
"53", "54", "55", "50", "01", "02", "03", "04", "05", "00" { 4, 3 }, { 4, 4 }, { 4, 5 }, { 4, 0 }, { 5, 1 }, { 5, 2 }, { 5, 3 }, { 5, 4 }, { 5, 5 }, { 5, 0 },
{ 0, 1 }, { 0, 2 }, { 0, 3 }, { 0, 4 }, { 0, 5 }, { 0, 0 }
}; };
/* 0 = Full, 1 = Ascender, 2 = Descender, 3 = Tracker */ /* 0 = Full, 1 = Ascender, 2 = Descender, 3 = Tracker */
static const char *RoyalTable[36] = { static const char RoyalTable[36][4] = {
"3300", "3210", "3201", "2310", "2301", "2211", "3120", "3030", "3021", {'3','3','0','0'}, {'3','2','1','0'}, {'3','2','0','1'}, {'2','3','1','0'}, {'2','3','0','1'}, {'2','2','1','1'},
"2130", "2121", "2031", "3102", "3012", "3003", "2112", "2103", "2013", "1320", "1230", {'3','1','2','0'}, {'3','0','3','0'}, {'3','0','2','1'}, {'2','1','3','0'}, {'2','1','2','1'}, {'2','0','3','1'},
"1221", "0330", "0321", "0231", "1302", "1212", "1203", "0312", "0303", "0213", "1122", {'3','1','0','2'}, {'3','0','1','2'}, {'3','0','0','3'}, {'2','1','1','2'}, {'2','1','0','3'}, {'2','0','1','3'},
"1032", "1023", "0132", "0123", "0033" {'1','3','2','0'}, {'1','2','3','0'}, {'1','2','2','1'}, {'0','3','3','0'}, {'0','3','2','1'}, {'0','2','3','1'},
{'1','3','0','2'}, {'1','2','1','2'}, {'1','2','0','3'}, {'0','3','1','2'}, {'0','3','0','3'}, {'0','2','1','3'},
{'1','1','2','2'}, {'1','0','3','2'}, {'1','0','2','3'}, {'0','1','3','2'}, {'0','1','2','3'}, {'0','0','3','3'}
}; };
static const char *FlatTable[10] = { static const char FlatTable[10][4] = {
"0504", "18", "0117", "0216", "0315", "0414", "0513", "0612", "0711", "0810" {'0','5','0','4'}, { "18" }, {'0','1','1','7'}, {'0','2','1','6'}, {'0','3','1','5'},
{'0','4','1','4'}, {'0','5','1','3'}, {'0','6','1','2'}, {'0','7','1','1'}, {'0','8','1','0'}
}; };
static const char *KoreaTable[10] = { static const char KoreaTable[10][10] = {
"1313150613", "0713131313", "0417131313", "1506131313", {'1','3','1','3','1','5','0','6','1','3'}, {'0','7','1','3','1','3','1','3','1','3'},
"0413171313", "17171313", "1315061313", "0413131713", "17131713", "13171713" {'0','4','1','7','1','3','1','3','1','3'}, {'1','5','0','6','1','3','1','3','1','3'},
{'0','4','1','3','1','7','1','3','1','3'}, { "17171313" },
{'1','3','1','5','0','6','1','3','1','3'}, {'0','4','1','3','1','3','1','7','1','3'},
{ "17131713" }, { "13171713" }
}; };
static const char *JapanTable[19] = { static const char JapanTable[19][3] = {
"114", "132", "312", "123", "141", "321", "213", "231", "411", "144", {'1','1','4'}, {'1','3','2'}, {'3','1','2'}, {'1','2','3'}, {'1','4','1'},
"414", "324", "342", "234", "432", "243", "423", "441", "111" {'3','2','1'}, {'2','1','3'}, {'2','3','1'}, {'4','1','1'}, {'1','4','4'},
{'4','1','4'}, {'3','2','4'}, {'3','4','2'}, {'2','3','4'}, {'4','3','2'},
{'2','4','3'}, {'4','2','3'}, {'4','4','1'}, {'1','1','1'}
}; };
/* Set height for POSTNET/PLANET codes, maintaining ratio */ /* Set height for POSTNET/PLANET codes, maintaining ratio */
@ -127,7 +136,7 @@ static int usps_set_height(struct zint_symbol *symbol, const int no_errtxt) {
} }
/* Handles the PostNet system used for Zip codes in the US */ /* Handles the PostNet system used for Zip codes in the US */
static int postnet_enc(struct zint_symbol *symbol, unsigned char source[], char dest[], int length) { static int postnet_enc(struct zint_symbol *symbol, const unsigned char source[], char *d, const int length) {
int i, sum, check_digit; int i, sum, check_digit;
int error_number = 0; int error_number = 0;
@ -139,25 +148,27 @@ static int postnet_enc(struct zint_symbol *symbol, unsigned char source[], char
strcpy(symbol->errtxt, "479: Input length is not standard (5, 9 or 11 characters)"); strcpy(symbol->errtxt, "479: Input length is not standard (5, 9 or 11 characters)");
error_number = ZINT_WARN_NONCOMPLIANT; error_number = ZINT_WARN_NONCOMPLIANT;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "481: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "481: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
sum = 0; sum = 0;
/* start character */ /* start character */
strcpy(dest, "L"); *d++ = 'L';
for (i = 0; i < length; i++) { for (i = 0; i < length; i++, d += 5) {
lookup(NEON, PNTable, source[i], dest); const int val = source[i] - '0';
sum += ctoi(source[i]); memcpy(d, PNTable[val], 5);
sum += val;
} }
check_digit = (10 - (sum % 10)) % 10; check_digit = (10 - (sum % 10)) % 10;
strcat(dest, PNTable[check_digit]); memcpy(d, PNTable[check_digit], 5);
d += 5;
/* stop character */ /* stop character */
strcat(dest, "L"); strcpy(d, "L");
return error_number; return error_number;
} }
@ -191,7 +202,7 @@ INTERNAL int postnet(struct zint_symbol *symbol, unsigned char source[], int len
} }
/* Handles the PLANET system used for item tracking in the US */ /* Handles the PLANET system used for item tracking in the US */
static int planet_enc(struct zint_symbol *symbol, unsigned char source[], char dest[], int length) { static int planet_enc(struct zint_symbol *symbol, const unsigned char source[], char *d, const int length) {
int i, sum, check_digit; int i, sum, check_digit;
int error_number = 0; int error_number = 0;
@ -203,25 +214,27 @@ static int planet_enc(struct zint_symbol *symbol, unsigned char source[], char d
strcpy(symbol->errtxt, "478: Input length is not standard (11 or 13 characters)"); strcpy(symbol->errtxt, "478: Input length is not standard (11 or 13 characters)");
error_number = ZINT_WARN_NONCOMPLIANT; error_number = ZINT_WARN_NONCOMPLIANT;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "483: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "483: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
sum = 0; sum = 0;
/* start character */ /* start character */
strcpy(dest, "L"); *d++ = 'L';
for (i = 0; i < length; i++) { for (i = 0; i < length; i++, d += 5) {
lookup(NEON, PLTable, source[i], dest); const int val = source[i] - '0';
sum += ctoi(source[i]); memcpy(d, PLTable[val], 5);
sum += val;
} }
check_digit = (10 - (sum % 10)) % 10; check_digit = (10 - (sum % 10)) % 10;
strcat(dest, PLTable[check_digit]); memcpy(d, PLTable[check_digit], 5);
d += 5;
/* stop character */ /* stop character */
strcat(dest, "L"); strcpy(d, "L");
return error_number; return error_number;
} }
@ -258,12 +271,14 @@ INTERNAL int planet(struct zint_symbol *symbol, unsigned char source[], int leng
INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int length) {
int total, loop, check, zeroes, error_number = 0; int total, loop, check, zeroes, error_number = 0;
char localstr[8], dest[80]; char localstr[8], dest[80];
char *d = dest;
int posns[6];
if (length > 6) { if (length > 6) {
strcpy(symbol->errtxt, "484: Input too long (6 character maximum)"); strcpy(symbol->errtxt, "484: Input too long (6 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "485: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "485: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -273,7 +288,8 @@ INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int l
total = 0; total = 0;
for (loop = 0; loop < 6; loop++) { for (loop = 0; loop < 6; loop++) {
total += ctoi(localstr[loop]); posns[loop] = ctoi(localstr[loop]);
total += posns[loop];
} }
check = 10 - (total % 10); check = 10 - (total % 10);
if (check == 10) { if (check == 10) {
@ -281,12 +297,17 @@ INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int l
} }
localstr[6] = itoc(check); localstr[6] = itoc(check);
localstr[7] = '\0'; localstr[7] = '\0';
*dest = '\0';
for (loop = 5; loop >= 0; loop--) { for (loop = 5; loop >= 0; loop--) {
lookup(NEON, KoreaTable, localstr[loop], dest); const char *const entry = KoreaTable[posns[loop]];
memcpy(d, entry, 10);
d += entry[8] ? 10 : 8;
} }
lookup(NEON, KoreaTable, localstr[6], dest); memcpy(d, KoreaTable[check], 10);
expand(symbol, dest); d += KoreaTable[check][8] ? 10 : 8;
expand(symbol, dest, d - dest);
ustrcpy(symbol->text, localstr); ustrcpy(symbol->text, localstr);
// TODO: Find documentation on BARCODE_KOREAPOST dimensions/height // TODO: Find documentation on BARCODE_KOREAPOST dimensions/height
@ -298,7 +319,6 @@ INTERNAL int koreapost(struct zint_symbol *symbol, unsigned char source[], int l
glyphs from http://en.wikipedia.org/wiki/Facing_Identification_Mark */ glyphs from http://en.wikipedia.org/wiki/Facing_Identification_Mark */
INTERNAL int fim(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int fim(struct zint_symbol *symbol, unsigned char source[], int length) {
int error_number = 0; int error_number = 0;
char dest[16] = {0};
if (length > 1) { if (length > 1) {
strcpy(symbol->errtxt, "486: Input too long (1 character maximum)"); strcpy(symbol->errtxt, "486: Input too long (1 character maximum)");
@ -308,19 +328,19 @@ INTERNAL int fim(struct zint_symbol *symbol, unsigned char source[], int length)
switch ((char) source[0]) { switch ((char) source[0]) {
case 'a': case 'a':
case 'A': case 'A':
strcpy(dest, "111515111"); expand(symbol, "111515111", 9);
break; break;
case 'b': case 'b':
case 'B': case 'B':
strcpy(dest, "13111311131"); expand(symbol, "13111311131", 11);
break; break;
case 'c': case 'c':
case 'C': case 'C':
strcpy(dest, "11131313111"); expand(symbol, "11131313111", 11);
break; break;
case 'd': case 'd':
case 'D': case 'D':
strcpy(dest, "1111131311111"); expand(symbol, "1111131311111", 13);
break; break;
default: default:
strcpy(symbol->errtxt, "487: Invalid character in data (\"A\", \"B\", \"C\" or \"D\" only)"); strcpy(symbol->errtxt, "487: Invalid character in data (\"A\", \"B\", \"C\" or \"D\" only)");
@ -328,8 +348,6 @@ INTERNAL int fim(struct zint_symbol *symbol, unsigned char source[], int length)
break; break;
} }
expand(symbol, dest);
if (symbol->output_options & COMPLIANT_HEIGHT) { if (symbol->output_options & COMPLIANT_HEIGHT) {
/* USPS Domestic Mail Manual (USPS DMM 300) Jan 8, 2006 (updated 2011) 708.9.3 /* USPS Domestic Mail Manual (USPS DMM 300) Jan 8, 2006 (updated 2011) 708.9.3
X 0.03125" (1/32) +- 0.008" so X max 0.03925", height 0.625" (5/8) +- 0.125" (1/8) */ X 0.03125" (1/32) +- 0.008" so X max 0.03925", height 0.625" (5/8) +- 0.125" (1/8) */
@ -344,7 +362,7 @@ INTERNAL int fim(struct zint_symbol *symbol, unsigned char source[], int length)
/* Set height for DAFT-type codes, maintaining ratio. Expects row_height[0] & row_height[1] to be set */ /* Set height for DAFT-type codes, maintaining ratio. Expects row_height[0] & row_height[1] to be set */
/* Used by auspost.c also */ /* Used by auspost.c also */
INTERNAL int daft_set_height(struct zint_symbol *symbol, float min_height, float max_height) { INTERNAL int daft_set_height(struct zint_symbol *symbol, const float min_height, const float max_height) {
int error_number = 0; int error_number = 0;
float t_ratio; /* Tracker ratio */ float t_ratio; /* Tracker ratio */
@ -376,22 +394,21 @@ INTERNAL int daft_set_height(struct zint_symbol *symbol, float min_height, float
} }
/* Handles the 4 State barcodes used in the UK by Royal Mail */ /* Handles the 4 State barcodes used in the UK by Royal Mail */
static char rm4scc_enc(unsigned char source[], char dest[], int length) { static void rm4scc_enc(const int *posns, char *d, const int length) {
int i; int i;
int top, bottom, row, column, check_digit; int top, bottom, row, column, check_digit;
char values[3], set_copy[] = KRSET;
top = 0; top = 0;
bottom = 0; bottom = 0;
/* start character */ /* start character */
strcpy(dest, "1"); *d++ = '1';
for (i = 0; i < length; i++) { for (i = 0; i < length; i++, d += 4) {
lookup(KRSET, RoyalTable, source[i], dest); const int p = posns[i];
strcpy(values, RoyalValues[posn(KRSET, source[i])]); memcpy(d, RoyalTable[p], 4);
top += ctoi(values[0]); top += RoyalValues[p][0];
bottom += ctoi(values[1]); bottom += RoyalValues[p][1];
} }
/* Calculate the check digit */ /* Calculate the check digit */
@ -404,32 +421,31 @@ static char rm4scc_enc(unsigned char source[], char dest[], int length) {
column = 5; column = 5;
} }
check_digit = (6 * row) + column; check_digit = (6 * row) + column;
strcat(dest, RoyalTable[check_digit]); memcpy(d, RoyalTable[check_digit], 4);
d += 4;
/* stop character */ /* stop character */
strcat(dest, "0"); strcpy(d, "0");
return set_copy[check_digit];
} }
/* Puts RM4SCC into the data matrix */ /* Puts RM4SCC into the data matrix */
INTERNAL int rm4scc(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int rm4scc(struct zint_symbol *symbol, unsigned char source[], int length) {
char height_pattern[210]; char height_pattern[210];
int posns[50];
int loopey, h; int loopey, h;
int writer; int writer;
int error_number = 0; int error_number = 0;
strcpy(height_pattern, "");
if (length > 50) { if (length > 50) {
strcpy(symbol->errtxt, "488: Input too long (50 character maximum)"); strcpy(symbol->errtxt, "488: Input too long (50 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
to_upper(source); to_upper(source, length);
if (is_sane(KRSET, source, length) != 0) { if (!is_sane_lookup(KRSET, 36, source, length, posns)) {
strcpy(symbol->errtxt, "489: Invalid character in data (alphanumerics only)"); strcpy(symbol->errtxt, "489: Invalid character in data (alphanumerics only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
/*check = */rm4scc_enc(source, height_pattern, length); rm4scc_enc(posns, height_pattern, length);
writer = 0; writer = 0;
h = (int) strlen(height_pattern); h = (int) strlen(height_pattern);
@ -467,34 +483,33 @@ INTERNAL int rm4scc(struct zint_symbol *symbol, unsigned char source[], int leng
} }
/* Handles Dutch Post TNT KIX symbols /* Handles Dutch Post TNT KIX symbols
The same as RM4SCC but without check digit The same as RM4SCC but without check digit or stop/start chars
Specification at http://www.tntpost.nl/zakelijk/klantenservice/downloads/kIX_code/download.aspx */ Specification at http://www.tntpost.nl/zakelijk/klantenservice/downloads/kIX_code/download.aspx */
INTERNAL int kix(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int kix(struct zint_symbol *symbol, unsigned char source[], int length) {
char height_pattern[75], localstr[20]; char height_pattern[75];
char *d = height_pattern;
int posns[18];
int loopey; int loopey;
int writer, i, h; int writer, i, h;
int error_number = 0; int error_number = 0;
strcpy(height_pattern, "");
if (length > 18) { if (length > 18) {
strcpy(symbol->errtxt, "490: Input too long (18 character maximum)"); strcpy(symbol->errtxt, "490: Input too long (18 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
to_upper(source); to_upper(source, length);
if (is_sane(KRSET, source, length) != 0) { if (!is_sane_lookup(KRSET, 36, source, length, posns)) {
strcpy(symbol->errtxt, "491: Invalid character in data (alphanumerics only)"); strcpy(symbol->errtxt, "491: Invalid character in data (alphanumerics only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
ustrcpy(localstr, source);
/* Encode data */ /* Encode data */
for (i = 0; i < length; i++) { for (i = 0; i < length; i++, d += 4) {
lookup(KRSET, RoyalTable, localstr[i], height_pattern); memcpy(d, RoyalTable[posns[i]], 4);
} }
writer = 0; writer = 0;
h = (int) strlen(height_pattern); h = d - height_pattern;
for (loopey = 0; loopey < h; loopey++) { for (loopey = 0; loopey < h; loopey++) {
if ((height_pattern[loopey] == '1') || (height_pattern[loopey] == '0')) { if ((height_pattern[loopey] == '1') || (height_pattern[loopey] == '0')) {
set_module(symbol, 0, writer); set_module(symbol, 0, writer);
@ -525,45 +540,28 @@ INTERNAL int kix(struct zint_symbol *symbol, unsigned char source[], int length)
/* Handles DAFT Code symbols */ /* Handles DAFT Code symbols */
INTERNAL int daft(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int daft(struct zint_symbol *symbol, unsigned char source[], int length) {
char height_pattern[100]; int posns[100];
unsigned int loopey, h; int loopey;
int writer, i; int writer;
strcpy(height_pattern, "");
if (length > 50) { if (length > 100) {
strcpy(symbol->errtxt, "492: Input too long (50 character maximum)"); strcpy(symbol->errtxt, "492: Input too long (100 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
to_upper(source); to_upper(source, length);
if (is_sane(DAFTSET, source, length) != 0) { if (!is_sane_lookup(DAFTSET, 4, source, length, posns)) {
strcpy(symbol->errtxt, "493: Invalid character in data (\"D\", \"A\", \"F\" and \"T\" only)"); strcpy(symbol->errtxt, "493: Invalid character in data (\"D\", \"A\", \"F\" and \"T\" only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
for (i = 0; i < length; i++) {
if (source[i] == 'D') {
strcat(height_pattern, "2");
}
if (source[i] == 'A') {
strcat(height_pattern, "1");
}
if (source[i] == 'F') {
strcat(height_pattern, "0");
}
if (source[i] == 'T') {
strcat(height_pattern, "3");
}
}
writer = 0; writer = 0;
h = (int) strlen(height_pattern); for (loopey = 0; loopey < length; loopey++) {
for (loopey = 0; loopey < h; loopey++) { if ((posns[loopey] == 1) || (posns[loopey] == 0)) {
if ((height_pattern[loopey] == '1') || (height_pattern[loopey] == '0')) {
set_module(symbol, 0, writer); set_module(symbol, 0, writer);
} }
set_module(symbol, 1, writer); set_module(symbol, 1, writer);
if ((height_pattern[loopey] == '2') || (height_pattern[loopey] == '0')) { if ((posns[loopey] == 2) || (posns[loopey] == 0)) {
set_module(symbol, 2, writer); set_module(symbol, 2, writer);
} }
writer += 2; writer += 2;
@ -594,21 +592,24 @@ INTERNAL int daft(struct zint_symbol *symbol, unsigned char source[], int length
INTERNAL int flat(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int flat(struct zint_symbol *symbol, unsigned char source[], int length) {
int loop, error_number = 0; int loop, error_number = 0;
char dest[512]; /* 90 * 4 + 1 ~ */ char dest[512]; /* 90 * 4 + 1 ~ */
char *d = dest;
if (length > 90) { if (length > 90) {
strcpy(symbol->errtxt, "494: Input too long (90 character maximum)"); strcpy(symbol->errtxt, "494: Input too long (90 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, length) != 0) { if (!is_sane(NEON_F, source, length)) {
strcpy(symbol->errtxt, "495: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "495: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
*dest = '\0';
for (loop = 0; loop < length; loop++) { for (loop = 0; loop < length; loop++) {
lookup(NEON, FlatTable, source[loop], dest); const char *const entry = FlatTable[source[loop] - '0'];
memcpy(d, entry, 4);
d += entry[2] ? 4 : 2;
} }
expand(symbol, dest); expand(symbol, dest, d - dest);
// TODO: Find documentation on BARCODE_FLAT dimensions/height // TODO: Find documentation on BARCODE_FLAT dimensions/height
@ -619,25 +620,19 @@ INTERNAL int flat(struct zint_symbol *symbol, unsigned char source[], int length
INTERNAL int japanpost(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int japanpost(struct zint_symbol *symbol, unsigned char source[], int length) {
int error_number = 0, h; int error_number = 0, h;
char pattern[69]; char pattern[69];
char *d = pattern;
int writer, loopey, inter_posn, i, sum, check; int writer, loopey, inter_posn, i, sum, check;
char check_char; char check_char;
char inter[23]; char inter[20 + 1];
#ifndef _MSC_VER
unsigned char local_source[length + 1];
#else
unsigned char *local_source = (unsigned char *) _alloca(length + 1);
#endif
if (length > 20) { if (length > 20) {
strcpy(symbol->errtxt, "496: Input too long (20 character maximum)"); strcpy(symbol->errtxt, "496: Input too long (20 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
ustrcpy(local_source, source); to_upper(source, length);
to_upper(local_source);
if (is_sane(SHKASUTSET, local_source, length) != 0) { if (!is_sane(SHKASUTSET_F, source, length)) {
strcpy(symbol->errtxt, "497: Invalid character in data (alphanumerics and \"-\" only)"); strcpy(symbol->errtxt, "497: Invalid character in data (alphanumerics and \"-\" only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -647,35 +642,36 @@ INTERNAL int japanpost(struct zint_symbol *symbol, unsigned char source[], int l
i = 0; i = 0;
inter_posn = 0; inter_posn = 0;
do { do {
if (((local_source[i] >= '0') && (local_source[i] <= '9')) || (local_source[i] == '-')) { if (((source[i] >= '0') && (source[i] <= '9')) || (source[i] == '-')) {
inter[inter_posn] = local_source[i]; inter[inter_posn] = source[i];
inter_posn++; inter_posn++;
} else { } else {
if ((local_source[i] >= 'A') && (local_source[i] <= 'J')) { if (source[i] <= 'J') {
inter[inter_posn] = 'a'; inter[inter_posn] = 'a';
inter[inter_posn + 1] = local_source[i] - 'A' + '0'; inter[inter_posn + 1] = source[i] - 'A' + '0';
inter_posn += 2; } else if (source[i] <= 'T') {
}
if ((local_source[i] >= 'K') && (local_source[i] <= 'T')) {
inter[inter_posn] = 'b'; inter[inter_posn] = 'b';
inter[inter_posn + 1] = local_source[i] - 'K' + '0'; inter[inter_posn + 1] = source[i] - 'K' + '0';
inter_posn += 2; } else { /* (source[i] >= 'U') && (source[i] <= 'Z') */
}
if ((local_source[i] >= 'U') && (local_source[i] <= 'Z')) {
inter[inter_posn] = 'c'; inter[inter_posn] = 'c';
inter[inter_posn + 1] = local_source[i] - 'U' + '0'; inter[inter_posn + 1] = source[i] - 'U' + '0';
inter_posn += 2;
} }
inter_posn += 2;
} }
i++; i++;
} while ((i < length) && (inter_posn < 20)); } while ((i < length) && (inter_posn < 20));
inter[20] = '\0';
strcpy(pattern, "13"); /* Start */ if (i != length || inter[20] != '\0') {
strcpy(symbol->errtxt, "477: Input too long (20 symbol character maximum)");
return ZINT_ERROR_TOO_LONG;
}
memcpy(d, "13", 2); /* Start */
d += 2;
sum = 0; sum = 0;
for (i = 0; i < 20; i++) { for (i = 0; i < 20; i++, d += 3) {
strcat(pattern, JapanTable[posn(KASUTSET, inter[i])]); memcpy(d, JapanTable[posn(KASUTSET, inter[i])], 3);
sum += posn(CHKASUTSET, inter[i]); sum += posn(CHKASUTSET, inter[i]);
} }
@ -691,15 +687,17 @@ INTERNAL int japanpost(struct zint_symbol *symbol, unsigned char source[], int l
} else { } else {
check_char = (check - 11) + 'a'; check_char = (check - 11) + 'a';
} }
strcat(pattern, JapanTable[posn(KASUTSET, check_char)]); memcpy(d, JapanTable[posn(KASUTSET, check_char)], 3);
d += 3;
if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check: %d, char: %c\n", check, check_char); if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check: %d, char: %c\n", check, check_char);
strcat(pattern, "31"); /* Stop */ memcpy(d, "31", 2); /* Stop */
d += 2;
/* Resolve pattern to 4-state symbols */ /* Resolve pattern to 4-state symbols */
writer = 0; writer = 0;
h = (int) strlen(pattern); h = d - pattern;
for (loopey = 0; loopey < h; loopey++) { for (loopey = 0; loopey < h; loopey++) {
if ((pattern[loopey] == '2') || (pattern[loopey] == '1')) { if ((pattern[loopey] == '2') || (pattern[loopey] == '1')) {
set_module(symbol, 0, writer); set_module(symbol, 0, writer);

View File

@ -305,7 +305,7 @@ static void qr_define_mode(char mode[], const unsigned int jisdata[], const int
/* Get optimal mode for each code point by tracing backwards */ /* Get optimal mode for each code point by tracing backwards */
for (i = length - 1, cm_i = i * QR_NUM_MODES; i >= 0; i--, cm_i -= QR_NUM_MODES) { for (i = length - 1, cm_i = i * QR_NUM_MODES; i >= 0; i--, cm_i -= QR_NUM_MODES) {
j = strchr(mode_types, cur_mode) - mode_types; j = posn(mode_types, cur_mode);
cur_mode = char_modes[cm_i + j]; cur_mode = char_modes[cm_i + j];
mode[i] = cur_mode; mode[i] = cur_mode;
} }
@ -327,7 +327,7 @@ static int mode_indicator(const int version, const int mode) {
{ 0, 1, 2, 3, }, { 0, 1, 2, 3, },
}; };
int mode_index = strchr(mode_types, mode) - mode_types; int mode_index = posn(mode_types, (const char) mode);
if (version < RMQR_VERSION) { if (version < RMQR_VERSION) {
return mode_indicators[0][mode_index]; /* QRCODE */ return mode_indicators[0][mode_index]; /* QRCODE */
@ -364,7 +364,7 @@ static int cci_bits(const int version, const int mode) {
static const unsigned short int *rmqr_ccis[QR_NUM_MODES] = { static const unsigned short int *rmqr_ccis[QR_NUM_MODES] = {
rmqr_numeric_cci, rmqr_alphanum_cci, rmqr_byte_cci, rmqr_kanji_cci, rmqr_numeric_cci, rmqr_alphanum_cci, rmqr_byte_cci, rmqr_kanji_cci,
}; };
int mode_index = strchr(mode_types, mode) - mode_types; int mode_index = posn(mode_types, (const char) mode);
if (version < RMQR_VERSION) { /* QRCODE */ if (version < RMQR_VERSION) { /* QRCODE */
if (version < 10) { if (version < 10) {
@ -393,7 +393,7 @@ static int terminator_bits(const int version) {
} }
/* Convert input data to a binary stream and add padding */ /* Convert input data to a binary stream and add padding */
static void qr_binary(unsigned char datastream[], const int version, const int target_codewords, const char mode[], static int qr_binary(unsigned char datastream[], const int version, const int target_codewords, const char mode[],
const unsigned int jisdata[], const int length, const struct zint_structapp *p_structapp, const int gs1, const unsigned int jisdata[], const int length, const struct zint_structapp *p_structapp, const int gs1,
const int eci, const int est_binlen, const int debug_print) { const int eci, const int est_binlen, const int debug_print) {
int position = 0; int position = 0;
@ -406,8 +406,9 @@ static void qr_binary(unsigned char datastream[], const int version, const int t
#ifndef _MSC_VER #ifndef _MSC_VER
char binary[est_binlen + 12]; char binary[est_binlen + 12];
#else #else
char *binary = (char *) _alloca(est_binlen + 12); char *binary= (char *) _alloca(est_binlen + 12);
#endif #endif
*binary = '\0'; *binary = '\0';
bp = 0; bp = 0;
@ -641,17 +642,17 @@ static void qr_binary(unsigned char datastream[], const int version, const int t
int count; int count;
int first = 0, prod; int first = 0, prod;
first = posn(NEON, (char) jisdata[position + i]); first = ctoi((const char) jisdata[position + i]);
count = 1; count = 1;
prod = first; prod = first;
if (i + 1 < short_data_block_length && mode[position + i + 1] == 'N') { if (i + 1 < short_data_block_length && mode[position + i + 1] == 'N') {
int second = posn(NEON, (char) jisdata[position + i + 1]); int second = ctoi((const char) jisdata[position + i + 1]);
count = 2; count = 2;
prod = (prod * 10) + second; prod = (prod * 10) + second;
if (i + 2 < short_data_block_length && mode[position + i + 2] == 'N') { if (i + 2 < short_data_block_length && mode[position + i + 2] == 'N') {
int third = posn(NEON, (char) jisdata[position + i + 2]); int third = ctoi((const char) jisdata[position + i + 2]);
count = 3; count = 3;
prod = (prod * 10) + third; prod = (prod * 10) + third;
} }
@ -678,9 +679,8 @@ static void qr_binary(unsigned char datastream[], const int version, const int t
if (version >= MICROQR_VERSION && version < MICROQR_VERSION + 4) { if (version >= MICROQR_VERSION && version < MICROQR_VERSION + 4) {
/* MICROQR does its own terminating/padding */ /* MICROQR does its own terminating/padding */
binary[bp] = '\0'; memcpy(datastream, binary, bp);
ustrcpy(datastream, binary); return bp;
return;
} }
/* Terminator */ /* Terminator */
@ -738,6 +738,8 @@ static void qr_binary(unsigned char datastream[], const int version, const int t
} }
printf("\n"); printf("\n");
} }
return 0; /* Not used */
} }
/* Split data into blocks, add error correction and then interleave the blocks and error correction data */ /* Split data into blocks, add error correction and then interleave the blocks and error correction data */
@ -769,7 +771,7 @@ static void add_ecc(unsigned char fullstream[], const unsigned char datastream[]
ecc_block_length = ecc_cw / blocks; ecc_block_length = ecc_cw / blocks;
/* Suppress some clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult/uninitialized.Assign warnings */ /* Suppress some clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult/uninitialized.Assign warnings */
assert(short_data_block_length >= 0); assert(short_data_block_length > 0);
assert(ecc_block_length * blocks == ecc_cw); assert(ecc_block_length * blocks == ecc_cw);
#ifndef _MSC_VER #ifndef _MSC_VER
@ -842,7 +844,6 @@ static void add_ecc(unsigned char fullstream[], const unsigned char datastream[]
fullstream[j] = interleaved_data[j]; fullstream[j] = interleaved_data[j];
} }
for (j = 0; j < ecc_cw; j++) { for (j = 0; j < ecc_cw; j++) {
// NOLINTNEXTLINE suppress clang-tidy warning: interleaved_ecc[ecc_cw] fully set
fullstream[j + data_cw] = interleaved_ecc[j]; fullstream[j + data_cw] = interleaved_ecc[j];
} }
@ -1788,8 +1789,8 @@ INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int leng
fullstream = (unsigned char *) _alloca(qr_total_codewords[version - 1] + 1); fullstream = (unsigned char *) _alloca(qr_total_codewords[version - 1] + 1);
#endif #endif
qr_binary(datastream, version, target_codewords, mode, jisdata, length, p_structapp, gs1, symbol->eci, (void) qr_binary(datastream, version, target_codewords, mode, jisdata, length, p_structapp, gs1, symbol->eci,
est_binlen, debug_print); est_binlen, debug_print);
#ifdef ZINT_TEST #ifdef ZINT_TEST
if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords);
#endif #endif
@ -1833,7 +1834,7 @@ INTERNAL int qrcode(struct zint_symbol *symbol, unsigned char source[], int leng
return 0; return 0;
} }
static void micro_qr_m1(struct zint_symbol *symbol, char binary_data[]) { static int micro_qr_m1(struct zint_symbol *symbol, char binary_data[], int bp) {
int i, j, latch; int i, j, latch;
int bits_total, bits_left; int bits_total, bits_left;
int data_codewords, ecc_codewords; int data_codewords, ecc_codewords;
@ -1844,26 +1845,26 @@ static void micro_qr_m1(struct zint_symbol *symbol, char binary_data[]) {
latch = 0; latch = 0;
/* Add terminator */ /* Add terminator */
bits_left = bits_total - (int) strlen(binary_data); bits_left = bits_total - bp;
if (bits_left <= 3) { if (bits_left <= 3) {
for (i = 0; i < bits_left; i++) { if (bits_left) {
strcat(binary_data, "0"); bp = bin_append_posn(0, bits_left, binary_data, bp);
} }
latch = 1; latch = 1;
} else { } else {
strcat(binary_data, "000"); bp = bin_append_posn(0, 3, binary_data, bp);
} }
if (symbol->debug & ZINT_DEBUG_PRINT) { if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("M1 Terminated binary (%d): %s (bits_left %d)\n", (int) strlen(binary_data), binary_data, bits_left); printf("M1 Terminated binary (%d): %s (bits_left %d)\n", bp, binary_data, bits_left);
} }
if (latch == 0) { if (latch == 0) {
/* Manage last (4-bit) block */ /* Manage last (4-bit) block */
bits_left = bits_total - (int) strlen(binary_data); bits_left = bits_total - bp;
if (bits_left <= 4) { if (bits_left <= 4) {
for (i = 0; i < bits_left; i++) { if (bits_left) {
strcat(binary_data, "0"); bp = bin_append_posn(0, bits_left, binary_data, bp);
} }
latch = 1; latch = 1;
} }
@ -1871,23 +1872,20 @@ static void micro_qr_m1(struct zint_symbol *symbol, char binary_data[]) {
if (latch == 0) { if (latch == 0) {
/* Complete current byte */ /* Complete current byte */
int remainder = 8 - (strlen(binary_data) % 8); int remainder = 8 - (bp % 8);
if (remainder == 8) { if (remainder != 8) {
remainder = 0; bp = bin_append_posn(0, remainder, binary_data, bp);
}
for (i = 0; i < remainder; i++) {
strcat(binary_data, "0");
} }
/* Add padding */ /* Add padding */
bits_left = bits_total - (int) strlen(binary_data); bits_left = bits_total - bp;
if (bits_left > 4) { if (bits_left > 4) {
remainder = (bits_left - 4) / 8; remainder = (bits_left - 4) / 8;
for (i = 0; i < remainder; i++) { for (i = 0; i < remainder; i++) {
strcat(binary_data, (i & 1) ? "00010001" : "11101100"); bp = bin_append_posn(i & 1 ? 0x11 : 0xEC, 8, binary_data, bp);
} }
} }
bin_append(0, 4, binary_data); bp = bin_append_posn(0, 4, binary_data, bp);
} }
data_codewords = 3; data_codewords = 3;
@ -1919,14 +1917,16 @@ static void micro_qr_m1(struct zint_symbol *symbol, char binary_data[]) {
/* Add Reed-Solomon codewords to binary data */ /* Add Reed-Solomon codewords to binary data */
for (i = 0; i < ecc_codewords; i++) { for (i = 0; i < ecc_codewords; i++) {
bin_append(ecc_blocks[ecc_codewords - i - 1], 8, binary_data); bp = bin_append_posn(ecc_blocks[ecc_codewords - i - 1], 8, binary_data, bp);
} }
return bp;
} }
static void micro_qr_m2(struct zint_symbol *symbol, char binary_data[], const int ecc_mode) { static int micro_qr_m2(struct zint_symbol *symbol, char binary_data[], int bp, const int ecc_mode) {
int i, j, latch; int i, j, latch;
int bits_total=0, bits_left; int bits_total = 0, bits_left;
int data_codewords=0, ecc_codewords=0; int data_codewords = 0, ecc_codewords = 0;
unsigned char data_blocks[6], ecc_blocks[7]; unsigned char data_blocks[6], ecc_blocks[7];
rs_t rs; rs_t rs;
@ -1941,35 +1941,32 @@ static void micro_qr_m2(struct zint_symbol *symbol, char binary_data[], const in
else assert(0); else assert(0);
/* Add terminator */ /* Add terminator */
bits_left = bits_total - (int) strlen(binary_data); bits_left = bits_total - bp;
if (bits_left <= 5) { if (bits_left <= 5) {
for (i = 0; i < bits_left; i++) { if (bits_left) {
strcat(binary_data, "0"); bp = bin_append_posn(0, bits_left, binary_data, bp);
} }
latch = 1; latch = 1;
} else { } else {
bin_append(0, 5, binary_data); bp = bin_append_posn(0, 5, binary_data, bp);
} }
if (symbol->debug & ZINT_DEBUG_PRINT) { if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("M2 Terminated binary (%d): %s (bits_left %d)\n", (int) strlen(binary_data), binary_data, bits_left); printf("M2 Terminated binary (%d): %s (bits_left %d)\n", bp, binary_data, bits_left);
} }
if (latch == 0) { if (latch == 0) {
/* Complete current byte */ /* Complete current byte */
int remainder = 8 - (strlen(binary_data) % 8); int remainder = 8 - (bp % 8);
if (remainder == 8) { if (remainder != 8) {
remainder = 0; bp = bin_append_posn(0, remainder, binary_data, bp);
}
for (i = 0; i < remainder; i++) {
strcat(binary_data, "0");
} }
/* Add padding */ /* Add padding */
bits_left = bits_total - (int) strlen(binary_data); bits_left = bits_total - bp;
remainder = bits_left / 8; remainder = bits_left / 8;
for (i = 0; i < remainder; i++) { for (i = 0; i < remainder; i++) {
strcat(binary_data, (i & 1) ? "00010001" : "11101100"); bp = bin_append_posn(i & 1 ? 0x11 : 0xEC, 8, binary_data, bp);
} }
} }
@ -2004,16 +2001,16 @@ static void micro_qr_m2(struct zint_symbol *symbol, char binary_data[], const in
/* Add Reed-Solomon codewords to binary data */ /* Add Reed-Solomon codewords to binary data */
for (i = 0; i < ecc_codewords; i++) { for (i = 0; i < ecc_codewords; i++) {
bin_append(ecc_blocks[ecc_codewords - i - 1], 8, binary_data); bp = bin_append_posn(ecc_blocks[ecc_codewords - i - 1], 8, binary_data, bp);
} }
return; return bp;
} }
static void micro_qr_m3(struct zint_symbol *symbol, char binary_data[], const int ecc_mode) { static int micro_qr_m3(struct zint_symbol *symbol, char binary_data[], int bp, const int ecc_mode) {
int i, j, latch; int i, j, latch;
int bits_total=0, bits_left; int bits_total = 0, bits_left;
int data_codewords=0, ecc_codewords=0; int data_codewords = 0, ecc_codewords = 0;
unsigned char data_blocks[12], ecc_blocks[9]; unsigned char data_blocks[12], ecc_blocks[9];
rs_t rs; rs_t rs;
@ -2028,26 +2025,26 @@ static void micro_qr_m3(struct zint_symbol *symbol, char binary_data[], const in
else assert(0); else assert(0);
/* Add terminator */ /* Add terminator */
bits_left = bits_total - (int) strlen(binary_data); bits_left = bits_total - bp;
if (bits_left <= 7) { if (bits_left <= 7) {
for (i = 0; i < bits_left; i++) { if (bits_left) {
strcat(binary_data, "0"); bp = bin_append_posn(0, bits_left, binary_data, bp);
} }
latch = 1; latch = 1;
} else { } else {
bin_append(0, 7, binary_data); bp = bin_append_posn(0, 7, binary_data, bp);
} }
if (symbol->debug & ZINT_DEBUG_PRINT) { if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("M3 Terminated binary (%d): %s (bits_left %d)\n", (int) strlen(binary_data), binary_data, bits_left); printf("M3 Terminated binary (%d): %s (bits_left %d)\n", bp, binary_data, bits_left);
} }
if (latch == 0) { if (latch == 0) {
/* Manage last (4-bit) block */ /* Manage last (4-bit) block */
bits_left = bits_total - (int) strlen(binary_data); bits_left = bits_total - bp;
if (bits_left <= 4) { if (bits_left <= 4) {
for (i = 0; i < bits_left; i++) { if (bits_left) {
strcat(binary_data, "0"); bp = bin_append_posn(0, bits_left, binary_data, bp);
} }
latch = 1; latch = 1;
} }
@ -2055,23 +2052,20 @@ static void micro_qr_m3(struct zint_symbol *symbol, char binary_data[], const in
if (latch == 0) { if (latch == 0) {
/* Complete current byte */ /* Complete current byte */
int remainder = 8 - (strlen(binary_data) % 8); int remainder = 8 - (bp % 8);
if (remainder == 8) { if (remainder != 8) {
remainder = 0; bp = bin_append_posn(0, remainder, binary_data, bp);
}
for (i = 0; i < remainder; i++) {
strcat(binary_data, "0");
} }
/* Add padding */ /* Add padding */
bits_left = bits_total - (int) strlen(binary_data); bits_left = bits_total - bp;
if (bits_left > 4) { if (bits_left > 4) {
remainder = (bits_left - 4) / 8; remainder = (bits_left - 4) / 8;
for (i = 0; i < remainder; i++) { for (i = 0; i < remainder; i++) {
strcat(binary_data, (i & 1) ? "00010001" : "11101100"); bp = bin_append_posn(i & 1 ? 0x11 : 0xEC, 8, binary_data, bp);
} }
} }
bin_append(0, 4, binary_data); bp = bin_append_posn(0, 4, binary_data, bp);
} }
if (ecc_mode == LEVEL_L) { if (ecc_mode == LEVEL_L) {
@ -2123,16 +2117,16 @@ static void micro_qr_m3(struct zint_symbol *symbol, char binary_data[], const in
/* Add Reed-Solomon codewords to binary data */ /* Add Reed-Solomon codewords to binary data */
for (i = 0; i < ecc_codewords; i++) { for (i = 0; i < ecc_codewords; i++) {
bin_append(ecc_blocks[ecc_codewords - i - 1], 8, binary_data); bp = bin_append_posn(ecc_blocks[ecc_codewords - i - 1], 8, binary_data, bp);
} }
return; return bp;
} }
static void micro_qr_m4(struct zint_symbol *symbol, char binary_data[], const int ecc_mode) { static int micro_qr_m4(struct zint_symbol *symbol, char binary_data[], int bp, const int ecc_mode) {
int i, j, latch; int i, j, latch;
int bits_total=0, bits_left; int bits_total = 0, bits_left;
int data_codewords=0, ecc_codewords=0; int data_codewords = 0, ecc_codewords = 0;
unsigned char data_blocks[17], ecc_blocks[15]; unsigned char data_blocks[17], ecc_blocks[15];
rs_t rs; rs_t rs;
@ -2150,14 +2144,14 @@ static void micro_qr_m4(struct zint_symbol *symbol, char binary_data[], const in
else assert(0); else assert(0);
/* Add terminator */ /* Add terminator */
bits_left = bits_total - (int) strlen(binary_data); bits_left = bits_total - bp;
if (bits_left <= 9) { if (bits_left <= 9) {
for (i = 0; i < bits_left; i++) { if (bits_left) {
strcat(binary_data, "0"); bp = bin_append_posn(0, bits_left, binary_data, bp);
} }
latch = 1; latch = 1;
} else { } else {
bin_append(0, 9, binary_data); bp = bin_append_posn(0, 9, binary_data, bp);
} }
if (symbol->debug & ZINT_DEBUG_PRINT) { if (symbol->debug & ZINT_DEBUG_PRINT) {
@ -2166,19 +2160,16 @@ static void micro_qr_m4(struct zint_symbol *symbol, char binary_data[], const in
if (latch == 0) { if (latch == 0) {
/* Complete current byte */ /* Complete current byte */
int remainder = 8 - (strlen(binary_data) % 8); int remainder = 8 - (bp % 8);
if (remainder == 8) { if (remainder != 8) {
remainder = 0; bp = bin_append_posn(0, remainder, binary_data, bp);
}
for (i = 0; i < remainder; i++) {
strcat(binary_data, "0");
} }
/* Add padding */ /* Add padding */
bits_left = bits_total - (int) strlen(binary_data); bits_left = bits_total - bp;
remainder = bits_left / 8; remainder = bits_left / 8;
for (i = 0; i < remainder; i++) { for (i = 0; i < remainder; i++) {
strcat(binary_data, (i & 1) ? "00010001" : "11101100"); bp = bin_append_posn(i & 1 ? 0x11 : 0xEC, 8, binary_data, bp);
} }
} }
@ -2217,8 +2208,10 @@ static void micro_qr_m4(struct zint_symbol *symbol, char binary_data[], const in
/* Add Reed-Solomon codewords to binary data */ /* Add Reed-Solomon codewords to binary data */
for (i = 0; i < ecc_codewords; i++) { for (i = 0; i < ecc_codewords; i++) {
bin_append(ecc_blocks[ecc_codewords - i - 1], 8, binary_data); bp = bin_append_posn(ecc_blocks[ecc_codewords - i - 1], 8, binary_data, bp);
} }
return bp;
} }
static void micro_setup_grid(unsigned char *grid, const int size) { static void micro_setup_grid(unsigned char *grid, const int size) {
@ -2256,13 +2249,12 @@ static void micro_setup_grid(unsigned char *grid, const int size) {
grid[(8 * size) + 8] |= 20; grid[(8 * size) + 8] |= 20;
} }
static void micro_populate_grid(unsigned char *grid, const int size, const char full_stream[]) { static void micro_populate_grid(unsigned char *grid, const int size, const char full_stream[], int bp) {
int direction = 1; /* up */ int direction = 1; /* up */
int row = 0; /* right hand side */ int row = 0; /* right hand side */
int n, i; int i;
int y; int y;
n = (int) strlen(full_stream);
y = size - 1; y = size - 1;
i = 0; i = 0;
do { do {
@ -2277,7 +2269,7 @@ static void micro_populate_grid(unsigned char *grid, const int size, const char
i++; i++;
} }
if (i < n) { if (i < bp) {
if (!(grid[(y * size) + x] & 0xf0)) { if (!(grid[(y * size) + x] & 0xf0)) {
if (full_stream[i] == '1') { if (full_stream[i] == '1') {
grid[(y * size) + x] = 0x01; grid[(y * size) + x] = 0x01;
@ -2305,7 +2297,7 @@ static void micro_populate_grid(unsigned char *grid, const int size, const char
y = size - 1; y = size - 1;
direction = 1; direction = 1;
} }
} while (i < n); } while (i < bp);
} }
static int micro_evaluate(const unsigned char *grid, const int size, const int pattern) { static int micro_evaluate(const unsigned char *grid, const int size, const int pattern) {
@ -2432,6 +2424,7 @@ static int micro_apply_bitmask(unsigned char *grid, const int size, const int us
INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int length) { INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int length) {
int i, size, j; int i, size, j;
char full_stream[200]; char full_stream[200];
int bp;
int full_multibyte; int full_multibyte;
int user_mask; int user_mask;
@ -2614,19 +2607,19 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len
qr_define_mode(mode, jisdata, length, 0 /*gs1*/, MICROQR_VERSION + version, debug_print); qr_define_mode(mode, jisdata, length, 0 /*gs1*/, MICROQR_VERSION + version, debug_print);
qr_binary((unsigned char *) full_stream, MICROQR_VERSION + version, 0 /*target_codewords*/, mode, jisdata, length, bp = qr_binary((unsigned char *) full_stream, MICROQR_VERSION + version, 0 /*target_codewords*/, mode, jisdata,
NULL /*p_structapp*/, 0 /*gs1*/, 0 /*eci*/, binary_count[version], debug_print); length, NULL /*p_structapp*/, 0 /*gs1*/, 0 /*eci*/, binary_count[version], debug_print);
if (debug_print) printf("Binary (%d): %s\n", (int) strlen(full_stream), full_stream); if (debug_print) printf("Binary (%d): %s\n", bp, full_stream);
switch (version) { switch (version) {
case 0: micro_qr_m1(symbol, full_stream); case 0: bp = micro_qr_m1(symbol, full_stream, bp);
break; break;
case 1: micro_qr_m2(symbol, full_stream, ecc_level); case 1: bp = micro_qr_m2(symbol, full_stream, bp, ecc_level);
break; break;
case 2: micro_qr_m3(symbol, full_stream, ecc_level); case 2: bp = micro_qr_m3(symbol, full_stream, bp, ecc_level);
break; break;
case 3: micro_qr_m4(symbol, full_stream, ecc_level); case 3: bp = micro_qr_m4(symbol, full_stream, bp, ecc_level);
break; break;
} }
@ -2641,7 +2634,7 @@ INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int len
memset(grid, 0, size_squared); memset(grid, 0, size_squared);
micro_setup_grid(grid, size); micro_setup_grid(grid, size);
micro_populate_grid(grid, size, full_stream); micro_populate_grid(grid, size, full_stream, bp);
bitmask = micro_apply_bitmask(grid, size, user_mask, debug_print); bitmask = micro_apply_bitmask(grid, size, user_mask, debug_print);
/* Add format data */ /* Add format data */
@ -2814,8 +2807,8 @@ INTERNAL int upnqr(struct zint_symbol *symbol, unsigned char source[], int lengt
fullstream = (unsigned char *) _alloca(qr_total_codewords[version - 1] + 1); fullstream = (unsigned char *) _alloca(qr_total_codewords[version - 1] + 1);
#endif #endif
qr_binary(datastream, version, target_codewords, mode, jisdata, length, NULL /*p_structapp*/, 0 /*gs1*/, (void) qr_binary(datastream, version, target_codewords, mode, jisdata, length, NULL /*p_structapp*/, 0 /*gs1*/,
symbol->eci, est_binlen, debug_print); symbol->eci, est_binlen, debug_print);
#ifdef ZINT_TEST #ifdef ZINT_TEST
if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords);
#endif #endif
@ -3145,8 +3138,8 @@ INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length
fullstream = (unsigned char *) _alloca(rmqr_total_codewords[version] + 1); fullstream = (unsigned char *) _alloca(rmqr_total_codewords[version] + 1);
#endif #endif
qr_binary(datastream, RMQR_VERSION + version, target_codewords, mode, jisdata, length, NULL /*p_structapp*/, gs1, (void) qr_binary(datastream, RMQR_VERSION + version, target_codewords, mode, jisdata, length,
symbol->eci, est_binlen, debug_print); NULL /*p_structapp*/, gs1, symbol->eci, est_binlen, debug_print);
#ifdef ZINT_TEST #ifdef ZINT_TEST
if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords);
#endif #endif

View File

@ -77,7 +77,7 @@ static int buffer_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf
}; };
int row; int row;
int plot_alpha = 0; int plot_alpha = 0;
unsigned char *bitmap; const size_t bm_bitmap_width = (size_t) symbol->bitmap_width * 3;
map[DEFAULT_INK][0] = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]); map[DEFAULT_INK][0] = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
map[DEFAULT_INK][1] = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]); map[DEFAULT_INK][1] = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]);
@ -110,7 +110,7 @@ static int buffer_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf
symbol->alphamap = NULL; symbol->alphamap = NULL;
} }
symbol->bitmap = (unsigned char *) malloc((size_t) symbol->bitmap_width * symbol->bitmap_height * 3); symbol->bitmap = (unsigned char *) malloc(bm_bitmap_width * symbol->bitmap_height);
if (symbol->bitmap == NULL) { if (symbol->bitmap == NULL) {
strcpy(symbol->errtxt, "661: Insufficient memory for bitmap buffer"); strcpy(symbol->errtxt, "661: Insufficient memory for bitmap buffer");
return ZINT_ERROR_MEMORY; return ZINT_ERROR_MEMORY;
@ -124,21 +124,31 @@ static int buffer_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf
} }
for (row = 0; row < symbol->bitmap_height; row++) { for (row = 0; row < symbol->bitmap_height; row++) {
int p = row * symbol->bitmap_width; int p = row * symbol->bitmap_width;
const int pe = p + symbol->bitmap_width; const unsigned char *pb = pixelbuf + p;
bitmap = symbol->bitmap + p * 3; unsigned char *bitmap = symbol->bitmap + p * 3;
for (; p < pe; p++, bitmap += 3) { if (row && memcmp(pb, pb - symbol->bitmap_width, symbol->bitmap_width) == 0) {
memcpy(bitmap, map[pixelbuf[p]], 3); memcpy(bitmap, bitmap - bm_bitmap_width, bm_bitmap_width);
symbol->alphamap[p] = pixelbuf[p] == DEFAULT_PAPER ? bgalpha : fgalpha; memcpy(symbol->alphamap + p, symbol->alphamap + p - symbol->bitmap_width, symbol->bitmap_width);
} else {
const int pe = p + symbol->bitmap_width;
for (; p < pe; p++, bitmap += 3) {
memcpy(bitmap, map[pixelbuf[p]], 3);
symbol->alphamap[p] = pixelbuf[p] == DEFAULT_PAPER ? bgalpha : fgalpha;
}
} }
} }
} else { } else {
for (row = 0; row < symbol->bitmap_height; row++) { for (row = 0; row < symbol->bitmap_height; row++) {
const int r = row * symbol->bitmap_width; const int r = row * symbol->bitmap_width;
const unsigned char *pb = pixelbuf + r; const unsigned char *pb = pixelbuf + r;
const unsigned char *const pe = pb + symbol->bitmap_width; unsigned char *bitmap = symbol->bitmap + r * 3;
bitmap = symbol->bitmap + r * 3; if (row && memcmp(pb, pb - symbol->bitmap_width, symbol->bitmap_width) == 0) {
for (; pb < pe; pb++, bitmap += 3) { memcpy(bitmap, bitmap - bm_bitmap_width, bm_bitmap_width);
memcpy(bitmap, map[*pb], 3); } else {
const unsigned char *const pbe = pb + symbol->bitmap_width;
for (; pb < pbe; pb++, bitmap += 3) {
memcpy(bitmap, map[*pb], 3);
}
} }
} }
} }
@ -262,15 +272,39 @@ static void draw_pt(unsigned char *buf, const int buf_width, const int buf_heigh
} }
} }
/* Draw the first line of a bar, to be completed by `copy_bar_line()`; more performant than multiple `draw_bar()`s */
static void draw_bar_line(unsigned char *pixelbuf, const int xpos, const int xlen, const int ypos,
const int image_width, const char fill) {
unsigned char *pb = pixelbuf + ((size_t) image_width * ypos) + xpos;
memset(pb, fill, xlen);
}
/* Fill out a bar code row by copying the first line (called after multiple `draw_bar_line()`s) */
static void copy_bar_line(unsigned char *pixelbuf, const int xpos, const int xlen, const int ypos, const int ylen,
const int image_width, const int image_height) {
int y;
const int ye = ypos + ylen > image_height ? image_height : ypos + ylen; /* Defensive, should never happen */
unsigned char *pb = pixelbuf + ((size_t) image_width * ypos) + xpos;
assert(ypos + ylen <= image_height); // Trigger assert if "should never happen" happens
for (y = ypos + 1; y < ye; y++) {
memcpy(pixelbuf + ((size_t) image_width * y) + xpos, pb, xlen);
}
}
/* Draw a rectangle */ /* Draw a rectangle */
static void draw_bar(unsigned char *pixelbuf, const int xpos, const int xlen, const int ypos, const int ylen, static void draw_bar(unsigned char *pixelbuf, const int xpos, const int xlen, const int ypos, const int ylen,
const int image_width, const int image_height, const char fill) { const int image_width, const int image_height, const char fill) {
int y; int y;
const int ye = ypos + ylen > image_height ? image_height : ypos + ylen; /* Defensive, should never happen */ const int ye = ypos + ylen > image_height ? image_height : ypos + ylen; /* Defensive, should never happen */
assert(ypos + ylen <= image_height); // Trigger assert if happens unsigned char *pb = pixelbuf + ((size_t) image_width * ypos) + xpos;
for (y = ypos; y < ye; y++) { assert(ypos + ylen <= image_height); // Trigger assert if "should never happen" happens
memset(pixelbuf + ((size_t) image_width * y) + xpos, fill, xlen);
for (y = ypos; y < ye; y++, pb += image_width) {
memset(pb, fill, xlen);
} }
} }
@ -682,7 +716,7 @@ static int plot_raster_maxicode(struct zint_symbol *symbol, const int rotate_ang
} }
scaler *= 10.0f; scaler *= 10.0f;
output_set_whitespace_offsets(symbol, 0 /*hide_text*/, &xoffset, &yoffset, &roffset, &boffset, scaler, out_set_whitespace_offsets(symbol, 0 /*hide_text*/, &xoffset, &yoffset, &roffset, &boffset, scaler,
&xoffset_si, &yoffset_si, &roffset_si, &boffset_si); &xoffset_si, &yoffset_si, &roffset_si, &boffset_si);
hex_width = (int) roundf(scaler); /* Short diameter, X in ISO/IEC 16023:2000 Figure 8 (same as W) */ hex_width = (int) roundf(scaler); /* Short diameter, X in ISO/IEC 16023:2000 Figure 8 (same as W) */
@ -779,7 +813,7 @@ static int plot_raster_dotty(struct zint_symbol *symbol, const int rotate_angle,
dot_radius_s = (symbol->dot_size * scaler) / 2.0f; dot_radius_s = (symbol->dot_size * scaler) / 2.0f;
dot_radius_si = (int) dot_radius_s; dot_radius_si = (int) dot_radius_s;
output_set_whitespace_offsets(symbol, 0 /*hide_text*/, &xoffset, &yoffset, &roffset, &boffset, scaler, out_set_whitespace_offsets(symbol, 0 /*hide_text*/, &xoffset, &yoffset, &roffset, &boffset, scaler,
&xoffset_si, &yoffset_si, &roffset_si, &boffset_si); &xoffset_si, &yoffset_si, &roffset_si, &boffset_si);
/* TODO: Revisit this overspill stuff, it's hacky */ /* TODO: Revisit this overspill stuff, it's hacky */
@ -884,6 +918,7 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
unsigned char textpart1[5], textpart2[7], textpart3[7], textpart4[2]; unsigned char textpart1[5], textpart2[7], textpart3[7], textpart4[2];
int hide_text; int hide_text;
int i, r; int i, r;
int block_width = 0;
int text_height; /* Font pixel size (so whole integers) */ int text_height; /* Font pixel size (so whole integers) */
float text_gap; /* Gap between barcode and text */ float text_gap; /* Gap between barcode and text */
float guard_descent; float guard_descent;
@ -910,20 +945,22 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
si = 2; si = 2;
} }
large_bar_height = output_large_bar_height(symbol, si /*Round to scale*/); large_bar_height = out_large_bar_height(symbol, si /*Round to scale*/);
symbol_height_si = (int) ceilf(symbol->height * si); symbol_height_si = (int) ceilf(symbol->height * si);
main_width = symbol->width; main_width = symbol->width;
if (is_extendable(symbol->symbology)) { if (is_extendable(symbol->symbology)) {
upceanflag = output_process_upcean(symbol, &main_width, &comp_xoffset, addon, &addon_gap); upceanflag = out_process_upcean(symbol, &main_width, &comp_xoffset, addon, &addon_gap);
} }
hide_text = ((!symbol->show_hrt) || (ustrlen(symbol->text) == 0) || scaler < 1.0f); hide_text = ((!symbol->show_hrt) || (ustrlen(symbol->text) == 0) || scaler < 1.0f);
output_set_whitespace_offsets(symbol, hide_text, &xoffset, &yoffset, &roffset, &boffset, si, out_set_whitespace_offsets(symbol, hide_text, &xoffset, &yoffset, &roffset, &boffset, si,
&xoffset_si, &yoffset_si, &roffset_si, &boffset_si); &xoffset_si, &yoffset_si, &roffset_si, &boffset_si);
comp_xoffset_si = xoffset_si + comp_xoffset * si;
/* Note font sizes halved as in pixels */ /* Note font sizes halved as in pixels */
if (upceanflag) { if (upceanflag) {
textflags = UPCEAN_TEXT | (symbol->output_options & SMALL_TEXT); /* Bold not available for UPC/EAN */ textflags = UPCEAN_TEXT | (symbol->output_options & SMALL_TEXT); /* Bold not available for UPC/EAN */
@ -960,40 +997,41 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
yposn = yoffset; yposn = yoffset;
/* Plot the body of the symbol to the pixel buffer */ /* Plot the body of the symbol to the pixel buffer */
for (r = 0; r < symbol->rows; r++) { if (symbol->symbology == BARCODE_ULTRA) {
int yposn_si = yposn * si; for (r = 0; r < symbol->rows; r++) {
float row_height = symbol->row_height[r] ? symbol->row_height[r] : large_bar_height; int yposn_si = yposn * si;
int row_height_si = (int) ceilf(row_height * si); float row_height = symbol->row_height[r];
int row_height_si = (int) ceilf(row_height * si);
i = 0; for (i = 0; i < symbol->width; i += block_width) {
int fill = module_colour_is_set(symbol, r, i);
if (symbol->symbology == BARCODE_ULTRA) { for (block_width = 1; (i + block_width < symbol->width)
do { && module_colour_is_set(symbol, r, i + block_width) == fill; block_width++);
int module_fill = module_colour_is_set(symbol, r, i); if (fill) {
int block_width = 0;
do {
block_width++;
} while ((i + block_width < symbol->width)
&& module_colour_is_set(symbol, r, i + block_width) == module_fill);
if (module_fill) {
/* a colour block */ /* a colour block */
draw_bar(pixelbuf, i * si + xoffset_si, block_width * si, yposn_si, row_height_si, draw_bar_line(pixelbuf, i * si + xoffset_si, block_width * si, yposn_si, image_width,
image_width, image_height, ultra_colour[module_fill]); ultra_colour[fill]);
} }
i += block_width; }
copy_bar_line(pixelbuf, xoffset_si, image_width - xoffset_si - roffset_si, yposn_si, row_height_si,
image_width, image_height);
yposn += row_height;
}
} while (i < symbol->width); } else if (upceanflag >= 6) { /* UPC-E, EAN-8, UPC-A, EAN-13 */
} else { for (r = 0; r < symbol->rows; r++) {
do { int yposn_si = yposn * si;
float addon_row_height; float row_height = symbol->row_height[r] ? symbol->row_height[r] : large_bar_height;
int module_fill = module_is_set(symbol, r, i); int row_height_si = (int) ceilf(row_height * si);
int block_width = 0;
do {
block_width++;
} while ((i + block_width < symbol->width)
&& module_is_set(symbol, r, i + block_width) == module_fill);
if (upceanflag && (addon_latch == 0) && (r == (symbol->rows - 1)) && (i > main_width)) { for (i = 0; i < symbol->width; i += block_width) {
int fill = module_is_set(symbol, r, i);
for (block_width = 1; (i + block_width < symbol->width)
&& module_is_set(symbol, r, i + block_width) == fill; block_width++);
if ((r == (symbol->rows - 1)) && (i > main_width) && (addon_latch == 0)) {
float addon_row_height;
copy_bar_line(pixelbuf, xoffset_si, main_width * si, yposn_si, row_height_si, image_width,
image_height);
yposn_si += (text_height + text_gap) * si; yposn_si += (text_height + text_gap) * si;
addon_text_yposn = yposn * si; addon_text_yposn = yposn * si;
addon_row_height = row_height - (text_height + text_gap); addon_row_height = row_height - (text_height + text_gap);
@ -1006,127 +1044,110 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
row_height_si = addon_row_height * si; row_height_si = addon_row_height * si;
addon_latch = 1; addon_latch = 1;
} }
if (module_fill) { if (fill) {
/* a bar */ /* a bar */
draw_bar(pixelbuf, i * si + xoffset_si, block_width * si, yposn_si, row_height_si, image_width, draw_bar_line(pixelbuf, i * si + xoffset_si, block_width * si, yposn_si, image_width,
image_height, DEFAULT_INK); DEFAULT_INK);
} }
i += block_width; }
if (addon_latch) {
} while (i < symbol->width); copy_bar_line(pixelbuf, xoffset_si + main_width * si,
image_width - main_width * si - xoffset_si - roffset_si, yposn_si, row_height_si,
image_width, image_height);
} else {
copy_bar_line(pixelbuf, xoffset_si, image_width - xoffset_si - roffset_si, yposn_si, row_height_si,
image_width, image_height);
}
yposn += row_height;
}
} else {
for (r = 0; r < symbol->rows; r++) {
int yposn_si = yposn * si;
float row_height = symbol->row_height[r] ? symbol->row_height[r] : large_bar_height;
int row_height_si = (int) ceilf(row_height * si);
for (i = 0; i < symbol->width; i += block_width) {
int fill = module_is_set(symbol, r, i);
for (block_width = 1; (i + block_width < symbol->width)
&& module_is_set(symbol, r, i + block_width) == fill; block_width++);
if (fill) {
/* a bar */
draw_bar_line(pixelbuf, i * si + xoffset_si, block_width * si, yposn_si, image_width,
DEFAULT_INK);
}
}
copy_bar_line(pixelbuf, xoffset_si, image_width - xoffset_si - roffset_si, yposn_si, row_height_si,
image_width, image_height);
yposn += row_height;
} }
yposn += row_height;
} }
comp_xoffset_si = xoffset_si + comp_xoffset * si; if (guard_descent && upceanflag >= 6) { /* UPC-E, EAN-8, UPC-A, EAN-13 */
if (upceanflag) {
/* Guard bar extension */ /* Guard bar extension */
int guard_yoffset_si = yoffset_si + symbol_height_si; int guard_yoffset_si = yoffset_si + symbol_height_si;
int guard_descent_si = guard_descent * si; int guard_descent_si = guard_descent * si;
if (upceanflag == 6) { /* UPC-E */ if (upceanflag == 6) { /* UPC-E */
draw_bar(pixelbuf, 0 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, draw_bar_line(pixelbuf, 0 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
image_width, image_height, DEFAULT_INK); draw_bar_line(pixelbuf, 2 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
draw_bar(pixelbuf, 2 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, draw_bar_line(pixelbuf, 46 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
image_width, image_height, DEFAULT_INK); draw_bar_line(pixelbuf, 48 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
draw_bar(pixelbuf, 46 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, draw_bar_line(pixelbuf, 50 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
image_width, image_height, DEFAULT_INK);
draw_bar(pixelbuf, 48 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si,
image_width, image_height, DEFAULT_INK);
draw_bar(pixelbuf, 50 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si,
image_width, image_height, DEFAULT_INK);
} else if (upceanflag == 8) { /* EAN-8 */ } else if (upceanflag == 8) { /* EAN-8 */
draw_bar(pixelbuf, 0 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, draw_bar_line(pixelbuf, 0 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
image_width, image_height, DEFAULT_INK); draw_bar_line(pixelbuf, 2 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
draw_bar(pixelbuf, 2 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, draw_bar_line(pixelbuf, 32 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
image_width, image_height, DEFAULT_INK); draw_bar_line(pixelbuf, 34 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
draw_bar(pixelbuf, 32 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, draw_bar_line(pixelbuf, 64 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
image_width, image_height, DEFAULT_INK); draw_bar_line(pixelbuf, 66 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
draw_bar(pixelbuf, 34 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si,
image_width, image_height, DEFAULT_INK);
draw_bar(pixelbuf, 64 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si,
image_width, image_height, DEFAULT_INK);
draw_bar(pixelbuf, 66 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si,
image_width, image_height, DEFAULT_INK);
} else if (upceanflag == 12) { /* UPC-A */ } else if (upceanflag == 12) { /* UPC-A */
int latch = 1; for (i = 0 + comp_xoffset; i < 11 + comp_xoffset; i += block_width) {
int fill = module_is_set(symbol, symbol->rows - 1, i);
i = 0 + comp_xoffset; for (block_width = 1; (i + block_width < symbol->width)
do { && module_is_set(symbol, symbol->rows - 1, i + block_width) == fill;
int module_fill = module_is_set(symbol, symbol->rows - 1, i); block_width++);
int block_width = 0; if (fill) {
do { draw_bar_line(pixelbuf, i * si + xoffset_si, block_width * si, guard_yoffset_si, image_width,
block_width++; DEFAULT_INK);
} while ((i + block_width < symbol->width)
&& module_is_set(symbol, symbol->rows - 1, i + block_width) == module_fill);
if (latch == 1) {
/* a bar */
draw_bar(pixelbuf, i * si + xoffset_si, block_width * si,
guard_yoffset_si, guard_descent_si, image_width, image_height, DEFAULT_INK);
latch = 0;
} else {
/* a space */
latch = 1;
} }
i += block_width; }
} while (i < 11 + comp_xoffset); draw_bar_line(pixelbuf, 46 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
draw_bar(pixelbuf, 46 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, draw_bar_line(pixelbuf, 48 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
image_width, image_height, DEFAULT_INK); for (i = 85 + comp_xoffset; i < 96 + comp_xoffset; i += block_width) {
draw_bar(pixelbuf, 48 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, int fill = module_is_set(symbol, symbol->rows - 1, i);
image_width, image_height, DEFAULT_INK); for (block_width = 1; (i + block_width < symbol->width)
latch = 1; && module_is_set(symbol, symbol->rows - 1, i + block_width) == fill;
i = 85 + comp_xoffset; block_width++);
do { if (fill) {
int module_fill = module_is_set(symbol, symbol->rows - 1, i); draw_bar_line(pixelbuf, i * si + xoffset_si, block_width * si, guard_yoffset_si, image_width,
int block_width = 0; DEFAULT_INK);
do {
block_width++;
} while ((i + block_width < symbol->width)
&& module_is_set(symbol, symbol->rows - 1, i + block_width) == module_fill);
if (latch == 1) {
/* a bar */
draw_bar(pixelbuf, i * si + xoffset_si, block_width * si,
guard_yoffset_si, guard_descent_si, image_width, image_height, DEFAULT_INK);
latch = 0;
} else {
/* a space */
latch = 1;
} }
i += block_width; }
} while (i < 96 + comp_xoffset);
} else if (upceanflag == 13) { /* EAN-13 */ } else { /* EAN-13 */
draw_bar(pixelbuf, 0 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, draw_bar_line(pixelbuf, 0 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
image_width, image_height, DEFAULT_INK); draw_bar_line(pixelbuf, 2 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
draw_bar(pixelbuf, 2 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, draw_bar_line(pixelbuf, 46 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
image_width, image_height, DEFAULT_INK); draw_bar_line(pixelbuf, 48 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
draw_bar(pixelbuf, 46 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si, draw_bar_line(pixelbuf, 92 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
image_width, image_height, DEFAULT_INK); draw_bar_line(pixelbuf, 94 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, image_width, DEFAULT_INK);
draw_bar(pixelbuf, 48 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si,
image_width, image_height, DEFAULT_INK);
draw_bar(pixelbuf, 92 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si,
image_width, image_height, DEFAULT_INK);
draw_bar(pixelbuf, 94 * si + comp_xoffset_si, 1 * si, guard_yoffset_si, guard_descent_si,
image_width, image_height, DEFAULT_INK);
} }
copy_bar_line(pixelbuf, comp_xoffset_si, image_width - comp_xoffset_si - roffset_si, guard_yoffset_si,
guard_descent_si, image_width, image_height);
} }
/* Add the text */ /* Add the text */
if (!hide_text) { if (!hide_text) {
int textdone = 0; int text_yposn = yoffset_si + symbol_height_si + (int) (text_gap * si); /* Calculated to top of text */
int text_xposn;
int text_yposn;
text_yposn = yoffset_si + symbol_height_si + (int) (text_gap * si); /* Calculated to top of text */
if (symbol->border_width > 0 && (symbol->output_options & (BARCODE_BOX | BARCODE_BIND))) { if (symbol->border_width > 0 && (symbol->output_options & (BARCODE_BOX | BARCODE_BIND))) {
text_yposn += symbol->border_width * si; text_yposn += symbol->border_width * si;
} }
if (upceanflag) { if (upceanflag >= 6) { /* UPC-E, EAN-8, UPC-A, EAN-13 */
/* Note font sizes halved as in pixels */ /* Note font sizes halved as in pixels */
@ -1136,10 +1157,10 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
/* Halved again to get middle position that draw_string() expects */ /* Halved again to get middle position that draw_string() expects */
int ean_width_adj = (UPCEAN_FONT_WIDTH + 3) / 4; int ean_width_adj = (UPCEAN_FONT_WIDTH + 3) / 4;
output_upcean_split_text(upceanflag, symbol->text, textpart1, textpart2, textpart3, textpart4); out_upcean_split_text(upceanflag, symbol->text, textpart1, textpart2, textpart3, textpart4);
if (upceanflag == 6) { /* UPC-E */ if (upceanflag == 6) { /* UPC-E */
text_xposn = -(5 + upcea_width_adj) * si + comp_xoffset_si; int text_xposn = -(5 + upcea_width_adj) * si + comp_xoffset_si;
draw_string(pixelbuf, textpart1, text_xposn, text_yposn + upcea_height_adj, textflags | SMALL_TEXT, draw_string(pixelbuf, textpart1, text_xposn, text_yposn + upcea_height_adj, textflags | SMALL_TEXT,
image_width, image_height, si); image_width, image_height, si);
text_xposn = 24 * si + comp_xoffset_si; text_xposn = 24 * si + comp_xoffset_si;
@ -1147,7 +1168,6 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
text_xposn = (51 + 3 + upcea_width_adj) * si + comp_xoffset_si; text_xposn = (51 + 3 + upcea_width_adj) * si + comp_xoffset_si;
draw_string(pixelbuf, textpart3, text_xposn, text_yposn + upcea_height_adj, textflags | SMALL_TEXT, draw_string(pixelbuf, textpart3, text_xposn, text_yposn + upcea_height_adj, textflags | SMALL_TEXT,
image_width, image_height, si); image_width, image_height, si);
textdone = 1;
switch (ustrlen(addon)) { switch (ustrlen(addon)) {
case 2: case 2:
text_xposn = (61 + addon_gap) * si + comp_xoffset_si; text_xposn = (61 + addon_gap) * si + comp_xoffset_si;
@ -1162,11 +1182,10 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
} }
} else if (upceanflag == 8) { /* EAN-8 */ } else if (upceanflag == 8) { /* EAN-8 */
text_xposn = 17 * si + comp_xoffset_si; int text_xposn = 17 * si + comp_xoffset_si;
draw_string(pixelbuf, textpart1, text_xposn, text_yposn, textflags, image_width, image_height, si); draw_string(pixelbuf, textpart1, text_xposn, text_yposn, textflags, image_width, image_height, si);
text_xposn = 50 * si + comp_xoffset_si; text_xposn = 50 * si + comp_xoffset_si;
draw_string(pixelbuf, textpart2, text_xposn, text_yposn, textflags, image_width, image_height, si); draw_string(pixelbuf, textpart2, text_xposn, text_yposn, textflags, image_width, image_height, si);
textdone = 1;
switch (ustrlen(addon)) { switch (ustrlen(addon)) {
case 2: case 2:
text_xposn = (77 + addon_gap) * si + comp_xoffset_si; text_xposn = (77 + addon_gap) * si + comp_xoffset_si;
@ -1181,7 +1200,7 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
} }
} else if (upceanflag == 12) { /* UPC-A */ } else if (upceanflag == 12) { /* UPC-A */
text_xposn = (-(5 + upcea_width_adj)) * si + comp_xoffset_si; int text_xposn = (-(5 + upcea_width_adj)) * si + comp_xoffset_si;
draw_string(pixelbuf, textpart1, text_xposn, text_yposn + upcea_height_adj, textflags | SMALL_TEXT, draw_string(pixelbuf, textpart1, text_xposn, text_yposn + upcea_height_adj, textflags | SMALL_TEXT,
image_width, image_height, si); image_width, image_height, si);
text_xposn = 27 * si + comp_xoffset_si; text_xposn = 27 * si + comp_xoffset_si;
@ -1191,7 +1210,6 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
text_xposn = (95 + 5 + upcea_width_adj) * si + comp_xoffset_si; text_xposn = (95 + 5 + upcea_width_adj) * si + comp_xoffset_si;
draw_string(pixelbuf, textpart4, text_xposn, text_yposn + upcea_height_adj, textflags | SMALL_TEXT, draw_string(pixelbuf, textpart4, text_xposn, text_yposn + upcea_height_adj, textflags | SMALL_TEXT,
image_width, image_height, si); image_width, image_height, si);
textdone = 1;
switch (ustrlen(addon)) { switch (ustrlen(addon)) {
case 2: case 2:
text_xposn = (105 + addon_gap) * si + comp_xoffset_si; text_xposn = (105 + addon_gap) * si + comp_xoffset_si;
@ -1205,14 +1223,13 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
break; break;
} }
} else if (upceanflag == 13) { /* EAN-13 */ } else { /* EAN-13 */
text_xposn = (-(5 + ean_width_adj)) * si + comp_xoffset_si; int text_xposn = (-(5 + ean_width_adj)) * si + comp_xoffset_si;
draw_string(pixelbuf, textpart1, text_xposn, text_yposn, textflags, image_width, image_height, si); draw_string(pixelbuf, textpart1, text_xposn, text_yposn, textflags, image_width, image_height, si);
text_xposn = 24 * si + comp_xoffset_si; text_xposn = 24 * si + comp_xoffset_si;
draw_string(pixelbuf, textpart2, text_xposn, text_yposn, textflags, image_width, image_height, si); draw_string(pixelbuf, textpart2, text_xposn, text_yposn, textflags, image_width, image_height, si);
text_xposn = 71 * si + comp_xoffset_si; text_xposn = 71 * si + comp_xoffset_si;
draw_string(pixelbuf, textpart3, text_xposn, text_yposn, textflags, image_width, image_height, si); draw_string(pixelbuf, textpart3, text_xposn, text_yposn, textflags, image_width, image_height, si);
textdone = 1;
switch (ustrlen(addon)) { switch (ustrlen(addon)) {
case 2: case 2:
text_xposn = (105 + addon_gap) * si + comp_xoffset_si; text_xposn = (105 + addon_gap) * si + comp_xoffset_si;
@ -1226,14 +1243,12 @@ static int plot_raster_default(struct zint_symbol *symbol, const int rotate_angl
break; break;
} }
} }
} } else {
int text_xposn = (main_width / 2) * si + comp_xoffset_si;
if (!textdone) {
/* Suppress clang-analyzer-core.CallAndMessage warning */ /* Suppress clang-analyzer-core.CallAndMessage warning */
unsigned char local_text[sizeof(symbol->text)] = {0}; unsigned char local_text[sizeof(symbol->text)] = {0};
to_iso8859_1(symbol->text, local_text); to_iso8859_1(symbol->text, local_text);
/* Put the human readable text at the bottom */ /* Put the human readable text at the bottom */
text_xposn = (main_width / 2) * si + comp_xoffset_si;
draw_string(pixelbuf, local_text, text_xposn, text_yposn, textflags, image_width, image_height, si); draw_string(pixelbuf, local_text, text_xposn, text_yposn, textflags, image_width, image_height, si);
} }
} }
@ -1319,7 +1334,7 @@ INTERNAL int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_
} }
#endif /* NO_PNG */ #endif /* NO_PNG */
error = output_check_colour_options(symbol); error = out_check_colour_options(symbol);
if (error != 0) { if (error != 0) {
return error; return error;
} }

View File

@ -106,8 +106,8 @@ INTERNAL void rs_init_gf(rs_t *rs, const unsigned int prime_poly) {
INTERNAL void rs_init_code(rs_t *rs, const int nsym, int index) { INTERNAL void rs_init_code(rs_t *rs, const int nsym, int index) {
int i, k; int i, k;
const unsigned char *logt = rs->logt; const unsigned char *const logt = rs->logt;
const unsigned char *alog = rs->alog; const unsigned char *const alog = rs->alog;
unsigned char *rspoly = rs->rspoly; unsigned char *rspoly = rs->rspoly;
rs->nsym = nsym; rs->nsym = nsym;
@ -129,9 +129,9 @@ INTERNAL void rs_init_code(rs_t *rs, const int nsym, int index) {
* and places them in reverse order in res */ * and places them in reverse order in res */
INTERNAL void rs_encode(const rs_t *rs, const int datalen, const unsigned char *data, unsigned char *res) { INTERNAL void rs_encode(const rs_t *rs, const int datalen, const unsigned char *data, unsigned char *res) {
int i, k; int i, k;
const unsigned char *logt = rs->logt; const unsigned char *const logt = rs->logt;
const unsigned char *alog = rs->alog; const unsigned char *const alog = rs->alog;
const unsigned char *rspoly = rs->rspoly; const unsigned char *const rspoly = rs->rspoly;
const int nsym = rs->nsym; const int nsym = rs->nsym;
memset(res, 0, nsym); memset(res, 0, nsym);
@ -157,9 +157,9 @@ INTERNAL void rs_encode(const rs_t *rs, const int datalen, const unsigned char *
INTERNAL void rs_encode_uint(const rs_t *rs, const int datalen, const unsigned int *data, unsigned int *res) { INTERNAL void rs_encode_uint(const rs_t *rs, const int datalen, const unsigned int *data, unsigned int *res) {
int i, k; int i, k;
const unsigned char *logt = rs->logt; const unsigned char *const logt = rs->logt;
const unsigned char *alog = rs->alog; const unsigned char *const alog = rs->alog;
const unsigned char *rspoly = rs->rspoly; const unsigned char *const rspoly = rs->rspoly;
const int nsym = rs->nsym; const int nsym = rs->nsym;
memset(res, 0, sizeof(unsigned int) * nsym); memset(res, 0, sizeof(unsigned int) * nsym);

View File

@ -177,18 +177,20 @@ static void dbar_set_gtin14_hrt(struct zint_symbol *symbol, const unsigned char
/* Expand from a width pattern to a bit pattern */ /* Expand from a width pattern to a bit pattern */
static int dbar_expand(struct zint_symbol *symbol, int writer, int *p_latch, const int width) { static int dbar_expand(struct zint_symbol *symbol, int writer, int *p_latch, const int width) {
int j; int j;
int latch = *p_latch;
for (j = 0; j < width; j++) { if (*p_latch) {
if (latch) { for (j = 0; j < width; j++) {
set_module(symbol, symbol->rows, writer); set_module(symbol, symbol->rows, writer);
} else { writer++;
unset_module(symbol, symbol->rows, writer); }
} else {
for (j = 0; j < width; j++) {
unset_module(symbol, symbol->rows, writer);
writer++;
} }
writer++;
} }
*p_latch = !latch; *p_latch = !*p_latch;
return writer; return writer;
} }
@ -304,7 +306,7 @@ INTERNAL int dbar_omn_cc(struct zint_symbol *symbol, unsigned char source[], int
strcpy(symbol->errtxt, "380: Input too long (14 character maximum)"); strcpy(symbol->errtxt, "380: Input too long (14 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, src_len) != 0) { if (!is_sane(NEON_F, source, src_len)) {
strcpy(symbol->errtxt, "381: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "381: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -641,7 +643,7 @@ INTERNAL int dbar_ltd_cc(struct zint_symbol *symbol, unsigned char source[], int
strcpy(symbol->errtxt, "382: Input too long (14 character maximum)"); strcpy(symbol->errtxt, "382: Input too long (14 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (is_sane(NEON, source, src_len) != 0) { if (!is_sane(NEON_F, source, src_len)) {
strcpy(symbol->errtxt, "383: Invalid character in data (digits only)"); strcpy(symbol->errtxt, "383: Invalid character in data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }

View File

@ -128,7 +128,7 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) {
int bg_alpha = 0xff; int bg_alpha = 0xff;
int fg_alpha = 0xff; int fg_alpha = 0xff;
float fg_alpha_opacity = 0.0f, bg_alpha_opacity = 0.0f; float fg_alpha_opacity = 0.0f, bg_alpha_opacity = 0.0f;
const char *font_family = "Helvetica, sans-serif"; const char font_family[] = "Helvetica, sans-serif";
int bold; int bold;
struct zint_vector_rect *rect; struct zint_vector_rect *rect;
@ -317,7 +317,7 @@ INTERNAL int svg_plot(struct zint_symbol *symbol) {
&& (!is_extendable(symbol->symbology) || (symbol->output_options & SMALL_TEXT)); && (!is_extendable(symbol->symbology) || (symbol->output_options & SMALL_TEXT));
string = symbol->vector->strings; string = symbol->vector->strings;
while (string) { while (string) {
const char *halign = string->halign == 2 ? "end" : string->halign == 1 ? "start" : "middle"; const char *const halign = string->halign == 2 ? "end" : string->halign == 1 ? "start" : "middle";
fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"%s\"\n", string->x, string->y, halign); fprintf(fsvg, " <text x=\"%.2f\" y=\"%.2f\" text-anchor=\"%s\"\n", string->x, string->y, halign);
fprintf(fsvg, " font-family=\"%s\" font-size=\"%.1f\"", font_family, string->fsize); fprintf(fsvg, " font-family=\"%s\" font-size=\"%.1f\"", font_family, string->fsize);
if (bold) { if (bold) {

View File

@ -34,50 +34,63 @@
/* Telepen Barcode Symbology information and History (BSiH) /* Telepen Barcode Symbology information and History (BSiH)
https://telepen.co.uk/wp-content/uploads/2018/10/Barcode-Symbology-information-and-History.pdf */ https://telepen.co.uk/wp-content/uploads/2018/10/Barcode-Symbology-information-and-History.pdf */
#define SODIUM "0123456789X" #define SODIUM_X_F (IS_NUM_F | IS_UX__F) /* SODIUM "0123456789X" */
#include <stdio.h> #include <stdio.h>
#include "common.h" #include "common.h"
static char *TeleTable[] = { static char TeleTable[128][16] = {
"31313131", "1131313111", "33313111", "1111313131", { "31313131" }, { "1131313111" }, { "33313111" }, { "1111313131" },
"3111313111", "11333131", "13133131", "111111313111", { "3111313111" }, { "11333131" }, { "13133131" }, { "111111313111" },
"31333111", "1131113131", "33113131", "1111333111", { "31333111" }, { "1131113131" }, { "33113131" }, { "1111333111" },
"3111113131", "1113133111", "1311133111", "111111113131", { "3111113131" }, { "1113133111" }, { "1311133111" }, { "111111113131" },
"3131113111", "11313331", "333331", "111131113111", { "3131113111" }, { "11313331" }, { "333331" }, { "111131113111" },
"31113331", "1133113111", "1313113111", "1111113331", { "31113331" }, { "1133113111" }, { "1313113111" }, { "1111113331" },
"31131331", "113111113111", "3311113111", "1111131331", { "31131331" }, { "113111113111" }, { "3311113111" }, { "1111131331" },
"311111113111", "1113111331", "1311111331", "11111111113111", { "311111113111" }, { "1113111331" }, { "1311111331" }, { "11111111113111" },
"31313311", "1131311131", "33311131", "1111313311", { "31313311" }, { "1131311131" }, { "33311131" }, { "1111313311" },
"3111311131", "11333311", "13133311", "111111311131", { "3111311131" }, { "11333311" }, { "13133311" }, { "111111311131" },
"31331131", "1131113311", "33113311", "1111331131", { "31331131" }, { "1131113311" }, { "33113311" }, { "1111331131" },
"3111113311", "1113131131", "1311131131", "111111113311", { "3111113311" }, { "1113131131" }, { "1311131131" }, { "111111113311" },
"3131111131", "1131131311", "33131311", "111131111131", { "3131111131" }, { "1131131311" }, { "33131311" }, { "111131111131" },
"3111131311", "1133111131", "1313111131", "111111131311", { "3111131311" }, { "1133111131" }, { "1313111131" }, { "111111131311" },
"3113111311", "113111111131", "3311111131", "111113111311", { "3113111311" }, { "113111111131" }, { "3311111131" }, { "111113111311" },
"311111111131", "111311111311", "131111111311", "11111111111131", { "311111111131" }, { "111311111311" }, { "131111111311" }, { "11111111111131" },
"3131311111", "11313133", "333133", "111131311111", { "3131311111" }, { "11313133" }, { "333133" }, { "111131311111" },
"31113133", "1133311111", "1313311111", "1111113133", { "31113133" }, { "1133311111" }, { "1313311111" }, { "1111113133" },
"313333", "113111311111", "3311311111", "11113333", { "313333" }, { "113111311111" }, { "3311311111" }, { "11113333" },
"311111311111", "11131333", "13111333", "11111111311111", { "311111311111" }, { "11131333" }, { "13111333" }, { "11111111311111" },
"31311133", "1131331111", "33331111", "1111311133", { "31311133" }, { "1131331111" }, { "33331111" }, { "1111311133" },
"3111331111", "11331133", "13131133", "111111331111", { "3111331111" }, { "11331133" }, { "13131133" }, { "111111331111" },
"3113131111", "1131111133", "33111133", "111113131111", { "3113131111" }, { "1131111133" }, { "33111133" }, { "111113131111" },
"3111111133", "111311131111", "131111131111", "111111111133", { "3111111133" }, { "111311131111" }, { "131111131111" }, { "111111111133" },
"31311313", "113131111111", "3331111111", "1111311313", { "31311313" }, { "113131111111" }, { "3331111111" }, { "1111311313" },
"311131111111", "11331313", "13131313", "11111131111111", { "311131111111" }, { "11331313" }, { "13131313" }, { "11111131111111" },
"3133111111", "1131111313", "33111313", "111133111111", { "3133111111" }, { "1131111313" }, { "33111313" }, { "111133111111" },
"3111111313", "111313111111", "131113111111", "111111111313", { "3111111313" }, { "111313111111" }, { "131113111111" }, { "111111111313" },
"313111111111", "1131131113", "33131113", "11113111111111", { "313111111111" }, { "1131131113" }, { "33131113" }, { "11113111111111" },
"3111131113", "113311111111", "131311111111", "111111131113", { "3111131113" }, { "113311111111" }, { "131311111111" }, { "111111131113" },
"3113111113", "11311111111111", "331111111111", "111113111113", { "3113111113" }, { "11311111111111" }, { "331111111111" }, { "111113111113" },
"31111111111111", "111311111113", "131111111113", "1111111111111111", { "31111111111111" }, { "111311111113" }, { "131111111113" },
{'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'},
};
/* Generated by "backend/tests/test_telepen -f generate_lens -g" */
static const char TeleLens[128] = {
8, 10, 8, 10, 10, 8, 8, 12, 8, 10, 8, 10, 10, 10, 10, 12,
10, 8, 6, 12, 8, 10, 10, 10, 8, 12, 10, 10, 12, 10, 10, 14,
8, 10, 8, 10, 10, 8, 8, 12, 8, 10, 8, 10, 10, 10, 10, 12,
10, 10, 8, 12, 10, 10, 10, 12, 10, 12, 10, 12, 12, 12, 12, 14,
10, 8, 6, 12, 8, 10, 10, 10, 6, 12, 10, 8, 12, 8, 8, 14,
8, 10, 8, 10, 10, 8, 8, 12, 10, 10, 8, 12, 10, 12, 12, 12,
8, 12, 10, 10, 12, 8, 8, 14, 10, 10, 8, 12, 10, 12, 12, 12,
12, 10, 8, 14, 10, 12, 12, 12, 10, 14, 12, 12, 14, 12, 12, 16
}; };
INTERNAL int telepen(struct zint_symbol *symbol, unsigned char source[], int src_len) { INTERNAL int telepen(struct zint_symbol *symbol, unsigned char source[], int src_len) {
int i, count, check_digit; int i, count, check_digit;
int error_number; int error_number;
char dest[521]; /* 12 (start) + 30 * 16 (max for DELs) + 16 (check digit) + 12 (stop) + 1 = 521 */ char dest[521]; /* 12 (start) + 30 * 16 (max for DELs) + 16 (check digit) + 12 (stop) + 1 = 521 */
char *d = dest;
error_number = 0; error_number = 0;
@ -88,7 +101,8 @@ INTERNAL int telepen(struct zint_symbol *symbol, unsigned char source[], int src
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
/* Start character */ /* Start character */
strcpy(dest, TeleTable['_']); memcpy(d, TeleTable['_'], 12);
d += 12;
for (i = 0; i < src_len; i++) { for (i = 0; i < src_len; i++) {
if (source[i] > 127) { if (source[i] > 127) {
@ -96,7 +110,8 @@ INTERNAL int telepen(struct zint_symbol *symbol, unsigned char source[], int src
strcpy(symbol->errtxt, "391: Invalid character in input data, extended ASCII not allowed"); strcpy(symbol->errtxt, "391: Invalid character in input data, extended ASCII not allowed");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
strcat(dest, TeleTable[source[i]]); memcpy(d, TeleTable[source[i]], TeleLens[source[i]]);
d += TeleLens[source[i]];
count += source[i]; count += source[i];
} }
@ -104,14 +119,16 @@ INTERNAL int telepen(struct zint_symbol *symbol, unsigned char source[], int src
if (check_digit == 127) { if (check_digit == 127) {
check_digit = 0; check_digit = 0;
} }
strcat(dest, TeleTable[check_digit]); memcpy(d, TeleTable[check_digit], TeleLens[check_digit]);
d += TeleLens[check_digit];
if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %d\n", check_digit); if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %d\n", check_digit);
/* Stop character */ /* Stop character */
strcat(dest, TeleTable['z']); memcpy(d, TeleTable['z'], 14);
d += 14;
expand(symbol, dest); expand(symbol, dest, d - dest);
if (symbol->output_options & COMPLIANT_HEIGHT) { if (symbol->output_options & COMPLIANT_HEIGHT) {
/* Default height from various Telepen docs is based on default 26pt at X 0.01125" /* Default height from various Telepen docs is based on default 26pt at X 0.01125"
@ -137,6 +154,7 @@ INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int
int error_number = 0; int error_number = 0;
int i; int i;
char dest[521]; /* 12 (start) + 30 * 16 (max for DELs) + 16 (check digit) + 12 (stop) + 1 = 521 */ char dest[521]; /* 12 (start) + 30 * 16 (max for DELs) + 16 (check digit) + 12 (stop) + 1 = 521 */
char *d = dest;
unsigned char temp[64]; unsigned char temp[64];
count = 0; count = 0;
@ -146,8 +164,8 @@ INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
ustrcpy(temp, source); ustrcpy(temp, source);
to_upper(temp); to_upper(temp, src_len);
if (is_sane(SODIUM, temp, src_len) != 0) { if (!is_sane(SODIUM_X_F, temp, src_len)) {
strcpy(symbol->errtxt, "393: Invalid character in data (digits and \"X\" only)"); strcpy(symbol->errtxt, "393: Invalid character in data (digits and \"X\" only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -161,7 +179,8 @@ INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int
} }
/* Start character */ /* Start character */
strcpy(dest, TeleTable['_']); memcpy(d, TeleTable['_'], 12);
d += 12;
for (i = 0; i < src_len; i += 2) { for (i = 0; i < src_len; i += 2) {
if (temp[i] == 'X') { if (temp[i] == 'X') {
@ -177,21 +196,24 @@ INTERNAL int telepen_num(struct zint_symbol *symbol, unsigned char source[], int
glyph += 27; glyph += 27;
count += glyph; count += glyph;
} }
strcat(dest, TeleTable[glyph]); memcpy(d, TeleTable[glyph], TeleLens[glyph]);
d += TeleLens[glyph];
} }
check_digit = 127 - (count % 127); check_digit = 127 - (count % 127);
if (check_digit == 127) { if (check_digit == 127) {
check_digit = 0; check_digit = 0;
} }
strcat(dest, TeleTable[check_digit]); memcpy(d, TeleTable[check_digit], TeleLens[check_digit]);
d += TeleLens[check_digit];
if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %d\n", check_digit); if (symbol->debug & ZINT_DEBUG_PRINT) printf("Check digit: %d\n", check_digit);
/* Stop character */ /* Stop character */
strcat(dest, TeleTable['z']); memcpy(d, TeleTable['z'], 14);
d += 14;
expand(symbol, dest); expand(symbol, dest, d - dest);
if (symbol->output_options & COMPLIANT_HEIGHT) { if (symbol->output_options & COMPLIANT_HEIGHT) {
(void) set_height(symbol, 0.0f, 32.0f, 0, 1 /*no_errtxt*/); /* Same as alphanumeric Telepen */ (void) set_height(symbol, 0.0f, 32.0f, 0, 1 /*no_errtxt*/); /* Same as alphanumeric Telepen */

View File

@ -236,61 +236,67 @@ static void test_encode(int index, int generate, int debug) {
/* 1*/ { BARCODE_C25STANDARD, 1, "87654321", 0, 1, 107, "With check digit", /* 1*/ { BARCODE_C25STANDARD, 1, "87654321", 0, 1, 107, "With check digit",
"11110101011101000101010001110100011101011101110101011101110111000101010001011101110101110100010111011110101" "11110101011101000101010001110100011101011101110101011101110111000101010001011101110101110100010111011110101"
}, },
/* 2*/ { BARCODE_C25INTER, -1, "87654321", 0, 1, 81, "Interleaved Code 2 of 5, even; verified manually against tec-it", /* 2*/ { BARCODE_C25STANDARD, -1, "1234567890", 0, 1, 117, "",
"111101010111010111010001011101110001010101110111011101110101000111010101000111011101000101000100010101110001011110101"
},
/* 3*/ { BARCODE_C25INTER, -1, "87654321", 0, 1, 81, "Interleaved Code 2 of 5, even; verified manually against tec-it",
"101011101010111000100010001110111000101010001000111010111010001110101011100011101" "101011101010111000100010001110111000101010001000111010111010001110101011100011101"
}, },
/* 3*/ { BARCODE_C25INTER, 1, "87654321", 0, 1, 99, "With check digit", /* 4*/ { BARCODE_C25INTER, 1, "87654321", 0, 1, 99, "With check digit",
"101010001011101110001010100010001110111011101011100010100011101110001010100011101000101011100011101" "101010001011101110001010100010001110111011101011100010100011101110001010100011101000101011100011101"
}, },
/* 4*/ { BARCODE_C25INTER, -1, "7654321", 0, 1, 81, "Interleaved Code 2 of 5, odd", /* 5*/ { BARCODE_C25INTER, -1, "7654321", 0, 1, 81, "Interleaved Code 2 of 5, odd",
"101010101110111000100010001110111000101010001000111010111010001110101011100011101" "101010101110111000100010001110111000101010001000111010111010001110101011100011101"
}, },
/* 5*/ { BARCODE_C25INTER, 1, "7654321", 0, 1, 81, "With check digit", /* 6*/ { BARCODE_C25INTER, 1, "7654321", 0, 1, 81, "With check digit",
"101010100010001110111011101011100010100011101110001010100011101010001000111011101" "101010100010001110111011101011100010100011101110001010100011101010001000111011101"
}, },
/* 6*/ { BARCODE_C25INTER, -1, "602003", 0, 1, 63, "DX cartridge barcode https://en.wikipedia.org/wiki/Interleaved_2_of_5 example", /* 7*/ { BARCODE_C25INTER, -1, "602003", 0, 1, 63, "DX cartridge barcode https://en.wikipedia.org/wiki/Interleaved_2_of_5 example",
"101010111011100010001010111010001000111010001000111011101011101" "101010111011100010001010111010001000111010001000111011101011101"
}, },
/* 7*/ { BARCODE_C25IATA, -1, "87654321", 0, 1, 121, "IATA Code 2 of 5; verified manually against tec-it", /* 8*/ { BARCODE_C25IATA, -1, "87654321", 0, 1, 121, "IATA Code 2 of 5; verified manually against tec-it",
"1010111010101110101010101110111010111011101010111010111010101010111010111011101110101010101110101011101110101010111011101" "1010111010101110101010101110111010111011101010111010111010101010111010111011101110101010101110101011101110101010111011101"
}, },
/* 8*/ { BARCODE_C25IATA, 1, "87654321", 0, 1, 135, "With check digit", /* 9*/ { BARCODE_C25IATA, 1, "87654321", 0, 1, 135, "With check digit",
"101011101010111010101010111011101011101110101011101011101010101011101011101110111010101010111010101110111010101011101011101010111011101" "101011101010111010101010111011101011101110101011101011101010101011101011101110111010101010111010101110111010101011101011101010111011101"
}, },
/* 9*/ { BARCODE_C25LOGIC, -1, "87654321", 0, 1, 89, "Code 2 of 5 Data Logic; verified manually against tec-it", /* 10*/ { BARCODE_C25LOGIC, -1, "87654321", 0, 1, 89, "Code 2 of 5 Data Logic; verified manually against tec-it",
"10101110100010101000111010001110101110111010101110111011100010101000101110111010111011101" "10101110100010101000111010001110101110111010101110111011100010101000101110111010111011101"
}, },
/* 10*/ { BARCODE_C25LOGIC, 1, "87654321", 0, 1, 99, "With check digit", /* 11*/ { BARCODE_C25LOGIC, 1, "87654321", 0, 1, 99, "With check digit",
"101011101000101010001110100011101011101110101011101110111000101010001011101110101110100010111011101" "101011101000101010001110100011101011101110101011101110111000101010001011101110101110100010111011101"
}, },
/* 11*/ { BARCODE_C25IND, -1, "87654321", 0, 1, 131, "Industrial Code 2 of 5; verified manually against tec-it", /* 12*/ { BARCODE_C25IND, -1, "87654321", 0, 1, 131, "Industrial Code 2 of 5; verified manually against tec-it",
"11101110101110101011101010101011101110101110111010101110101110101010101110101110111011101010101011101010111011101010101110111010111" "11101110101110101011101010101011101110101110111010101110101110101010101110101110111011101010101011101010111011101010101110111010111"
}, },
/* 12*/ { BARCODE_C25IND, 1, "87654321", 0, 1, 145, "With check digit", /* 13*/ { BARCODE_C25IND, 1, "87654321", 0, 1, 145, "With check digit",
"1110111010111010101110101010101110111010111011101010111010111010101010111010111011101110101010101110101011101110101010111010111010101110111010111" "1110111010111010101110101010101110111010111011101010111010111010101010111010111011101110101010101110101011101110101010111010111010101110111010111"
}, },
/* 13*/ { BARCODE_DPLEIT, -1, "0000087654321", 0, 1, 135, "Deutsche Post Leitcode; verified manually against tec-it", /* 14*/ { BARCODE_C25IND, -1, "1234567890", 0, 1, 159, "",
"111011101011101010101110101110101011101110111010101010101110101110111010111010101011101110101010101011101110111010101110101011101011101010101110111010111010111"
},
/* 15*/ { BARCODE_DPLEIT, -1, "0000087654321", 0, 1, 135, "Deutsche Post Leitcode; verified manually against tec-it",
"101010101110001110001010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000100010111011101" "101010101110001110001010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000100010111011101"
}, },
/* 14*/ { BARCODE_DPLEIT, -1, "5082300702800", 0, 1, 135, "Deutsche Post Leitcode https://de.wikipedia.org/wiki/Leitcode example", /* 16*/ { BARCODE_DPLEIT, -1, "5082300702800", 0, 1, 135, "Deutsche Post Leitcode https://de.wikipedia.org/wiki/Leitcode example",
"101011101011100010001011101000101110100011101110100010001010101110111000100010100011101110100011101010001110001010001011100011101011101" "101011101011100010001011101000101110100011101110100010001010101110111000100010100011101110100011101010001110001010001011100011101011101"
}, },
/* 15*/ { BARCODE_DPIDENT, -1, "00087654321", 0, 1, 117, "Deutsche Post Identcode; verified manually against tec-it", /* 17*/ { BARCODE_DPIDENT, -1, "00087654321", 0, 1, 117, "Deutsche Post Identcode; verified manually against tec-it",
"101010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000100010111011101" "101010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000100010111011101"
}, },
/* 16*/ { BARCODE_DPIDENT, -1, "39601313414", 0, 1, 117, "Deutsche Post Identcode https://de.wikipedia.org/wiki/Leitcode example", /* 18*/ { BARCODE_DPIDENT, -1, "39601313414", 0, 1, 117, "Deutsche Post Identcode https://de.wikipedia.org/wiki/Leitcode example",
"101011101110001010001010111011100010001011100010001010111011100010001010111010001011101011100010101110001000111011101" "101011101110001010001010111011100010001011100010001010111011100010001010111010001011101011100010101110001000111011101"
}, },
/* 17*/ { BARCODE_ITF14, -1, "0000087654321", 0, 1, 135, "ITF-14; verified manually against tec-it", /* 19*/ { BARCODE_ITF14, -1, "0000087654321", 0, 1, 135, "ITF-14; verified manually against tec-it",
"101010101110001110001010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000101011100011101" "101010101110001110001010101110001110001010001011101110001010100010001110111011101011100010100011101110001010100011101000101011100011101"
}, },
/* 18*/ { BARCODE_ITF14, -1, "0950110153000", 0, 1, 135, "GS1 General Specifications Figure 5.1-2", /* 20*/ { BARCODE_ITF14, -1, "0950110153000", 0, 1, 135, "GS1 General Specifications Figure 5.1-2",
"101010100011101110001011101011100010001011100010101011100010001011101110100011100010001110101010101110001110001010001000111011101011101" "101010100011101110001011101011100010001011100010101011100010001011101110100011100010001110101010101110001110001010001000111011101011101"
}, },
/* 19*/ { BARCODE_ITF14, -1, "1540014128876", 0, 1, 135, "GS1 General Specifications Figure 5.3.2.4-1", /* 21*/ { BARCODE_ITF14, -1, "1540014128876", 0, 1, 135, "GS1 General Specifications Figure 5.3.2.4-1",
"101011100010100010111010101110001000111010001011101110100010001011101011100010001110101000111011101010111000100010001110001110101011101" "101011100010100010111010101110001000111010001011101110100010001011101011100010001110101000111011101010111000100010001110001110101011101"
}, },
/* 20*/ { BARCODE_ITF14, -1, "0950110153001", 0, 1, 135, "GS1 General Specifications Figure 5.3.6-1", /* 22*/ { BARCODE_ITF14, -1, "0950110153001", 0, 1, 135, "GS1 General Specifications Figure 5.3.6-1",
"101010100011101110001011101011100010001011100010101011100010001011101110100011100010001110101010101110001110001011101010001000111011101" "101010100011101110001011101011100010001011100010101011100010001011101110100011100010001110101010101110001110001011101010001000111011101"
}, },
}; };
@ -351,6 +357,107 @@ static void test_encode(int index, int generate, int debug) {
testFinish(); testFinish();
} }
#include <time.h>
#define TEST_PERF_ITER_MILLES 5
#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000)
#define TEST_PERF_TIME(arg) ((arg) * 1000.0 / CLOCKS_PER_SEC)
// Not a real test, just performance indicator
static void test_perf(int index, int debug) {
struct item {
int symbology;
int option_2;
char *data;
int ret;
int expected_rows;
int expected_width;
char *comment;
};
struct item data[] = {
/* 0*/ { BARCODE_C25INTER, -1, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", 0, 1, 819, "C25INTER 90" },
/* 1*/ { BARCODE_C25INTER, -1, "1234567890", 0, 1, 99, "C25INTER 10" },
/* 2*/ { BARCODE_C25STANDARD, -1, "12345678901234567890123456789012345678901234567890123456789012345678901234567890", 0, 1, 817, "C25STANDARD 80" },
/* 3*/ { BARCODE_C25STANDARD, -1, "1234567890", 0, 1, 117, "C25STANDARD 10" },
};
int data_size = ARRAY_SIZE(data);
int i, length, ret;
struct zint_symbol *symbol;
clock_t start;
clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0;
clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print;
int comment_max = 0;
if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */
return;
}
for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment);
printf("Iterations %d\n", TEST_PERF_ITERATIONS);
for (i = 0; i < data_size; i++) {
int j;
if (index != -1 && i != index) continue;
diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0;
for (j = 0; j < TEST_PERF_ITERATIONS; j++) {
start = clock();
symbol = ZBarcode_Create();
diff_create += clock() - start;
assert_nonnull(symbol, "Symbol not created\n");
length = testUtilSetSymbol(symbol, data[i].symbology, DATA_MODE, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug);
start = clock();
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
diff_encode += clock() - start;
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
assert_equal(symbol->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);
start = clock();
ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/);
diff_buffer += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
symbol->output_options |= OUT_BUFFER_INTERMEDIATE;
start = clock();
ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/);
diff_buf_inter += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; // Undo
start = clock();
ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/);
diff_print += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile);
ZBarcode_Delete(symbol);
}
printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment,
TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create));
total_create += diff_create;
total_encode += diff_encode;
total_buffer += diff_buffer;
total_buf_inter += diff_buf_inter;
total_print += diff_print;
}
if (index == -1) {
printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals",
TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create));
}
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */
@ -358,6 +465,7 @@ int main(int argc, char *argv[]) {
{ "test_hrt", test_hrt, 1, 0, 1 }, { "test_hrt", test_hrt, 1, 0, 1 },
{ "test_input", test_input, 1, 0, 1 }, { "test_input", test_input, 1, 0, 1 },
{ "test_encode", test_encode, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 },
{ "test_perf", test_perf, 1, 0, 1 },
}; };
testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); testRun(argc, argv, funcs, ARRAY_SIZE(funcs));

View File

@ -236,17 +236,42 @@ static void test_encode(int index, int generate, int debug) {
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000101010100010101010101000100000101010000010100010100010101010001010000010001010100000100010101000000000101000001010100000000010000" "0000101010100010101010101000100000101010000010100010100010101010001010000010001010100000100010101000000000101000001010100000000010000"
}, },
/* 5*/ { BARCODE_AUSREPLY, "12345678", 0, 3, 73, "Verified manually against tec-it", /* 5*/ { BARCODE_AUSPOST, "12345678DEGHJKLMNO", 0, 3, 133, "62 Custom 3 C encoding GDSET 1st part",
"1000001010001010100010101010100000100010000010101010101010001010001010101010101010100010101010101010100000001010000010000000000010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000101010101000101000100000001010101000101010001010000010101010100000101000100000101000001000000000001000001010000010001010001010000"
},
/* 6*/ { BARCODE_AUSPOST, "23456789PQRSTUVWXY", 0, 3, 133, "62 Custom 3 C encoding GDSET 2nd part",
"1000001010001000101010101000001000100000001010001010001010000000101000101000100000101000101000100000001000101000101010101000101010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000101010101010001000000010101010001010001000101000100000101010101010100010101010001010000010001010101000000010001000001010101000000"
},
/* 7*/ { BARCODE_AUSPOST, "34567890Zcefgijklm", 0, 3, 133, "62 Custom 3 C encoding GDSET 3rd part",
"1000001010001010101010000010001000000010101000001010001010000010100010100010001010001010000010000000100000101000100000001010001010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000101010100010000000101010100010100010101010100010000010000000100000000000001000000000001000000010100000101000000010101010100010000"
},
/* 8*/ { BARCODE_AUSPOST, "12345678lnopqrstuv", 0, 3, 133, "62 Custom 3 C encoding GDSET 4th part",
"1000001010001010100010101010100000100010000010000000100000000000001000001000000000000000100000100000000000001010001010101000000010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000101010101000101000100000001010101000101000000010000010100010001010000010001010000000100000000000100000100000001010001000100000000"
},
/* 9*/ { BARCODE_AUSPOST, "09876543wxy# ", 0, 3, 103, "59 Custom 2 C encoding GDSET 5th part",
"1000100000101010001000000010001010001010101000001000001000000010100010100000100010000000000010100010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"0000001000101010001010101000101000100000001000001000000000001010000010100000001010001000001000100000000"
},
/* 10*/ { BARCODE_AUSREPLY, "12345678", 0, 3, 73, "Verified manually against tec-it",
"1000101010001010100010101010100000100010000000001000001000000000100010100" "1000101010001010100010101010100000100010000000001000001000000000100010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101" "1010101010101010101010101010101010101010101010101010101010101010101010101"
"0000000000101000101000100000001010101000101000000000100010101000101000000" "0000000000101000101000100000001010101000101000000000100010101000101000000"
}, },
/* 6*/ { BARCODE_AUSROUTE, "34567890", 0, 3, 73, "Verified manually against tec-it", /* 11*/ { BARCODE_AUSROUTE, "34567890", 0, 3, 73, "Verified manually against tec-it",
"1000000000101010101010000010001000000010101000100010101010000000101000100" "1000000000101010101010000010001000000010101000100010101010000000101000100"
"1010101010101010101010101010101010101010101010101010101010101010101010101" "1010101010101010101010101010101010101010101010101010101010101010101010101"
"0000101010000010000000101010100010100010101000100010101010001010001000000" "0000101010000010000000101010100010100010101000100010101010001010001000000"
}, },
/* 7*/ { BARCODE_AUSREDIRECT, "98765432", 0, 3, 73, "Verified manually against tec-it", /* 12*/ { BARCODE_AUSREDIRECT, "98765432", 0, 3, 73, "Verified manually against tec-it",
"1000001010000010000000100010100010101010100000101010101000100010100010100" "1000001010000010000000100010100010101010100000101010101000100010100010100"
"1010101010101010101010101010101010101010101010101010101010101010101010101" "1010101010101010101010101010101010101010101010101010101010101010101010101"
"0000001010100010101010001010001000000010101000000000001010101000001010000" "0000001010100010101010001010001000000010101000000000001010101000001010000"

View File

@ -31,6 +31,65 @@
#include "testcommon.h" #include "testcommon.h"
static void test_hrt(int index, int debug) {
struct item {
int option_2;
char *data;
int length;
char *expected;
};
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
struct item data[] = {
/* 0*/ { -1, "1", -1, "01" },
/* 1*/ { 3, "1", -1, "01" },
/* 2*/ { 3, "12", -1, "12" },
/* 3*/ { 4, "123", -1, "123" },
/* 4*/ { 5, "123", -1, "0123" },
/* 5*/ { 5, "12", -1, "0012" },
/* 6*/ { 5, "1", -1, "0001" },
/* 7*/ { 5, "1234", -1, "1234" },
/* 8*/ { 6, "1234", -1, "01234" },
/* 9*/ { 6, "123", -1, "00123" },
/* 10*/ { 6, "12", -1, "00012" },
/* 11*/ { 6, "1", -1, "00001" },
/* 12*/ { 7, "1234", -1, "001234" },
/* 13*/ { 7, "12345", -1, "012345" },
/* 14*/ { 7, "123456", -1, "123456" },
/* 15*/ { 7, "1", -1, "000001" },
/* 16*/ { 8, "12345", -1, "0012345" },
/* 17*/ { 8, "123456", -1, "0123456" },
/* 18*/ { 8, "1234567", -1, "1234567" },
/* 19*/ { 8, "12", -1, "0000012" },
/* 20*/ { 8, "1", -1, "0000001" },
};
int data_size = ARRAY_SIZE(data);
int i, length, ret;
struct zint_symbol *symbol;
testStart("test_hrt");
for (i = 0; i < data_size; i++) {
if (index != -1 && i != index) continue;
symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n");
length = testUtilSetSymbol(symbol, BARCODE_CHANNEL, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, data[i].length, debug);
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
assert_zero(ret, "i:%d ZBarcode_Encode ret %d != 0 %s\n", i, ret, symbol->errtxt);
assert_zero(strcmp((char *) symbol->text, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->text, data[i].expected);
ZBarcode_Delete(symbol);
}
testFinish();
}
static void test_input(int index, int debug) { static void test_input(int index, int debug) {
struct item { struct item {
@ -436,6 +495,7 @@ static void test_generate(int generate) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */
{ "test_hrt", test_hrt, 1, 0, 1 },
{ "test_input", test_input, 1, 0, 1 }, { "test_input", test_input, 1, 0, 1 },
{ "test_encode", test_encode, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 },
{ "test_generate", test_generate, 0, 1, 0 }, { "test_generate", test_generate, 0, 1, 0 },

View File

@ -428,12 +428,25 @@ static void test_encode(int index, int generate, int debug) {
"1101000010010111101110110001001001011000111011011001100100011000101101100110011011101000110110111101111011101010010000110100100111101100011101011" "1101000010010111101110110001001001011000111011011001100100011000101101100110011011101000110110111101111011101010010000110100100111101100011101011"
"1101000010010111101110101100111001000111101011001010000100011110101001101000011011011110101110111101000011001011011101110101001111001100011101011" "1101000010010111101110101100111001000111101011001010000100011110101001101000011011011110101110111101000011001011011101110101001111001100011101011"
}, },
/* 11*/ { BARCODE_HIBC_BLOCKF, 3, -1, "A123BJC5D6E71", 0, 3, 123, 0, "Verified manually against tec-it; differs from BWIPP (columns=6) which uses Code C for final 71 (same no. of codewords)", /* 11*/ { BARCODE_CODABLOCKF, -1, -1, " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", 0, 11, 156, 1, "Visible ASCII",
"110100001001011110111010000110100110110011001100110110011001100110100100110001001000110010001001100100110010001001100010010001100100101100011101100011101011"
"110100001001011110111011000100100110010010001100100010011000100100101100111001001101110010011001110101110011001001110110010011100110100001100101100011101011"
"110100001001011101111010001101110111011011101011101100010000101100110110111101011110111011100100110111011001001110011010011100110010100001001101100011101011"
"110100001001011110111010011011100110110110001101100011011000110110101000110001000101100010001000110101100010001000110100010001100010111100010101100011101011"
"110100001001011110111010011001110110100010001100010100011000100010101101110001011000111010001101110101110110001011100011010001110110100110111001100011101011"
"110100001001011110111010111001100111011101101101000111011000101110110111010001101110001011011101110111010110001110100011011100010110100001011001100011101011"
"110100001001011110111011100100110111011010001110110001011100011010111011110101100100001011110001010101001100001010000110010010110000100011000101100011101011"
"110100001001011110111011101100100100100001101000010110010000100110101100100001011000010010011010000100110000101000011010010000110010101011110001100011101011"
"110100001001011110111011100110100110000100101100101000011110111010110000101001000111101010100111100100101111001001001111010111100100101100011101100011101011"
"110100001001011110111011100110010100111101001001111001011110100100111100101001111001001011011011110110111101101111011011010101111000111101010001100011101011"
"110100001001011110111011011011000101000111101000101111010111011110101111011101011101111010111101110101110111101011100011011101101110101001100001100011101011"
},
/* 12*/ { BARCODE_HIBC_BLOCKF, 3, -1, "A123BJC5D6E71", 0, 3, 123, 0, "Verified manually against tec-it; differs from BWIPP (columns=6) which uses Code C for final 71 (same no. of codewords)",
"110100001001011110111010010110000110001001001010001100010011100110110011100101100101110010001011000100100001101100011101011" "110100001001011110111010010110000110001001001010001100010011100110110011100101100101110010001011000100100001101100011101011"
"110100001001011110111011000100100101101110001000100011011011100100101100010001100111010010001101000111001001101100011101011" "110100001001011110111011000100100101101110001000100011011011100100101100010001100111010010001101000111001001101100011101011"
"110100001001011110111010110011100111011011101001110011011010001000101110111101011100011011001110100100100110001100011101011" "110100001001011110111010110011100111011011101001110011011010001000101110111101011100011011001110100100100110001100011101011"
}, },
/* 12*/ { BARCODE_HIBC_BLOCKF, -1, -1, "$$52001510X3G", 0, 4, 101, 1, "tec-it differs as adds unnecessary Code C at end of 1st line", /* 13*/ { BARCODE_HIBC_BLOCKF, -1, -1, "$$52001510X3G", 0, 4, 101, 1, "tec-it differs as adds unnecessary Code C at end of 1st line",
"11010000100101111011101001000011011000100100100100011001001000110011011100100101110011001100011101011" "11010000100101111011101001000011011000100100100100011001001000110011011100100101110011001100011101011"
"11010000100101110111101011000111011001001110110011011001101110100010111101110100001100101100011101011" "11010000100101110111101011000111011001001110110011011001101110100010111101110100001100101100011101011"
"11010000100101111011101011001110010011101100111000101101100101110011010001000100100011001100011101011" "11010000100101111011101011001110010011101100111000101101100101110011010001000100100011001100011101011"

View File

@ -185,38 +185,64 @@ static void test_input(int index, int debug) {
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
struct item data[] = { struct item data[] = {
/* 0*/ { BARCODE_CODE11, -1, "-", -1, 0, 1, 37 }, /* 0*/ { BARCODE_CODE11, -1, "-", -1, 0, 1, 37 },
/* 1*/ { BARCODE_CODE11, -1, "A", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 1*/ { BARCODE_CODE11, -1, "0123456789-", -1, 0, 1, 115 },
/* 2*/ { BARCODE_CODE11, 3, "1", -1, ZINT_ERROR_INVALID_OPTION, -1, -1 }, /* 2*/ { BARCODE_CODE11, -1, "A", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 3*/ { BARCODE_CODE39, -1, "a", -1, 0, 1, 38 }, // Converts to upper /* 3*/ { BARCODE_CODE11, -1, "12+", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 4*/ { BARCODE_CODE39, -1, ",", 1, ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 4*/ { BARCODE_CODE11, -1, "1.2", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 5*/ { BARCODE_CODE39, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 5*/ { BARCODE_CODE11, -1, "12!", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 6*/ { BARCODE_CODE39, 0, "1", -1, 0, 1, 38 }, /* 6*/ { BARCODE_CODE11, -1, " ", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 7*/ { BARCODE_CODE39, 1, "1", -1, 0, 1, 51 }, // Check digit /* 7*/ { BARCODE_CODE11, 3, "1", -1, ZINT_ERROR_INVALID_OPTION, -1, -1 },
/* 8*/ { BARCODE_CODE39, 2, "1", -1, 0, 1, 38 }, // option_2 > 1 gnored /* 8*/ { BARCODE_CODE39, -1, "a", -1, 0, 1, 38 }, // Converts to upper
/* 9*/ { BARCODE_EXCODE39, -1, "A", -1, 0, 1, 38 }, /* 9*/ { BARCODE_CODE39, -1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%", -1, 0, 1, 584 },
/* 10*/ { BARCODE_EXCODE39, -1, "a", -1, 0, 1, 51 }, /* 10*/ { BARCODE_CODE39, -1, "AB!", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 11*/ { BARCODE_EXCODE39, -1, ",", -1, 0, 1, 51 }, /* 11*/ { BARCODE_CODE39, -1, "A\"B", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 12*/ { BARCODE_EXCODE39, -1, "\000", 1, 0, 1, 51 }, /* 12*/ { BARCODE_CODE39, -1, "#AB", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 13*/ { BARCODE_EXCODE39, -1, "é", -1, ZINT_ERROR_INVALID_DATA, -1, -1, }, /* 13*/ { BARCODE_CODE39, -1, "&", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 14*/ { BARCODE_LOGMARS, -1, "A", -1, 0, 1, 47 }, /* 14*/ { BARCODE_CODE39, -1, "'", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 15*/ { BARCODE_LOGMARS, -1, "a", -1, 0, 1, 47 }, /* 15*/ { BARCODE_CODE39, -1, "(", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 16*/ { BARCODE_LOGMARS, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1, }, /* 16*/ { BARCODE_CODE39, -1, ")", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 17*/ { BARCODE_LOGMARS, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1, }, /* 17*/ { BARCODE_CODE39, -1, "*", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 18*/ { BARCODE_CODE93, -1, "A", -1, 0, 1, 46 }, /* 18*/ { BARCODE_CODE39, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 19*/ { BARCODE_CODE93, -1, "a", -1, 0, 1, 55 }, /* 19*/ { BARCODE_CODE39, -1, ":", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 20*/ { BARCODE_CODE93, -1, ",", -1, 0, 1, 55 }, /* 20*/ { BARCODE_CODE39, -1, "@", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 21*/ { BARCODE_CODE93, -1, "\000", 1, 0, 1, 55 }, /* 21*/ { BARCODE_CODE39, -1, "[", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 22*/ { BARCODE_CODE93, -1, "é", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 22*/ { BARCODE_CODE39, -1, "`", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 23*/ { BARCODE_PZN, -1, "1", -1, 0, 1, 142 }, /* 23*/ { BARCODE_CODE39, -1, "{", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 24*/ { BARCODE_PZN, -1, "A", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 24*/ { BARCODE_CODE39, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 25*/ { BARCODE_PZN, -1, "1000006", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, // Check digit == 10 so can't be used /* 25*/ { BARCODE_CODE39, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 26*/ { BARCODE_VIN, -1, "5GZCZ43D13S812715", -1, 0, 1, 246 }, /* 26*/ { BARCODE_CODE39, 0, "1", -1, 0, 1, 38 },
/* 27*/ { BARCODE_VIN, -1, "5GZCZ43D23S812715", -1, ZINT_ERROR_INVALID_CHECK, -1, -1 }, // North American with invalid check character /* 27*/ { BARCODE_CODE39, 1, "1", -1, 0, 1, 51 }, // Check digit
/* 28*/ { BARCODE_VIN, -1, "WP0ZZZ99ZTS392124", -1, 0, 1, 246 }, // Not North American so no check /* 28*/ { BARCODE_CODE39, 2, "1", -1, 0, 1, 38 }, // option_2 > 1 gnored
/* 29*/ { BARCODE_VIN, -1, "WPOZZZ99ZTS392124", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, // O not allowed /* 29*/ { BARCODE_EXCODE39, -1, "A", -1, 0, 1, 38 },
/* 30*/ { BARCODE_HIBC_39, -1, "a", -1, 0, 1, 79 }, // Converts to upper /* 30*/ { BARCODE_EXCODE39, -1, "a", -1, 0, 1, 51 },
/* 31*/ { BARCODE_HIBC_39, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 31*/ { BARCODE_EXCODE39, -1, ",", -1, 0, 1, 51 },
/* 32*/ { BARCODE_HIBC_39, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1 }, /* 32*/ { BARCODE_EXCODE39, -1, "\000", 1, 0, 1, 51 },
/* 33*/ { BARCODE_EXCODE39, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 34*/ { BARCODE_EXCODE39, -1, "é", -1, ZINT_ERROR_INVALID_DATA, -1, -1, },
/* 35*/ { BARCODE_LOGMARS, -1, "A", -1, 0, 1, 47 },
/* 36*/ { BARCODE_LOGMARS, -1, "a", -1, 0, 1, 47 },
/* 37*/ { BARCODE_LOGMARS, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1, },
/* 38*/ { BARCODE_LOGMARS, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1, },
/* 39*/ { BARCODE_LOGMARS, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1, },
/* 40*/ { BARCODE_CODE93, -1, "A", -1, 0, 1, 46 },
/* 41*/ { BARCODE_CODE93, -1, "a", -1, 0, 1, 55 },
/* 42*/ { BARCODE_CODE93, -1, ",", -1, 0, 1, 55 },
/* 43*/ { BARCODE_CODE93, -1, "\000", 1, 0, 1, 55 },
/* 44*/ { BARCODE_CODE93, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 45*/ { BARCODE_CODE93, -1, "é", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 46*/ { BARCODE_PZN, -1, "1", -1, 0, 1, 142 },
/* 47*/ { BARCODE_PZN, -1, "A", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 48*/ { BARCODE_PZN, -1, "1000006", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, // Check digit == 10 so can't be used
/* 49*/ { BARCODE_VIN, -1, "5GZCZ43D13S812715", -1, 0, 1, 246 },
/* 50*/ { BARCODE_VIN, -1, "5GZCZ43D23S812715", -1, ZINT_ERROR_INVALID_CHECK, -1, -1 }, // North American with invalid check character
/* 51*/ { BARCODE_VIN, -1, "WP0ZZZ99ZTS392124", -1, 0, 1, 246 }, // Not North American so no check
/* 52*/ { BARCODE_VIN, -1, "WP0ZZZ99ZTS392I24", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, // I not allowed
/* 53*/ { BARCODE_VIN, -1, "WPOZZZ99ZTS392124", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, // O not allowed
/* 54*/ { BARCODE_VIN, -1, "WPQZZZ99ZTS392124", -1, ZINT_ERROR_INVALID_DATA, -1, -1 }, // Q not allowed
/* 55*/ { BARCODE_HIBC_39, -1, "a", -1, 0, 1, 79 }, // Converts to upper
/* 56*/ { BARCODE_HIBC_39, -1, ",", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 57*/ { BARCODE_HIBC_39, -1, "\000", 1, ZINT_ERROR_INVALID_DATA, -1, -1 },
/* 58*/ { BARCODE_HIBC_39, -1, "\300", -1, ZINT_ERROR_INVALID_DATA, -1, -1 },
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, length, ret; int i, length, ret;
@ -310,67 +336,82 @@ static void test_encode(int index, int generate, int debug) {
/* 15*/ { BARCODE_CODE39, -1, "+A/E%U$A/D%T+Z", -1, 0, 1, 207, "Same as BARCODE_EXCODE39 'a%\000\001$\177z' below", /* 15*/ { BARCODE_CODE39, -1, "+A/E%U$A/D%T+Z", -1, 0, 1, 207, "Same as BARCODE_EXCODE39 'a%\000\001$\177z' below",
"100101101101010010100100101101010010110100100101001011010110010101010010010010110010101011010010010010101101010010110100100101001010101100101101010010010010101011011001010010100100101001101101010100101101101" "100101101101010010100100101101010010110100100101001011010110010101010010010010110010101011010010010010101101010010110100100101001010101100101101010010010010101011011001010010100100101001101101010100101101101"
}, },
/* 16*/ { BARCODE_EXCODE39, -1, "1A", -1, 0, 1, 51, "ISO/IEC 16388:2007 Figure 1", /* 16*/ { BARCODE_CODE39, -1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%", -1, 0, 1, 584, "Full CODE39 set",
"10010110110101010011011010110100101011010110010101101101100101010101001101011011010011010101011001101010101001011011011010010110101011001011010110101001011010110100101101101101001010101011001011011010110010101011011001010101010011011011010100110101011010011010101011001101011010101001101011010100110110110101001010101101001101101011010010101101101001010101011001101101010110010101101011001010101101100101100101010110100110101011011001101010101001011010110110010110101010011011010101001010110110110010101101010011010110101001001001010100100101001010010100100101010010010010100101101101"
},
/* 17*/ { BARCODE_EXCODE39, -1, "1A", -1, 0, 1, 51, "ISO/IEC 16388:2007 Figure 1",
"100101101101011010010101101101010010110100101101101" "100101101101011010010101101101010010110100101101101"
}, },
/* 17*/ { BARCODE_EXCODE39, 1, "1A", -1, 0, 1, 64, "With check digit", /* 18*/ { BARCODE_EXCODE39, 1, "1A", -1, 0, 1, 64, "With check digit",
"1001011011010110100101011011010100101101011010010110100101101101" "1001011011010110100101011011010100101101011010010110100101101101"
}, },
/* 18*/ { BARCODE_EXCODE39, 1, "Z4", -1, 0, 1, 64, "Check digit $", /* 19*/ { BARCODE_EXCODE39, 1, "Z4", -1, 0, 1, 64, "Check digit $",
"1001011011010100110110101010100110101101001001001010100101101101" "1001011011010100110110101010100110101101001001001010100101101101"
}, },
/* 19*/ { BARCODE_EXCODE39, -1, "a%\000\001$\177z", 7, 0, 1, 207, "Verified manually against tec-it", /* 20*/ { BARCODE_EXCODE39, -1, "a%\000\001$\177z", 7, 0, 1, 207, "Verified manually against tec-it",
"100101101101010010100100101101010010110100100101001011010110010101010010010010110010101011010010010010101101010010110100100101001010101100101101010010010010101011011001010010100100101001101101010100101101101" "100101101101010010100100101101010010110100100101001011010110010101010010010010110010101011010010010010101101010010110100100101001010101100101101010010010010101011011001010010100100101001101101010100101101101"
}, },
/* 20*/ { BARCODE_EXCODE39, -1, "\033\037!+/\\@A~", -1, 0, 1, 246, "Verified manually against tec-it", /* 21*/ { BARCODE_EXCODE39, -1, "\033\037!+/\\@A~", -1, 0, 1, 246, "Verified manually against tec-it",
"100101101101010100100100101101010010110101001001001011010110010101001001010010110101001011010010010100101101010100110100100101001011010110100101010010010010101101010011010100100100101001101010110110101001011010100100100101011010110010100101101101" "100101101101010100100100101101010010110101001001001011010110010101001001010010110101001011010010010100101101010100110100100101001011010110100101010010010010101101010011010100100100101001101010110110101001011010100100100101011010110010100101101101"
}, },
/* 21*/ { BARCODE_LOGMARS, -1, "1A", -1, 0, 1, 63, "Verified manually against tec-it", /* 22*/ { BARCODE_EXCODE39, -1, " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]", -1, 0, 1, 1130, "Visible ASCII 1st 85 symbol chars",
"10010110110101001101011010100100101001011010100101101001001010010101101001011010010010100101101101001010100100101001010101100101101001001010010110101100101010010010100101011011001010100100101001010101001101101001001010010110101001101010010010100101011010011010100100101001010101100110101001001010010110101010011010010010100101011010100110100101011011011001010110101001001010010110101101001010100110110101101001010110101100101011011011001010101010011010110110100110101010110011010101010010110110110100101101010110010110101001001010010100110110101010100100100101011011001010101001001001010101001101101010010010010110101001101010100100100101011010011010101001001001010101100110101010010010010100110101011011010100101101011010010110110110100101010101100101101101011001010101101100101010101001101101101010011010101101001101010101100110101101010100110101101010011011011010100101010110100110110101101001010110110100101010101100110110101011001010110101100101010110110010110010101011010011010101101100110101010100101101011011001011010101001101101010101001001001011010101001101010010010010101101010011010100100100101101101010010100101101101"
},
/* 23*/ { BARCODE_EXCODE39, -1, "^_`abcdefghijklmnopqrstuvwxyz{|}~", -1, 0, 1, 883, "Visible ASCII last part",
"1001011011010101001001001010101101001101010010010010110101101001010100100100101100110101010100101001001011010100101101001010010010101101001011010010100100101101101001010100101001001010101100101101001010010010110101100101010010100100101011011001010100101001001010101001101101001010010010110101001101010010100100101011010011010100101001001010101100110101001010010010110101010011010010100100101011010100110100101001001011011010100101001010010010101011010011010010100100101101011010010100101001001010110110100101001010010010101010110011010010100100101101010110010100101001001010110101100101001010010010101011011001010010100100101100101010110100101001001010011010101101001010010010110011010101010010100100101001011010110100101001001011001011010101001010010010100110110101010100100100101011011010010101001001001010101011001101010010010010110101011001010100100100101011010110010100101101101"
},
/* 24*/ { BARCODE_LOGMARS, -1, "1A", -1, 0, 1, 63, "Verified manually against tec-it",
"100010111011101011101000101011101110101000101110100010111011101" "100010111011101011101000101011101110101000101110100010111011101"
}, },
/* 22*/ { BARCODE_LOGMARS, 1, "1A", -1, 0, 1, 79, "With check digit; verified manually against tec-it", /* 25*/ { BARCODE_LOGMARS, 1, "1A", -1, 0, 1, 79, "With check digit; verified manually against tec-it",
"1000101110111010111010001010111011101010001011101011101000101110100010111011101" "1000101110111010111010001010111011101010001011101011101000101110100010111011101"
}, },
/* 23*/ { BARCODE_LOGMARS, -1, "ABC", -1, 0, 1, 79, "MIL-STD-1189 Rev. B Figure 1", /* 26*/ { BARCODE_LOGMARS, -1, "ABC", -1, 0, 1, 79, "MIL-STD-1189 Rev. B Figure 1",
"1000101110111010111010100010111010111010001011101110111010001010100010111011101" "1000101110111010111010100010111010111010001011101110111010001010100010111011101"
}, },
/* 24*/ { BARCODE_LOGMARS, -1, "SAMPLE 1", -1, 0, 1, 159, "MIL-STD-1189 Rev. B Figure 2 top", /* 27*/ { BARCODE_LOGMARS, -1, "SAMPLE 1", -1, 0, 1, 159, "MIL-STD-1189 Rev. B Figure 2 top",
"100010111011101010111010111000101110101000101110111011101010001010111011101000101011101010001110111010111000101010001110101110101110100010101110100010111011101" "100010111011101010111010111000101110101000101110111011101010001010111011101000101011101010001110111010111000101010001110101110101110100010101110100010111011101"
}, },
/* 25*/ { BARCODE_LOGMARS, 1, "12345/ABCDE", -1, 0, 1, 223, "MIL-STD-1189 Rev. B Section 6.2.1 check character example; verified manually against tec-it", /* 28*/ { BARCODE_LOGMARS, 1, "12345/ABCDE", -1, 0, 1, 223, "MIL-STD-1189 Rev. B Section 6.2.1 check character example; verified manually against tec-it",
"1000101110111010111010001010111010111000101011101110111000101010101000111010111011101000111010101000100010100010111010100010111010111010001011101110111010001010101011100010111011101011100010101010111011100010100010111011101" "1000101110111010111010001010111010111000101011101110111000101010101000111010111011101000111010101000100010100010111010100010111010111010001011101110111010001010101011100010111011101011100010101010111011100010100010111011101"
}, },
/* 26*/ { BARCODE_CODE93, -1, "C93", -1, 0, 1, 64, "ANSI/AIM BC5-1995 Figure 1; verified manually against tec-it", /* 29*/ { BARCODE_CODE93, -1, "C93", -1, 0, 1, 64, "ANSI/AIM BC5-1995 Figure 1; verified manually against tec-it",
"1010111101101000101000010101010000101101010001110110101010111101" "1010111101101000101000010101010000101101010001110110101010111101"
}, },
/* 27*/ { BARCODE_CODE93, -1, "CODE\01593", -1, 0, 1, 109, "ANSI/AIM BC5-1995 Figure B1; verified manually against tec-it", /* 30*/ { BARCODE_CODE93, -1, "CODE\01593", -1, 0, 1, 109, "ANSI/AIM BC5-1995 Figure B1; verified manually against tec-it",
"1010111101101000101001011001100101001100100101001001101010011001000010101010000101100101001000101101010111101" "1010111101101000101001011001100101001100100101001001101010011001000010101010000101100101001000101101010111101"
}, },
/* 28*/ { BARCODE_CODE93, -1, "1A", -1, 0, 1, 55, "Verified manually against tec-it", /* 31*/ { BARCODE_CODE93, -1, "1A", -1, 0, 1, 55, "Verified manually against tec-it",
"1010111101010010001101010001101000101001110101010111101" "1010111101010010001101010001101000101001110101010111101"
}, },
/* 29*/ { BARCODE_CODE93, -1, "TEST93", -1, 0, 1, 91, "Verified manually against tec-it", /* 32*/ { BARCODE_CODE93, -1, "TEST93", -1, 0, 1, 91, "Verified manually against tec-it",
"1010111101101001101100100101101011001101001101000010101010000101011101101001000101010111101" "1010111101101001101100100101101011001101001101000010101010000101011101101001000101010111101"
}, },
/* 30*/ { BARCODE_CODE93, -1, "\000a\177", 3, 0, 1, 91, "Verified manually against tec-it", /* 33*/ { BARCODE_CODE93, -1, "\000a\177", 3, 0, 1, 91, "Verified manually against tec-it",
"1010111101110110101100101101001100101101010001110110101101001101011011101010010001010111101" "1010111101110110101100101101001100101101010001110110101101001101011011101010010001010111101"
}, },
/* 31*/ { BARCODE_PZN, -1, "1234567", -1, 0, 1, 142, "Example from IFA Info Code 39 EN V2.1; verified manually against tec-it", /* 34*/ { BARCODE_CODE93, -1, " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghij", -1, 0, 1, 1000, "Visible ASCII 1st 107 symbol chars",
"1010111101110100101110101101101010001110101101101001001110101101101000101110010101101011101110101101100010101110101101011010001110101101011001001110101101011000101110101101001101001011101101110101101010110001001011101110101001011011101000101001010010001010001001010000101001010001001001001001000101010100001000100101000010101110101101001110101110110101100010101110110101011010001110110101011001001110110101011000101110110101001101001110110101100110101101010001101001001101000101100101001100100101100010101011010001011001001011000101001101001000110101010110001010011001010001101001011001000101101101101001101100101101011001101001101100101101100110101011011001011001101001101101001110101110110101000110101110110101010110001110110101010011001110110101010001101110110101001011001110110101011011001001100101101010001001100101101001001001100101101000101001100101100101001001100101100100101001100101100010101001100101011010001001100101011001001001100101011000101001100101001101001010001101101001101010111101"
},
/* 35*/ { BARCODE_CODE93, -1, "klmnopqrstuvwxyz{|}~", -1, 0, 1, 397, "Visible ASCII last part",
"1010111101001100101000110101001100101010110001001100101010011001001100101010001101001100101001011001001100101000101101001100101101101001001100101101100101001100101101011001001100101101001101001100101100101101001100101100110101001100101011011001001100101011001101001100101001101101001100101001110101110110101000101101110110101101101001110110101101100101110110101101011001101001001101100101010111101"
},
/* 36*/ { BARCODE_PZN, -1, "1234567", -1, 0, 1, 142, "Example from IFA Info Code 39 EN V2.1; verified manually against tec-it",
"1001011011010100101011011011010010101101011001010110110110010101010100110101101101001101010101100110101010100101101101101001011010100101101101" "1001011011010100101011011011010010101101011001010110110110010101010100110101101101001101010101100110101010100101101101101001011010100101101101"
}, },
/* 32*/ { BARCODE_PZN, -1, "2758089", -1, 0, 1, 142, "Example from IFA Info Check Digit Calculations EN 15 July 2019; verified manually against tec-it", /* 37*/ { BARCODE_PZN, -1, "2758089", -1, 0, 1, 142, "Example from IFA Info Check Digit Calculations EN 15 July 2019; verified manually against tec-it",
"1001011011010100101011011010110010101101010010110110110100110101011010010110101010011011010110100101101010110010110101011001011010100101101101" "1001011011010100101011011010110010101101010010110110110100110101011010010110101010011011010110100101101010110010110101011001011010100101101101"
}, },
/* 33*/ { BARCODE_VIN, -1, "1FTCR10UXTPA78180", -1, 0, 1, 246, "https://www.vinquery.com/img/vinbarcode/vinbarcode4.jpg", /* 38*/ { BARCODE_VIN, -1, "1FTCR10UXTPA78180", -1, 0, 1, 246, "https://www.vinquery.com/img/vinbarcode/vinbarcode4.jpg",
"100101101101011010010101101011011001010101011011001011011010010101101010110010110100101011010100110110101100101010110100101101011010101101100101011011010010110101001011010100101101101101001011010110100101011011010010110101010011011010100101101101" "100101101101011010010101101011011001010101011011001011011010010101101010110010110100101011010100110110101100101010110100101101011010101101100101011011010010110101001011010100101101101101001011010110100101011011010010110101010011011010100101101101"
}, },
/* 34*/ { BARCODE_VIN, 1, "2FTPX28L0XCA15511", -1, 0, 1, 259, "With Import 'I' prefix; https://www.vinquery.com/img/vinbarcode/vinbarcode1.jpg", /* 39*/ { BARCODE_VIN, 1, "2FTPX28L0XCA15511", -1, 0, 1, 259, "With Import 'I' prefix; https://www.vinquery.com/img/vinbarcode/vinbarcode1.jpg",
"1001011011010101101001101010110010101101011011001010101011011001010110110100101001011010110101100101011011010010110101011010100110101001101101010010110101101101101001010110101001011011010010101101101001101010110100110101011010010101101101001010110100101101101" "1001011011010101101001101010110010101101011011001010101011011001010110110100101001011010110101100101011011010010110101011010100110101001101101010010110101101101101001010110101001011011010010101101101001101010110100110101011010010101101101001010110100101101101"
}, },
/* 35*/ { BARCODE_HIBC_39, -1, "A123BJC5D6E71", -1, 0, 1, 271, "ANSI/HIBC 2.6 - 2016 Figure 2, same", /* 40*/ { BARCODE_HIBC_39, -1, "A123BJC5D6E71", -1, 0, 1, 271, "ANSI/HIBC 2.6 - 2016 Figure 2, same",
"1000101110111010100010100010001011101010001011101110100010101110101110001010111011101110001010101011101000101110101011100011101011101110100010101110100011101010101011100010111010111000111010101110101110001010101000101110111011101000101011101010100011101110100010111011101" "1000101110111010100010100010001011101010001011101110100010101110101110001010111011101110001010101011101000101110101011100011101011101110100010101110100011101010101011100010111010111000111010101110101110001010101000101110111011101000101011101010100011101110100010111011101"
}, },
/* 36*/ { BARCODE_HIBC_39, -1, "$$52001510X3G", -1, 0, 1, 271, "ANSI/HIBC 2.6 - 2016 Figure 6, same", /* 41*/ { BARCODE_HIBC_39, -1, "$$52001510X3G", -1, 0, 1, 271, "ANSI/HIBC 2.6 - 2016 Figure 6, same",
"1000101110111010100010100010001010001000100010101000100010001010111010001110101010111000101011101010001110111010101000111011101011101000101011101110100011101010111010001010111010100011101110101000101110101110111011100010101010101000111011101010111000101110100010111011101" "1000101110111010100010100010001010001000100010101000100010001010111010001110101010111000101011101010001110111010101000111011101011101000101011101110100011101010111010001010111010100011101110101000101110101110111011100010101010101000111011101010111000101110100010111011101"
}, },
}; };
@ -431,6 +472,111 @@ static void test_encode(int index, int generate, int debug) {
testFinish(); testFinish();
} }
#include <time.h>
#define TEST_PERF_ITER_MILLES 5
#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000)
#define TEST_PERF_TIME(arg) ((arg) * 1000.0 / CLOCKS_PER_SEC)
// Not a real test, just performance indicator
static void test_perf(int index, int debug) {
struct item {
int symbology;
int option_2;
char *data;
int ret;
int expected_rows;
int expected_width;
char *comment;
};
struct item data[] = {
/* 0*/ { BARCODE_CODE39, -1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+", 0, 1, 1130, "CODE39 85" },
/* 1*/ { BARCODE_CODE39, -1, "123456ABCD", 0, 1, 155, "CODE39 10" },
/* 2*/ { BARCODE_CODE93, -1,
"\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037 !\"#$%&'()*+,-./0123456789ABCDEFGHIJ",
0, 1, 1000, "CODE93 107 symbol chars" },
/* 3*/ { BARCODE_CODE93, -1, "123456ABCD", 0, 1, 127, "CODE93 10" },
/* 4*/ { BARCODE_CODE11, -1, "1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-1234567890-", 0, 1, 966, "CODE11 121" },
/* 5*/ { BARCODE_CODE11, -1, "1234567890-", 0, 1, 116, "CODE11 5" },
};
int data_size = ARRAY_SIZE(data);
int i, length, ret;
struct zint_symbol *symbol;
clock_t start;
clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0;
clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print;
int comment_max = 0;
if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */
return;
}
for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment);
printf("Iterations %d\n", TEST_PERF_ITERATIONS);
for (i = 0; i < data_size; i++) {
int j;
if (index != -1 && i != index) continue;
diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0;
for (j = 0; j < TEST_PERF_ITERATIONS; j++) {
start = clock();
symbol = ZBarcode_Create();
diff_create += clock() - start;
assert_nonnull(symbol, "Symbol not created\n");
length = testUtilSetSymbol(symbol, data[i].symbology, DATA_MODE, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug);
start = clock();
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
diff_encode += clock() - start;
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
assert_equal(symbol->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);
start = clock();
ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/);
diff_buffer += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
symbol->output_options |= OUT_BUFFER_INTERMEDIATE;
start = clock();
ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/);
diff_buf_inter += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; // Undo
start = clock();
ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/);
diff_print += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile);
ZBarcode_Delete(symbol);
}
printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment,
TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create));
total_create += diff_create;
total_encode += diff_encode;
total_buffer += diff_buffer;
total_buf_inter += diff_buf_inter;
total_print += diff_print;
}
if (index == -1) {
printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals",
TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create));
}
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */
@ -438,6 +584,7 @@ int main(int argc, char *argv[]) {
{ "test_hrt", test_hrt, 1, 0, 1 }, { "test_hrt", test_hrt, 1, 0, 1 },
{ "test_input", test_input, 1, 0, 1 }, { "test_input", test_input, 1, 0, 1 },
{ "test_encode", test_encode, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 },
{ "test_perf", test_perf, 1, 0, 1 },
}; };
testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); testRun(argc, argv, funcs, ARRAY_SIZE(funcs));

View File

@ -839,6 +839,105 @@ static void test_encode(int index, int generate, int debug) {
testFinish(); testFinish();
} }
#include <time.h>
#define TEST_PERF_ITER_MILLES 10
#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000)
#define TEST_PERF_TIME(arg) (((arg) * 1000.0) / CLOCKS_PER_SEC)
// Not a real test, just performance indicator
static void test_perf(int index, int debug) {
struct item {
int symbology;
char *data;
int ret;
int expected_rows;
int expected_width;
char *comment;
};
struct item data[] = {
/* 0*/ { BARCODE_CODE128, "123456ABCD123456ABCD123456ABCD123456ABCD123456ABCD123456ABCD", 0, 1, 618, "CODE128 60" },
/* 1*/ { BARCODE_CODE128, "123456ABCD", 0, 1, 123, "CODE128 10" },
/* 2*/ { BARCODE_GS1_128, "[01]09501101530003", 0, 1, 134, "GS1_128 (01)" },
};
int data_size = ARRAY_SIZE(data);
int i, length, ret;
struct zint_symbol *symbol;
clock_t start;
clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0;
clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print;
int comment_max = 0;
if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */
return;
}
for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment);
printf("Iterations %d\n", TEST_PERF_ITERATIONS);
for (i = 0; i < data_size; i++) {
int j;
if (index != -1 && i != index) continue;
diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0;
for (j = 0; j < TEST_PERF_ITERATIONS; j++) {
start = clock();
symbol = ZBarcode_Create();
diff_create += clock() - start;
assert_nonnull(symbol, "Symbol not created\n");
length = testUtilSetSymbol(symbol, data[i].symbology, DATA_MODE, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug);
start = clock();
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
diff_encode += clock() - start;
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
assert_equal(symbol->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);
start = clock();
ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/);
diff_buffer += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
symbol->output_options |= OUT_BUFFER_INTERMEDIATE;
start = clock();
ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/);
diff_buf_inter += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; // Undo
start = clock();
ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/);
diff_print += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile);
ZBarcode_Delete(symbol);
}
printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment,
TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create));
total_create += diff_create;
total_encode += diff_encode;
total_buffer += diff_buffer;
total_buf_inter += diff_buf_inter;
total_print += diff_print;
}
if (index == -1) {
printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals",
TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create));
}
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */
@ -852,6 +951,7 @@ int main(int argc, char *argv[]) {
{ "test_ean14_input", test_ean14_input, 1, 1, 1 }, { "test_ean14_input", test_ean14_input, 1, 1, 1 },
{ "test_dpd_input", test_dpd_input, 1, 1, 1 }, { "test_dpd_input", test_dpd_input, 1, 1, 1 },
{ "test_encode", test_encode, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 },
{ "test_perf", test_perf, 1, 0, 1 },
}; };
testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); testRun(argc, argv, funcs, ARRAY_SIZE(funcs));

View File

@ -31,6 +31,230 @@
#include "testcommon.h" #include "testcommon.h"
/* Original */
static int is_sane_orig(const char test_string[], const unsigned char source[], const int length) {
int i, j, lt = (int) strlen(test_string);
for (i = 0; i < length; i++) {
unsigned int latch = FALSE;
for (j = 0; j < lt; j++) {
if (source[i] == test_string[j]) {
latch = TRUE;
break;
}
}
if (!(latch)) {
return ZINT_ERROR_INVALID_DATA;
}
}
return 0;
}
static void test_is_sane(int index) {
struct item {
unsigned int flg;
char *data;
int length;
int ret;
char *orig_test;
};
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
struct item data[] = {
/* 0*/ { IS_SPC_F, " ", -1, 1, " " },
/* 1*/ { IS_SPC_F, "\000", 1, 0, " " },
/* 2*/ { IS_HSH_F, "#", -1, 1, "#" },
/* 3*/ { IS_HSH_F, " ", -1, 0, "#" },
/* 4*/ { IS_PLS_F, "+", -1, 1, "+" },
/* 5*/ { IS_PLS_F, " ", -1, 0, "+" },
/* 6*/ { IS_MNS_F, "-", -1, 1, "-" },
/* 7*/ { IS_MNS_F, " ", -1, 0, "-" },
/* 8*/ { IS_NUM_F, "0123456789", -1, 1, "0123456789" }, // NEON
/* 9*/ { IS_NUM_F, "0123456789 ", -1, 0, "0123456789" },
/* 10*/ { IS_NUM_F, "012345678A9", -1, 0, "0123456789" },
/* 11*/ { IS_UPO_F, "GHIJKLMNOPQRSTUVWYZ", -1, 1, "GHIJKLMNOPQRSTUVWYZ" },
/* 12*/ { IS_UPO_F, "FGHIJKLMNOPQRSTUVWYZ", -1, 0, "GHIJKLMNOPQRSTUVWYZ" },
/* 13*/ { IS_LWO_F, "ghijklmnopqrstuvwyz", -1, 1, "ghijklmnopqrstuvwyz" },
/* 14*/ { IS_LWO_F, "fghijklmnopqrstuvwyz", -1, 0, "ghijklmnopqrstuvwyz" },
/* 15*/ { IS_UHX_F, "ABCDEF", -1, 1, "ABCDEF" },
/* 16*/ { IS_UHX_F, "ABCDEf", -1, 0, "ABCDEF" },
/* 17*/ { IS_LHX_F, "abcdef", -1, 1, "abcdef" },
/* 18*/ { IS_LHX_F, "abcdeF", -1, 0, "abcdef" },
/* 19*/ { IS_UPR_F, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", -1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" },
/* 20*/ { IS_UPR_F, "ABCDEFGHIJKLMNOPQRSTUVWXYZ ", -1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" },
/* 21*/ { IS_UPR_F, "X", -1, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" },
/* 22*/ { IS_UPR_F, "x", -1, 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZ" },
/* 23*/ { IS_LWR_F, "abcdefghijklmnopqrstuvwxyz", -1, 1, "abcdefghijklmnopqrstuvwxyz" },
/* 24*/ { IS_LWR_F, "abcdefghijklmnopqrstuvwxyz ", -1, 0, "abcdefghijklmnopqrstuvwxyz" },
/* 25*/ { IS_LWR_F, "x", -1, 1, "abcdefghijklmnopqrstuvwxyz" },
/* 26*/ { IS_LWR_F, "X", -1, 0, "abcdefghijklmnopqrstuvwxyz" },
/* 27*/ { IS_UX__F, "X", -1, 1, "X" },
/* 28*/ { IS_UX__F, "x", -1, 0, "X" },
/* 29*/ { IS_LX__F, "x", -1, 1, "x" },
/* 30*/ { IS_LX__F, "X", -1, 0, "x" },
/* 31*/ { IS_C82_F, "!\"%&'()*,./:;<=>?_", -1, 1, "!\"%&'()*,./:;<=>?_" }, // CSET82 punctuation less "-+"
/* 32*/ { IS_C82_F, "!\"%&'()*,./:;<=>?_ ", -1, 0, "!\"%&'()*,./:;<=>?_" },
/* 33*/ { IS_C82_F, "-", -1, 0, "!\"%&'()*,./:;<=>?_" },
/* 34*/ { IS_C82_F, "$", -1, 0, "!\"%&'()*,./:;<=>?_" },
/* 35*/ { IS_SIL_F, ".$/%", -1, 1, ".$/%" }, // SILVER punctuation less " -+"
/* 36*/ { IS_SIL_F, ".$/% " , -1, 0, ".$/%" },
/* 37*/ { IS_SIL_F, "-", -1, 0, ".$/%" },
/* 38*/ { IS_CLI_F, "$:/.", -1, 1, "$:/." }, // CALCIUM INNER punctuation less "-+"
/* 39*/ { IS_CLI_F, "$:/. ", -1, 0, "$:/." },
/* 40*/ { IS_CLI_F, "+", -1, 0, "$:/." },
/* 41*/ { IS_ARS_F, "ABCDEFGHJKLMNPRSTUVWXYZ", -1, 1, "ABCDEFGHJKLMNPRSTUVWXYZ" }, // ARSENIC uppercase
/* 42*/ { IS_ARS_F, "ABCDEFGHJKLMNPRSTUVWXYZ ", -1, 0, "ABCDEFGHJKLMNPRSTUVWXYZ" },
/* 43*/ { IS_ARS_F, "I", -1, 0, "ABCDEFGHJKLMNPRSTUVWXYZ" },
/* 44*/ { IS_ARS_F, "O", -1, 0, "ABCDEFGHJKLMNPRSTUVWXYZ" },
/* 45*/ { IS_NUM_F | IS_UHX_F, "0123456789ABCDEF", -1, 1, "0123456789ABCDEF" }, // SSET
/* 46*/ { IS_NUM_F | IS_UHX_F, "0123456789ABCDEf", -1, 0, "0123456789ABCDEF" },
/* 47*/ { IS_NUM_F | IS_PLS_F, "0123456789+", -1, 1, "0123456789+" }, // SODIUM_PLS
/* 48*/ { IS_NUM_F | IS_PLS_F, "0123456789+-", -1, 0, "0123456789+" },
/* 49*/ { IS_NUM_F | IS_UX__F, "0123456789X", -1, 1, "0123456789X" }, // ISBNX_SANE
/* 50*/ { IS_NUM_F | IS_UX__F, "0123456789x", -1, 0, "0123456789X" },
/* 51*/ { IS_NUM_F | IS_UX__F | IS_LX__F | IS_PLS_F, "0123456789Xx+", -1, 1, "0123456789Xx+" }, // ISBNX_ADDON_SANE
/* 52*/ { IS_NUM_F | IS_UX__F | IS_LX__F | IS_PLS_F, "0123456789Xx+Y", -1, 0, "0123456789Xx+" },
/* 53*/ { IS_NUM_F | IS_MNS_F, "0123456789-", -1, 1, "0123456789-" }, // SODIUM_MNS
/* 54*/ { IS_NUM_F | IS_MNS_F, "0123456789-+", -1, 0, "0123456789-" },
/* 55*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz", -1, 1, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" }, // CSET82
/* 56*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, " ", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" },
/* 57*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "#", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" },
/* 58*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "$", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" },
/* 59*/ { IS_C82_F | IS_MNS_F | IS_PLS_F | IS_NUM_F | IS_UPR_F | IS_LWR_F, "@", -1, 0, "!\"%&'()*+,-./0123456789:;<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" },
/* 60*/ { IS_LWR_F | IS_C82_F | IS_PLS_F | IS_MNS_F | IS_SPC_F, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ ", -1, 1, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ " }, // IS_ISOIEC_F
/* 61*/ { IS_LWR_F | IS_C82_F | IS_PLS_F | IS_MNS_F | IS_SPC_F, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ #", -1, 0, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ " },
/* 62*/ { IS_LWR_F | IS_C82_F | IS_PLS_F | IS_MNS_F | IS_SPC_F, "$", -1, 0, "abcdefghijklmnopqrstuvwxyz!\"%&'()*+,-./:;<=>?_ " },
/* 63*/ { IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "-. $/+%", -1, 1, "" },
/* 64*/ { IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "-. $/!+%", -1, 0, "" },
/* 65*/ { IS_NUM_F | IS_UPR_F | IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%" }, // SILVER
/* 66*/ { IS_NUM_F | IS_UPR_F | IS_MNS_F | IS_SIL_F | IS_SPC_F | IS_PLS_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%a", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%" },
/* 67*/ { IS_NUM_F | IS_ARS_F, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ", -1, 1, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" }, // ARSENIC
/* 68*/ { IS_NUM_F | IS_ARS_F, "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ", -1, 0, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" },
/* 69*/ { IS_NUM_F | IS_ARS_F, "0123456789ABCDEFGHJKLMNPRSTUVWXYz", -1, 0, "0123456789ABCDEFGHJKLMNPRSTUVWXYZ" },
/* 70*/ { IS_NUM_F | IS_UPR_F | IS_LWR_F | IS_SPC_F | IS_HSH_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #" }, // GDSET
/* 71*/ { IS_NUM_F | IS_UPR_F | IS_LWR_F | IS_SPC_F | IS_HSH_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #!", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz #" },
/* 72*/ { IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F, "0123456789-$:/.+", -1, 1, "0123456789-$:/.+" }, // CALCIUM_INNER
/* 73*/ { IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F, "0123456789-$:/.+ ", -1, 0, "0123456789-$:/.+" },
/* 74*/ { IS_NUM_F | IS_MNS_F | IS_CLI_F | IS_PLS_F, "0123456789-$:/.+!", -1, 0, "0123456789-$:/.+" },
/* 75*/ { IS_NUM_F | IS_UPR_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, // KRSET
/* 76*/ { IS_NUM_F | IS_UPR_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYz", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" },
/* 77*/ { IS_NUM_F | IS_UPR_F | IS_SPC_F, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ", -1, 1, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " }, // RUBIDIUM
/* 78*/ { IS_NUM_F | IS_UPR_F | IS_SPC_F, "0123456789aBCDEFGHIJKLMNOPQRSTUVWXYZ ", -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " },
/* 79*/ { IS_NUM_F | IS_MNS_F | IS_UPR_F, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ", -1, 1, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ" }, // SHKASUTSET
/* 80*/ { IS_NUM_F | IS_MNS_F | IS_UPR_F, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYz", -1, 0, "1234567890-ABCDEFGHIJKLMNOPQRSTUVWXYZ" },
};
int data_size = ARRAY_SIZE(data);
int i, length, ret;
testStart("test_is_sane");
for (i = 0; i < data_size; i++) {
if (index != -1 && i != index) continue;
length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length;
ret = is_sane(data[i].flg, (const unsigned char *) data[i].data, length);
assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret);
if (data[i].orig_test[0]) {
int orig_ret = is_sane_orig(data[i].orig_test, (const unsigned char *) data[i].data, length);
if (orig_ret == 0) {
assert_nonzero(ret, "i:%d orig_ret %d, ret %d == 0\n", i, orig_ret, ret);
} else {
assert_zero(ret, "i:%d orig_ret %d, ret %d != 0\n", i, orig_ret, ret);
}
}
}
testFinish();
}
static void test_is_sane_lookup(int index) {
struct item {
char *test_string;
int test_length;
char *data;
int length;
int ret;
int posns[32];
};
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
struct item data[] = {
/* 0*/ { "1234567", -1, "7654321357", -1, 1, { 6, 5, 4, 3, 2, 1, 0, 2, 4, 6 } },
/* 1*/ { "1234567", -1, "76543213578", -1, 0, {0} },
};
int data_size = ARRAY_SIZE(data);
int i, length, ret;
int test_length;
int posns[32];
testStart("test_is_sane_lookup");
for (i = 0; i < data_size; i++) {
if (index != -1 && i != index) continue;
test_length = data[i].test_length == -1 ? (int) strlen(data[i].test_string) : data[i].test_length;
length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length;
ret = is_sane_lookup(data[i].test_string, test_length, (const unsigned char *) data[i].data, length, posns);
assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret);
if (ret) {
int j;
for (j = 0; j < length; j++) {
assert_equal(posns[j], data[i].posns[j], "i:%d posns[%d] %d != expected posns[%d] %d\n", i, j, posns[j], j, data[i].posns[j]);
}
}
}
testFinish();
}
static void test_is_valid_utf8(int index) {
struct item {
char *data;
int length;
int ret;
char *comment;
};
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
struct item data[] = {
/* 0*/ { "", -1, 1, "" },
/* 1*/ { "abcdefghijklmnopqrstuvwxyz", -1, 1, "" },
/* 2*/ { "éa", -1, 1, "" },
/* 3*/ { "a\000b", 3, 1, "Embedded nul" },
/* 4*/ { "\357\273\277a", -1, 1, "Bom" },
/* 5*/ { "a\xC2", -1, 0, "Missing 2nd byte" },
/* 6*/ { "a\200b", -1, 0, "Orphan continuation 0x80" },
/* 7*/ { "\300\201", -1, 0, "Overlong 0xC081" },
/* 8*/ { "\355\240\200", -1, 0, "Surrogate 0xEDA080" },
};
int data_size = ARRAY_SIZE(data);
int i, length, ret;
testStart("test_is_valid_utf8");
for (i = 0; i < data_size; i++) {
if (index != -1 && i != index) continue;
length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length;
ret = is_valid_utf8((const unsigned char *) data[i].data, length);
assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret);
}
testFinish();
}
static void test_utf8_to_unicode(int index, int debug) { static void test_utf8_to_unicode(int index, int debug) {
struct item { struct item {
@ -142,45 +366,6 @@ static void test_set_height(int index, int debug) {
testFinish(); testFinish();
} }
static void test_is_valid_utf8(int index) {
struct item {
char *data;
int length;
int ret;
char *comment;
};
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
struct item data[] = {
/* 0*/ { "", -1, 1, "" },
/* 1*/ { "abcdefghijklmnopqrstuvwxyz", -1, 1, "" },
/* 2*/ { "éa", -1, 1, "" },
/* 3*/ { "a\000b", 3, 1, "Embedded nul" },
/* 4*/ { "\357\273\277a", -1, 1, "Bom" },
/* 5*/ { "a\xC2", -1, 0, "Missing 2nd byte" },
/* 6*/ { "a\200b", -1, 0, "Orphan continuation 0x80" },
/* 7*/ { "\300\201", -1, 0, "Overlong 0xC081" },
/* 8*/ { "\355\240\200", -1, 0, "Surrogate 0xEDA080" },
};
int data_size = ARRAY_SIZE(data);
int i, length, ret;
testStart("test_is_valid_utf8");
for (i = 0; i < data_size; i++) {
if (index != -1 && i != index) continue;
length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length;
ret = is_valid_utf8((const unsigned char *) data[i].data, length);
assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret);
}
testFinish();
}
static void test_debug_test_codeword_dump_int(int index, int debug) { static void test_debug_test_codeword_dump_int(int index, int debug) {
struct item { struct item {
@ -217,9 +402,11 @@ static void test_debug_test_codeword_dump_int(int index, int debug) {
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */
{ "test_is_sane", test_is_sane, 1, 0, 0 },
{ "test_is_sane_lookup", test_is_sane_lookup, 1, 0, 0 },
{ "test_is_valid_utf8", test_is_valid_utf8, 1, 0, 0 },
{ "test_utf8_to_unicode", test_utf8_to_unicode, 1, 0, 1 }, { "test_utf8_to_unicode", test_utf8_to_unicode, 1, 0, 1 },
{ "test_set_height", test_set_height, 1, 0, 1 }, { "test_set_height", test_set_height, 1, 0, 1 },
{ "test_is_valid_utf8", test_is_valid_utf8, 1, 0, 0 },
{ "test_debug_test_codeword_dump_int", test_debug_test_codeword_dump_int, 1, 0, 1 }, { "test_debug_test_codeword_dump_int", test_debug_test_codeword_dump_int, 1, 0, 1 },
}; };

View File

@ -146,7 +146,7 @@ static void test_print(int index, int generate, int debug) {
ret = testUtilCmpBins(symbol->outfile, expected_file); ret = testUtilCmpBins(symbol->outfile, expected_file);
assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret); assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret);
assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile); if (index == -1) assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile);
} }
ZBarcode_Delete(symbol); ZBarcode_Delete(symbol);

View File

@ -62,7 +62,7 @@ static void test_csv(int index, int debug) {
assert_nonnull(fd, "fopen(%s) == NULL", csvfile); assert_nonnull(fd, "fopen(%s) == NULL", csvfile);
while (fgets(buffer, sizeof(buffer), fd) != NULL) { while (fgets(buffer, sizeof(buffer), fd) != NULL) {
char *b; const char *b;
struct zint_symbol *symbol; struct zint_symbol *symbol;
lc++; lc++;

View File

@ -501,7 +501,7 @@ static void test_cap_compliant_height() {
testStart("test_cap_compliant_height"); testStart("test_cap_compliant_height");
for (symbol_id = 1; symbol_id <= BARCODE_RMQR; symbol_id++) { for (symbol_id = 1; symbol_id <= BARCODE_LAST; symbol_id++) {
if (!ZBarcode_ValidID(symbol_id)) continue; if (!ZBarcode_ValidID(symbol_id)) continue;
ret = ZBarcode_Cap(symbol_id, ZINT_CAP_COMPLIANT_HEIGHT); ret = ZBarcode_Cap(symbol_id, ZINT_CAP_COMPLIANT_HEIGHT);

View File

@ -31,7 +31,7 @@
#include "testcommon.h" #include "testcommon.h"
STATIC_UNLESS_ZINT_TEST int quiet_zones(const struct zint_symbol *symbol, const int hide_text, STATIC_UNLESS_ZINT_TEST int out_quiet_zones(const struct zint_symbol *symbol, const int hide_text,
float *left, float *right, float *top, float *bottom); float *left, float *right, float *top, float *bottom);
static void test_quiet_zones(void) { static void test_quiet_zones(void) {
@ -42,11 +42,11 @@ static void test_quiet_zones(void) {
testStart("test_quiet_zones"); testStart("test_quiet_zones");
for (i = BARCODE_CODE11; i <= BARCODE_RMQR; i++) { for (i = 1; i <= BARCODE_LAST; i++) {
if (!ZBarcode_ValidID(i)) continue; if (!ZBarcode_ValidID(i)) continue;
symbol.symbology = i; symbol.symbology = i;
symbol.output_options = BARCODE_QUIET_ZONES; symbol.output_options = BARCODE_QUIET_ZONES;
ret = quiet_zones(&symbol, hide_text, &left, &right, &top, &bottom); ret = out_quiet_zones(&symbol, hide_text, &left, &right, &top, &bottom);
if (i != BARCODE_FLAT) { // Only one which isn't marked as done if (i != BARCODE_FLAT) { // Only one which isn't marked as done
assert_nonzero(ret, "i:%d %s not done\n", i, testUtilBarcodeName(i)); assert_nonzero(ret, "i:%d %s not done\n", i, testUtilBarcodeName(i));
} }

View File

@ -319,6 +319,107 @@ static void test_encode(int index, int generate, int debug) {
testFinish(); testFinish();
} }
#include <time.h>
#define TEST_PERF_ITER_MILLES 5
#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000)
#define TEST_PERF_TIME(arg) ((arg) * 1000.0 / CLOCKS_PER_SEC)
// Not a real test, just performance indicator
static void test_perf(int index, int debug) {
struct item {
int symbology;
int option_2;
char *data;
int ret;
int expected_rows;
int expected_width;
char *comment;
};
struct item data[] = {
/* 0*/ { BARCODE_PLESSEY, -1, "1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1", 0, 1, 1107, "PLESSEY 65" },
/* 1*/ { BARCODE_PLESSEY, -1, "123456ABCD", 0, 1, 227, "PLESSEY 10" },
/* 2*/ { BARCODE_MSI_PLESSEY, -1, "12345678901234567890123456789012345678901234567890123456789012345", 0, 1, 787, "MSI_PLESSEY 65" },
/* 3*/ { BARCODE_MSI_PLESSEY, -1, "1234567890", 0, 1, 127, "MSI_PLESSEY 10" },
};
int data_size = ARRAY_SIZE(data);
int i, length, ret;
struct zint_symbol *symbol;
clock_t start;
clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0;
clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print;
int comment_max = 0;
if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */
return;
}
for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment);
printf("Iterations %d\n", TEST_PERF_ITERATIONS);
for (i = 0; i < data_size; i++) {
int j;
if (index != -1 && i != index) continue;
diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0;
for (j = 0; j < TEST_PERF_ITERATIONS; j++) {
start = clock();
symbol = ZBarcode_Create();
diff_create += clock() - start;
assert_nonnull(symbol, "Symbol not created\n");
length = testUtilSetSymbol(symbol, data[i].symbology, DATA_MODE, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug);
start = clock();
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
diff_encode += clock() - start;
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
assert_equal(symbol->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);
start = clock();
ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/);
diff_buffer += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
symbol->output_options |= OUT_BUFFER_INTERMEDIATE;
start = clock();
ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/);
diff_buf_inter += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; // Undo
start = clock();
ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/);
diff_print += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile);
ZBarcode_Delete(symbol);
}
printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment,
TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create));
total_create += diff_create;
total_encode += diff_encode;
total_buffer += diff_buffer;
total_buf_inter += diff_buf_inter;
total_print += diff_print;
}
if (index == -1) {
printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals",
TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create));
}
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */
@ -326,6 +427,7 @@ int main(int argc, char *argv[]) {
{ "test_hrt", test_hrt, 1, 0, 1 }, { "test_hrt", test_hrt, 1, 0, 1 },
{ "test_input", test_input, 1, 0, 1 }, { "test_input", test_input, 1, 0, 1 },
{ "test_encode", test_encode, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 },
{ "test_perf", test_perf, 1, 0, 1 },
}; };
testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); testRun(argc, argv, funcs, ARRAY_SIZE(funcs));

View File

@ -385,6 +385,33 @@ static void test_wpng_error_handler(void) {
testFinish(); testFinish();
} }
// Check compliant height printable for max CODABLOCKF with 44 rows * ((62 cols) * 0.55 + 3)) = 1632.4
static void test_large_compliant_height(void) {
int ret;
struct zint_symbol *symbol = NULL;
const char pattern[] = { "1" };
const int codablockf_max = 2726;
char data_buf[2726 + 1];
testStart("test_large_compliant_height");
symbol = ZBarcode_Create();
assert_nonnull(symbol, "Symbol not created\n");
symbol->symbology = BARCODE_CODABLOCKF;
symbol->output_options |= COMPLIANT_HEIGHT;
testUtilStrCpyRepeat(data_buf, pattern, codablockf_max);
assert_equal(codablockf_max, (int) strlen(data_buf), "length %d != strlen(data_buf) %d\n", codablockf_max, (int) strlen(data_buf));
ret = ZBarcode_Encode_and_Print(symbol, (const unsigned char *) data_buf, codablockf_max, 0);
assert_zero(ret, "ZBarcode_Encode_and_Print ret %d != 0 (%s)\n", ret, symbol->errtxt);
assert_zero(remove(symbol->outfile), "remove(%s) != 0\n", symbol->outfile);
ZBarcode_Delete(symbol);
testFinish();
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */
@ -392,6 +419,7 @@ int main(int argc, char *argv[]) {
{ "test_print", test_print, 1, 1, 1 }, { "test_print", test_print, 1, 1, 1 },
{ "test_outfile", test_outfile, 0, 0, 0 }, { "test_outfile", test_outfile, 0, 0, 0 },
{ "test_wpng_error_handler", test_wpng_error_handler, 0, 0, 0 }, { "test_wpng_error_handler", test_wpng_error_handler, 0, 0, 0 },
{ "test_large_compliant_height", test_large_compliant_height, 0, 0, 0 },
}; };
testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); testRun(argc, argv, funcs, ARRAY_SIZE(funcs));

View File

@ -59,16 +59,18 @@ static void test_large(int index, int debug) {
/* 9*/ { BARCODE_RM4SCC, "1", 51, ZINT_ERROR_TOO_LONG, -1, -1 }, /* 9*/ { BARCODE_RM4SCC, "1", 51, ZINT_ERROR_TOO_LONG, -1, -1 },
/* 10*/ { BARCODE_JAPANPOST, "1", 20, 0, 3, 133 }, /* 10*/ { BARCODE_JAPANPOST, "1", 20, 0, 3, 133 },
/* 11*/ { BARCODE_JAPANPOST, "1", 21, ZINT_ERROR_TOO_LONG, -1, -1 }, /* 11*/ { BARCODE_JAPANPOST, "1", 21, ZINT_ERROR_TOO_LONG, -1, -1 },
/* 12*/ { BARCODE_KOREAPOST, "1", 6, 0, 1, 162 }, /* 12*/ { BARCODE_JAPANPOST, "A", 10, 0, 3, 133 },
/* 13*/ { BARCODE_KOREAPOST, "1", 7, ZINT_ERROR_TOO_LONG, -1, -1 }, /* 13*/ { BARCODE_JAPANPOST, "A", 11, ZINT_ERROR_TOO_LONG, -1, -1 },
/* 14*/ { BARCODE_PLANET, "1", 13, 0, 2, 143 }, /* 14*/ { BARCODE_KOREAPOST, "1", 6, 0, 1, 162 },
/* 15*/ { BARCODE_PLANET, "1", 14, ZINT_WARN_NONCOMPLIANT, 2, 153 }, /* 15*/ { BARCODE_KOREAPOST, "1", 7, ZINT_ERROR_TOO_LONG, -1, -1 },
/* 16*/ { BARCODE_PLANET, "1", 38, ZINT_WARN_NONCOMPLIANT, 2, 393 }, /* 16*/ { BARCODE_PLANET, "1", 13, 0, 2, 143 },
/* 17*/ { BARCODE_PLANET, "1", 39, ZINT_ERROR_TOO_LONG, -1, -1 }, /* 17*/ { BARCODE_PLANET, "1", 14, ZINT_WARN_NONCOMPLIANT, 2, 153 },
/* 18*/ { BARCODE_KIX, "1", 18, 0, 3, 143 }, /* 18*/ { BARCODE_PLANET, "1", 38, ZINT_WARN_NONCOMPLIANT, 2, 393 },
/* 19*/ { BARCODE_KIX, "1", 19, ZINT_ERROR_TOO_LONG, -1, -1 }, /* 19*/ { BARCODE_PLANET, "1", 39, ZINT_ERROR_TOO_LONG, -1, -1 },
/* 20*/ { BARCODE_DAFT, "D", 50, 0, 3, 99 }, /* 20*/ { BARCODE_KIX, "1", 18, 0, 3, 143 },
/* 21*/ { BARCODE_DAFT, "D", 51, ZINT_ERROR_TOO_LONG, -1, -1 }, /* 21*/ { BARCODE_KIX, "1", 19, ZINT_ERROR_TOO_LONG, -1, -1 },
/* 22*/ { BARCODE_DAFT, "D", 100, 0, 3, 199 },
/* 23*/ { BARCODE_DAFT, "D", 101, ZINT_ERROR_TOO_LONG, -1, -1 },
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, length, ret; int i, length, ret;
@ -237,27 +239,31 @@ static void test_input(int index, int debug) {
/* 17*/ { BARCODE_RM4SCC, -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, 3, 299, 8 }, /* 17*/ { BARCODE_RM4SCC, -1, 0, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, 3, 299, 8 },
/* 18*/ { BARCODE_RM4SCC, -1, 0, "a", 0, 3, 19, 8 }, // Converts to upper /* 18*/ { BARCODE_RM4SCC, -1, 0, "a", 0, 3, 19, 8 }, // Converts to upper
/* 19*/ { BARCODE_RM4SCC, -1, 0, ",", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, /* 19*/ { BARCODE_RM4SCC, -1, 0, ",", ZINT_ERROR_INVALID_DATA, -1, -1, -1 },
/* 20*/ { BARCODE_JAPANPOST, -1, 0, "1234567890-ABCDEFGH", 0, 3, 133, 8 }, /* 20*/ { BARCODE_JAPANPOST, -1, 0, "1234567890-ABCD", 0, 3, 133, 8 }, // 19 symbol chars
/* 21*/ { BARCODE_JAPANPOST, -1, 0, "a", 0, 3, 133, 8 }, // Converts to upper /* 21*/ { BARCODE_JAPANPOST, -1, 0, "1234567890-ABCD1", 0, 3, 133, 8 }, // 20 symbol chars
/* 22*/ { BARCODE_JAPANPOST, -1, 0, ",", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, /* 22*/ { BARCODE_JAPANPOST, -1, 0, "1234567890-ABCDE", ZINT_ERROR_TOO_LONG, -1, -1, -1 }, // 21 symbol chars
/* 23*/ { BARCODE_KOREAPOST, -1, 0, "123456", 0, 1, 167, 50 }, /* 23*/ { BARCODE_JAPANPOST, -1, 0, "1234567890-ABCD12", ZINT_ERROR_TOO_LONG, -1, -1, -1 }, // 21 symbol chars
/* 24*/ { BARCODE_KOREAPOST, -1, 0, "A", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, /* 24*/ { BARCODE_JAPANPOST, -1, 0, "1234567890ABCDE", 0, 3, 133, 8 }, // 20 symbol chars
/* 25*/ { BARCODE_PLANET, -1, 0, "12345678901", 0, 2, 123, 12 }, /* 25*/ { BARCODE_JAPANPOST, -1, 0, "a", 0, 3, 133, 8 }, // Converts to upper
/* 26*/ { BARCODE_PLANET, -1, 0, "1234567890123", 0, 2, 143, 12 }, /* 26*/ { BARCODE_JAPANPOST, -1, 0, ",", ZINT_ERROR_INVALID_DATA, -1, -1, -1 },
/* 27*/ { BARCODE_PLANET, -1, 0, "0", ZINT_WARN_NONCOMPLIANT, 2, 23, 12 }, /* 27*/ { BARCODE_KOREAPOST, -1, 0, "123456", 0, 1, 167, 50 },
/* 28*/ { BARCODE_PLANET, -1, 0, "1234567890", ZINT_WARN_NONCOMPLIANT, 2, 113, 12 }, /* 28*/ { BARCODE_KOREAPOST, -1, 0, "A", ZINT_ERROR_INVALID_DATA, -1, -1, -1 },
/* 29*/ { BARCODE_PLANET, -1, 0, "123456789012", ZINT_WARN_NONCOMPLIANT, 2, 133, 12 }, /* 29*/ { BARCODE_PLANET, -1, 0, "12345678901", 0, 2, 123, 12 },
/* 30*/ { BARCODE_PLANET, -1, 0, "12345678901234", ZINT_WARN_NONCOMPLIANT, 2, 153, 12 }, /* 30*/ { BARCODE_PLANET, -1, 0, "1234567890123", 0, 2, 143, 12 },
/* 31*/ { BARCODE_PLANET, -1, 0, "1234567890A", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, /* 31*/ { BARCODE_PLANET, -1, 0, "0", ZINT_WARN_NONCOMPLIANT, 2, 23, 12 },
/* 32*/ { BARCODE_KIX, -1, 0, "0123456789ABCDEFGH", 0, 3, 143, 8 }, /* 32*/ { BARCODE_PLANET, -1, 0, "1234567890", ZINT_WARN_NONCOMPLIANT, 2, 113, 12 },
/* 33*/ { BARCODE_KIX, -1, 0, "a", 0, 3, 7, 8 }, // Converts to upper /* 33*/ { BARCODE_PLANET, -1, 0, "123456789012", ZINT_WARN_NONCOMPLIANT, 2, 133, 12 },
/* 34*/ { BARCODE_KIX, -1, 0, ",", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, /* 34*/ { BARCODE_PLANET, -1, 0, "12345678901234", ZINT_WARN_NONCOMPLIANT, 2, 153, 12 },
/* 35*/ { BARCODE_DAFT, -1, 0, "DAFT", 0, 3, 7, 8 }, /* 35*/ { BARCODE_PLANET, -1, 0, "1234567890A", ZINT_ERROR_INVALID_DATA, -1, -1, -1 },
/* 36*/ { BARCODE_DAFT, -1, 0, "a", 0, 3, 1, 8 }, // Converts to upper /* 36*/ { BARCODE_KIX, -1, 0, "0123456789ABCDEFGH", 0, 3, 143, 8 },
/* 37*/ { BARCODE_DAFT, -1, 0, "B", ZINT_ERROR_INVALID_DATA, -1, -1, -1 }, /* 37*/ { BARCODE_KIX, -1, 0, "a", 0, 3, 7, 8 }, // Converts to upper
/* 38*/ { BARCODE_DAFT, -1, 1.9, "DAFT", 0, 3, 7, 2 }, /* 38*/ { BARCODE_KIX, -1, 0, ",", ZINT_ERROR_INVALID_DATA, -1, -1, -1 },
/* 39*/ { BARCODE_DAFT, 500, 0.9, "DAFT", 0, 3, 7, 2 }, // 50% ratio /* 39*/ { BARCODE_DAFT, -1, 0, "DAFT", 0, 3, 7, 8 },
/* 40*/ { BARCODE_DAFT, 500, 0.4, "DAFT", 0, 3, 7, 8 }, // 50% ratio /* 40*/ { BARCODE_DAFT, -1, 0, "a", 0, 3, 1, 8 }, // Converts to upper
/* 41*/ { BARCODE_DAFT, -1, 0, "B", ZINT_ERROR_INVALID_DATA, -1, -1, -1 },
/* 42*/ { BARCODE_DAFT, -1, 1.9, "DAFT", 0, 3, 7, 2 },
/* 43*/ { BARCODE_DAFT, 500, 0.9, "DAFT", 0, 3, 7, 2 }, // 50% ratio
/* 44*/ { BARCODE_DAFT, 500, 0.4, "DAFT", 0, 3, 7, 8 }, // 50% ratio
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, length, ret; int i, length, ret;
@ -329,60 +335,95 @@ static void test_encode(int index, int generate, int debug) {
"101010101010101010101010101010101010101010101010101010101010101010101010101" "101010101010101010101010101010101010101010101010101010101010101010101010101"
"000010100000100010001000100000101010100000100000100000101000100010001010001" "000010100000100010001000100000101010100000100000100000101000100010001010001"
}, },
/* 6*/ { BARCODE_JAPANPOST, "15400233-16-4-205", 0, 3, 133, "Zip/Barcode Manual p.6 1st example; verified manually against tec-it", /* 6*/ { BARCODE_RM4SCC, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, 3, 299, "Verified manually against tec-it",
"10000010100000101000001010000010100000101000001010001000100010001000100010001000100010001000100010001010000010100000101000001010000010100000101000100000101000001010000010100000101000001010000010100010001000100010001000100010001000100010001000101000001010000010100000101000001010000010100000101000001"
"10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"00000010100010001000101000100000101000100010100000000010100010001000101000100000101000100010100000000010100010001000101000100000101000100010100000000010100010001000101000100000101000100010100000000010100010001000101000100000101000100010100000000010100010001000101000100000101000100010100000101000001"
},
/* 7*/ { BARCODE_JAPANPOST, "15400233-16-4-205", 0, 3, 133, "Zip/Barcode Manual p.6 1st example; verified manually against tec-it",
"1000101000100010101000100000100000100010001010001010001000101000001010001000101000001000100010100000100010000010000010000010001010001" "1000101000100010101000100000100000100010001010001010001000101000001010001000101000001000100010100000100010000010000010000010001010001"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"1010101000100010100010100000100000101000101000101000001000101000100010001000100010001000101000100000100010001000001000001000100010101" "1010101000100010100010100000100000101000101000101000001000101000100010001000100010001000101000100000100010001000001000001000100010101"
}, },
/* 7*/ { BARCODE_JAPANPOST, "350110622-1A308", 0, 3, 133, "Zip/Barcode Manual p.6 2nd example; verified manually against tec-it", /* 8*/ { BARCODE_JAPANPOST, "350110622-1A308", 0, 3, 133, "Zip/Barcode Manual p.6 2nd example; verified manually against tec-it",
"1000001010100010100000101000101000100000001010100010100010001000101000001000100000001010100000100010000010000010000010000010100010001" "1000001010100010100000101000101000100000001010100010100010001000101000001000100000001010100000100010000010000010000010000010100010001"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"1010101000100010100000101000101000100000100010101000101000001000101000100000100000101000100000001010001000001000001000001000100010101" "1010101000100010100000101000101000100000100010101000101000001000101000100000100000101000100000001010001000001000001000001000100010101"
}, },
/* 8*/ { BARCODE_JAPANPOST, "12345671-2-3", 0, 3, 133, "Verified manually against tec-it", /* 9*/ { BARCODE_JAPANPOST, "12345671-2-3", 0, 3, 133, "Verified manually against tec-it",
"1000101000100010001010101000100010001010101000101000001000100010001000001010000010000010000010000010000010000010000010000010100010001" "1000101000100010001010101000100010001010101000101000001000100010001000001010000010000010000010000010000010000010000010000010100010001"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"1010101000101000101000100010100010100010001010101000001000101000001000101000001000001000001000001000001000001000001000001000100010101" "1010101000101000101000100010100010100010001010101000001000101000001000101000001000001000001000001000001000001000001000001000100010101"
}, },
/* 9*/ { BARCODE_KOREAPOST, "010230", 0, 1, 167, "Verified manually against tec-it", /* 10*/ { BARCODE_JAPANPOST, "1234567BCDEFG", 0, 3, 133, "Verified manually against tec-it",
"1000101000100010001010101000100010001010101000001000101000001000100010001000001010001000101000001000100010001000001010000010101000001"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"1010101000101000101000100010100010100010001010100000101000100000101000100000101000100000100010100000100010100000100010001000100010101"
},
/* 11*/ { BARCODE_JAPANPOST, "8901234HIJKLM", 0, 3, 133, "Verified manually against tec-it",
"1000100010001010100000101000100010001010101000001000101000001000100010001000001010000010100000000010101000000010100010000010100000001"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"1010001010001010100000101000101000101000100010100000001010100000001010100000001010100000100000100000101000100000101000001000000010101"
},
/* 12*/ { BARCODE_JAPANPOST, "0987654NOPQRS", 0, 3, 133, "Verified manually against tec-it",
"1000100000001010100010101000001010100010101000000010001010000010101000000010100010000010001010000010101000000010100010000010100000001"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"1010100000001010001010001010100010100010100010100000101000100000100010100000100010100000100010100000001010100000001010001000001000101"
},
/* 13*/ { BARCODE_JAPANPOST, "3210987TUVWXY", 0, 3, 133, "Verified manually against tec-it",
"1000001010100010101000100000001010100010101000000010001010100000100000100000101000100000100010100000001010100000101000000010000010001"
"1010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"1010101000101000101000100000001010001010001010100000001010001000100000001000101000001000101000001000101000001000100010001000100000101"
},
/* 14*/ { BARCODE_KOREAPOST, "010230", 0, 1, 167, "Verified manually against tec-it",
"10001000100000000000100010000000000010001000100000001000000010001000100010001000100000000000100000000001000100010001000100010001000000000001000000010001000000010001000" "10001000100000000000100010000000000010001000100000001000000010001000100010001000100000000000100000000001000100010001000100010001000000000001000000010001000000010001000"
}, },
/* 10*/ { BARCODE_KOREAPOST, "923457", 0, 1, 168, "Verified manually against tec-it", /* 15*/ { BARCODE_KOREAPOST, "923457", 0, 1, 168, "Verified manually against tec-it",
"000010001000100000001000100000001000000010001000000010001000000010001000100000000000100010001000000010000000100010001000100010000000100000001000100010001000000000001000" "000010001000100000001000100000001000000010001000000010001000000010001000100000000000100010001000000010000000100010001000100010000000100000001000100010001000000000001000"
}, },
/* 11*/ { BARCODE_PLANET, "4012345235636", 0, 2, 143, "USPS Publication 197 (2004) Exhibit 4; verified manually against tec-it", /* 16*/ { BARCODE_PLANET, "4012345235636", 0, 2, 143, "USPS Publication 197 (2004) Exhibit 4; verified manually against tec-it",
"10100010100000001010101010100000101000100010100000101000101000100010001010100010001010000010100010001010000010101010000010100000101010000010101" "10100010100000001010101010100000101000100010100000101000101000100010001010100010001010000010100010001010000010101010000010100000101010000010101"
"10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
}, },
/* 12*/ { BARCODE_PLANET, "40123452356", 0, 2, 123, "Verified manually against tec-it", /* 17*/ { BARCODE_PLANET, "40123452356", 0, 2, 123, "Verified manually against tec-it",
"101000101000000010101010101000001010001000101000001010001010001000100010101000100010100000101000100010100000101010001000101" "101000101000000010101010101000001010001000101000001010001010001000100010101000100010100000101000100010100000101010001000101"
"101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
}, },
/* 13*/ { BARCODE_PLANET, "5020140235635", 0, 2, 143, "USPS Publication 197 (2004) Exhibit 6; verified manually against tec-it", /* 18*/ { BARCODE_PLANET, "5020140235635", 0, 2, 143, "USPS Publication 197 (2004) Exhibit 6; verified manually against tec-it",
"10100010001000001010101010001000000010101010101000001000101000000010101010100010001010000010100010001010000010101010000010100010001010001010001" "10100010001000001010101010001000000010101010101000001000101000000010101010100010001010000010100010001010000010101010000010100010001010001010001"
"10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
}, },
/* 14*/ { BARCODE_KIX, "2500GG30250", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 1", /* 19*/ { BARCODE_KIX, "2500GG30250", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 1",
"000010100000101000001010000010100010100000101000000010100000101000001010000010100000101" "000010100000101000001010000010100010100000101000000010100000101000001010000010100000101"
"101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"001010001010000000001010000010101000100010001000100000100000101000101000101000000000101" "001010001010000000001010000010101000100010001000100000100000101000101000101000000000101"
}, },
/* 15*/ { BARCODE_KIX, "2130VA80430", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 2", /* 20*/ { BARCODE_KIX, "2130VA80430", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 2",
"000010100000101000001010000010101010000000100010001000100000101000001010000010100000101" "000010100000101000001010000010101010000000100010001000100000101000001010000010100000101"
"101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"001010000010001010000010000010100010001010001000001010000000101010001000100000100000101" "001010000010001010000010000010100010001010001000001010000000101010001000100000100000101"
}, },
/* 16*/ { BARCODE_KIX, "1231GF156X2", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 3", /* 21*/ { BARCODE_KIX, "1231GF156X2", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 3",
"000010100000101000001010000010100010100000101000000010100000101000100010101000000000101" "000010100000101000001010000010100010100000101000000010100000101000100010101000000000101"
"101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"001000100010100010000010001000101000100010000010001000101010000000001010100000100010100" "001000100010100010000010001000101000100010000010001000101010000000001010100000100010100"
}, },
/* 17*/ { BARCODE_KIX, "1231FZ13Xhs", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 4", /* 22*/ { BARCODE_KIX, "1231FZ13Xhs", 0, 3, 87, "PostNL Handleiding KIX code Section 2.1 Example 4",
"000010100000101000001010000010100010100010100000000010100000101010100000001010001000100" "000010100000101000001010000010100010100010100000000010100000101010100000001010001000100"
"101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" "101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"001000100010100010000010001000101000001010100000001000101000001010000010101000001000100" "001000100010100010000010001000101000001010100000001000101000001010000010101000001000100"
}, },
/* 18*/ { BARCODE_DAFT, "DAFTTFADFATDTATFT", 0, 3, 33, "Verified manually against tec-it", /* 23*/ { BARCODE_KIX, "1234567890ABCDEFGH", 0, 3, 143, "Verified manually against tec-it",
"00001010000010100000101000001010000010100010001000100010001000100010001000001010001000100010001000101000001010000010100000101000001010000010100"
"10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"00100010001010001000001010001000101000000000101000100010001010001000001000001010100010001010000000001010001000100010100010000010100010001010000"
},
/* 24*/ { BARCODE_KIX, "IJKLMNOPQRSTUVWXYZ", 0, 3, 143, "Verified manually against tec-it",
"10000010100000101000001010000010100000101000001010001000100010001000100010001000100010001000100010100000101000001010000010100000101000001010000"
"10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101"
"00001010001000100010100010000010100010001010000000001010001000100010100010000010100010001010000000001010001000100010100010000010100010001010000"
},
/* 25*/ { BARCODE_DAFT, "DAFTTFADFATDTATFT", 0, 3, 33, "Verified manually against tec-it",
"001010000010100010100000001000100" "001010000010100010100000001000100"
"101010101010101010101010101010101" "101010101010101010101010101010101"
"100010000010001010000010000000100" "100010000010001010000010000000100"
@ -445,6 +486,106 @@ static void test_encode(int index, int generate, int debug) {
testFinish(); testFinish();
} }
#include <time.h>
#define TEST_PERF_ITER_MILLES 10
#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000)
#define TEST_PERF_TIME(arg) ((arg) * 1000.0 / CLOCKS_PER_SEC)
// Not a real test, just performance indicator
static void test_perf(int index, int debug) {
struct item {
int symbology;
int option_2;
char *data;
int ret;
int expected_rows;
int expected_width;
char *comment;
};
struct item data[] = {
/* 0*/ { BARCODE_POSTNET, -1, "12345678901", 0, 2, 123, "POSTNET 11" },
/* 1*/ { BARCODE_PLANET, -1, "1234567890123", 0, 2, 143, "PLANET 13" },
/* 2*/ { BARCODE_KOREAPOST, -1, "123456", 0, 1, 167, "KOREAPOST 6" },
};
int data_size = ARRAY_SIZE(data);
int i, length, ret;
struct zint_symbol *symbol;
clock_t start;
clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0;
clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print;
int comment_max = 0;
if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */
return;
}
for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment);
printf("Iterations %d\n", TEST_PERF_ITERATIONS);
for (i = 0; i < data_size; i++) {
int j;
if (index != -1 && i != index) continue;
diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0;
for (j = 0; j < TEST_PERF_ITERATIONS; j++) {
start = clock();
symbol = ZBarcode_Create();
diff_create += clock() - start;
assert_nonnull(symbol, "Symbol not created\n");
length = testUtilSetSymbol(symbol, data[i].symbology, DATA_MODE, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug);
start = clock();
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
diff_encode += clock() - start;
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
assert_equal(symbol->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);
start = clock();
ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/);
diff_buffer += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
symbol->output_options |= OUT_BUFFER_INTERMEDIATE;
start = clock();
ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/);
diff_buf_inter += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; // Undo
start = clock();
ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/);
diff_print += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile);
ZBarcode_Delete(symbol);
}
printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment,
TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create));
total_create += diff_create;
total_encode += diff_encode;
total_buffer += diff_buffer;
total_buf_inter += diff_buf_inter;
total_print += diff_print;
}
if (index == -1) {
printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals",
TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create));
}
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */
@ -453,6 +594,7 @@ int main(int argc, char *argv[]) {
{ "test_japanpost", test_japanpost, 1, 0, 1 }, { "test_japanpost", test_japanpost, 1, 0, 1 },
{ "test_input", test_input, 1, 0, 1 }, { "test_input", test_input, 1, 0, 1 },
{ "test_encode", test_encode, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 },
{ "test_perf", test_perf, 1, 0, 1 },
}; };
testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); testRun(argc, argv, funcs, ARRAY_SIZE(funcs));

View File

@ -2518,7 +2518,9 @@ static void test_height(int index, int generate, int debug) {
#include <time.h> #include <time.h>
#define TEST_PERF_ITERATIONS 1000 #define TEST_PERF_ITER_MILLES 1
#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000)
#define TEST_PERF_TIME(arg) (((arg) * 1000.0) / CLOCKS_PER_SEC)
// Not a real test, just performance indicator for scaling // Not a real test, just performance indicator for scaling
static void test_perf_scale(int index, int debug) { static void test_perf_scale(int index, int debug) {
@ -2547,28 +2549,38 @@ static void test_perf_scale(int index, int debug) {
"HIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234567" "HIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234567"
"890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcde" "890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcde"
"fghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO", "fghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO",
0, 40, 307, "960 chars, text/numeric" }, 0, 40, 307, "PDF417 960 chars, text/numeric, 1.3" },
/* 1*/ { BARCODE_POSTNET, -1, -1, BARCODE_QUIET_ZONES, -1, -1, 0, 1.1, "12345", 0, 2, 63, "" }, /* 1*/ { BARCODE_POSTNET, -1, -1, BARCODE_QUIET_ZONES, -1, -1, 0, 1.1, "12345", 0, 2, 63, "POSTNET 5 chars, quiet zones, 1.1" },
/* 2*/ { BARCODE_ITF14, -1, 4, BARCODE_BIND, -1, -1, 61.8, 3.1, "12345", 0, 1, 135, "" }, /* 2*/ { BARCODE_ITF14, -1, 4, BARCODE_BIND, -1, -1, 61.8, 3.1, "12345", 0, 1, 135, "ITF14 bind 4, height 61.8, 3.1" },
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, length, ret; int i, length, ret;
struct zint_symbol *symbol;
clock_t start, total_encode = 0, total_buffer = 0, diff_encode, diff_buffer; clock_t start;
clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0;
clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print;
int comment_max = 0;
if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */ if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */
return; return;
} }
for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment);
printf("Iterations %d\n", TEST_PERF_ITERATIONS);
for (i = 0; i < data_size; i++) { for (i = 0; i < data_size; i++) {
int j; int j;
if (index != -1 && i != index) continue; if (index != -1 && i != index) continue;
diff_encode = diff_buffer = 0; diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0;
for (j = 0; j < TEST_PERF_ITERATIONS; j++) { for (j = 0; j < TEST_PERF_ITERATIONS; j++) {
struct zint_symbol *symbol = ZBarcode_Create(); start = clock();
symbol = ZBarcode_Create();
diff_create += clock() - start;
assert_nonnull(symbol, "Symbol not created\n"); assert_nonnull(symbol, "Symbol not created\n");
length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, data[i].option_1, data[i].option_2, -1, data[i].output_options, data[i].data, -1, debug); length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, data[i].option_1, data[i].option_2, -1, data[i].output_options, data[i].data, -1, debug);
@ -2592,16 +2604,34 @@ static void test_perf_scale(int index, int debug) {
diff_buffer += clock() - start; diff_buffer += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt); assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
symbol->output_options |= OUT_BUFFER_INTERMEDIATE;
start = clock();
ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/);
diff_buf_inter += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; // Undo
start = clock();
ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/);
diff_print += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile);
ZBarcode_Delete(symbol); ZBarcode_Delete(symbol);
} }
printf("%s: diff_encode %gms, diff_buffer %gms\n", data[i].comment, diff_encode * 1000.0 / CLOCKS_PER_SEC, diff_buffer * 1000.0 / CLOCKS_PER_SEC); printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment,
TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create));
total_create += diff_create;
total_encode += diff_encode; total_encode += diff_encode;
total_buffer += diff_buffer; total_buffer += diff_buffer;
total_buf_inter += diff_buf_inter;
total_print += diff_print;
} }
if (index != -1) { if (index == -1) {
printf("totals: encode %gms, buffer %gms\n", total_encode * 1000.0 / CLOCKS_PER_SEC, total_buffer * 1000.0 / CLOCKS_PER_SEC); printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals",
TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create));
} }
} }

View File

@ -34,28 +34,28 @@
// Print out the log/alog tables for "backend/reedsol_logs.h" // Print out the log/alog tables for "backend/reedsol_logs.h"
static void print_logs(const char *name, int logmod, unsigned int *logt, unsigned int *alog, int u16, int last) { static void print_logs(const char *name, int logmod, unsigned int *logt, unsigned int *alog, int u16, int last) {
int i; int i;
const char *type = u16 ? "short" : "char"; const char *type = u16 ? "short" : "char";
const char *format = u16 ? " 0x%04X," : " 0x%02X,"; const char *format = u16 ? " 0x%04X," : " 0x%02X,";
printf("static const unsigned %s logt_%s[%d] = {", type, name, logmod + 1); printf("static const unsigned %s logt_%s[%d] = {", type, name, logmod + 1);
for (i = 0; i < logmod + 1; i++) { for (i = 0; i < logmod + 1; i++) {
if (i % 16 == 0) printf("\n "); if (i % 16 == 0) printf("\n ");
printf(format, i ? logt[i] : 0); printf(format, i ? logt[i] : 0);
} }
printf("\n};\n"); printf("\n};\n");
printf("static const unsigned %s alog_%s[%d] = {", type, name, logmod * 2); printf("static const unsigned %s alog_%s[%d] = {", type, name, logmod * 2);
for (i = 0; i < logmod; i++) { for (i = 0; i < logmod; i++) {
if (i % 16 == 0) printf("\n "); if (i % 16 == 0) printf("\n ");
printf(format, alog[i]); printf(format, alog[i]);
} }
// Double antilog table // Double antilog table
for (i = 0; i < logmod; i++) { for (i = 0; i < logmod; i++) {
if (i % 16 == 0) printf("\n "); if (i % 16 == 0) printf("\n ");
printf(format, alog[i]); printf(format, alog[i]);
} }
printf("\n};\n"); printf("\n};\n");
if (!last) { if (!last) {
printf("\n"); printf("\n");
} }

View File

@ -330,6 +330,62 @@ static void test_fuzz(int index, int debug) {
testFinish(); testFinish();
} }
static char TeleTable[128][16] = {
{ "31313131" }, { "1131313111" }, { "33313111" }, { "1111313131" },
{ "3111313111" }, { "11333131" }, { "13133131" }, { "111111313111" },
{ "31333111" }, { "1131113131" }, { "33113131" }, { "1111333111" },
{ "3111113131" }, { "1113133111" }, { "1311133111" }, { "111111113131" },
{ "3131113111" }, { "11313331" }, { "333331" }, { "111131113111" },
{ "31113331" }, { "1133113111" }, { "1313113111" }, { "1111113331" },
{ "31131331" }, { "113111113111" }, { "3311113111" }, { "1111131331" },
{ "311111113111" }, { "1113111331" }, { "1311111331" }, { "11111111113111" },
{ "31313311" }, { "1131311131" }, { "33311131" }, { "1111313311" },
{ "3111311131" }, { "11333311" }, { "13133311" }, { "111111311131" },
{ "31331131" }, { "1131113311" }, { "33113311" }, { "1111331131" },
{ "3111113311" }, { "1113131131" }, { "1311131131" }, { "111111113311" },
{ "3131111131" }, { "1131131311" }, { "33131311" }, { "111131111131" },
{ "3111131311" }, { "1133111131" }, { "1313111131" }, { "111111131311" },
{ "3113111311" }, { "113111111131" }, { "3311111131" }, { "111113111311" },
{ "311111111131" }, { "111311111311" }, { "131111111311" }, { "11111111111131" },
{ "3131311111" }, { "11313133" }, { "333133" }, { "111131311111" },
{ "31113133" }, { "1133311111" }, { "1313311111" }, { "1111113133" },
{ "313333" }, { "113111311111" }, { "3311311111" }, { "11113333" },
{ "311111311111" }, { "11131333" }, { "13111333" }, { "11111111311111" },
{ "31311133" }, { "1131331111" }, { "33331111" }, { "1111311133" },
{ "3111331111" }, { "11331133" }, { "13131133" }, { "111111331111" },
{ "3113131111" }, { "1131111133" }, { "33111133" }, { "111113131111" },
{ "3111111133" }, { "111311131111" }, { "131111131111" }, { "111111111133" },
{ "31311313" }, { "113131111111" }, { "3331111111" }, { "1111311313" },
{ "311131111111" }, { "11331313" }, { "13131313" }, { "11111131111111" },
{ "3133111111" }, { "1131111313" }, { "33111313" }, { "111133111111" },
{ "3111111313" }, { "111313111111" }, { "131113111111" }, { "111111111313" },
{ "313111111111" }, { "1131131113" }, { "33131113" }, { "11113111111111" },
{ "3111131113" }, { "113311111111" }, { "131311111111" }, { "111111131113" },
{ "3113111113" }, { "11311111111111" }, { "331111111111" }, { "111113111113" },
{ "31111111111111" }, { "111311111113" }, { "131111111113" },
{'1','1','1','1','1','1','1','1','1','1','1','1','1','1','1','1'},
};
// Dummy to generate lengths table
static void test_generate_lens(int generate) {
int i;
if (!generate) {
return;
}
printf("static const char TeleLens[128] = {");
for (i = 0; i < 127; i++) {
if ((i % 16) == 0) {
printf("\n %2d,", (int) strlen(TeleTable[i]));
} else {
printf(" %2d,", (int) strlen(TeleTable[i]));
}
}
printf(" 16\n};\n");
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */
@ -338,6 +394,7 @@ int main(int argc, char *argv[]) {
{ "test_input", test_input, 1, 0, 1 }, { "test_input", test_input, 1, 0, 1 },
{ "test_encode", test_encode, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 },
{ "test_fuzz", test_fuzz, 1, 0, 1 }, { "test_fuzz", test_fuzz, 1, 0, 1 },
{ "test_generate_lens", test_generate_lens, 0, 1, 0 },
}; };
testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); testRun(argc, argv, funcs, ARRAY_SIZE(funcs));

View File

@ -92,7 +92,7 @@ static void test_pixel_plot(int index, int debug) {
char *tif = "out.tif"; char *tif = "out.tif";
char data_buf[65536]; char data_buf[ZINT_MAX_DATA_LEN * 2 + 1];
int have_tiffinfo = testUtilHaveTiffInfo(); int have_tiffinfo = testUtilHaveTiffInfo();
int have_identify = testUtilHaveIdentify(); int have_identify = testUtilHaveIdentify();

View File

@ -266,150 +266,154 @@ static void test_upca_input(int index, int debug) {
testFinish(); testFinish();
} }
static void test_eanx_input(int index, int debug) { static void test_eanx_input(int index, int generate, int debug) {
struct item { struct item {
int symbology; int symbology;
char *data; char *data;
int ret; int ret;
char *ret_errtxt;
char *comment;
}; };
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
struct item data[] = { struct item data[] = {
/* 0*/ { BARCODE_EANX, "123456789012", 0 }, /* 0*/ { BARCODE_EANX, "123456789012", 0, "", "" },
/* 1*/ { BARCODE_EANX, "12345678901A", ZINT_ERROR_INVALID_DATA }, /* 1*/ { BARCODE_EANX, "12345678901A", ZINT_ERROR_INVALID_DATA, "Error 284: Invalid character in data (digits and \"+\" only)", "" },
/* 2*/ { BARCODE_EANX, "12345678901", 0 }, /* 2*/ { BARCODE_EANX, "12345678901", 0, "", "" },
/* 3*/ { BARCODE_EANX, "1234567890128", 0 }, // EANX accepts CHK (treated as such if no leading zeroes required) /* 3*/ { BARCODE_EANX, "1234567890128", 0, "", "EANX accepts CHK (treated as such if no leading zeroes required)" },
/* 4*/ { BARCODE_EANX, "1234567890120", ZINT_ERROR_INVALID_CHECK }, /* 4*/ { BARCODE_EANX, "1234567890120", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '0', expecting '8'", "" },
/* 5*/ { BARCODE_EANX, "123456789012+1", 0 }, /* 5*/ { BARCODE_EANX, "123456789012+1", 0, "", "" },
/* 6*/ { BARCODE_EANX, "1234567890128+1", 0 }, /* 6*/ { BARCODE_EANX, "1234567890128+1", 0, "", "" },
/* 7*/ { BARCODE_EANX, "1234567890121+1", ZINT_ERROR_INVALID_CHECK }, /* 7*/ { BARCODE_EANX, "1234567890121+1", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '1', expecting '8'", "" },
/* 8*/ { BARCODE_EANX, "123456789012+12", 0 }, /* 8*/ { BARCODE_EANX, "123456789012+12", 0, "", "" },
/* 9*/ { BARCODE_EANX, "1234567890128+12", 0 }, /* 9*/ { BARCODE_EANX, "1234567890128+12", 0, "", "" },
/* 10*/ { BARCODE_EANX, "1234567890122+12", ZINT_ERROR_INVALID_CHECK }, /* 10*/ { BARCODE_EANX, "1234567890122+12", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '2', expecting '8'", "" },
/* 11*/ { BARCODE_EANX, "12345678901234+12", ZINT_ERROR_TOO_LONG }, /* 11*/ { BARCODE_EANX, "12345678901234+12", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/* 12*/ { BARCODE_EANX, "123456789012345+12", ZINT_ERROR_TOO_LONG }, /* 12*/ { BARCODE_EANX, "123456789012345+12", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/* 13*/ { BARCODE_EANX, "1234567890123456+12", ZINT_ERROR_TOO_LONG }, /* 13*/ { BARCODE_EANX, "1234567890123456+12", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/* 14*/ { BARCODE_EANX, "123456789012+123", 0 }, /* 14*/ { BARCODE_EANX, "123456789012+123", 0, "", "" },
/* 15*/ { BARCODE_EANX, "1234567890128+123", 0 }, /* 15*/ { BARCODE_EANX, "1234567890128+123", 0, "", "" },
/* 16*/ { BARCODE_EANX, "1234567890123+123", ZINT_ERROR_INVALID_CHECK }, /* 16*/ { BARCODE_EANX, "1234567890123+123", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '3', expecting '8'", "" },
/* 17*/ { BARCODE_EANX, "12345678901234+123", ZINT_ERROR_TOO_LONG }, /* 17*/ { BARCODE_EANX, "12345678901234+123", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/* 18*/ { BARCODE_EANX, "123456789012345+123", ZINT_ERROR_TOO_LONG }, /* 18*/ { BARCODE_EANX, "123456789012345+123", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/* 19*/ { BARCODE_EANX, "123456789012+1234", 0 }, /* 19*/ { BARCODE_EANX, "123456789012+1234", 0, "", "" },
/* 20*/ { BARCODE_EANX, "1234567890128+1234", 0 }, /* 20*/ { BARCODE_EANX, "1234567890128+1234", 0, "", "" },
/* 21*/ { BARCODE_EANX, "1234567890124+1234", ZINT_ERROR_INVALID_CHECK }, /* 21*/ { BARCODE_EANX, "1234567890124+1234", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '4', expecting '8'", "" },
/* 22*/ { BARCODE_EANX, "12345678901234+1234", ZINT_ERROR_TOO_LONG }, /* 22*/ { BARCODE_EANX, "12345678901234+1234", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/* 23*/ { BARCODE_EANX, "123456789012+12345", 0 }, /* 23*/ { BARCODE_EANX, "123456789012+12345", 0, "", "" },
/* 24*/ { BARCODE_EANX, "1234567890128+12345", 0 }, /* 24*/ { BARCODE_EANX, "1234567890128+12345", 0, "", "" },
/* 25*/ { BARCODE_EANX, "12345678901234+12345", ZINT_ERROR_TOO_LONG }, /* 25*/ { BARCODE_EANX, "12345678901234+12345", ZINT_ERROR_TOO_LONG, "Error 283: Input too long (19 character maximum)", "" },
/* 26*/ { BARCODE_EANX, "1234567890125+12345", ZINT_ERROR_INVALID_CHECK }, /* 26*/ { BARCODE_EANX, "1234567890125+12345", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '5', expecting '8'", "" },
/* 27*/ { BARCODE_EANX, "123456789012+123456", ZINT_ERROR_TOO_LONG }, /* 27*/ { BARCODE_EANX, "123456789012+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 28*/ { BARCODE_EANX, "1234567890128+123456", ZINT_ERROR_TOO_LONG }, /* 28*/ { BARCODE_EANX, "1234567890128+123456", ZINT_ERROR_TOO_LONG, "Error 283: Input too long (19 character maximum)", "" },
/* 29*/ { BARCODE_EANX, "12345678901+123456", ZINT_ERROR_TOO_LONG }, /* 29*/ { BARCODE_EANX, "12345678901+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 30*/ { BARCODE_EANX, "12345678901+1234567", ZINT_ERROR_TOO_LONG }, /* 30*/ { BARCODE_EANX, "12345678901+1234567", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 31*/ { BARCODE_EANX, "1234567890+123456", ZINT_ERROR_TOO_LONG }, /* 31*/ { BARCODE_EANX, "1234567890+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 32*/ { BARCODE_EANX, "1234567890+1234567", ZINT_ERROR_TOO_LONG }, /* 32*/ { BARCODE_EANX, "1234567890+1234567", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 33*/ { BARCODE_EANX, "123456789+123456", ZINT_ERROR_TOO_LONG }, /* 33*/ { BARCODE_EANX, "123456789+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 34*/ { BARCODE_EANX, "123456789+1234567", ZINT_ERROR_TOO_LONG }, /* 34*/ { BARCODE_EANX, "123456789+1234567", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 35*/ { BARCODE_EANX, "12345678+123456", ZINT_ERROR_TOO_LONG }, /* 35*/ { BARCODE_EANX, "12345678+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 36*/ { BARCODE_EANX, "1234567+123456", ZINT_ERROR_TOO_LONG }, // EAN-8 /* 36*/ { BARCODE_EANX, "1234567+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "EAN-8" },
/* 37*/ { BARCODE_EANX, "123456+123456", ZINT_ERROR_TOO_LONG }, /* 37*/ { BARCODE_EANX, "123456+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 38*/ { BARCODE_EANX, "12345+123456", ZINT_ERROR_TOO_LONG }, /* 38*/ { BARCODE_EANX, "12345+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 39*/ { BARCODE_EANX, "1234+123456", ZINT_ERROR_TOO_LONG }, /* 39*/ { BARCODE_EANX, "1234+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 40*/ { BARCODE_EANX, "123+123456", ZINT_ERROR_TOO_LONG }, /* 40*/ { BARCODE_EANX, "123+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 41*/ { BARCODE_EANX, "12+123456", ZINT_ERROR_TOO_LONG }, /* 41*/ { BARCODE_EANX, "12+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 42*/ { BARCODE_EANX, "1+123456", ZINT_ERROR_TOO_LONG }, /* 42*/ { BARCODE_EANX, "1+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 43*/ { BARCODE_EANX, "1+12345678901234", ZINT_ERROR_TOO_LONG }, /* 43*/ { BARCODE_EANX, "1+12345678901234", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 44*/ { BARCODE_EANX, "1+12345", 0 }, /* 44*/ { BARCODE_EANX, "1+12345", 0, "", "" },
/* 45*/ { BARCODE_EANX, "1+", 0 }, // EAN-2 /* 45*/ { BARCODE_EANX, "1+", 0, "", "EAN-2" },
/* 46*/ { BARCODE_EANX, "+1", 0 }, // EAN-8 /* 46*/ { BARCODE_EANX, "+1", 0, "", "EAN-8" },
/* 47*/ { BARCODE_EANX, "+", 0 }, // EAN-2 /* 47*/ { BARCODE_EANX, "+", 0, "", "EAN-2" },
/* 48*/ { BARCODE_EANX, "1", 0 }, // EAN-2 /* 48*/ { BARCODE_EANX, "1", 0, "", "EAN-2" },
/* 49*/ { BARCODE_EANX, "12", 0 }, // EAN-2 /* 49*/ { BARCODE_EANX, "12", 0, "", "EAN-2" },
/* 50*/ { BARCODE_EANX, "123", 0 }, // EAN-5 /* 50*/ { BARCODE_EANX, "123", 0, "", "EAN-5" },
/* 51*/ { BARCODE_EANX, "12345678901234", ZINT_ERROR_TOO_LONG }, /* 51*/ { BARCODE_EANX, "12345678901234", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/* 52*/ { BARCODE_EANX, "1234567890123A", ZINT_ERROR_INVALID_DATA }, /* 52*/ { BARCODE_EANX, "1234567890123A", ZINT_ERROR_INVALID_DATA, "Error 284: Invalid character in data (digits and \"+\" only)", "" },
/* 53*/ { BARCODE_EANX, "123456789012345", ZINT_ERROR_TOO_LONG }, /* 53*/ { BARCODE_EANX, "123456789012345", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/* 54*/ { BARCODE_EANX, "12345678901234A", ZINT_ERROR_INVALID_DATA }, /* 54*/ { BARCODE_EANX, "12345678901234A", ZINT_ERROR_INVALID_DATA, "Error 284: Invalid character in data (digits and \"+\" only)", "" },
/* 55*/ { BARCODE_EANX, "1234567890123456", ZINT_ERROR_TOO_LONG }, /* 55*/ { BARCODE_EANX, "1234567890123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/* 56*/ { BARCODE_EANX, "12345678901234567", ZINT_ERROR_TOO_LONG }, /* 56*/ { BARCODE_EANX, "12345678901234567", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/* 57*/ { BARCODE_EANX, "123456789012345678", ZINT_ERROR_TOO_LONG }, /* 57*/ { BARCODE_EANX, "123456789012345678", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/* 58*/ { BARCODE_EANX, "1234567890123456789", ZINT_ERROR_TOO_LONG }, /* 58*/ { BARCODE_EANX, "1234567890123456789", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/* 59*/ { BARCODE_EANX_CHK, "1234567890128", 0 }, /* 59*/ { BARCODE_EANX_CHK, "1234567890128", 0, "", "" },
/* 60*/ { BARCODE_EANX_CHK, "1234567890126", ZINT_ERROR_INVALID_CHECK }, /* 60*/ { BARCODE_EANX_CHK, "1234567890126", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '6', expecting '8'", "" },
/* 61*/ { BARCODE_EANX_CHK, "123456789012A", ZINT_ERROR_INVALID_DATA }, /* 61*/ { BARCODE_EANX_CHK, "123456789012A", ZINT_ERROR_INVALID_DATA, "Error 284: Invalid character in data (digits and \"+\" only)", "" },
/* 62*/ { BARCODE_EANX_CHK, "123456789012", 0 }, // Note: this is "0123456789012" with '2' happening to be the correct check digit /* 62*/ { BARCODE_EANX_CHK, "123456789012", 0, "", "Note: this is '0123456789012' with '2' happening to be the correct check digit" },
/* 63*/ { BARCODE_EANX_CHK, "123456789013", ZINT_ERROR_INVALID_CHECK }, /* 63*/ { BARCODE_EANX_CHK, "123456789013", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '3', expecting '2'", "" },
/* 64*/ { BARCODE_EANX_CHK, "12345678901", ZINT_ERROR_INVALID_CHECK }, /* 64*/ { BARCODE_EANX_CHK, "12345678901", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '1', expecting '5'", "" },
/* 65*/ { BARCODE_EANX_CHK, "12345678905", 0 }, /* 65*/ { BARCODE_EANX_CHK, "12345678905", 0, "", "" },
/* 66*/ { BARCODE_EANX_CHK, "1234567890", ZINT_ERROR_INVALID_CHECK }, /* 66*/ { BARCODE_EANX_CHK, "1234567890", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '0', expecting '5'", "" },
/* 67*/ { BARCODE_EANX_CHK, "123456789", ZINT_ERROR_INVALID_CHECK }, /* 67*/ { BARCODE_EANX_CHK, "123456789", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '9', expecting '4'", "" },
/* 68*/ { BARCODE_EANX_CHK, "12345678", ZINT_ERROR_INVALID_CHECK }, // EAN-8 /* 68*/ { BARCODE_EANX_CHK, "12345678", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '8', expecting '0'", "EAN-8" },
/* 69*/ { BARCODE_EANX_CHK, "1234567", ZINT_ERROR_INVALID_CHECK }, /* 69*/ { BARCODE_EANX_CHK, "1234567", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '7', expecting '5'", "" },
/* 70*/ { BARCODE_EANX_CHK, "123456", ZINT_ERROR_INVALID_CHECK }, /* 70*/ { BARCODE_EANX_CHK, "123456", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '6', expecting '7'", "" },
/* 71*/ { BARCODE_EANX_CHK, "12345", 0 }, // EAN-5 /* 71*/ { BARCODE_EANX_CHK, "12345", 0, "", "EAN-5" },
/* 72*/ { BARCODE_EANX_CHK, "1234", 0 }, /* 72*/ { BARCODE_EANX_CHK, "1234", 0, "", "" },
/* 73*/ { BARCODE_EANX_CHK, "123", 0 }, /* 73*/ { BARCODE_EANX_CHK, "123", 0, "", "" },
/* 74*/ { BARCODE_EANX_CHK, "12", 0 }, // EAN-2 /* 74*/ { BARCODE_EANX_CHK, "12", 0, "", "EAN-2" },
/* 75*/ { BARCODE_EANX_CHK, "1", 0 }, /* 75*/ { BARCODE_EANX_CHK, "1", 0, "", "" },
/* 76*/ { BARCODE_EANX_CHK, "123456789012+1", 0 }, /* 76*/ { BARCODE_EANX_CHK, "123456789012+1", 0, "", "" },
/* 77*/ { BARCODE_EANX_CHK, "1234567890128+1", 0 }, /* 77*/ { BARCODE_EANX_CHK, "1234567890128+1", 0, "", "" },
/* 78*/ { BARCODE_EANX_CHK, "1234567890127+1", ZINT_ERROR_INVALID_CHECK }, /* 78*/ { BARCODE_EANX_CHK, "1234567890127+1", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '7', expecting '8'", "" },
/* 79*/ { BARCODE_EANX_CHK, "123456789012+12", 0 }, /* 79*/ { BARCODE_EANX_CHK, "123456789012+12", 0, "", "" },
/* 80*/ { BARCODE_EANX_CHK, "1234567890128+12", 0 }, /* 80*/ { BARCODE_EANX_CHK, "1234567890128+12", 0, "", "" },
/* 81*/ { BARCODE_EANX_CHK, "1234567890129+12", ZINT_ERROR_INVALID_CHECK }, /* 81*/ { BARCODE_EANX_CHK, "1234567890129+12", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '9', expecting '8'", "" },
/* 82*/ { BARCODE_EANX_CHK, "123456789012+123", 0 }, /* 82*/ { BARCODE_EANX_CHK, "123456789012+123", 0, "", "" },
/* 83*/ { BARCODE_EANX_CHK, "1234567890128+123", 0 }, /* 83*/ { BARCODE_EANX_CHK, "1234567890128+123", 0, "", "" },
/* 84*/ { BARCODE_EANX_CHK, "1234567890120+1234", ZINT_ERROR_INVALID_CHECK }, /* 84*/ { BARCODE_EANX_CHK, "1234567890120+1234", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '0', expecting '8'", "" },
/* 85*/ { BARCODE_EANX_CHK, "123456789012+1234", 0 }, /* 85*/ { BARCODE_EANX_CHK, "123456789012+1234", 0, "", "" },
/* 86*/ { BARCODE_EANX_CHK, "1234567890128+1234", 0 }, /* 86*/ { BARCODE_EANX_CHK, "1234567890128+1234", 0, "", "" },
/* 87*/ { BARCODE_EANX_CHK, "1234567890121+1234", ZINT_ERROR_INVALID_CHECK }, /* 87*/ { BARCODE_EANX_CHK, "1234567890121+1234", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '1', expecting '8'", "" },
/* 88*/ { BARCODE_EANX_CHK, "123456789012+12345", 0 }, /* 88*/ { BARCODE_EANX_CHK, "123456789012+12345", 0, "", "" },
/* 89*/ { BARCODE_EANX_CHK, "1234567890128+12345", 0 }, /* 89*/ { BARCODE_EANX_CHK, "1234567890128+12345", 0, "", "" },
/* 90*/ { BARCODE_EANX_CHK, "1234567890122+12345", ZINT_ERROR_INVALID_CHECK }, /* 90*/ { BARCODE_EANX_CHK, "1234567890122+12345", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '2', expecting '8'", "" },
/* 91*/ { BARCODE_EANX_CHK, "1234567890122+1234A", ZINT_ERROR_INVALID_DATA }, /* 91*/ { BARCODE_EANX_CHK, "1234567890122+1234A", ZINT_ERROR_INVALID_DATA, "Error 284: Invalid character in data (digits and \"+\" only)", "" },
/* 92*/ { BARCODE_EANX_CHK, "123456789012+123456", ZINT_ERROR_TOO_LONG }, /* 92*/ { BARCODE_EANX_CHK, "123456789012+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 93*/ { BARCODE_EANX_CHK, "123456789012+12345A", ZINT_ERROR_INVALID_DATA }, /* 93*/ { BARCODE_EANX_CHK, "123456789012+12345A", ZINT_ERROR_INVALID_DATA, "Error 284: Invalid character in data (digits and \"+\" only)", "" },
/* 94*/ { BARCODE_EANX_CHK, "1234567890128+123456", ZINT_ERROR_TOO_LONG }, /* 94*/ { BARCODE_EANX_CHK, "1234567890128+123456", ZINT_ERROR_TOO_LONG, "Error 283: Input too long (19 character maximum)", "" },
/* 95*/ { BARCODE_EANX_CHK, "12345678901+123456", ZINT_ERROR_TOO_LONG }, /* 95*/ { BARCODE_EANX_CHK, "12345678901+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 96*/ { BARCODE_EANX_CHK, "12345678901+1234567", ZINT_ERROR_TOO_LONG }, /* 96*/ { BARCODE_EANX_CHK, "12345678901+1234567", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 97*/ { BARCODE_EANX_CHK, "12345678901+12345", ZINT_ERROR_INVALID_CHECK }, /* 97*/ { BARCODE_EANX_CHK, "12345678901+12345", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '1', expecting '5'", "" },
/* 98*/ { BARCODE_EANX_CHK, "1234567890+12345", ZINT_ERROR_INVALID_CHECK }, /* 98*/ { BARCODE_EANX_CHK, "1234567890+12345", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '0', expecting '5'", "" },
/* 99*/ { BARCODE_EANX_CHK, "1234567890+123456", ZINT_ERROR_TOO_LONG }, /* 99*/ { BARCODE_EANX_CHK, "1234567890+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/*100*/ { BARCODE_EANX_CHK, "123456789+12345", ZINT_ERROR_INVALID_CHECK }, /*100*/ { BARCODE_EANX_CHK, "123456789+12345", ZINT_ERROR_INVALID_CHECK, "Error 275: Invalid check digit '9', expecting '4'", "" },
/*101*/ { BARCODE_EANX_CHK, "12345678+12345", ZINT_ERROR_INVALID_CHECK }, // EAN-8 /*101*/ { BARCODE_EANX_CHK, "12345678+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '8', expecting '0'", "EAN-8" },
/*102*/ { BARCODE_EANX_CHK, "12345670+12345", 0 }, /*102*/ { BARCODE_EANX_CHK, "12345670+12345", 0, "", "" },
/*103*/ { BARCODE_EANX_CHK, "1234567+12345", ZINT_ERROR_INVALID_CHECK }, /*103*/ { BARCODE_EANX_CHK, "1234567+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '7', expecting '5'", "" },
/*104*/ { BARCODE_EANX_CHK, "1234565+12345", 0 }, /*104*/ { BARCODE_EANX_CHK, "1234565+12345", 0, "", "" },
/*105*/ { BARCODE_EANX_CHK, "123456+12345", ZINT_ERROR_INVALID_CHECK }, /*105*/ { BARCODE_EANX_CHK, "123456+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '6', expecting '7'", "" },
/*106*/ { BARCODE_EANX_CHK, "123457+12345", 0 }, /*106*/ { BARCODE_EANX_CHK, "123457+12345", 0, "", "" },
/*107*/ { BARCODE_EANX_CHK, "12345+12345", ZINT_ERROR_INVALID_CHECK }, /*107*/ { BARCODE_EANX_CHK, "12345+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '5', expecting '8'", "" },
/*108*/ { BARCODE_EANX_CHK, "12348+12345", 0 }, /*108*/ { BARCODE_EANX_CHK, "12348+12345", 0, "", "" },
/*109*/ { BARCODE_EANX_CHK, "1234+12345", ZINT_ERROR_INVALID_CHECK }, /*109*/ { BARCODE_EANX_CHK, "1234+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '4', expecting '6'", "" },
/*110*/ { BARCODE_EANX_CHK, "1236+12345", 0 }, /*110*/ { BARCODE_EANX_CHK, "1236+12345", 0, "", "" },
/*111*/ { BARCODE_EANX_CHK, "123+12345", 0 }, // 3 happens to be correct check digit /*111*/ { BARCODE_EANX_CHK, "123+12345", 0, "", "3 happens to be correct check digit" },
/*112*/ { BARCODE_EANX_CHK, "124+12345", ZINT_ERROR_INVALID_CHECK }, /*112*/ { BARCODE_EANX_CHK, "124+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '4', expecting '3'", "" },
/*113*/ { BARCODE_EANX_CHK, "12+12345", ZINT_ERROR_INVALID_CHECK }, /*113*/ { BARCODE_EANX_CHK, "12+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '2', expecting '7'", "" },
/*114*/ { BARCODE_EANX_CHK, "17+12345", 0 }, /*114*/ { BARCODE_EANX_CHK, "17+12345", 0, "", "" },
/*115*/ { BARCODE_EANX_CHK, "1+12345", ZINT_ERROR_INVALID_CHECK }, /*115*/ { BARCODE_EANX_CHK, "1+12345", ZINT_ERROR_INVALID_CHECK, "Error 276: Invalid check digit '1', expecting '0'", "" },
/*116*/ { BARCODE_EANX_CHK, "0+12345", 0 }, /*116*/ { BARCODE_EANX_CHK, "0+12345", 0, "", "" },
/*117*/ { BARCODE_EANX_CHK, "0+123456", ZINT_ERROR_TOO_LONG }, /*117*/ { BARCODE_EANX_CHK, "0+123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/*118*/ { BARCODE_EANX_CHK, "1+12345678901234", ZINT_ERROR_TOO_LONG }, /*118*/ { BARCODE_EANX_CHK, "1+12345678901234", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/*119*/ { BARCODE_EANX_CHK, "0+12345678901234", ZINT_ERROR_TOO_LONG }, /*119*/ { BARCODE_EANX_CHK, "0+12345678901234", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (5 character maximum for add-on)", "" },
/*120*/ { BARCODE_EANX_CHK, "1+", 0 }, // EAN-2 /*120*/ { BARCODE_EANX_CHK, "1+", 0, "", "EAN-2" },
/*121*/ { BARCODE_EANX_CHK, "+1", 0 }, // EAN-8 /*121*/ { BARCODE_EANX_CHK, "+1", 0, "", "EAN-8" },
/*122*/ { BARCODE_EANX_CHK, "+", 0 }, // EAN-2 /*122*/ { BARCODE_EANX_CHK, "+", 0, "", "EAN-2" },
/*123*/ { BARCODE_EANX_CHK, "12345678901234", ZINT_ERROR_TOO_LONG }, /*123*/ { BARCODE_EANX_CHK, "12345678901234", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/*124*/ { BARCODE_EANX_CHK, "1234567890123A", ZINT_ERROR_INVALID_DATA }, /*124*/ { BARCODE_EANX_CHK, "1234567890123A", ZINT_ERROR_INVALID_DATA, "Error 284: Invalid character in data (digits and \"+\" only)", "" },
/*125*/ { BARCODE_EANX_CHK, "123456789012345", ZINT_ERROR_TOO_LONG }, /*125*/ { BARCODE_EANX_CHK, "123456789012345", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/*126*/ { BARCODE_EANX_CHK, "1234567890123456", ZINT_ERROR_TOO_LONG }, /*126*/ { BARCODE_EANX_CHK, "1234567890123456", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/*127*/ { BARCODE_EANX_CHK, "12345678901234567", ZINT_ERROR_TOO_LONG }, /*127*/ { BARCODE_EANX_CHK, "12345678901234567", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/*128*/ { BARCODE_EANX_CHK, "123456789012345678", ZINT_ERROR_TOO_LONG }, /*128*/ { BARCODE_EANX_CHK, "123456789012345678", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
/*129*/ { BARCODE_EANX_CHK, "1234567890123456789", ZINT_ERROR_TOO_LONG }, /*129*/ { BARCODE_EANX_CHK, "1234567890123456789", ZINT_ERROR_TOO_LONG, "Error 294: Input too long (13 character maximum)", "" },
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, length, ret; int i, length, ret;
struct zint_symbol *symbol; struct zint_symbol *symbol;
char errtxt_escaped[256];
testStart("test_eanx_input"); testStart("test_eanx_input");
for (i = 0; i < data_size; i++) { for (i = 0; i < data_size; i++) {
@ -422,7 +426,16 @@ static void test_eanx_input(int index, int debug) {
length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug);
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
assert_equal(ret, data[i].ret, "i:%d ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
if (generate) {
printf(" /*%3d*/ { %s, \"%s\", %s, \"%s\", \"%s\" },\n",
i, testUtilBarcodeName(data[i].symbology), data[i].data, testUtilErrorName(data[i].ret),
testUtilEscape(symbol->errtxt, (int) strlen(symbol->errtxt), errtxt_escaped, sizeof(errtxt_escaped)),
data[i].comment);
} else {
assert_equal(ret, data[i].ret, "i:%d ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
assert_zero(strcmp(symbol->errtxt, data[i].ret_errtxt), "i:%d errtxt %s != %s\n", i, symbol->errtxt, data[i].ret_errtxt);
}
ZBarcode_Delete(symbol); ZBarcode_Delete(symbol);
} }
@ -430,125 +443,129 @@ static void test_eanx_input(int index, int debug) {
testFinish(); testFinish();
} }
static void test_isbn_input(int index, int debug) { static void test_isbn_input(int index, int generate, int debug) {
struct item { struct item {
char *data; char *data;
int ret_encode; int ret_encode;
int ret_vector; int ret_vector;
char *ret_errtxt;
char *comment;
}; };
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
struct item data[] = { struct item data[] = {
/* 0*/ { "0", 0, 0 }, // Left zero-padded if < 10 chars /* 0*/ { "0", 0, 0, "", "Left zero-padded if < 10 chars" },
/* 1*/ { "1", ZINT_ERROR_INVALID_CHECK, -1 }, /* 1*/ { "1", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '1', expecting '0'", "" },
/* 2*/ { "X", ZINT_ERROR_INVALID_CHECK, -1 }, /* 2*/ { "X", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit 'X', expecting '0'", "" },
/* 3*/ { "12", ZINT_ERROR_INVALID_CHECK, -1 }, /* 3*/ { "12", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '2', expecting '9'", "" },
/* 4*/ { "19", 0, 0, }, /* 4*/ { "19", 0, 0, "", "" },
/* 5*/ { "X9", ZINT_ERROR_INVALID_DATA, -1 }, /* 5*/ { "X9", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 6*/ { "123", ZINT_ERROR_INVALID_CHECK, -1 }, /* 6*/ { "123", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '3', expecting '4'", "" },
/* 7*/ { "124", 0, 0, }, /* 7*/ { "124", 0, 0, "", "" },
/* 8*/ { "1X4", ZINT_ERROR_INVALID_DATA, -1 }, /* 8*/ { "1X4", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 9*/ { "1234", ZINT_ERROR_INVALID_CHECK, -1 }, /* 9*/ { "1234", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '4', expecting '6'", "" },
/* 10*/ { "1236", 0, 0, }, /* 10*/ { "1236", 0, 0, "", "" },
/* 11*/ { "12X6", ZINT_ERROR_INVALID_DATA, -1 }, /* 11*/ { "12X6", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 12*/ { "12345", ZINT_ERROR_INVALID_CHECK, -1 }, /* 12*/ { "12345", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '5', expecting '3'", "" },
/* 13*/ { "12343", 0, 0, }, /* 13*/ { "12343", 0, 0, "", "" },
/* 14*/ { "123X3", ZINT_ERROR_INVALID_DATA, -1 }, /* 14*/ { "123X3", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 15*/ { "123456", ZINT_ERROR_INVALID_CHECK, -1 }, /* 15*/ { "123456", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '6', expecting '5'", "" },
/* 16*/ { "123455", 0, 0, }, /* 16*/ { "123455", 0, 0, "", "" },
/* 17*/ { "1234X5", ZINT_ERROR_INVALID_DATA, -1 }, /* 17*/ { "1234X5", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 18*/ { "1234567", ZINT_ERROR_INVALID_CHECK, -1 }, /* 18*/ { "1234567", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '7', expecting '0'", "" },
/* 19*/ { "1234560", 0, 0, }, /* 19*/ { "1234560", 0, 0, "", "" },
/* 20*/ { "12345X0", ZINT_ERROR_INVALID_DATA, -1 }, /* 20*/ { "12345X0", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 21*/ { "12345678", ZINT_ERROR_INVALID_CHECK, -1 }, /* 21*/ { "12345678", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '8', expecting '9'", "" },
/* 22*/ { "12345679", 0, 0 }, // 9 is correct check digit /* 22*/ { "12345679", 0, 0, "", "9 is correct check digit" },
/* 23*/ { "98765434", 0, 0 }, // 4 is correct check digit /* 23*/ { "98765434", 0, 0, "", "4 is correct check digit" },
/* 24*/ { "123456X9", ZINT_ERROR_INVALID_DATA, -1 }, /* 24*/ { "123456X9", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 25*/ { "123456789", 0, 0 }, /* 25*/ { "123456789", 0, 0, "", "" },
/* 26*/ { "340013817", ZINT_ERROR_INVALID_CHECK, -1 }, /* 26*/ { "340013817", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '7', expecting '8'", "" },
/* 27*/ { "340013818", 0, 0 }, // 8 is correct check digit /* 27*/ { "340013818", 0, 0, "", "8 is correct check digit" },
/* 28*/ { "902888455", 0, 0 }, // 5 is correct check digit /* 28*/ { "902888455", 0, 0, "", "5 is correct check digit" },
/* 29*/ { "9028884X5", ZINT_ERROR_INVALID_DATA, -1 }, /* 29*/ { "9028884X5", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 30*/ { "0123456789", 0, 0 }, /* 30*/ { "0123456789", 0, 0, "", "" },
/* 31*/ { "1234567890", ZINT_ERROR_INVALID_CHECK, -1 }, /* 31*/ { "1234567890", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid ISBN check digit '0', expecting 'X'", "" },
/* 32*/ { "123456789X", 0, 0 }, // X is correct check digit /* 32*/ { "123456789X", 0, 0, "", "X is correct check digit" },
/* 33*/ { "123456789x", 0, 0 }, // x is correct check digit /* 33*/ { "123456789x", 0, 0, "", "x is correct check digit" },
/* 34*/ { "8175257660", 0, 0 }, // 0 is correct check digit /* 34*/ { "8175257660", 0, 0, "", "0 is correct check digit" },
/* 35*/ { "0590764845", 0, 0 }, // 5 is correct check digit /* 35*/ { "0590764845", 0, 0, "", "5 is correct check digit" },
/* 36*/ { "0906495741", 0, 0 }, // 1 is correct check digit /* 36*/ { "0906495741", 0, 0, "", "1 is correct check digit" },
/* 37*/ { "0140430016", 0, 0 }, // 6 is correct check digit /* 37*/ { "0140430016", 0, 0, "", "6 is correct check digit" },
/* 38*/ { "0571086187", 0, 0 }, // 7 is correct check digit /* 38*/ { "0571086187", 0, 0, "", "7 is correct check digit" },
/* 39*/ { "0486600882", 0, 0 }, // 2 is correct check digit /* 39*/ { "0486600882", 0, 0, "", "2 is correct check digit" },
/* 40*/ { "04866008X2", ZINT_ERROR_INVALID_DATA, -1 }, /* 40*/ { "04866008X2", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 41*/ { "123456789A", ZINT_ERROR_INVALID_DATA, -1 }, /* 41*/ { "123456789A", ZINT_ERROR_INVALID_DATA, -1, "Error 285: Invalid character in data (digits, \"X\" and \"+\" only)", "" },
/* 42*/ { "12345678901", ZINT_ERROR_TOO_LONG, -1 }, /* 42*/ { "12345678901", ZINT_ERROR_TOO_LONG, -1, "Error 278: Input wrong length (9, 10, or 13 characters only)", "" },
/* 43*/ { "1234567890A", ZINT_ERROR_INVALID_DATA, -1 }, /* 43*/ { "1234567890A", ZINT_ERROR_INVALID_DATA, -1, "Error 285: Invalid character in data (digits, \"X\" and \"+\" only)", "" },
/* 44*/ { "123456789012", ZINT_ERROR_TOO_LONG, -1 }, /* 44*/ { "123456789012", ZINT_ERROR_TOO_LONG, -1, "Error 278: Input wrong length (9, 10, or 13 characters only)", "" },
/* 45*/ { "12345678901", ZINT_ERROR_TOO_LONG, -1 }, /* 45*/ { "12345678901", ZINT_ERROR_TOO_LONG, -1, "Error 278: Input wrong length (9, 10, or 13 characters only)", "" },
/* 46*/ { "123456789012", ZINT_ERROR_TOO_LONG, -1 }, /* 46*/ { "123456789012", ZINT_ERROR_TOO_LONG, -1, "Error 278: Input wrong length (9, 10, or 13 characters only)", "" },
/* 47*/ { "1234567890123", ZINT_ERROR_INVALID_DATA, -1 }, /* 47*/ { "1234567890123", ZINT_ERROR_INVALID_DATA, -1, "Error 279: Invalid ISBN (must begin with \"978\" or \"979\")", "" },
/* 48*/ { "9784567890123", ZINT_ERROR_INVALID_CHECK, -1 }, /* 48*/ { "9784567890123", ZINT_ERROR_INVALID_CHECK, -1, "Error 280: Invalid ISBN check digit '3', expecting '0'", "" },
/* 49*/ { "9784567890120", 0, 0 }, // 0 is correct check digit /* 49*/ { "9784567890120", 0, 0, "", "0 is correct check digit" },
/* 50*/ { "9783161484100", 0, 0 }, // 0 is correct check digit /* 50*/ { "9783161484100", 0, 0, "", "0 is correct check digit" },
/* 51*/ { "9781846688225", 0, 0 }, // 5 is correct check digit /* 51*/ { "9781846688225", 0, 0, "", "5 is correct check digit" },
/* 52*/ { "9781847657954", 0, 0 }, // 4 is correct check digit /* 52*/ { "9781847657954", 0, 0, "", "4 is correct check digit" },
/* 53*/ { "9781846688188", 0, 0 }, // 8 is correct check digit /* 53*/ { "9781846688188", 0, 0, "", "8 is correct check digit" },
/* 54*/ { "9781847659293", 0, 0 }, // 3 is correct check digit /* 54*/ { "9781847659293", 0, 0, "", "3 is correct check digit" },
/* 55*/ { "97845678901201", ZINT_ERROR_TOO_LONG, -1 }, /* 55*/ { "97845678901201", ZINT_ERROR_TOO_LONG, -1, "Error 294: Input too long (13 character maximum)", "" },
/* 56*/ { "978456789012012", ZINT_ERROR_TOO_LONG, -1 }, /* 56*/ { "978456789012012", ZINT_ERROR_TOO_LONG, -1, "Error 294: Input too long (13 character maximum)", "" },
/* 57*/ { "3954994+12", 0, 0 }, /* 57*/ { "3954994+12", 0, 0, "", "" },
/* 58*/ { "3954994+1X", ZINT_ERROR_INVALID_DATA, -1 }, /* 58*/ { "3954994+1X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" },
/* 59*/ { "39549X4+12", ZINT_ERROR_INVALID_DATA, -1 }, /* 59*/ { "39549X4+12", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 60*/ { "3954994+12345", 0, 0 }, /* 60*/ { "3954994+12345", 0, 0, "", "" },
/* 61*/ { "3954994+1234X", ZINT_ERROR_INVALID_DATA, -1 }, /* 61*/ { "3954994+1234X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" },
/* 62*/ { "39549X4+12345", ZINT_ERROR_INVALID_DATA, -1 }, /* 62*/ { "39549X4+12345", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 63*/ { "3954994+123456", ZINT_ERROR_TOO_LONG, -1 }, /* 63*/ { "3954994+123456", ZINT_ERROR_TOO_LONG, -1, "Error 294: Input too long (5 character maximum for add-on)", "" },
/* 64*/ { "3954994+", 0, 0 }, /* 64*/ { "3954994+", 0, 0, "", "" },
/* 65*/ { "3954X94+", ZINT_ERROR_INVALID_DATA, -1 }, /* 65*/ { "3954X94+", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 66*/ { "61954993+1", 0, 0 }, /* 66*/ { "61954993+1", 0, 0, "", "" },
/* 67*/ { "61954993+X", ZINT_ERROR_INVALID_DATA, -1 }, /* 67*/ { "61954993+X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" },
/* 68*/ { "619549X3+1", ZINT_ERROR_INVALID_DATA, -1 }, /* 68*/ { "619549X3+1", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 69*/ { "61954992+123", ZINT_ERROR_INVALID_CHECK, -1 }, /* 69*/ { "61954992+123", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '2', expecting '3'", "" },
/* 70*/ { "61954993+123", 0, 0 }, /* 70*/ { "61954993+123", 0, 0, "", "" },
/* 71*/ { "61954993+12X", ZINT_ERROR_INVALID_DATA, -1 }, /* 71*/ { "61954993+12X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" },
/* 72*/ { "619549X3+123", ZINT_ERROR_INVALID_DATA, -1 }, /* 72*/ { "619549X3+123", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 73*/ { "361954990+12", ZINT_ERROR_INVALID_CHECK, -1 }, /* 73*/ { "361954990+12", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid SBN check digit '0', expecting '9'", "" },
/* 74*/ { "361954999+12", 0, 0 }, /* 74*/ { "361954999+12", 0, 0, "", "" },
/* 75*/ { "361954999+1X", ZINT_ERROR_INVALID_DATA, -1 }, /* 75*/ { "361954999+1X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" },
/* 76*/ { "3619549X9+12", ZINT_ERROR_INVALID_DATA, -1 }, /* 76*/ { "3619549X9+12", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 77*/ { "361954999+1234", 0, 0 }, /* 77*/ { "361954999+1234", 0, 0, "", "" },
/* 78*/ { "361954999+123X", ZINT_ERROR_INVALID_DATA, -1 }, /* 78*/ { "361954999+123X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" },
/* 79*/ { "3619549X9+1234", ZINT_ERROR_INVALID_DATA, -1 }, /* 79*/ { "3619549X9+1234", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 80*/ { "1999000030+12", ZINT_ERROR_INVALID_CHECK, -1 }, /* 80*/ { "1999000030+12", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid ISBN check digit '0', expecting 'X'", "" },
/* 81*/ { "199900003X+12", 0, 0 }, /* 81*/ { "199900003X+12", 0, 0, "", "" },
/* 82*/ { "199900003x+12", 0, 0 }, /* 82*/ { "199900003x+12", 0, 0, "", "" },
/* 83*/ { "19990000XX+12", ZINT_ERROR_INVALID_DATA, -1 }, /* 83*/ { "19990000XX+12", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 84*/ { "199900003X+1X", ZINT_ERROR_INVALID_DATA, -1 }, /* 84*/ { "199900003X+1X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" },
/* 85*/ { "1999000031+12345", ZINT_ERROR_INVALID_CHECK, -1 }, /* 85*/ { "1999000031+12345", ZINT_ERROR_INVALID_CHECK, -1, "Error 281: Invalid ISBN check digit '1', expecting 'X'", "" },
/* 86*/ { "199900003X+12345", 0, 0 }, /* 86*/ { "199900003X+12345", 0, 0, "", "" },
/* 87*/ { "199900003x+12345", 0, 0 }, /* 87*/ { "199900003x+12345", 0, 0, "", "" },
/* 88*/ { "199900003X+1234X", ZINT_ERROR_INVALID_DATA, -1 }, /* 88*/ { "199900003X+1234X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" },
/* 89*/ { "19990000XX+12345", ZINT_ERROR_INVALID_DATA, -1 }, /* 89*/ { "19990000XX+12345", ZINT_ERROR_INVALID_DATA, -1, "Error 296: Invalid character in data, \"X\" allowed in last position only", "" },
/* 90*/ { "199900003X+1234A", ZINT_ERROR_INVALID_DATA, -1 }, /* 90*/ { "199900003X+1234A", ZINT_ERROR_INVALID_DATA, -1, "Error 285: Invalid character in data (digits, \"X\" and \"+\" only)", "" },
/* 91*/ { "9791234567895+12", ZINT_ERROR_INVALID_CHECK, -1 }, /* 91*/ { "9791234567895+12", ZINT_ERROR_INVALID_CHECK, -1, "Error 280: Invalid ISBN check digit '5', expecting '6'", "" },
/* 92*/ { "9791234567896+12", 0, 0 }, /* 92*/ { "9791234567896+12", 0, 0, "", "" },
/* 93*/ { "9791234567896+1X", ZINT_ERROR_INVALID_DATA, -1 }, /* 93*/ { "9791234567896+1X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" },
/* 94*/ { "97912345678X6+12", ZINT_ERROR_INVALID_DATA, -1 }, /* 94*/ { "97912345678X6+12", ZINT_ERROR_INVALID_DATA, -1, "Error 282: Invalid character in data, \"X\" not allowed in ISBN-13", "" },
/* 95*/ { "9791234567897+12345", ZINT_ERROR_INVALID_CHECK, -1 }, /* 95*/ { "9791234567897+12345", ZINT_ERROR_INVALID_CHECK, -1, "Error 280: Invalid ISBN check digit '7', expecting '6'", "" },
/* 96*/ { "9791234567896+12345", 0, 0 }, /* 96*/ { "9791234567896+12345", 0, 0, "", "" },
/* 97*/ { "9791234567896+1234X", ZINT_ERROR_INVALID_DATA, -1 }, /* 97*/ { "9791234567896+1234X", ZINT_ERROR_INVALID_DATA, -1, "Error 295: Invalid add-on data (digits only)", "" },
/* 98*/ { "979123456X896+12345", ZINT_ERROR_INVALID_DATA, -1 }, /* 98*/ { "979123456X896+12345", ZINT_ERROR_INVALID_DATA, -1, "Error 282: Invalid character in data, \"X\" not allowed in ISBN-13", "" },
/* 99*/ { "9791234567892+", ZINT_ERROR_INVALID_CHECK, -1 }, /* 99*/ { "9791234567892+", ZINT_ERROR_INVALID_CHECK, -1, "Error 280: Invalid ISBN check digit '2', expecting '6'", "" },
/*100*/ { "9791234567896+", 0, 0 }, /*100*/ { "9791234567896+", 0, 0, "", "" },
/*101*/ { "97912345678X6+", ZINT_ERROR_INVALID_DATA, -1 }, /*101*/ { "97912345678X6+", ZINT_ERROR_INVALID_DATA, -1, "Error 282: Invalid character in data, \"X\" not allowed in ISBN-13", "" },
/*102*/ { "97912345678961+", ZINT_ERROR_TOO_LONG, -1 }, /*102*/ { "97912345678961+", ZINT_ERROR_TOO_LONG, -1, "Error 294: Input too long (13 character maximum)", "" },
/*103*/ { "97912345678961+12345", ZINT_ERROR_TOO_LONG, -1 }, /*103*/ { "97912345678961+12345", ZINT_ERROR_TOO_LONG, -1, "Error 283: Input too long (19 character maximum)", "" },
/*104*/ { "9791234567896+123456", ZINT_ERROR_TOO_LONG, -1 }, /*104*/ { "9791234567896+123456", ZINT_ERROR_TOO_LONG, -1, "Error 283: Input too long (19 character maximum)", "" },
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
int i, length, ret; int i, length, ret;
struct zint_symbol *symbol; struct zint_symbol *symbol;
char errtxt_escaped[256];
testStart("test_isbn_input"); testStart("test_isbn_input");
for (i = 0; i < data_size; i++) { for (i = 0; i < data_size; i++) {
@ -562,11 +579,20 @@ static void test_isbn_input(int index, int debug) {
length = testUtilSetSymbol(symbol, BARCODE_ISBNX, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); length = testUtilSetSymbol(symbol, BARCODE_ISBNX, -1 /*input_mode*/, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug);
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
assert_equal(ret, data[i].ret_encode, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret_encode, symbol->errtxt);
if (data[i].ret_vector != -1) { if (generate) {
ret = ZBarcode_Buffer_Vector(symbol, 0); printf(" /*%3d*/ { \"%s\", %s, %d, \"%s\", \"%s\" },\n",
assert_equal(ret, data[i].ret_vector, "i:%d ZBarcode_Buffer_Vector ret %d != %d (%s)\n", i, ret, data[i].ret_vector, symbol->errtxt); i, data[i].data, testUtilErrorName(data[i].ret_encode), data[i].ret_vector,
testUtilEscape(symbol->errtxt, (int) strlen(symbol->errtxt), errtxt_escaped, sizeof(errtxt_escaped)),
data[i].comment);
} else {
assert_equal(ret, data[i].ret_encode, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret_encode, symbol->errtxt);
assert_zero(strcmp(symbol->errtxt, data[i].ret_errtxt), "i:%d errtxt %s != %s\n", i, symbol->errtxt, data[i].ret_errtxt);
if (data[i].ret_vector != -1) {
ret = ZBarcode_Buffer_Vector(symbol, 0);
assert_equal(ret, data[i].ret_vector, "i:%d ZBarcode_Buffer_Vector ret %d != %d (%s)\n", i, ret, data[i].ret_vector, symbol->errtxt);
}
} }
ZBarcode_Delete(symbol); ZBarcode_Delete(symbol);
@ -955,18 +981,127 @@ static void test_fuzz(int index, int debug) {
testFinish(); testFinish();
} }
#include <time.h>
#define TEST_PERF_ITER_MILLES 10
#define TEST_PERF_ITERATIONS (TEST_PERF_ITER_MILLES * 1000)
#define TEST_PERF_TIME(arg) (((arg) * 1000.0) / CLOCKS_PER_SEC)
// Not a real test, just performance indicator
static void test_perf(int index, int debug) {
struct item {
int symbology;
int option_2;
char *data;
int ret;
int expected_rows;
int expected_width;
char *comment;
};
// s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<"))
struct item data[] = {
/* 0*/ { BARCODE_EANX, -1, "123456789012+12345", 0, 1, 149, "EAN-13 add-on 5" },
/* 1*/ { BARCODE_EANX, -1, "123456789012", 0, 1, 95, "EAN-13 no add-on" },
/* 2*/ { BARCODE_UPCA, -1, "12345678901+12345", 0, 1, 151, "UPC-A add-on 5" },
/* 3*/ { BARCODE_UPCA, -1, "12345678901", 0, 1, 95, "UPC-A no add-on" },
/* 4*/ { BARCODE_EANX, -1, "1234567+12345", 0, 1, 121, "EAN-8 add-on 5" },
/* 5*/ { BARCODE_EANX, -1, "1234567", 0, 1, 67, "EAN-8 no add-on" },
/* 6*/ { BARCODE_UPCE, -1, "1234567+12", 0, 1, 78, "UPC-E add-on 2" },
/* 7*/ { BARCODE_UPCE, -1, "1234567", 0, 1, 51, "UPC-E no add-on" },
/* 8*/ { BARCODE_EANX, -1, "12345", 0, 1, 47, "EAN-5" },
/* 9*/ { BARCODE_EANX, -1, "12", 0, 1, 20, "EAN-2" },
};
int data_size = ARRAY_SIZE(data);
int i, length, ret;
struct zint_symbol *symbol;
clock_t start;
clock_t total_create = 0, total_encode = 0, total_buffer = 0, total_buf_inter = 0, total_print = 0;
clock_t diff_create, diff_encode, diff_buffer, diff_buf_inter, diff_print;
int comment_max = 0;
if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */
return;
}
for (i = 0; i < data_size; i++) if ((int) strlen(data[i].comment) > comment_max) comment_max = (int) strlen(data[i].comment);
printf("Iterations %d\n", TEST_PERF_ITERATIONS);
for (i = 0; i < data_size; i++) {
int j;
if (index != -1 && i != index) continue;
diff_create = diff_encode = diff_buffer = diff_buf_inter = diff_print = 0;
for (j = 0; j < TEST_PERF_ITERATIONS; j++) {
start = clock();
symbol = ZBarcode_Create();
diff_create += clock() - start;
assert_nonnull(symbol, "Symbol not created\n");
length = testUtilSetSymbol(symbol, data[i].symbology, DATA_MODE, -1 /*eci*/, -1 /*option_1*/, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug);
start = clock();
ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length);
diff_encode += clock() - start;
assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt);
assert_equal(symbol->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);
start = clock();
ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/);
diff_buffer += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Buffer ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
symbol->output_options |= OUT_BUFFER_INTERMEDIATE;
start = clock();
ret = ZBarcode_Buffer(symbol, 0 /*rotate_angle*/);
diff_buf_inter += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Buffer OUT_BUFFER_INTERMEDIATE ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
symbol->output_options &= ~OUT_BUFFER_INTERMEDIATE; // Undo
start = clock();
ret = ZBarcode_Print(symbol, 0 /*rotate_angle*/);
diff_print += clock() - start;
assert_zero(ret, "i:%d ZBarcode_Print ret %d != 0 (%s)\n", i, ret, symbol->errtxt);
assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile);
ZBarcode_Delete(symbol);
}
printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, data[i].comment,
TEST_PERF_TIME(diff_encode), TEST_PERF_TIME(diff_buffer), TEST_PERF_TIME(diff_buf_inter), TEST_PERF_TIME(diff_print), TEST_PERF_TIME(diff_create));
total_create += diff_create;
total_encode += diff_encode;
total_buffer += diff_buffer;
total_buf_inter += diff_buf_inter;
total_print += diff_print;
}
if (index == -1) {
printf("%*s: encode % 8gms, buffer % 8gms, buf_inter % 8gms, print % 8gms, create % 8gms\n", comment_max, "totals",
TEST_PERF_TIME(total_encode), TEST_PERF_TIME(total_buffer), TEST_PERF_TIME(total_buf_inter), TEST_PERF_TIME(total_print), TEST_PERF_TIME(total_create));
}
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */
{ "test_upce_input", test_upce_input, 1, 0, 1 }, { "test_upce_input", test_upce_input, 1, 0, 1 },
{ "test_upca_print", test_upca_print, 1, 0, 1 }, { "test_upca_print", test_upca_print, 1, 0, 1 },
{ "test_upca_input", test_upca_input, 1, 0, 1 }, { "test_upca_input", test_upca_input, 1, 0, 1 },
{ "test_eanx_input", test_eanx_input, 1, 0, 1 }, { "test_eanx_input", test_eanx_input, 1, 1, 1 },
{ "test_isbn_input", test_isbn_input, 1, 0, 1 }, { "test_isbn_input", test_isbn_input, 1, 1, 1 },
{ "test_hrt", test_hrt, 1, 0, 1 }, { "test_hrt", test_hrt, 1, 0, 1 },
{ "test_vector_same", test_vector_same, 1, 0, 1 }, { "test_vector_same", test_vector_same, 1, 0, 1 },
{ "test_encode", test_encode, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 },
{ "test_fuzz", test_fuzz, 1, 0, 1 }, { "test_fuzz", test_fuzz, 1, 0, 1 },
{ "test_perf", test_perf, 1, 0, 1 },
}; };
testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); testRun(argc, argv, funcs, ARRAY_SIZE(funcs));

View File

@ -84,13 +84,13 @@ void assert_nonzero(int exp, const char *fmt, ...) {
va_list args; assertionFailed++; va_start(args, fmt); vprintf(fmt, args); va_end(args); testFinish(); va_list args; assertionFailed++; va_start(args, fmt); vprintf(fmt, args); va_end(args); testFinish();
} }
} }
void assert_null(void *exp, const char *fmt, ...) { void assert_null(const void *exp, const char *fmt, ...) {
assertionNum++; assertionNum++;
if (exp != NULL) { if (exp != NULL) {
va_list args; assertionFailed++; va_start(args, fmt); vprintf(fmt, args); va_end(args); testFinish(); va_list args; assertionFailed++; va_start(args, fmt); vprintf(fmt, args); va_end(args); testFinish();
} }
} }
void assert_nonnull(void *exp, const char *fmt, ...) { void assert_nonnull(const void *exp, const char *fmt, ...) {
assertionNum++; assertionNum++;
if (exp == NULL) { if (exp == NULL) {
va_list args; assertionFailed++; va_start(args, fmt); vprintf(fmt, args); va_end(args); testFinish(); va_list args; assertionFailed++; va_start(args, fmt); vprintf(fmt, args); va_end(args); testFinish();
@ -683,7 +683,7 @@ const char *testUtilOutputOptionsName(int output_options) {
} }
/* Convert modules spanning 3 rows to DAFT equivalents */ /* Convert modules spanning 3 rows to DAFT equivalents */
int testUtilDAFTConvert(const struct zint_symbol *symbol, char *buffer, int buffer_size) { int testUtilDAFTConvert(const struct zint_symbol *symbol, char *buffer, const int buffer_size) {
int i; int i;
char *b = buffer; char *b = buffer;
*b = '\0'; *b = '\0';
@ -720,7 +720,7 @@ int testUtilIsValidUTF8(const unsigned char str[], const int length) {
} }
/* Escape data for printing on generate test. Has a number of issues, e.g. need to use octal escapes */ /* Escape data for printing on generate test. Has a number of issues, e.g. need to use octal escapes */
char *testUtilEscape(char *buffer, int length, char *escaped, int escaped_size) { char *testUtilEscape(const char *buffer, const int length, char *escaped, const int escaped_size) {
int i; int i;
unsigned char *b = (unsigned char *) buffer; unsigned char *b = (unsigned char *) buffer;
unsigned char *be = b + length; unsigned char *be = b + length;
@ -767,9 +767,9 @@ char *testUtilEscape(char *buffer, int length, char *escaped, int escaped_size)
} }
/* Helper to read a CSV field */ /* Helper to read a CSV field */
char *testUtilReadCSVField(char *buffer, char *field, int field_size) { const char *testUtilReadCSVField(const char *buffer, char *field, const int field_size) {
int i; int i;
char *b = buffer; const char *b = buffer;
for (i = 0; i < field_size && *b && *b != ',' && *b != '\n' && *b != '\r'; i++) { for (i = 0; i < field_size && *b && *b != ',' && *b != '\n' && *b != '\r'; i++) {
field[i] = *b++; field[i] = *b++;
} }
@ -781,7 +781,7 @@ char *testUtilReadCSVField(char *buffer, char *field, int field_size) {
} }
/* Helper to fill a buffer (for "large" tests) - single-byte filler only */ /* Helper to fill a buffer (for "large" tests) - single-byte filler only */
void testUtilStrCpyRepeat(char *buffer, char *repeat, int size) { void testUtilStrCpyRepeat(char *buffer, const char *repeat, const int size) {
int i; int i;
int len = (int) strlen(repeat); int len = (int) strlen(repeat);
int max = size - len; int max = size - len;
@ -2046,7 +2046,7 @@ static const char *testUtilBwippName(int index, const struct zint_symbol *symbol
{ "identcode", BARCODE_DPIDENT, 22, 0, 0, 0, 0, 0, }, { "identcode", BARCODE_DPIDENT, 22, 0, 0, 0, 0, 0, },
{ "code16k", BARCODE_CODE16K, 23, 0, 0, 0, 8 /*linear_row_height*/, 0, }, { "code16k", BARCODE_CODE16K, 23, 0, 0, 0, 8 /*linear_row_height*/, 0, },
{ "code49", BARCODE_CODE49, 24, 0, 0, 0, 8 /*linear_row_height*/, 0, }, { "code49", BARCODE_CODE49, 24, 0, 0, 0, 8 /*linear_row_height*/, 0, },
{ "code93", BARCODE_CODE93, 25, 0, 0, 0, 0, 0, }, { "code93ext", BARCODE_CODE93, 25, 0, 0, 0, 0, 0, },
{ "", -1, 26, 0, 0, 0, 0, 0, }, { "", -1, 26, 0, 0, 0, 0, 0, },
{ "", -1, 27, 0, 0, 0, 0, 0, }, { "", -1, 27, 0, 0, 0, 0, 0, },
{ "flattermarken", BARCODE_FLAT, 28, 0, 0, 0, 0, 0, }, { "flattermarken", BARCODE_FLAT, 28, 0, 0, 0, 0, 0, },
@ -2598,9 +2598,6 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int
} else if (symbology == BARCODE_CODE93) { } else if (symbology == BARCODE_CODE93) {
sprintf(bwipp_opts_buf + strlen(bwipp_opts_buf), "%sincludecheck", sprintf(bwipp_opts_buf + strlen(bwipp_opts_buf), "%sincludecheck",
strlen(bwipp_opts_buf) ? " " : ""); strlen(bwipp_opts_buf) ? " " : "");
if (parse) {
bwipp_barcode = "code93ext";
}
bwipp_opts = bwipp_opts_buf; bwipp_opts = bwipp_opts_buf;
} else if (symbology == BARCODE_PZN) { } else if (symbology == BARCODE_PZN) {
sprintf(bwipp_opts_buf + strlen(bwipp_opts_buf), "%spzn8", strlen(bwipp_opts_buf) ? " " : ""); sprintf(bwipp_opts_buf + strlen(bwipp_opts_buf), "%spzn8", strlen(bwipp_opts_buf) ? " " : "");
@ -2681,7 +2678,7 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int
|| symbology == BARCODE_PHARMA_TWO) { || symbology == BARCODE_PHARMA_TWO) {
for (r = 0; r < symbol->rows; r++) bwipp_row_height[r] = 1; /* Zap */ for (r = 0; r < symbol->rows; r++) bwipp_row_height[r] = 1; /* Zap */
if (symbology == BARCODE_KIX) { if (symbology == BARCODE_KIX) {
to_upper((unsigned char *) bwipp_data); to_upper((unsigned char *) bwipp_data, (int) strlen(bwipp_data));
} else if (symbology == BARCODE_USPS_IMAIL) { } else if (symbology == BARCODE_USPS_IMAIL) {
char *dash = strchr(bwipp_data, '-'); char *dash = strchr(bwipp_data, '-');
if (dash) { if (dash) {

View File

@ -96,8 +96,8 @@ void testRun(int argc, char *argv[], testFunction funcs[], int funcs_size);
#include "../ms_stdint.h" #include "../ms_stdint.h"
void assert_zero(int exp, const char *fmt, ...); void assert_zero(int exp, const char *fmt, ...);
void assert_nonzero(int exp, const char *fmt, ...); void assert_nonzero(int exp, const char *fmt, ...);
void assert_null(void *exp, const char *fmt, ...); void assert_null(const void *exp, const char *fmt, ...);
void assert_nonnull(void *exp, const char *fmt, ...); void assert_nonnull(const void *exp, const char *fmt, ...);
void assert_equal(int e1, int e2, const char *fmt, ...); void assert_equal(int e1, int e2, const char *fmt, ...);
void assert_equalu64(uint64_t e1, uint64_t e2, const char *fmt, ...); void assert_equalu64(uint64_t e1, uint64_t e2, const char *fmt, ...);
void assert_notequal(int e1, int e2, ...); void assert_notequal(int e1, int e2, ...);
@ -126,11 +126,11 @@ const char *testUtilInputModeName(int input_mode);
const char *testUtilOption3Name(int option_3); const char *testUtilOption3Name(int option_3);
const char *testUtilOutputOptionsName(int output_options); const char *testUtilOutputOptionsName(int output_options);
int testUtilDAFTConvert(const struct zint_symbol *symbol, char *buffer, int buffer_size); int testUtilDAFTConvert(const struct zint_symbol *symbol, char *buffer, const int buffer_size);
int testUtilIsValidUTF8(const unsigned char str[], const int length); int testUtilIsValidUTF8(const unsigned char str[], const int length);
char *testUtilEscape(char *buffer, int length, char *escaped, int escaped_size); char *testUtilEscape(const char *buffer, const int length, char *escaped, const int escaped_size);
char *testUtilReadCSVField(char *buffer, char *field, int field_size); const char *testUtilReadCSVField(const char *buffer, char *field, const int field_size);
void testUtilStrCpyRepeat(char *buffer, char *repeat, int size); void testUtilStrCpyRepeat(char *buffer, const char *repeat, const int size);
int testUtilSymbolCmp(const struct zint_symbol *a, const struct zint_symbol *b); int testUtilSymbolCmp(const struct zint_symbol *a, const struct zint_symbol *b);
struct zint_vector *testUtilVectorCpy(const struct zint_vector *in); struct zint_vector *testUtilVectorCpy(const struct zint_vector *in);

View File

@ -46,7 +46,7 @@
#define GFMUL(i, j) ((((i) == 0)||((j) == 0)) ? 0 : gfPwr[(gfLog[i] + gfLog[j])]) #define GFMUL(i, j) ((((i) == 0)||((j) == 0)) ? 0 : gfPwr[(gfLog[i] + gfLog[j])])
static const char fragment[27][14] = {"http://", "https://", "http://www.", "https://www.", static const char fragment[27][13] = {"http://", "https://", "http://www.", "https://www.",
"ftp://", "www.", ".com", ".edu", ".gov", ".int", ".mil", ".net", ".org", "ftp://", "www.", ".com", ".edu", ".gov", ".int", ".mil", ".net", ".org",
".mobi", ".coop", ".biz", ".info", "mailto:", "tel:", ".cgi", ".asp", ".mobi", ".coop", ".biz", ".info", "mailto:", "tel:", ".cgi", ".asp",
".aspx", ".php", ".htm", ".html", ".shtml", "file:"}; ".aspx", ".php", ".htm", ".html", ".shtml", "file:"};
@ -273,7 +273,7 @@ static float look_ahead_eightbit(unsigned char source[], int in_length, int in_l
*cw_len = codeword_count; *cw_len = codeword_count;
if (codeword_count == 0) { if (codeword_count == 0) {
return 0.0; return 0.0f;
} }
return (float) letters_encoded / (float) codeword_count; return (float) letters_encoded / (float) codeword_count;
} }
@ -362,7 +362,7 @@ static float look_ahead_ascii(unsigned char source[], int in_length, int in_locn
*cw_len = codeword_count; *cw_len = codeword_count;
if (codeword_count == 0) { if (codeword_count == 0) {
return 0.0; return 0.0f;
} }
return (float) letters_encoded / (float) codeword_count; return (float) letters_encoded / (float) codeword_count;
} }
@ -372,8 +372,8 @@ static int c43_should_latch_other(const unsigned char data[], const int length,
const int gs1) { const int gs1) {
int i, fraglen, predict_window; int i, fraglen, predict_window;
int cnt, alt_cnt, fragno; int cnt, alt_cnt, fragno;
const char *set = subset == 1 ? ultra_c43_set1 : ultra_c43_set2; const char *const set = subset == 1 ? ultra_c43_set1 : ultra_c43_set2;
const char *alt_set = subset == 2 ? ultra_c43_set1 : ultra_c43_set2; const char *const alt_set = subset == 2 ? ultra_c43_set1 : ultra_c43_set2;
if (locn + 3 > length) { if (locn + 3 > length) {
return 0; return 0;
@ -394,10 +394,10 @@ static int c43_should_latch_other(const unsigned char data[], const int length,
} }
i += fraglen - 1; i += fraglen - 1;
} else { } else {
if (strchr(set, data[i]) != NULL) { if (posn(set, data[i]) != -1) {
cnt++; cnt++;
} }
if (strchr(alt_set, data[i]) != NULL) { if (posn(alt_set, data[i]) != -1) {
alt_cnt++; alt_cnt++;
} }
} }
@ -612,7 +612,7 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn,
*cw_len = codeword_count; *cw_len = codeword_count;
if (codeword_count == 0) { if (codeword_count == 0) {
return 0.0; return 0.0f;
} }
return (float) letters_encoded / (float) codeword_count; return (float) letters_encoded / (float) codeword_count;
} }

View File

@ -30,12 +30,9 @@
*/ */
/* vim: set ts=4 sw=4 et : */ /* vim: set ts=4 sw=4 et : */
#define SODIUM "0123456789+" #define SODIUM_PLS_F (IS_NUM_F | IS_PLS_F) /* SODIUM "0123456789+" */
#define ISBNX_SANE "0123456789X" #define ISBNX_SANE_F (IS_NUM_F | IS_UX__F) /* ISBNX_SANE "0123456789X" */
#define ISBNX_ADDON_SANE "0123456789Xx+" #define ISBNX_ADDON_SANE_F (IS_NUM_F | IS_UX__F | IS_LX__F | IS_PLS_F) /* ISBNX_ADDON_SANE "0123456789Xx+" */
#define EAN2 102
#define EAN5 105
#include <stdio.h> #include <stdio.h>
#include "common.h" #include "common.h"
@ -43,66 +40,72 @@
/* UPC and EAN tables checked against EN 797:1996 */ /* UPC and EAN tables checked against EN 797:1996 */
static const char *UPCParity0[10] = { static const char UPCParity0[10][6] = {
/* Number set for UPC-E symbol (EN Table 4) */ /* Number set for UPC-E symbol (EN Table 4) */
"BBBAAA", "BBABAA", "BBAABA", "BBAAAB", "BABBAA", "BAABBA", "BAAABB", {'B','B','B','A','A','A'}, {'B','B','A','B','A','A'}, {'B','B','A','A','B','A'}, {'B','B','A','A','A','B'},
"BABABA", "BABAAB", "BAABAB" {'B','A','B','B','A','A'}, {'B','A','A','B','B','A'}, {'B','A','A','A','B','B'}, {'B','A','B','A','B','A'},
{'B','A','B','A','A','B'}, {'B','A','A','B','A','B'}
}; };
static const char *UPCParity1[10] = { static const char UPCParity1[10][6] = {
/* Not covered by BS EN 797:1995 */ /* Not covered by BS EN 797:1995 */
"AAABBB", "AABABB", "AABBAB", "AABBBA", "ABAABB", "ABBAAB", "ABBBAA", {'A','A','A','B','B','B'}, {'A','A','B','A','B','B'}, {'A','A','B','B','A','B'}, {'A','A','B','B','B','A'},
"ABABAB", "ABABBA", "ABBABA" {'A','B','A','A','B','B'}, {'A','B','B','A','A','B'}, {'A','B','B','B','A','A'}, {'A','B','A','B','A','B'},
{'A','B','A','B','B','A'}, {'A','B','B','A','B','A'}
}; };
static const char *EAN2Parity[4] = { static const char EAN2Parity[4][2] = {
/* Number sets for 2-digit add-on (EN Table 6) */ /* Number sets for 2-digit add-on (EN Table 6) */
"AA", "AB", "BA", "BB" {'A','A'}, {'A','B'}, {'B','A'}, {'B','B'}
}; };
static const char *EAN5Parity[10] = { static const char EAN5Parity[10][5] = {
/* Number set for 5-digit add-on (EN Table 7) */ /* Number set for 5-digit add-on (EN Table 7) */
"BBAAA", "BABAA", "BAABA", "BAAAB", "ABBAA", "AABBA", "AAABB", "ABABA", {'B','B','A','A','A'}, {'B','A','B','A','A'}, {'B','A','A','B','A'}, {'B','A','A','A','B'}, {'A','B','B','A','A'},
"ABAAB", "AABAB" {'A','A','B','B','A'}, {'A','A','A','B','B'}, {'A','B','A','B','A'}, {'A','B','A','A','B'}, {'A','A','B','A','B'}
}; };
static const char *EAN13Parity[10] = { static const char EAN13Parity[10][5] = {
/* Left hand of the EAN-13 symbol (EN Table 3) */ /* Left hand of the EAN-13 symbol (EN Table 3) */
"AAAAA", "ABABB", "ABBAB", "ABBBA", "BAABB", "BBAAB", "BBBAA", "BABAB", {'A','A','A','A','A'}, {'A','B','A','B','B'}, {'A','B','B','A','B'}, {'A','B','B','B','A'}, {'B','A','A','B','B'},
"BABBA", "BBABA" {'B','B','A','A','B'}, {'B','B','B','A','A'}, {'B','A','B','A','B'}, {'B','A','B','B','A'}, {'B','B','A','B','A'}
}; };
static const char *EANsetA[10] = { static const char EANsetA[10][4] = {
/* Representation set A and C (EN Table 1) */ /* Representation set A and C (EN Table 1) */
"3211", "2221", "2122", "1411", "1132", "1231", "1114", "1312", "1213", "3112" {'3','2','1','1'}, {'2','2','2','1'}, {'2','1','2','2'}, {'1','4','1','1'}, {'1','1','3','2'},
{'1','2','3','1'}, {'1','1','1','4'}, {'1','3','1','2'}, {'1','2','1','3'}, {'3','1','1','2'}
}; };
static const char *EANsetB[10] = { static const char EANsetB[10][4] = {
/* Representation set B (EN Table 1) */ /* Representation set B (EN Table 1) */
"1123", "1222", "2212", "1141", "2311", "1321", "4111", "2131", "3121", "2113" {'1','1','2','3'}, {'1','2','2','2'}, {'2','2','1','2'}, {'1','1','4','1'}, {'2','3','1','1'},
{'1','3','2','1'}, {'4','1','1','1'}, {'2','1','3','1'}, {'3','1','2','1'}, {'2','1','1','3'}
}; };
/* UPC A is usually used for 12 digit numbers, but this function takes a source of any length */ /* UPC A is usually used for 12 digit numbers, but this function takes a source of any length */
static void upca_draw(const unsigned char source[], const int length, char dest[]) { static void upca_draw(const unsigned char source[], const int length, char *d) {
int i, half_way; int i, half_way;
half_way = length / 2; half_way = length / 2;
/* start character */ /* start character */
strcat(dest, "111"); memcpy(d, "111", 3);
d += 3;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++, d += 4) {
if (i == half_way) { if (i == half_way) {
/* middle character - separates manufacturer no. from product no. */ /* middle character - separates manufacturer no. from product no. */
/* also inverts right hand characters */ /* also inverts right hand characters */
strcat(dest, "11111"); memcpy(d, "11111", 5);
d += 5;
} }
lookup(NEON, EANsetA, source[i], dest); memcpy(d, EANsetA[source[i] - '0'], 4);
} }
/* stop character */ /* stop character */
strcat(dest, "111"); strcpy(d, "111");
} }
/* Make a UPC-A barcode, allowing for composite if `cc_rows` set */ /* Make a UPC-A barcode, allowing for composite if `cc_rows` set */
@ -156,9 +159,10 @@ static int upca(struct zint_symbol *symbol, const unsigned char source[], int le
} }
/* UPC-E, allowing for composite if `cc_rows` set */ /* UPC-E, allowing for composite if `cc_rows` set */
static int upce_cc(struct zint_symbol *symbol, unsigned char source[], int length, char dest[], int cc_rows) { static int upce_cc(struct zint_symbol *symbol, unsigned char source[], int length, char *d, int cc_rows) {
int i, num_system; int i, num_system;
char emode, check_digit, parity[8]; char emode, check_digit;
const char *parity;
char src_check_digit = '\0'; char src_check_digit = '\0';
unsigned char equivalent[12]; unsigned char equivalent[12];
unsigned char *hrt = symbol->text; unsigned char *hrt = symbol->text;
@ -266,27 +270,28 @@ static int upce_cc(struct zint_symbol *symbol, unsigned char source[], int lengt
/* Use the number system and check digit information to choose a parity scheme */ /* Use the number system and check digit information to choose a parity scheme */
if (num_system == 1) { if (num_system == 1) {
strcpy(parity, UPCParity1[ctoi(check_digit)]); parity = UPCParity1[ctoi(check_digit)];
} else { } else {
strcpy(parity, UPCParity0[ctoi(check_digit)]); parity = UPCParity0[ctoi(check_digit)];
} }
/* Take all this information and make the barcode pattern */ /* Take all this information and make the barcode pattern */
/* start character */ /* start character */
strcat(dest, "111"); memcpy(d, "111", 3);
d += 3;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++, d += 4) {
switch (parity[i]) { switch (parity[i]) {
case 'A': lookup(NEON, EANsetA, source[i], dest); case 'A': memcpy(d, EANsetA[source[i] - '0'], 4);
break; break;
case 'B': lookup(NEON, EANsetB, source[i], dest); case 'B': memcpy(d, EANsetB[source[i] - '0'], 4);
break; break;
} }
} }
/* stop character */ /* stop character */
strcat(dest, "111111"); strcpy(d, "111111");
hrt[7] = check_digit; hrt[7] = check_digit;
hrt[8] = '\0'; hrt[8] = '\0';
@ -323,36 +328,27 @@ static int upce(struct zint_symbol *symbol, unsigned char source[], int length,
/* EAN-2 and EAN-5 add-on codes */ /* EAN-2 and EAN-5 add-on codes */
static void ean_add_on(const unsigned char source[], const int length, char dest[], const int addon_gap) { static void ean_add_on(const unsigned char source[], const int length, char dest[], const int addon_gap) {
char parity[6]; const char *parity;
int i, code_type; int i;
char *d = dest + strlen(dest);
/* If an add-on then append with space */ /* If an add-on then append with space */
if (addon_gap != 0) { if (addon_gap != 0) {
i = (int) strlen(dest); *d++ = itoc(addon_gap);
dest[i] = itoc(addon_gap);
dest[i + 1] = '\0';
} }
/* Start character */ /* Start character */
strcat(dest, "112"); memcpy(d, "112", 3);
d += 3;
/* Determine EAN2 or EAN5 add-on */ /* Calculate parity */
if (length == 2) { if (length == 2) { /* EAN-2 */
code_type = EAN2;
} else {
code_type = EAN5;
}
/* Calculate parity for EAN2 */
if (code_type == EAN2) {
int code_value, parity_bit; int code_value, parity_bit;
code_value = (10 * ctoi(source[0])) + ctoi(source[1]); code_value = (10 * ctoi(source[0])) + ctoi(source[1]);
parity_bit = code_value % 4; parity_bit = code_value % 4;
strcpy(parity, EAN2Parity[parity_bit]); parity = EAN2Parity[parity_bit];
} } else { /* EAN-5 */
if (code_type == EAN5) {
int values[6], parity_sum, parity_bit; int values[6], parity_sum, parity_bit;
for (i = 0; i < 6; i++) { for (i = 0; i < 6; i++) {
@ -363,34 +359,37 @@ static void ean_add_on(const unsigned char source[], const int length, char dest
parity_sum += (9 * (values[1] + values[3])); parity_sum += (9 * (values[1] + values[3]));
parity_bit = parity_sum % 10; parity_bit = parity_sum % 10;
strcpy(parity, EAN5Parity[parity_bit]); parity = EAN5Parity[parity_bit];
} }
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
switch (parity[i]) { switch (parity[i]) {
case 'A': lookup(NEON, EANsetA, source[i], dest); case 'A': memcpy(d, EANsetA[source[i] - '0'], 4);
d += 4;
break; break;
case 'B': lookup(NEON, EANsetB, source[i], dest); case 'B': memcpy(d, EANsetB[source[i] - '0'], 4);
d += 4;
break; break;
} }
/* Glyph separator */ /* Glyph separator */
if (i != (length - 1)) { if (i != (length - 1)) {
strcat(dest, "11"); memcpy(d, "11", 2);
d += 2;
} }
} }
*d = '\0';
} }
/* ************************ EAN-13 ****************** */ /* ************************ EAN-13 ****************** */
static int ean13_cc(struct zint_symbol *symbol, const unsigned char source[], int length, char dest[], static int ean13_cc(struct zint_symbol *symbol, const unsigned char source[], int length, char *d,
int cc_rows) { int cc_rows) {
int i, half_way; int i, half_way;
char parity[6]; const char *parity;
unsigned char *gtin = symbol->text; unsigned char *gtin = symbol->text;
int error_number = 0; int error_number = 0;
parity[0] = '\0';
ustrcpy(gtin, source); ustrcpy(gtin, source);
/* Add the appropriate check digit */ /* Add the appropriate check digit */
@ -410,29 +409,32 @@ static int ean13_cc(struct zint_symbol *symbol, const unsigned char source[], in
} }
/* Get parity for first half of the symbol */ /* Get parity for first half of the symbol */
lookup(SODIUM, EAN13Parity, gtin[0], parity); parity = EAN13Parity[gtin[0] - '0'];
/* Now get on with the cipher */ /* Now get on with the cipher */
half_way = 7; half_way = 7;
/* start character */ /* start character */
strcat(dest, "111"); memcpy(d, "111", 3);
for (i = 1; i < length; i++) { d += 3;
for (i = 1; i < length; i++, d += 4) {
if (i == half_way) { if (i == half_way) {
/* middle character - separates manufacturer no. from product no. */ /* middle character - separates manufacturer no. from product no. */
/* also inverses right hand characters */ /* also inverses right hand characters */
strcat(dest, "11111"); memcpy(d, "11111", 5);
d += 5;
} }
if (((i > 1) && (i < 7)) && (parity[i - 2] == 'B')) { if (((i > 1) && (i < 7)) && (parity[i - 2] == 'B')) {
lookup(NEON, EANsetB, gtin[i], dest); memcpy(d, EANsetB[gtin[i] - '0'], 4);
} else { } else {
lookup(NEON, EANsetA, gtin[i], dest); memcpy(d, EANsetA[gtin[i] - '0'], 4);
} }
} }
/* stop character */ /* stop character */
strcat(dest, "111"); strcpy(d, "111");
if (symbol->output_options & COMPLIANT_HEIGHT) { if (symbol->output_options & COMPLIANT_HEIGHT) {
/* BS EN 797:1996 4.5.1 Nominal dimensions 22.85mm / 0.33mm (X) ~ 69.24, /* BS EN 797:1996 4.5.1 Nominal dimensions 22.85mm / 0.33mm (X) ~ 69.24,
@ -535,8 +537,8 @@ static int isbnx(struct zint_symbol *symbol, unsigned char source[], const int s
int i; int i;
char check_digit; char check_digit;
to_upper(source); to_upper(source, src_len);
if (is_sane(ISBNX_SANE, source, src_len) != 0) { if (!is_sane(ISBNX_SANE_F, source, src_len)) {
strcpy(symbol->errtxt, "277: Invalid character in data (digits and \"X\" only)"); strcpy(symbol->errtxt, "277: Invalid character in data (digits and \"X\" only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -554,16 +556,15 @@ static int isbnx(struct zint_symbol *symbol, unsigned char source[], const int s
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
/* "X" can only occur in last position */ /* "X" cannot occur */
if (is_sane(NEON, source, 12) != 0) { if (!is_sane(NEON_F, source, 13)) {
strcpy(symbol->errtxt, "282: Invalid character in data, \"X\" allowed in last position only"); strcpy(symbol->errtxt, "282: Invalid character in data, \"X\" not allowed in ISBN-13");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
check_digit = gs1_check_digit(source, 12); check_digit = gs1_check_digit(source, 12);
if (source[src_len - 1] != check_digit) { if (source[12] != check_digit) {
sprintf(symbol->errtxt, "280: Invalid ISBN check digit '%c', expecting '%c'", sprintf(symbol->errtxt, "280: Invalid ISBN check digit '%c', expecting '%c'", source[12], check_digit);
source[src_len - 1], check_digit);
return ZINT_ERROR_INVALID_CHECK; return ZINT_ERROR_INVALID_CHECK;
} }
source[12] = '\0'; source[12] = '\0';
@ -578,7 +579,7 @@ static int isbnx(struct zint_symbol *symbol, unsigned char source[], const int s
} }
/* "X" can only occur in last position */ /* "X" can only occur in last position */
if (is_sane(NEON, source, 9) != 0) { if (!is_sane(NEON_F, source, 9)) {
strcpy(symbol->errtxt, "296: Invalid character in data, \"X\" allowed in last position only"); strcpy(symbol->errtxt, "296: Invalid character in data, \"X\" allowed in last position only");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -589,7 +590,7 @@ static int isbnx(struct zint_symbol *symbol, unsigned char source[], const int s
source[9], check_digit); source[9], check_digit);
return ZINT_ERROR_INVALID_CHECK; return ZINT_ERROR_INVALID_CHECK;
} }
for (i = 11; i > 2; i--) { for (i = 11; i > 2; i--) { /* This drops the check digit */
source[i] = source[i - 3]; source[i] = source[i - 3];
} }
source[0] = '9'; source[0] = '9';
@ -603,8 +604,9 @@ static int isbnx(struct zint_symbol *symbol, unsigned char source[], const int s
/* Add leading zeroes to EAN and UPC strings */ /* Add leading zeroes to EAN and UPC strings */
INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char source[], INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char source[],
unsigned char local_source[], int *p_with_addon) { unsigned char local_source[], int *p_with_addon, unsigned char *zfirst_part,
unsigned char first_part[14], second_part[6], zfirst_part[14], zsecond_part[6]; unsigned char *zsecond_part) {
unsigned char first_part[14], second_part[6];
int with_addon = 0; int with_addon = 0;
int first_len = 0, second_len = 0, zfirst_len = 0, zsecond_len = 0, i, h; int first_len = 0, second_len = 0, zfirst_len = 0, zsecond_len = 0, i, h;
@ -641,14 +643,10 @@ INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char
/* Calculate target lengths */ /* Calculate target lengths */
if (second_len == 0) { if (second_len == 0) {
zsecond_len = 0; zsecond_len = 0;
} else if (second_len <= 2) {
zsecond_len = 2;
} else { } else {
if (second_len <= 5) { zsecond_len = 5;
if (second_len <= 2) {
zsecond_len = 2;
} else {
zsecond_len = 5;
}
}
} }
switch (symbol->symbology) { switch (symbol->symbology) {
case BARCODE_EANX: case BARCODE_EANX:
@ -717,25 +715,29 @@ INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char
break; break;
} }
/* Copy adjusted data back to local_source */
/* Add leading zeroes */ /* Add leading zeroes */
zfirst_part[0] = '\0';
for (i = 0; i < (zfirst_len - first_len); i++) { for (i = 0; i < (zfirst_len - first_len); i++) {
ustrcat(zfirst_part, "0"); local_source[i] = '0';
} }
ustrcat(zfirst_part, first_part); ustrcpy(local_source + i, first_part);
if (zfirst_part) {
zsecond_part[0] = '\0'; ustrcpy(zfirst_part, local_source);
for (i = 0; i < (zsecond_len - second_len); i++) {
ustrcat(zsecond_part, "0");
} }
ustrcat(zsecond_part, second_part);
/* Copy adjusted data back to local_source */ if (with_addon) {
ustrcat(local_source, zfirst_part); h = (int) ustrlen(local_source);
if (*zsecond_part) { local_source[h++] = '+';
ustrcat(local_source, "+"); for (i = 0; i < (zsecond_len - second_len); i++) {
ustrcat(local_source, zsecond_part); local_source[h + i] = '0';
}
ustrcpy(local_source + h + i, second_part);
if (zsecond_part) {
ustrcpy(zsecond_part, local_source + h);
}
} else if (zsecond_part) {
*zsecond_part = '\0';
} }
if (p_with_addon) { if (p_with_addon) {
@ -746,30 +748,26 @@ INTERNAL int ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char
} }
INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int src_len, int cc_rows) { INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int src_len, int cc_rows) {
unsigned char first_part[14] = {0}, second_part[6] = {0}; unsigned char first_part[14], second_part[6];
unsigned char local_source[20] = {0}; /* Allow 13 + "+" + 5 + 1 */ unsigned char local_source[20]; /* Allow 13 + "+" + 5 + 1 */
char dest[1000] = {0}; char dest[1000] = {0};
int latch, reader, writer;
int with_addon; int with_addon;
int error_number = 0, i, plus_count; int error_number = 0, i, plus_count;
int addon_gap = 0; int addon_gap = 0;
int first_part_len, second_part_len; int first_part_len, second_part_len;
latch = FALSE;
writer = 0;
if (src_len > 19) { if (src_len > 19) {
strcpy(symbol->errtxt, "283: Input too long (19 character maximum)"); strcpy(symbol->errtxt, "283: Input too long (19 character maximum)");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
if (symbol->symbology != BARCODE_ISBNX) { if (symbol->symbology != BARCODE_ISBNX) {
/* ISBN has its own sanity routine */ /* ISBN has its own sanity routine */
if (is_sane(SODIUM, source, src_len) != 0) { if (!is_sane(SODIUM_PLS_F, source, src_len)) {
strcpy(symbol->errtxt, "284: Invalid character in data (digits and \"+\" only)"); strcpy(symbol->errtxt, "284: Invalid character in data (digits and \"+\" only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
} else { } else {
if (is_sane(ISBNX_ADDON_SANE, source, src_len) != 0) { if (!is_sane(ISBNX_ADDON_SANE_F, source, src_len)) {
strcpy(symbol->errtxt, "285: Invalid character in data (digits, \"X\" and \"+\" only)"); strcpy(symbol->errtxt, "285: Invalid character in data (digits, \"X\" and \"+\" only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -789,42 +787,19 @@ INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int src
} }
/* Add leading zeroes, checking max lengths of parts */ /* Add leading zeroes, checking max lengths of parts */
if (!ean_leading_zeroes(symbol, source, local_source, &with_addon)) { if (!ean_leading_zeroes(symbol, source, local_source, &with_addon, first_part, second_part)) {
sprintf(symbol->errtxt, "294: Input too long (%s)", sprintf(symbol->errtxt, "294: Input too long (%s)",
with_addon ? "5 character maximum for add-on" : "13 character maximum"); with_addon ? "5 character maximum for add-on" : "13 character maximum");
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
reader = 0;
if (with_addon) { if (with_addon) {
int local_length = (int) ustrlen(local_source);
do {
if (local_source[reader] == '+') {
first_part[writer] = '\0';
latch = TRUE;
reader++;
writer = 0;
}
if (latch) {
second_part[writer] = local_source[reader];
reader++;
writer++;
} else {
first_part[writer] = local_source[reader];
reader++;
writer++;
}
} while (reader <= local_length);
if (symbol->symbology == BARCODE_UPCA || symbol->symbology == BARCODE_UPCA_CHK if (symbol->symbology == BARCODE_UPCA || symbol->symbology == BARCODE_UPCA_CHK
|| symbol->symbology == BARCODE_UPCA_CC) { || symbol->symbology == BARCODE_UPCA_CC) {
addon_gap = symbol->option_2 >= 9 && symbol->option_2 <= 12 ? symbol->option_2 : 9; addon_gap = symbol->option_2 >= 9 && symbol->option_2 <= 12 ? symbol->option_2 : 9;
} else { } else {
addon_gap = symbol->option_2 >= 7 && symbol->option_2 <= 12 ? symbol->option_2 : 7; addon_gap = symbol->option_2 >= 7 && symbol->option_2 <= 12 ? symbol->option_2 : 7;
} }
} else {
ustrcpy(first_part, local_source);
} }
first_part_len = (int) ustrlen(first_part); first_part_len = (int) ustrlen(first_part);
@ -960,7 +935,7 @@ INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int src
second_part_len = (int) ustrlen(second_part); second_part_len = (int) ustrlen(second_part);
if (symbol->symbology == BARCODE_ISBNX) { /* Need to further check that add-on numeric only */ if (symbol->symbology == BARCODE_ISBNX) { /* Need to further check that add-on numeric only */
if (is_sane(NEON, second_part, second_part_len) != 0) { if (!is_sane(NEON_F, second_part, second_part_len)) {
strcpy(symbol->errtxt, "295: Invalid add-on data (digits only)"); strcpy(symbol->errtxt, "295: Invalid add-on data (digits only)");
return ZINT_ERROR_INVALID_DATA; return ZINT_ERROR_INVALID_DATA;
} }
@ -983,7 +958,7 @@ INTERNAL int eanx_cc(struct zint_symbol *symbol, unsigned char source[], int src
return ZINT_ERROR_TOO_LONG; return ZINT_ERROR_TOO_LONG;
} }
expand(symbol, (const char *) dest); expand(symbol, dest, (int) strlen(dest));
switch (symbol->symbology) { switch (symbol->symbology) {
case BARCODE_EANX_CC: case BARCODE_EANX_CC:

View File

@ -407,6 +407,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
unsigned char textpart1[5], textpart2[7], textpart3[7], textpart4[2]; unsigned char textpart1[5], textpart2[7], textpart3[7], textpart4[2];
int hide_text; int hide_text;
int i, r; int i, r;
int block_width = 0;
int text_height; /* Font pixel size (so whole integers) */ int text_height; /* Font pixel size (so whole integers) */
float text_gap; /* Gap between barcode and text */ float text_gap; /* Gap between barcode and text */
float guard_descent; float guard_descent;
@ -415,7 +416,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
float digit_ascent_factor = 0.25f; /* Assuming digit ascent roughly 25% less than font size */ float digit_ascent_factor = 0.25f; /* Assuming digit ascent roughly 25% less than font size */
float dot_overspill = 0.0f; float dot_overspill = 0.0f;
float dot_offset = 0.0f; float dot_offset = 0.0f;
int rect_count, last_row_start = 0; int rect_count = 0, last_row_start = 0;
struct zint_vector *vector; struct zint_vector *vector;
struct zint_vector_rect *rect, *last_rectangle = NULL; struct zint_vector_rect *rect, *last_rectangle = NULL;
@ -427,7 +428,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
vector_free(symbol); vector_free(symbol);
// Sanity check colours // Sanity check colours
error_number = output_check_colour_options(symbol); error_number = out_check_colour_options(symbol);
if (error_number != 0) { if (error_number != 0) {
return error_number; return error_number;
} }
@ -443,17 +444,17 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
vector->circles = NULL; vector->circles = NULL;
vector->strings = NULL; vector->strings = NULL;
large_bar_height = output_large_bar_height(symbol, 0 /*No rounding to scale*/); large_bar_height = out_large_bar_height(symbol, 0 /*No rounding to scale*/);
main_width = symbol->width; main_width = symbol->width;
if (is_extendable(symbol->symbology)) { if (is_extendable(symbol->symbology)) {
upceanflag = output_process_upcean(symbol, &main_width, &comp_xoffset, addon, &addon_gap); upceanflag = out_process_upcean(symbol, &main_width, &comp_xoffset, addon, &addon_gap);
} }
hide_text = ((!symbol->show_hrt) || (ustrlen(symbol->text) == 0)); hide_text = ((!symbol->show_hrt) || (ustrlen(symbol->text) == 0));
output_set_whitespace_offsets(symbol, hide_text, &xoffset, &yoffset, &roffset, &boffset, 0 /*scaler*/, out_set_whitespace_offsets(symbol, hide_text, &xoffset, &yoffset, &roffset, &boffset, 0 /*scaler*/,
NULL, NULL, NULL, NULL); NULL, NULL, NULL, NULL);
/* Note font sizes scaled by 2 so really twice these values */ /* Note font sizes scaled by 2 so really twice these values */
@ -540,12 +541,12 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
/* Hexagons */ /* Hexagons */
for (r = 0; r < symbol->rows; r++) { for (r = 0; r < symbol->rows; r++) {
const int odd_row = r & 1; /* Odd (reduced) row, even (full) row */ const int odd_row = r & 1; /* Odd (reduced) row, even (full) row */
const float yposn = r * yposn_offset + hex_yradius + yoffset; const float hex_yposn = r * yposn_offset + hex_yradius + yoffset;
const float xposn_offset = (odd_row ? hex_diameter : hex_radius) + xoffset; const float xposn_offset = (odd_row ? hex_diameter : hex_radius) + xoffset;
for (i = 0; i < symbol->width - odd_row; i++) { for (i = 0; i < symbol->width - odd_row; i++) {
if (module_is_set(symbol, r, i)) { if (module_is_set(symbol, r, i)) {
const float xposn = i * hex_diameter + xposn_offset; const float hex_xposn = i * hex_diameter + xposn_offset;
hexagon = vector_plot_create_hexagon(symbol, xposn, yposn, hex_diameter); hexagon = vector_plot_create_hexagon(symbol, hex_xposn, hex_yposn, hex_diameter);
if (!hexagon) return ZINT_ERROR_MEMORY; if (!hexagon) return ZINT_ERROR_MEMORY;
vector_plot_add_hexagon(symbol, hexagon, &last_hexagon); vector_plot_add_hexagon(symbol, hexagon, &last_hexagon);
} }
@ -564,79 +565,93 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
} }
} }
// Plot rectangles - most symbols created here // Plot rectangles - most symbols created here
} else { } else if (symbol->symbology == BARCODE_ULTRA) {
rect_count = 0; yposn = yoffset;
for (r = 0; r < symbol->rows; r++) {
float row_height = symbol->row_height[r];
last_row_start = rect_count;
for (i = 0; i < symbol->width; i += block_width) {
int fill = module_colour_is_set(symbol, r, i);
for (block_width = 1; (i + block_width < symbol->width)
&& module_colour_is_set(symbol, r, i + block_width) == fill; block_width++);
if (fill) {
/* a colour block */
rect = vector_plot_create_rect(symbol, i + xoffset, yposn, block_width, row_height);
if (!rect) return ZINT_ERROR_MEMORY;
rect->colour = module_colour_is_set(symbol, r, i);
vector_plot_add_rect(symbol, rect, &last_rectangle);
rect_count++;
}
}
yposn += row_height;
}
} else if (upceanflag >= 6) { /* UPC-E, EAN-8, UPC-A, EAN-13 */
yposn = yoffset; yposn = yoffset;
for (r = 0; r < symbol->rows; r++) { for (r = 0; r < symbol->rows; r++) {
float row_height = symbol->row_height[r] ? symbol->row_height[r] : large_bar_height; float row_height = symbol->row_height[r] ? symbol->row_height[r] : large_bar_height;
last_row_start = rect_count; last_row_start = rect_count;
i = 0; for (i = 0; i < symbol->width; i += block_width) {
float addon_row_height;
int fill = module_is_set(symbol, r, i);
for (block_width = 1; (i + block_width < symbol->width)
&& module_is_set(symbol, r, i + block_width) == fill; block_width++);
if (symbol->symbology == BARCODE_ULTRA) { if ((r == (symbol->rows - 1)) && (i > main_width) && (addon_latch == 0)) {
do { addon_text_yposn = yposn + text_height - text_height * digit_ascent_factor;
int module_fill = module_colour_is_set(symbol, r, i); if (addon_text_yposn < 0.0f) {
int block_width = 0; addon_text_yposn = 0.0f;
do { }
block_width++; addon_row_height = row_height - (addon_text_yposn - yposn) + text_gap;
} while (i + block_width < symbol->width if (upceanflag != 12 && upceanflag != 6) { /* UPC-A/E add-ons don't descend */
&& module_colour_is_set(symbol, r, i + block_width) == module_fill); addon_row_height += guard_descent;
if (module_fill) { }
/* a colour block */ if (addon_row_height < 0.5f) {
addon_row_height = 0.5f;
}
addon_latch = 1;
}
if (fill) {
/* a bar */
if (addon_latch) {
rect = vector_plot_create_rect(symbol, i + xoffset, addon_text_yposn - text_gap,
block_width, addon_row_height);
} else {
rect = vector_plot_create_rect(symbol, i + xoffset, yposn, block_width, row_height); rect = vector_plot_create_rect(symbol, i + xoffset, yposn, block_width, row_height);
if (!rect) return ZINT_ERROR_MEMORY;
rect->colour = module_colour_is_set(symbol, r, i);
vector_plot_add_rect(symbol, rect, &last_rectangle);
rect_count++;
} }
i += block_width; if (!rect) return ZINT_ERROR_MEMORY;
vector_plot_add_rect(symbol, rect, &last_rectangle);
rect_count++;
}
}
yposn += row_height;
}
} while (i < symbol->width); } else {
} else { yposn = yoffset;
do { for (r = 0; r < symbol->rows; r++) {
float addon_row_height; float row_height = symbol->row_height[r] ? symbol->row_height[r] : large_bar_height;
int module_fill = module_is_set(symbol, r, i); last_row_start = rect_count;
int block_width = 0;
do {
block_width++;
} while (i + block_width < symbol->width
&& module_is_set(symbol, r, i + block_width) == module_fill);
if (upceanflag && (addon_latch == 0) && (r == (symbol->rows - 1)) && (i > main_width)) { for (i = 0; i < symbol->width; i += block_width) {
addon_text_yposn = yposn + text_height - text_height * digit_ascent_factor; int fill = module_is_set(symbol, r, i);
if (addon_text_yposn < 0.0f) { for (block_width = 1; (i + block_width < symbol->width)
addon_text_yposn = 0.0f; && module_is_set(symbol, r, i + block_width) == fill; block_width++);
} if (fill) {
addon_row_height = row_height - (addon_text_yposn - yposn) + text_gap; /* a bar */
if (upceanflag != 12 && upceanflag != 6) { /* UPC-A/E add-ons don't descend */ rect = vector_plot_create_rect(symbol, i + xoffset, yposn, block_width, row_height);
addon_row_height += guard_descent; if (!rect) return ZINT_ERROR_MEMORY;
} vector_plot_add_rect(symbol, rect, &last_rectangle);
if (addon_row_height < 0.5f) { rect_count++;
addon_row_height = 0.5f; }
}
addon_latch = 1;
}
if (module_fill) {
/* a bar */
if (addon_latch == 0) {
rect = vector_plot_create_rect(symbol, i + xoffset, yposn, block_width, row_height);
} else {
rect = vector_plot_create_rect(symbol, i + xoffset, addon_text_yposn - text_gap,
block_width, addon_row_height);
}
if (!rect) return ZINT_ERROR_MEMORY;
vector_plot_add_rect(symbol, rect, &last_rectangle);
rect_count++;
}
i += block_width;
} while (i < symbol->width);
} }
yposn += row_height; yposn += row_height;
} }
} }
if (upceanflag) { if (guard_descent && upceanflag >= 6) { /* UPC-E, EAN-8, UPC-A, EAN-13 */
/* Guard bar extension */ /* Guard bar extension */
if (upceanflag == 6) { /* UPC-E */ if (upceanflag == 6) { /* UPC-E */
i = 0; i = 0;
@ -686,7 +701,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
} }
i++; i++;
} }
} else if (upceanflag == 13) { /* EAN-13 */ } else { /* EAN-13 */
i = 0; i = 0;
for (rect = symbol->vector->rectangles; rect != NULL; rect = rect->next) { for (rect = symbol->vector->rectangles; rect != NULL; rect = rect->next) {
switch (i - last_row_start) { switch (i - last_row_start) {
@ -707,7 +722,6 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
/* Add the text */ /* Add the text */
if (!hide_text) { if (!hide_text) {
int textdone = 0;
float text_xposn; float text_xposn;
float text_yposn; float text_yposn;
@ -718,10 +732,10 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
text_yposn += symbol->border_width; text_yposn += symbol->border_width;
} }
if (upceanflag) { if (upceanflag >= 6) { /* UPC-E, EAN-8, UPC-A, EAN-13 */
float textwidth; float textwidth;
output_upcean_split_text(upceanflag, symbol->text, textpart1, textpart2, textpart3, textpart4); out_upcean_split_text(upceanflag, symbol->text, textpart1, textpart2, textpart3, textpart4);
if (upceanflag == 6) { /* UPC-E */ if (upceanflag == 6) { /* UPC-E */
text_xposn = -5.0f + xoffset; text_xposn = -5.0f + xoffset;
@ -736,7 +750,6 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
textwidth = 6.2f; textwidth = 6.2f;
if (!vector_plot_add_string(symbol, textpart3, text_xposn, text_yposn, upcae_outside_text_height, if (!vector_plot_add_string(symbol, textpart3, text_xposn, text_yposn, upcae_outside_text_height,
textwidth, 1 /*left align*/, &last_string)) return ZINT_ERROR_MEMORY; textwidth, 1 /*left align*/, &last_string)) return ZINT_ERROR_MEMORY;
textdone = 1;
switch (ustrlen(addon)) { switch (ustrlen(addon)) {
case 2: case 2:
text_xposn = 61.0f + xoffset + addon_gap; text_xposn = 61.0f + xoffset + addon_gap;
@ -760,7 +773,6 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
text_xposn = 50.0f + xoffset; text_xposn = 50.0f + xoffset;
if (!vector_plot_add_string(symbol, textpart2, text_xposn, text_yposn, if (!vector_plot_add_string(symbol, textpart2, text_xposn, text_yposn,
text_height, textwidth, 0, &last_string)) return ZINT_ERROR_MEMORY; text_height, textwidth, 0, &last_string)) return ZINT_ERROR_MEMORY;
textdone = 1;
switch (ustrlen(addon)) { switch (ustrlen(addon)) {
case 2: case 2:
text_xposn = 77.0f + xoffset + addon_gap; text_xposn = 77.0f + xoffset + addon_gap;
@ -792,7 +804,6 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
textwidth = 6.2f; textwidth = 6.2f;
if (!vector_plot_add_string(symbol, textpart4, text_xposn, text_yposn, upcae_outside_text_height, if (!vector_plot_add_string(symbol, textpart4, text_xposn, text_yposn, upcae_outside_text_height,
textwidth, 1 /*left align*/, &last_string)) return ZINT_ERROR_MEMORY; textwidth, 1 /*left align*/, &last_string)) return ZINT_ERROR_MEMORY;
textdone = 1;
switch (ustrlen(addon)) { switch (ustrlen(addon)) {
case 2: case 2:
text_xposn = 105.0f + xoffset + addon_gap; text_xposn = 105.0f + xoffset + addon_gap;
@ -808,7 +819,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
break; break;
} }
} else if (upceanflag == 13) { /* EAN-13 */ } else { /* EAN-13 */
text_xposn = -5.0f + xoffset; text_xposn = -5.0f + xoffset;
textwidth = 8.5f; textwidth = 8.5f;
if (!vector_plot_add_string(symbol, textpart1, text_xposn, text_yposn, if (!vector_plot_add_string(symbol, textpart1, text_xposn, text_yposn,
@ -820,7 +831,6 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
text_xposn = 71.0f + xoffset; text_xposn = 71.0f + xoffset;
if (!vector_plot_add_string(symbol, textpart3, text_xposn, text_yposn, if (!vector_plot_add_string(symbol, textpart3, text_xposn, text_yposn,
text_height, textwidth, 0, &last_string)) return ZINT_ERROR_MEMORY; text_height, textwidth, 0, &last_string)) return ZINT_ERROR_MEMORY;
textdone = 1;
switch (ustrlen(addon)) { switch (ustrlen(addon)) {
case 2: case 2:
text_xposn = 105.0f + xoffset + addon_gap; text_xposn = 105.0f + xoffset + addon_gap;
@ -836,9 +846,7 @@ INTERNAL int plot_vector(struct zint_symbol *symbol, int rotate_angle, int file_
break; break;
} }
} }
} } else {
if (!textdone) {
/* Put normal human readable text at the bottom (and centered) */ /* Put normal human readable text at the bottom (and centered) */
// calculate start xoffset to center text // calculate start xoffset to center text
text_xposn = main_width / 2.0f + xoffset; text_xposn = main_width / 2.0f + xoffset;

View File

@ -253,6 +253,7 @@ extern "C" {
#define BARCODE_UPNQR 143 /* UPNQR (Univerzalnega Plačilnega Naloga QR) */ #define BARCODE_UPNQR 143 /* UPNQR (Univerzalnega Plačilnega Naloga QR) */
#define BARCODE_ULTRA 144 /* Ultracode */ #define BARCODE_ULTRA 144 /* Ultracode */
#define BARCODE_RMQR 145 /* Rectangular Micro QR Code (rMQR) */ #define BARCODE_RMQR 145 /* Rectangular Micro QR Code (rMQR) */
#define BARCODE_LAST 145 /* Max barcode number marker, not barcode */
/* Output options (`symbol->output_options`) */ /* Output options (`symbol->output_options`) */
#define BARCODE_NO_ASCII 0x0001 /* Legacy (no-op) */ #define BARCODE_NO_ASCII 0x0001 /* Legacy (no-op) */

View File

@ -111,7 +111,7 @@ static const struct bstyle_item bstyle_items[] = {
{ QSL("POSTNET"), BARCODE_POSTNET }, { QSL("POSTNET"), BARCODE_POSTNET },
{ QSL("QR Code (ISO 18004) (and HIBC)"), BARCODE_QRCODE }, { QSL("QR Code (ISO 18004) (and HIBC)"), BARCODE_QRCODE },
{ QSL("Rectangular Micro QR (rMQR)"), BARCODE_RMQR }, { QSL("Rectangular Micro QR (rMQR)"), BARCODE_RMQR },
{ QSL("Royal Mail 4-state Barcode"), BARCODE_RM4SCC }, { QSL("Royal Mail 4-state Barcode (RM4SCC)"), BARCODE_RM4SCC },
{ QSL("Royal Mail 4-state Mailmark"), BARCODE_MAILMARK }, { QSL("Royal Mail 4-state Mailmark"), BARCODE_MAILMARK },
{ QSL("Telepen"), BARCODE_TELEPEN }, { QSL("Telepen"), BARCODE_TELEPEN },
{ QSL("Telepen Numeric"), BARCODE_TELEPEN_NUM }, { QSL("Telepen Numeric"), BARCODE_TELEPEN_NUM },