diff --git a/backend/auspost.c b/backend/auspost.c index 39d34147..5b047fca 100644 --- a/backend/auspost.c +++ b/backend/auspost.c @@ -70,24 +70,24 @@ static inline char convert_pattern(char data, int shift) { /* Adds Reed-Solomon error correction to auspost */ static void rs_error(char data_pattern[]) { - size_t reader, triple_writer = 0; - char triple[31]; + int reader, len, triple_writer = 0; + unsigned char triple[31]; unsigned char result[5]; + rs_t rs; - for (reader = 2; reader < strlen(data_pattern); reader += 3, triple_writer++) { + for (reader = 2, len = (int) strlen(data_pattern); reader < len; reader += 3, triple_writer++) { triple[triple_writer] = convert_pattern(data_pattern[reader], 4) + convert_pattern(data_pattern[reader + 1], 2) + convert_pattern(data_pattern[reader + 2], 0); } - rs_init_gf(0x43); - rs_init_code(4, 1); - rs_encode(triple_writer, (unsigned char*) triple, result); + rs_init_gf(&rs, 0x43); + rs_init_code(&rs, 4, 1); + rs_encode(&rs, triple_writer, triple, result); for (reader = 4; reader > 0; reader--) { strcat(data_pattern, AusBarTable[(int) result[reader - 1]]); } - rs_free(); } /* Handles Australia Posts's 4 State Codes */ @@ -168,7 +168,7 @@ INTERNAL int australia_post(struct zint_symbol *symbol, unsigned char source[], localstr[zeroes] = '\0'; } - strcat(localstr, (char*) source); + strncat(localstr, (char *) source, length); h = strlen(localstr); /* Verifiy that the first 8 characters are numbers */ memcpy(dpid, localstr, 8); diff --git a/backend/aztec.c b/backend/aztec.c index 941a260d..0e0373fe 100644 --- a/backend/aztec.c +++ b/backend/aztec.c @@ -41,104 +41,75 @@ #define AZTEC_MAX_CAPACITY 19968 /* ISO/IEC 24778:2008 5.3 Table 1 Maximum Symbol Bit Capacity */ #define AZTEC_BIN_CAPACITY 17940 /* Above less 169 * 12 = 2028 bits (169 = 10% of 1664 + 3) */ +#define AZTEC_MAP_SIZE 22801 /* AztecMap Version 32 151 x 151 */ -static int AztecMap[22801]; - -static int count_doubles(const unsigned char source[], const int posn, const size_t src_len) { +static int count_doubles(const unsigned char source[], int i, const int length) { int c = 0; - int i = posn; - int cond = 1; - while ((i + 1 < (int) src_len) && cond) { - if (((source[i] == '.') || (source[i] == ',')) && (source[i + 1] == ' ')) { - c++; - } else { - cond = 0; - } + while ((i + 1 < length) && ((source[i] == '.') || (source[i] == ',')) && (source[i + 1] == ' ')) { + c++; i += 2; } return c; } -static int count_cr(unsigned char source[], int posn, int length) { +static int count_cr(unsigned char source[], int i, const int length) { int c = 0; - int i = posn; - int cond = 1; - while ((i < length) && cond) { - if (source[i] == 13) { - c++; - } else { - cond = 0; - } + while (i < length && source[i] == 13) { + c++; i++; } return c; } -static int count_dotcomma(unsigned char source[], int posn, int length) { +static int count_dotcomma(unsigned char source[], int i, const int length) { int c = 0; - int i = posn; - int cond = 1; - while ((i < length) && cond) { - if ((source[i] == '.') || (source[i] == ',')) { - c++; - } else { - cond = 0; - } + while (i < length && ((source[i] == '.') || (source[i] == ','))) { + c++; i++; } return c; } -static int count_spaces(unsigned char source[], int posn, int length) { +static int count_spaces(unsigned char source[], int i, const int length) { int c = 0; - int i = posn; - int cond = 1; - while ((i < length) && cond) { - if (source[i] == ' ') { - c++; - } else { - cond = 0; - } + while (i < length && source[i] == ' ') { + c++; i++; } return c; } -static char get_next_mode(char encode_mode[], const size_t src_len, const int posn) { - int i = posn; +static char get_next_mode(char encode_mode[], const int src_len, int i) { + int current_mode = encode_mode[i]; do { i++; - } while ((i < (int) src_len) && (encode_mode[i] == encode_mode[posn])); - if (i >= (int) src_len) { + } while ((i < src_len) && (encode_mode[i] == current_mode)); + if (i >= src_len) { return 'E'; } else { return encode_mode[i]; } } -static int az_bin_append(const int arg, const int length, char *binary) { - size_t posn = strlen(binary); +static int az_bin_append_posn(const int arg, const int length, char *binary, int posn) { if (posn + length > AZTEC_BIN_CAPACITY) { return 0; /* Fail */ } - bin_append_posn(arg, length, binary, posn); - - binary[posn + length] = '\0'; - - return 1; /* Success */ + return bin_append_posn(arg, length, binary, posn); } -static int aztec_text_process(const unsigned char source[], const size_t src_len, char binary_string[], const int gs1, const int eci, const int debug) { +static int aztec_text_process(const unsigned char source[], int src_len, char binary_string[], const int gs1, + const int eci, int *data_length, const int debug) { int i, j; char current_mode; @@ -146,6 +117,7 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len char next_mode; int reduced_length; int byte_mode = 0; + int bp; #ifndef _MSC_VER char encode_mode[src_len + 1]; @@ -157,7 +129,7 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len char *reduced_encode_mode = (char *) _alloca(src_len + 1); #endif - for (i = 0; i < (int) src_len; i++) { + for (i = 0; i < src_len; i++) { if (source[i] >= 128) { encode_mode[i] = 'B'; } else { @@ -168,20 +140,18 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len // Deal first with letter combinations which can be combined to one codeword // Combinations are (CR LF) (. SP) (, SP) (: SP) in Punct mode current_mode = 'U'; - for (i = 0; i + 1 < (int) src_len; i++) { + for (i = 0; i + 1 < src_len; i++) { // Combination (CR LF) should always be in Punct mode if ((source[i] == 13) && (source[i + 1] == 10)) { encode_mode[i] = 'P'; encode_mode[i + 1] = 'P'; - } // Combination (: SP) should always be in Punct mode - if ((source[i] == ':') && (source[i + 1] == ' ')) { + } else if ((source[i] == ':') && (source[i + 1] == ' ')) { encode_mode[i + 1] = 'P'; - } // Combinations (. SP) and (, SP) sometimes use fewer bits in Digit mode - if (((source[i] == '.') || (source[i] == ',')) && (source[i + 1] == ' ') && (encode_mode[i] == 'X')) { + } else if (((source[i] == '.') || (source[i] == ',')) && (source[i + 1] == ' ') && (encode_mode[i] == 'X')) { count = count_doubles(source, i, src_len); next_mode = get_next_mode(encode_mode, src_len, i); @@ -191,34 +161,26 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len encode_mode[i + j] = 'D'; } } - } - if (current_mode == 'L') { - if ((next_mode == 'U') && (count == 1)) { - encode_mode[i] = 'D'; - encode_mode[i + 1] = 'D'; - } + } else if (current_mode == 'L') { if ((next_mode == 'D') && (count <= 4)) { for (j = 0; j < (2 * count); j++) { encode_mode[i + j] = 'D'; } } - } - if (current_mode == 'M') { + } else if (current_mode == 'M') { if ((next_mode == 'D') && (count == 1)) { encode_mode[i] = 'D'; encode_mode[i + 1] = 'D'; } - } - if (current_mode == 'D') { + } else if (current_mode == 'D') { if ((next_mode != 'D') && (count <= 4)) { for (j = 0; j < (2 * count); j++) { encode_mode[i + j] = 'D'; } - } - if ((next_mode == 'D') && (count <= 7)) { + } else if ((next_mode == 'D') && (count <= 7)) { for (j = 0; j < (2 * count); j++) { encode_mode[i + j] = 'D'; } @@ -239,7 +201,7 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len if (debug) { printf("First Pass:\n"); - for (i = 0; i < (int) src_len; i++) { + for (i = 0; i < src_len; i++) { printf("%c", encode_mode[i]); } printf("\n"); @@ -248,23 +210,29 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len // Reduce two letter combinations to one codeword marked as [abcd] in Punct mode i = 0; j = 0; - while (i < (int) src_len) { - if ((source[i] == 13) && (i + 1 < (int) src_len) && (source[i + 1] == 10)) { // CR LF - reduced_source[j] = 'a'; - reduced_encode_mode[j] = encode_mode[i]; - i += 2; - } else if ((source[i] == '.') && (i + 1 < (int) src_len) && (source[i + 1] == ' ') && (encode_mode[i] == 'P')) { - reduced_source[j] = 'b'; - reduced_encode_mode[j] = encode_mode[i]; - i += 2; - } else if ((source[i] == ',') && (i + 1 < (int) src_len) && (source[i + 1] == ' ') && (encode_mode[i] == 'P')) { - reduced_source[j] = 'c'; - reduced_encode_mode[j] = encode_mode[i]; - i += 2; - } else if ((source[i] == ':') && (i + 1 < (int) src_len) && (source[i + 1] == ' ')) { - reduced_source[j] = 'd'; - reduced_encode_mode[j] = encode_mode[i]; - i += 2; + while (i < src_len) { + if (i + 1 < src_len) { + if ((source[i] == 13) && (source[i + 1] == 10)) { // CR LF + reduced_source[j] = 'a'; + reduced_encode_mode[j] = encode_mode[i]; + i += 2; + } else if ((source[i] == '.') && (source[i + 1] == ' ') && (encode_mode[i] == 'P')) { + reduced_source[j] = 'b'; + reduced_encode_mode[j] = encode_mode[i]; + i += 2; + } else if ((source[i] == ',') && (source[i + 1] == ' ') && (encode_mode[i] == 'P')) { + reduced_source[j] = 'c'; + reduced_encode_mode[j] = encode_mode[i]; + i += 2; + } else if ((source[i] == ':') && (source[i + 1] == ' ')) { + reduced_source[j] = 'd'; + reduced_encode_mode[j] = encode_mode[i]; + i += 2; + } else { + reduced_source[j] = source[i]; + reduced_encode_mode[j] = encode_mode[i]; + i++; + } } else { reduced_source[j] = source[i]; reduced_encode_mode[j] = encode_mode[i]; @@ -284,13 +252,11 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len if ((current_mode == 'U') && ((next_mode == 'U') || (next_mode == 'B')) && (count == 1)) { reduced_encode_mode[i] = 'P'; - } - if ((current_mode == 'L') && ((next_mode == 'L') || (next_mode == 'B')) && (count == 1)) { + } else if ((current_mode == 'L') && ((next_mode == 'L') || (next_mode == 'B')) && (count == 1)) { reduced_encode_mode[i] = 'P'; - } - if ((current_mode == 'P') || (next_mode == 'P')) { + } else if ((current_mode == 'P') || (next_mode == 'P')) { reduced_encode_mode[i] = 'P'; } @@ -299,8 +265,7 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'P'; } - } - if ((next_mode == 'L') && (count == 1)) { + } else if ((next_mode == 'L') && (count == 1)) { reduced_encode_mode[i] = 'P'; } } @@ -309,10 +274,9 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len if (reduced_encode_mode[i] == 'X') { reduced_encode_mode[i] = 'M'; } - } // Resolve full stop and comma which can be in Punct or Digit mode - if ((reduced_source[i] == '.') || (reduced_source[i] == ',')) { + } else if ((reduced_source[i] == '.') || (reduced_source[i] == ',')) { count = count_dotcomma(reduced_source, i, reduced_length); next_mode = get_next_mode(reduced_encode_mode, reduced_length, i); @@ -320,33 +284,28 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len if (((next_mode == 'U') || (next_mode == 'L') || (next_mode == 'M') || (next_mode == 'B')) && (count == 1)) { reduced_encode_mode[i] = 'P'; } - } - if (current_mode == 'L') { + } else if (current_mode == 'L') { if ((next_mode == 'L') && (count <= 2)) { for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'P'; } - } - if (((next_mode == 'M') || (next_mode == 'B')) && (count == 1)) { + } else if (((next_mode == 'M') || (next_mode == 'B')) && (count == 1)) { reduced_encode_mode[i] = 'P'; } - } - if (current_mode == 'M') { + } else if (current_mode == 'M') { if (((next_mode == 'E') || (next_mode == 'U') || (next_mode == 'L') || (next_mode == 'M')) && (count <= 4)) { for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'P'; } - } - if ((next_mode == 'B') && (count <= 2)) { + } else if ((next_mode == 'B') && (count <= 2)) { for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'P'; } } - } - if ((current_mode == 'P') && (next_mode != 'D') && (count <= 9)) { + } else if ((current_mode == 'P') && (next_mode != 'D') && (count <= 9)) { for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'P'; } @@ -356,10 +315,9 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len if (reduced_encode_mode[i] == 'X') { reduced_encode_mode[i] = 'D'; } - } // Resolve Space (SP) which can be any mode except Punct - if (reduced_source[i] == ' ') { + } else if (reduced_source[i] == ' ') { count = count_spaces(reduced_source, i, reduced_length); next_mode = get_next_mode(reduced_encode_mode, reduced_length, i); @@ -368,63 +326,56 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'U'; } - } - if (((next_mode == 'U') || (next_mode == 'L') || (next_mode == 'M') || (next_mode == 'P') || (next_mode == 'B')) && (count <= 9)) { + } else if (((next_mode == 'U') || (next_mode == 'L') || (next_mode == 'M') || (next_mode == 'P') || (next_mode == 'B')) && (count <= 9)) { for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'U'; } } - } - if (current_mode == 'L') { + } else if (current_mode == 'L') { if ((next_mode == 'E') && (count <= 5)) { for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'L'; } - } - if ((next_mode == 'U') && (count == 1)) { - reduced_encode_mode[i] = 'L'; - } - if ((next_mode == 'L') && (count <= 14)) { - for (j = 0; j < count; j++) { - reduced_encode_mode[i + j] = 'L'; - } - } - if (((next_mode == 'M') || (next_mode == 'P') || (next_mode == 'B')) && (count <= 9)) { - for (j = 0; j < count; j++) { - reduced_encode_mode[i + j] = 'L'; - } - } - } - if (current_mode == 'M') { + } else if ((next_mode == 'U') && (count == 1)) { + reduced_encode_mode[i] = 'L'; + + } else if ((next_mode == 'L') && (count <= 14)) { + for (j = 0; j < count; j++) { + reduced_encode_mode[i + j] = 'L'; + } + + } else if (((next_mode == 'M') || (next_mode == 'P') || (next_mode == 'B')) && (count <= 9)) { + for (j = 0; j < count; j++) { + reduced_encode_mode[i + j] = 'L'; + } + } + + } else if (current_mode == 'M') { if (((next_mode == 'E') || (next_mode == 'U')) && (count <= 9)) { for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'M'; } - } - if (((next_mode == 'L') || (next_mode == 'B')) && (count <= 14)) { + } else if (((next_mode == 'L') || (next_mode == 'B')) && (count <= 14)) { + for (j = 0; j < count; j++) { + reduced_encode_mode[i + j] = 'M'; + } + + } else if (((next_mode == 'M') || (next_mode == 'P')) && (count <= 19)) { for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'M'; } } - if (((next_mode == 'M') || (next_mode == 'P')) && (count <= 19)) { - for (j = 0; j < count; j++) { - reduced_encode_mode[i + j] = 'M'; - } - } - } - - if (current_mode == 'P') { + } else if (current_mode == 'P') { if ((next_mode == 'E') && (count <= 5)) { for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'U'; } - } - if (((next_mode == 'U') || (next_mode == 'L') || (next_mode == 'M') || (next_mode == 'P') || (next_mode == 'B')) && (count <= 9)) { + } else if (((next_mode == 'U') || (next_mode == 'L') || (next_mode == 'M') || (next_mode == 'P') || (next_mode == 'B')) && (count <= 9)) { for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'U'; } @@ -456,57 +407,47 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'p'; } - } - if ((current_mode == 'L') && (next_mode != 'U') && (count <= 2)) { + } else if ((current_mode == 'L') && (next_mode != 'U') && (count <= 2)) { for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'p'; } - } - if ((current_mode == 'L') && (next_mode == 'U') && (count == 1)) { + } else if ((current_mode == 'L') && (next_mode == 'U') && (count == 1)) { reduced_encode_mode[i] = 'p'; - } - if ((current_mode == 'M') && (next_mode != 'M') && (count == 1)) { + } else if ((current_mode == 'M') && (next_mode != 'M') && (count == 1)) { reduced_encode_mode[i] = 'p'; - } - if ((current_mode == 'M') && (next_mode == 'M') && (count <= 2)) { + } else if ((current_mode == 'M') && (next_mode == 'M') && (count <= 2)) { + for (j = 0; j < count; j++) { + reduced_encode_mode[i + j] = 'p'; + } + + } else if ((current_mode == 'D') && (next_mode != 'D') && (count <= 3)) { + for (j = 0; j < count; j++) { + reduced_encode_mode[i + j] = 'p'; + } + + } else if ((current_mode == 'D') && (next_mode == 'D') && (count <= 6)) { for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'p'; } } - if ((current_mode == 'D') && (next_mode != 'D') && (count <= 3)) { - for (j = 0; j < count; j++) { - reduced_encode_mode[i + j] = 'p'; - } - } - - if ((current_mode == 'D') && (next_mode == 'D') && (count <= 6)) { - for (j = 0; j < count; j++) { - reduced_encode_mode[i + j] = 'p'; - } - } - } - - if (reduced_encode_mode[i] == 'U') { + } else if (reduced_encode_mode[i] == 'U') { if ((current_mode == 'L') && ((next_mode == 'L') || (next_mode == 'M')) && (count <= 2)) { for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'u'; } - } - if ((current_mode == 'L') && ((next_mode == 'E') || (next_mode == 'D') || (next_mode == 'B') || (next_mode == 'P')) && (count == 1)) { + } else if ((current_mode == 'L') && ((next_mode == 'E') || (next_mode == 'D') || (next_mode == 'B') || (next_mode == 'P')) && (count == 1)) { reduced_encode_mode[i] = 'u'; - } - if ((current_mode == 'D') && (next_mode == 'D') && (count == 1)) { + } else if ((current_mode == 'D') && (next_mode == 'D') && (count == 1)) { reduced_encode_mode[i] = 'u'; - } - if ((current_mode == 'D') && (next_mode == 'P') && (count <= 2)) { + } else if ((current_mode == 'D') && (next_mode == 'P') && (count <= 2)) { for (j = 0; j < count; j++) { reduced_encode_mode[i + j] = 'u'; } @@ -531,54 +472,50 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len } *binary_string = '\0'; + bp = 0; if (gs1) { - bin_append(0, 5, binary_string); // P/S - bin_append(0, 5, binary_string); // FLG(n) - bin_append(0, 3, binary_string); // FLG(0) + bp = bin_append_posn(0, 5, binary_string, bp); // P/S + bp = bin_append_posn(0, 5, binary_string, bp); // FLG(n) + bp = bin_append_posn(0, 3, binary_string, bp); // FLG(0) } if (eci != 0) { - bin_append(0, 5, binary_string); // P/S - bin_append(0, 5, binary_string); // FLG(n) + bp = bin_append_posn(0, 5, binary_string, bp); // P/S + bp = bin_append_posn(0, 5, binary_string, bp); // FLG(n) if (eci < 10) { - bin_append(1, 3, binary_string); // FLG(1) - bin_append(2 + eci, 4, binary_string); - } - if ((eci >= 10) && (eci <= 99)) { - bin_append(2, 3, binary_string); // FLG(2) - bin_append(2 + (eci / 10), 4, binary_string); - bin_append(2 + (eci % 10), 4, binary_string); - } - if ((eci >= 100) && (eci <= 999)) { - bin_append(3, 3, binary_string); // FLG(3) - bin_append(2 + (eci / 100), 4, binary_string); - bin_append(2 + ((eci % 100) / 10), 4, binary_string); - bin_append(2 + (eci % 10), 4, binary_string); - } - if ((eci >= 1000) && (eci <= 9999)) { - bin_append(4, 3, binary_string); // FLG(4) - bin_append(2 + (eci / 1000), 4, binary_string); - bin_append(2 + ((eci % 1000) / 100), 4, binary_string); - bin_append(2 + ((eci % 100) / 10), 4, binary_string); - bin_append(2 + (eci % 10), 4, binary_string); - } - if ((eci >= 10000) && (eci <= 99999)) { - bin_append(5, 3, binary_string); // FLG(5) - bin_append(2 + (eci / 10000), 4, binary_string); - bin_append(2 + ((eci % 10000) / 1000), 4, binary_string); - bin_append(2 + ((eci % 1000) / 100), 4, binary_string); - bin_append(2 + ((eci % 100) / 10), 4, binary_string); - bin_append(2 + (eci % 10), 4, binary_string); - } - if (eci >= 100000) { - bin_append(6, 3, binary_string); // FLG(6) - bin_append(2 + (eci / 100000), 4, binary_string); - bin_append(2 + ((eci % 100000) / 10000), 4, binary_string); - bin_append(2 + ((eci % 10000) / 1000), 4, binary_string); - bin_append(2 + ((eci % 1000) / 100), 4, binary_string); - bin_append(2 + ((eci % 100) / 10), 4, binary_string); - bin_append(2 + (eci % 10), 4, binary_string); + bp = bin_append_posn(1, 3, binary_string, bp); // FLG(1) + bp = bin_append_posn(2 + eci, 4, binary_string, bp); + } else if (eci <= 99) { + bp = bin_append_posn(2, 3, binary_string, bp); // FLG(2) + bp = bin_append_posn(2 + (eci / 10), 4, binary_string, bp); + bp = bin_append_posn(2 + (eci % 10), 4, binary_string, bp); + } else if (eci <= 999) { + bp = bin_append_posn(3, 3, binary_string, bp); // FLG(3) + bp = bin_append_posn(2 + (eci / 100), 4, binary_string, bp); + bp = bin_append_posn(2 + ((eci % 100) / 10), 4, binary_string, bp); + bp = bin_append_posn(2 + (eci % 10), 4, binary_string, bp); + } else if (eci <= 9999) { + bp = bin_append_posn(4, 3, binary_string, bp); // FLG(4) + bp = bin_append_posn(2 + (eci / 1000), 4, binary_string, bp); + bp = bin_append_posn(2 + ((eci % 1000) / 100), 4, binary_string, bp); + bp = bin_append_posn(2 + ((eci % 100) / 10), 4, binary_string, bp); + bp = bin_append_posn(2 + (eci % 10), 4, binary_string, bp); + } else if (eci <= 99999) { + bp = bin_append_posn(5, 3, binary_string, bp); // FLG(5) + bp = bin_append_posn(2 + (eci / 10000), 4, binary_string, bp); + bp = bin_append_posn(2 + ((eci % 10000) / 1000), 4, binary_string, bp); + bp = bin_append_posn(2 + ((eci % 1000) / 100), 4, binary_string, bp); + bp = bin_append_posn(2 + ((eci % 100) / 10), 4, binary_string, bp); + bp = bin_append_posn(2 + (eci % 10), 4, binary_string, bp); + } else { + bp = bin_append_posn(6, 3, binary_string, bp); // FLG(6) + bp = bin_append_posn(2 + (eci / 100000), 4, binary_string, bp); + bp = bin_append_posn(2 + ((eci % 100000) / 10000), 4, binary_string, bp); + bp = bin_append_posn(2 + ((eci % 10000) / 1000), 4, binary_string, bp); + bp = bin_append_posn(2 + ((eci % 1000) / 100), 4, binary_string, bp); + bp = bin_append_posn(2 + ((eci % 100) / 10), 4, binary_string, bp); + bp = bin_append_posn(2 + (eci % 10), 4, binary_string, bp); } } @@ -594,132 +531,124 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len if (current_mode == 'U') { switch (reduced_encode_mode[i]) { case 'L': - if (!az_bin_append(28, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // L/L + if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // L/L break; case 'M': - if (!az_bin_append(29, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // M/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // M/L break; case 'P': - if (!az_bin_append(29, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // M/L - if (!az_bin_append(30, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // P/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // M/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/L break; case 'p': - if (!az_bin_append(0, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // P/S + if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/S break; case 'D': - if (!az_bin_append(30, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // D/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // D/L break; case 'B': - if (!az_bin_append(31, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // B/S + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // B/S break; } - } - - if (current_mode == 'L') { + } else if (current_mode == 'L') { switch (reduced_encode_mode[i]) { case 'U': - if (!az_bin_append(30, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // D/L - if (!az_bin_append(14, 4, binary_string)) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // D/L + if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L break; case 'u': - if (!az_bin_append(28, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // U/S + if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/S break; case 'M': - if (!az_bin_append(29, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // M/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // M/L break; case 'P': - if (!az_bin_append(29, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // M/L - if (!az_bin_append(30, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // P/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // M/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/L break; case 'p': - if (!az_bin_append(0, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // P/S + if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/S break; case 'D': - if (!az_bin_append(30, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // D/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // D/L break; case 'B': - if (!az_bin_append(31, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // B/S + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // B/S break; } - } - - if (current_mode == 'M') { + } else if (current_mode == 'M') { switch (reduced_encode_mode[i]) { case 'U': - if (!az_bin_append(29, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L break; case 'L': - if (!az_bin_append(28, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // L/L + if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // L/L break; case 'P': - if (!az_bin_append(30, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // P/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/L break; case 'p': - if (!az_bin_append(0, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // P/S + if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/S break; case 'D': - if (!az_bin_append(29, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // U/L - if (!az_bin_append(30, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // D/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // D/L break; case 'B': - if (!az_bin_append(31, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // B/S + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // B/S break; } - } - - if (current_mode == 'P') { + } else if (current_mode == 'P') { switch (reduced_encode_mode[i]) { case 'U': - if (!az_bin_append(31, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L break; case 'L': - if (!az_bin_append(31, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // U/L - if (!az_bin_append(28, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // L/L + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // L/L break; case 'M': - if (!az_bin_append(31, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // U/L - if (!az_bin_append(29, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // M/L + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // M/L break; case 'D': - if (!az_bin_append(31, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // U/L - if (!az_bin_append(30, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // D/L + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // D/L break; case 'B': - if (!az_bin_append(31, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L current_mode = 'U'; - if (!az_bin_append(31, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // B/S + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // B/S break; } - } - - if (current_mode == 'D') { + } else if (current_mode == 'D') { switch (reduced_encode_mode[i]) { case 'U': - if (!az_bin_append(14, 4, binary_string)) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L break; case 'u': - if (!az_bin_append(15, 4, binary_string)) return ZINT_ERROR_TOO_LONG; // U/S + if (!(bp = az_bin_append_posn(15, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/S break; case 'L': - if (!az_bin_append(14, 4, binary_string)) return ZINT_ERROR_TOO_LONG; // U/L - if (!az_bin_append(28, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // L/L + if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(28, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // L/L break; case 'M': - if (!az_bin_append(14, 4, binary_string)) return ZINT_ERROR_TOO_LONG; // U/L - if (!az_bin_append(29, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // M/L + if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // M/L break; case 'P': - if (!az_bin_append(14, 4, binary_string)) return ZINT_ERROR_TOO_LONG; // U/L - if (!az_bin_append(29, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // M/L - if (!az_bin_append(30, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // P/L + if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(29, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // M/L + if (!(bp = az_bin_append_posn(30, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/L break; case 'p': - if (!az_bin_append(0, 4, binary_string)) return ZINT_ERROR_TOO_LONG; // P/S + if (!(bp = az_bin_append_posn(0, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // P/S break; case 'B': - if (!az_bin_append(14, 4, binary_string)) return ZINT_ERROR_TOO_LONG; // U/L + if (!(bp = az_bin_append_posn(14, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // U/L current_mode = 'U'; - if (!az_bin_append(31, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // B/S + if (!(bp = az_bin_append_posn(31, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // B/S break; } } @@ -734,11 +663,11 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len if (count > 31) { /* Put 00000 followed by 11-bit number of bytes less 31 */ - if (!az_bin_append(0, 5, binary_string)) return ZINT_ERROR_TOO_LONG; - if (!az_bin_append(count - 31, 11, binary_string)) return ZINT_ERROR_TOO_LONG; + if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; + if (!(bp = az_bin_append_posn(count - 31, 11, binary_string, bp))) return ZINT_ERROR_TOO_LONG; } else { /* Put 5-bit number of bytes */ - if (!az_bin_append(count, 5, binary_string)) return ZINT_ERROR_TOO_LONG; + if (!(bp = az_bin_append_posn(count, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; } byte_mode = 1; } @@ -750,67 +679,57 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len if ((reduced_encode_mode[i] == 'U') || (reduced_encode_mode[i] == 'u')) { if (reduced_source[i] == ' ') { - if (!az_bin_append(1, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // SP + if (!(bp = az_bin_append_posn(1, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // SP } else { - if (!az_bin_append(AztecSymbolChar[(int) reduced_source[i]], 5, binary_string)) return ZINT_ERROR_TOO_LONG; + if (!(bp = az_bin_append_posn(AztecSymbolChar[(int) reduced_source[i]], 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; } - } - - if (reduced_encode_mode[i] == 'L') { + } else if (reduced_encode_mode[i] == 'L') { if (reduced_source[i] == ' ') { - if (!az_bin_append(1, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // SP + if (!(bp = az_bin_append_posn(1, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // SP } else { - if (!az_bin_append(AztecSymbolChar[(int) reduced_source[i]], 5, binary_string)) return ZINT_ERROR_TOO_LONG; + if (!(bp = az_bin_append_posn(AztecSymbolChar[(int) reduced_source[i]], 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; } - } - - if (reduced_encode_mode[i] == 'M') { + } else if (reduced_encode_mode[i] == 'M') { if (reduced_source[i] == ' ') { - if (!az_bin_append(1, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // SP + if (!(bp = az_bin_append_posn(1, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // SP } else if (reduced_source[i] == 13) { - if (!az_bin_append(14, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // CR + if (!(bp = az_bin_append_posn(14, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // CR } else { - if (!az_bin_append(AztecSymbolChar[(int) reduced_source[i]], 5, binary_string)) return ZINT_ERROR_TOO_LONG; + if (!(bp = az_bin_append_posn(AztecSymbolChar[(int) reduced_source[i]], 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; } - } - - if ((reduced_encode_mode[i] == 'P') || (reduced_encode_mode[i] == 'p')) { + } else if ((reduced_encode_mode[i] == 'P') || (reduced_encode_mode[i] == 'p')) { if (gs1 && (reduced_source[i] == '[')) { - if (!az_bin_append(0, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // FLG(n) - if (!az_bin_append(0, 3, binary_string)) return ZINT_ERROR_TOO_LONG; // FLG(0) = FNC1 + if (!(bp = az_bin_append_posn(0, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // FLG(n) + if (!(bp = az_bin_append_posn(0, 3, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // FLG(0) = FNC1 } else if (reduced_source[i] == 13) { - if (!az_bin_append(1, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // CR + if (!(bp = az_bin_append_posn(1, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // CR } else if (reduced_source[i] == 'a') { - if (!az_bin_append(2, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // CR LF + if (!(bp = az_bin_append_posn(2, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // CR LF } else if (reduced_source[i] == 'b') { - if (!az_bin_append(3, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // . SP + if (!(bp = az_bin_append_posn(3, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // . SP } else if (reduced_source[i] == 'c') { - if (!az_bin_append(4, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // , SP + if (!(bp = az_bin_append_posn(4, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // , SP } else if (reduced_source[i] == 'd') { - if (!az_bin_append(5, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // : SP + if (!(bp = az_bin_append_posn(5, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // : SP } else if (reduced_source[i] == ',') { - if (!az_bin_append(17, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // Comma + if (!(bp = az_bin_append_posn(17, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // Comma } else if (reduced_source[i] == '.') { - if (!az_bin_append(19, 5, binary_string)) return ZINT_ERROR_TOO_LONG; // Full stop + if (!(bp = az_bin_append_posn(19, 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // Full stop } else { - if (!az_bin_append(AztecSymbolChar[(int) reduced_source[i]], 5, binary_string)) return ZINT_ERROR_TOO_LONG; + if (!(bp = az_bin_append_posn(AztecSymbolChar[(int) reduced_source[i]], 5, binary_string, bp))) return ZINT_ERROR_TOO_LONG; } - } - - if (reduced_encode_mode[i] == 'D') { + } else if (reduced_encode_mode[i] == 'D') { if (reduced_source[i] == ' ') { - if (!az_bin_append(1, 4, binary_string)) return ZINT_ERROR_TOO_LONG; // SP + if (!(bp = az_bin_append_posn(1, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // SP } else if (reduced_source[i] == ',') { - if (!az_bin_append(12, 4, binary_string)) return ZINT_ERROR_TOO_LONG; // Comma + if (!(bp = az_bin_append_posn(12, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // Comma } else if (reduced_source[i] == '.') { - if (!az_bin_append(13, 4, binary_string)) return ZINT_ERROR_TOO_LONG; // Full stop + if (!(bp = az_bin_append_posn(13, 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; // Full stop } else { - if (!az_bin_append(AztecSymbolChar[(int) reduced_source[i]], 4, binary_string)) return ZINT_ERROR_TOO_LONG; + if (!(bp = az_bin_append_posn(AztecSymbolChar[(int) reduced_source[i]], 4, binary_string, bp))) return ZINT_ERROR_TOO_LONG; } - } - - if (reduced_encode_mode[i] == 'B') { - if (!az_bin_append(reduced_source[i], 8, binary_string)) return ZINT_ERROR_TOO_LONG; + } else if (reduced_encode_mode[i] == 'B') { + if (!(bp = az_bin_append_posn(reduced_source[i], 8, binary_string, bp))) return ZINT_ERROR_TOO_LONG; } } @@ -819,6 +738,8 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len printf("%s\n", binary_string); } + *data_length = bp; + return 0; } @@ -826,46 +747,18 @@ static int aztec_text_process(const unsigned char source[], const size_t src_len static int avoidReferenceGrid(int output) { if (output > 10) { - output++; - } - if (output > 26) { - output++; - } - if (output > 42) { - output++; - } - if (output > 58) { - output++; - } - if (output > 74) { - output++; - } - if (output > 90) { - output++; - } - if (output > 106) { - output++; - } - if (output > 122) { - output++; - } - if (output > 138) { - output++; + output += (output - 11) / 15 + 1; } return output; } /* Calculate the position of the bits in the grid */ -static void populate_map() { +static void populate_map(int AztecMap[]) { int layer, n, i; int x, y; - for (x = 0; x < 151; x++) { - for (y = 0; y < 151; y++) { - AztecMap[(x * 151) + y] = 0; - } - } + memset(AztecMap, 0, sizeof(int) * AZTEC_MAP_SIZE); for (layer = 1; layer < 33; layer++) { const int start = (112 * (layer - 1)) + (16 * (layer - 1) * (layer - 1)) + 2; @@ -975,15 +868,18 @@ static void populate_map() { AztecMap[(avoidReferenceGrid(76) * 151) + avoidReferenceGrid(77)] = 1; } -INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], const size_t length) { +INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], int length) { int x, y, i, j, p, data_blocks, ecc_blocks, layers, total_bits; char binary_string[AZTEC_BIN_CAPACITY + 1], bit_pattern[20045], descriptor[42]; char adjusted_string[AZTEC_MAX_CAPACITY + 1]; + int AztecMap[AZTEC_MAP_SIZE]; unsigned char desc_data[4], desc_ecc[6]; int error_number, ecc_level, compact, data_length, data_maxsize, codeword_size, adjusted_length; int remainder, padbits, count, gs1, adjustment_size; int debug = (symbol->debug & ZINT_DEBUG_PRINT), reader = 0; int comp_loop = 4; + rs_t rs; + rs_uint_t rs_uint; #ifdef _MSC_VER unsigned int* data_part; @@ -1007,9 +903,9 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], const siz return ZINT_ERROR_INVALID_OPTION; } - populate_map(); + populate_map(AztecMap); - error_number = aztec_text_process(source, length, binary_string, gs1, symbol->eci, debug); + error_number = aztec_text_process(source, length, binary_string, gs1, symbol->eci, &data_length, debug); if (error_number != 0) { strcpy(symbol->errtxt, "502: Input too long or too many extended ASCII characters"); @@ -1032,9 +928,6 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], const siz ecc_level = 2; } - data_length = (int) strlen(binary_string); - - layers = 0; /* Keep compiler happy! */ data_maxsize = 0; /* Keep compiler happy! */ adjustment_size = 0; if (symbol->option_2 == 0) { /* The size of the symbol can be determined by Zint */ @@ -1114,14 +1007,13 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], const siz } /* Determine codeword bitlength - Table 3 */ - codeword_size = 6; /* if (layers <= 2) */ - if ((layers >= 3) && (layers <= 8)) { + if (layers <= 2) { + codeword_size = 6; + } else if (layers <= 8) { codeword_size = 8; - } - if ((layers >= 9) && (layers <= 22)) { + } else if (layers <= 22) { codeword_size = 10; - } - if (layers >= 23) { + } else { codeword_size = 12; } @@ -1162,9 +1054,9 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], const siz } for (i = 0; i < padbits; i++) { - strcat(adjusted_string, "1"); + adjusted_string[adjusted_length++] = '1'; } - adjusted_length = (int) strlen(adjusted_string); + adjusted_string[adjusted_length] = '\0'; count = 0; for (i = (adjusted_length - codeword_size); i < adjusted_length; i++) { @@ -1193,33 +1085,29 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], const siz be encoded in a symbol of the selected size */ } else { /* The size of the symbol has been specified by the user */ - if ((reader == 1) && ((symbol->option_2 >= 2) && (symbol->option_2 <= 4))) { - symbol->option_2 = 5; - } - if ((symbol->option_2 >= 1) && (symbol->option_2 <= 4)) { - compact = 1; - layers = symbol->option_2; - } - if ((symbol->option_2 >= 5) && (symbol->option_2 <= 36)) { - compact = 0; - layers = symbol->option_2 - 4; - } if ((symbol->option_2 < 0) || (symbol->option_2 > 36)) { strcpy(symbol->errtxt, "510: Invalid Aztec Code size"); return ZINT_ERROR_INVALID_OPTION; } + if ((reader == 1) && ((symbol->option_2 >= 2) && (symbol->option_2 <= 4))) { + symbol->option_2 = 5; + } + if (symbol->option_2 <= 4) { + compact = 1; + layers = symbol->option_2; + } else { + compact = 0; + layers = symbol->option_2 - 4; + } /* Determine codeword bitlength - Table 3 */ - if ((layers >= 0) && (layers <= 2)) { + if (layers <= 2) { codeword_size = 6; - } - if ((layers >= 3) && (layers <= 8)) { + } else if (layers <= 8) { codeword_size = 8; - } - if ((layers >= 9) && (layers <= 22)) { + } else if (layers <= 22) { codeword_size = 10; - } - if (layers >= 23) { + } else { codeword_size = 12; } @@ -1257,9 +1145,9 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], const siz } for (i = 0; i < padbits; i++) { - strcat(adjusted_string, "1"); + adjusted_string[adjusted_length++] = '1'; } - adjusted_length = (int) strlen(adjusted_string); + adjusted_string[adjusted_length] = '\0'; count = 0; for (i = (adjusted_length - codeword_size); i < adjusted_length; i++) { @@ -1348,25 +1236,32 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], const siz switch (codeword_size) { case 6: - rs_init_gf(0x43); + rs_init_gf(&rs, 0x43); + rs_init_code(&rs, ecc_blocks, 1); + rs_encode_uint(&rs, data_blocks, data_part, ecc_part); break; case 8: - rs_init_gf(0x12d); + rs_init_gf(&rs, 0x12d); + rs_init_code(&rs, ecc_blocks, 1); + rs_encode_uint(&rs, data_blocks, data_part, ecc_part); break; case 10: - rs_init_gf(0x409); + rs_uint_init_gf(&rs_uint, 0x409, 1023); + rs_uint_init_code(&rs_uint, ecc_blocks, 1); + rs_uint_encode(&rs_uint, data_blocks, data_part, ecc_part); + rs_uint_free(&rs_uint); break; case 12: - rs_init_gf(0x1069); + rs_uint_init_gf(&rs_uint, 0x1069, 4095); + rs_uint_init_code(&rs_uint, ecc_blocks, 1); + rs_uint_encode(&rs_uint, data_blocks, data_part, ecc_part); + rs_uint_free(&rs_uint); break; } - rs_init_code(ecc_blocks, 1); - rs_encode_long(data_blocks, data_part, ecc_part); for (i = (ecc_blocks - 1); i >= 0; i--) { - bin_append(ecc_part[i], codeword_size, adjusted_string); + adjusted_length = bin_append_posn(ecc_part[i], codeword_size, adjusted_string, adjusted_length); } - rs_free(); /* Invert the data so that actual data is on the outside and reed-solomon on the inside */ memset(bit_pattern, '0', 20045); @@ -1464,10 +1359,10 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], const siz /* Add reed-solomon error correction with Galois field GF(16) and prime modulus x^4 + x + 1 (section 7.2.3)*/ - rs_init_gf(0x13); + rs_init_gf(&rs, 0x13); if (compact) { - rs_init_code(5, 1); - rs_encode(2, desc_data, desc_ecc); + rs_init_code(&rs, 5, 1); + rs_encode(&rs, 2, desc_data, desc_ecc); for (i = 0; i < 5; i++) { if (desc_ecc[4 - i] & 0x08) { descriptor[(i * 4) + 8] = '1'; @@ -1491,8 +1386,8 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], const siz } } } else { - rs_init_code(6, 1); - rs_encode(4, desc_data, desc_ecc); + rs_init_code(&rs, 6, 1); + rs_encode(&rs, 4, desc_data, desc_ecc); for (i = 0; i < 6; i++) { if (desc_ecc[5 - i] & 0x08) { descriptor[(i * 4) + 16] = '1'; @@ -1516,7 +1411,6 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], const siz } } } - rs_free(); /* Merge descriptor with the rest of the symbol */ for (i = 0; i < 40; i++) { @@ -1529,39 +1423,43 @@ INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], const siz /* Plot all of the data into the symbol in pre-defined spiral pattern */ if (compact) { - - for (y = AztecCompactOffset[layers - 1]; y < (27 - AztecCompactOffset[layers - 1]); y++) { - for (x = AztecCompactOffset[layers - 1]; x < (27 - AztecCompactOffset[layers - 1]); x++) { - if (CompactAztecMap[(y * 27) + x] == 1) { - set_module(symbol, y - AztecCompactOffset[layers - 1], x - AztecCompactOffset[layers - 1]); - } - if (CompactAztecMap[(y * 27) + x] >= 2) { - if (bit_pattern[CompactAztecMap[(y * 27) + x] - 2] == '1') { - set_module(symbol, y - AztecCompactOffset[layers - 1], x - AztecCompactOffset[layers - 1]); + int offset = AztecCompactOffset[layers - 1]; + int end_offset = 27 - offset; + for (y = offset; y < end_offset; y++) { + int y_map = y * 27; + for (x = offset; x < end_offset; x++) { + int map = CompactAztecMap[y_map + x]; + if (map == 1) { + set_module(symbol, y - offset, x - offset); + } else if (map >= 2) { + if (bit_pattern[map - 2] == '1') { + set_module(symbol, y - offset, x - offset); } } } - symbol->row_height[y - AztecCompactOffset[layers - 1]] = 1; + symbol->row_height[y - offset] = 1; } - symbol->rows = 27 - (2 * AztecCompactOffset[layers - 1]); - symbol->width = 27 - (2 * AztecCompactOffset[layers - 1]); + symbol->rows = 27 - (2 * offset); + symbol->width = 27 - (2 * offset); } else { - - for (y = AztecOffset[layers - 1]; y < (151 - AztecOffset[layers - 1]); y++) { - for (x = AztecOffset[layers - 1]; x < (151 - AztecOffset[layers - 1]); x++) { - if (AztecMap[(y * 151) + x] == 1) { - set_module(symbol, y - AztecOffset[layers - 1], x - AztecOffset[layers - 1]); - } - if (AztecMap[(y * 151) + x] >= 2) { - if (bit_pattern[AztecMap[(y * 151) + x] - 2] == '1') { - set_module(symbol, y - AztecOffset[layers - 1], x - AztecOffset[layers - 1]); + int offset = AztecOffset[layers - 1]; + int end_offset = 151 - offset; + for (y = offset; y < end_offset; y++) { + int y_map = y * 151; + for (x = offset; x < end_offset; x++) { + int map = AztecMap[y_map + x]; + if (map == 1) { + set_module(symbol, y - offset, x - offset); + } else if (map >= 2) { + if (bit_pattern[map - 2] == '1') { + set_module(symbol, y - offset, x - offset); } } } - symbol->row_height[y - AztecOffset[layers - 1]] = 1; + symbol->row_height[y - offset] = 1; } - symbol->rows = 151 - (2 * AztecOffset[layers - 1]); - symbol->width = 151 - (2 * AztecOffset[layers - 1]); + symbol->rows = 151 - (2 * offset); + symbol->width = 151 - (2 * offset); } return error_number; @@ -1573,6 +1471,7 @@ INTERNAL int aztec_runes(struct zint_symbol *symbol, unsigned char source[], int char binary_string[28]; unsigned char data_codewords[3], ecc_codewords[6]; int debug = symbol->debug & ZINT_DEBUG_PRINT; + rs_t rs; input_value = 0; if (length > 3) { @@ -1622,10 +1521,9 @@ INTERNAL int aztec_runes(struct zint_symbol *symbol, unsigned char source[], int } } - rs_init_gf(0x13); - rs_init_code(5, 1); - rs_encode(2, data_codewords, ecc_codewords); - rs_free(); + rs_init_gf(&rs, 0x13); + rs_init_code(&rs, 5, 1); + rs_encode(&rs, 2, data_codewords, ecc_codewords); for (i = 0; i < 5; i++) { if (ecc_codewords[4 - i] & 0x08) { diff --git a/backend/code1.c b/backend/code1.c index 8ba456b1..f6baa28e 100644 --- a/backend/code1.c +++ b/backend/code1.c @@ -560,7 +560,6 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne } if ((length - sp) >= 8) { - int latch = 0; j = 0; for (i = 0; i < 8; i++) { @@ -663,7 +662,6 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne } if ((length - sp) >= 8) { - int latch = 0; j = 0; for (i = 0; i < 8; i++) { @@ -764,7 +762,6 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne } if ((length - sp) >= 8) { - int latch = 0; j = 0; for (i = 0; i < 8; i++) { @@ -1163,13 +1160,15 @@ static int c1_encode(struct zint_symbol *symbol, unsigned char source[], unsigne strcpy(symbol->errtxt, "512: Input data too long"); return 0; } - /* - printf("targets:\n"); - for(i = 0; i < tp; i++) { - printf("[%d]", target[i]); + + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf("Target:"); + for (i = 0; i < tp; i++) { + printf(" [%d]", target[i]); + } + printf("\n"); } - printf("\n"); - */ + return tp; } @@ -1191,6 +1190,7 @@ INTERNAL int code_one(struct zint_symbol *symbol, unsigned char source[], int le char datagrid[136][120]; int row, col; int sub_version = 0; + rs_t rs; if ((symbol->option_2 < 0) || (symbol->option_2 > 10)) { strcpy(symbol->errtxt, "513: Invalid symbol size"); @@ -1239,10 +1239,9 @@ INTERNAL int code_one(struct zint_symbol *symbol, unsigned char source[], int le large_uint_array(&elreg, data, codewords, 5 /*bits*/); - rs_init_gf(0x25); - rs_init_code(codewords, 1); - rs_encode_long(codewords, data, ecc); - rs_free(); + rs_init_gf(&rs, 0x25); + rs_init_code(&rs, codewords, 1); + rs_encode_uint(&rs, codewords, data, ecc); for (i = 0; i < codewords; i++) { stream[i] = data[i]; @@ -1344,10 +1343,9 @@ INTERNAL int code_one(struct zint_symbol *symbol, unsigned char source[], int le } /* Calculate error correction data */ - rs_init_gf(0x12d); - rs_init_code(ecc_cw, 1); - rs_encode_long(data_cw, data, ecc); - rs_free(); + rs_init_gf(&rs, 0x12d); + rs_init_code(&rs, ecc_cw, 1); + rs_encode_uint(&rs, data_cw, data, ecc); /* "Stream" combines data and error correction data */ for (i = 0; i < data_cw; i++) { @@ -1446,19 +1444,18 @@ INTERNAL int code_one(struct zint_symbol *symbol, unsigned char source[], int le data_blocks = c1_blocks[size - 1]; - rs_init_gf(0x12d); - rs_init_code(c1_ecc_blocks[size - 1], 0); + rs_init_gf(&rs, 0x12d); + rs_init_code(&rs, c1_ecc_blocks[size - 1], 0); for (i = 0; i < data_blocks; i++) { for (j = 0; j < c1_data_blocks[size - 1]; j++) { sub_data[j] = data[j * data_blocks + i]; } - rs_encode_long(c1_data_blocks[size - 1], sub_data, sub_ecc); + rs_encode_uint(&rs, c1_data_blocks[size - 1], sub_data, sub_ecc); for (j = 0; j < c1_ecc_blocks[size - 1]; j++) { ecc[c1_ecc_length[size - 1] - (j * data_blocks + i) - 1] = sub_ecc[j]; } } - rs_free(); /* "Stream" combines data and error correction data */ for (i = 0; i < data_length; i++) { diff --git a/backend/common.c b/backend/common.c index 4011e1a0..99e45888 100644 --- a/backend/common.c +++ b/backend/common.c @@ -303,11 +303,12 @@ INTERNAL unsigned int decode_utf8(unsigned int *state, unsigned int *codep, cons return *state; } -/* Convert UTF-8 to Unicode. If `disallow_4byte` unset, allow all values (UTF-32). - * If `disallow_4byte` set, only allow codepoints <= U+FFFF (ie four-byte sequences not allowed) (UTF-16, no surrogates) */ -INTERNAL int utf8_to_unicode(struct zint_symbol *symbol, const unsigned char source[], unsigned int vals[], size_t *length, int disallow_4byte) { - size_t bpos; - int jpos; +/* Convert UTF-8 to Unicode. If `disallow_4byte` unset, allow all values (UTF-32). If `disallow_4byte` set, + * only allow codepoints <= U+FFFF (ie four-byte sequences not allowed) (UTF-16, no surrogates) */ +INTERNAL int utf8_to_unicode(struct zint_symbol *symbol, const unsigned char source[], unsigned int vals[], + int *length, int disallow_4byte) { + int bpos; + int jpos; unsigned int codepoint, state = 0; bpos = 0; @@ -361,99 +362,6 @@ INTERNAL void set_minimum_height(struct zint_symbol *symbol, const int min_heigh } } -/* Calculate optimized encoding modes. Adapted from Project Nayuki */ -INTERNAL void pn_define_mode(char *mode, const unsigned int data[], const size_t length, const int debug, - unsigned int state[], const char mode_types[], const int num_modes, - pn_head_costs head_costs, pn_switch_cost switch_cost, pn_eod_cost eod_cost, pn_cur_cost cur_cost) { - /* - * Copyright (c) Project Nayuki. (MIT License) - * https://www.nayuki.io/page/qr-code-generator-library - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of - * the Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - */ - int i, j, k, cm_i; - unsigned int min_cost; - char cur_mode; -#ifndef _MSC_VER - unsigned int prev_costs[num_modes]; - char char_modes[length * num_modes]; - unsigned int cur_costs[num_modes]; -#else - unsigned int *prev_costs; - char *char_modes; - unsigned int *cur_costs; - prev_costs = (unsigned int *) _alloca(num_modes * sizeof(unsigned int)); - char_modes = (char *) _alloca(length * num_modes); - cur_costs = (unsigned int *) _alloca(num_modes * sizeof(unsigned int)); -#endif - - /* char_modes[i * num_modes + j] represents the mode to encode the code point at index i such that the final - * segment ends in mode_types[j] and the total number of bits is minimized over all possible choices */ - memset(char_modes, 0, length * num_modes); - - /* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/XX_MULT) - * bits needed to encode the entire string prefix of length i, and end in mode_types[j] */ - memcpy(prev_costs, (*head_costs)(state), num_modes * sizeof(unsigned int)); - - /* Calculate costs using dynamic programming */ - for (i = 0, cm_i = 0; i < (int) length; i++, cm_i += num_modes) { - memset(cur_costs, 0, num_modes * sizeof(unsigned int)); - - (*cur_cost)(state, data, length, i, char_modes, prev_costs, cur_costs); - - if (eod_cost && i == (int) length - 1) { /* Add end of data costs if last character */ - for (j = 0; j < num_modes; j++) { - if (char_modes[cm_i + j]) { - cur_costs[j] += (*eod_cost)(state, j); - } - } - } - - /* Start new segment at the end to switch modes */ - for (j = 0; j < num_modes; j++) { /* To mode */ - for (k = 0; k < num_modes; k++) { /* From mode */ - if (j != k && char_modes[cm_i + k]) { - unsigned int new_cost = cur_costs[k] + (*switch_cost)(state, k, j); - if (!char_modes[cm_i + j] || new_cost < cur_costs[j]) { - cur_costs[j] = new_cost; - char_modes[cm_i + j] = mode_types[k]; - } - } - } - } - - memcpy(prev_costs, cur_costs, num_modes * sizeof(unsigned int)); - } - - /* Find optimal ending mode */ - min_cost = prev_costs[0]; - cur_mode = mode_types[0]; - for (i = 1; i < num_modes; i++) { - if (prev_costs[i] < min_cost) { - min_cost = prev_costs[i]; - cur_mode = mode_types[i]; - } - } - - /* Get optimal mode for each code point by tracing backwards */ - for (i = length - 1, cm_i = i * num_modes; i >= 0; i--, cm_i -= num_modes) { - j = strchr(mode_types, cur_mode) - mode_types; - cur_mode = char_modes[cm_i + j]; - mode[i] = cur_mode; - } - - if (debug & ZINT_DEBUG_PRINT) { - printf(" Mode: %.*s\n", (int) length, mode); - } -} - INTERNAL int colour_to_red(int colour) { int return_val = 0; diff --git a/backend/common.h b/backend/common.h index 0cb1c337..714ce20c 100644 --- a/backend/common.h +++ b/backend/common.h @@ -110,18 +110,9 @@ extern "C" { INTERNAL int istwodigits(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 int utf8_to_unicode(struct zint_symbol *symbol, const unsigned char source[], unsigned int vals[], - size_t *length, int disallow_4byte); + int *length, int disallow_4byte); INTERNAL void set_minimum_height(struct zint_symbol *symbol, const int min_height); - typedef unsigned int *(*pn_head_costs)(unsigned int state[]); - typedef unsigned int (*pn_switch_cost)(unsigned int state[], const int k, const int j); - typedef unsigned int (*pn_eod_cost)(unsigned int state[], const int k); - typedef void (*pn_cur_cost)(unsigned int state[], const unsigned int data[], const size_t length, const int i, - char *char_modes, unsigned int prev_costs[], unsigned int cur_costs[]); - INTERNAL void pn_define_mode(char *mode, const unsigned int data[], const size_t length, const int debug, - unsigned int state[], const char mode_types[], const int num_modes, - pn_head_costs head_costs, pn_switch_cost switch_cost, pn_eod_cost eod_cost, pn_cur_cost cur_cost); - INTERNAL int colour_to_red(int colour); INTERNAL int colour_to_green(int colour); INTERNAL int colour_to_blue(int colour); diff --git a/backend/dmatrix.c b/backend/dmatrix.c index a2c7a6f5..a7b86875 100644 --- a/backend/dmatrix.c +++ b/backend/dmatrix.c @@ -193,14 +193,16 @@ static void ecc200placement(int *array, const int NR, const int NC) { static void ecc200(unsigned char *binary, const int bytes, const int datablock, const int rsblock, const int skew) { int blocks = (bytes + 2) / datablock, b; int n; - rs_init_gf(0x12d); - rs_init_code(rsblock, 1); + rs_t rs; + + rs_init_gf(&rs, 0x12d); + rs_init_code(&rs, rsblock, 1); for (b = 0; b < blocks; b++) { unsigned char buf[256], ecc[256]; int p = 0; for (n = b; n < bytes; n += blocks) buf[p++] = binary[n]; - rs_encode(p, buf, ecc); + rs_encode(&rs, p, buf, ecc); p = rsblock - 1; // comes back reversed for (n = b; n < rsblock * blocks; n += blocks) { if (skew) { @@ -216,7 +218,6 @@ static void ecc200(unsigned char *binary, const int bytes, const int datablock, } } } - rs_free(); } /* Return true (1) if a character is valid in X12 set */ @@ -1289,9 +1290,9 @@ static int data_matrix_200(struct zint_symbol *symbol,const unsigned char source unsigned char *grid; NC = W - 2 * (W / FW); NR = H - 2 * (H / FH); - places = (int*) malloc(NC * NR * sizeof (int)); + places = (int *) malloc(sizeof(int) * NC * NR); ecc200placement(places, NR, NC); - grid = (unsigned char*) malloc(W * H); + grid = (unsigned char *) malloc((size_t) W * H); memset(grid, 0, W * H); for (y = 0; y < H; y += FH) { for (x = 0; x < W; x++) @@ -1328,7 +1329,6 @@ static int data_matrix_200(struct zint_symbol *symbol,const unsigned char source //fprintf (stderr, "\n"); } for (y = H - 1; y >= 0; y--) { - int x; for (x = 0; x < W; x++) { if (grid[W * y + x]) { set_module(symbol, (H - y) - 1, x); diff --git a/backend/eci.c b/backend/eci.c index d07ae347..ee4af0a3 100644 --- a/backend/eci.c +++ b/backend/eci.c @@ -39,7 +39,7 @@ #endif /* Convert Unicode to other character encodings */ -INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[], size_t *length) { +INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[], int *length) { int in_posn; int out_posn; int ext; @@ -69,7 +69,7 @@ INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned ch bytelen = 2; glyph = (source[in_posn] & 0x1f) << 6; - if ((int) *length < (in_posn + 2)) { + if (*length < (in_posn + 2)) { return ZINT_ERROR_INVALID_DATA; } @@ -85,11 +85,11 @@ INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned ch bytelen = 3; glyph = (source[in_posn] & 0x0f) << 12; - if ((int) *length < (in_posn + 2)) { + if (*length < (in_posn + 2)) { return ZINT_ERROR_INVALID_DATA; } - if ((int) *length < (in_posn + 3)) { + if (*length < (in_posn + 3)) { return ZINT_ERROR_INVALID_DATA; } @@ -245,7 +245,7 @@ INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned ch in_posn += bytelen; out_posn++; - } while (in_posn < (int) *length); + } while (in_posn < *length); dest[out_posn] = '\0'; *length = out_posn; @@ -253,7 +253,7 @@ INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned ch } /* Find the lowest ECI mode which will encode a given set of Unicode text */ -INTERNAL int get_best_eci(unsigned char source[], size_t length) { +INTERNAL int get_best_eci(unsigned char source[], int length) { int eci = 3; #ifndef _MSC_VER diff --git a/backend/gb18030.c b/backend/gb18030.c index ae67fd71..7b8d64fd 100644 --- a/backend/gb18030.c +++ b/backend/gb18030.c @@ -52,7 +52,6 @@ * License along with the GNU LIBICONV Library; see the file COPYING.LIB. * If not, see . */ -#include #ifdef _MSC_VER #include #endif @@ -60,7 +59,8 @@ #include "gb2312.h" #include "gb18030.h" -INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[], size_t *length); /* Convert Unicode to other encodings */ +/* Convert Unicode to other encodings */ +INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[], int *length); /* * CP936 extensions (libiconv-1.16/lib/cp936ext.h) @@ -81,7 +81,7 @@ static const unsigned short cp936ext_pagefe[24] = { 0xa6e5, 0xa6e8, 0xa6e9, 0xa6ea, 0xa6eb, 0x0000, 0x0000, 0x0000, /*0x40-0x47*/ }; -static int cp936ext_wctomb(unsigned int* r, unsigned int wc) { +static int cp936ext_wctomb(unsigned int *r, unsigned int wc) { unsigned short c = 0; if (wc >= 0x0140 && wc < 0x0150) { c = cp936ext_page01[wc-0x0140]; @@ -2383,7 +2383,7 @@ static const Summary16 gbkext_inv_uni2indx_pagefe[31] = { { 14311, 0x0000 }, { 14311, 0x0000 }, { 14311, 0x0014 }, }; -static int gbkext_inv_wctomb(unsigned int* r, unsigned int wc) { +static int gbkext_inv_wctomb(unsigned int *r, unsigned int wc) { const Summary16 *summary = NULL; if (wc >= 0x0200 && wc < 0x02e0) { summary = &gbkext_inv_uni2indx_page02[(wc>>4)-0x020]; @@ -2424,7 +2424,7 @@ static int gbkext_inv_wctomb(unsigned int* r, unsigned int wc) { * GBK (libiconv-1.16/lib/gbk.h) */ -static int gbk_wctomb(unsigned int* r, unsigned int wc) { +static int gbk_wctomb(unsigned int *r, unsigned int wc) { int ret; /* ZINT: Note these mappings U+30FB and U+2015 different from GB 2312 */ @@ -2553,7 +2553,7 @@ static const unsigned short gb18030ext_pagefe[16] = { 0xa6ed, 0xa6f3, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*0x18-0x1f*/ }; -static int gb18030ext_wctomb(unsigned int* r, unsigned int wc) { +static int gb18030ext_wctomb(unsigned int *r, unsigned int wc) { unsigned short c = 0; if (wc == 0x01f9) { c = 0xa8bf; @@ -2727,7 +2727,7 @@ static const unsigned short gb18030uni_ranges[206] = { 25994, 25998, 26012, 26016, 26110, 26116 }; -static int gb18030uni_wctomb(unsigned int* r1, unsigned int* r2, unsigned int wc) { +static int gb18030uni_wctomb(unsigned int *r1, unsigned int *r2, unsigned int wc) { unsigned int i = wc; if (i >= 0x0080 && i <= 0xffff) { if (i == 0xe7c7) { @@ -2798,7 +2798,7 @@ static const unsigned short gb18030_pua2charset[31*3] = { 0xe864, 0xe864, 0xfea0, }; -INTERNAL int gb18030_wctomb_zint(unsigned int* r1, unsigned int* r2, unsigned int wc) { +INTERNAL int gb18030_wctomb_zint(unsigned int *r1, unsigned int *r2, unsigned int wc) { int ret; /* Code set 0 (ASCII) */ @@ -2870,13 +2870,14 @@ INTERNAL int gb18030_wctomb_zint(unsigned int* r1, unsigned int* r2, unsigned in } /* Convert UTF-8 string to GB 18030 and place in array of ints */ -INTERNAL int gb18030_utf8tomb(struct zint_symbol *symbol, const unsigned char source[], size_t* p_length, unsigned int* gbdata) { +INTERNAL int gb18030_utf8tomb(struct zint_symbol *symbol, const unsigned char source[], int *p_length, + unsigned int *gbdata) { int error_number, ret; unsigned int i, j, length; #ifndef _MSC_VER unsigned int utfdata[*p_length + 1]; #else - unsigned int* utfdata = (unsigned int*) _alloca((*p_length + 1) * sizeof(unsigned int)); + unsigned int *utfdata = (unsigned int *) _alloca((*p_length + 1) * sizeof(unsigned int)); #endif error_number = utf8_to_unicode(symbol, source, utfdata, p_length, 0 /*disallow_4byte*/); @@ -2905,12 +2906,13 @@ INTERNAL int gb18030_utf8tomb(struct zint_symbol *symbol, const unsigned char so } /* Convert UTF-8 string to single byte ECI and place in array of ints */ -INTERNAL int gb18030_utf8tosb(int eci, const unsigned char source[], size_t* p_length, unsigned int* gbdata, int full_multibyte) { +INTERNAL int gb18030_utf8tosb(int eci, const unsigned char source[], int *p_length, unsigned int *gbdata, + int full_multibyte) { int error_number; #ifndef _MSC_VER unsigned char single_byte[*p_length + 1]; #else - unsigned char* single_byte = (unsigned char*) _alloca(*p_length + 1); + unsigned char *single_byte = (unsigned char *) _alloca(*p_length + 1); #endif error_number = utf_to_eci(eci, source, single_byte, p_length); @@ -2924,9 +2926,9 @@ INTERNAL int gb18030_utf8tosb(int eci, const unsigned char source[], size_t* p_l return 0; } -/* If `full_multibyte` set, copy byte input stream to array of ints, putting double-bytes that match HANXIN Chinese mode in single entry, - * and quad-bytes in 2 entries. If `full_multibyte` not set, do a straight copy */ -INTERNAL void gb18030_cpy(const unsigned char source[], size_t* p_length, unsigned int* gbdata, int full_multibyte) { +/* If `full_multibyte` set, copy byte input stream to array of ints, putting double-bytes that match HANXIN Chinese + * mode in single entry, and quad-bytes in 2 entries. If `full_multibyte` not set, do a straight copy */ +INTERNAL void gb18030_cpy(const unsigned char source[], int *p_length, unsigned int *gbdata, int full_multibyte) { unsigned int i, j, length; int done; unsigned char c1, c2, c3, c4; diff --git a/backend/gb18030.h b/backend/gb18030.h index 704e4bdb..d2731654 100644 --- a/backend/gb18030.h +++ b/backend/gb18030.h @@ -37,10 +37,12 @@ extern "C" { #endif /* __cplusplus */ -INTERNAL int gb18030_wctomb_zint(unsigned int* r1, unsigned int* r2, unsigned int wc); -INTERNAL int gb18030_utf8tomb(struct zint_symbol *symbol, const unsigned char source[], size_t* p_length, unsigned int* gbdata); -INTERNAL int gb18030_utf8tosb(int eci, const unsigned char source[], size_t* p_length, unsigned int* gbdata, int full_multibyte); -INTERNAL void gb18030_cpy(const unsigned char source[], size_t* p_length, unsigned int* gbdata, int full_multibyte); +INTERNAL int gb18030_wctomb_zint(unsigned int *r1, unsigned int *r2, unsigned int wc); +INTERNAL int gb18030_utf8tomb(struct zint_symbol *symbol, const unsigned char source[], int *p_length, + unsigned int *gbdata); +INTERNAL int gb18030_utf8tosb(int eci, const unsigned char source[], int *p_length, unsigned int *gbdata, + int full_multibyte); +INTERNAL void gb18030_cpy(const unsigned char source[], int *p_length, unsigned int *gbdata, int full_multibyte); #ifdef __cplusplus } diff --git a/backend/gb2312.c b/backend/gb2312.c index 1259f68f..ea2c849f 100644 --- a/backend/gb2312.c +++ b/backend/gb2312.c @@ -52,14 +52,14 @@ * License along with the GNU LIBICONV Library; see the file COPYING.LIB. * If not, see . */ -#include #ifdef _MSC_VER #include #endif #include "common.h" #include "gb2312.h" -INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[], size_t *length); /* Convert Unicode to other encodings */ +/* Convert Unicode to other encodings */ +INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[], int *length); /* * GB2312.1980-0 (libiconv-1.16/lib/gb2312.h) @@ -1502,7 +1502,7 @@ static const Summary16 gb2312_uni2indx_pageff[15] = { { 7441, 0x0000 }, { 7441, 0x0000 }, { 7441, 0x002b }, }; -INTERNAL int gb2312_wctomb_zint(unsigned int* r, unsigned int wc) { +INTERNAL int gb2312_wctomb_zint(unsigned int *r, unsigned int wc) { const Summary16 *summary = NULL; if (wc < 0x0460) { if (wc == 0x00b7) { /* ZINT: Patched to duplicate map to 0xA1A4 */ @@ -1544,13 +1544,14 @@ INTERNAL int gb2312_wctomb_zint(unsigned int* r, unsigned int wc) { } /* Convert UTF-8 string to GB 2312 (EUC-CN) and place in array of ints */ -INTERNAL int gb2312_utf8tomb(struct zint_symbol *symbol, const unsigned char source[], size_t* p_length, unsigned int* gbdata) { +INTERNAL int gb2312_utf8tomb(struct zint_symbol *symbol, const unsigned char source[], int *p_length, + unsigned int *gbdata) { int error_number; unsigned int i, length; #ifndef _MSC_VER unsigned int utfdata[*p_length + 1]; #else - unsigned int* utfdata = (unsigned int*) _alloca((*p_length + 1) * sizeof(unsigned int)); + unsigned int *utfdata = (unsigned int *) _alloca((*p_length + 1) * sizeof(unsigned int)); #endif error_number = utf8_to_unicode(symbol, source, utfdata, p_length, 1 /*disallow_4byte*/); @@ -1573,12 +1574,13 @@ INTERNAL int gb2312_utf8tomb(struct zint_symbol *symbol, const unsigned char sou } /* Convert UTF-8 string to single byte ECI and place in array of ints */ -INTERNAL int gb2312_utf8tosb(int eci, const unsigned char source[], size_t* p_length, unsigned int* gbdata, int full_multibyte) { +INTERNAL int gb2312_utf8tosb(int eci, const unsigned char source[], int *p_length, unsigned int *gbdata, + int full_multibyte) { int error_number; #ifndef _MSC_VER unsigned char single_byte[*p_length + 1]; #else - unsigned char* single_byte = (unsigned char*) _alloca(*p_length + 1); + unsigned char *single_byte = (unsigned char *) _alloca(*p_length + 1); #endif error_number = utf_to_eci(eci, source, single_byte, p_length); @@ -1592,9 +1594,9 @@ INTERNAL int gb2312_utf8tosb(int eci, const unsigned char source[], size_t* p_le return 0; } -/* If `full_multibyte` set, copy byte input stream to array of ints, putting double-bytes that match GRIDMATRIX Chinese mode in a single entry. - * If `full_multibyte` not set, do a straight copy */ -INTERNAL void gb2312_cpy(const unsigned char source[], size_t* p_length, unsigned int* gbdata, int full_multibyte) { +/* If `full_multibyte` set, copy byte input stream to array of ints, putting double-bytes that match GRIDMATRIX Chinese + * mode in a single entry. If `full_multibyte` not set, do a straight copy */ +INTERNAL void gb2312_cpy(const unsigned char source[], int *p_length, unsigned int *gbdata, int full_multibyte) { unsigned int i, j, length; unsigned char c1, c2; @@ -1604,7 +1606,8 @@ INTERNAL void gb2312_cpy(const unsigned char source[], size_t* p_length, unsigne c1 = source[i]; c2 = source[i + 1]; if (((c1 >= 0xA1 && c1 <= 0xA9) || (c1 >= 0xB0 && c1 <= 0xF7)) && c2 >= 0xA1 && c2 <= 0xFE) { - /* This may or may not be valid GB 2312 (EUC-CN), but don't care as long as it can be encoded in GRIDMATRIX Chinese mode */ + /* This may or may not be valid GB 2312 (EUC-CN), but don't care as long as it can be encoded in + * GRIDMATRIX Chinese mode */ gbdata[j] = (c1 << 8) | c2; i++; } else { diff --git a/backend/gb2312.h b/backend/gb2312.h index b3ca91be..c83d4c6a 100644 --- a/backend/gb2312.h +++ b/backend/gb2312.h @@ -37,10 +37,12 @@ extern "C" { #endif /* __cplusplus */ -INTERNAL int gb2312_wctomb_zint(unsigned int* r, unsigned int wc); -INTERNAL int gb2312_utf8tomb(struct zint_symbol *symbol, const unsigned char source[], size_t* p_length, unsigned int* gbdata); -INTERNAL int gb2312_utf8tosb(int eci, const unsigned char source[], size_t* p_length, unsigned int* gbdata, int full_multibyte); -INTERNAL void gb2312_cpy(const unsigned char source[], size_t* p_length, unsigned int* gbdata, int full_multibyte); +INTERNAL int gb2312_wctomb_zint(unsigned int *r, unsigned int wc); +INTERNAL int gb2312_utf8tomb(struct zint_symbol *symbol, const unsigned char source[], int *p_length, + unsigned int *gbdata); +INTERNAL int gb2312_utf8tosb(int eci, const unsigned char source[], int *p_length, unsigned int *gbdata, + int full_multibyte); +INTERNAL void gb2312_cpy(const unsigned char source[], int *p_length, unsigned int *gbdata, int full_multibyte); #ifdef __cplusplus } diff --git a/backend/gridmtx.c b/backend/gridmtx.c index bfb04bef..213381b2 100644 --- a/backend/gridmtx.c +++ b/backend/gridmtx.c @@ -49,11 +49,13 @@ static const char numeral_nondigits[] = " +-.,"; /* Non-digit numeral set, excluding EOL (carriage return/linefeed) */ -/* Whether in numeral or not. If in numeral, *p_numeral_end is set to position after numeral, and *p_numeral_cost is set to per-numeral cost */ -static int in_numeral(const unsigned int gbdata[], const size_t length, const unsigned int posn, unsigned int* p_numeral_end, unsigned int* p_numeral_cost) { - unsigned int i, digit_cnt, nondigit, nondigit_posn; +/* Whether in numeral or not. If in numeral, *p_numeral_end is set to position after numeral, + * and *p_numeral_cost is set to per-numeral cost */ +static int in_numeral(const unsigned int gbdata[], const int length, const int in_posn, + unsigned int *p_numeral_end, unsigned int *p_numeral_cost) { + int i, digit_cnt, nondigit, nondigit_posn; - if (posn < *p_numeral_end) { + if (in_posn < (int) *p_numeral_end) { return 1; } @@ -61,7 +63,7 @@ static int in_numeral(const unsigned int gbdata[], const size_t length, const un /* Also ensures that numeric mode is not selected when it cannot be used: for example in a string which has "2.2.0" (cannot have more than one non-numeric character for each block of three numeric characters) */ - for (i = posn, digit_cnt = 0, nondigit = 0, nondigit_posn = 0; i < length && i < posn + 4 && digit_cnt < 3; i++) { + for (i = in_posn, digit_cnt = 0, nondigit = 0, nondigit_posn = 0; i < length && i < in_posn + 4 && digit_cnt < 3; i++) { if (gbdata[i] >= '0' && gbdata[i] <= '9') { digit_cnt++; } else if (strchr(numeral_nondigits, gbdata[i])) { @@ -88,7 +90,7 @@ static int in_numeral(const unsigned int gbdata[], const size_t length, const un if (nondigit && nondigit_posn == i - 1) { /* Non-digit can't be at end */ nondigit = 0; } - *p_numeral_end = posn + digit_cnt + nondigit; + *p_numeral_end = in_posn + digit_cnt + nondigit; /* Calculate per-numeral cost where 120 == (10 + 10) * GM_MULT, 60 == 10 * GM_MULT */ if (digit_cnt == 3) { *p_numeral_cost = nondigit == 2 ? 24 /* (120 / 5) */ : nondigit == 1 ? 30 /* (120 / 4) */ : 20 /* (60 / 3) */; @@ -119,19 +121,19 @@ static int in_numeral(const unsigned int gbdata[], const size_t length, const un #define GM_NUM_MODES 6 -/* Initial mode costs */ -static unsigned int head_costs[GM_NUM_MODES] = { -/* H N (+pad prefix) L U M B (+byte count) */ - 4 * GM_MULT, (4 + 2) * GM_MULT, 4 * GM_MULT, 4 * GM_MULT, 4 * GM_MULT, (4 + 9) * GM_MULT -}; +/* Calculate optimized encoding modes. Adapted from Project Nayuki */ +/* Copyright (c) Project Nayuki. (MIT License) See qr.c for detailed notice */ +static void define_mode(char* mode, const unsigned int gbdata[], const int length, const int debug) { + /* Must be in same order as GM_H etc */ + static const char mode_types[] = { GM_CHINESE, GM_NUMBER, GM_LOWER, GM_UPPER, GM_MIXED, GM_BYTE, '\0' }; -static unsigned int* gm_head_costs(unsigned int state[]) { - (void)state; /* Unused */ - return head_costs; -} + /* Initial mode costs */ + static unsigned int head_costs[GM_NUM_MODES] = { + /* H N (+pad prefix) L U M B (+byte count) */ + 4 * GM_MULT, (4 + 2) * GM_MULT, 4 * GM_MULT, 4 * GM_MULT, 4 * GM_MULT, (4 + 9) * GM_MULT + }; -/* Cost of switching modes from k to j - see AIMD014 Rev. 1.63 Table 9 – Type conversion codes */ -static unsigned int gm_switch_cost(unsigned int state[], const int k, const int j) { + /* Cost of switching modes from k to j - see AIMD014 Rev. 1.63 Table 9 – Type conversion codes */ static const unsigned int switch_costs[GM_NUM_MODES][GM_NUM_MODES] = { /* H N L U M B */ /*H*/ { 0, (13 + 2) * GM_MULT, 13 * GM_MULT, 13 * GM_MULT, 13 * GM_MULT, (13 + 9) * GM_MULT }, @@ -142,107 +144,172 @@ static unsigned int gm_switch_cost(unsigned int state[], const int k, const int /*B*/ { 4 * GM_MULT, (4 + 2) * GM_MULT, 4 * GM_MULT, 4 * GM_MULT, 4 * GM_MULT, 0 }, }; - (void)state; /* Unused */ - return switch_costs[k][j]; -} - -/* Final end-of-data cost - see AIMD014 Rev. 1.63 Table 9 – Type conversion codes */ -static unsigned int gm_eod_cost(unsigned int state[], const int k) { + /* Final end-of-data cost - see AIMD014 Rev. 1.63 Table 9 – Type conversion codes */ static const unsigned int eod_costs[GM_NUM_MODES] = { /* H N L U M B */ 13 * GM_MULT, 10 * GM_MULT, 5 * GM_MULT, 5 * GM_MULT, 10 * GM_MULT, 4 * GM_MULT }; - (void)state; /* Unused */ - return eod_costs[k]; -} - -/* Calculate cost of encoding current character */ -static void gm_cur_cost(unsigned int state[], const unsigned int gbdata[], const size_t length, const int i, char* char_modes, unsigned int prev_costs[], unsigned int cur_costs[]) { - int cm_i = i * GM_NUM_MODES; + unsigned int numeral_end = 0, numeral_cost = 0, byte_count = 0; /* State */ int double_byte, space, numeric, lower, upper, control, double_digit, eol; - unsigned int* p_numeral_end = &state[0]; - unsigned int* p_numeral_cost = &state[1]; - unsigned int* p_byte_count = &state[2]; - double_byte = gbdata[i] > 0xFF; - space = gbdata[i] == ' '; - numeric = gbdata[i] >= '0' && gbdata[i] <= '9'; - lower = gbdata[i] >= 'a' && gbdata[i] <= 'z'; - upper = gbdata[i] >= 'A' && gbdata[i] <= 'Z'; - control = !space && !numeric && !lower && !upper && gbdata[i] < 0x7F; /* Exclude DEL */ - double_digit = i < (int) length - 1 && numeric && gbdata[i + 1] >= '0' && gbdata[i + 1] <= '9'; - eol = i < (int) length - 1 && gbdata[i] == 13 && gbdata[i + 1] == 10; + int i, j, k, cm_i; + unsigned int min_cost; + char cur_mode; + unsigned int prev_costs[GM_NUM_MODES]; + unsigned int cur_costs[GM_NUM_MODES]; +#ifndef _MSC_VER + char char_modes[length * GM_NUM_MODES]; +#else + char *char_modes = (char *) _alloca(length * GM_NUM_MODES); +#endif - /* Hanzi mode can encode anything */ - cur_costs[GM_H] = prev_costs[GM_H] + (double_digit || eol ? 39 : 78); /* (6.5 : 13) * GM_MULT */ - char_modes[cm_i + GM_H] = GM_CHINESE; + /* char_modes[i * GM_NUM_MODES + j] represents the mode to encode the code point at index i such that the final + * segment ends in mode_types[j] and the total number of bits is minimized over all possible choices */ + memset(char_modes, 0, length * GM_NUM_MODES); - /* Byte mode can encode anything */ - if (*p_byte_count == 512 || (double_byte && *p_byte_count == 511)) { - cur_costs[GM_B] = head_costs[GM_B]; - if (double_byte && *p_byte_count == 511) { - cur_costs[GM_B] += 48; /* 8 * GM_MULT */ - double_byte = 0; /* Splitting double-byte so mark as single */ + /* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/XX_MULT) + * bits needed to encode the entire string prefix of length i, and end in mode_types[j] */ + memcpy(prev_costs, head_costs, GM_NUM_MODES * sizeof(unsigned int)); + + /* Calculate costs using dynamic programming */ + for (i = 0, cm_i = 0; i < length; i++, cm_i += GM_NUM_MODES) { + memset(cur_costs, 0, GM_NUM_MODES * sizeof(unsigned int)); + + space = numeric = lower = upper = control = double_digit = eol = 0; + + double_byte = gbdata[i] > 0xFF; + if (!double_byte) { + space = gbdata[i] == ' '; + if (!space) { + numeric = gbdata[i] >= '0' && gbdata[i] <= '9'; + if (!numeric) { + lower = gbdata[i] >= 'a' && gbdata[i] <= 'z'; + if (!lower) { + upper = gbdata[i] >= 'A' && gbdata[i] <= 'Z'; + if (!upper) { + control = gbdata[i] < 0x7F; /* Exclude DEL */ + if (control && i + 1 < length) { + eol = gbdata[i] == 13 && gbdata[i + 1] == 10; + } + } + } + } else if (i + 1 < length) { + double_digit = gbdata[i + 1] >= '0' && gbdata[i + 1] <= '9'; + } + } } - *p_byte_count = 0; - } - cur_costs[GM_B] += prev_costs[GM_B] + (double_byte ? 96 : 48); /* (16 : 8) * GM_MULT */ - char_modes[cm_i + GM_B] = GM_BYTE; - *p_byte_count += double_byte ? 2 : 1; - if (in_numeral(gbdata, length, i, p_numeral_end, p_numeral_cost)) { - cur_costs[GM_N] = prev_costs[GM_N] + *p_numeral_cost; - char_modes[cm_i + GM_N] = GM_NUMBER; - } + /* Hanzi mode can encode anything */ + cur_costs[GM_H] = prev_costs[GM_H] + (double_digit || eol ? 39 : 78); /* (6.5 : 13) * GM_MULT */ + char_modes[cm_i + GM_H] = GM_CHINESE; - if (control) { - cur_costs[GM_L] = prev_costs[GM_L] + 78; /* (7 + 6) * GM_MULT */ - char_modes[cm_i + GM_L] = GM_LOWER; - cur_costs[GM_U] = prev_costs[GM_U] + 78; /* (7 + 6) * GM_MULT */ - char_modes[cm_i + GM_U] = GM_UPPER; - cur_costs[GM_M] = prev_costs[GM_M] + 96; /* (10 + 6) * GM_MULT */ - char_modes[cm_i + GM_M] = GM_MIXED; - } else { - if (lower || space) { - cur_costs[GM_L] = prev_costs[GM_L] + 30; /* 5 * GM_MULT */ + /* Byte mode can encode anything */ + if (byte_count == 512 || (double_byte && byte_count == 511)) { + cur_costs[GM_B] = head_costs[GM_B]; + if (double_byte && byte_count == 511) { + cur_costs[GM_B] += 48; /* 8 * GM_MULT */ + double_byte = 0; /* Splitting double-byte so mark as single */ + } + byte_count = 0; + } + cur_costs[GM_B] += prev_costs[GM_B] + (double_byte ? 96 : 48); /* (16 : 8) * GM_MULT */ + char_modes[cm_i + GM_B] = GM_BYTE; + byte_count += double_byte ? 2 : 1; + + if (in_numeral(gbdata, length, i, &numeral_end, &numeral_cost)) { + cur_costs[GM_N] = prev_costs[GM_N] + numeral_cost; + char_modes[cm_i + GM_N] = GM_NUMBER; + } + + if (control) { + cur_costs[GM_L] = prev_costs[GM_L] + 78; /* (7 + 6) * GM_MULT */ char_modes[cm_i + GM_L] = GM_LOWER; - } - if (upper || space) { - cur_costs[GM_U] = prev_costs[GM_U] + 30; /* 5 * GM_MULT */ + cur_costs[GM_U] = prev_costs[GM_U] + 78; /* (7 + 6) * GM_MULT */ char_modes[cm_i + GM_U] = GM_UPPER; - } - if (numeric || lower || upper || space) { - cur_costs[GM_M] = prev_costs[GM_M] + 36; /* 6 * GM_MULT */ + cur_costs[GM_M] = prev_costs[GM_M] + 96; /* (10 + 6) * GM_MULT */ char_modes[cm_i + GM_M] = GM_MIXED; + } else { + if (lower || space) { + cur_costs[GM_L] = prev_costs[GM_L] + 30; /* 5 * GM_MULT */ + char_modes[cm_i + GM_L] = GM_LOWER; + } + if (upper || space) { + cur_costs[GM_U] = prev_costs[GM_U] + 30; /* 5 * GM_MULT */ + char_modes[cm_i + GM_U] = GM_UPPER; + } + if (numeric || lower || upper || space) { + cur_costs[GM_M] = prev_costs[GM_M] + 36; /* 6 * GM_MULT */ + char_modes[cm_i + GM_M] = GM_MIXED; + } + } + + if (i == length - 1) { /* Add end of data costs if last character */ + for (j = 0; j < GM_NUM_MODES; j++) { + if (char_modes[cm_i + j]) { + cur_costs[j] += eod_costs[j]; + } + } + } + + /* Start new segment at the end to switch modes */ + for (j = 0; j < GM_NUM_MODES; j++) { /* To mode */ + for (k = 0; k < GM_NUM_MODES; k++) { /* From mode */ + if (j != k && char_modes[cm_i + k]) { + unsigned int new_cost = cur_costs[k] + switch_costs[k][j]; + if (!char_modes[cm_i + j] || new_cost < cur_costs[j]) { + cur_costs[j] = new_cost; + char_modes[cm_i + j] = mode_types[k]; + } + } + } + } + + memcpy(prev_costs, cur_costs, GM_NUM_MODES * sizeof(unsigned int)); + } + + /* Find optimal ending mode */ + min_cost = prev_costs[0]; + cur_mode = mode_types[0]; + for (i = 1; i < GM_NUM_MODES; i++) { + if (prev_costs[i] < min_cost) { + min_cost = prev_costs[i]; + cur_mode = mode_types[i]; } } -} -/* Calculate optimized encoding modes */ -static void define_mode(char* mode, const unsigned int gbdata[], const size_t length, const int debug) { - static const char mode_types[] = { GM_CHINESE, GM_NUMBER, GM_LOWER, GM_UPPER, GM_MIXED, GM_BYTE, '\0' }; /* Must be in same order as GM_H etc */ - unsigned int state[3] = { 0 /*numeral_end*/, 0 /*numeral_cost*/, 0 /*byte_count*/ }; + /* 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) { + j = strchr(mode_types, cur_mode) - mode_types; + cur_mode = char_modes[cm_i + j]; + mode[i] = cur_mode; + } - pn_define_mode(mode, gbdata, length, debug, state, mode_types, GM_NUM_MODES, gm_head_costs, gm_switch_cost, gm_eod_cost, gm_cur_cost); + if (debug & ZINT_DEBUG_PRINT) { + printf(" Mode: %.*s\n", length, mode); + } } /* Add the length indicator for byte encoded blocks */ -static void add_byte_count(char binary[], const size_t byte_count_posn, const int byte_count) { +static void add_byte_count(char binary[], const int byte_count_posn, const int byte_count) { /* AIMD014 6.3.7: "Let L be the number of bytes of input data to be encoded in the 8-bit binary data set. * First output (L-1) as a 9-bit binary prefix to record the number of bytes..." */ bin_append_posn(byte_count - 1, 9, binary, byte_count_posn); } /* Add a control character to the data stream */ -static void add_shift_char(char binary[], int shifty, int debug) { +static int add_shift_char(char binary[], int bp, int shifty, int debug) { int i; int glyph = 0; - for (i = 0; i < 64; i++) { - if (shift_set[i] == shifty) { - glyph = i; - break; + if (shifty < 32) { + glyph = shifty; + } else { + for (i = 32; i < 64; i++) { + if (shift_set[i] == shifty) { + glyph = i; + break; + } } } @@ -250,51 +317,54 @@ static void add_shift_char(char binary[], int shifty, int debug) { printf("SHIFT [%d] ", glyph); } - bin_append(glyph, 6, binary); + bp = bin_append_posn(glyph, 6, binary, bp); + + return bp; } -static int gm_encode(unsigned int gbdata[], const size_t length, char binary[], const int reader, const int eci, int debug) { +static int gm_encode(unsigned int gbdata[], const int length, char binary[], const int reader, const int eci, + int *bin_len, int debug) { /* Create a binary stream representation of the input data. 7 sets are defined - Chinese characters, Numerals, Lower case letters, Upper case letters, Mixed numerals and latters, Control characters and 8-bit binary data */ - unsigned int sp; + int sp; int current_mode, last_mode; unsigned int glyph = 0; int c1, c2, done; int p = 0, ppos; int numbuf[3], punt = 0; - size_t number_pad_posn, byte_count_posn = 0; + int number_pad_posn, byte_count_posn = 0; int byte_count = 0; int shift; + int bp; #ifndef _MSC_VER char mode[length]; #else char* mode = (char*) _alloca(length); #endif - strcpy(binary, ""); + *binary = '\0'; + bp = 0; sp = 0; current_mode = 0; number_pad_posn = 0; if (reader) { - bin_append(10, 4, binary); /* FNC3 - Reader Initialisation */ + bp = bin_append_posn(10, 4, binary, bp); /* FNC3 - Reader Initialisation */ } if (eci != 0) { /* ECI assignment according to Table 8 */ - bin_append(12, 4, binary); /* ECI */ + bp = bin_append_posn(12, 4, binary, bp); /* ECI */ if (eci <= 1023) { - bin_append(eci, 11, binary); - } - if ((eci >= 1024) && (eci <= 32767)) { - strcat(binary, "10"); - bin_append(eci, 15, binary); - } - if (eci >= 32768) { - strcat(binary, "11"); - bin_append(eci, 20, binary); + bp = bin_append_posn(eci, 11, binary, bp); + } else if (eci <= 32767) { + bp = bin_append_posn(2, 2, binary, bp); + bp = bin_append_posn(eci, 15, binary, bp); + } else { + bp = bin_append_posn(3, 2, binary, bp); + bp = bin_append_posn(eci, 20, binary, bp); } } @@ -307,31 +377,31 @@ static int gm_encode(unsigned int gbdata[], const size_t length, char binary[], switch (current_mode) { case 0: switch (next_mode) { - case GM_CHINESE: bin_append(1, 4, binary); + case GM_CHINESE: bp = bin_append_posn(1, 4, binary, bp); break; - case GM_NUMBER: bin_append(2, 4, binary); + case GM_NUMBER: bp = bin_append_posn(2, 4, binary, bp); break; - case GM_LOWER: bin_append(3, 4, binary); + case GM_LOWER: bp = bin_append_posn(3, 4, binary, bp); break; - case GM_UPPER: bin_append(4, 4, binary); + case GM_UPPER: bp = bin_append_posn(4, 4, binary, bp); break; - case GM_MIXED: bin_append(5, 4, binary); + case GM_MIXED: bp = bin_append_posn(5, 4, binary, bp); break; - case GM_BYTE: bin_append(6, 4, binary); + case GM_BYTE: bp = bin_append_posn(6, 4, binary, bp); break; } break; case GM_CHINESE: switch (next_mode) { - case GM_NUMBER: bin_append(8161, 13, binary); + case GM_NUMBER: bp = bin_append_posn(8161, 13, binary, bp); break; - case GM_LOWER: bin_append(8162, 13, binary); + case GM_LOWER: bp = bin_append_posn(8162, 13, binary, bp); break; - case GM_UPPER: bin_append(8163, 13, binary); + case GM_UPPER: bp = bin_append_posn(8163, 13, binary, bp); break; - case GM_MIXED: bin_append(8164, 13, binary); + case GM_MIXED: bp = bin_append_posn(8164, 13, binary, bp); break; - case GM_BYTE: bin_append(8165, 13, binary); + case GM_BYTE: bp = bin_append_posn(8165, 13, binary, bp); break; } break; @@ -349,45 +419,45 @@ static int gm_encode(unsigned int gbdata[], const size_t length, char binary[], break; // 0 pad digits } switch (next_mode) { - case GM_CHINESE: bin_append(1019, 10, binary); + case GM_CHINESE: bp = bin_append_posn(1019, 10, binary, bp); break; - case GM_LOWER: bin_append(1020, 10, binary); + case GM_LOWER: bp = bin_append_posn(1020, 10, binary, bp); break; - case GM_UPPER: bin_append(1021, 10, binary); + case GM_UPPER: bp = bin_append_posn(1021, 10, binary, bp); break; - case GM_MIXED: bin_append(1022, 10, binary); + case GM_MIXED: bp = bin_append_posn(1022, 10, binary, bp); break; - case GM_BYTE: bin_append(1023, 10, binary); + case GM_BYTE: bp = bin_append_posn(1023, 10, binary, bp); break; } break; case GM_LOWER: case GM_UPPER: switch (next_mode) { - case GM_CHINESE: bin_append(28, 5, binary); + case GM_CHINESE: bp = bin_append_posn(28, 5, binary, bp); break; - case GM_NUMBER: bin_append(29, 5, binary); + case GM_NUMBER: bp = bin_append_posn(29, 5, binary, bp); break; case GM_LOWER: - case GM_UPPER: bin_append(30, 5, binary); + case GM_UPPER: bp = bin_append_posn(30, 5, binary, bp); break; - case GM_MIXED: bin_append(124, 7, binary); + case GM_MIXED: bp = bin_append_posn(124, 7, binary, bp); break; - case GM_BYTE: bin_append(126, 7, binary); + case GM_BYTE: bp = bin_append_posn(126, 7, binary, bp); break; } break; case GM_MIXED: switch (next_mode) { - case GM_CHINESE: bin_append(1009, 10, binary); + case GM_CHINESE: bp = bin_append_posn(1009, 10, binary, bp); break; - case GM_NUMBER: bin_append(1010, 10, binary); + case GM_NUMBER: bp = bin_append_posn(1010, 10, binary, bp); break; - case GM_LOWER: bin_append(1011, 10, binary); + case GM_LOWER: bp = bin_append_posn(1011, 10, binary, bp); break; - case GM_UPPER: bin_append(1012, 10, binary); + case GM_UPPER: bp = bin_append_posn(1012, 10, binary, bp); break; - case GM_BYTE: bin_append(1015, 10, binary); + case GM_BYTE: bp = bin_append_posn(1015, 10, binary, bp); break; } break; @@ -396,15 +466,15 @@ static int gm_encode(unsigned int gbdata[], const size_t length, char binary[], add_byte_count(binary, byte_count_posn, byte_count); byte_count = 0; switch (next_mode) { - case GM_CHINESE: bin_append(1, 4, binary); + case GM_CHINESE: bp = bin_append_posn(1, 4, binary, bp); break; - case GM_NUMBER: bin_append(2, 4, binary); + case GM_NUMBER: bp = bin_append_posn(2, 4, binary, bp); break; - case GM_LOWER: bin_append(3, 4, binary); + case GM_LOWER: bp = bin_append_posn(3, 4, binary, bp); break; - case GM_UPPER: bin_append(4, 4, binary); + case GM_UPPER: bp = bin_append_posn(4, 4, binary, bp); break; - case GM_MIXED: bin_append(5, 4, binary); + case GM_MIXED: bp = bin_append_posn(5, 4, binary, bp); break; } break; @@ -474,15 +544,15 @@ static int gm_encode(unsigned int gbdata[], const size_t length, char binary[], printf("[%d] ", glyph); } - bin_append(glyph, 13, binary); + bp = bin_append_posn(glyph, 13, binary, bp); sp++; break; case GM_NUMBER: if (last_mode != current_mode) { /* Reserve a space for numeric digit padding value (2 bits) */ - number_pad_posn = strlen(binary); - strcat(binary, "XX"); + number_pad_posn = bp; + bp = bin_append_posn(0, 2, binary, bp); } p = 0; ppos = -1; @@ -539,7 +609,7 @@ static int gm_encode(unsigned int gbdata[], const size_t length, char binary[], printf("[%d] ", glyph); } - bin_append(glyph, 10, binary); + bp = bin_append_posn(glyph, 10, binary, bp); } glyph = (100 * (numbuf[0] - '0')) + (10 * (numbuf[1] - '0')) + (numbuf[2] - '0'); @@ -547,34 +617,34 @@ static int gm_encode(unsigned int gbdata[], const size_t length, char binary[], printf("[%d] ", glyph); } - bin_append(glyph, 10, binary); + bp = bin_append_posn(glyph, 10, binary, bp); break; case GM_BYTE: if (last_mode != current_mode) { /* Reserve space for byte block length indicator (9 bits) */ - byte_count_posn = strlen(binary); - strcat(binary, "LLLLLLLLL"); + byte_count_posn = bp; + bp = bin_append_posn(0, 9, binary, bp); } glyph = gbdata[sp]; if (byte_count == 512 || (glyph > 0xFF && byte_count == 511)) { /* Maximum byte block size is 512 bytes. If longer is needed then start a new block */ if (glyph > 0xFF && byte_count == 511) { /* Split double-byte */ - bin_append(glyph >> 8, 8, binary); + bp = bin_append_posn(glyph >> 8, 8, binary, bp); glyph &= 0xFF; byte_count++; } add_byte_count(binary, byte_count_posn, byte_count); - bin_append(7, 4, binary); - byte_count_posn = strlen(binary); - strcat(binary, "LLLLLLLLL"); + bp = bin_append_posn(7, 4, binary, bp); + byte_count_posn = bp; + bp = bin_append_posn(0, 9, binary, bp); byte_count = 0; } if (debug & ZINT_DEBUG_PRINT) { printf("[%d] ", glyph); } - bin_append(glyph, glyph > 0xFF ? 16 : 8, binary); + bp = bin_append_posn(glyph, glyph > 0xFF ? 16 : 8, binary, bp); sp++; byte_count++; if (glyph > 0xFF) { @@ -586,14 +656,11 @@ static int gm_encode(unsigned int gbdata[], const size_t length, char binary[], shift = 1; if ((gbdata[sp] >= '0') && (gbdata[sp] <= '9')) { shift = 0; - } - if ((gbdata[sp] >= 'A') && (gbdata[sp] <= 'Z')) { + } else if ((gbdata[sp] >= 'A') && (gbdata[sp] <= 'Z')) { shift = 0; - } - if ((gbdata[sp] >= 'a') && (gbdata[sp] <= 'z')) { + } else if ((gbdata[sp] >= 'a') && (gbdata[sp] <= 'z')) { shift = 0; - } - if (gbdata[sp] == ' ') { + } else if (gbdata[sp] == ' ') { shift = 0; } @@ -604,11 +671,11 @@ static int gm_encode(unsigned int gbdata[], const size_t length, char binary[], printf("[%d] ", glyph); } - bin_append(glyph, 6, binary); + bp = bin_append_posn(glyph, 6, binary, bp); } else { /* Shift Mode character */ - bin_append(1014, 10, binary); /* shift indicator */ - add_shift_char(binary, gbdata[sp], debug); + bp = bin_append_posn(1014, 10, binary, bp); /* shift indicator */ + bp = add_shift_char(binary, bp, gbdata[sp], debug); } sp++; @@ -618,8 +685,7 @@ static int gm_encode(unsigned int gbdata[], const size_t length, char binary[], shift = 1; if ((gbdata[sp] >= 'A') && (gbdata[sp] <= 'Z')) { shift = 0; - } - if (gbdata[sp] == ' ') { + } else if (gbdata[sp] == ' ') { shift = 0; } @@ -630,11 +696,11 @@ static int gm_encode(unsigned int gbdata[], const size_t length, char binary[], printf("[%d] ", glyph); } - bin_append(glyph, 5, binary); + bp = bin_append_posn(glyph, 5, binary, bp); } else { /* Shift Mode character */ - bin_append(125, 7, binary); /* shift indicator */ - add_shift_char(binary, gbdata[sp], debug); + bp = bin_append_posn(125, 7, binary, bp); /* shift indicator */ + bp = add_shift_char(binary, bp, gbdata[sp], debug); } sp++; @@ -644,8 +710,7 @@ static int gm_encode(unsigned int gbdata[], const size_t length, char binary[], shift = 1; if ((gbdata[sp] >= 'a') && (gbdata[sp] <= 'z')) { shift = 0; - } - if (gbdata[sp] == ' ') { + } else if (gbdata[sp] == ' ') { shift = 0; } @@ -656,17 +721,17 @@ static int gm_encode(unsigned int gbdata[], const size_t length, char binary[], printf("[%d] ", glyph); } - bin_append(glyph, 5, binary); + bp = bin_append_posn(glyph, 5, binary, bp); } else { /* Shift Mode character */ - bin_append(125, 7, binary); /* shift indicator */ - add_shift_char(binary, gbdata[sp], debug); + bp = bin_append_posn(125, 7, binary, bp); /* shift indicator */ + bp = add_shift_char(binary, bp, gbdata[sp], debug); } sp++; break; } - if (strlen(binary) > 9191) { + if (bp > 9191) { return ZINT_ERROR_TOO_LONG; } @@ -694,37 +759,46 @@ static int gm_encode(unsigned int gbdata[], const size_t length, char binary[], /* Add "end of data" character */ switch (current_mode) { - case GM_CHINESE: bin_append(8160, 13, binary); + case GM_CHINESE: bp = bin_append_posn(8160, 13, binary, bp); break; - case GM_NUMBER: bin_append(1018, 10, binary); + case GM_NUMBER: bp = bin_append_posn(1018, 10, binary, bp); break; case GM_LOWER: - case GM_UPPER: bin_append(27, 5, binary); + case GM_UPPER: bp = bin_append_posn(27, 5, binary, bp); break; - case GM_MIXED: bin_append(1008, 10, binary); + case GM_MIXED: bp = bin_append_posn(1008, 10, binary, bp); break; - case GM_BYTE: bin_append(0, 4, binary); + case GM_BYTE: bp = bin_append_posn(0, 4, binary, bp); break; } /* Add padding bits if required */ - p = 7 - (strlen(binary) % 7); + p = 7 - (bp % 7); if (p % 7) { - bin_append(0, p, binary); + bp = bin_append_posn(0, p, binary, bp); } - if (strlen(binary) > 9191) { + if (bp > 9191) { return ZINT_ERROR_TOO_LONG; } + binary[bp] = '\0'; + *bin_len = bp; + + if (debug & ZINT_DEBUG_PRINT) { + printf("\nBinary (%d): %s\n", bp, binary); + } + return 0; } -static void gm_add_ecc(const char binary[], const size_t data_posn, const int layers, const int ecc_level, unsigned char word[]) { +static void gm_add_ecc(const char binary[], const int data_posn, const int layers, const int ecc_level, + unsigned char word[]) { int data_cw, i, j, wp, p; int n1, b1, n2, b2, e1, b3, e2; int block_size, ecc_size; unsigned char data[1320], block[130]; unsigned char data_block[115], ecc_block[70]; + rs_t rs; data_cw = gm_data_codewords[((layers - 1) * 5) + (ecc_level - 1)]; @@ -733,7 +807,7 @@ static void gm_add_ecc(const char binary[], const size_t data_posn, const int la } /* Convert from binary stream to 7-bit codewords */ - for (i = 0; i < (int) data_posn; i++) { + for (i = 0; i < data_posn; i++) { for (p = 0; p < 7; p++) { if (binary[i * 7 + p] == '1') { data[i] += (0x40 >> p); @@ -743,7 +817,7 @@ static void gm_add_ecc(const char binary[], const size_t data_posn, const int la /* Add padding codewords */ data[data_posn] = 0x00; - for (i = (int) (data_posn + 1); i < data_cw; i++) { + for (i = (data_posn + 1); i < data_cw; i++) { if (i & 1) { data[i] = 0x7e; } else { @@ -760,6 +834,8 @@ static void gm_add_ecc(const char binary[], const size_t data_posn, const int la b3 = gm_ebeb[((layers - 1) * 20) + ((ecc_level - 1) * 4) + 1]; e2 = gm_ebeb[((layers - 1) * 20) + ((ecc_level - 1) * 4) + 2]; + rs_init_gf(&rs, 0x89); + /* Split the data into blocks */ wp = 0; for (i = 0; i < (b1 + b2); i++) { @@ -784,10 +860,8 @@ static void gm_add_ecc(const char binary[], const size_t data_posn, const int la } /* Calculate ECC data for this block */ - rs_init_gf(0x89); - rs_init_code(ecc_size, 1); - rs_encode(data_size, data_block, ecc_block); - rs_free(); + rs_init_code(&rs, ecc_size, 1); + rs_encode(&rs, data_size, data_block, ecc_block); /* Correct error correction data but in reverse order */ for (j = 0; j < data_size; j++) { @@ -922,15 +996,17 @@ static void place_layer_id(char* grid, int size, int layers, int modules, int ec } } -INTERNAL int grid_matrix(struct zint_symbol *symbol, const unsigned char source[], size_t length) { +INTERNAL int grid_matrix(struct zint_symbol *symbol, unsigned char source[], int length) { int size, modules, error_number; int auto_layers, min_layers, layers, auto_ecc_level, min_ecc_level, ecc_level; int x, y, i; int full_multibyte; char binary[9300]; int data_cw, input_latch = 0; - unsigned char word[1460]; + unsigned char word[1460] = {0}; int data_max, reader = 0; + int size_squared; + int bin_len; #ifndef _MSC_VER unsigned int gbdata[length + 1]; @@ -939,11 +1015,8 @@ INTERNAL int grid_matrix(struct zint_symbol *symbol, const unsigned char source[ unsigned int* gbdata = (unsigned int *) _alloca((length + 1) * sizeof (unsigned int)); #endif - for (i = 0; i < 1460; i++) { - word[i] = 0; - } - - full_multibyte = symbol->option_3 == ZINT_FULL_MULTIBYTE; /* If set use Hanzi mode in DATA_MODE or for single-byte Latin */ + /* If ZINT_FULL_MULTIBYTE set use Hanzi mode in DATA_MODE or for single-byte Latin */ + full_multibyte = (symbol->option_3 & 0xFF) == ZINT_FULL_MULTIBYTE; if ((symbol->input_mode & 0x07) == DATA_MODE) { gb2312_cpy(source, &length, gbdata, full_multibyte); @@ -951,7 +1024,8 @@ INTERNAL int grid_matrix(struct zint_symbol *symbol, const unsigned char source[ int done = 0; if (symbol->eci != 29) { /* Unless ECI 29 (GB) */ /* Try single byte (Latin) conversion first */ - int error_number = gb2312_utf8tosb(symbol->eci && symbol->eci <= 899 ? symbol->eci : 3, source, &length, gbdata, full_multibyte); + error_number = gb2312_utf8tosb(symbol->eci && symbol->eci <= 899 ? symbol->eci : 3, source, &length, + gbdata, full_multibyte); if (error_number == 0) { done = 1; } else if (symbol->eci && symbol->eci <= 899) { @@ -961,7 +1035,7 @@ INTERNAL int grid_matrix(struct zint_symbol *symbol, const unsigned char source[ } if (!done) { /* Try GB 2312 (EUC-CN) */ - int error_number = gb2312_utf8tomb(symbol, source, &length, gbdata); + error_number = gb2312_utf8tomb(symbol, source, &length, gbdata); if (error_number != 0) { return error_number; } @@ -975,14 +1049,14 @@ INTERNAL int grid_matrix(struct zint_symbol *symbol, const unsigned char source[ return ZINT_ERROR_INVALID_OPTION; } - error_number = gm_encode(gbdata, length, binary, reader, symbol->eci, symbol->debug); + error_number = gm_encode(gbdata, length, binary, reader, symbol->eci, &bin_len, symbol->debug); if (error_number != 0) { strcpy(symbol->errtxt, "531: Input data too long"); return error_number; } /* Determine the size of the symbol */ - data_cw = (int)strlen(binary) / 7; + data_cw = bin_len / 7; /* Binary length always a multiple of 7 */ auto_layers = 13; for (i = 12; i > 0; i--) { @@ -1011,8 +1085,7 @@ INTERNAL int grid_matrix(struct zint_symbol *symbol, const unsigned char source[ auto_ecc_level = 3; if (layers == 1) { auto_ecc_level = 5; - } - if ((layers == 2) || (layers == 3)) { + } else if ((layers == 2) || (layers == 3)) { auto_ecc_level = 4; } ecc_level = auto_ecc_level; @@ -1020,8 +1093,7 @@ INTERNAL int grid_matrix(struct zint_symbol *symbol, const unsigned char source[ min_ecc_level = 1; if (layers == 1) { min_ecc_level = 4; - } - if (layers == 2) { + } else if (layers == 2) { min_ecc_level = 2; } @@ -1033,7 +1105,8 @@ INTERNAL int grid_matrix(struct zint_symbol *symbol, const unsigned char source[ } } if (data_cw > gm_data_codewords[(5 * (layers - 1)) + (ecc_level - 1)]) { - if (input_latch && ecc_level > min_ecc_level) { /* If layers user-specified (option_2), try reducing ECC level first */ + /* If layers user-specified (option_2), try reducing ECC level first */ + if (input_latch && ecc_level > min_ecc_level) { do { ecc_level--; } while ((data_cw > gm_data_codewords[(5 * (layers - 1)) + (ecc_level - 1)]) && (ecc_level > min_ecc_level)); @@ -1041,7 +1114,8 @@ INTERNAL int grid_matrix(struct zint_symbol *symbol, const unsigned char source[ while (data_cw > gm_data_codewords[(5 * (layers - 1)) + (ecc_level - 1)] && (layers < 13)) { layers++; } - while (data_cw > gm_data_codewords[(5 * (layers - 1)) + (ecc_level - 1)] && ecc_level > 1) { /* ECC min level 1 for layers > 2 */ + /* ECC min level 1 for layers > 2 */ + while (data_cw > gm_data_codewords[(5 * (layers - 1)) + (ecc_level - 1)] && ecc_level > 1) { ecc_level--; } } @@ -1069,18 +1143,15 @@ INTERNAL int grid_matrix(struct zint_symbol *symbol, const unsigned char source[ #endif size = 6 + (layers * 12); modules = 1 + (layers * 2); + size_squared = size * size; #ifndef _MSC_VER - char grid[size * size]; + char grid[size_squared]; #else - grid = (char *) _alloca((size * size) * sizeof (char)); + grid = (char *) _alloca(size_squared * sizeof(char)); #endif - for (x = 0; x < size; x++) { - for (y = 0; y < size; y++) { - grid[(y * size) + x] = '0'; - } - } + memset(grid, '0', size_squared); place_data_in_grid(word, grid, modules, size); place_layer_id(grid, size, layers, modules, ecc_level); diff --git a/backend/hanxin.c b/backend/hanxin.c index 25db2743..901411c1 100644 --- a/backend/hanxin.c +++ b/backend/hanxin.c @@ -30,10 +30,10 @@ */ /* vim: set ts=4 sw=4 et : */ -/* This code attempts to implement Han Xin Code according to ISO/IEC 20830 (draft 2019-10-10) (previously AIMD-015:2010 (Rev 0.8)) */ +/* This code attempts to implement Han Xin Code according to ISO/IEC 20830 (draft 2019-10-10) + * (previously AIMD-015:2010 (Rev 0.8)) */ #include -#include #ifdef _MSC_VER #include #endif @@ -45,26 +45,25 @@ #include "assert.h" /* Find which submode to use for a text character */ -static int getsubmode(unsigned int input) { - int submode = 2; +static int getsubmode(const unsigned int input) { if ((input >= '0') && (input <= '9')) { - submode = 1; + return 1; } if ((input >= 'A') && (input <= 'Z')) { - submode = 1; + return 1; } if ((input >= 'a') && (input <= 'z')) { - submode = 1; + return 1; } - return submode; + return 2; } /* Return length of terminator for encoding mode */ -static int terminator_length(char mode) { +static int terminator_length(const char mode) { int result = 0; switch (mode) { @@ -87,8 +86,8 @@ static int terminator_length(char mode) { } /* Calculate the length of the binary string */ -static int calculate_binlength(char mode[], unsigned int source[], const size_t length, int eci) { - size_t i; +static int calculate_binlength(const char mode[], const unsigned int source[], const int length, const int eci) { + int i; char lastmode = '\0'; int est_binlen = 0; int submode = 1; @@ -98,7 +97,7 @@ static int calculate_binlength(char mode[], unsigned int source[], const size_t est_binlen += 4; if (eci <= 127) { est_binlen += 8; - } else if ((eci >= 128) && (eci <= 16383)) { + } else if (eci <= 16383) { est_binlen += 16; } else { est_binlen += 24; @@ -160,135 +159,124 @@ static int calculate_binlength(char mode[], unsigned int source[], const size_t return est_binlen; } -static int isRegion1(unsigned int glyph) { - int first_byte, second_byte; - int valid = 0; +static int isRegion1(const unsigned int glyph) { + unsigned int byte; - first_byte = (glyph & 0xff00) >> 8; - second_byte = glyph & 0xff; + byte = glyph >> 8; - if ((first_byte >= 0xb0) && (first_byte <= 0xd7)) { - if ((second_byte >= 0xa1) && (second_byte <= 0xfe)) { - valid = 1; + if ((byte >= 0xb0) && (byte <= 0xd7)) { + byte = glyph & 0xff; + if ((byte >= 0xa1) && (byte <= 0xfe)) { + return 1; } - } - - if ((first_byte >= 0xa1) && (first_byte <= 0xa3)) { - if ((second_byte >= 0xa1) && (second_byte <= 0xfe)) { - valid = 1; + } else if ((byte >= 0xa1) && (byte <= 0xa3)) { + byte = glyph & 0xff; + if ((byte >= 0xa1) && (byte <= 0xfe)) { + return 1; } + } else if ((glyph >= 0xa8a1) && (glyph <= 0xa8c0)) { + return 1; } - if ((glyph >= 0xa8a1) && (glyph <= 0xa8c0)) { - valid = 1; - } - - return valid; + return 0; } -static int isRegion2(unsigned int glyph) { - int first_byte, second_byte; - int valid = 0; +static int isRegion2(const unsigned int glyph) { + unsigned int byte; - first_byte = (glyph & 0xff00) >> 8; - second_byte = glyph & 0xff; + byte = glyph >> 8; - if ((first_byte >= 0xd8) && (first_byte <= 0xf7)) { - if ((second_byte >= 0xa1) && (second_byte <= 0xfe)) { - valid = 1; + if ((byte >= 0xd8) && (byte <= 0xf7)) { + byte = glyph & 0xff; + if ((byte >= 0xa1) && (byte <= 0xfe)) { + return 1; } } - return valid; + return 0; } -static int isDoubleByte(unsigned int glyph) { - int first_byte, second_byte; - int valid = 0; +static int isDoubleByte(const unsigned int glyph) { + unsigned int byte; - first_byte = (glyph & 0xff00) >> 8; - second_byte = glyph & 0xff; + byte = glyph >> 8; - if ((first_byte >= 0x81) && (first_byte <= 0xfe)) { - if ((second_byte >= 0x40) && (second_byte <= 0x7e)) { - valid = 1; + if ((byte >= 0x81) && (byte <= 0xfe)) { + byte = glyph & 0xff; + if ((byte >= 0x40) && (byte <= 0x7e)) { + return 1; } - - if ((second_byte >= 0x80) && (second_byte <= 0xfe)) { - valid = 1; + if ((byte >= 0x80) && (byte <= 0xfe)) { + return 1; } } - return valid; + return 0; } -static int isFourByte(unsigned int glyph, unsigned int glyph2) { - int first_byte, second_byte; - int third_byte, fourth_byte; - int valid = 0; +static int isFourByte(const unsigned int glyph, const unsigned int glyph2) { + unsigned int byte; - first_byte = (glyph & 0xff00) >> 8; - second_byte = glyph & 0xff; - third_byte = (glyph2 & 0xff00) >> 8; - fourth_byte = glyph2 & 0xff; + byte = glyph >> 8; - if ((first_byte >= 0x81) && (first_byte <= 0xfe)) { - if ((second_byte >= 0x30) && (second_byte <= 0x39)) { - if ((third_byte >= 0x81) && (third_byte <= 0xfe)) { - if ((fourth_byte >= 0x30) && (fourth_byte <= 0x39)) { - valid = 1; + if ((byte >= 0x81) && (byte <= 0xfe)) { + byte = glyph & 0xff; + if ((byte >= 0x30) && (byte <= 0x39)) { + byte = glyph2 >> 8; + if ((byte >= 0x81) && (byte <= 0xfe)) { + byte = glyph2 & 0xff; + if ((byte >= 0x30) && (byte <= 0x39)) { + return 1; } } } } - return valid; + return 0; } /* Convert Text 1 sub-mode character to encoding value, as given in table 3 */ -static int lookup_text1(unsigned int input) { - int encoding_value = -1; +static int lookup_text1(const unsigned int input) { if ((input >= '0') && (input <= '9')) { - encoding_value = input - '0'; + return input - '0'; } if ((input >= 'A') && (input <= 'Z')) { - encoding_value = input - 'A' + 10; + return input - 'A' + 10; } if ((input >= 'a') && (input <= 'z')) { - encoding_value = input - 'a' + 36; + return input - 'a' + 36; } - return encoding_value; + return -1; } /* Convert Text 2 sub-mode character to encoding value, as given in table 4 */ -static int lookup_text2(unsigned int input) { - int encoding_value = -1; +static int lookup_text2(const unsigned int input) { if (input <= 27) { - encoding_value = input; + return input; } if ((input >= ' ') && (input <= '/')) { - encoding_value = input - ' ' + 28; + return input - ' ' + 28; } if ((input >= ':') && (input <= '@')) { - encoding_value = input - ':' + 44; + return input - ':' + 44; } if ((input >= '[') && (input <= 96)) { - encoding_value = input - '[' + 51; + return input - '[' + 51; } if ((input >= '{') && (input <= 127)) { - encoding_value = input - '{' + 57; + return input - '{' + 57; } - return encoding_value; + return -1; } /* hx_define_mode() stuff */ @@ -296,18 +284,20 @@ static int lookup_text2(unsigned int input) { /* Bits multiplied by this for costs, so as to be whole integer divisible by 2 and 3 */ #define HX_MULT 6 -/* Whether in numeric or not. If in numeric, *p_end is set to position after numeric, and *p_cost is set to per-numeric cost */ -static int in_numeric(const unsigned int gbdata[], const size_t length, const unsigned int posn, unsigned int* p_end, unsigned int* p_cost) { - unsigned int i, digit_cnt; +/* Whether in numeric or not. If in numeric, *p_end is set to position after numeric, + * and *p_cost is set to per-numeric cost */ +static int in_numeric(const unsigned int gbdata[], const int length, const int in_posn, + unsigned int *p_end, unsigned int *p_cost) { + int i, digit_cnt; - if (posn < *p_end) { + if (in_posn < (int) *p_end) { return 1; } /* Attempt to calculate the average 'cost' of using numeric mode in number of bits (times HX_MULT) */ - for (i = posn; i < length && i < posn + 4 && gbdata[i] >= '0' && gbdata[i] <= '9'; i++); + for (i = in_posn; i < length && i < in_posn + 4 && gbdata[i] >= '0' && gbdata[i] <= '9'; i++); - digit_cnt = i - posn; + digit_cnt = i - in_posn; if (digit_cnt == 0) { *p_end = 0; @@ -318,17 +308,19 @@ static int in_numeric(const unsigned int gbdata[], const size_t length, const un return 1; } -/* Whether in four-byte or not. If in four-byte, *p_fourbyte is set to position after four-byte, and *p_fourbyte_cost is set to per-position cost */ -static int in_fourbyte(const unsigned int gbdata[], const size_t length, const unsigned int posn, unsigned int* p_end, unsigned int* p_cost) { - if (posn < *p_end) { +/* Whether in four-byte or not. If in four-byte, *p_fourbyte is set to position after four-byte, + * and *p_fourbyte_cost is set to per-position cost */ +static int in_fourbyte(const unsigned int gbdata[], const int length, const int in_posn, + unsigned int *p_end, unsigned int *p_cost) { + if (in_posn < (int) *p_end) { return 1; } - if (posn == length - 1 || !isFourByte(gbdata[posn], gbdata[posn + 1])) { + if (in_posn == length - 1 || !isFourByte(gbdata[in_posn], gbdata[in_posn + 1])) { *p_end = 0; return 0; } - *p_end = posn + 2; + *p_end = in_posn + 2; *p_cost = 75; /* ((4 + 21) / 2) * HX_MULT */ return 1; } @@ -345,19 +337,19 @@ static int in_fourbyte(const unsigned int gbdata[], const size_t length, const u #define HX_NUM_MODES 7 -/* Initial mode costs */ -static unsigned int* hx_head_costs(unsigned int state[]) { +/* Calculate optimized encoding modes. Adapted from Project Nayuki */ +/* Copyright (c) Project Nayuki. (MIT License) See qr.c for detailed notice */ +static void hx_define_mode(char *mode, const unsigned int gbdata[], const int length, const int debug) { + /* Must be in same order as HX_N etc */ + static const char mode_types[] = { 'n', 't', 'b', '1', '2', 'd', 'f', '\0' }; + + /* Initial mode costs */ static unsigned int head_costs[HX_NUM_MODES] = { /* N T B 1 2 D F */ 4 * HX_MULT, 4 * HX_MULT, (4 + 13) * HX_MULT, 4 * HX_MULT, 4 * HX_MULT, 4 * HX_MULT, 0 }; - (void)state; /* Unused */ - return head_costs; -} - -/* Cost of switching modes from k to j */ -static unsigned int hx_switch_cost(unsigned int state[], const int k, const int j) { + /* Cost of switching modes from k to j */ static const unsigned int switch_costs[HX_NUM_MODES][HX_NUM_MODES] = { /* N T B 1 2 D F */ /*N*/ { 0, (10 + 4) * HX_MULT, (10 + 4 + 13) * HX_MULT, (10 + 4) * HX_MULT, (10 + 4) * HX_MULT, (10 + 4) * HX_MULT, 10 * HX_MULT }, @@ -369,103 +361,147 @@ static unsigned int hx_switch_cost(unsigned int state[], const int k, const int /*F*/ { 4 * HX_MULT, 4 * HX_MULT, (4 + 13) * HX_MULT, 4 * HX_MULT, 4 * HX_MULT, 4 * HX_MULT, 0 }, }; - (void)state; /* Unused */ - return switch_costs[k][j]; -} - -/* Final end-of-data costs */ -static unsigned int hx_eod_cost(unsigned int state[], const int k) { + /* Final end-of-data costs */ static const unsigned int eod_costs[HX_NUM_MODES] = { /* N T B 1 2 D F */ 10 * HX_MULT, 6 * HX_MULT, 0, 12 * HX_MULT, 12 * HX_MULT, 15 * HX_MULT, 0 }; - (void)state; /* Unused */ - return eod_costs[k]; -} - -/* Calculate cost of encoding character */ -static void hx_cur_cost(unsigned int state[], const unsigned int gbdata[], const size_t length, const int i, char* char_modes, unsigned int prev_costs[], unsigned int cur_costs[]) { - int cm_i = i * HX_NUM_MODES; + unsigned int numeric_end = 0, numeric_cost = 0, text_submode = 1, fourbyte_end = 0, fourbyte_cost = 0; /* State */ int text1, text2; - unsigned int* p_numeric_end = &state[0]; - unsigned int* p_numeric_cost = &state[1]; - unsigned int* p_text_submode = &state[2]; - unsigned int* p_fourbyte_end = &state[3]; - unsigned int* p_fourbyte_cost = &state[4]; - if (in_numeric(gbdata, length, i, p_numeric_end, p_numeric_cost)) { - cur_costs[HX_N] = prev_costs[HX_N] + *p_numeric_cost; - char_modes[cm_i + HX_N] = 'n'; - } + int i, j, k, cm_i; + unsigned int min_cost; + char cur_mode; + unsigned int prev_costs[HX_NUM_MODES]; + unsigned int cur_costs[HX_NUM_MODES]; +#ifndef _MSC_VER + char char_modes[length * HX_NUM_MODES]; +#else + char *char_modes = (char *) _alloca(length * HX_NUM_MODES); +#endif - text1 = lookup_text1(gbdata[i]) != -1; - text2 = lookup_text2(gbdata[i]) != -1; + /* char_modes[i * HX_NUM_MODES + j] represents the mode to encode the code point at index i such that the final + * segment ends in mode_types[j] and the total number of bits is minimized over all possible choices */ + memset(char_modes, 0, length * HX_NUM_MODES); - if (text1 || text2) { - if ((*p_text_submode == 1 && text2) || (*p_text_submode == 2 && text1)) { - cur_costs[HX_T] = prev_costs[HX_T] + 72; /* (6 + 6) * HX_MULT */ - *p_text_submode = text2 ? 2 : 1; - } else { - cur_costs[HX_T] = prev_costs[HX_T] + 36; /* 6 * HX_MULT */ + /* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/XX_MULT) + * bits needed to encode the entire string prefix of length i, and end in mode_types[j] */ + memcpy(prev_costs, head_costs, HX_NUM_MODES * sizeof(unsigned int)); + + /* Calculate costs using dynamic programming */ + for (i = 0, cm_i = 0; i < length; i++, cm_i += HX_NUM_MODES) { + memset(cur_costs, 0, HX_NUM_MODES * sizeof(unsigned int)); + + if (in_numeric(gbdata, length, i, &numeric_end, &numeric_cost)) { + cur_costs[HX_N] = prev_costs[HX_N] + numeric_cost; + char_modes[cm_i + HX_N] = 'n'; } - char_modes[cm_i + HX_T] = 't'; - } else { - *p_text_submode = 1; + + text1 = lookup_text1(gbdata[i]) != -1; + text2 = lookup_text2(gbdata[i]) != -1; + + if (text1 || text2) { + if ((text_submode == 1 && text2) || (text_submode == 2 && text1)) { + cur_costs[HX_T] = prev_costs[HX_T] + 72; /* (6 + 6) * HX_MULT */ + text_submode = text2 ? 2 : 1; + } else { + cur_costs[HX_T] = prev_costs[HX_T] + 36; /* 6 * HX_MULT */ + } + char_modes[cm_i + HX_T] = 't'; + } else { + text_submode = 1; + } + + /* Binary mode can encode anything */ + cur_costs[HX_B] = prev_costs[HX_B] + (gbdata[i] > 0xFF ? 96 : 48); /* (16 : 8) * HX_MULT */ + char_modes[cm_i + HX_B] = 'b'; + + if (isRegion1(gbdata[i])) { + cur_costs[HX_1] = prev_costs[HX_1] + 72; /* 12 * HX_MULT */ + char_modes[cm_i + HX_1] = '1'; + } + if (isRegion2(gbdata[i])) { + cur_costs[HX_2] = prev_costs[HX_2] + 72; /* 12 * HX_MULT */ + char_modes[cm_i + HX_2] = '2'; + } + if (isDoubleByte(gbdata[i])) { + cur_costs[HX_D] = prev_costs[HX_D] + 90; /* 15 * HX_MULT */ + char_modes[cm_i + HX_D] = 'd'; + } + if (in_fourbyte(gbdata, length, i, &fourbyte_end, &fourbyte_cost)) { + cur_costs[HX_F] = prev_costs[HX_F] + fourbyte_cost; + char_modes[cm_i + HX_F] = 'f'; + } + + if (i == length - 1) { /* Add end of data costs if last character */ + for (j = 0; j < HX_NUM_MODES; j++) { + if (char_modes[cm_i + j]) { + cur_costs[j] += eod_costs[j]; + } + } + } + + /* Start new segment at the end to switch modes */ + for (j = 0; j < HX_NUM_MODES; j++) { /* To mode */ + for (k = 0; k < HX_NUM_MODES; k++) { /* From mode */ + if (j != k && char_modes[cm_i + k]) { + unsigned int new_cost = cur_costs[k] + switch_costs[k][j]; + if (!char_modes[cm_i + j] || new_cost < cur_costs[j]) { + cur_costs[j] = new_cost; + char_modes[cm_i + j] = mode_types[k]; + } + } + } + } + + memcpy(prev_costs, cur_costs, HX_NUM_MODES * sizeof(unsigned int)); } - /* Binary mode can encode anything */ - cur_costs[HX_B] = prev_costs[HX_B] + (gbdata[i] > 0xFF ? 96 : 48); /* (16 : 8) * HX_MULT */ - char_modes[cm_i + HX_B] = 'b'; + /* Find optimal ending mode */ + min_cost = prev_costs[0]; + cur_mode = mode_types[0]; + for (i = 1; i < HX_NUM_MODES; i++) { + if (prev_costs[i] < min_cost) { + min_cost = prev_costs[i]; + cur_mode = mode_types[i]; + } + } - if (isRegion1(gbdata[i])) { - cur_costs[HX_1] = prev_costs[HX_1] + 72; /* 12 * HX_MULT */ - char_modes[cm_i + HX_1] = '1'; + /* 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) { + j = strchr(mode_types, cur_mode) - mode_types; + cur_mode = char_modes[cm_i + j]; + mode[i] = cur_mode; } - if (isRegion2(gbdata[i])) { - cur_costs[HX_2] = prev_costs[HX_2] + 72; /* 12 * HX_MULT */ - char_modes[cm_i + HX_2] = '2'; - } - if (isDoubleByte(gbdata[i])) { - cur_costs[HX_D] = prev_costs[HX_D] + 90; /* 15 * HX_MULT */ - char_modes[cm_i + HX_D] = 'd'; - } - if (in_fourbyte(gbdata, length, i, p_fourbyte_end, p_fourbyte_cost)) { - cur_costs[HX_F] = prev_costs[HX_F] + *p_fourbyte_cost; - char_modes[cm_i + HX_F] = 'f'; - } -} -/* Calculate optimized encoding modes */ -static void hx_define_mode(char* mode, const unsigned int gbdata[], const size_t length, const int debug) { - static const char mode_types[] = { 'n', 't', 'b', '1', '2', 'd', 'f', '\0' }; /* Must be in same order as HX_N etc */ - unsigned int state[5] = { 0 /*numeric_end*/, 0 /*numeric_cost*/, 1 /*text_submode*/, 0 /*fourbyte_end*/, 0 /*fourbyte_cost*/ }; - - pn_define_mode(mode, gbdata, length, debug, state, mode_types, HX_NUM_MODES, hx_head_costs, hx_switch_cost, hx_eod_cost, hx_cur_cost); + if (debug & ZINT_DEBUG_PRINT) { + printf(" Mode: %.*s\n", length, mode); + } } /* Convert input data to binary stream */ -static void calculate_binary(char binary[], char mode[], unsigned int source[], const size_t length, const int eci, int debug) { - unsigned int position = 0; +static void calculate_binary(char binary[], const char mode[], unsigned int source[], const int length, const int eci, + int *bin_len, const int debug) { + int position = 0; int i, count, encoding_value; int first_byte, second_byte; int third_byte, fourth_byte; int glyph; int submode; + int bp = 0; if (eci != 0) { /* Encoding ECI assignment number, according to Table 5 */ - bin_append(8, 4, binary); // ECI + bp = bin_append_posn(8, 4, binary, bp); // ECI if (eci <= 127) { - bin_append(eci, 8, binary); - } - if ((eci >= 128) && (eci <= 16383)) { - strcat(binary, "10"); - bin_append(eci, 14, binary); - } - if (eci >= 16384) { - strcat(binary, "110"); - bin_append(eci, 21, binary); + bp = bin_append_posn(eci, 8, binary, bp); + } else if (eci <= 16383) { + bp = bin_append_posn(2, 2, binary, bp); + bp = bin_append_posn(eci, 14, binary, bp); + } else { + bp = bin_append_posn(6, 3, binary, bp); + bp = bin_append_posn(eci, 21, binary, bp); } } @@ -483,7 +519,7 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], case 'n': /* Numeric mode */ /* Mode indicator */ - bin_append(1, 4, binary); + bp = bin_append_posn(1, 4, binary, bp); if (debug & ZINT_DEBUG_PRINT) { printf("Numeric\n"); @@ -511,10 +547,10 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], } } - bin_append(encoding_value, 10, binary); + bp = bin_append_posn(encoding_value, 10, binary, bp); if (debug & ZINT_DEBUG_PRINT) { - printf("0x%4x (%d)", encoding_value, encoding_value); + printf("0x%3x (%d)", encoding_value, encoding_value); } i += count; @@ -523,13 +559,13 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], /* Mode terminator depends on number of characters in last group (Table 2) */ switch (count) { case 1: - bin_append(1021, 10, binary); + bp = bin_append_posn(1021, 10, binary, bp); break; case 2: - bin_append(1022, 10, binary); + bp = bin_append_posn(1022, 10, binary, bp); break; case 3: - bin_append(1023, 10, binary); + bp = bin_append_posn(1023, 10, binary, bp); break; } @@ -541,7 +577,7 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], case 't': /* Text mode */ /* Mode indicator */ - bin_append(2, 4, binary); + bp = bin_append_posn(2, 4, binary, bp); if (debug & ZINT_DEBUG_PRINT) { printf("Text\n"); @@ -555,7 +591,7 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], if (getsubmode(source[i + position]) != submode) { /* Change submode */ - bin_append(62, 6, binary); + bp = bin_append_posn(62, 6, binary, bp); submode = getsubmode(source[i + position]); if (debug & ZINT_DEBUG_PRINT) { printf("SWITCH "); @@ -568,7 +604,7 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], encoding_value = lookup_text2(source[i + position]); } - bin_append(encoding_value, 6, binary); + bp = bin_append_posn(encoding_value, 6, binary, bp); if (debug & ZINT_DEBUG_PRINT) { printf("%.2x [ASC %.2x] ", encoding_value, source[i + position]); @@ -577,7 +613,7 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], } /* Terminator */ - bin_append(63, 6, binary); + bp = bin_append_posn(63, 6, binary, bp); if (debug & ZINT_DEBUG_PRINT) { printf("\n"); @@ -586,10 +622,10 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], case 'b': /* Binary Mode */ /* Mode indicator */ - bin_append(3, 4, binary); + bp = bin_append_posn(3, 4, binary, bp); /* Count indicator */ - bin_append(block_length + double_byte, 13, binary); + bp = bin_append_posn(block_length + double_byte, 13, binary, bp); if (debug & ZINT_DEBUG_PRINT) { printf("Binary (length %d)\n", block_length + double_byte); @@ -600,7 +636,7 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], while (i < block_length) { /* 8-bit bytes with no conversion */ - bin_append(source[i + position], source[i + position] > 0xFF ? 16 : 8, binary); + bp = bin_append_posn(source[i + position], source[i + position] > 0xFF ? 16 : 8, binary, bp); if (debug & ZINT_DEBUG_PRINT) { printf("%d ", source[i + position]); @@ -617,11 +653,11 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], /* Region 1 encoding */ /* Mode indicator */ if (position == 0 || mode[position - 1] != '2') { /* Unless previous mode Region 2 */ - bin_append(4, 4, binary); + bp = bin_append_posn(4, 4, binary, bp); } if (debug & ZINT_DEBUG_PRINT) { - printf("Region 1\n"); + printf("Region 1%s\n", position == 0 || mode[position - 1] != '2' ? "" : " (NO indicator)" ); } i = 0; @@ -646,18 +682,18 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], } if (debug & ZINT_DEBUG_PRINT) { - printf("%.4x [GB %.4x] ", glyph, source[i + position]); + printf("%.3x [GB %.4x] ", glyph, source[i + position]); } - bin_append(glyph, 12, binary); + bp = bin_append_posn(glyph, 12, binary, bp); i++; } /* Terminator */ - bin_append(position == length - 1 || mode[position + 1] != '2' ? 4095 : 4094, 12, binary); + bp = bin_append_posn(position + block_length == length || mode[position + block_length] != '2' ? 4095 : 4094, 12, binary, bp); if (debug & ZINT_DEBUG_PRINT) { - printf("\n"); + printf("(TERM %x)\n", position + block_length == length || mode[position + block_length] != '2' ? 4095 : 4094); } break; @@ -665,11 +701,11 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], /* Region 2 encoding */ /* Mode indicator */ if (position == 0 || mode[position - 1] != '1') { /* Unless previous mode Region 1 */ - bin_append(5, 4, binary); + bp = bin_append_posn(5, 4, binary, bp); } if (debug & ZINT_DEBUG_PRINT) { - printf("Region 2\n"); + printf("Region 2%s\n", position == 0 || mode[position - 1] != '1' ? "" : " (NO indicator)" ); } i = 0; @@ -681,24 +717,25 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], glyph = (0x5e * (first_byte - 0xd8)) + (second_byte - 0xa1); if (debug & ZINT_DEBUG_PRINT) { - printf("%.4x [GB %.4x] ", glyph, source[i + position]); + printf("%.3x [GB %.4x] ", glyph, source[i + position]); } - bin_append(glyph, 12, binary); + bp = bin_append_posn(glyph, 12, binary, bp); i++; } /* Terminator */ - bin_append(position == length - 1 || mode[position + 1] != '1' ? 4095 : 4094, 12, binary); + bp = bin_append_posn(position + block_length == length || mode[position + block_length] != '1' ? 4095 : 4094, 12, binary, bp); if (debug & ZINT_DEBUG_PRINT) { - printf("\n"); + printf("(TERM %x)\n", position + block_length == length || mode[position + block_length] != '1' ? 4095 : 4094); } + break; case 'd': /* Double byte encoding */ /* Mode indicator */ - bin_append(6, 4, binary); + bp = bin_append_posn(6, 4, binary, bp); if (debug & ZINT_DEBUG_PRINT) { printf("Double byte\n"); @@ -720,12 +757,12 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], printf("%.4x ", glyph); } - bin_append(glyph, 15, binary); + bp = bin_append_posn(glyph, 15, binary, bp); i++; } /* Terminator */ - bin_append(32767, 15, binary); + bp = bin_append_posn(32767, 15, binary, bp); /* Terminator sequence of length 12 is a mistake - confirmed by Wang Yi */ @@ -744,7 +781,7 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], while (i < block_length) { /* Mode indicator */ - bin_append(7, 4, binary); + bp = bin_append_posn(7, 4, binary, bp); first_byte = (source[i + position] & 0xff00) >> 8; second_byte = source[i + position] & 0xff; @@ -758,7 +795,7 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], printf("%d ", glyph); } - bin_append(glyph, 21, binary); + bp = bin_append_posn(glyph, 21, binary, bp); i += 2; } @@ -768,16 +805,21 @@ static void calculate_binary(char binary[], char mode[], unsigned int source[], printf("\n"); } break; - } position += block_length; } while (position < length); + + binary[bp] = '\0'; + + if (debug & ZINT_DEBUG_PRINT) printf("Binary (%d): %s\n", bp, binary); + + *bin_len = bp; } /* Finder pattern for top left of symbol */ -static void hx_place_finder_top_left(unsigned char* grid, int size) { +static void hx_place_finder_top_left(unsigned char *grid, const int size) { int xp, yp; int x = 0, y = 0; char finder[] = {0x7F, 0x40, 0x5F, 0x50, 0x57, 0x57, 0x57}; @@ -794,7 +836,7 @@ static void hx_place_finder_top_left(unsigned char* grid, int size) { } /* Finder pattern for top right and bottom left of symbol */ -static void hx_place_finder(unsigned char* grid, int size, int x, int y) { +static void hx_place_finder(unsigned char *grid, const int size, const int x, const int y) { int xp, yp; char finder[] = {0x7F, 0x01, 0x7D, 0x05, 0x75, 0x75, 0x75}; @@ -810,7 +852,7 @@ static void hx_place_finder(unsigned char* grid, int size, int x, int y) { } /* Finder pattern for bottom right of symbol */ -static void hx_place_finder_bottom_right(unsigned char* grid, int size) { +static void hx_place_finder_bottom_right(unsigned char *grid, const int size) { int xp, yp; int x = size - 7, y = size - 7; char finder[] = {0x75, 0x75, 0x75, 0x05, 0x7D, 0x01, 0x7F}; @@ -827,7 +869,7 @@ static void hx_place_finder_bottom_right(unsigned char* grid, int size) { } /* Avoid plotting outside symbol or over finder patterns */ -static void hx_safe_plot(unsigned char *grid, int size, int x, int y, int value) { +static void hx_safe_plot(unsigned char *grid, const int size, const int x, const int y, const int value) { if ((x >= 0) && (x < size)) { if ((y >= 0) && (y < size)) { if (grid[(y * size) + x] == 0) { @@ -838,7 +880,7 @@ static void hx_safe_plot(unsigned char *grid, int size, int x, int y, int value) } /* Plot an alignment pattern around top and right of a module */ -static void hx_plot_alignment(unsigned char *grid, int size, int x, int y, int w, int h) { +static void hx_plot_alignment(unsigned char *grid, const int size, const int x, const int y, const int w, const int h) { int i; hx_safe_plot(grid, size, x, y, 0x11); hx_safe_plot(grid, size, x - 1, y + 1, 0x10); @@ -857,7 +899,7 @@ static void hx_plot_alignment(unsigned char *grid, int size, int x, int y, int w } /* Plot assistant alignment patterns */ -static void hx_plot_assistant(unsigned char *grid, int size, int x, int y) { +static void hx_plot_assistant(unsigned char *grid, const int size, const int x, const int y) { hx_safe_plot(grid, size, x - 1, y - 1, 0x10); hx_safe_plot(grid, size, x, y - 1, 0x10); hx_safe_plot(grid, size, x + 1, y - 1, 0x10); @@ -870,14 +912,10 @@ static void hx_plot_assistant(unsigned char *grid, int size, int x, int y) { } /* Put static elements in the grid */ -static void hx_setup_grid(unsigned char* grid, int size, int version) { - int i, j; +static void hx_setup_grid(unsigned char *grid, const int size, const int version) { + int i; - for (i = 0; i < size; i++) { - for (j = 0; j < size; j++) { - grid[(i * size) + j] = 0; - } - } + memset(grid, 0, (size_t) size * size); /* Add finder patterns */ hx_place_finder_top_left(grid, size); @@ -941,12 +979,12 @@ static void hx_setup_grid(unsigned char* grid, int size, int version) { module_height = r - 1; } - if ((mod_y % 2) == 0) { - if ((m % 2) == 1) { + if ((mod_y & 1) == 0) { + if ((m & 1) == 1) { hx_plot_assistant(grid, size, 0, y); } } else { - if ((m % 2) == 0) { + if ((m & 1) == 0) { hx_plot_assistant(grid, size, 0, y); } hx_plot_assistant(grid, size, size - 1, y); @@ -966,12 +1004,12 @@ static void hx_setup_grid(unsigned char* grid, int size, int version) { module_width = r - 1; } - if ((mod_x % 2) == 0) { - if ((m % 2) == 1) { + if ((mod_x & 1) == 0) { + if ((m & 1) == 1) { hx_plot_assistant(grid, size, x, (size - 1)); } } else { - if ((m % 2) == 0) { + if ((m & 1) == 0) { hx_plot_assistant(grid, size, x, (size - 1)); } hx_plot_assistant(grid, size, x, 0); @@ -1028,19 +1066,25 @@ static void hx_setup_grid(unsigned char* grid, int size, int version) { } /* Calculate error correction codes */ -static void hx_add_ecc(unsigned char fullstream[], unsigned char datastream[], int data_codewords, int version, int ecc_level) { +static void hx_add_ecc(unsigned char fullstream[], const unsigned char datastream[], const int data_codewords, + const int version, const int ecc_level) { unsigned char data_block[180]; unsigned char ecc_block[36]; int i, j, block; int input_position = -1; int output_position = -1; int table_d1_pos = ((version - 1) * 36) + ((ecc_level - 1) * 9); + rs_t rs; + + rs_init_gf(&rs, 0x163); // x^8 + x^6 + x^5 + x + 1 = 0 for (i = 0; i < 3; i++) { int batch_size = hx_table_d1[table_d1_pos + (3 * i)]; int data_length = hx_table_d1[table_d1_pos + (3 * i) + 1]; int ecc_length = hx_table_d1[table_d1_pos + (3 * i) + 2]; + rs_init_code(&rs, ecc_length, 1); + for (block = 0; block < batch_size; block++) { for (j = 0; j < data_length; j++) { input_position++; @@ -1049,10 +1093,7 @@ static void hx_add_ecc(unsigned char fullstream[], unsigned char datastream[], i fullstream[output_position] = data_block[j]; } - rs_init_gf(0x163); // x^8 + x^6 + x^5 + x + 1 = 0 - rs_init_code(ecc_length, 1); - rs_encode(data_length, data_block, ecc_block); - rs_free(); + rs_encode(&rs, data_length, data_block, ecc_block); for (j = 0; j < ecc_length; j++) { output_position++; @@ -1062,8 +1103,74 @@ static void hx_add_ecc(unsigned char fullstream[], unsigned char datastream[], i } } +static void hx_set_function_info(unsigned char *grid, const int size, const int version, const int ecc_level, + const int bitmask, const int debug) { + int i, j; + char function_information[34]; + unsigned char fi_cw[3] = {0}; + unsigned char fi_ecc[4]; + int bp = 0; + rs_t rs; + + /* Form function information string */ + + bp = bin_append_posn(version + 20, 8, function_information, bp); + bp = bin_append_posn(ecc_level - 1, 2, function_information, bp); + bp = bin_append_posn(bitmask, 2, function_information, bp); + + for (i = 0; i < 3; i++) { + for (j = 0; j < 4; j++) { + if (function_information[(i * 4) + j] == '1') { + fi_cw[i] += (0x08 >> j); + } + } + } + + rs_init_gf(&rs, 0x13); + rs_init_code(&rs, 4, 1); + rs_encode(&rs, 3, fi_cw, fi_ecc); + + for (i = 3; i >= 0; i--) { + bp = bin_append_posn(fi_ecc[i], 4, function_information, bp); + } + + /* This alternating filler pattern at end not mentioned in ISO/IEC 20830 (draft 2019-10-10) and does not appear + * in Figure 1 or the figures in Annex K but does appear in Figure 2 and Figures 4-9 */ + for (i = 28; i < 34; i++) { + if (i & 1) { + function_information[i] = '1'; + } else { + function_information[i] = '0'; + } + } + + if (debug & ZINT_DEBUG_PRINT) { + printf("Version: %d, ECC: %d, Mask: %d, Structural Info: %.34s\n", version, ecc_level, bitmask, function_information); + } + + /* Add function information to symbol */ + for (i = 0; i < 9; i++) { + if (function_information[i] == '1') { + grid[(8 * size) + i] = 0x01; + grid[((size - 8 - 1) * size) + (size - i - 1)] = 0x01; + } + if (function_information[i + 8] == '1') { + grid[((8 - i) * size) + 8] = 0x01; + grid[((size - 8 - 1 + i) * size) + (size - 8 - 1)] = 0x01; + } + if (function_information[i + 17] == '1') { + grid[(i * size) + (size - 1 - 8)] = 0x01; + grid[((size - 1 - i) * size) + 8] = 0x01; + } + if (function_information[i + 25] == '1') { + grid[(8 * size) + (size - 1 - 8 + i)] = 0x01; + grid[((size - 1 - 8) * size) + (8 - i)] = 0x01; + } + } +} + /* Rearrange data in batches of 13 codewords (section 5.8.2) */ -static void make_picket_fence(unsigned char fullstream[], unsigned char picket_fence[], int streamsize) { +static void make_picket_fence(const unsigned char fullstream[], unsigned char picket_fence[], const int streamsize) { int i, start; int output_position = 0; @@ -1078,128 +1185,98 @@ static void make_picket_fence(unsigned char fullstream[], unsigned char picket_f } /* Evaluate a bitmask according to table 9 */ -static int hx_evaluate(unsigned char *eval, int size, int pattern) { - int x, y, block, weight; +static int hx_evaluate(const unsigned char *local, const int size) { + static const unsigned char h1010111[7] = { 1, 0, 1, 0, 1, 1, 1 }; + static const unsigned char h1110101[7] = { 1, 1, 1, 0, 1, 0, 1 }; + + int x, y, r, block; int result = 0; - char state; - int p; + int state; int a, b, afterCount, beforeCount; -#ifndef _MSC_VER - char local[size * size]; -#else - char* local = (char *) _alloca((size * size) * sizeof (char)); -#endif - /* all four bitmask variants have been encoded in the 4 bits of the bytes - * that make up the grid array. select them for evaluation according to the - * desired pattern.*/ - for (x = 0; x < size; x++) { - for (y = 0; y < size; y++) { - if (eval[(y * size) + x] & 0xf0) { - local[(y * size) + x] = 0; - } else if ((eval[(y * size) + x] & (0x01 << pattern)) != 0) { - local[(y * size) + x] = '1'; - } else { - local[(y * size) + x] = '0'; - } - } - } - - /* Test 1: 1:1:1:1:3 or 3:1:1:1:1 ratio pattern in row/column */ + /* Test 1: 1:1:1:1:3 or 3:1:1:1:1 ratio pattern in row/column */ /* Vertical */ for (x = 0; x < size; x++) { - for (y = 0; y < (size - 7); y++) { - if (local[(y * size) + x] == 0) { - continue; - } - p = 0; - for (weight = 0; weight < 7; weight++) { - if (local[((y + weight) * size) + x] == '1') { - p += (0x40 >> weight); - } - } - if ((p == 0x57) || (p == 0x75)) { + for (y = 0; y <= (size - 7); y++) { + if (local[y * size + x] && local[(y + 1) * size + x] != local[(y + 5) * size + x] && + local[(y + 2) * size + x] && !local[(y + 3) * size + x] && + local[(y + 4) * size + x] && local[(y + 6) * size + x]) { /* Pattern found, check before and after */ beforeCount = 0; - for (b = (y - 3); b < y; b++) { - if (b < 0) { - beforeCount++; - } else { - if (local[(b * size) + x] == '0') { - beforeCount++; - } else { - break; - } + for (b = (y - 1); b >= (y - 3); b--) { + if (b < 0) { /* Count < edge as whitespace */ + beforeCount = 3; + break; } - } - - afterCount = 0; - for (a = (y + 7); a <= (y + 9); a++) { - if (a >= size) { - afterCount++; - } else { - if (local[(a * size) + x] == '0') { - afterCount++; - } else { - break; - } + if (local[(b * size) + x]) { + break; } + beforeCount++; } - - if ((beforeCount == 3) || (afterCount == 3)) { - /* Pattern is preceeded or followed by light area - 3 modules wide */ + if (beforeCount == 3) { + /* Pattern is preceded by light area 3 modules wide */ result += 50; + } else { + afterCount = 0; + for (a = (y + 7); a <= (y + 9); a++) { + if (a >= size) { /* Count > edge as whitespace */ + afterCount = 3; + break; + } + if (local[(a * size) + x]) { + break; + } + afterCount++; + } + if (afterCount == 3) { + /* Pattern is followed by light area 3 modules wide */ + result += 50; + } } + y++; /* Skip to next possible match */ } } } /* Horizontal */ for (y = 0; y < size; y++) { - for (x = 0; x < (size - 7); x++) { - if (local[(y * size) + x] == 0) { - continue; - } - p = 0; - for (weight = 0; weight < 7; weight++) { - if (local[(y * size) + x + weight] == '1') { - p += (0x40 >> weight); - } - } - if ((p == 0x57) || (p == 0x75)) { + r = y * size; + for (x = 0; x <= (size - 7); x++) { + if (memcmp(local + r + x, h1010111, 7) == 0 || memcmp(local + r + x, h1110101, 7) == 0) { /* Pattern found, check before and after */ beforeCount = 0; - for (b = (x - 3); b < x; b++) { - if (b < 0) { - beforeCount++; - } else { - if (local[(y * size) + b] == '0') { - beforeCount++; - } else { - break; - } + for (b = (x - 1); b >= (x - 3); b--) { + if (b < 0) { /* Count < edge as whitespace */ + beforeCount = 3; + break; } + if (local[r + b]) { + break; + } + beforeCount++; } - afterCount = 0; - for (a = (x + 7); a <= (x + 9); a++) { - if (a >= size) { - afterCount++; - } else { - if (local[(y * size) + a] == '0') { - afterCount++; - } else { - break; - } - } - } - - if ((beforeCount == 3) || (afterCount == 3)) { - /* Pattern is preceeded or followed by light area - 3 modules wide */ + if (beforeCount == 3) { + /* Pattern is preceded by light area 3 modules wide */ result += 50; + } else { + afterCount = 0; + for (a = (x + 7); a <= (x + 9); a++) { + if (a >= size) { /* Count > edge as whitespace */ + afterCount = 3; + break; + } + if (local[r + a]) { + break; + } + afterCount++; + } + if (afterCount == 3) { + /* Pattern is followed by light area 3 modules wide */ + result += 50; + } } + x++; /* Skip to next possible match */ } } } @@ -1216,52 +1293,39 @@ static int hx_evaluate(unsigned char *eval, int size, int pattern) { block = 0; state = 0; for (y = 0; y < size; y++) { - if (local[(y * size) + x] == 0) { - if (block >= 3) { - result += (3 + block) * 4; - } - block = 0; - state = 0; - } else if (local[(y * size) + x] == state || state == 0) { + if (local[(y * size) + x] == state) { block++; - state = local[(y * size) + x]; } else { if (block >= 3) { - result += (3 + block) * 4; + result += block * 4; } block = 1; state = local[(y * size) + x]; } } if (block >= 3) { - result += (3 + block) * 4; + result += block * 4; } } /* Horizontal */ for (y = 0; y < size; y++) { - state = local[y * size]; + r = y * size; block = 0; + state = 0; for (x = 0; x < size; x++) { - if (local[(y * size) + x] == 0) { - if (block >= 3) { - result += (3 + block) * 4; - } - block = 0; - state = 0; - } else if (local[(y * size) + x] == state || state == 0) { + if (local[r + x] == state) { block++; - state = local[(y * size) + x]; } else { if (block >= 3) { - result += (3 + block) * 4; + result += block * 4; } block = 1; - state = local[(y * size) + x]; + state = local[r + x]; } } if (block >= 3) { - result += (3 + block) * 4; + result += block * 4; } } @@ -1269,128 +1333,128 @@ static int hx_evaluate(unsigned char *eval, int size, int pattern) { } /* Apply the four possible bitmasks for evaluation */ -/* TODO: Haven't been able to replicate (or even get close to) the penalty scores in ISO/IEC 20830 (draft 2019-10-10) Annex K examples */ -static int hx_apply_bitmask(unsigned char *grid, int size) { +/* TODO: Haven't been able to replicate (or even get close to) the penalty scores in ISO/IEC 20830 + * (draft 2019-10-10) Annex K examples; however they don't use alternating filler pattern on structural info */ +static void hx_apply_bitmask(unsigned char *grid, const int size, const int version, const int ecc_level, + const int user_mask, const int debug) { int x, y; - int i, j; - int pattern, penalty[4]; - int best_pattern, best_val; + int i, j, r, k; + int pattern, penalty[4] = {0}; + int best_pattern; int bit; - unsigned char p; + int size_squared = size * size; #ifndef _MSC_VER - unsigned char mask[(unsigned int)(size * size)]; /* Cast to suppress gcc -Walloc-size-larger-than */ - unsigned char eval[(unsigned int)(size * size)]; + unsigned char mask[size_squared]; + unsigned char local[size_squared]; #else - unsigned char* mask = (unsigned char *) _alloca((size * size) * sizeof (unsigned char)); - unsigned char* eval = (unsigned char *) _alloca((size * size) * sizeof (unsigned char)); + unsigned char *mask = (unsigned char *) _alloca(size_squared * sizeof(unsigned char)); + unsigned char *local = (unsigned char *) _alloca(size_squared * sizeof(unsigned char)); #endif /* Perform data masking */ - for (x = 0; x < size; x++) { - for (y = 0; y < size; y++) { - mask[(y * size) + x] = 0x00; - j = x + 1; - i = y + 1; + memset(mask, 0, size_squared); + for (y = 0; y < size; y++) { + r = y * size; + for (x = 0; x < size; x++) { + k = r + x; - if (!(grid[(y * size) + x] & 0xf0)) { - if ((i + j) % 2 == 0) { - mask[(y * size) + x] += 0x02; + if (!(grid[k] & 0xf0)) { + j = x + 1; + i = y + 1; + if (((i + j) & 1) == 0) { + mask[k] |= 0x02; } - if ((((i + j) % 3) + (j % 3)) % 2 == 0) { - mask[(y * size) + x] += 0x04; + if (((((i + j) % 3) + (j % 3)) & 1) == 0) { + mask[k] |= 0x04; } - if (((i % j) + (j % i) + (i % 3) + (j % 3)) % 2 == 0) { - mask[(y * size) + x] += 0x08; + if ((((i % j) + (j % i) + (i % 3) + (j % 3)) & 1) == 0) { + mask[k] |= 0x08; } } } } - // apply data masks to grid, result in eval - for (x = 0; x < size; x++) { - for (y = 0; y < size; y++) { - if (grid[(y * size) + x] & 0xf0) { - p = 0xf0; - } else if (grid[(y * size) + x] & 0x01) { - p = 0x0f; - } else { - p = 0x00; + if (user_mask) { + best_pattern = user_mask - 1; + } else { + // apply data masks to grid, result in local + + /* Do null pattern 00 separately first */ + pattern = 0; + for (k = 0; k < size_squared; k++) { + local[k] = grid[k] & 0x0f; + } + /* Set the Structural Info */ + hx_set_function_info(local, size, version, ecc_level, pattern, 0 /*debug*/); + + /* Evaluate result */ + penalty[pattern] = hx_evaluate(local, size); + + best_pattern = 0; + for (pattern = 1; pattern < 4; pattern++) { + bit = 1 << pattern; + for (k = 0; k < size_squared; k++) { + if (mask[k] & bit) { + local[k] = grid[k] ^ 0x01; + } else { + local[k] = grid[k] & 0x0f; + } } + /* Set the Structural Info */ + hx_set_function_info(local, size, version, ecc_level, pattern, 0 /*debug*/); - eval[(y * size) + x] = mask[(y * size) + x] ^ p; + /* Evaluate result */ + penalty[pattern] = hx_evaluate(local, size); + if (penalty[pattern] < penalty[best_pattern]) { + best_pattern = pattern; + } } } - /* Evaluate result */ - for (pattern = 0; pattern < 4; pattern++) { - penalty[pattern] = hx_evaluate(eval, size, pattern); - } - - best_pattern = 0; - best_val = penalty[0]; - for (pattern = 1; pattern < 4; pattern++) { - if (penalty[pattern] < best_val) { - best_pattern = pattern; - best_val = penalty[pattern]; + if (debug & ZINT_DEBUG_PRINT) { + printf("Mask: %d (%s)", best_pattern, user_mask ? "specified" : "automatic"); + if (!user_mask) { + for (pattern = 0; pattern < 4; pattern++) printf(" %d:%d", pattern, penalty[pattern]); } + printf("\n"); } /* Apply mask */ - for (x = 0; x < size; x++) { - for (y = 0; y < size; y++) { - bit = 0; - switch (best_pattern) { - case 0: if (mask[(y * size) + x] & 0x01) { - bit = 1; - } - break; - case 1: if (mask[(y * size) + x] & 0x02) { - bit = 1; - } - break; - case 2: if (mask[(y * size) + x] & 0x04) { - bit = 1; - } - break; - case 3: if (mask[(y * size) + x] & 0x08) { - bit = 1; - } - break; - } - if (bit == 1) { - if (grid[(y * size) + x] & 0x01) { - grid[(y * size) + x] = 0x00; - } else { - grid[(y * size) + x] = 0x01; + if (best_pattern) { /* If not null mask */ + if (!user_mask && best_pattern == 3) { /* Reuse last */ + memcpy(grid, local, size_squared); + } else { + bit = 1 << best_pattern; + for (k = 0; k < size_squared; k++) { + if (mask[k] & bit) { + grid[k] ^= 0x01; } } } } - - return best_pattern; + /* Set the Structural Info */ + hx_set_function_info(grid, size, version, ecc_level, best_pattern, debug); } /* Han Xin Code - main */ -INTERNAL int han_xin(struct zint_symbol *symbol, const unsigned char source[], size_t length) { +INTERNAL int han_xin(struct zint_symbol *symbol, unsigned char source[], int length) { int est_binlen; int ecc_level = symbol->option_1; - int i, j, version; + int i, j, j_max, version; int full_multibyte; + int user_mask; int data_codewords = 0, size; + int size_squared; int codewords; - int bitmask; int bin_len; - char function_information[36]; - unsigned char fi_cw[3] = {0, 0, 0}; - unsigned char fi_ecc[4]; #ifndef _MSC_VER unsigned int gbdata[(length + 1) * 2]; - char mode[length + 1]; + char mode[length]; #else unsigned int* gbdata = (unsigned int *) _alloca(((length + 1) * 2) * sizeof (unsigned int)); - char* mode = (char *) _alloca((length + 1) * sizeof (char)); + char *mode = (char *) _alloca(length); char* binary; unsigned char *datastream; unsigned char *fullstream; @@ -1398,7 +1462,12 @@ INTERNAL int han_xin(struct zint_symbol *symbol, const unsigned char source[], s unsigned char *grid; #endif - full_multibyte = symbol->option_3 == ZINT_FULL_MULTIBYTE; /* If set use Hanzi mode in DATA_MODE or for single-byte Latin */ + /* If ZINT_FULL_MULTIBYTE set use Hanzi mode in DATA_MODE or for single-byte Latin */ + full_multibyte = (symbol->option_3 & 0xFF) == ZINT_FULL_MULTIBYTE; + user_mask = (symbol->option_3 >> 8) & 0x0F; /* User mask is pattern + 1, so >= 1 and <= 4 */ + if (user_mask > 4) { + user_mask = 0; /* Ignore */ + } if ((symbol->input_mode & 0x07) == DATA_MODE) { gb18030_cpy(source, &length, gbdata, full_multibyte); @@ -1406,7 +1475,8 @@ INTERNAL int han_xin(struct zint_symbol *symbol, const unsigned char source[], s int done = 0; if (symbol->eci != 29) { /* Unless ECI 29 (GB) */ /* Try single byte (Latin) conversion first */ - int error_number = gb18030_utf8tosb(symbol->eci && symbol->eci <= 899 ? symbol->eci : 3, source, &length, gbdata, full_multibyte); + int error_number = gb18030_utf8tosb(symbol->eci && symbol->eci <= 899 ? symbol->eci : 3, source, &length, + gbdata, full_multibyte); if (error_number == 0) { done = 1; } else if (symbol->eci && symbol->eci <= 899) { @@ -1432,16 +1502,14 @@ INTERNAL int han_xin(struct zint_symbol *symbol, const unsigned char source[], s #else binary = (char *) _alloca((est_binlen + 1) * sizeof (char)); #endif - memset(binary, 0, (est_binlen + 1) * sizeof (char)); if ((ecc_level <= 0) || (ecc_level >= 5)) { ecc_level = 1; } - calculate_binary(binary, mode, gbdata, length, symbol->eci, symbol->debug); - bin_len = strlen(binary); - codewords = bin_len / 8; - if (bin_len % 8 != 0) { + calculate_binary(binary, mode, gbdata, length, symbol->eci, &bin_len, symbol->debug); + codewords = bin_len >> 3; + if (bin_len & 0x07) { codewords++; } @@ -1516,26 +1584,25 @@ INTERNAL int han_xin(struct zint_symbol *symbol, const unsigned char source[], s } size = (version * 2) + 21; + size_squared = size * size; #ifndef _MSC_VER unsigned char datastream[data_codewords]; unsigned char fullstream[hx_total_codewords[version - 1]]; unsigned char picket_fence[hx_total_codewords[version - 1]]; - unsigned char grid[size * size]; + unsigned char grid[size_squared]; #else datastream = (unsigned char *) _alloca((data_codewords) * sizeof (unsigned char)); fullstream = (unsigned char *) _alloca((hx_total_codewords[version - 1]) * sizeof (unsigned char)); picket_fence = (unsigned char *) _alloca((hx_total_codewords[version - 1]) * sizeof (unsigned char)); - grid = (unsigned char *) _alloca((size * size) * sizeof (unsigned char)); + grid = (unsigned char *) _alloca(size_squared * sizeof(unsigned char)); #endif - for (i = 0; i < data_codewords; i++) { - datastream[i] = 0; - } + memset(datastream, 0, data_codewords); for (i = 0; i < bin_len; i++) { if (binary[i] == '1') { - datastream[i / 8] += 0x80 >> (i % 8); + datastream[i >> 3] |= 0x80 >> (i & 0x07); } } @@ -1559,102 +1626,29 @@ INTERNAL int han_xin(struct zint_symbol *symbol, const unsigned char source[], s /* Populate grid */ j = 0; - for (i = 0; i < (size * size); i++) { + j_max = hx_total_codewords[version - 1] * 8; + for (i = 0; i < size_squared; i++) { if (grid[i] == 0x00) { - if (j < (hx_total_codewords[version - 1] * 8)) { - if (picket_fence[(j / 8)] & (0x80 >> (j % 8))) { + if (j < j_max) { + if (picket_fence[(j >> 3)] & (0x80 >> (j & 0x07))) { grid[i] = 0x01; } j++; - } - } - } - - bitmask = hx_apply_bitmask(grid, size); - - /* Form function information string */ - for (i = 0; i < 34; i++) { - if (i % 2) { - function_information[i] = '1'; - } else { - function_information[i] = '0'; - } - } - function_information[34] = '\0'; - - for (i = 0; i < 8; i++) { - if ((version + 20) & (0x80 >> i)) { - function_information[i] = '1'; - } else { - function_information[i] = '0'; - } - } - - for (i = 0; i < 2; i++) { - if ((ecc_level - 1) & (0x02 >> i)) { - function_information[i + 8] = '1'; - } else { - function_information[i + 8] = '0'; - } - } - - for (i = 0; i < 2; i++) { - if (bitmask & (0x02 >> i)) { - function_information[i + 10] = '1'; - } else { - function_information[i + 10] = '0'; - } - } - - for (i = 0; i < 3; i++) { - for (j = 0; j < 4; j++) { - if (function_information[(i * 4) + j] == '1') { - fi_cw[i] += (0x08 >> j); - } - } - } - - rs_init_gf(0x13); - rs_init_code(4, 1); - rs_encode(3, fi_cw, fi_ecc); - rs_free(); - - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - if (fi_ecc[3 - i] & (0x08 >> j)) { - function_information[(i * 4) + j + 12] = '1'; } else { - function_information[(i * 4) + j + 12] = '0'; + break; } } } - /* Add function information to symbol */ - for (i = 0; i < 9; i++) { - if (function_information[i] == '1') { - grid[(8 * size) + i] = 0x01; - grid[((size - 8 - 1) * size) + (size - i - 1)] = 0x01; - } - if (function_information[i + 8] == '1') { - grid[((8 - i) * size) + 8] = 0x01; - grid[((size - 8 - 1 + i) * size) + (size - 8 - 1)] = 0x01; - } - if (function_information[i + 17] == '1') { - grid[(i * size) + (size - 1 - 8)] = 0x01; - grid[((size - 1 - i) * size) + 8] = 0x01; - } - if (function_information[i + 25] == '1') { - grid[(8 * size) + (size - 1 - 8 + i)] = 0x01; - grid[((size - 1 - 8) * size) + (8 - i)] = 0x01; - } - } + hx_apply_bitmask(grid, size, version, ecc_level, user_mask, symbol->debug); symbol->width = size; symbol->rows = size; for (i = 0; i < size; i++) { + int r = i * size; for (j = 0; j < size; j++) { - if (grid[(i * size) + j] & 0x01) { + if (grid[r + j] & 0x01) { set_module(symbol, i, j); } } diff --git a/backend/library.c b/backend/library.c index 4f68bf0a..86e54c2d 100644 --- a/backend/library.c +++ b/backend/library.c @@ -115,8 +115,8 @@ void ZBarcode_Delete(struct zint_symbol *symbol) { free(symbol); } -INTERNAL int get_best_eci(unsigned char source[], size_t length); /* Calculate suitable ECI mode */ -INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[], size_t *length); /* Convert Unicode to other encodings */ +INTERNAL int get_best_eci(unsigned char source[], int length); /* Calculate suitable ECI mode */ +INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[], int *length); /* Convert Unicode to other encodings */ INTERNAL int eanx(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN system barcodes */ INTERNAL int c39(struct zint_symbol *symbol, unsigned char source[], const size_t length); /* Code 3 from 9 (or Code 39) */ @@ -157,29 +157,29 @@ INTERNAL int rsslimited(struct zint_symbol *symbol, unsigned char source[], int INTERNAL int rssexpanded(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS Expanded */ INTERNAL int composite(struct zint_symbol *symbol, unsigned char source[], int length); /* Composite Symbology */ INTERNAL int kix_code(struct zint_symbol *symbol, unsigned char source[], int length); /* TNT KIX Code */ -INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], const size_t length); /* Aztec Code */ +INTERNAL int aztec(struct zint_symbol *symbol, unsigned char source[], int length); /* Aztec Code */ INTERNAL int code32(struct zint_symbol *symbol, unsigned char source[], int length); /* Italian Pharmacode */ INTERNAL int daft_code(struct zint_symbol *symbol, unsigned char source[], int length); /* DAFT Code */ INTERNAL int ean_14(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN-14 */ INTERNAL int nve_18(struct zint_symbol *symbol, unsigned char source[], int length); /* NVE-18 */ -INTERNAL int microqr(struct zint_symbol *symbol, const unsigned char source[], size_t length); /* Micro QR Code */ +INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int length); /* Micro QR Code */ INTERNAL int aztec_runes(struct zint_symbol *symbol, unsigned char source[], int length); /* Aztec Runes */ INTERNAL int korea_post(struct zint_symbol *symbol, unsigned char source[], int length); /* Korea Post */ INTERNAL int japan_post(struct zint_symbol *symbol, unsigned char source[], int length); /* Japanese Post */ INTERNAL int code_49(struct zint_symbol *symbol, unsigned char source[], const int length); /* Code 49 */ INTERNAL int channel_code(struct zint_symbol *symbol, unsigned char source[], int length); /* Channel Code */ INTERNAL int code_one(struct zint_symbol *symbol, unsigned char source[], int length); /* Code One */ -INTERNAL int grid_matrix(struct zint_symbol *symbol, const unsigned char source[], size_t length); /* Grid Matrix */ -INTERNAL int han_xin(struct zint_symbol * symbol, const unsigned char source[], size_t length); /* Han Xin */ +INTERNAL int grid_matrix(struct zint_symbol *symbol, unsigned char source[], int length); /* Grid Matrix */ +INTERNAL int han_xin(struct zint_symbol * symbol, unsigned char source[], int length); /* Han Xin */ INTERNAL int dotcode(struct zint_symbol * symbol, const unsigned char source[], int length); /* DotCode */ INTERNAL int codablock(struct zint_symbol * symbol, const unsigned char source[], const size_t length); /* Codablock */ -INTERNAL int upnqr(struct zint_symbol *symbol, const unsigned char source[], size_t length); /* UPNQR */ -INTERNAL int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t length); /* QR Code */ +INTERNAL int upnqr(struct zint_symbol *symbol, unsigned char source[], int length); /* UPNQR */ +INTERNAL int qr_code(struct zint_symbol *symbol, unsigned char source[], int length); /* QR Code */ INTERNAL int dmatrix(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* Data Matrix (IEC16022) */ INTERNAL int vin(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* VIN Code (Vehicle Identification Number) */ INTERNAL int mailmark(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* Royal Mail 4-state Mailmark */ INTERNAL int ultracode(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* Ultracode */ -INTERNAL int rmqr(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* rMQR */ +INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int in_length); /* rMQR */ INTERNAL int dpd_parcel(struct zint_symbol *symbol, unsigned char source[], int length); /* DPD Code */ INTERNAL int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to PNG/BMP/PCX */ @@ -261,8 +261,8 @@ static int dump_plot(struct zint_symbol *symbol) { } /* Process health industry bar code data */ -static int hibc(struct zint_symbol *symbol, unsigned char source[], size_t length) { - size_t i; +static int hibc(struct zint_symbol *symbol, unsigned char source[], int length) { + int i; int counter, error_number; char to_process[113], check_digit; @@ -669,6 +669,15 @@ unsigned int ZBarcode_Cap(int symbol_id, unsigned int cap_flag) { break; } } + if (cap_flag & ZINT_CAP_MASK) { + switch (symbol_id) { + case BARCODE_QRCODE: + case BARCODE_MICROQR: + case BARCODE_HANXIN: + result |= ZINT_CAP_MASK; + break; + } + } return result; } @@ -700,7 +709,7 @@ int ZBarcode_ValidID(int symbol_id) { return ids[symbol_id] != 0; } -static int reduced_charset(struct zint_symbol *symbol, unsigned char *source, size_t in_length); +static int reduced_charset(struct zint_symbol *symbol, unsigned char *source, int in_length); static int extended_or_reduced_charset(struct zint_symbol *symbol, unsigned char *source, const int length) { int error_number = 0; @@ -726,7 +735,7 @@ static int extended_or_reduced_charset(struct zint_symbol *symbol, unsigned char return error_number; } -static int reduced_charset(struct zint_symbol *symbol, unsigned char *source, size_t in_length) { +static int reduced_charset(struct zint_symbol *symbol, unsigned char *source, int in_length) { /* These are the "norm" standards which only support Latin-1 at most, though a few support ECI */ int error_number = 0; unsigned char *preprocessed = source; diff --git a/backend/mailmark.c b/backend/mailmark.c index 6e0588f0..f498b412 100644 --- a/backend/mailmark.c +++ b/backend/mailmark.c @@ -144,6 +144,7 @@ INTERNAL int mailmark(struct zint_symbol *symbol, const unsigned char source[], int check_count; int i, j, len; int length = (int) in_length; + rs_t rs; if (length > 26) { strcpy(symbol->errtxt, "580: Input too long"); @@ -402,10 +403,9 @@ INTERNAL int mailmark(struct zint_symbol *symbol, const unsigned char source[], } // Generation of Reed-Solomon Check Numbers - rs_init_gf(0x25); - rs_init_code(check_count, 1); - rs_encode((data_top + 1), data, check); - rs_free(); + rs_init_gf(&rs, 0x25); + rs_init_code(&rs, check_count, 1); + rs_encode(&rs, (data_top + 1), data, check); // Append check digits to data for (i = 1; i <= check_count; i++) { diff --git a/backend/maxicode.c b/backend/maxicode.c index b1f2db22..415041fc 100644 --- a/backend/maxicode.c +++ b/backend/maxicode.c @@ -43,18 +43,18 @@ static void maxi_do_primary_check(int maxi_codeword[144]) { int j; int datalen = 10; int ecclen = 10; + rs_t rs; - rs_init_gf(0x43); - rs_init_code(ecclen, 1); + rs_init_gf(&rs, 0x43); + rs_init_code(&rs, ecclen, 1); for (j = 0; j < datalen; j += 1) data[j] = maxi_codeword[j]; - rs_encode(datalen, data, results); + rs_encode(&rs, datalen, data, results); for (j = 0; j < ecclen; j += 1) maxi_codeword[ datalen + j] = results[ecclen - 1 - j]; - rs_free(); } /* Handles error correction of odd characters in secondary */ @@ -63,9 +63,10 @@ static void maxi_do_secondary_chk_odd(int maxi_codeword[144], int ecclen) { unsigned char results[30]; int j; int datalen = 68; + rs_t rs; - rs_init_gf(0x43); - rs_init_code(ecclen, 1); + rs_init_gf(&rs, 0x43); + rs_init_code(&rs, ecclen, 1); if (ecclen == 20) datalen = 84; @@ -74,11 +75,10 @@ static void maxi_do_secondary_chk_odd(int maxi_codeword[144], int ecclen) { if (j & 1) // odd data[(j - 1) / 2] = maxi_codeword[j + 20]; - rs_encode(datalen / 2, data, results); + rs_encode(&rs, datalen / 2, data, results); for (j = 0; j < (ecclen); j += 1) maxi_codeword[ datalen + (2 * j) + 1 + 20 ] = results[ecclen - 1 - j]; - rs_free(); } /* Handles error correction of even characters in secondary */ @@ -87,22 +87,22 @@ static void maxi_do_secondary_chk_even(int maxi_codeword[144], int ecclen) { unsigned char results[30]; int j; int datalen = 68; + rs_t rs; if (ecclen == 20) datalen = 84; - rs_init_gf(0x43); - rs_init_code(ecclen, 1); + rs_init_gf(&rs, 0x43); + rs_init_code(&rs, ecclen, 1); for (j = 0; j < datalen + 1; j += 1) if (!(j & 1)) // even data[j / 2] = maxi_codeword[j + 20]; - rs_encode(datalen / 2, data, results); + rs_encode(&rs, datalen / 2, data, results); for (j = 0; j < (ecclen); j += 1) maxi_codeword[ datalen + (2 * j) + 20] = results[ecclen - 1 - j]; - rs_free(); } /* Moves everything up so that a shift or latch can be inserted */ diff --git a/backend/png.c b/backend/png.c index bfe1a9b8..0552cfca 100644 --- a/backend/png.c +++ b/backend/png.c @@ -196,10 +196,10 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) /* Pixel Plotting */ incr = use_alpha ? 4 : 3; for (row = 0; row < symbol->bitmap_height; row++) { - int p = symbol->bitmap_width * row; + unsigned char *pb = pixelbuf + symbol->bitmap_width * row; image_data = outdata; - for (column = 0; column < symbol->bitmap_width; column++, p++, image_data += incr) { - memcpy(image_data, map[pixelbuf[p]], incr); + for (column = 0; column < symbol->bitmap_width; column++, pb++, image_data += incr) { + memcpy(image_data, map[*pb], incr); } /* write row contents to file */ png_write_row(png_ptr, outdata); diff --git a/backend/qr.c b/backend/qr.c index 6c67a135..68bc633a 100644 --- a/backend/qr.c +++ b/backend/qr.c @@ -30,6 +30,7 @@ */ /* vim: set ts=4 sw=4 et : */ +#include #ifdef _MSC_VER #include #endif @@ -40,7 +41,8 @@ #include "reedsol.h" #include -INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[], size_t *length); /* Convert Unicode to other encodings */ +/* Convert Unicode to other encodings */ +INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[], int *length); /* Returns true if input glyph is in the Alphanumeric set */ static int is_alpha(const unsigned int glyph, const int gs1) { @@ -74,18 +76,20 @@ static int is_alpha(const unsigned int glyph, const int gs1) { /* Bits multiplied by this for costs, so as to be whole integer divisible by 2 and 3 */ #define QR_MULT 6 -/* Whether in numeric or not. If in numeric, *p_end is set to position after numeric, and *p_cost is set to per-numeric cost */ -static int in_numeric(const unsigned int jisdata[], const size_t length, const unsigned int posn, unsigned int* p_end, unsigned int* p_cost) { - unsigned int i, digit_cnt; +/* Whether in numeric or not. If in numeric, *p_end is set to position after numeric, and *p_cost is set to + * per-numeric cost */ +static int in_numeric(const unsigned int jisdata[], const int length, const int in_posn, + unsigned int *p_end, unsigned int *p_cost) { + int i, digit_cnt; - if (posn < *p_end) { + if (in_posn < (int) *p_end) { return 1; } /* Attempt to calculate the average 'cost' of using numeric mode in number of bits (times QR_MULT) */ - for (i = posn; i < length && i < posn + 4 && jisdata[i] >= '0' && jisdata[i] <= '9'; i++); + for (i = in_posn; i < length && i < in_posn + 4 && jisdata[i] >= '0' && jisdata[i] <= '9'; i++); - digit_cnt = i - posn; + digit_cnt = i - in_posn; if (digit_cnt == 0) { *p_end = 0; @@ -96,14 +100,16 @@ static int in_numeric(const unsigned int jisdata[], const size_t length, const u return 1; } -/* Whether in alpha or not. If in alpha, *p_end is set to position after alpha, and *p_cost is set to per-alpha cost. For GS1, *p_pcent set if 2nd char percent */ -static int in_alpha(const unsigned int jisdata[], const size_t length, const unsigned int posn, unsigned int* p_end, unsigned int* p_cost, unsigned int* p_pcent, unsigned int gs1) { +/* Whether in alpha or not. If in alpha, *p_end is set to position after alpha, and *p_cost is set to per-alpha cost. + * For GS1, *p_pcent set if 2nd char percent */ +static int in_alpha(const unsigned int jisdata[], const int length, const int in_posn, + unsigned int *p_end, unsigned int *p_cost, unsigned int *p_pcent, unsigned int gs1) { int two_alphas; - if (posn < *p_end) { + if (in_posn < (int) *p_end) { if (gs1 && *p_pcent) { /* Previous 2nd char was a percent, so allow for second half of doubled-up percent here */ - two_alphas = posn < length - 1 && is_alpha(jisdata[posn + 1], gs1); + two_alphas = in_posn < length - 1 && is_alpha(jisdata[in_posn + 1], gs1); *p_cost = two_alphas ? 33 /* (11 / 2) * QR_MULT */ : 36 /* 6 * QR_MULT */; *p_pcent = 0; } @@ -111,24 +117,24 @@ static int in_alpha(const unsigned int jisdata[], const size_t length, const uns } /* Attempt to calculate the average 'cost' of using alphanumeric mode in number of bits (times QR_MULT) */ - if (!is_alpha(jisdata[posn], gs1)) { + if (!is_alpha(jisdata[in_posn], gs1)) { *p_end = 0; *p_pcent = 0; return 0; } - if (gs1 && jisdata[posn] == '%') { /* Must double-up so counts as 2 chars */ - *p_end = posn + 1; + if (gs1 && jisdata[in_posn] == '%') { /* Must double-up so counts as 2 chars */ + *p_end = in_posn + 1; *p_cost = 66; /* 11 * QR_MULT */ *p_pcent = 0; return 1; } - two_alphas = posn < length - 1 && is_alpha(jisdata[posn + 1], gs1); + two_alphas = in_posn < length - 1 && is_alpha(jisdata[in_posn + 1], gs1); - *p_end = two_alphas ? posn + 2 : posn + 1; + *p_end = two_alphas ? in_posn + 2 : in_posn + 1; *p_cost = two_alphas ? 33 /* (11 / 2) * QR_MULT */ : 36 /* 6 * QR_MULT */; - *p_pcent = two_alphas && gs1 && jisdata[posn + 1] == '%'; /* 2nd char is percent */ + *p_pcent = two_alphas && gs1 && jisdata[in_posn + 1] == '%'; /* 2nd char is percent */ return 1; } @@ -144,20 +150,19 @@ static const char mode_types[] = { 'N', 'A', 'B', 'K', '\0' }; /* Must be in sam /* Indexes into state array (0..3 head costs) */ #define QR_VER 4 /* Version */ -#define QR_GS1 5 /* GS1 mode (boolean) */ -#define QR_N_END 6 /* Numeric end index */ -#define QR_N_COST 7 /* Numeric cost */ -#define QR_A_END 8 /* Alpha end index */ -#define QR_A_COST 9 /* Alpha cost */ -#define QR_A_PCENT 10 /* Alpha 2nd char percent (GS1-specific) */ +#define QR_N_END 5 /* Numeric end index */ +#define QR_N_COST 6 /* Numeric cost */ +#define QR_A_END 7 /* Alpha end index */ +#define QR_A_COST 8 /* Alpha cost */ +#define QR_A_PCENT 9 /* Alpha 2nd char percent (GS1-specific) */ /* Costs set to this for invalid MICROQR modes for versions M1 and M2. * 128 is the max number of data bits for M4-L (ISO/IEC 18004:2015 Table 7) */ #define QR_MICROQR_MAX 774 /* (128 + 1) * QR_MULT */ /* Initial mode costs */ -static unsigned int* qr_head_costs(unsigned int state[]) { - static const int head_costs[7][QR_NUM_MODES] = { +static unsigned int *qr_head_costs(unsigned int state[10]) { + static const unsigned int head_costs[7][QR_NUM_MODES] = { /* N A B K */ { (10 + 4) * QR_MULT, (9 + 4) * QR_MULT, (8 + 4) * QR_MULT, (8 + 4) * QR_MULT, }, /* QR */ { (12 + 4) * QR_MULT, (11 + 4) * QR_MULT, (16 + 4) * QR_MULT, (10 + 4) * QR_MULT, }, @@ -170,19 +175,16 @@ static unsigned int* qr_head_costs(unsigned int state[]) { int version; /* Head costs kept in states 0..3 */ - if (state[QR_N] != 0) { /* Numeric non-zero in all configs */ - return state; /* Already set */ - } version = state[QR_VER]; if (version < RMQR_VERSION) { /* QRCODE */ if (version < 10) { - memcpy(state, head_costs, QR_NUM_MODES * sizeof(unsigned int)); + memcpy(state, head_costs[0], QR_NUM_MODES * sizeof(unsigned int)); } else if (version < 27) { - memcpy(state, head_costs + 1, QR_NUM_MODES * sizeof(unsigned int)); + memcpy(state, head_costs[1], QR_NUM_MODES * sizeof(unsigned int)); } else { - memcpy(state, head_costs + 2, QR_NUM_MODES * sizeof(unsigned int)); + memcpy(state, head_costs[2], QR_NUM_MODES * sizeof(unsigned int)); } } else if (version < MICROQR_VERSION) { /* RMQR */ version -= RMQR_VERSION; @@ -191,59 +193,138 @@ static unsigned int* qr_head_costs(unsigned int state[]) { state[QR_B] = (rmqr_byte_cci[version] + 3) * QR_MULT; state[QR_K] = (rmqr_kanji_cci[version] + 3) * QR_MULT; } else { /* MICROQR */ - memcpy(state, head_costs + 3 + (version - MICROQR_VERSION), QR_NUM_MODES * sizeof(unsigned int)); + memcpy(state, head_costs[3 + (version - MICROQR_VERSION)], QR_NUM_MODES * sizeof(unsigned int)); } return state; } -/* Costs of switching modes from k to j */ -static unsigned int qr_switch_cost(unsigned int state[], const int k, const int j) { - (void)k; /* Unused */ - return state[j]; /* Same as head cost */ -} +/* Calculate optimized encoding modes. Adapted from Project Nayuki */ +static void qr_define_mode(char mode[], const unsigned int jisdata[], const int length, const int gs1, + const int version, const int debug_print) { + /* + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + */ + unsigned int state[10] = { + 0 /*N*/, 0 /*A*/, 0 /*B*/, 0 /*K*/, /* Head/switch costs */ + (unsigned int) version, + 0 /*numeric_end*/, 0 /*numeric_cost*/, 0 /*alpha_end*/, 0 /*alpha_cost*/, 0 /*alpha_pcent*/ + }; + int m1, m2; -/* Calculate cost of encoding character */ -static void qr_cur_cost(unsigned int state[], const unsigned int jisdata[], const size_t length, const int i, char* char_modes, unsigned int prev_costs[], unsigned int cur_costs[]) { - int cm_i = i * QR_NUM_MODES, m1, m2; - unsigned int version = state[QR_VER]; - unsigned int gs1 = state[QR_GS1]; - unsigned int* p_numeric_end = &state[QR_N_END]; - unsigned int* p_numeric_cost = &state[QR_N_COST]; - unsigned int* p_alpha_end = &state[QR_A_END]; - unsigned int* p_alpha_cost = &state[QR_A_COST]; - unsigned int* p_alpha_pcent = &state[QR_A_PCENT]; + int i, j, k, cm_i; + unsigned int min_cost; + char cur_mode; + unsigned int prev_costs[QR_NUM_MODES]; + unsigned int cur_costs[QR_NUM_MODES]; +#ifndef _MSC_VER + char char_modes[length * QR_NUM_MODES]; +#else + char *char_modes = (char *) _alloca(length * QR_NUM_MODES); +#endif - m1 = version == MICROQR_VERSION; - m2 = version == MICROQR_VERSION + 1; + /* char_modes[i * QR_NUM_MODES + j] represents the mode to encode the code point at index i such that the final + * segment ends in mode_types[j] and the total number of bits is minimized over all possible choices */ + memset(char_modes, 0, length * QR_NUM_MODES); - if (jisdata[i] > 0xFF) { - cur_costs[QR_B] = prev_costs[QR_B] + ((m1 || m2) ? QR_MICROQR_MAX : 96); /* 16 * QR_MULT */ - char_modes[cm_i + QR_B] = 'B'; - cur_costs[QR_K] = prev_costs[QR_K] + ((m1 || m2) ? QR_MICROQR_MAX : 78); /* 13 * QR_MULT */ - char_modes[cm_i + QR_K] = 'K'; - } else { - if (in_numeric(jisdata, length, i, p_numeric_end, p_numeric_cost)) { - cur_costs[QR_N] = prev_costs[QR_N] + *p_numeric_cost; - char_modes[cm_i + QR_N] = 'N'; + /* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/QR_MULT) + * bits needed to encode the entire string prefix of length i, and end in mode_types[j] */ + memcpy(prev_costs, qr_head_costs(state), QR_NUM_MODES * sizeof(unsigned int)); + + /* Calculate costs using dynamic programming */ + for (i = 0, cm_i = 0; i < length; i++, cm_i += QR_NUM_MODES) { + memset(cur_costs, 0, QR_NUM_MODES * sizeof(unsigned int)); + + m1 = version == MICROQR_VERSION; + m2 = version == MICROQR_VERSION + 1; + + if (jisdata[i] > 0xFF) { + cur_costs[QR_B] = prev_costs[QR_B] + ((m1 || m2) ? QR_MICROQR_MAX : 96); /* 16 * QR_MULT */ + char_modes[cm_i + QR_B] = 'B'; + cur_costs[QR_K] = prev_costs[QR_K] + ((m1 || m2) ? QR_MICROQR_MAX : 78); /* 13 * QR_MULT */ + char_modes[cm_i + QR_K] = 'K'; + } else { + if (in_numeric(jisdata, length, i, &state[QR_N_END], &state[QR_N_COST])) { + cur_costs[QR_N] = prev_costs[QR_N] + state[QR_N_COST]; + char_modes[cm_i + QR_N] = 'N'; + } + if (in_alpha(jisdata, length, i, &state[QR_A_END], &state[QR_A_COST], &state[QR_A_PCENT], gs1)) { + cur_costs[QR_A] = prev_costs[QR_A] + (m1 ? QR_MICROQR_MAX : state[QR_A_COST]); + char_modes[cm_i + QR_A] = 'A'; + } + cur_costs[QR_B] = prev_costs[QR_B] + ((m1 || m2) ? QR_MICROQR_MAX : 48); /* 8 * QR_MULT */ + char_modes[cm_i + QR_B] = 'B'; } - if (in_alpha(jisdata, length, i, p_alpha_end, p_alpha_cost, p_alpha_pcent, gs1)) { - cur_costs[QR_A] = prev_costs[QR_A] + (m1 ? QR_MICROQR_MAX : *p_alpha_cost); - char_modes[cm_i + QR_A] = 'A'; + + /* Start new segment at the end to switch modes */ + for (j = 0; j < QR_NUM_MODES; j++) { /* To mode */ + for (k = 0; k < QR_NUM_MODES; k++) { /* From mode */ + if (j != k && char_modes[cm_i + k]) { + unsigned int new_cost = cur_costs[k] + state[j]; /* Switch costs same as head costs */ + if (!char_modes[cm_i + j] || new_cost < cur_costs[j]) { + cur_costs[j] = new_cost; + char_modes[cm_i + j] = mode_types[k]; + } + } + } } - cur_costs[QR_B] = prev_costs[QR_B] + ((m1 || m2) ? QR_MICROQR_MAX : 48); /* 8 * QR_MULT */ - char_modes[cm_i + QR_B] = 'B'; + + memcpy(prev_costs, cur_costs, QR_NUM_MODES * sizeof(unsigned int)); + } + + /* Find optimal ending mode */ + min_cost = prev_costs[0]; + cur_mode = mode_types[0]; + for (i = 1; i < QR_NUM_MODES; i++) { + if (prev_costs[i] < min_cost) { + min_cost = prev_costs[i]; + cur_mode = mode_types[i]; + } + } + + /* Get optimal mode for each code point by tracing backwards */ + for (i = length - 1, cm_i = i * QR_NUM_MODES; i >= 0; i--, cm_i -= QR_NUM_MODES) { + j = strchr(mode_types, cur_mode) - mode_types; + cur_mode = char_modes[cm_i + j]; + mode[i] = cur_mode; + } + + if (debug_print) { + printf(" Mode: %.*s\n", length, mode); } } -static void qr_define_mode(char mode[], const unsigned int jisdata[], const size_t length, const int gs1, const int version, const int debug) { - unsigned int state[11] = { - 0 /*N*/, 0 /*A*/, 0 /*B*/, 0 /*K*/, - (unsigned int) version, (unsigned int) gs1, - 0 /*numeric_end*/, 0 /*numeric_cost*/, 0 /*alpha_end*/, 0 /*alpha_cost*/, 0 /*alpha_pcent*/ +/* Returns mode indicator based on version and mode */ +static int mode_indicator(const int version, const int mode) { + static const int mode_indicators[6][QR_NUM_MODES] = { + /*N A B K */ + { 1, 2, 4, 8, }, /* QRCODE */ + { 1, 2, 3, 4, }, /* RMQR */ + { 0, 0, 0, 0, }, /* MICROQR */ + { 0, 1, 0, 0, }, + { 0, 1, 2, 3, }, + { 0, 1, 2, 3, }, }; - pn_define_mode(mode, jisdata, length, debug, state, mode_types, QR_NUM_MODES, qr_head_costs, qr_switch_cost, NULL, qr_cur_cost); + int mode_index = strchr(mode_types, mode) - mode_types; + + if (version < RMQR_VERSION) { + return mode_indicators[0][mode_index]; /* QRCODE */ + } + if (version < MICROQR_VERSION) { + return mode_indicators[1][mode_index] /* RMQR */; + } + return mode_indicators[2 + version - MICROQR_VERSION][mode_index]; /* MICROQR */ } /* Return mode indicator bits based on version */ @@ -269,7 +350,7 @@ static int cci_bits(const int version, const int mode) { { 5, 4, 4, 3, }, { 6, 5, 5, 4, } }; - static const unsigned short int* rmqr_ccis[QR_NUM_MODES] = { + static const unsigned short int *rmqr_ccis[QR_NUM_MODES] = { rmqr_numeric_cci, rmqr_alphanum_cci, rmqr_byte_cci, rmqr_kanji_cci, }; int mode_index = strchr(mode_types, mode) - mode_types; @@ -289,29 +370,6 @@ static int cci_bits(const int version, const int mode) { return cci_bits[3 + (version - MICROQR_VERSION)][mode_index]; /* MICROQR */ } -/* Returns mode indicator based on version and mode */ -static const char* mode_indicator(const int version, const int mode) { - static const char* mode_indicators[6][QR_NUM_MODES] = { - /* N A B K */ - { "0001", "0010", "0100", "1000", }, /* QRCODE */ - { "001", "010", "011", "100", }, /* RMQR */ - { "", "", "", "", }, /* MICROQR */ - { "0", "1", "", "", }, - { "00", "01", "10", "11", }, - { "000", "001", "010", "011", }, - }; - - int mode_index = strchr(mode_types, mode) - mode_types; - - if (version < RMQR_VERSION) { - return mode_indicators[0][mode_index]; /* QRCODE */ - } - if (version < MICROQR_VERSION) { - return mode_indicators[1][mode_index] /* RMQR */; - } - return mode_indicators[2 + version - MICROQR_VERSION][mode_index]; /* MICROQR */ -} - /* Returns terminator bits based on version */ static int terminator_bits(const int version) { if (version < RMQR_VERSION) { @@ -324,12 +382,13 @@ static int terminator_bits(const int version) { } /* 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[], const unsigned int jisdata[], const size_t length, - const int gs1, const int eci, const int est_binlen, const int debug) { - unsigned int position = 0; - int i; - int termbits, padbits; - int current_binlen, current_bytes; +static void qr_binary(unsigned char datastream[], const int version, const int target_codewords, const char mode[], + const unsigned int jisdata[], const int length, const int gs1, const int eci, const int est_binlen, + const int debug_print) { + int position = 0; + int i, j, bp; + int termbits, padbits, modebits; + int current_bytes; int toggle, percent; int percent_count; @@ -338,36 +397,32 @@ static void qr_binary(unsigned char datastream[], const int version, const int t #else char* binary = (char *) _alloca(est_binlen + 12); #endif - strcpy(binary, ""); + *binary = '\0'; + bp = 0; if (gs1) { /* Not applicable to MICROQR */ if (version < RMQR_VERSION) { - strcat(binary, "0101"); /* FNC1 */ + bp = bin_append_posn(5, 4, binary, bp); /* FNC1 */ } else { - strcat(binary, "101"); + bp = bin_append_posn(5, 3, binary, bp); } } if (eci != 0) { /* Not applicable to RMQR or MICROQR */ - strcat(binary, "0111"); /* ECI (Table 4) */ + bp = bin_append_posn(7, 4, binary, bp); /* ECI (Table 4) */ if (eci <= 127) { - bin_append(eci, 8, binary); /* 000000 to 000127 */ + bp = bin_append_posn(eci, 8, binary, bp); /* 000000 to 000127 */ } else if (eci <= 16383) { - bin_append(0x8000 + eci, 16, binary); /* 000000 to 016383 */ + bp = bin_append_posn(0x8000 + eci, 16, binary, bp); /* 000128 to 016383 */ } else { - bin_append(0xC00000 + eci, 24, binary); /* 000000 to 999999 */ + bp = bin_append_posn(0xC00000 + eci, 24, binary, bp); /* 016384 to 999999 */ } } - if (debug & ZINT_DEBUG_PRINT) { - for (i = 0; i < (int) length; i++) { - printf("%c", mode[i]); - } - printf("\n"); - } - percent = 0; + modebits = mode_bits(version); + do { char data_block = mode[position]; int short_data_block_length = 0; @@ -380,16 +435,19 @@ static void qr_binary(unsigned char datastream[], const int version, const int t } while (((short_data_block_length + position) < length) && (mode[position + short_data_block_length] == data_block)); + /* Mode indicator */ + if (modebits) { + bp = bin_append_posn(mode_indicator(version, data_block), modebits, binary, bp); + } + switch (data_block) { case 'K': /* Kanji mode */ - /* Mode indicator */ - strcat(binary, mode_indicator(version, data_block)); /* Character count indicator */ - bin_append(short_data_block_length, cci_bits(version, data_block), binary); + bp = bin_append_posn(short_data_block_length, cci_bits(version, data_block), binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Kanji block (length %d)\n\t", short_data_block_length); } @@ -406,27 +464,25 @@ static void qr_binary(unsigned char datastream[], const int version, const int t prod = ((jis >> 8) * 0xc0) + (jis & 0xff); - bin_append(prod, 13, binary); + bp = bin_append_posn(prod, 13, binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("0x%04X ", prod); } } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("\n"); } break; case 'B': /* Byte mode */ - /* Mode indicator */ - strcat(binary, mode_indicator(version, data_block)); /* Character count indicator */ - bin_append(short_data_block_length + double_byte, cci_bits(version, data_block), binary); + bp = bin_append_posn(short_data_block_length + double_byte, cci_bits(version, data_block), binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Byte block (length %d)\n\t", short_data_block_length + double_byte); } @@ -438,22 +494,20 @@ static void qr_binary(unsigned char datastream[], const int version, const int t byte = 0x1d; /* FNC1 */ } - bin_append(byte, byte > 0xFF ? 16 : 8, binary); + bp = bin_append_posn(byte, byte > 0xFF ? 16 : 8, binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("0x%02X(%d) ", byte, byte); } } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("\n"); } break; case 'A': /* Alphanumeric mode */ - /* Mode indicator */ - strcat(binary, mode_indicator(version, data_block)); percent_count = 0; if (gs1) { @@ -465,9 +519,9 @@ static void qr_binary(unsigned char datastream[], const int version, const int t } /* Character count indicator */ - bin_append(short_data_block_length + percent_count, cci_bits(version, data_block), binary); + bp = bin_append_posn(short_data_block_length + percent_count, cci_bits(version, data_block), binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Alpha block (length %d)\n\t", short_data_block_length + percent_count); } @@ -479,16 +533,16 @@ static void qr_binary(unsigned char datastream[], const int version, const int t if (percent == 0) { if (gs1 && (jisdata[position + i] == '%')) { - first = posn(RHODIUM, '%'); - second = posn(RHODIUM, '%'); + first = QR_PERCENT; + second = QR_PERCENT; count = 2; prod = (first * 45) + second; i++; } else { if (gs1 && (jisdata[position + i] == '[')) { - first = posn(RHODIUM, '%'); /* FNC1 */ + first = QR_PERCENT; /* FNC1 */ } else { - first = posn(RHODIUM, (char) jisdata[position + i]); + first = qr_alphanumeric[jisdata[position + i] - 32]; } count = 1; i++; @@ -496,15 +550,15 @@ static void qr_binary(unsigned char datastream[], const int version, const int t if (i < short_data_block_length && mode[position + i] == 'A') { if (gs1 && (jisdata[position + i] == '%')) { - second = posn(RHODIUM, '%'); + second = QR_PERCENT; count = 2; prod = (first * 45) + second; percent = 1; } else { if (gs1 && (jisdata[position + i] == '[')) { - second = posn(RHODIUM, '%'); /* FNC1 */ + second = QR_PERCENT; /* FNC1 */ } else { - second = posn(RHODIUM, (char) jisdata[position + i]); + second = qr_alphanumeric[jisdata[position + i] - 32]; } count = 2; i++; @@ -513,7 +567,7 @@ static void qr_binary(unsigned char datastream[], const int version, const int t } } } else { - first = posn(RHODIUM, '%'); + first = QR_PERCENT; count = 1; i++; prod = first; @@ -521,15 +575,15 @@ static void qr_binary(unsigned char datastream[], const int version, const int t if (i < short_data_block_length && mode[position + i] == 'A') { if (gs1 && (jisdata[position + i] == '%')) { - second = posn(RHODIUM, '%'); + second = QR_PERCENT; count = 2; prod = (first * 45) + second; percent = 1; } else { if (gs1 && (jisdata[position + i] == '[')) { - second = posn(RHODIUM, '%'); /* FNC1 */ + second = QR_PERCENT; /* FNC1 */ } else { - second = posn(RHODIUM, (char) jisdata[position + i]); + second = qr_alphanumeric[jisdata[position + i] - 32]; } count = 2; i++; @@ -538,27 +592,25 @@ static void qr_binary(unsigned char datastream[], const int version, const int t } } - bin_append(prod, 1 + (5 * count), binary); + bp = bin_append_posn(prod, 1 + (5 * count), binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("0x%X ", prod); } } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("\n"); } break; case 'N': /* Numeric mode */ - /* Mode indicator */ - strcat(binary, mode_indicator(version, data_block)); /* Character count indicator */ - bin_append(short_data_block_length, cci_bits(version, data_block), binary); + bp = bin_append_posn(short_data_block_length, cci_bits(version, data_block), binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Number block (length %d)\n\t", short_data_block_length); } @@ -584,16 +636,16 @@ static void qr_binary(unsigned char datastream[], const int version, const int t } } - bin_append(prod, 1 + (3 * count), binary); + bp = bin_append_posn(prod, 1 + (3 * count), binary, bp); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("0x%X(%d) ", prod, prod); } i += count; }; - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("\n"); } @@ -605,41 +657,41 @@ static void qr_binary(unsigned char datastream[], const int version, const int t if (version >= MICROQR_VERSION && version < MICROQR_VERSION + 4) { /* MICROQR does its own terminating/padding */ + binary[bp] = '\0'; strcpy((char*)datastream, binary); return; } /* Terminator */ - current_binlen = (int)strlen(binary); - termbits = 8 - current_binlen % 8; + termbits = 8 - bp % 8; if (termbits == 8) { termbits = 0; } - current_bytes = (current_binlen + termbits) / 8; + current_bytes = (bp + termbits) / 8; if (termbits || current_bytes < target_codewords) { int max_termbits = terminator_bits(version); termbits = termbits < max_termbits && current_bytes == target_codewords ? termbits : max_termbits; - bin_append(0, termbits, binary); - current_binlen += termbits; + bp = bin_append_posn(0, termbits, binary, bp); } /* Padding bits */ - padbits = 8 - current_binlen % 8; + padbits = 8 - bp % 8; if (padbits == 8) { padbits = 0; } if (padbits) { - current_bytes = (current_binlen + padbits) / 8; - bin_append(0, padbits, binary); + current_bytes = (bp + padbits) / 8; + (void) bin_append_posn(0, padbits, binary, bp); /* Last use so not setting bp */ } /* Put data into 8-bit codewords */ for (i = 0; i < current_bytes; i++) { int p; + j = i * 8; datastream[i] = 0x00; for (p = 0; p < 8; p++) { - if (binary[i * 8 + p] == '1') { - datastream[i] += (0x80 >> p); + if (binary[j + p] == '1') { + datastream[i] |= (0x80 >> p); } } } @@ -656,7 +708,7 @@ static void qr_binary(unsigned char datastream[], const int version, const int t } } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Resulting codewords:\n\t"); for (i = 0; i < target_codewords; i++) { printf("0x%02X ", datastream[i]); @@ -666,13 +718,15 @@ static void qr_binary(unsigned char datastream[], const int version, const int t } /* Split data into blocks, add error correction and then interleave the blocks and error correction data */ -static void add_ecc(unsigned char fullstream[], const unsigned char datastream[], const int version, const int data_cw, const int blocks, int debug) { +static void add_ecc(unsigned char fullstream[], const unsigned char datastream[], const int version, const int data_cw, + const int blocks, int debug_print) { int ecc_cw; int short_data_block_length; int qty_long_blocks; int qty_short_blocks; int ecc_block_length; - int i, j, length_this_block, posn; + int i, j, length_this_block, in_posn; + rs_t rs; #ifdef _MSC_VER unsigned char* data_block; unsigned char* ecc_block; @@ -707,7 +761,10 @@ static void add_ecc(unsigned char fullstream[], const unsigned char datastream[] interleaved_ecc = (unsigned char *) _alloca(ecc_cw); #endif - posn = 0; + rs_init_gf(&rs, 0x11d); + rs_init_code(&rs, ecc_block_length, 0); + + in_posn = 0; for (i = 0; i < blocks; i++) { if (i < qty_short_blocks) { @@ -721,15 +778,12 @@ static void add_ecc(unsigned char fullstream[], const unsigned char datastream[] } for (j = 0; j < length_this_block; j++) { - data_block[j] = datastream[posn + j]; + data_block[j] = datastream[in_posn + j]; } - rs_init_gf(0x11d); - rs_init_code(ecc_block_length, 0); - rs_encode(length_this_block, data_block, ecc_block); - rs_free(); + rs_encode(&rs, length_this_block, data_block, ecc_block); - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Block %d: ", i + 1); for (j = 0; j < length_this_block; j++) { printf("%2X ", data_block[j]); @@ -756,7 +810,7 @@ static void add_ecc(unsigned char fullstream[], const unsigned char datastream[] interleaved_ecc[(j * blocks) + i] = ecc_block[ecc_block_length - j - 1]; } - posn += length_this_block; + in_posn += length_this_block; } for (j = 0; j < data_cw; j++) { @@ -766,7 +820,7 @@ static void add_ecc(unsigned char fullstream[], const unsigned char datastream[] fullstream[j + data_cw] = interleaved_ecc[j]; // NOLINT suppress clang-tidy warning: interleaved_ecc[ecc_cw] fully set } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("\nData Stream: \n"); for (j = 0; j < (data_cw + ecc_cw); j++) { printf("%2X ", fullstream[j]); @@ -775,7 +829,7 @@ static void add_ecc(unsigned char fullstream[], const unsigned char datastream[] } } -static void place_finder(unsigned char grid[],const int size,const int x,const int y) { +static void place_finder(unsigned char grid[], const int size, const int x, const int y) { int xp, yp; char finder[] = {0x7F, 0x41, 0x5D, 0x5D, 0x5D, 0x41, 0x7F}; @@ -790,7 +844,7 @@ static void place_finder(unsigned char grid[],const int size,const int x,const i } } -static void place_align(unsigned char grid[],const int size,int x,int y) { +static void place_align(unsigned char grid[], const int size, int x, int y) { int xp, yp; char alignment[] = {0x1F, 0x11, 0x15, 0x11, 0x1F}; @@ -808,7 +862,7 @@ static void place_align(unsigned char grid[],const int size,int x,int y) { } } -static void setup_grid(unsigned char* grid,const int size,const int version) { +static void setup_grid(unsigned char *grid, const int size, const int version) { int i, toggle = 1; /* Add timing patterns */ @@ -862,12 +916,12 @@ static void setup_grid(unsigned char* grid,const int size,const int version) { /* Reserve space for format information */ for (i = 0; i < 8; i++) { - grid[(8 * size) + i] += 0x20; - grid[(i * size) + 8] += 0x20; + grid[(8 * size) + i] |= 0x20; + grid[(i * size) + 8] |= 0x20; grid[(8 * size) + (size - 1 - i)] = 0x20; grid[((size - 1 - i) * size) + 8] = 0x20; } - grid[(8 * size) + 8] += 0x20; + grid[(8 * size) + 8] |= 0x20; grid[((size - 1 - 7) * size) + 8] = 0x21; /* Dark Module from Figure 25 */ /* Reserve space for version information */ @@ -884,16 +938,16 @@ static void setup_grid(unsigned char* grid,const int size,const int version) { } static int cwbit(const unsigned char* fullstream, const int i) { - int resultant = 0; - if (fullstream[(i / 8)] & (0x80 >> (i % 8))) { - resultant = 1; + if (fullstream[(i >> 3)] & (0x80 >> (i & 0x07))) { + return 1; } - return resultant; + return 0; } -static void populate_grid(unsigned char* grid, const int h_size, const int v_size, const unsigned char* fullstream, const int cw) { +static void populate_grid(unsigned char *grid, const int h_size, const int v_size, const unsigned char *fullstream, + const int cw) { int direction = 1; /* up */ int row = 0; /* right hand side */ @@ -904,46 +958,39 @@ static void populate_grid(unsigned char* grid, const int h_size, const int v_siz i = 0; while (i < n) { int x = (h_size - 2) - (row * 2); + int r = y * h_size; if ((x < 6) && (v_size == h_size)) x--; /* skip over vertical timing pattern */ - if (!(grid[(y * h_size) + (x + 1)] & 0xf0)) { - if (cwbit(fullstream, i)) { - grid[(y * h_size) + (x + 1)] = 0x01; - } else { - grid[(y * h_size) + (x + 1)] = 0x00; - } + if (!(grid[r + (x + 1)] & 0xf0)) { + grid[r + (x + 1)] = cwbit(fullstream, i); i++; } if (i < n) { - if (!(grid[(y * h_size) + x] & 0xf0)) { - if (cwbit(fullstream, i)) { - grid[(y * h_size) + x] = 0x01; - } else { - grid[(y * h_size) + x] = 0x00; - } + if (!(grid[r + x] & 0xf0)) { + grid[r + x] = cwbit(fullstream, i); i++; } } if (direction) { y--; + if (y == -1) { + /* reached the top */ + row++; + y = 0; + direction = 0; + } } else { y++; - } - if (y == -1) { - /* reached the top */ - row++; - y = 0; - direction = 0; - } - if (y == v_size) { - /* reached the bottom */ - row++; - y = v_size - 1; - direction = 1; + if (y == v_size) { + /* reached the bottom */ + row++; + y = v_size - 1; + direction = 1; + } } } } @@ -970,47 +1017,23 @@ static int write_log(char log[]) { } #endif -static int evaluate(unsigned char *eval,const int size,const int pattern) { - int x, y, block, weight; +static int evaluate(unsigned char *local, const int size) { + static const unsigned char h1011101[7] = { 1, 0, 1, 1, 1, 0, 1 }; + + int x, y, r, k, block; int result = 0; char state; - int p; int dark_mods; - int percentage, k; + double percentage; int a, b, afterCount, beforeCount; #ifdef ZINTLOG int result_b = 0; char str[15]; #endif -#ifndef _MSC_VER - char local[size * size]; -#else - char* local = (char *) _alloca((size * size) * sizeof (char)); -#endif - /* Suppresses clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult warnings */ assert(size > 0); -#ifdef ZINTLOG - write_log(""); - sprintf(str, "%d", pattern); - write_log(str); -#endif - - /* all eight bitmask variants have been encoded in the 8 bits of the bytes - * that make up the grid array. select them for evaluation according to the - * desired pattern.*/ - for (x = 0; x < size; x++) { - for (y = 0; y < size; y++) { - if ((eval[(y * size) + x] & (0x01 << pattern)) != 0) { - local[(y * size) + x] = '1'; - } else { - local[(y * size) + x] = '0'; - } - } - } - #ifdef ZINTLOG //bitmask output for (y = 0; y < size; y++) { @@ -1027,41 +1050,42 @@ static int evaluate(unsigned char *eval,const int size,const int pattern) { /* Test 1: Adjacent modules in row/column in same colour */ /* Vertical */ for (x = 0; x < size; x++) { - state = local[x]; block = 0; + state = 0; for (y = 0; y < size; y++) { if (local[(y * size) + x] == state) { block++; } else { - if (block > 5) { - result += (3 + (block - 5)); + if (block >= 5) { + result += block - 2; } - block = 0; + block = 1; state = local[(y * size) + x]; } } - if (block > 5) { - result += (3 + (block - 5)); + if (block >= 5) { + result += block - 2; } } /* Horizontal */ for (y = 0; y < size; y++) { - state = local[y * size]; + r = y * size; block = 0; + state = 0; for (x = 0; x < size; x++) { - if (local[(y * size) + x] == state) { + if (local[r + x] == state) { block++; } else { - if (block > 5) { - result += (3 + (block - 5)); + if (block >= 5) { + result += block - 2; } - block = 0; - state = local[(y * size) + x]; + block = 1; + state = local[r + x]; } } - if (block > 5) { - result += (3 + (block - 5)); + if (block >= 5) { + result += block - 2; } } @@ -1073,13 +1097,18 @@ static int evaluate(unsigned char *eval,const int size,const int pattern) { #endif /* Test 2: Block of modules in same color */ + dark_mods = 0; /* Count dark mods simultaneously (see Test 4 below) */ for (x = 0; x < size - 1; x++) { for (y = 0; y < size - 1; y++) { - if (((local[(y * size) + x] == local[((y + 1) * size) + x]) && - (local[(y * size) + x] == local[(y * size) + (x + 1)])) && - (local[(y * size) + x] == local[((y + 1) * size) + (x + 1)])) { + k = local[(y * size) + x]; + if (((k == local[((y + 1) * size) + x]) && + (k == local[(y * size) + (x + 1)])) && + (k == local[((y + 1) * size) + (x + 1)])) { result += 3; } + if (k) { + dark_mods++; + } } } @@ -1093,92 +1122,86 @@ static int evaluate(unsigned char *eval,const int size,const int pattern) { /* Test 3: 1:1:3:1:1 ratio pattern in row/column */ /* Vertical */ for (x = 0; x < size; x++) { - for (y = 0; y < (size - 7); y++) { - p = 0; - for (weight = 0; weight < 7; weight++) { - if (local[((y + weight) * size) + x] == '1') { - p += (0x40 >> weight); - } - } - if (p == 0x5d) { + for (y = 0; y <= (size - 7); y++) { + if (local[y * size + x] && !local[(y + 1) * size + x] && local[(y + 2) * size + x] && + local[(y + 3) * size + x] && local[(y + 4) * size + x] && + !local[(y + 5) * size + x] && local[(y + 6) * size + x]) { /* Pattern found, check before and after */ beforeCount = 0; - for (b = (y - 4); b < y; b++) { - if (b < 0) { - beforeCount++; - } else { - if (local[(b * size) + x] == '0') { - beforeCount++; - } else { - beforeCount = 0; - } + for (b = (y - 1); b >= (y - 4); b--) { + if (b < 0) { /* Count < edge as whitespace */ + beforeCount = 4; + break; } - } - - afterCount = 0; - for (a = (y + 7); a <= (y + 10); a++) { - if (a >= size) { - afterCount++; - } else { - if (local[(a * size) + x] == '0') { - afterCount++; - } else { - afterCount = 0; - } + if (local[(b * size) + x]) { + break; } + beforeCount++; } - - if ((beforeCount == 4) || (afterCount == 4)) { - /* Pattern is preceeded or followed by light area - 4 modules wide */ + if (beforeCount == 4) { + /* Pattern is preceded by light area 4 modules wide */ result += 40; + } else { + afterCount = 0; + for (a = (y + 7); a <= (y + 10); a++) { + if (a >= size) { /* Count > edge as whitespace */ + afterCount = 4; + break; + } + if (local[(a * size) + x]) { + break; + } + afterCount++; + } + if (afterCount == 4) { + /* Pattern is followed by light area 4 modules wide */ + result += 40; + } } + y += 3; /* Skip to next possible match */ } } } /* Horizontal */ for (y = 0; y < size; y++) { - for (x = 0; x < (size - 7); x++) { - p = 0; - for (weight = 0; weight < 7; weight++) { - if (local[(y * size) + x + weight] == '1') { - p += (0x40 >> weight); - } - } - if (p == 0x5d) { + r = y * size; + for (x = 0; x <= (size - 7); x++) { + if (memcmp(local + r + x, h1011101, 7) == 0) { /* Pattern found, check before and after */ beforeCount = 0; - for (b = (x - 4); b < x; b++) { - if (b < 0) { - beforeCount++; - } else { - if (local[(y * size) + b] == '0') { - beforeCount++; - } else { - beforeCount = 0; - } + for (b = (x - 1); b >= (x - 4); b--) { + if (b < 0) { /* Count < edge as whitespace */ + beforeCount = 4; + break; } + if (local[r + b]) { + break; + } + beforeCount++; } - afterCount = 0; - for (a = (x + 7); a <= (x + 10); a++) { - if (a >= size) { - afterCount++; - } else { - if (local[(y * size) + a] == '0') { - afterCount++; - } else { - afterCount = 0; - } - } - } - - if ((beforeCount == 4) || (afterCount == 4)) { - /* Pattern is preceeded or followed by light area - 4 modules wide */ + if (beforeCount == 4) { + /* Pattern is preceded by light area 4 modules wide */ result += 40; + } else { + afterCount = 0; + for (a = (x + 7); a <= (x + 10); a++) { + if (a >= size) { /* Count > edge as whitespace */ + afterCount = 4; + break; + } + if (local[r + a]) { + break; + } + afterCount++; + } + if (afterCount == 4) { + /* Pattern is followed by light area 4 modules wide */ + result += 40; + } } + x += 3; /* Skip to next possible match */ } } } @@ -1191,19 +1214,11 @@ static int evaluate(unsigned char *eval,const int size,const int pattern) { #endif /* Test 4: Proportion of dark modules in entire symbol */ - dark_mods = 0; - for (x = 0; x < size; x++) { - for (y = 0; y < size; y++) { - if (local[(y * size) + x] == '1') { - dark_mods++; - } - } - } - percentage = 100 * (dark_mods / (size * size)); - if (percentage <= 50) { - k = ((100 - percentage) - 50) / 5; + percentage = (100.0 * dark_mods) / (size * size); + if (percentage < 50.0) { + k = (int) ceil(((100.0 - percentage) - 50.0) / 5.0); } else { - k = (percentage - 50) / 5; + k = (int) ceil((percentage - 50.0) / 5.0); } result += 10 * k; @@ -1220,123 +1235,130 @@ static int evaluate(unsigned char *eval,const int size,const int pattern) { return result; } -static void add_format_info_eval(unsigned char *eval,const int size,const int ecc_level,const int pattern) { - /* Add format information to grid */ - +/* Add format information to grid */ +static void add_format_info(unsigned char *grid, const int size, const int ecc_level, const int pattern) { int format = pattern; unsigned int seq; int i; switch (ecc_level) { - case LEVEL_L: format += 0x08; + case LEVEL_L: format |= 0x08; break; - case LEVEL_Q: format += 0x18; + case LEVEL_Q: format |= 0x18; break; - case LEVEL_H: format += 0x10; + case LEVEL_H: format |= 0x10; break; } seq = qr_annex_c[format]; for (i = 0; i < 6; i++) { - eval[(i * size) + 8] = ((seq >> i) & 0x01) ? (0x01 >> pattern) : 0x00; + grid[(i * size) + 8] |= (seq >> i) & 0x01; } for (i = 0; i < 8; i++) { - eval[(8 * size) + (size - i - 1)] = ((seq >> i) & 0x01) ? (0x01 >> pattern) : 0x00; + grid[(8 * size) + (size - i - 1)] |= (seq >> i) & 0x01; } for (i = 0; i < 6; i++) { - eval[(8 * size) + (5 - i)] = ((seq >> (i + 9)) & 0x01) ? (0x01 >> pattern) : 0x00; + grid[(8 * size) + (5 - i)] |= (seq >> (i + 9)) & 0x01; } for (i = 0; i < 7; i++) { - eval[(((size - 7) + i) * size) + 8] = ((seq >> (i + 8)) & 0x01) ? (0x01 >> pattern) : 0x00; + grid[(((size - 7) + i) * size) + 8] |= (seq >> (i + 8)) & 0x01; } - eval[(7 * size) + 8] = ((seq >> 6) & 0x01) ? (0x01 >> pattern) : 0x00; - eval[(8 * size) + 8] = ((seq >> 7) & 0x01) ? (0x01 >> pattern) : 0x00; - eval[(8 * size) + 7] = ((seq >> 8) & 0x01) ? (0x01 >> pattern) : 0x00; + grid[(7 * size) + 8] |= (seq >> 6) & 0x01; + grid[(8 * size) + 8] |= (seq >> 7) & 0x01; + grid[(8 * size) + 7] |= (seq >> 8) & 0x01; } -static int apply_bitmask(unsigned char *grid,const int size,const int ecc_level) { +static int apply_bitmask(unsigned char *grid, const int size, const int ecc_level, const int user_mask, + const int debug_print) { int x, y; - unsigned char p; + int r, k; + int bit; int pattern, penalty[8]; - int best_val, best_pattern; + int best_pattern; + int size_squared = size * size; #ifndef _MSC_VER - unsigned char mask[size * size]; - unsigned char eval[size * size]; + unsigned char mask[size_squared]; + unsigned char local[size_squared]; #else - unsigned char* mask = (unsigned char *) _alloca((size * size) * sizeof (unsigned char)); - unsigned char* eval = (unsigned char *) _alloca((size * size) * sizeof (unsigned char)); + unsigned char *mask = (unsigned char *) _alloca(size_squared * sizeof (unsigned char)); + unsigned char *local = (unsigned char *) _alloca(size_squared * sizeof (unsigned char)); #endif /* Perform data masking */ - for (x = 0; x < size; x++) { - for (y = 0; y < size; y++) { - mask[(y * size) + x] = 0x00; + memset(mask, 0, size_squared); + for (y = 0; y < size; y++) { + r = y * size; + for (x = 0; x < size; x++) { // all eight bitmask variants are encoded in the 8 bits of the bytes that make up the mask array. - if (!(grid[(y * size) + x] & 0xf0)) { // exclude areas not to be masked. + if (!(grid[r + x] & 0xf0)) { // exclude areas not to be masked. if (((y + x) & 1) == 0) { - mask[(y * size) + x] += 0x01; + mask[r + x] |= 0x01; } if ((y & 1) == 0) { - mask[(y * size) + x] += 0x02; + mask[r + x] |= 0x02; } if ((x % 3) == 0) { - mask[(y * size) + x] += 0x04; + mask[r + x] |= 0x04; } if (((y + x) % 3) == 0) { - mask[(y * size) + x] += 0x08; + mask[r + x] |= 0x08; } if ((((y / 2) + (x / 3)) & 1) == 0) { - mask[(y * size) + x] += 0x10; + mask[r + x] |= 0x10; } - if ((((y * x) & 1) + ((y * x) % 3)) == 0) { - mask[(y * size) + x] += 0x20; + if ((y * x) % 6 == 0) { /* Equivalent to (y * x) % 2 + (y * x) % 3 == 0 */ + mask[r + x] |= 0x20; } if (((((y * x) & 1) + ((y * x) % 3)) & 1) == 0) { - mask[(y * size) + x] += 0x40; + mask[r + x] |= 0x40; } if (((((y + x) & 1) + ((y * x) % 3)) & 1) == 0) { - mask[(y * size) + x] += 0x80; + mask[r + x] |= 0x80; } } } } - // apply data masks to grid, result in eval - for (x = 0; x < size; x++) { - for (y = 0; y < size; y++) { - if (grid[(y * size) + x] & 0x01) { - p = 0xff; - } else { - p = 0x00; + if (user_mask) { + best_pattern = user_mask - 1; + } else { + /* all eight bitmask variants have been encoded in the 8 bits of the bytes + * that make up the mask array. select them for evaluation according to the + * desired pattern.*/ + best_pattern = 0; + for (pattern = 0; pattern < 8; pattern++) { + + bit = 1 << pattern; + for (k = 0; k < size_squared; k++) { + if (mask[k] & bit) { + local[k] = grid[k] ^ 0x01; + } else { + local[k] = grid[k] & 0x0f; + } } + add_format_info(local, size, ecc_level, pattern); - eval[(y * size) + x] = mask[(y * size) + x] ^ p; + penalty[pattern] = evaluate(local, size); + + if (penalty[pattern] < penalty[best_pattern]) { + best_pattern = pattern; + } } } - - /* Evaluate result */ - for (pattern = 0; pattern < 8; pattern++) { - - add_format_info_eval(eval, size, ecc_level, pattern); - - penalty[pattern] = evaluate(eval, size, pattern); - } - - best_pattern = 0; - best_val = penalty[0]; - for (pattern = 1; pattern < 8; pattern++) { - if (penalty[pattern] < best_val) { - best_pattern = pattern; - best_val = penalty[pattern]; + if (debug_print) { + printf("Mask: %d (%s)", best_pattern, user_mask ? "specified" : "automatic"); + if (!user_mask) { + for (pattern = 0; pattern < 8; pattern++) printf(" %d:%d", pattern, penalty[pattern]); } + printf("\n"); } #ifdef ZINTLOG @@ -1347,14 +1369,13 @@ static int apply_bitmask(unsigned char *grid,const int size,const int ecc_level) #endif /* Apply mask */ - for (x = 0; x < size; x++) { - for (y = 0; y < size; y++) { - if (mask[(y * size) + x] & (0x01 << best_pattern)) { - if (grid[(y * size) + x] & 0x01) { - grid[(y * size) + x] = 0x00; - } else { - grid[(y * size) + x] = 0x01; - } + if (!user_mask && best_pattern == 7) { /* Reuse last */ + memcpy(grid, local, size_squared); + } else { + bit = 1 << best_pattern; + for (y = 0; y < size_squared; y++) { + if (mask[y] & bit) { + grid[y] ^= 0x01; } } } @@ -1362,46 +1383,8 @@ static int apply_bitmask(unsigned char *grid,const int size,const int ecc_level) return best_pattern; } -/* Add format information to grid */ -static void add_format_info(unsigned char *grid,const int size,const int ecc_level,const int pattern) { - int format = pattern; - unsigned int seq; - int i; - - switch (ecc_level) { - case LEVEL_L: format += 0x08; - break; - case LEVEL_Q: format += 0x18; - break; - case LEVEL_H: format += 0x10; - break; - } - - seq = qr_annex_c[format]; - - for (i = 0; i < 6; i++) { - grid[(i * size) + 8] += (seq >> i) & 0x01; - } - - for (i = 0; i < 8; i++) { - grid[(8 * size) + (size - i - 1)] += (seq >> i) & 0x01; - } - - for (i = 0; i < 6; i++) { - grid[(8 * size) + (5 - i)] += (seq >> (i + 9)) & 0x01; - } - - for (i = 0; i < 7; i++) { - grid[(((size - 7) + i) * size) + 8] += (seq >> (i + 8)) & 0x01; - } - - grid[(7 * size) + 8] += (seq >> 6) & 0x01; - grid[(8 * size) + 8] += (seq >> 7) & 0x01; - grid[(8 * size) + 7] += (seq >> 8) & 0x01; -} - /* Add version information */ -static void add_version_info(unsigned char *grid,const int size,const int version) { +static void add_version_info(unsigned char *grid, const int size, const int version) { int i; long int version_data = qr_annex_d[version - 7]; @@ -1415,9 +1398,9 @@ static void add_version_info(unsigned char *grid,const int size,const int versio } } -static size_t blockLength(const size_t start,const char inputMode[],const size_t inputLength) { +static int blockLength(const int start, const char inputMode[], const int inputLength) { /* Find the length of the block starting from 'start' */ - size_t i; + int i; int count; char mode = inputMode[start]; @@ -1431,15 +1414,16 @@ static size_t blockLength(const size_t start,const char inputMode[],const size_t return count; } -static int getBinaryLength(const int version, char inputMode[], const unsigned int inputData[], const size_t inputLength, const int gs1, const int eci, const int debug) { +static int getBinaryLength(const int version, char inputMode[], const unsigned int inputData[], const int inputLength, + const int gs1, const int eci, const int debug_print) { /* Calculate the actual bitlength of the proposed binary string */ - size_t i, j; + int i, j; char currentMode; int count = 0; int alphalength; int blocklength; - qr_define_mode(inputMode, inputData, inputLength, gs1, version, debug); + qr_define_mode(inputMode, inputData, inputLength, gs1, version, debug_print); currentMode = ' '; // Null @@ -1519,33 +1503,43 @@ static int getBinaryLength(const int version, char inputMode[], const unsigned i } } - if (debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Estimated Binary Length: %d (version %d, eci %d, gs1 %d)\n", count, version, eci, gs1); } return count; } -INTERNAL int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t length) { - int i, j, est_binlen; +INTERNAL int qr_code(struct zint_symbol *symbol, unsigned char source[], int length) { + int i, j, est_binlen, prev_est_binlen; int ecc_level, autosize, version, max_cw, target_codewords, blocks, size; int bitmask, gs1; int full_multibyte; + int user_mask; int canShrink; + int size_squared; + int debug_print = symbol->debug & ZINT_DEBUG_PRINT; #ifndef _MSC_VER unsigned int jisdata[length + 1]; - char mode[length + 1]; + char mode[length]; + char prev_mode[length]; #else unsigned char* datastream; unsigned char* fullstream; unsigned char* grid; unsigned int* jisdata = (unsigned int *) _alloca((length + 1) * sizeof (unsigned int)); - char* mode = (char *) _alloca(length + 1); + char *mode = (char *) _alloca(length); + char *prev_mode = (char *) _alloca(length); #endif gs1 = ((symbol->input_mode & 0x07) == GS1_MODE); - full_multibyte = symbol->option_3 == ZINT_FULL_MULTIBYTE; /* If set use Kanji mode in DATA_MODE or for single-byte Latin */ + /* If ZINT_FULL_MULTIBYTE use Kanji mode in DATA_MODE or for single-byte Latin */ + full_multibyte = (symbol->option_3 & 0xFF) == ZINT_FULL_MULTIBYTE; + user_mask = (symbol->option_3 >> 8) & 0x0F; /* User mask is pattern + 1, so >= 1 and <= 8 */ + if (user_mask > 8) { + user_mask = 0; /* Ignore */ + } if ((symbol->input_mode & 0x07) == DATA_MODE) { sjis_cpy(source, &length, jisdata, full_multibyte); @@ -1553,7 +1547,8 @@ INTERNAL int qr_code(struct zint_symbol *symbol, const unsigned char source[], s int done = 0; if (symbol->eci != 20) { /* Unless ECI 20 (Shift JIS) */ /* Try single byte (Latin) conversion first */ - int error_number = sjis_utf8tosb(symbol->eci && symbol->eci <= 899 ? symbol->eci : 3, source, &length, jisdata, full_multibyte); + int error_number = sjis_utf8tosb(symbol->eci && symbol->eci <= 899 ? symbol->eci : 3, source, &length, + jisdata, full_multibyte); if (error_number == 0) { done = 1; } else if (symbol->eci && symbol->eci <= 899) { @@ -1570,7 +1565,7 @@ INTERNAL int qr_code(struct zint_symbol *symbol, const unsigned char source[], s } } - est_binlen = getBinaryLength(40, mode, jisdata, length, gs1, symbol->eci, symbol->debug); + est_binlen = getBinaryLength(40, mode, jisdata, length, gs1, symbol->eci, debug_print); ecc_level = LEVEL_L; max_cw = 2956; @@ -1621,7 +1616,7 @@ INTERNAL int qr_code(struct zint_symbol *symbol, const unsigned char source[], s } } if (autosize != 40) { - est_binlen = getBinaryLength(autosize, mode, jisdata, length, gs1, symbol->eci, symbol->debug); + est_binlen = getBinaryLength(autosize, mode, jisdata, length, gs1, symbol->eci, debug_print); } // Now see if the optimised binary will fit in a smaller symbol. @@ -1631,7 +1626,9 @@ INTERNAL int qr_code(struct zint_symbol *symbol, const unsigned char source[], s if (autosize == 1) { canShrink = 0; } else { - est_binlen = getBinaryLength(autosize - 1, mode, jisdata, length, gs1, symbol->eci, symbol->debug); + prev_est_binlen = est_binlen; + memcpy(prev_mode, mode, length); + est_binlen = getBinaryLength(autosize - 1, mode, jisdata, length, gs1, symbol->eci, debug_print); switch (ecc_level) { case LEVEL_L: @@ -1661,7 +1658,8 @@ INTERNAL int qr_code(struct zint_symbol *symbol, const unsigned char source[], s autosize--; } else { // Data did not fit in the smaller symbol, revert to original size - est_binlen = getBinaryLength(autosize, mode, jisdata, length, gs1, symbol->eci, symbol->debug); + est_binlen = prev_est_binlen; + memcpy(mode, prev_mode, length); } } } while (canShrink == 1); @@ -1675,7 +1673,7 @@ INTERNAL int qr_code(struct zint_symbol *symbol, const unsigned char source[], s */ if (symbol->option_2 > version) { version = symbol->option_2; - est_binlen = getBinaryLength(symbol->option_2, mode, jisdata, length, gs1, symbol->eci, symbol->debug); + est_binlen = getBinaryLength(symbol->option_2, mode, jisdata, length, gs1, symbol->eci, debug_print); } if (symbol->option_2 < version) { @@ -1719,24 +1717,21 @@ INTERNAL int qr_code(struct zint_symbol *symbol, const unsigned char source[], s fullstream = (unsigned char *) _alloca(qr_total_codewords[version - 1] + 1); #endif - qr_binary(datastream, version, target_codewords, mode, jisdata, length, gs1, symbol->eci, est_binlen, symbol->debug); + qr_binary(datastream, version, target_codewords, mode, jisdata, length, gs1, symbol->eci, est_binlen, debug_print); #ifdef ZINT_TEST if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); #endif - add_ecc(fullstream, datastream, version, target_codewords, blocks, symbol->debug); + add_ecc(fullstream, datastream, version, target_codewords, blocks, debug_print); size = qr_sizes[version - 1]; + size_squared = size * size; #ifndef _MSC_VER - unsigned char grid[size * size]; + unsigned char grid[size_squared]; #else - grid = (unsigned char *) _alloca((size * size) * sizeof (unsigned char)); + grid = (unsigned char *) _alloca(size_squared * sizeof (unsigned char)); #endif - for (i = 0; i < size; i++) { - for (j = 0; j < size; j++) { - grid[(i * size) + j] = 0; - } - } + memset(grid, 0, size_squared); setup_grid(grid, size, version); populate_grid(grid, size, size, fullstream, qr_total_codewords[version - 1]); @@ -1745,7 +1740,7 @@ INTERNAL int qr_code(struct zint_symbol *symbol, const unsigned char source[], s add_version_info(grid, size, version); } - bitmask = apply_bitmask(grid, size, ecc_level); + bitmask = apply_bitmask(grid, size, ecc_level, user_mask, debug_print); add_format_info(grid, size, ecc_level, bitmask); @@ -1753,8 +1748,9 @@ INTERNAL int qr_code(struct zint_symbol *symbol, const unsigned char source[], s symbol->rows = size; for (i = 0; i < size; i++) { + int r = i * size; for (j = 0; j < size; j++) { - if (grid[(i * size) + j] & 0x01) { + if (grid[r + j] & 0x01) { set_module(symbol, i, j); } } @@ -1769,6 +1765,7 @@ static void micro_qr_m1(struct zint_symbol *symbol, char binary_data[]) { int bits_total, bits_left; int data_codewords, ecc_codewords; unsigned char data_blocks[4], ecc_blocks[3]; + rs_t rs; bits_total = 20; latch = 0; @@ -1824,14 +1821,14 @@ static void micro_qr_m1(struct zint_symbol *symbol, char binary_data[]) { data_blocks[i] = 0; for (j = 0; j < 8; j++) { if (binary_data[(i * 8) + j] == '1') { - data_blocks[i] += 0x80 >> j; + data_blocks[i] |= 0x80 >> j; } } } data_blocks[2] = 0; for (j = 0; j < 4; j++) { if (binary_data[16 + j] == '1') { - data_blocks[2] += 0x80 >> j; + data_blocks[2] |= 0x80 >> j; } } #ifdef ZINT_TEST @@ -1841,10 +1838,9 @@ static void micro_qr_m1(struct zint_symbol *symbol, char binary_data[]) { #endif /* Calculate Reed-Solomon error codewords */ - rs_init_gf(0x11d); - rs_init_code(ecc_codewords, 0); - rs_encode(data_codewords, data_blocks, ecc_blocks); - rs_free(); + rs_init_gf(&rs, 0x11d); + rs_init_code(&rs, ecc_codewords, 0); + rs_encode(&rs, data_codewords, data_blocks, ecc_blocks); /* Add Reed-Solomon codewords to binary data */ for (i = 0; i < ecc_codewords; i++) { @@ -1857,6 +1853,7 @@ static void micro_qr_m2(struct zint_symbol *symbol, char binary_data[], const in int bits_total=0, bits_left; int data_codewords=0, ecc_codewords=0; unsigned char data_blocks[6], ecc_blocks[7]; + rs_t rs; latch = 0; @@ -1913,7 +1910,7 @@ static void micro_qr_m2(struct zint_symbol *symbol, char binary_data[], const in for (j = 0; j < 8; j++) { if (binary_data[(i * 8) + j] == '1') { - data_blocks[i] += 0x80 >> j; + data_blocks[i] |= 0x80 >> j; } } } @@ -1924,10 +1921,9 @@ static void micro_qr_m2(struct zint_symbol *symbol, char binary_data[], const in #endif /* Calculate Reed-Solomon error codewords */ - rs_init_gf(0x11d); - rs_init_code(ecc_codewords, 0); - rs_encode(data_codewords, data_blocks, ecc_blocks); - rs_free(); + rs_init_gf(&rs, 0x11d); + rs_init_code(&rs, ecc_codewords, 0); + rs_encode(&rs, data_codewords, data_blocks, ecc_blocks); /* Add Reed-Solomon codewords to binary data */ for (i = 0; i < ecc_codewords; i++) { @@ -1942,6 +1938,7 @@ static void micro_qr_m3(struct zint_symbol *symbol, char binary_data[], const in int bits_total=0, bits_left; int data_codewords=0, ecc_codewords=0; unsigned char data_blocks[12], ecc_blocks[9]; + rs_t rs; latch = 0; @@ -2012,7 +2009,7 @@ static void micro_qr_m3(struct zint_symbol *symbol, char binary_data[], const in for (j = 0; j < 8; j++) { if (binary_data[(i * 8) + j] == '1') { - data_blocks[i] += 0x80 >> j; + data_blocks[i] |= 0x80 >> j; } } } @@ -2021,7 +2018,7 @@ static void micro_qr_m3(struct zint_symbol *symbol, char binary_data[], const in data_blocks[10] = 0; for (j = 0; j < 4; j++) { if (binary_data[80 + j] == '1') { - data_blocks[10] += 0x80 >> j; + data_blocks[10] |= 0x80 >> j; } } } @@ -2030,7 +2027,7 @@ static void micro_qr_m3(struct zint_symbol *symbol, char binary_data[], const in data_blocks[8] = 0; for (j = 0; j < 4; j++) { if (binary_data[64 + j] == '1') { - data_blocks[8] += 0x80 >> j; + data_blocks[8] |= 0x80 >> j; } } } @@ -2041,10 +2038,9 @@ static void micro_qr_m3(struct zint_symbol *symbol, char binary_data[], const in #endif /* Calculate Reed-Solomon error codewords */ - rs_init_gf(0x11d); - rs_init_code(ecc_codewords, 0); - rs_encode(data_codewords, data_blocks, ecc_blocks); - rs_free(); + rs_init_gf(&rs, 0x11d); + rs_init_code(&rs, ecc_codewords, 0); + rs_encode(&rs, data_codewords, data_blocks, ecc_blocks); /* Add Reed-Solomon codewords to binary data */ for (i = 0; i < ecc_codewords; i++) { @@ -2059,6 +2055,7 @@ static void micro_qr_m4(struct zint_symbol *symbol, char binary_data[], const in int bits_total=0, bits_left; int data_codewords=0, ecc_codewords=0; unsigned char data_blocks[17], ecc_blocks[15]; + rs_t rs; latch = 0; @@ -2122,7 +2119,7 @@ static void micro_qr_m4(struct zint_symbol *symbol, char binary_data[], const in for (j = 0; j < 8; j++) { if (binary_data[(i * 8) + j] == '1') { - data_blocks[i] += 0x80 >> j; + data_blocks[i] |= 0x80 >> j; } } } @@ -2133,10 +2130,9 @@ static void micro_qr_m4(struct zint_symbol *symbol, char binary_data[], const in #endif /* Calculate Reed-Solomon error codewords */ - rs_init_gf(0x11d); - rs_init_code(ecc_codewords, 0); - rs_encode(data_codewords, data_blocks, ecc_blocks); - rs_free(); + rs_init_gf(&rs, 0x11d); + rs_init_code(&rs, ecc_codewords, 0); + rs_encode(&rs, data_codewords, data_blocks, ecc_blocks); /* Add Reed-Solomon codewords to binary data */ for (i = 0; i < ecc_codewords; i++) { @@ -2144,7 +2140,7 @@ static void micro_qr_m4(struct zint_symbol *symbol, char binary_data[], const in } } -static void micro_setup_grid(unsigned char* grid,const int size) { +static void micro_setup_grid(unsigned char *grid, const int size) { int i, toggle = 1; /* Add timing patterns */ @@ -2173,16 +2169,16 @@ static void micro_setup_grid(unsigned char* grid,const int size) { /* Reserve space for format information */ for (i = 0; i < 8; i++) { - grid[(8 * size) + i] += 0x20; - grid[(i * size) + 8] += 0x20; + grid[(8 * size) + i] |= 0x20; + grid[(i * size) + 8] |= 0x20; } - 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 direction = 1; /* up */ int row = 0; /* right hand side */ - size_t n, i; + int n, i; int y; n = strlen(full_stream); @@ -2231,7 +2227,7 @@ static void micro_populate_grid(unsigned char* grid,const int size,const char fu } while (i < n); } -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) { int sum1, sum2, i, filter = 0, retval; switch (pattern) { @@ -2265,81 +2261,86 @@ static int micro_evaluate(const unsigned char *grid,const int size,const int pat return retval; } -static int micro_apply_bitmask(unsigned char *grid,const int size) { +static int micro_apply_bitmask(unsigned char *grid, const int size, const int user_mask, const int debug_print) { int x, y; - unsigned char p; - int pattern, value[8]; - int best_val, best_pattern; + int r, k; + int bit; + int pattern, value[4]; + int best_pattern; + int size_squared = size * size; #ifndef _MSC_VER - unsigned char mask[size * size]; - unsigned char eval[size * size]; + unsigned char mask[size_squared]; + unsigned char eval[size_squared]; #else - unsigned char* mask = (unsigned char *) _alloca((size * size) * sizeof (unsigned char)); - unsigned char* eval = (unsigned char *) _alloca((size * size) * sizeof (unsigned char)); + unsigned char *mask = (unsigned char *) _alloca(size_squared * sizeof (unsigned char)); + unsigned char *eval = (unsigned char *) _alloca(size_squared * sizeof (unsigned char)); #endif /* Perform data masking */ - for (x = 0; x < size; x++) { - for (y = 0; y < size; y++) { - mask[(y * size) + x] = 0x00; + memset(mask, 0, size_squared); + for (y = 0; y < size; y++) { + r = y * size; + for (x = 0; x < size; x++) { - if (!(grid[(y * size) + x] & 0xf0)) { + if (!(grid[r + x] & 0xf0)) { if ((y & 1) == 0) { - mask[(y * size) + x] += 0x01; + mask[r + x] |= 0x01; } if ((((y / 2) + (x / 3)) & 1) == 0) { - mask[(y * size) + x] += 0x02; + mask[r + x] |= 0x02; } if (((((y * x) & 1) + ((y * x) % 3)) & 1) == 0) { - mask[(y * size) + x] += 0x04; + mask[r + x] |= 0x04; } if (((((y + x) & 1) + ((y * x) % 3)) & 1) == 0) { - mask[(y * size) + x] += 0x08; + mask[r + x] |= 0x08; } } } } - for (x = 0; x < size; x++) { - for (y = 0; y < size; y++) { - if (grid[(y * size) + x] & 0x01) { - p = 0xff; + if (user_mask) { + best_pattern = user_mask - 1; + } else { + for (k = 0; k < size_squared; k++) { + if (grid[k] & 0x01) { + eval[k] = mask[k] ^ 0xff; } else { - p = 0x00; + eval[k] = mask[k]; } + } - eval[(y * size) + x] = mask[(y * size) + x] ^ p; + + /* Evaluate result */ + best_pattern = 0; + for (pattern = 0; pattern < 4; pattern++) { + value[pattern] = micro_evaluate(eval, size, pattern); + if (value[pattern] > value[best_pattern]) { + best_pattern = pattern; + } } } - - /* Evaluate result */ - for (pattern = 0; pattern < 8; pattern++) { - value[pattern] = micro_evaluate(eval, size, pattern); - } - - best_pattern = 0; - best_val = value[0]; - for (pattern = 1; pattern < 4; pattern++) { - if (value[pattern] > best_val) { - best_pattern = pattern; - best_val = value[pattern]; + if (debug_print) { + printf("Mask: %d (%s)", best_pattern, user_mask ? "specified" : "automatic"); + if (!user_mask) { + for (pattern = 0; pattern < 4; pattern++) printf(" %d:%d", pattern, value[pattern]); } + printf("\n"); } /* Apply mask */ - for (x = 0; x < size; x++) { - for (y = 0; y < size; y++) { - if (mask[(y * size) + x] & (0x01 << best_pattern)) { - if (grid[(y * size) + x] & 0x01) { - grid[(y * size) + x] = 0x00; - } else { - grid[(y * size) + x] = 0x01; - } + bit = 1 << best_pattern; + for (k = 0; k < size_squared; k++) { + if (mask[k] & bit) { + if (grid[k] & 0x01) { + grid[k] = 0x00; + } else { + grid[k] = 0x01; } } } @@ -2347,10 +2348,11 @@ static int micro_apply_bitmask(unsigned char *grid,const int size) { return best_pattern; } -INTERNAL int microqr(struct zint_symbol *symbol, const unsigned char source[], size_t length) { - size_t i, size, j; +INTERNAL int microqr(struct zint_symbol *symbol, unsigned char source[], int length) { + int i, size, j; char full_stream[200]; int full_multibyte; + int user_mask; unsigned int jisdata[40]; char mode[40]; @@ -2359,6 +2361,8 @@ INTERNAL int microqr(struct zint_symbol *symbol, const unsigned char source[], s int binary_count[4]; int ecc_level, autoversion, version; int bitmask, format, format_full; + int size_squared; + int debug_print = symbol->debug & ZINT_DEBUG_PRINT; #ifdef _MSC_VER unsigned char* grid; #endif @@ -2388,7 +2392,12 @@ INTERNAL int microqr(struct zint_symbol *symbol, const unsigned char source[], s ecc_level = symbol->option_1; } - full_multibyte = symbol->option_3 == ZINT_FULL_MULTIBYTE; /* If set use Kanji mode in DATA_MODE or for single-byte Latin */ + /* If ZINT_FULL_MULTIBYTE use Kanji mode in DATA_MODE or for single-byte Latin */ + full_multibyte = (symbol->option_3 & 0xFF) == ZINT_FULL_MULTIBYTE; + user_mask = (symbol->option_3 >> 8) & 0x0F; /* User mask is pattern + 1, so >= 1 and <= 4 */ + if (user_mask > 4) { + user_mask = 0; /* Ignore */ + } if ((symbol->input_mode & 0x07) == DATA_MODE) { sjis_cpy(source, &length, jisdata, full_multibyte); @@ -2439,7 +2448,7 @@ INTERNAL int microqr(struct zint_symbol *symbol, const unsigned char source[], s /* Determine length of binary data */ for (i = 0; i < 4; i++) { if (version_valid[i]) { - binary_count[i] = getBinaryLength(MICROQR_VERSION + i, mode, jisdata, length, 0 /*gs1*/, 0 /*eci*/, symbol->debug); + binary_count[i] = getBinaryLength(MICROQR_VERSION + i, mode, jisdata, length, 0 /*gs1*/, 0 /*eci*/, debug_print); } else { binary_count[i] = 128 + 1; } @@ -2521,9 +2530,10 @@ INTERNAL int microqr(struct zint_symbol *symbol, const unsigned char source[], s } } - qr_define_mode(mode, jisdata, length, 0 /*gs1*/, MICROQR_VERSION + version, symbol->debug); + 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, 0 /*gs1*/, 0 /*eci*/, binary_count[version], symbol->debug); + qr_binary((unsigned char *) full_stream, MICROQR_VERSION + version, 0 /*target_codewords*/, mode, jisdata, length, + 0 /*gs1*/, 0 /*eci*/, binary_count[version], debug_print); switch (version) { case 0: micro_qr_m1(symbol, full_stream); @@ -2537,21 +2547,18 @@ INTERNAL int microqr(struct zint_symbol *symbol, const unsigned char source[], s } size = micro_qr_sizes[version]; + size_squared = size * size; #ifndef _MSC_VER - unsigned char grid[size * size]; + unsigned char grid[size_squared]; #else - grid = (unsigned char *) _alloca((size * size) * sizeof (unsigned char)); + grid = (unsigned char *) _alloca(size_squared * sizeof (unsigned char)); #endif - for (i = 0; i < size; i++) { - for (j = 0; j < size; j++) { - grid[(i * size) + j] = 0; - } - } + memset(grid, 0, size_squared); micro_setup_grid(grid, size); micro_populate_grid(grid, size, full_stream); - bitmask = micro_apply_bitmask(grid, size); + bitmask = micro_apply_bitmask(grid, size, user_mask, debug_print); /* Add format data */ format = 0; @@ -2584,49 +2591,49 @@ INTERNAL int microqr(struct zint_symbol *symbol, const unsigned char source[], s format_full = qr_annex_c1[(format << 2) + bitmask]; if (format_full & 0x4000) { - grid[(8 * size) + 1] += 0x01; + grid[(8 * size) + 1] |= 0x01; } if (format_full & 0x2000) { - grid[(8 * size) + 2] += 0x01; + grid[(8 * size) + 2] |= 0x01; } if (format_full & 0x1000) { - grid[(8 * size) + 3] += 0x01; + grid[(8 * size) + 3] |= 0x01; } if (format_full & 0x800) { - grid[(8 * size) + 4] += 0x01; + grid[(8 * size) + 4] |= 0x01; } if (format_full & 0x400) { - grid[(8 * size) + 5] += 0x01; + grid[(8 * size) + 5] |= 0x01; } if (format_full & 0x200) { - grid[(8 * size) + 6] += 0x01; + grid[(8 * size) + 6] |= 0x01; } if (format_full & 0x100) { - grid[(8 * size) + 7] += 0x01; + grid[(8 * size) + 7] |= 0x01; } if (format_full & 0x80) { - grid[(8 * size) + 8] += 0x01; + grid[(8 * size) + 8] |= 0x01; } if (format_full & 0x40) { - grid[(7 * size) + 8] += 0x01; + grid[(7 * size) + 8] |= 0x01; } if (format_full & 0x20) { - grid[(6 * size) + 8] += 0x01; + grid[(6 * size) + 8] |= 0x01; } if (format_full & 0x10) { - grid[(5 * size) + 8] += 0x01; + grid[(5 * size) + 8] |= 0x01; } if (format_full & 0x08) { - grid[(4 * size) + 8] += 0x01; + grid[(4 * size) + 8] |= 0x01; } if (format_full & 0x04) { - grid[(3 * size) + 8] += 0x01; + grid[(3 * size) + 8] |= 0x01; } if (format_full & 0x02) { - grid[(2 * size) + 8] += 0x01; + grid[(2 * size) + 8] |= 0x01; } if (format_full & 0x01) { - grid[(1 * size) + 8] += 0x01; + grid[(1 * size) + 8] |= 0x01; } symbol->width = size; @@ -2645,10 +2652,12 @@ INTERNAL int microqr(struct zint_symbol *symbol, const unsigned char source[], s } /* For UPNQR the symbol size and error correction capacity is fixed */ -INTERNAL int upnqr(struct zint_symbol *symbol, const unsigned char source[], size_t length) { - int i, j, est_binlen; +INTERNAL int upnqr(struct zint_symbol *symbol, unsigned char source[], int length) { + int i, j, r, est_binlen; int ecc_level, version, target_codewords, blocks, size; int bitmask, error_number; + int size_squared; + int debug_print = symbol->debug & ZINT_DEBUG_PRINT; #ifndef _MSC_VER unsigned int jisdata[length + 1]; @@ -2672,7 +2681,7 @@ INTERNAL int upnqr(struct zint_symbol *symbol, const unsigned char source[], siz switch (symbol->input_mode & 0x07) { case DATA_MODE: /* Input is already in ISO-8859-2 format */ - for (i = 0; i < (int) length; i++) { + for (i = 0; i < length; i++) { jisdata[i] = source[i]; mode[i] = 'B'; } @@ -2687,14 +2696,14 @@ INTERNAL int upnqr(struct zint_symbol *symbol, const unsigned char source[], siz strcpy(symbol->errtxt, "572: Invalid characters in input data"); return error_number; } - for (i = 0; i < (int) length; i++) { + for (i = 0; i < length; i++) { jisdata[i] = preprocessed[i]; mode[i] = 'B'; } break; } - est_binlen = getBinaryLength(15, mode, jisdata, length, 0, symbol->eci, symbol->debug); + est_binlen = getBinaryLength(15, mode, jisdata, length, 0, symbol->eci, debug_print); ecc_level = LEVEL_M; @@ -2715,31 +2724,28 @@ INTERNAL int upnqr(struct zint_symbol *symbol, const unsigned char source[], siz fullstream = (unsigned char *) _alloca(qr_total_codewords[version - 1] + 1); #endif - qr_binary(datastream, version, target_codewords, mode, jisdata, length, 0, symbol->eci, est_binlen, symbol->debug); + qr_binary(datastream, version, target_codewords, mode, jisdata, length, 0, symbol->eci, est_binlen, debug_print); #ifdef ZINT_TEST if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); #endif - add_ecc(fullstream, datastream, version, target_codewords, blocks, symbol->debug); + add_ecc(fullstream, datastream, version, target_codewords, blocks, debug_print); size = qr_sizes[version - 1]; + size_squared = size * size; #ifndef _MSC_VER - unsigned char grid[size * size]; + unsigned char grid[size_squared]; #else - grid = (unsigned char *) _alloca((size * size) * sizeof (unsigned char)); + grid = (unsigned char *) _alloca(size_squared * sizeof (unsigned char)); #endif - for (i = 0; i < size; i++) { - for (j = 0; j < size; j++) { - grid[(i * size) + j] = 0; - } - } + memset(grid, 0, size_squared); setup_grid(grid, size, version); populate_grid(grid, size, size, fullstream, qr_total_codewords[version - 1]); add_version_info(grid, size, version); - bitmask = apply_bitmask(grid, size, ecc_level); + bitmask = apply_bitmask(grid, size, ecc_level, 0 /*user_mask*/, debug_print); add_format_info(grid, size, ecc_level, bitmask); @@ -2747,8 +2753,9 @@ INTERNAL int upnqr(struct zint_symbol *symbol, const unsigned char source[], siz symbol->rows = size; for (i = 0; i < size; i++) { + r = i * size; for (j = 0; j < size; j++) { - if (grid[(i * size) + j] & 0x01) { + if (grid[r + j] & 0x01) { set_module(symbol, i, j); } } @@ -2822,11 +2829,11 @@ static void setup_rmqr_grid(unsigned char* grid, const int h_size, const int v_s /* Add alignment patterns */ if (h_size > 27) { - h_version = 0; // Suppress compiler warning [-Wmaybe-uninitialized] + h_version = 0; // Suppress compiler warning [-Wmaybe-uninitialized] for(i = 0; i < 5; i++) { if (h_size == rmqr_width[i]) { h_version = i; - break; + break; } } @@ -2873,13 +2880,14 @@ static void setup_rmqr_grid(unsigned char* grid, const int h_size, const int v_s } /* rMQR according to 2018 draft standard */ -INTERNAL int rmqr(struct zint_symbol *symbol, const unsigned char source[], size_t length) { +INTERNAL int rmqr(struct zint_symbol *symbol, unsigned char source[], int length) { int i, j, est_binlen; int ecc_level, autosize, version, max_cw, target_codewords, blocks, h_size, v_size; int gs1; int full_multibyte; int footprint, best_footprint, format_data; unsigned int left_format_info, right_format_info; + int debug_print = symbol->debug & ZINT_DEBUG_PRINT; #ifndef _MSC_VER unsigned int jisdata[length + 1]; @@ -2893,7 +2901,8 @@ INTERNAL int rmqr(struct zint_symbol *symbol, const unsigned char source[], size #endif gs1 = ((symbol->input_mode & 0x07) == GS1_MODE); - full_multibyte = symbol->option_3 == ZINT_FULL_MULTIBYTE; /* If set use Kanji mode in DATA_MODE or for single-byte Latin */ + /* If ZINT_FULL_MULTIBYTE use Kanji mode in DATA_MODE or for single-byte Latin */ + full_multibyte = (symbol->option_3 & 0xFF) == ZINT_FULL_MULTIBYTE; if ((symbol->input_mode & 0x07) == DATA_MODE) { sjis_cpy(source, &length, jisdata, full_multibyte); @@ -2909,7 +2918,7 @@ INTERNAL int rmqr(struct zint_symbol *symbol, const unsigned char source[], size } } - est_binlen = getBinaryLength(RMQR_VERSION + 31, mode, jisdata, length, gs1, 0 /*eci*/, symbol->debug); + est_binlen = getBinaryLength(RMQR_VERSION + 31, mode, jisdata, length, gs1, 0 /*eci*/, debug_print); ecc_level = LEVEL_M; max_cw = 152; @@ -2945,7 +2954,7 @@ INTERNAL int rmqr(struct zint_symbol *symbol, const unsigned char source[], size autosize = 31; best_footprint = rmqr_height[31] * rmqr_width[31]; for (version = 30; version >= 0; version--) { - est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, 0 /*eci*/, symbol->debug); + est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, 0 /*eci*/, debug_print); footprint = rmqr_height[version] * rmqr_width[version]; if (ecc_level == LEVEL_M) { if (8 * rmqr_data_codewords_M[version] >= est_binlen) { @@ -2964,20 +2973,20 @@ INTERNAL int rmqr(struct zint_symbol *symbol, const unsigned char source[], size } } version = autosize; - est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, 0 /*eci*/, symbol->debug); + est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, 0 /*eci*/, debug_print); } if ((symbol->option_2 >= 1) && (symbol->option_2 <= 32)) { // User specified symbol size version = symbol->option_2 - 1; - est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, 0 /*eci*/, symbol->debug); + est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, 0 /*eci*/, debug_print); } if (symbol->option_2 >= 33) { // User has specified symbol height only version = rmqr_fixed_height_upper_bound[symbol->option_2 - 32]; for(i = version - 1; i > rmqr_fixed_height_upper_bound[symbol->option_2 - 33]; i--) { - est_binlen = getBinaryLength(RMQR_VERSION + i, mode, jisdata, length, gs1, 0 /*eci*/, symbol->debug); + est_binlen = getBinaryLength(RMQR_VERSION + i, mode, jisdata, length, gs1, 0 /*eci*/, debug_print); if (ecc_level == LEVEL_M) { if (8 * rmqr_data_codewords_M[i] >= est_binlen) { version = i; @@ -2988,7 +2997,7 @@ INTERNAL int rmqr(struct zint_symbol *symbol, const unsigned char source[], size } } } - est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, 0 /*eci*/, symbol->debug); + est_binlen = getBinaryLength(RMQR_VERSION + version, mode, jisdata, length, gs1, 0 /*eci*/, debug_print); } if (symbol->option_1 == -1) { @@ -3012,7 +3021,7 @@ INTERNAL int rmqr(struct zint_symbol *symbol, const unsigned char source[], size return ZINT_ERROR_TOO_LONG; } - if (symbol->debug & ZINT_DEBUG_PRINT) { + if (debug_print) { printf("Minimum codewords = %d\n", est_binlen / 8); printf("Selected version: %d = R%dx%d-", (version + 1), rmqr_height[version], rmqr_width[version]); if (ecc_level == LEVEL_M) { @@ -3032,11 +3041,11 @@ INTERNAL int rmqr(struct zint_symbol *symbol, const unsigned char source[], size fullstream = (unsigned char *) _alloca((rmqr_total_codewords[version] + 1) * sizeof (unsigned char)); #endif - qr_binary(datastream, RMQR_VERSION + version, target_codewords, mode, jisdata, length, gs1, 0 /*eci*/, est_binlen, symbol->debug); + qr_binary(datastream, RMQR_VERSION + version, target_codewords, mode, jisdata, length, gs1, 0 /*eci*/, est_binlen, debug_print); #ifdef ZINT_TEST if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, datastream, target_codewords); #endif - add_ecc(fullstream, datastream, RMQR_VERSION + version, target_codewords, blocks, symbol->debug); + add_ecc(fullstream, datastream, RMQR_VERSION + version, target_codewords, blocks, debug_print); h_size = rmqr_width[version]; v_size = rmqr_height[version]; @@ -3047,26 +3056,23 @@ INTERNAL int rmqr(struct zint_symbol *symbol, const unsigned char source[], size grid = (unsigned char *) _alloca((h_size * v_size) * sizeof (unsigned char)); #endif - for (i = 0; i < v_size; i++) { - for (j = 0; j < h_size; j++) { - grid[(i * h_size) + j] = 0; - } - } + memset(grid, 0, h_size * v_size); setup_rmqr_grid(grid, h_size, v_size); populate_grid(grid, h_size, v_size, fullstream, rmqr_total_codewords[version]); /* apply bitmask */ for (i = 0; i < v_size; i++) { + int r = i * h_size; for (j = 0; j < h_size; j++) { - if ((grid[(i * h_size) + j] & 0xf0) == 0) { + if ((grid[r + j] & 0xf0) == 0) { // This is a data module if (((i / 2) + (j / 3)) % 2 == 0) { // < This is the data mask from section 7.8.2 // This module needs to be changed - if (grid[(i * h_size) + j] == 0x01) { - grid[(i * h_size) + j] = 0x00; + if (grid[r + j] == 0x01) { + grid[r + j] = 0x00; } else { - grid[(i * h_size) + j] = 0x01; + grid[r + j] = 0x01; } } } @@ -3099,8 +3105,9 @@ INTERNAL int rmqr(struct zint_symbol *symbol, const unsigned char source[], size symbol->rows = v_size; for (i = 0; i < v_size; i++) { + int r = i * h_size; for (j = 0; j < h_size; j++) { - if (grid[(i * h_size) + j] & 0x01) { + if (grid[r + j] & 0x01) { set_module(symbol, i, j); } } diff --git a/backend/qr.h b/backend/qr.h index b19ded60..32281c0a 100644 --- a/backend/qr.h +++ b/backend/qr.h @@ -1,7 +1,7 @@ /* qr.h Data for QR Code, Micro QR Code and rMQR libzint - the open source barcode library - Copyright (C) 2008-2019 Robin Stuart + Copyright (C) 2008 - 2020 Robin Stuart Copyright (C) 2006 Kentaro Fukuchi Redistribution and use in source and binary forms, with or without @@ -35,12 +35,20 @@ #define LEVEL_Q 3 #define LEVEL_H 4 -#define RHODIUM "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:" +#define QR_PERCENT 38 /* Alphanumeric mode % */ + +/* From ISO/IEC 18004:2015 Table 5 Encoding/decoding table for Alphanumeric mode */ +static const char qr_alphanumeric[59] = { + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, /* SP-/ */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, /* 0-? */ + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* @-O */ + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35 /* P-Z */ +}; #define RMQR_VERSION 100 #define MICROQR_VERSION 200 -/* From ISO/IEC 18004:2006 Table 7 */ +/* From ISO/IEC 18004:2015 Table 7 */ static const unsigned short int qr_data_codewords_L[] = { 19, 34, 55, 80, 108, 136, 156, 194, 232, 274, 324, 370, 428, 461, 523, 589, 647, 721, 795, 861, 932, 1006, 1094, 1174, 1276, 1370, 1468, 1531, 1631, diff --git a/backend/raster.c b/backend/raster.c index 94463db9..a71f3d27 100644 --- a/backend/raster.c +++ b/backend/raster.c @@ -82,7 +82,7 @@ static int buffer_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) { NULL, blue, cyan, NULL, NULL, NULL, green, NULL, NULL, NULL, black, NULL, magenta, /* A-M */ NULL, NULL, NULL, NULL, red, NULL, NULL, NULL, NULL, white, NULL, yellow, NULL /* N-Z */ }; - int row, column, p; + int row, column; int plot_alpha = 0; unsigned char *bitmap; @@ -130,7 +130,7 @@ static int buffer_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) { return ZINT_ERROR_MEMORY; } for (row = 0; row < symbol->bitmap_height; row++) { - p = row * symbol->bitmap_width; + int p = row * symbol->bitmap_width; bitmap = symbol->bitmap + p * 3; for (column = 0; column < symbol->bitmap_width; column++, p++, bitmap += 3) { memcpy(bitmap, map[pixelbuf[p]], 3); @@ -139,10 +139,11 @@ static int buffer_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) { } } else { for (row = 0; row < symbol->bitmap_height; row++) { - p = row * symbol->bitmap_width; - bitmap = symbol->bitmap + p * 3; - for (column = 0; column < symbol->bitmap_width; column++, p++, bitmap += 3) { - memcpy(bitmap, map[pixelbuf[p]], 3); + int r = row * symbol->bitmap_width; + unsigned char *pb = pixelbuf + r; + bitmap = symbol->bitmap + r * 3; + for (column = 0; column < symbol->bitmap_width; column++, pb++, bitmap += 3) { + memcpy(bitmap, map[*pb], 3); } } } @@ -470,7 +471,6 @@ static void draw_string(unsigned char *pixbuf, unsigned char input_string[], int if (odd_si) { x_incr += i * letter_width / 2; } - // NOLINTNEXTLINE(clang-analyzer-core.CallAndMessage) suppress (probable) false positive about 2nd arg input_string[i] being uninitialized draw_letter(pixbuf, input_string[i], string_left_hand + x_incr, yposn, textflags, image_width, image_height, si); } } @@ -1063,7 +1063,7 @@ static int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int } if (!textdone) { - unsigned char local_text[sizeof(symbol->text)]; + unsigned char local_text[sizeof(symbol->text)] = {0}; /* Suppress clang-analyzer-core.CallAndMessage warning */ to_iso8859_1(symbol->text, local_text); /* Put the human readable text at the bottom */ textpos = (main_width / 2 + xoffset) * si; diff --git a/backend/reedsol.c b/backend/reedsol.c index 67e6b89f..4308e7a6 100644 --- a/backend/reedsol.c +++ b/backend/reedsol.c @@ -37,9 +37,9 @@ // // Usage: -// First call rs_init_gf(poly) to set up the Galois Field parameters. -// Then call rs_init_code(size, index) to set the encoding size -// Then call rs_encode(datasize, data, out) to encode the data. +// First call rs_init_gf(&rs, prime_poly) to set up the Galois Field parameters. +// Then call rs_init_code(&rs, nsym, index) to set the encoding size +// Then call rs_encode(&rs, datalen, data, out) to encode the data. // // These can be called repeatedly as required - but note that // rs_init_code must be called following any rs_init_gf call. @@ -48,129 +48,220 @@ // replaced with constants in the obvious way, and additionally // malloc/free can be avoided by using static arrays of a suitable // size. +// Note: use of statics has been done for (up to) 8-bit tables. #ifdef _MSC_VER #include #endif -#include #include "common.h" #include "reedsol.h" -static int logmod; // 2**symsize - 1 -static int rlen; +#include "reedsol_logs.h" -static int *logt = NULL, *alog = NULL, *rspoly = NULL; - -// rs_init_gf(poly) initialises the parameters for the Galois Field. +// rs_init_gf(&rs, prime_poly) initialises the parameters for the Galois Field. // The symbol size is determined from the highest bit set in poly -// This implementation will support sizes up to 30 bits (though that -// will result in very large log/antilog tables) - bit sizes of -// 8 or 4 are typical +// This implementation will support sizes up to 8 bits (see rs_unit_init_gf() +// for sizes > 8 bits and <= 30 bits) - bit sizes of 8 or 4 are typical // // The poly is the bit pattern representing the GF characteristic // polynomial. e.g. for ECC200 (8-bit symbols) the polynomial is // a**8 + a**5 + a**3 + a**2 + 1, which translates to 0x12d. -INTERNAL void rs_init_gf(const int poly) { - int m, b, p, v; +INTERNAL void rs_init_gf(rs_t *rs, const unsigned int prime_poly) { + struct item { + const unsigned char *logt; + const unsigned char *alog; + }; + /* To add a new prime poly of degree <= 8 add its details to this table and to the table in `test_generate()` + * in "backend/tests/test_reedsol.c" and regenerate the log tables by running "./test_reedsol -f generate -g". + * Paste the result in "reedsol_logs.h" */ + static const struct item data[] = { + { logt_0x13, alog_0x13 }, /* 0 000- */ + { logt_0x25, alog_0x25 }, /* 0 001- */ + { logt_0x43, alog_0x43 }, /* 0 010- */ + { NULL, NULL }, + { logt_0x89, alog_0x89 }, /* 0 100- */ + { NULL, NULL }, + { NULL, NULL }, + { NULL, NULL }, + { logt_0x11d, alog_0x11d }, /* 1 000- */ + { logt_0x12d, alog_0x12d }, /* 1 001- */ + { NULL, NULL }, + { logt_0x163, alog_0x163 }, /* 1 011- */ + }; - // Suppress clang-tidy clang-analyzer-core.UndefinedBinaryOperatorResult warning - assert(poly >= 2); + /* Using bits 9-6 as hash to save a few cycles */ + /* Alter this hash or just iterate if new prime poly added that doesn't fit */ + unsigned int hash = prime_poly >> 5; - // Find the top bit, and hence the symbol size - for (b = 1, m = 0; b <= poly; b <<= 1) - m++; - b >>= 1; - m--; - - // Ensure m not negative to supress gcc -Walloc-size-larger-than - if (m < 0) { - m = 0; - } - - // Calculate the log/alog tables - logmod = (1 << m) - 1; - logt = (int *) malloc(sizeof (int) * (logmod + 1)); - alog = (int *) malloc(sizeof (int) * logmod); - - for (p = 1, v = 0; v < logmod; v++) { - alog[v] = p; - logt[p] = v; - p <<= 1; - if (p & b) - p ^= poly; - } + rs->logt = data[hash].logt; + rs->alog = data[hash].alog; } -// rs_init_code(nsym, index) initialises the Reed-Solomon encoder +// rs_init_code(&rs, nsym, index) initialises the Reed-Solomon encoder // nsym is the number of symbols to be generated (to be appended // to the input data). index is usually 1 - it is the index of // the constant in the first term (i) of the RS generator polynomial: // (x + 2**i)*(x + 2**(i+1))*... [nsym terms] // For ECC200, index is 1. -INTERNAL void rs_init_code(const int nsym, int index) { +#include +INTERNAL void rs_init_code(rs_t *rs, const int nsym, int index) { int i, k; + const unsigned char *logt = rs->logt; + const unsigned char *alog = rs->alog; + unsigned char *rspoly = rs->rspoly; - rspoly = (int *) malloc(sizeof (int) * (nsym + 1)); - - rlen = nsym; + rs->nsym = nsym; rspoly[0] = 1; for (i = 1; i <= nsym; i++) { rspoly[i] = 1; for (k = i - 1; k > 0; k--) { if (rspoly[k]) - rspoly[k] = alog[(logt[rspoly[k]] + index) % logmod]; - rspoly[k] ^= rspoly[k - 1]; + rspoly[k] = alog[logt[rspoly[k]] + index]; /* Multiply coeff by 2**index */ + rspoly[k] ^= rspoly[k - 1]; /* Add coeff of x**(k-1) * x */ } - rspoly[0] = alog[(logt[rspoly[0]] + index) % logmod]; + rspoly[0] = alog[logt[rspoly[0]] + index]; /* 2**(i + (i+1) + ... + index) */ index++; } } -INTERNAL void rs_encode(const size_t len, const unsigned char *data, unsigned char *res) { +/* rs_encode(&rs, datalen, data, res) generates nsym Reed-Solomon codes (nsym as given in rs_init_code()) + * 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) { int i, k; - for (i = 0; i < rlen; i++) - res[i] = 0; - for (i = 0; i < (int) len; i++) { - int m = res[rlen - 1] ^ data[i]; - for (k = rlen - 1; k > 0; k--) { - if (m && rspoly[k]) - res[k] = (unsigned char) (res[k - 1] ^ alog[(logt[m] + logt[rspoly[k]]) % logmod]); - else - res[k] = res[k - 1]; - } - if (m && rspoly[0]) - res[0] = (unsigned char) (alog[(logt[m] + logt[rspoly[0]]) % logmod]); - else + const unsigned char *logt = rs->logt; + const unsigned char *alog = rs->alog; + const unsigned char *rspoly = rs->rspoly; + const int nsym = rs->nsym; + + memset(res, 0, nsym); + for (i = 0; i < datalen; i++) { + unsigned int m = res[nsym - 1] ^ data[i]; + if (m) { + unsigned int log_m = logt[m]; + for (k = nsym - 1; k > 0; k--) { + if (rspoly[k]) + res[k] = (unsigned char) (res[k - 1] ^ alog[log_m + logt[rspoly[k]]]); + else + res[k] = res[k - 1]; + } + res[0] = alog[log_m + logt[rspoly[0]]]; /* rspoly[0] can't be zero */ + } else { + memmove(res + 1, res, nsym - 1); res[0] = 0; + } } } -/* The same as above but for larger bitlengths - Aztec code compatible */ -INTERNAL void rs_encode_long(const int len, const unsigned int *data, unsigned int *res) { +/* The same as above but for unsigned int data and result - Aztec code compatible */ + +INTERNAL void rs_encode_uint(const rs_t *rs, const int datalen, const unsigned int *data, unsigned int *res) { int i, k; - for (i = 0; i < rlen; i++) - res[i] = 0; - for (i = 0; i < len; i++) { - int m = res[rlen - 1] ^ data[i]; - for (k = rlen - 1; k > 0; k--) { - if (m && rspoly[k]) - res[k] = res[k - 1] ^ alog[(logt[m] + logt[rspoly[k]]) % logmod]; - else - res[k] = res[k - 1]; - } - if (m && rspoly[0]) - res[0] = alog[(logt[m] + logt[rspoly[0]]) % logmod]; - else + const unsigned char *logt = rs->logt; + const unsigned char *alog = rs->alog; + const unsigned char *rspoly = rs->rspoly; + const int nsym = rs->nsym; + + memset(res, 0, sizeof(unsigned int) * nsym); + for (i = 0; i < datalen; i++) { + unsigned int m = res[nsym - 1] ^ data[i]; + if (m) { + unsigned int log_m = logt[m]; + for (k = nsym - 1; k > 0; k--) { + if (rspoly[k]) + res[k] = res[k - 1] ^ alog[log_m + logt[rspoly[k]]]; + else + res[k] = res[k - 1]; + } + res[0] = alog[log_m + logt[rspoly[0]]]; + } else { + memmove(res + 1, res, sizeof(unsigned int) * (nsym - 1)); res[0] = 0; + } } } -/* Free memory */ -INTERNAL void rs_free(void) { - free(logt); - free(alog); - free(rspoly); - rspoly = NULL; +/* Versions of the above for bitlengths > 8 and <= 30 and unsigned int data and results - Aztec code compatible */ + +// Usage: +// First call rs_uint_init_gf(&rs_uint, prime_poly, logmod) to set up the Galois Field parameters. +// Then call rs_uint_init_code(&rs_uint, nsym, index) to set the encoding size +// Then call rs_uint_encode(&rs_uint, datalen, data, out) to encode the data. +// Then call rs_uint_free(&rs_uint) to free the log tables. + +/* `logmod` (field characteristic) will be 2**bitlength - 1, eg 1023 for bitlength 10, 4095 for bitlength 12 */ +INTERNAL void rs_uint_init_gf(rs_uint_t *rs_uint, const unsigned int prime_poly, const int logmod) { + int b, p, v; + unsigned int *logt, *alog; + + b = logmod + 1; + + logt = (unsigned int *) malloc(sizeof(unsigned int) * b); + alog = (unsigned int *) malloc(sizeof(unsigned int) * b * 2); + + // Calculate the log/alog tables + for (p = 1, v = 0; v < logmod; v++) { + alog[v] = p; + alog[logmod + v] = p; /* Double up, avoids mod */ + logt[p] = v; + p <<= 1; + if (p & b) /* If overflow */ + p ^= prime_poly; /* Subtract prime poly */ + } + rs_uint->logt = logt; + rs_uint->alog = alog; +} + +INTERNAL void rs_uint_init_code(rs_uint_t *rs_uint, const int nsym, int index) { + int i, k; + const unsigned int *logt = rs_uint->logt; + const unsigned int *alog = rs_uint->alog; + unsigned short *rspoly = rs_uint->rspoly; + + rs_uint->nsym = nsym; + + rspoly[0] = 1; + for (i = 1; i <= nsym; i++) { + rspoly[i] = 1; + for (k = i - 1; k > 0; k--) { + if (rspoly[k]) + rspoly[k] = alog[(logt[rspoly[k]] + index)]; + rspoly[k] ^= rspoly[k - 1]; + } + rspoly[0] = alog[(logt[rspoly[0]] + index)]; + index++; + } +} + +INTERNAL void rs_uint_encode(const rs_uint_t *rs_uint, const int datalen, const unsigned int *data, unsigned int *res) { + int i, k; + const unsigned int *logt = rs_uint->logt; + const unsigned int *alog = rs_uint->alog; + const unsigned short *rspoly = rs_uint->rspoly; + const int nsym = rs_uint->nsym; + + memset(res, 0, sizeof(unsigned int) * nsym); + for (i = 0; i < datalen; i++) { + unsigned int m = res[nsym - 1] ^ data[i]; + if (m) { + unsigned int log_m = logt[m]; + for (k = nsym - 1; k > 0; k--) { + if (rspoly[k]) + res[k] = res[k - 1] ^ alog[log_m + logt[rspoly[k]]]; + else + res[k] = res[k - 1]; + } + res[0] = alog[log_m + logt[rspoly[0]]]; + } else { + memmove(res + 1, res, sizeof(unsigned int) * (nsym - 1)); + res[0] = 0; + } + } +} + +INTERNAL void rs_uint_free(rs_uint_t *rs_uint) { + free(rs_uint->logt); + free(rs_uint->alog); } diff --git a/backend/reedsol.h b/backend/reedsol.h index d0703c9d..d7187625 100644 --- a/backend/reedsol.h +++ b/backend/reedsol.h @@ -38,14 +38,33 @@ extern "C" { #endif /* __cplusplus */ -INTERNAL void rs_init_gf(const int poly); -INTERNAL void rs_init_code(const int nsym,int index); -INTERNAL void rs_encode(const size_t len,const unsigned char *data, unsigned char *res); -INTERNAL void rs_encode_long(const int len,const unsigned int *data, unsigned int *res); -INTERNAL void rs_free(void); +typedef struct { + const unsigned char *logt; /* These are static */ + const unsigned char *alog; + unsigned char rspoly[256]; + int nsym; +} rs_t; + +typedef struct { + unsigned int *logt; /* These are malloced */ + unsigned int *alog; + unsigned short rspoly[4096]; /* 12-bit max - needs to be enlarged if > 12-bit used */ + int nsym; +} rs_uint_t; + +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_encode(const rs_t *rs, const int datalen, const unsigned char *data, unsigned char *res); +INTERNAL void rs_encode_uint(const rs_t *rs, const int datalen, const unsigned int *data, unsigned int *res); +/* No free needed as log tables static */ + +INTERNAL void rs_uint_init_gf(rs_uint_t *rs_uint, const unsigned int prime_poly, const int logmod); +INTERNAL void rs_uint_init_code(rs_uint_t *rs_uint, const int nsym, int index); +INTERNAL void rs_uint_encode(const rs_uint_t *rs_uint, const int datalen, const unsigned int *data, unsigned int *res); +INTERNAL void rs_uint_free(rs_uint_t *rs_uint); #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* __REEDSOL_H */ +#endif /* __REEDSOL_H */ diff --git a/backend/reedsol_logs.h b/backend/reedsol_logs.h new file mode 100644 index 00000000..945db287 --- /dev/null +++ b/backend/reedsol_logs.h @@ -0,0 +1,264 @@ +/* reedsol_logs.h - Log and antilog tables for Reed-Solomon + + libzint - the open source barcode library + Copyright (C) 2020 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + */ +/* vim: set ts=4 sw=4 et : */ + +#ifndef REEDSOL_LOGS_H +#define REEDSOL_LOGS_H + +/* Static log/antilog tables for prime polys of up to degree 8 (> 8 too large so generated at runtime instead). + * Antilog tables doubled to avoid mod. */ + +/* Paste output of "./test_reedsol -f generate -g" here */ +static const unsigned char logt_0x13[16] = { + 0x00, 0x00, 0x01, 0x04, 0x02, 0x08, 0x05, 0x0A, 0x03, 0x0E, 0x09, 0x07, 0x06, 0x0D, 0x0B, 0x0C, +}; +static const unsigned char alog_0x13[30] = { + 0x01, 0x02, 0x04, 0x08, 0x03, 0x06, 0x0C, 0x0B, 0x05, 0x0A, 0x07, 0x0E, 0x0F, 0x0D, 0x09, + 0x01, 0x02, 0x04, 0x08, 0x03, 0x06, 0x0C, 0x0B, 0x05, 0x0A, 0x07, 0x0E, 0x0F, 0x0D, 0x09, +}; + +static const unsigned char logt_0x25[32] = { + 0x00, 0x00, 0x01, 0x12, 0x02, 0x05, 0x13, 0x0B, 0x03, 0x1D, 0x06, 0x1B, 0x14, 0x08, 0x0C, 0x17, + 0x04, 0x0A, 0x1E, 0x11, 0x07, 0x16, 0x1C, 0x1A, 0x15, 0x19, 0x09, 0x10, 0x0D, 0x0E, 0x18, 0x0F, +}; +static const unsigned char alog_0x25[62] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x05, 0x0A, 0x14, 0x0D, 0x1A, 0x11, 0x07, 0x0E, 0x1C, 0x1D, 0x1F, + 0x1B, 0x13, 0x03, 0x06, 0x0C, 0x18, 0x15, 0x0F, 0x1E, 0x19, 0x17, 0x0B, 0x16, 0x09, 0x12, + 0x01, 0x02, 0x04, 0x08, 0x10, 0x05, 0x0A, 0x14, 0x0D, 0x1A, 0x11, 0x07, 0x0E, 0x1C, 0x1D, 0x1F, + 0x1B, 0x13, 0x03, 0x06, 0x0C, 0x18, 0x15, 0x0F, 0x1E, 0x19, 0x17, 0x0B, 0x16, 0x09, 0x12, +}; + +static const unsigned char logt_0x43[64] = { + 0x00, 0x00, 0x01, 0x06, 0x02, 0x0C, 0x07, 0x1A, 0x03, 0x20, 0x0D, 0x23, 0x08, 0x30, 0x1B, 0x12, + 0x04, 0x18, 0x21, 0x10, 0x0E, 0x34, 0x24, 0x36, 0x09, 0x2D, 0x31, 0x26, 0x1C, 0x29, 0x13, 0x38, + 0x05, 0x3E, 0x19, 0x0B, 0x22, 0x1F, 0x11, 0x2F, 0x0F, 0x17, 0x35, 0x33, 0x25, 0x2C, 0x37, 0x28, + 0x0A, 0x3D, 0x2E, 0x1E, 0x32, 0x16, 0x27, 0x2B, 0x1D, 0x3C, 0x2A, 0x15, 0x14, 0x3B, 0x39, 0x3A, +}; +static const unsigned char alog_0x43[126] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x23, 0x05, 0x0A, 0x14, 0x28, + 0x13, 0x26, 0x0F, 0x1E, 0x3C, 0x3B, 0x35, 0x29, 0x11, 0x22, 0x07, 0x0E, 0x1C, 0x38, 0x33, 0x25, + 0x09, 0x12, 0x24, 0x0B, 0x16, 0x2C, 0x1B, 0x36, 0x2F, 0x1D, 0x3A, 0x37, 0x2D, 0x19, 0x32, 0x27, + 0x0D, 0x1A, 0x34, 0x2B, 0x15, 0x2A, 0x17, 0x2E, 0x1F, 0x3E, 0x3F, 0x3D, 0x39, 0x31, 0x21, + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x23, 0x05, 0x0A, 0x14, 0x28, + 0x13, 0x26, 0x0F, 0x1E, 0x3C, 0x3B, 0x35, 0x29, 0x11, 0x22, 0x07, 0x0E, 0x1C, 0x38, 0x33, 0x25, + 0x09, 0x12, 0x24, 0x0B, 0x16, 0x2C, 0x1B, 0x36, 0x2F, 0x1D, 0x3A, 0x37, 0x2D, 0x19, 0x32, 0x27, + 0x0D, 0x1A, 0x34, 0x2B, 0x15, 0x2A, 0x17, 0x2E, 0x1F, 0x3E, 0x3F, 0x3D, 0x39, 0x31, 0x21, +}; + +static const unsigned char logt_0x89[128] = { + 0x00, 0x00, 0x01, 0x1F, 0x02, 0x3E, 0x20, 0x67, 0x03, 0x07, 0x3F, 0x0F, 0x21, 0x54, 0x68, 0x5D, + 0x04, 0x7C, 0x08, 0x79, 0x40, 0x4F, 0x10, 0x73, 0x22, 0x0B, 0x55, 0x26, 0x69, 0x2E, 0x5E, 0x33, + 0x05, 0x52, 0x7D, 0x3C, 0x09, 0x2C, 0x7A, 0x4D, 0x41, 0x43, 0x50, 0x2A, 0x11, 0x45, 0x74, 0x17, + 0x23, 0x76, 0x0C, 0x1C, 0x56, 0x19, 0x27, 0x39, 0x6A, 0x13, 0x2F, 0x59, 0x5F, 0x47, 0x34, 0x6E, + 0x06, 0x0E, 0x53, 0x5C, 0x7E, 0x1E, 0x3D, 0x66, 0x0A, 0x25, 0x2D, 0x32, 0x7B, 0x78, 0x4E, 0x72, + 0x42, 0x29, 0x44, 0x16, 0x51, 0x3B, 0x2B, 0x4C, 0x12, 0x58, 0x46, 0x6D, 0x75, 0x1B, 0x18, 0x38, + 0x24, 0x31, 0x77, 0x71, 0x0D, 0x5B, 0x1D, 0x65, 0x57, 0x6C, 0x1A, 0x37, 0x28, 0x15, 0x3A, 0x4B, + 0x6B, 0x36, 0x14, 0x4A, 0x30, 0x70, 0x5A, 0x64, 0x60, 0x61, 0x48, 0x62, 0x35, 0x49, 0x6F, 0x63, +}; +static const unsigned char alog_0x89[254] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x09, 0x12, 0x24, 0x48, 0x19, 0x32, 0x64, 0x41, 0x0B, + 0x16, 0x2C, 0x58, 0x39, 0x72, 0x6D, 0x53, 0x2F, 0x5E, 0x35, 0x6A, 0x5D, 0x33, 0x66, 0x45, 0x03, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0x49, 0x1B, 0x36, 0x6C, 0x51, 0x2B, 0x56, 0x25, 0x4A, 0x1D, 0x3A, + 0x74, 0x61, 0x4B, 0x1F, 0x3E, 0x7C, 0x71, 0x6B, 0x5F, 0x37, 0x6E, 0x55, 0x23, 0x46, 0x05, 0x0A, + 0x14, 0x28, 0x50, 0x29, 0x52, 0x2D, 0x5A, 0x3D, 0x7A, 0x7D, 0x73, 0x6F, 0x57, 0x27, 0x4E, 0x15, + 0x2A, 0x54, 0x21, 0x42, 0x0D, 0x1A, 0x34, 0x68, 0x59, 0x3B, 0x76, 0x65, 0x43, 0x0F, 0x1E, 0x3C, + 0x78, 0x79, 0x7B, 0x7F, 0x77, 0x67, 0x47, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0x69, 0x5B, 0x3F, 0x7E, + 0x75, 0x63, 0x4F, 0x17, 0x2E, 0x5C, 0x31, 0x62, 0x4D, 0x13, 0x26, 0x4C, 0x11, 0x22, 0x44, + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x09, 0x12, 0x24, 0x48, 0x19, 0x32, 0x64, 0x41, 0x0B, + 0x16, 0x2C, 0x58, 0x39, 0x72, 0x6D, 0x53, 0x2F, 0x5E, 0x35, 0x6A, 0x5D, 0x33, 0x66, 0x45, 0x03, + 0x06, 0x0C, 0x18, 0x30, 0x60, 0x49, 0x1B, 0x36, 0x6C, 0x51, 0x2B, 0x56, 0x25, 0x4A, 0x1D, 0x3A, + 0x74, 0x61, 0x4B, 0x1F, 0x3E, 0x7C, 0x71, 0x6B, 0x5F, 0x37, 0x6E, 0x55, 0x23, 0x46, 0x05, 0x0A, + 0x14, 0x28, 0x50, 0x29, 0x52, 0x2D, 0x5A, 0x3D, 0x7A, 0x7D, 0x73, 0x6F, 0x57, 0x27, 0x4E, 0x15, + 0x2A, 0x54, 0x21, 0x42, 0x0D, 0x1A, 0x34, 0x68, 0x59, 0x3B, 0x76, 0x65, 0x43, 0x0F, 0x1E, 0x3C, + 0x78, 0x79, 0x7B, 0x7F, 0x77, 0x67, 0x47, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0x69, 0x5B, 0x3F, 0x7E, + 0x75, 0x63, 0x4F, 0x17, 0x2E, 0x5C, 0x31, 0x62, 0x4D, 0x13, 0x26, 0x4C, 0x11, 0x22, 0x44, +}; + +static const unsigned char logt_0x11d[256] = { + 0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1A, 0xC6, 0x03, 0xDF, 0x33, 0xEE, 0x1B, 0x68, 0xC7, 0x4B, + 0x04, 0x64, 0xE0, 0x0E, 0x34, 0x8D, 0xEF, 0x81, 0x1C, 0xC1, 0x69, 0xF8, 0xC8, 0x08, 0x4C, 0x71, + 0x05, 0x8A, 0x65, 0x2F, 0xE1, 0x24, 0x0F, 0x21, 0x35, 0x93, 0x8E, 0xDA, 0xF0, 0x12, 0x82, 0x45, + 0x1D, 0xB5, 0xC2, 0x7D, 0x6A, 0x27, 0xF9, 0xB9, 0xC9, 0x9A, 0x09, 0x78, 0x4D, 0xE4, 0x72, 0xA6, + 0x06, 0xBF, 0x8B, 0x62, 0x66, 0xDD, 0x30, 0xFD, 0xE2, 0x98, 0x25, 0xB3, 0x10, 0x91, 0x22, 0x88, + 0x36, 0xD0, 0x94, 0xCE, 0x8F, 0x96, 0xDB, 0xBD, 0xF1, 0xD2, 0x13, 0x5C, 0x83, 0x38, 0x46, 0x40, + 0x1E, 0x42, 0xB6, 0xA3, 0xC3, 0x48, 0x7E, 0x6E, 0x6B, 0x3A, 0x28, 0x54, 0xFA, 0x85, 0xBA, 0x3D, + 0xCA, 0x5E, 0x9B, 0x9F, 0x0A, 0x15, 0x79, 0x2B, 0x4E, 0xD4, 0xE5, 0xAC, 0x73, 0xF3, 0xA7, 0x57, + 0x07, 0x70, 0xC0, 0xF7, 0x8C, 0x80, 0x63, 0x0D, 0x67, 0x4A, 0xDE, 0xED, 0x31, 0xC5, 0xFE, 0x18, + 0xE3, 0xA5, 0x99, 0x77, 0x26, 0xB8, 0xB4, 0x7C, 0x11, 0x44, 0x92, 0xD9, 0x23, 0x20, 0x89, 0x2E, + 0x37, 0x3F, 0xD1, 0x5B, 0x95, 0xBC, 0xCF, 0xCD, 0x90, 0x87, 0x97, 0xB2, 0xDC, 0xFC, 0xBE, 0x61, + 0xF2, 0x56, 0xD3, 0xAB, 0x14, 0x2A, 0x5D, 0x9E, 0x84, 0x3C, 0x39, 0x53, 0x47, 0x6D, 0x41, 0xA2, + 0x1F, 0x2D, 0x43, 0xD8, 0xB7, 0x7B, 0xA4, 0x76, 0xC4, 0x17, 0x49, 0xEC, 0x7F, 0x0C, 0x6F, 0xF6, + 0x6C, 0xA1, 0x3B, 0x52, 0x29, 0x9D, 0x55, 0xAA, 0xFB, 0x60, 0x86, 0xB1, 0xBB, 0xCC, 0x3E, 0x5A, + 0xCB, 0x59, 0x5F, 0xB0, 0x9C, 0xA9, 0xA0, 0x51, 0x0B, 0xF5, 0x16, 0xEB, 0x7A, 0x75, 0x2C, 0xD7, + 0x4F, 0xAE, 0xD5, 0xE9, 0xE6, 0xE7, 0xAD, 0xE8, 0x74, 0xD6, 0xF4, 0xEA, 0xA8, 0x50, 0x58, 0xAF, +}; +static const unsigned char alog_0x11d[510] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1D, 0x3A, 0x74, 0xE8, 0xCD, 0x87, 0x13, 0x26, + 0x4C, 0x98, 0x2D, 0x5A, 0xB4, 0x75, 0xEA, 0xC9, 0x8F, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, + 0x9D, 0x27, 0x4E, 0x9C, 0x25, 0x4A, 0x94, 0x35, 0x6A, 0xD4, 0xB5, 0x77, 0xEE, 0xC1, 0x9F, 0x23, + 0x46, 0x8C, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x5D, 0xBA, 0x69, 0xD2, 0xB9, 0x6F, 0xDE, 0xA1, + 0x5F, 0xBE, 0x61, 0xC2, 0x99, 0x2F, 0x5E, 0xBC, 0x65, 0xCA, 0x89, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, + 0xFD, 0xE7, 0xD3, 0xBB, 0x6B, 0xD6, 0xB1, 0x7F, 0xFE, 0xE1, 0xDF, 0xA3, 0x5B, 0xB6, 0x71, 0xE2, + 0xD9, 0xAF, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xBD, 0x67, 0xCE, + 0x81, 0x1F, 0x3E, 0x7C, 0xF8, 0xED, 0xC7, 0x93, 0x3B, 0x76, 0xEC, 0xC5, 0x97, 0x33, 0x66, 0xCC, + 0x85, 0x17, 0x2E, 0x5C, 0xB8, 0x6D, 0xDA, 0xA9, 0x4F, 0x9E, 0x21, 0x42, 0x84, 0x15, 0x2A, 0x54, + 0xA8, 0x4D, 0x9A, 0x29, 0x52, 0xA4, 0x55, 0xAA, 0x49, 0x92, 0x39, 0x72, 0xE4, 0xD5, 0xB7, 0x73, + 0xE6, 0xD1, 0xBF, 0x63, 0xC6, 0x91, 0x3F, 0x7E, 0xFC, 0xE5, 0xD7, 0xB3, 0x7B, 0xF6, 0xF1, 0xFF, + 0xE3, 0xDB, 0xAB, 0x4B, 0x96, 0x31, 0x62, 0xC4, 0x95, 0x37, 0x6E, 0xDC, 0xA5, 0x57, 0xAE, 0x41, + 0x82, 0x19, 0x32, 0x64, 0xC8, 0x8D, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xDD, 0xA7, 0x53, 0xA6, + 0x51, 0xA2, 0x59, 0xB2, 0x79, 0xF2, 0xF9, 0xEF, 0xC3, 0x9B, 0x2B, 0x56, 0xAC, 0x45, 0x8A, 0x09, + 0x12, 0x24, 0x48, 0x90, 0x3D, 0x7A, 0xF4, 0xF5, 0xF7, 0xF3, 0xFB, 0xEB, 0xCB, 0x8B, 0x0B, 0x16, + 0x2C, 0x58, 0xB0, 0x7D, 0xFA, 0xE9, 0xCF, 0x83, 0x1B, 0x36, 0x6C, 0xD8, 0xAD, 0x47, 0x8E, + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1D, 0x3A, 0x74, 0xE8, 0xCD, 0x87, 0x13, 0x26, + 0x4C, 0x98, 0x2D, 0x5A, 0xB4, 0x75, 0xEA, 0xC9, 0x8F, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, + 0x9D, 0x27, 0x4E, 0x9C, 0x25, 0x4A, 0x94, 0x35, 0x6A, 0xD4, 0xB5, 0x77, 0xEE, 0xC1, 0x9F, 0x23, + 0x46, 0x8C, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x5D, 0xBA, 0x69, 0xD2, 0xB9, 0x6F, 0xDE, 0xA1, + 0x5F, 0xBE, 0x61, 0xC2, 0x99, 0x2F, 0x5E, 0xBC, 0x65, 0xCA, 0x89, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, + 0xFD, 0xE7, 0xD3, 0xBB, 0x6B, 0xD6, 0xB1, 0x7F, 0xFE, 0xE1, 0xDF, 0xA3, 0x5B, 0xB6, 0x71, 0xE2, + 0xD9, 0xAF, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xBD, 0x67, 0xCE, + 0x81, 0x1F, 0x3E, 0x7C, 0xF8, 0xED, 0xC7, 0x93, 0x3B, 0x76, 0xEC, 0xC5, 0x97, 0x33, 0x66, 0xCC, + 0x85, 0x17, 0x2E, 0x5C, 0xB8, 0x6D, 0xDA, 0xA9, 0x4F, 0x9E, 0x21, 0x42, 0x84, 0x15, 0x2A, 0x54, + 0xA8, 0x4D, 0x9A, 0x29, 0x52, 0xA4, 0x55, 0xAA, 0x49, 0x92, 0x39, 0x72, 0xE4, 0xD5, 0xB7, 0x73, + 0xE6, 0xD1, 0xBF, 0x63, 0xC6, 0x91, 0x3F, 0x7E, 0xFC, 0xE5, 0xD7, 0xB3, 0x7B, 0xF6, 0xF1, 0xFF, + 0xE3, 0xDB, 0xAB, 0x4B, 0x96, 0x31, 0x62, 0xC4, 0x95, 0x37, 0x6E, 0xDC, 0xA5, 0x57, 0xAE, 0x41, + 0x82, 0x19, 0x32, 0x64, 0xC8, 0x8D, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xDD, 0xA7, 0x53, 0xA6, + 0x51, 0xA2, 0x59, 0xB2, 0x79, 0xF2, 0xF9, 0xEF, 0xC3, 0x9B, 0x2B, 0x56, 0xAC, 0x45, 0x8A, 0x09, + 0x12, 0x24, 0x48, 0x90, 0x3D, 0x7A, 0xF4, 0xF5, 0xF7, 0xF3, 0xFB, 0xEB, 0xCB, 0x8B, 0x0B, 0x16, + 0x2C, 0x58, 0xB0, 0x7D, 0xFA, 0xE9, 0xCF, 0x83, 0x1B, 0x36, 0x6C, 0xD8, 0xAD, 0x47, 0x8E, +}; + +static const unsigned char logt_0x12d[256] = { + 0x00, 0x00, 0x01, 0xF0, 0x02, 0xE1, 0xF1, 0x35, 0x03, 0x26, 0xE2, 0x85, 0xF2, 0x2B, 0x36, 0xD2, + 0x04, 0xC3, 0x27, 0x72, 0xE3, 0x6A, 0x86, 0x1C, 0xF3, 0x8C, 0x2C, 0x17, 0x37, 0x76, 0xD3, 0xEA, + 0x05, 0xDB, 0xC4, 0x60, 0x28, 0xDE, 0x73, 0x67, 0xE4, 0x4E, 0x6B, 0x7D, 0x87, 0x08, 0x1D, 0xA2, + 0xF4, 0xBA, 0x8D, 0xB4, 0x2D, 0x63, 0x18, 0x31, 0x38, 0x0D, 0x77, 0x99, 0xD4, 0xC7, 0xEB, 0x5B, + 0x06, 0x4C, 0xDC, 0xD9, 0xC5, 0x0B, 0x61, 0xB8, 0x29, 0x24, 0xDF, 0xFD, 0x74, 0x8A, 0x68, 0xC1, + 0xE5, 0x56, 0x4F, 0xAB, 0x6C, 0xA5, 0x7E, 0x91, 0x88, 0x22, 0x09, 0x4A, 0x1E, 0x20, 0xA3, 0x54, + 0xF5, 0xAD, 0xBB, 0xCC, 0x8E, 0x51, 0xB5, 0xBE, 0x2E, 0x58, 0x64, 0x9F, 0x19, 0xE7, 0x32, 0xCF, + 0x39, 0x93, 0x0E, 0x43, 0x78, 0x80, 0x9A, 0xF8, 0xD5, 0xA7, 0xC8, 0x3F, 0xEC, 0x6E, 0x5C, 0xB0, + 0x07, 0xA1, 0x4D, 0x7C, 0xDD, 0x66, 0xDA, 0x5F, 0xC6, 0x5A, 0x0C, 0x98, 0x62, 0x30, 0xB9, 0xB3, + 0x2A, 0xD1, 0x25, 0x84, 0xE0, 0x34, 0xFE, 0xEF, 0x75, 0xE9, 0x8B, 0x16, 0x69, 0x1B, 0xC2, 0x71, + 0xE6, 0xCE, 0x57, 0x9E, 0x50, 0xBD, 0xAC, 0xCB, 0x6D, 0xAF, 0xA6, 0x3E, 0x7F, 0xF7, 0x92, 0x42, + 0x89, 0xC0, 0x23, 0xFC, 0x0A, 0xB7, 0x4B, 0xD8, 0x1F, 0x53, 0x21, 0x49, 0xA4, 0x90, 0x55, 0xAA, + 0xF6, 0x41, 0xAE, 0x3D, 0xBC, 0xCA, 0xCD, 0x9D, 0x8F, 0xA9, 0x52, 0x48, 0xB6, 0xD7, 0xBF, 0xFB, + 0x2F, 0xB2, 0x59, 0x97, 0x65, 0x5E, 0xA0, 0x7B, 0x1A, 0x70, 0xE8, 0x15, 0x33, 0xEE, 0xD0, 0x83, + 0x3A, 0x45, 0x94, 0x12, 0x0F, 0x10, 0x44, 0x11, 0x79, 0x95, 0x81, 0x13, 0x9B, 0x3B, 0xF9, 0x46, + 0xD6, 0xFA, 0xA8, 0x47, 0xC9, 0x9C, 0x40, 0x3C, 0xED, 0x82, 0x6F, 0x14, 0x5D, 0x7A, 0xB1, 0x96, +}; +static const unsigned char alog_0x12d[510] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x2D, 0x5A, 0xB4, 0x45, 0x8A, 0x39, 0x72, 0xE4, + 0xE5, 0xE7, 0xE3, 0xEB, 0xFB, 0xDB, 0x9B, 0x1B, 0x36, 0x6C, 0xD8, 0x9D, 0x17, 0x2E, 0x5C, 0xB8, + 0x5D, 0xBA, 0x59, 0xB2, 0x49, 0x92, 0x09, 0x12, 0x24, 0x48, 0x90, 0x0D, 0x1A, 0x34, 0x68, 0xD0, + 0x8D, 0x37, 0x6E, 0xDC, 0x95, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xED, 0xF7, 0xC3, 0xAB, 0x7B, + 0xF6, 0xC1, 0xAF, 0x73, 0xE6, 0xE1, 0xEF, 0xF3, 0xCB, 0xBB, 0x5B, 0xB6, 0x41, 0x82, 0x29, 0x52, + 0xA4, 0x65, 0xCA, 0xB9, 0x5F, 0xBE, 0x51, 0xA2, 0x69, 0xD2, 0x89, 0x3F, 0x7E, 0xFC, 0xD5, 0x87, + 0x23, 0x46, 0x8C, 0x35, 0x6A, 0xD4, 0x85, 0x27, 0x4E, 0x9C, 0x15, 0x2A, 0x54, 0xA8, 0x7D, 0xFA, + 0xD9, 0x9F, 0x13, 0x26, 0x4C, 0x98, 0x1D, 0x3A, 0x74, 0xE8, 0xFD, 0xD7, 0x83, 0x2B, 0x56, 0xAC, + 0x75, 0xEA, 0xF9, 0xDF, 0x93, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x4D, 0x9A, 0x19, 0x32, 0x64, 0xC8, + 0xBD, 0x57, 0xAE, 0x71, 0xE2, 0xE9, 0xFF, 0xD3, 0x8B, 0x3B, 0x76, 0xEC, 0xF5, 0xC7, 0xA3, 0x6B, + 0xD6, 0x81, 0x2F, 0x5E, 0xBC, 0x55, 0xAA, 0x79, 0xF2, 0xC9, 0xBF, 0x53, 0xA6, 0x61, 0xC2, 0xA9, + 0x7F, 0xFE, 0xD1, 0x8F, 0x33, 0x66, 0xCC, 0xB5, 0x47, 0x8E, 0x31, 0x62, 0xC4, 0xA5, 0x67, 0xCE, + 0xB1, 0x4F, 0x9E, 0x11, 0x22, 0x44, 0x88, 0x3D, 0x7A, 0xF4, 0xC5, 0xA7, 0x63, 0xC6, 0xA1, 0x6F, + 0xDE, 0x91, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xCD, 0xB7, 0x43, 0x86, 0x21, 0x42, 0x84, 0x25, 0x4A, + 0x94, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x6D, 0xDA, 0x99, 0x1F, 0x3E, 0x7C, 0xF8, 0xDD, 0x97, + 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xAD, 0x77, 0xEE, 0xF1, 0xCF, 0xB3, 0x4B, 0x96, + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x2D, 0x5A, 0xB4, 0x45, 0x8A, 0x39, 0x72, 0xE4, + 0xE5, 0xE7, 0xE3, 0xEB, 0xFB, 0xDB, 0x9B, 0x1B, 0x36, 0x6C, 0xD8, 0x9D, 0x17, 0x2E, 0x5C, 0xB8, + 0x5D, 0xBA, 0x59, 0xB2, 0x49, 0x92, 0x09, 0x12, 0x24, 0x48, 0x90, 0x0D, 0x1A, 0x34, 0x68, 0xD0, + 0x8D, 0x37, 0x6E, 0xDC, 0x95, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xED, 0xF7, 0xC3, 0xAB, 0x7B, + 0xF6, 0xC1, 0xAF, 0x73, 0xE6, 0xE1, 0xEF, 0xF3, 0xCB, 0xBB, 0x5B, 0xB6, 0x41, 0x82, 0x29, 0x52, + 0xA4, 0x65, 0xCA, 0xB9, 0x5F, 0xBE, 0x51, 0xA2, 0x69, 0xD2, 0x89, 0x3F, 0x7E, 0xFC, 0xD5, 0x87, + 0x23, 0x46, 0x8C, 0x35, 0x6A, 0xD4, 0x85, 0x27, 0x4E, 0x9C, 0x15, 0x2A, 0x54, 0xA8, 0x7D, 0xFA, + 0xD9, 0x9F, 0x13, 0x26, 0x4C, 0x98, 0x1D, 0x3A, 0x74, 0xE8, 0xFD, 0xD7, 0x83, 0x2B, 0x56, 0xAC, + 0x75, 0xEA, 0xF9, 0xDF, 0x93, 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x4D, 0x9A, 0x19, 0x32, 0x64, 0xC8, + 0xBD, 0x57, 0xAE, 0x71, 0xE2, 0xE9, 0xFF, 0xD3, 0x8B, 0x3B, 0x76, 0xEC, 0xF5, 0xC7, 0xA3, 0x6B, + 0xD6, 0x81, 0x2F, 0x5E, 0xBC, 0x55, 0xAA, 0x79, 0xF2, 0xC9, 0xBF, 0x53, 0xA6, 0x61, 0xC2, 0xA9, + 0x7F, 0xFE, 0xD1, 0x8F, 0x33, 0x66, 0xCC, 0xB5, 0x47, 0x8E, 0x31, 0x62, 0xC4, 0xA5, 0x67, 0xCE, + 0xB1, 0x4F, 0x9E, 0x11, 0x22, 0x44, 0x88, 0x3D, 0x7A, 0xF4, 0xC5, 0xA7, 0x63, 0xC6, 0xA1, 0x6F, + 0xDE, 0x91, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xCD, 0xB7, 0x43, 0x86, 0x21, 0x42, 0x84, 0x25, 0x4A, + 0x94, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x6D, 0xDA, 0x99, 0x1F, 0x3E, 0x7C, 0xF8, 0xDD, 0x97, + 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xAD, 0x77, 0xEE, 0xF1, 0xCF, 0xB3, 0x4B, 0x96, +}; + +static const unsigned char logt_0x163[256] = { + 0x00, 0x00, 0x01, 0xC5, 0x02, 0x8B, 0xC6, 0x6C, 0x03, 0x32, 0x8C, 0xC0, 0xC7, 0x25, 0x6D, 0x51, + 0x04, 0x17, 0x33, 0xEE, 0x8D, 0xD8, 0xC1, 0xEA, 0xC8, 0x0C, 0x26, 0xF7, 0x6E, 0x86, 0x52, 0x7C, + 0x05, 0x42, 0x18, 0x91, 0x34, 0x73, 0xEF, 0x4C, 0x8E, 0xCE, 0xD9, 0xD1, 0xC2, 0xBD, 0xEB, 0xF4, + 0xC9, 0x2D, 0x0D, 0xDC, 0x27, 0xB4, 0xF8, 0xA4, 0x6F, 0xB0, 0x87, 0xD4, 0x53, 0x1E, 0x7D, 0x9E, + 0x06, 0x64, 0x43, 0x37, 0x19, 0x81, 0x92, 0xE3, 0x35, 0xE1, 0x74, 0x76, 0xF0, 0x9A, 0x4D, 0x78, + 0x8F, 0x4A, 0xCF, 0xF2, 0xDA, 0xA2, 0xD2, 0x9C, 0xC3, 0x6A, 0xBE, 0x4F, 0xEC, 0xE8, 0xF5, 0x7A, + 0xCA, 0xAC, 0x2E, 0x08, 0x0E, 0x57, 0xDD, 0x66, 0x28, 0x12, 0xB5, 0x45, 0xF9, 0x5E, 0xA5, 0x39, + 0x70, 0xBA, 0xB1, 0x1B, 0x88, 0x22, 0xD5, 0x83, 0x54, 0x5B, 0x1F, 0x94, 0x7E, 0x97, 0x9F, 0xE5, + 0x07, 0xAB, 0x65, 0x56, 0x44, 0x11, 0x38, 0x5D, 0x1A, 0xB9, 0x82, 0x21, 0x93, 0x5A, 0xE4, 0x96, + 0x36, 0x63, 0xE2, 0x80, 0x75, 0xE0, 0x77, 0x99, 0xF1, 0x49, 0x9B, 0xA1, 0x4E, 0x69, 0x79, 0xE7, + 0x90, 0x41, 0x4B, 0x72, 0xD0, 0xCD, 0xF3, 0xBC, 0xDB, 0x2C, 0xA3, 0xB3, 0xD3, 0xAF, 0x9D, 0x1D, + 0xC4, 0xFE, 0x6B, 0x8A, 0xBF, 0x31, 0x50, 0x24, 0xED, 0x16, 0xE9, 0xD7, 0xF6, 0x0B, 0x7B, 0x85, + 0xCB, 0x3F, 0xAD, 0x2A, 0x2F, 0xFC, 0x09, 0x14, 0x0F, 0xA9, 0x58, 0xB7, 0xDE, 0x61, 0x67, 0x47, + 0x29, 0x3E, 0x13, 0xFB, 0xB6, 0xA8, 0x46, 0x60, 0xFA, 0x3D, 0x5F, 0xA7, 0xA6, 0x3C, 0x3A, 0x3B, + 0x71, 0x40, 0xBB, 0xCC, 0xB2, 0x2B, 0x1C, 0xAE, 0x89, 0xFD, 0x23, 0x30, 0xD6, 0x15, 0x84, 0x0A, + 0x55, 0xAA, 0x5C, 0x10, 0x20, 0xB8, 0x95, 0x59, 0x7F, 0x62, 0x98, 0xDF, 0xA0, 0x48, 0xE6, 0x68, +}; +static const unsigned char alog_0x163[510] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x63, 0xC6, 0xEF, 0xBD, 0x19, 0x32, 0x64, 0xC8, + 0xF3, 0x85, 0x69, 0xD2, 0xC7, 0xED, 0xB9, 0x11, 0x22, 0x44, 0x88, 0x73, 0xE6, 0xAF, 0x3D, 0x7A, + 0xF4, 0x8B, 0x75, 0xEA, 0xB7, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xC3, 0xE5, 0xA9, 0x31, 0x62, 0xC4, + 0xEB, 0xB5, 0x09, 0x12, 0x24, 0x48, 0x90, 0x43, 0x86, 0x6F, 0xDE, 0xDF, 0xDD, 0xD9, 0xD1, 0xC1, + 0xE1, 0xA1, 0x21, 0x42, 0x84, 0x6B, 0xD6, 0xCF, 0xFD, 0x99, 0x51, 0xA2, 0x27, 0x4E, 0x9C, 0x5B, + 0xB6, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0x83, 0x65, 0xCA, 0xF7, 0x8D, 0x79, 0xF2, 0x87, 0x6D, 0xDA, + 0xD7, 0xCD, 0xF9, 0x91, 0x41, 0x82, 0x67, 0xCE, 0xFF, 0x9D, 0x59, 0xB2, 0x07, 0x0E, 0x1C, 0x38, + 0x70, 0xE0, 0xA3, 0x25, 0x4A, 0x94, 0x4B, 0x96, 0x4F, 0x9E, 0x5F, 0xBE, 0x1F, 0x3E, 0x7C, 0xF8, + 0x93, 0x45, 0x8A, 0x77, 0xEE, 0xBF, 0x1D, 0x3A, 0x74, 0xE8, 0xB3, 0x05, 0x0A, 0x14, 0x28, 0x50, + 0xA0, 0x23, 0x46, 0x8C, 0x7B, 0xF6, 0x8F, 0x7D, 0xFA, 0x97, 0x4D, 0x9A, 0x57, 0xAE, 0x3F, 0x7E, + 0xFC, 0x9B, 0x55, 0xAA, 0x37, 0x6E, 0xDC, 0xDB, 0xD5, 0xC9, 0xF1, 0x81, 0x61, 0xC2, 0xE7, 0xAD, + 0x39, 0x72, 0xE4, 0xAB, 0x35, 0x6A, 0xD4, 0xCB, 0xF5, 0x89, 0x71, 0xE2, 0xA7, 0x2D, 0x5A, 0xB4, + 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xE3, 0xA5, 0x29, 0x52, + 0xA4, 0x2B, 0x56, 0xAC, 0x3B, 0x76, 0xEC, 0xBB, 0x15, 0x2A, 0x54, 0xA8, 0x33, 0x66, 0xCC, 0xFB, + 0x95, 0x49, 0x92, 0x47, 0x8E, 0x7F, 0xFE, 0x9F, 0x5D, 0xBA, 0x17, 0x2E, 0x5C, 0xB8, 0x13, 0x26, + 0x4C, 0x98, 0x53, 0xA6, 0x2F, 0x5E, 0xBC, 0x1B, 0x36, 0x6C, 0xD8, 0xD3, 0xC5, 0xE9, 0xB1, + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x63, 0xC6, 0xEF, 0xBD, 0x19, 0x32, 0x64, 0xC8, + 0xF3, 0x85, 0x69, 0xD2, 0xC7, 0xED, 0xB9, 0x11, 0x22, 0x44, 0x88, 0x73, 0xE6, 0xAF, 0x3D, 0x7A, + 0xF4, 0x8B, 0x75, 0xEA, 0xB7, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xC3, 0xE5, 0xA9, 0x31, 0x62, 0xC4, + 0xEB, 0xB5, 0x09, 0x12, 0x24, 0x48, 0x90, 0x43, 0x86, 0x6F, 0xDE, 0xDF, 0xDD, 0xD9, 0xD1, 0xC1, + 0xE1, 0xA1, 0x21, 0x42, 0x84, 0x6B, 0xD6, 0xCF, 0xFD, 0x99, 0x51, 0xA2, 0x27, 0x4E, 0x9C, 0x5B, + 0xB6, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0x83, 0x65, 0xCA, 0xF7, 0x8D, 0x79, 0xF2, 0x87, 0x6D, 0xDA, + 0xD7, 0xCD, 0xF9, 0x91, 0x41, 0x82, 0x67, 0xCE, 0xFF, 0x9D, 0x59, 0xB2, 0x07, 0x0E, 0x1C, 0x38, + 0x70, 0xE0, 0xA3, 0x25, 0x4A, 0x94, 0x4B, 0x96, 0x4F, 0x9E, 0x5F, 0xBE, 0x1F, 0x3E, 0x7C, 0xF8, + 0x93, 0x45, 0x8A, 0x77, 0xEE, 0xBF, 0x1D, 0x3A, 0x74, 0xE8, 0xB3, 0x05, 0x0A, 0x14, 0x28, 0x50, + 0xA0, 0x23, 0x46, 0x8C, 0x7B, 0xF6, 0x8F, 0x7D, 0xFA, 0x97, 0x4D, 0x9A, 0x57, 0xAE, 0x3F, 0x7E, + 0xFC, 0x9B, 0x55, 0xAA, 0x37, 0x6E, 0xDC, 0xDB, 0xD5, 0xC9, 0xF1, 0x81, 0x61, 0xC2, 0xE7, 0xAD, + 0x39, 0x72, 0xE4, 0xAB, 0x35, 0x6A, 0xD4, 0xCB, 0xF5, 0x89, 0x71, 0xE2, 0xA7, 0x2D, 0x5A, 0xB4, + 0x0B, 0x16, 0x2C, 0x58, 0xB0, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xE3, 0xA5, 0x29, 0x52, + 0xA4, 0x2B, 0x56, 0xAC, 0x3B, 0x76, 0xEC, 0xBB, 0x15, 0x2A, 0x54, 0xA8, 0x33, 0x66, 0xCC, 0xFB, + 0x95, 0x49, 0x92, 0x47, 0x8E, 0x7F, 0xFE, 0x9F, 0x5D, 0xBA, 0x17, 0x2E, 0x5C, 0xB8, 0x13, 0x26, + 0x4C, 0x98, 0x53, 0xA6, 0x2F, 0x5E, 0xBC, 0x1B, 0x36, 0x6C, 0xD8, 0xD3, 0xC5, 0xE9, 0xB1, +}; + +#endif /* REEDSOL_LOGS_H */ diff --git a/backend/sjis.c b/backend/sjis.c index daa8aaeb..ccdf20be 100644 --- a/backend/sjis.c +++ b/backend/sjis.c @@ -52,20 +52,20 @@ * License along with the GNU LIBICONV Library; see the file COPYING.LIB. * If not, see . */ -#include #ifdef _MSC_VER #include #endif #include "common.h" #include "sjis.h" -INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[], size_t *length); /* Convert Unicode to other encodings */ +/* Convert Unicode to other encodings */ +INTERNAL int utf_to_eci(const int eci, const unsigned char source[], unsigned char dest[], int *length); /* * JISX0201.1976-0 (libiconv-1.16/lib/jisx0201.h) */ -static int jisx0201_wctomb(unsigned int* r, unsigned int wc) { +static int jisx0201_wctomb(unsigned int *r, unsigned int wc) { if (wc < 0x0080 && !(wc == 0x005c || wc == 0x007e)) { *r = wc; return 1; @@ -1444,7 +1444,7 @@ static const Summary16 jisx0208_uni2indx_pageff[15] = { { 6877, 0x0000 }, { 6877, 0x0000 }, { 6877, 0x0028 }, }; -static int jisx0208_wctomb(unsigned int* r, unsigned int wc) { +static int jisx0208_wctomb(unsigned int *r, unsigned int wc) { const Summary16 *summary = NULL; if (wc < 0x0100) { summary = &jisx0208_uni2indx_page00[(wc>>4)]; @@ -1484,7 +1484,7 @@ static int jisx0208_wctomb(unsigned int* r, unsigned int wc) { */ /* Returns 1 or 2 on success, 0 if no mapping */ -INTERNAL int sjis_wctomb_zint(unsigned int* r, unsigned int wc) { +INTERNAL int sjis_wctomb_zint(unsigned int *r, unsigned int wc) { int ret; /* Try JIS X 0201-1976. */ @@ -1494,7 +1494,8 @@ INTERNAL int sjis_wctomb_zint(unsigned int* r, unsigned int wc) { } /* Try JIS X 0208-1990. */ - /* ZINT: Note leaving mapping of full-width reverse solidus U+FF3C to 0x815F (duplicate of patched U+005C) to avoid having to regen tables */ + /* ZINT: Note leaving mapping of full-width reverse solidus U+FF3C to 0x815F (duplicate of patched U+005C) to avoid + * having to regen tables */ ret = jisx0208_wctomb(r, wc); if (ret) { return ret; @@ -1515,13 +1516,14 @@ INTERNAL int sjis_wctomb_zint(unsigned int* r, unsigned int wc) { } /* Convert UTF-8 string to Shift JIS and place in array of ints */ -INTERNAL int sjis_utf8tomb(struct zint_symbol *symbol, const unsigned char source[], size_t* p_length, unsigned int* jisdata) { +INTERNAL int sjis_utf8tomb(struct zint_symbol *symbol, const unsigned char source[], int *p_length, + unsigned int *jisdata) { int error_number; unsigned int i, length; #ifndef _MSC_VER unsigned int utfdata[*p_length + 1]; #else - unsigned int* utfdata = (unsigned int*) _alloca((*p_length + 1) * sizeof(unsigned int)); + unsigned int *utfdata = (unsigned int *) _alloca((*p_length + 1) * sizeof(unsigned int)); #endif error_number = utf8_to_unicode(symbol, source, utfdata, p_length, 1 /*disallow_4byte*/); @@ -1540,12 +1542,13 @@ INTERNAL int sjis_utf8tomb(struct zint_symbol *symbol, const unsigned char sourc } /* Convert UTF-8 string to single byte ECI and place in array of ints */ -INTERNAL int sjis_utf8tosb(int eci, const unsigned char source[], size_t* p_length, unsigned int* jisdata, int full_multibyte) { +INTERNAL int sjis_utf8tosb(int eci, const unsigned char source[], int *p_length, unsigned int *jisdata, + int full_multibyte) { int error_number; #ifndef _MSC_VER unsigned char single_byte[*p_length + 1]; #else - unsigned char* single_byte = (unsigned char*) _alloca(*p_length + 1); + unsigned char *single_byte = (unsigned char *) _alloca(*p_length + 1); #endif error_number = utf_to_eci(eci, source, single_byte, p_length); @@ -1559,9 +1562,9 @@ INTERNAL int sjis_utf8tosb(int eci, const unsigned char source[], size_t* p_leng return 0; } -/* If `full_multibyte` set, copy byte input stream to array of ints, putting double-bytes that match QR Kanji mode in a single entry. - * If `full_multibyte` not set, do a straight copy */ -INTERNAL void sjis_cpy(const unsigned char source[], size_t* p_length, unsigned int* jisdata, int full_multibyte) { +/* If `full_multibyte` set, copy byte input stream to array of ints, putting double-bytes that match QR Kanji mode in a + * single entry. If `full_multibyte` not set, do a straight copy */ +INTERNAL void sjis_cpy(const unsigned char source[], int *p_length, unsigned int *jisdata, int full_multibyte) { unsigned int i, j, jis, length; unsigned char c; @@ -1571,7 +1574,8 @@ INTERNAL void sjis_cpy(const unsigned char source[], size_t* p_length, unsigned if (((c >= 0x81 && c <= 0x9F) || (c >= 0xE0 && c <= 0xEB)) && length - i >= 2) { jis = (c << 8) | source[i + 1]; if ((jis >= 0x8140 && jis <= 0x9FFC) || (jis >= 0xE040 && jis <= 0xEBBF)) { - /* This may or may not be valid Shift JIS, but don't care as long as it can be encoded in QR Kanji mode */ + /* This may or may not be valid Shift JIS, but don't care as long as it can be encoded in + * QR Kanji mode */ jisdata[j] = jis; i++; } else { diff --git a/backend/sjis.h b/backend/sjis.h index b019a1b0..4e237391 100644 --- a/backend/sjis.h +++ b/backend/sjis.h @@ -37,10 +37,12 @@ extern "C" { #endif /* __cplusplus */ -INTERNAL int sjis_wctomb_zint(unsigned int* r, unsigned int wc); -INTERNAL int sjis_utf8tomb(struct zint_symbol *symbol, const unsigned char source[], size_t* p_length, unsigned int* jisdata); -INTERNAL int sjis_utf8tosb(int eci, const unsigned char source[], size_t* p_length, unsigned int* jisdata, int full_multibyte); -INTERNAL void sjis_cpy(const unsigned char source[], size_t* p_length, unsigned int* jisdata, int full_multibyte); +INTERNAL int sjis_wctomb_zint(unsigned int *r, unsigned int wc); +INTERNAL int sjis_utf8tomb(struct zint_symbol *symbol, const unsigned char source[], int *p_length, + unsigned int *jisdata); +INTERNAL int sjis_utf8tosb(int eci, const unsigned char source[], int *p_length, unsigned int *jisdata, + int full_multibyte); +INTERNAL void sjis_cpy(const unsigned char source[], int *p_length, unsigned int *jisdata, int full_multibyte); #ifdef __cplusplus } diff --git a/backend/tests/CMakeLists.txt b/backend/tests/CMakeLists.txt index bb3afc14..4aad7f5e 100644 --- a/backend/tests/CMakeLists.txt +++ b/backend/tests/CMakeLists.txt @@ -115,6 +115,7 @@ zint_add_test(print, test_print) zint_add_test(ps, test_ps) zint_add_test(qr, test_qr) zint_add_test(raster, test_raster) +zint_add_test(reedsol, test_reedsol) zint_add_test(rss, test_rss) zint_add_test(sjis, test_sjis) zint_add_test(svg, test_svg) diff --git a/backend/tests/data/emf/ean13_5addon_#185.emf b/backend/tests/data/emf/ean13_5addon_#185.emf new file mode 100644 index 00000000..2898e104 Binary files /dev/null and b/backend/tests/data/emf/ean13_5addon_#185.emf differ diff --git a/backend/tests/data/emf/maxicode_#185.emf b/backend/tests/data/emf/maxicode_#185.emf new file mode 100644 index 00000000..3c77c37c Binary files /dev/null and b/backend/tests/data/emf/maxicode_#185.emf differ diff --git a/backend/tests/data/print/bmp/qr_v1_m.bmp b/backend/tests/data/print/bmp/qr_v1_m.bmp index 868f016a..8a43eacf 100644 Binary files a/backend/tests/data/print/bmp/qr_v1_m.bmp and b/backend/tests/data/print/bmp/qr_v1_m.bmp differ diff --git a/backend/tests/data/print/emf/qr_v1_m.emf b/backend/tests/data/print/emf/qr_v1_m.emf index 2493b9fd..eefe3b04 100644 Binary files a/backend/tests/data/print/emf/qr_v1_m.emf and b/backend/tests/data/print/emf/qr_v1_m.emf differ diff --git a/backend/tests/data/print/eps/qr_v1_m.eps b/backend/tests/data/print/eps/qr_v1_m.eps index ab46ffdc..5c138d3e 100644 --- a/backend/tests/data/print/eps/qr_v1_m.eps +++ b/backend/tests/data/print/eps/qr_v1_m.eps @@ -17,7 +17,7 @@ TE 0.00 0.00 0.00 setrgbcolor 2.00 40.00 TB 0.00 14.00 TR TE -2.00 40.00 TB 18.00 2.00 TR +2.00 40.00 TB 20.00 2.00 TR TE 2.00 40.00 TB 24.00 2.00 TR TE @@ -27,155 +27,147 @@ TE TE 10.00 30.00 TB 12.00 2.00 TR TE -2.00 38.00 TB 16.00 2.00 TR -TE -2.00 38.00 TB 22.00 4.00 TR -TE 10.00 30.00 TB 28.00 2.00 TR TE 10.00 30.00 TB 40.00 2.00 TR TE 6.00 32.00 TB 4.00 6.00 TR TE -2.00 36.00 TB 18.00 2.00 TR +10.00 28.00 TB 16.00 2.00 TR +TE +2.00 36.00 TB 20.00 2.00 TR TE 6.00 32.00 TB 32.00 6.00 TR TE -8.00 28.00 TB 24.00 2.00 TR +2.00 34.00 TB 22.00 2.00 TR TE -2.00 32.00 TB 16.00 4.00 TR +2.00 32.00 TB 20.00 2.00 TR +TE +2.00 32.00 TB 24.00 2.00 TR +TE +2.00 30.00 TB 22.00 2.00 TR TE 2.00 28.00 TB 0.00 14.00 TR TE -2.00 28.00 TB 16.00 2.00 TR -TE 2.00 28.00 TB 20.00 2.00 TR TE +2.00 28.00 TB 24.00 2.00 TR +TE 2.00 28.00 TB 28.00 14.00 TR TE -2.00 26.00 TB 18.00 2.00 TR -TE -2.00 26.00 TB 22.00 4.00 TR +2.00 26.00 TB 16.00 4.00 TR TE 2.00 24.00 TB 0.00 2.00 TR TE -2.00 24.00 TB 4.00 2.00 TR +2.00 24.00 TB 4.00 10.00 TR TE -2.00 24.00 TB 8.00 2.00 TR +2.00 24.00 TB 22.00 2.00 TR TE -2.00 24.00 TB 12.00 2.00 TR +2.00 24.00 TB 28.00 10.00 TR TE -2.00 24.00 TB 18.00 6.00 TR +2.00 22.00 TB 4.00 6.00 TR TE -2.00 24.00 TB 32.00 2.00 TR +2.00 22.00 TB 16.00 2.00 TR TE -2.00 24.00 TB 38.00 2.00 TR +2.00 22.00 TB 20.00 10.00 TR TE -2.00 22.00 TB 0.00 12.00 TR +2.00 22.00 TB 34.00 8.00 TR TE -2.00 22.00 TB 14.00 4.00 TR +2.00 20.00 TB 0.00 2.00 TR TE -2.00 22.00 TB 20.00 2.00 TR +2.00 20.00 TB 10.00 6.00 TR TE -2.00 22.00 TB 28.00 2.00 TR -TE -2.00 22.00 TB 40.00 2.00 TR -TE -6.00 16.00 TB 0.00 2.00 TR -TE -2.00 20.00 TB 4.00 14.00 TR +2.00 20.00 TB 18.00 4.00 TR TE 2.00 20.00 TB 24.00 2.00 TR TE -2.00 20.00 TB 32.00 4.00 TR +2.00 20.00 TB 28.00 4.00 TR TE -4.00 16.00 TB 8.00 2.00 TR +2.00 20.00 TB 34.00 2.00 TR TE -4.00 16.00 TB 28.00 2.00 TR +2.00 20.00 TB 40.00 2.00 TR TE -2.00 18.00 TB 34.00 2.00 TR +2.00 18.00 TB 2.00 2.00 TR TE -2.00 18.00 TB 40.00 2.00 TR +2.00 18.00 TB 8.00 4.00 TR +TE +2.00 18.00 TB 14.00 2.00 TR +TE +2.00 18.00 TB 22.00 8.00 TR +TE +2.00 18.00 TB 36.00 6.00 TR +TE +2.00 16.00 TB 0.00 2.00 TR +TE +2.00 16.00 TB 4.00 4.00 TR TE 2.00 16.00 TB 12.00 2.00 TR TE -2.00 16.00 TB 24.00 2.00 TR +4.00 14.00 TB 16.00 6.00 TR TE -2.00 16.00 TB 32.00 2.00 TR +4.00 14.00 TB 24.00 2.00 TR TE -2.00 16.00 TB 38.00 4.00 TR +4.00 14.00 TB 30.00 2.00 TR TE -2.00 14.00 TB 16.00 8.00 TR +2.00 16.00 TB 38.00 2.00 TR TE -2.00 14.00 TB 26.00 2.00 TR -TE -2.00 14.00 TB 30.00 2.00 TR -TE -4.00 12.00 TB 34.00 2.00 TR -TE -2.00 14.00 TB 38.00 2.00 TR +2.00 14.00 TB 36.00 2.00 TR TE 2.00 12.00 TB 0.00 14.00 TR TE -2.00 12.00 TB 20.00 4.00 TR +2.00 12.00 TB 18.00 2.00 TR TE -2.00 12.00 TB 26.00 6.00 TR +2.00 12.00 TB 22.00 2.00 TR +TE +2.00 12.00 TB 26.00 2.00 TR +TE +2.00 12.00 TB 32.00 4.00 TR +TE +4.00 10.00 TB 40.00 2.00 TR TE 10.00 2.00 TB 0.00 2.00 TR TE 10.00 2.00 TB 12.00 2.00 TR TE -2.00 10.00 TB 18.00 2.00 TR +4.00 8.00 TB 16.00 4.00 TR TE -2.00 10.00 TB 22.00 6.00 TR +2.00 10.00 TB 30.00 4.00 TR TE -2.00 10.00 TB 30.00 6.00 TR -TE -2.00 10.00 TB 38.00 4.00 TR +2.00 10.00 TB 36.00 2.00 TR TE 6.00 4.00 TB 4.00 6.00 TR TE -2.00 8.00 TB 16.00 2.00 TR +2.00 8.00 TB 22.00 2.00 TR TE -2.00 8.00 TB 20.00 4.00 TR +2.00 8.00 TB 26.00 2.00 TR TE -2.00 8.00 TB 26.00 6.00 TR +2.00 8.00 TB 32.00 6.00 TR TE -2.00 8.00 TB 34.00 4.00 TR +2.00 6.00 TB 16.00 2.00 TR TE -2.00 8.00 TB 40.00 2.00 TR +2.00 6.00 TB 20.00 12.00 TR TE -2.00 6.00 TB 20.00 2.00 TR +4.00 4.00 TB 34.00 4.00 TR TE -2.00 6.00 TB 28.00 4.00 TR -TE -2.00 6.00 TB 38.00 2.00 TR -TE -2.00 4.00 TB 16.00 2.00 TR +2.00 4.00 TB 16.00 6.00 TR TE 2.00 4.00 TB 24.00 2.00 TR TE -2.00 4.00 TB 32.00 6.00 TR -TE -2.00 4.00 TB 40.00 2.00 TR +2.00 4.00 TB 28.00 4.00 TR TE 2.00 2.00 TB 18.00 2.00 TR TE -2.00 2.00 TB 28.00 4.00 TR +2.00 2.00 TB 22.00 10.00 TR TE -2.00 2.00 TB 34.00 2.00 TR +2.00 2.00 TB 36.00 4.00 TR TE 2.00 0.00 TB 0.00 14.00 TR TE -2.00 0.00 TB 16.00 6.00 TR +2.00 0.00 TB 16.00 2.00 TR TE 2.00 0.00 TB 24.00 2.00 TR TE -2.00 0.00 TB 28.00 2.00 TR -TE -2.00 0.00 TB 32.00 2.00 TR +2.00 0.00 TB 30.00 2.00 TR TE 2.00 0.00 TB 36.00 2.00 TR TE -2.00 0.00 TB 40.00 2.00 TR -TE diff --git a/backend/tests/data/print/gif/qr_v1_m.gif b/backend/tests/data/print/gif/qr_v1_m.gif index 49cdd8cc..e8385883 100644 Binary files a/backend/tests/data/print/gif/qr_v1_m.gif and b/backend/tests/data/print/gif/qr_v1_m.gif differ diff --git a/backend/tests/data/print/pcx/qr_v1_m.pcx b/backend/tests/data/print/pcx/qr_v1_m.pcx index 79338148..ba1f2d12 100644 Binary files a/backend/tests/data/print/pcx/qr_v1_m.pcx and b/backend/tests/data/print/pcx/qr_v1_m.pcx differ diff --git a/backend/tests/data/print/png/qr_v1_m.png b/backend/tests/data/print/png/qr_v1_m.png index 0892287b..c150041b 100644 Binary files a/backend/tests/data/print/png/qr_v1_m.png and b/backend/tests/data/print/png/qr_v1_m.png differ diff --git a/backend/tests/data/print/svg/qr_v1_m.svg b/backend/tests/data/print/svg/qr_v1_m.svg index 41a6e3c9..79c56a1f 100644 --- a/backend/tests/data/print/svg/qr_v1_m.svg +++ b/backend/tests/data/print/svg/qr_v1_m.svg @@ -9,86 +9,82 @@ - + - - - + + - - + + + + - + - - + - - - - - - - - - - - - - + + + + + + + + + + - - - - - + + + + + + + + + + - - - - - - - - + + + + + - - + + + + + - - - - + + + - - - - - - - - - + + + + + + + - - + - - + + - + - - + - diff --git a/backend/tests/data/print/tif/qr_v1_m.tif b/backend/tests/data/print/tif/qr_v1_m.tif index a03f5162..0b21536e 100644 Binary files a/backend/tests/data/print/tif/qr_v1_m.tif and b/backend/tests/data/print/tif/qr_v1_m.tif differ diff --git a/backend/tests/data/print/txt/qr_v1_m.txt b/backend/tests/data/print/txt/qr_v1_m.txt index 5b7bec81..d805bbe1 100644 --- a/backend/tests/data/print/txt/qr_v1_m.txt +++ b/backend/tests/data/print/txt/qr_v1_m.txt @@ -1,21 +1,21 @@ -FE 4B F8 -82 9A 08 -BA 42 E8 -BA 0A E8 -BA CA E8 -82 0A 08 +FE 2B F8 +82 02 08 +BA A2 E8 +BA 92 E8 +BA AA E8 +82 92 08 FE AB F8 -00 58 00 -AA 70 90 -FD A2 08 -BF 88 C0 -88 02 48 -8A 0A 98 -00 F5 50 -FE 37 40 -82 5D D8 -BA B7 68 -BA 23 10 -BA 88 E8 -82 43 40 -FE EA A8 +00 C0 00 +BE 13 E0 +38 BE 78 +87 6B 48 +4D 1E 38 +B2 E9 10 +00 E9 20 +FE 54 C8 +82 C1 A8 +BA D4 E0 +BA BF 60 +BA EB 60 +82 5F 30 +FE 89 20 diff --git a/backend/tests/test_aztec.c b/backend/tests/test_aztec.c index ab69ef15..9804d810 100644 --- a/backend/tests/test_aztec.c +++ b/backend/tests/test_aztec.c @@ -775,7 +775,28 @@ static void test_encode(int index, int generate, int debug) { "110110000101100" "010001010010110" }, - /* 20*/ { BARCODE_AZTEC, DATA_MODE, 3, -1, -1, -1, "\101\300", -1, 0, 15, 15, 1, "AÀ", + /* 20*/ { BARCODE_AZTEC, UNICODE_MODE, -1, -1, -1, 2, "121212121abcd", -1, 0, 19, 19, 1, "#210", + "1101101111001101010" + "1101111011110110000" + "0001111101100010000" + "0100011111001001001" + "1010110100101010010" + "1000111111111111101" + "0001110000000111110" + "0111010111110110100" + "1001010100010101010" + "1001010101010101100" + "0010010100010101100" + "0110110111110111011" + "1001110000000111010" + "1011011111111110010" + "0011000011111001100" + "0110100001100101011" + "1001001010110011011" + "0011111001001010011" + "1001101000100100001" + }, + /* 21*/ { BARCODE_AZTEC, DATA_MODE, 3, -1, -1, -1, "\101\300", -1, 0, 15, 15, 1, "AÀ", "000000101011100" "000100010100111" "001100000110110" @@ -792,7 +813,7 @@ static void test_encode(int index, int generate, int debug) { "110001000111110" "111001100011011" }, - /* 21*/ { BARCODE_AZTEC, UNICODE_MODE, 26, -1, -1, -1, "AÀ", -1, 0, 15, 15, 1, "AÀ", + /* 22*/ { BARCODE_AZTEC, UNICODE_MODE, 26, -1, -1, -1, "AÀ", -1, 0, 15, 15, 1, "AÀ", "001111011000101" "000110100011000" "001100001000111" @@ -809,7 +830,291 @@ static void test_encode(int index, int generate, int debug) { "001100010010010" "011110110011000" }, - /* 22*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "0", -1, 0, 11, 11, 1, "ISO/IEC 24778:2008 Figure A.1 (1st)", + /* 23*/ { BARCODE_AZTEC, UNICODE_MODE, 100, -1, -1, -1, "A", -1, 0, 15, 15, 1, "FLG(3)", + "001101001111101" + "000000111011100" + "001100000100101" + "011111111111110" + "001100000001111" + "000101111101001" + "011101000101001" + "010101010101001" + "100101000101101" + "011101111101010" + "100100000001100" + "010111111111111" + "000011011110011" + "100011101111100" + "000111110001110" + }, + /* 24*/ { BARCODE_AZTEC, UNICODE_MODE, 1000, -1, -1, -1, "A", -1, 0, 15, 15, 1, "FLG(4)", + "001010100011011" + "001000100000101" + "001100000100111" + "011111111111110" + "001100000001110" + "000101111101000" + "011101000101010" + "100101010101001" + "000101000101101" + "011101111101011" + "100100000001101" + "010111111111100" + "000011011110011" + "101000000111010" + "000001110101111" + }, + /* 25*/ { BARCODE_AZTEC, UNICODE_MODE, 10000, -1, -1, -1, "A", -1, 0, 15, 15, 1, "FLG(5)", + "000100110110010" + "000001000010111" + "001100000110101" + "011111111111111" + "000100000001010" + "001101111101101" + "011101000101110" + "100101010101100" + "100101000101101" + "010101111101100" + "101100000001011" + "010111111111111" + "000011110110011" + "101010001110110" + "000000011000101" + }, + /* 26*/ { BARCODE_AZTEC, UNICODE_MODE, 100000, -1, -1, -1, "A", -1, 0, 15, 15, 1, "FLG(6)", + "000010010000010" + "001101000100110" + "001100000110111" + "011111111111111" + "001100000001110" + "001101111101010" + "011101000101111" + "110101010101011" + "000101000101001" + "011101111101101" + "101100000001110" + "010111111111101" + "000011000110011" + "101010100011011" + "000000000111010" + }, + /* 27*/ { BARCODE_AZTEC, UNICODE_MODE, -1, -1, -1, -1, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.", -1, 0, 61, 61, 0, "Zint website example gui3.png NOTE now ends with CTRL_DL . instead of CTRL_PS .; BWIPP different encodation (doesn't use CTRL_PS doubles)", + "0010110111101110101100000101001101110100010000100111011100001" + "0001100000000000001101110010000100010101110011000001000011110" + "0001111110101010100101000110101101000110011000101111011100110" + "0011000000001001101011010000010110111000011110000000010001001" + "0111001010111110010111100000001111101100011100100000001000000" + "1001100111000000001000011101000000001011001100000111100110000" + "1101101000101111010010010000101100010100100100111011011100000" + "1100100110001001100001110100100101001100011000001010110010000" + "0000101001000010000101001001101011110000000000100000001011111" + "1011100100011001100110101001100001100011110111010110110101001" + "0001101000110010111010000000001010111101010000100001001000100" + "0110100010001101000100011011100011000110000011011111001010010" + "0010000010110011001111011110101001010101001010100110000010000" + "1110001010110000110011000100010001111110110000011011001111001" + "1010101010101010101010101010101010101010101010101010101010101" + "0010110110101001010101000111110011001011000111000011100111001" + "1100110100101111110010000000111011110100100011101100110001100" + "0001001001100101000010011100000111100000111010011000000001101" + "1101000001000011101100000010011100001110110010101001000010010" + "1010110011000101100001111000100001001111100010001100111001100" + "0010011111000011101101000010101100001001000100100110000100001" + "0000100101100001111110111011010011101000011010000100000011101" + "1010011010011110110000000000011010110110101001111101010001000" + "1000100001011000111011111010100000110100010111010001010001110" + "1001100110000011001011011111111111111110011010101011001000000" + "1011110010100101000001001000000000001100001001011011001000000" + "0000011111110010010001111011111111101000000001110010001110100" + "1100000001001100110101011010000000101000010110011110010011110" + "0110010000111011111010111010111110101010111010111111001000010" + "0001001001111101111000011010100010101011100000000000000001010" + "1010101010101010101010101010101010101010101010101010101010101" + "1010111000100000110011111010100010101011100001000111100001010" + "1101101000101111100010101010111110101001110111100010010101110" + "0010000101101001111100101010000000101101111100011110110111110" + "1100101110001111000000111011111111101101000101101000010100011" + "1000011000011101111101111000000000001111100100010100010011000" + "0010000010010111001010001111111111111110000100101110110111011" + "0001000100011000011111100010110001100011001101000000010000100" + "1010001010001110100101011010001101011111010011111000011001110" + "0110000110110101011111001110000010010001010111000101000010100" + "0110101001110010110010011100001010001100000111111100011000000" + "1010110110000001111100011001000011011001111100010110000100000" + "0000011010001010000011011001101001110010001100101000111011010" + "0001001010100100010010000010110110101110101100010101010001011" + "1100010000010110110110101101101011111001101111110100011000011" + "0110001101000001111010001100110011001111011111010010100011000" + "1010101010101010101010101010101010101010101010101010101010101" + "1011000001100100011100000111010101011110110011001000100000010" + "0000111101110110001110101001001101000011110010100000101001010" + "0100100001011000000001000100000010001011110101010011110110000" + "0001001110010110101001011101101010001101000000100001101000010" + "1110010011010000011001010010010101000100110100011010001101100" + "0011001010010010011100110100011000111011100100110001001001001" + "0000111010110000100100000001110011001110001101010100001010101" + "1100010010110111011011111100001011001011001011100011100000101" + "0110111000011101110110010111100000010000011101011010001110101" + "0001000000111010000000001100001010101111100010100000010011101" + "0101000010010000110000000010000001110010000111000111100011000" + "0110100111000110011010010101111110001000000011101100000100101" + "1110000011010000000000100001100001000111011110011010000000001" + "0000010101001111100010001001111100101000010001110010010101101" + }, + /* 28*/ { BARCODE_AZTEC, UNICODE_MODE, -1, -1, -1, 36, "Lorem ipsum dolor sit amet.", -1, 0, 151, 151, 1, "Max version 151x151", + "0110011000001101111010100010010110101010100001110111111001101101010000111100111111111001000011100001010000101001010001001010101001000111101011111001101" + "1011011111111000001111111001010101111011100101110110001011011000101000010101101100000110011110100000010100110111100111111011011110001000110100111100100" + "1110001110001111110101011110010010011011001011001000001010000010000110101010101011111110110010000010000111000010000011011110001111111001000010000000111" + "1111111110111100000010100111101000111010110101100001000110010111110111110011110100111110101100011000001010110110100001111101110111001101001101011100001" + "0001111011000111110101010100010001011101110011011100001110100100111111001010100000010111000001100010110011100000111110011000101100011011000010100100001" + "1010011111011100100000000001110110111000110110010101110001011100100001101101111010100110101101111101111101011101101111001001010010011000011110010111000" + "0010100000000010010111100000011001110011011011101010011101101010000010010110110100010010010001000100001011100011011010101010001000010011001010110111111" + "0111111001111100110000010101000101011011100110110110010011011110101110111011000100111001101100111001011011110101000100101111101001100011010100010101110" + "0010010101101010010100100100110010111100100010111001000100000101000110110000110110100000011010001001101010100010011110101100110010010100011010001011011" + "1110101000010010000001001011111110111011001110110000111011111010110010001011111101011101110100100000010101110001010101101001101101101110011110100001110" + "0001011111001011100101100010111101000010011010000010010100000111011111100010110101100000101011011101001000000011000001011110001001001011101001101001000" + "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010" + "1110101001101000000110000100110101010101001011110010001100001111110110010000101011100011011001000110101100100110110100001010001011101111011000001110110" + "0000111010111110110101010011100110100110111101010000011001110011001101100011100001000000100100110101110111010011010110011101110111100101011110001001001" + "1110100110100000100100001010111100110000001000000100001010000010010110001010001111111010111001010110111100100001110110011000100011100011011001100001000" + "1001000111111111011011001111011110111000011110101110011100011101110001010111001111001010100110010010000101011100110010001001011100010010111100110111101" + "0001001001001100010001111110010110001101000011010111000011001000111110011110000100111111100010011001100111001001110111110000110101110001100010001000010" + "0000000100011110100100000011010101101011010111110000000110110010011111110111010110100001111110011000010001110100101110000101011100001000111101100000010" + "1001000010101000000001001000101000111110010000110111000111100111111010100100111101101001101010100010010010101001110011001100010001110001000000101001111" + "1011010010111100010011100001111110100001100100010001001010110101111101010101111101010101011101110101011111110110011011101101001110000101110111010010110" + "1000010000000110100010011000100011000000100000011111111101100001010111000010000101100110101011011010000100000100100111100010000010110100010011100010110" + "1010110100110111101010110101000000001111001111011001111000010011010111001111110000111011000101000110010011011100110111101001111001000001110100001101001" + "0001100110001110101110000010000000111100000011111000101110101111100111001110011001000110001011100101001100101110010000000000011111101011011011001010110" + "1110001000010100000011010011011100011000010111101010111111010011001010011101010110011010001111101001100101011101100100011111111111000001010101011001011" + "0100110011100111100111010110010011000001010011001100110010101000101001001010100111100110000001001101011101101000111001100100011010011000001001100111110" + "0011001110110110101100000101000111010001110110010110101000010111111110100001101011000110011111000000101011011000110001010001101111000111000101000101101" + "1001000100101010110101111010011011011101101000011000001011001000000011110000011110100111100011100001011001001011011100111010010100101110000000111011110" + "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010" + "1101101101100010000110100110000001010101011010111011011010101100010100000100100110011100011000100111010110100100111011101010110111100011011000011011101" + "0010011010011111011100111101111001010010101100001000011000111101010100111001011100010101011100110001001100110001101111101111000110110000010111001011111" + "1101000110001011110100100110010100000011000000010000111010001001010100000010110101000010000000001010000001100011101011001110011011000111101011111001000" + "1001000010110011011110000111100001100001111100111111001100010111011101101111111101011101110110101110111011011100111101110001110010110001000101011011000" + "0000000100100000011011001110011011001010000011110000101001100000011100110010101010010010001010010011101100100100001001101000110111000000010010011111000" + "0010111110111010010000100001111110010010100111100010001100110000100111011011010111010101100110110010000010011010111011010111011111111000000101110101110" + "1010101111000010110010011010101001101010111000010010010001001110010111111100110111010110111001101100000000001010101100100000101011100101100011100100101" + "0110101110110100101100111001111000011000001101000011100011011010110011010011001100011101011101011100110001110110000000100011011111011100101110111100110" + "0111110110101000001001001000100101011000100001110011100000000000111111100100010101001100010010011101010011000110111100010000111000000111011000100100001" + "1010010111111010001001100001001101111100100110101101011000011110010111001101101001101000000101111000010010010111001100111101110110010001101101010100000" + "0011100010101101110010100010101000010011001000100000010110100110110010001100001100111100001010101101001010101000011110010110110101100101001000110000001" + "0000001010011110010101110111001100001101011110000011110111111010101111001101111000110000110100110001101000111100010111010011001000001010100100010111110" + "1100110111001001100100000000100000000001001000011001011011100000001111100110001110001111000011111001010111100111000111111110101011100101011000000100001" + "0101110000110100000101101001001011011110110101011010110110010110000001101001011001110110000101101000000011111000101100101101001100101001001110010010001" + "1000000100101010101110001010101010000110100000000010010101100100001000000000100110010100001011010001110100000111110110111010011110000000000011101100001" + "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010" + "0010101101101101000001101000100111100101010000110001010010101000010000000000000010111010100010010000000010101111100001010010001101001110001001101000001" + "0111010100111101011001001101101001000011000111111111110011010101000000010011101010101010010100000100110001011000100110100011110000110110000111111001101" + "0001001101101100100010100000100110100000011001110010000110001011100100010010101011011000011000101011011110101011100100101000111001010001100011011100100" + "1101011011011101000110100111100100011011110110101010011010011100101010000101000101000110101110001011000100110100101001011001000100011000011101000010101" + "0011100100101001100001000100011011110010100000000110010100100101001000010000100111101100001011010010001101100111111000010010110000110110011001000001011" + "0011100010111011110010111101010001000110110100110011101011110011111100101101011001101011001111000110111111010100100100101001111110010000100111000001010" + "1100101101000011110101001110110011011100100011000011101101001001100011011000000111101011110010001100111101101100011000111100001010110100100011100100010" + "0100110010010111110000101011101111111101111110000001010011111011111111101001110110001001011101100101110000111111101110000101101010010010010111110101010" + "0011001100000011000111111000101001000010011011000010001111100001111011010100100110000100101000110010010011001110000100011100010111011101101001011111001" + "0111110110010111010011000001010110110101010100011101001111011010001000011101100000001101101110000011000111010010100110010001110110100010010110001101100" + "0110011111100110111111101000111110100100011001100010100101001100110100100010001010101110101010000110011111000001010101101100100011011100000001001110000" + "0111110101010110000101100011100010010110000100110000001111110001111010010101010101100111001100011100001010010001001000101111110101001011111101001100001" + "0111011010000001000101011010110010110011100010110110010011001101110011011100011110010000011001100100011001101101000110001000001000101010101010111000000" + "0100000101011111110001001011011111000101011111101011101100011111001001110111110001010101011101101010110011111101100110100011001101010000000101001011001" + "0011001010101111100011001010010011100001001011100111111111101111010011011100011110000110101001001101101100000100010001101010100101100001111011101001010" + "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010" + "0000011100101011001000111110011011101100011010001011010010001110111011101000101001011111010011001010100011001000000000101110010010010111010010001111010" + "1001100110011100011111000101000000100000011101110101110011111000000100011011000001110011100110001001101110010011001110101101100100100100001101000010111" + "0001010010100000011111001110101010100111011011000111110100000010111111101010111001000001110000111000001111101011000010100000111000001000111001111000000" + "1011111100010010110100100101010100010010001110100000101001011111110011110101101110000000110101001011100011111001111101111111111010110101010110100100001" + "0101111011100000110101111100110110000000000011011101110011101111000101111100011101111000111010110110100100001111101110000010101011110010110011011010011" + "1110100100110011000110110101000010010011000110110100011000010010111011000111010100110100010111111100110000010011101011000011010001011100000110000100001" + "0001111101001000101110001100100001011100011010101000001111100000111100111110010100011101011001010101101001001010101101001110110110001100100010000100011" + "0101010000110101111110010101100100001101101101111000101000110011100101001011001111101001001110100001101111111101111011100101111001001000010101011001110" + "1001010000001111111000000010011001010011100000010111101101100101010111111110000000111010000010100111010010000100000110010010011110110111110001011100100" + "1010111001010011111110000101000100010101001110101101111110110101101111111111111111100100110101111001010000111001101101110001111110111010110101110011111" + "1000000100100010010101011110110111100111011011101000111111001110001001000000000001010110010000000110100001100000101111001000001010100101101000010001001" + "1110011000111101010011001111011010010011001100101100101110010101101111011111111101010101011110111001010001110000000010000001011110101110010111001100111" + "1100100000000011110001110010001100000011001011011000111101101001001001010000000101110011010010000011011100000000101100000010000101100110111010011101000" + "1001001010110111111111010011010101111010101111000101110111011011110101010111110101001000001111111111010100111001111110010101001100110100000100110000000" + "1110010000000011010111110000001010000110010011100111111100000001000011010100010101101111011010110000010000000010000110111100010001001011100000000101110" + "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010" + "0111000010101100001110010100000100001100111001111010010011001110111001010100010101100001010000111111001010101010100010100010100001110101010001001110000" + "1100010110010000110000100101001011111100111100101100001001111101011001010111110101000101010100111111001101011000111000010111000001011100000110000010011" + "0000100111000001011000100110100010111000001010011101111100001111000101010000000101010101000011100110100101000011101100010110001001110001010000111000100" + "1111110010010110011010100111010110000100111101111101111110110100000001011111111101000010010110101000010101010111010010100111010110011101110110000100011" + "1100111010101111110010110100100110100010101010111111101010001101100011000000000001100010001000011110100001000001010010010000110011000001000010100011001" + "1010111010010000101001111001111011111011001100101100000011010101100001111111111111111101001100110010010001110010100010010011000011100111011100110001110" + "0101101101000000010100101000000111000000011011001000110000001110011000100110100010000101100000101011010110101110111111101100010111111000100001000100000" + "0001101001011101010111101101111101011000001111111110000100010111011101101011010000101000110100010100100001010011111101011101110010001011101100000100100" + "1101101111100101000111111110111010110101100010101010001101100000011001000110000010011001100011001101000100100111101000001100110101110101011011011010100" + "1110001010010010110101010011011100000111101101111100001011111111001001010101010101001001111100010000010101011101101101001001011011110000110101101101000" + "1110001011100111101011001100111010010111000001100111110001101110001101111010000011011000111010100001101011100010110010111100110111111010101000000010101" + "0010100101111110111110001111000001101110100100100110011111010001001010010101000001111100100111110100001110110011111001011111010001100100101100010000001" + "1010001010100100110110111010011010100010101001010101010101000011011000011110110111010010101000110101101111101011110110011100101000101101111011011011110" + "0110000100010000100101110101101010010101010100001111011000111101011010110101010101101100001110011001001010111110001101100101000111011101000101101101000" + "0111011011000001110010111100100001111100000011000000011010000101101010100010100101010000010001011001101101000100111100101110001100111001101001000111000" + "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010" + "1001000110000001010110111110000011111101101010010001111000101001010100010010100110001100100001001000000000000100111101111110001001000111000000000010101" + "1101000100010100111100010111111111001010011111100111101011111010101110110011101010010101100101111111001100011111111111110101011000110101001110001110000" + "1100010101100000000000111000000001011101010011010111000100000011100111100010010001000011101001000100010101001001110101011010010011100001010011101000000" + "1011100010110110110000100101100000000010010111010101100111110101001110000101111011100110101111100010101011110011110100101111101111011011101101111111110" + "1001101001000101000101000110110101001110111000011011110000100000110101110010011011100111111011100101111001001100101011000000011100010111111011010110100" + "1110100111010111100010100011100000010001101101110101000001111011010000000011000110100100110101101000110000110010101001101101110100100111110111000111001" + "1110011001100100010111011010001010010100001001110101001101000001101100001010110111000010001010011010100111101100000101010100001011101110001001101110111" + "0011001000011100100111111111000111111100110100100100001011010101011110101101110100101101101101110111101110011101001101100111100111001101100100010110111" + "1101011110001110111110100110001001000111111010011001010000100011110110110100000001101101000010010010111011101010100111101100001000100011010011111111011" + "1001100111010000100111100111010110111100010110111000010011110100110010011101100110101101010111001101100100111101001011001101010110100010111110010100010" + "1010100000100101000100111010101101000101011010000010011101001100110101001010001001010011010010111101000111101011011001101000001011111011010001111010011" + "0001111010010010001100110101111111101100001101101001000101111111111101010001111011001011101111111010011101010110111111001111100110001101100101001100110" + "0101000000101011000000010000101001011110111011111101001101000010101100101100011000000100000000001011100101001101111100110100010010100010111010011110011" + "1100010010110101000101011011110100001011100101001011011101111101000111101011000000100011001111100110011010111111101001010001001100000101011101001001010" + "1011111100100010001111101100010001011011001010000111110000101010000100010100101010000000011000101001100011100111010111010110010100010101111010110011000" + "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010" + "1010011001001000111101011100011010101000111000111111111111001001110110001010010101100001011010110111010101101100011101111100010111101001010011100001111" + "1010000001011110101000101111001000110010000110001010111000011010110010111111110111100011001111111010001000110001111100010001100110100110100110110111100" + "1110100110001001111000011110010110101001100000011010010010101110100011100110011100000010000000100100001000100101100001000000100110100011101010101110101" + "0010111110010111100101011001100101010001010101101001001101011111011010011011000110001011101111001111011111011001010100010001110011101101011111101010010" + "0110111010101110011111101100101011000110011011101001110100101101101100010010111101000111010010010010111100001100101010011000001000000111100010011000100" + "1111111100011101110010111001000110010000101100101011101011011100110111000111010100001101001101111001001100011010111011110111111000010111010101000010100" + "0101111000101010101001011010011111101111011011010010100110001110010010101010000010101111011010100000011100001101000001111110110111000100011011100111100" + "0110000000011011110101001001011010100001010110010100011100111011000010000101010000001011110111111111100001010111010001110011001101010100110110000000000" + "1100110001000100110100011010110011110110000011010100111010100100011000000000010000110000110000111100010001100101101101111110101110011110000010101111011" + "1100110111110000010100001011001000001111001111101101010000011111001011100101110100100011110101110101011111111100001100100101100100111111010110011010110" + "0110110011000111100000011110111001110001101011101000100010101101101101110100100011100110010011100111101111100101100111011110001100111011010001110001101" + "0111001010110101011001001011000101101001001100110000000001111101011010001101001000010010011110101101111110011111101110100011101111001001011100101111101" + "0010011101101010100111100010011100010011000011010101101000001010100011101010111111100110001000000001101100100110110000000110011001011001111011101100001" + "1000110111011110100100110001000010010000100111011010001000011010111100010101001100011111101100010110000011011111101000001011111100110001101110110101011" + "1101011001101010111110000110100101010000100001001110101110000100010110001110010001010011100010110101010110001100000001101000010011101010000000111101011" + "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010" + "0001001110100100001101000110101001111011101001011011001100101100111110000010101011101111010000000000100110101101001101011100000100000011011000010011101" + "1000010101110010110001111011101111111001101111011011101101011110001011110101010101011011010101100011101101010100111001111001100100010000001101111001011" + "1001110110000010011011111000101000110010000010000111001101100100100101110000101010011110111011010000001010101111011110100110011011100000111001100111011" + "0110000100011001011000111101110001111001000101000011111110011110110101000001111101111101100111110010101010110001011011000101011001101111110100110101011" + "1010100111100111101110010100001010110011000000010110011000000010100001000010101000111011100001001001010111001101010100100000110001011100011001100100100" + "1101011100111100110101110101001111100100010100110111011000010110100000000101001001001100011100101011110011110101001100110011010011111011010100100011100" + "0001111101101100011000100010110100110011100011011110110011101000101010010100110110010000011010100100101001100100011011111100101100101000110001100000010" + "0110110101010101011000000011101100110000010110111001001100111011011100000111110110111110110111101011000010010111010101110001110101110010111101011011101" + "1011010000100001101110101100011101011001000010110111111001000111101101011010110010010111010011000111101000100000110000011000010010110001011011110111110" + "0011101110011110110100001101100111100101101110100010001100011100001001001001000111001000000100100110001100111011100100001101101000011101010101100000010" + "0101000110101100011100101110101011111000001000010101011000000011001100101000110010100000101010110001111101101011010010010100011000001010001010010100111" + "1000100000111011001011000011100010110110100111011111001000111111111110011101010011100001010100111010011011011001001001011001010001011001011101011111110" + "0111110000100111111101001110011000101101110000010010101111101101000010000010000011100101011000101000011110101111100010000110010010100100110011011110010" + "0110100111111100001111000011010011010101101110001001110101111011000001000001001000100010001110100100001110010010010110100011001101000001100111110101001" + "0010011011100100101100011110010110011010001010001110111000101011100101001000101001001001101000010110000110101000011110110010101110101000011000000010110" + "0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010" + "0000111011001011101000110110100010010000000011011011011101001010110100101110110100001010100000001000101100000100011011001100001001101011011000111010100" + "1011101011110000100011110101010110111100011110111001011001010000001011111111010111001100010111110011111000110011001011111111010010110100111101001111101" + "0111100100101010000001010010000101011001000001001101110000101010110000111110010110010101000010000011001011101001000110010010000011101010110001100111100" + "1000101111010011001101110101000110000001001100111110010110010010010001011001010111100110110111001001001001111101101101010001011111100101110100011110100" + "1101000111101110010011001110111100100110010000000110001101001001110000111100010101011100010011001101111100101110111100001000001111100000101011110110100" + "0110111110110001100101011101000011111001001111010100100101110011010000111111101100100111010111000101000001010011110011100011010001111011100111001101100" + "0101010101101010010000110100111010110010110001110011110011101100011111110000000101010001000011001011111100000111101000010010111111011111101000110010001" + "1100111000010101000011100001001001101000111101110011001001010111011111001001011011100001101100100010000001111100101001001111110000000110101111001100111" + "1001101001000001000111111110110101001101010000110110110011101100000101011010111100101000001011001101101010000010101000010110001101101011110001110010001" + "1000000100011011110011111011110000011111110111001111111010110101100011000111010100100010001111000101110110110100000111000011101011011101111111000011111" + "1000110110001001001111110010011100000100011010101101101101101001001001011110101010011110010011011110100111100111110111111110000101100111110000101010011" + }, + /* 29*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "0", -1, 0, 11, 11, 1, "ISO/IEC 24778:2008 Figure A.1 (1st)", "11101010101" "11111111111" "01000000010" @@ -822,7 +1127,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00101010100" }, - /* 23*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "25", -1, 0, 11, 11, 1, "ISO/IEC 24778:2008 Figure A.1 (2nd)", + /* 30*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "25", -1, 0, 11, 11, 1, "ISO/IEC 24778:2008 Figure A.1 (2nd)", "11101100101" "11111111111" "01000000011" @@ -835,7 +1140,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00100100000" }, - /* 24*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "125", -1, 0, 11, 11, 1, "ISO/IEC 24778:2008 Figure A.1 (3rd)", + /* 31*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "125", -1, 0, 11, 11, 1, "ISO/IEC 24778:2008 Figure A.1 (3rd)", "11110101101" "11111111111" "11000000011" @@ -848,7 +1153,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00111101000" }, - /* 25*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "255", -1, 0, 11, 11, 1, "ISO/IEC 24778:2008 Figure A.1 (4th)", + /* 32*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "255", -1, 0, 11, 11, 1, "ISO/IEC 24778:2008 Figure A.1 (4th)", "11010101001" "11111111111" "01000000011" @@ -861,7 +1166,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00110011100" }, - /* 26*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "1", -1, 0, 11, 11, 1, "", + /* 33*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "1", -1, 0, 11, 11, 1, "", "11101010101" "11111111111" "11000000011" @@ -874,7 +1179,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00100110100" }, - /* 27*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "15", -1, 0, 11, 11, 1, "", + /* 34*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "15", -1, 0, 11, 11, 1, "", "11101001001" "11111111111" "11000000011" @@ -887,7 +1192,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00001111100" }, - /* 28*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "16", -1, 0, 11, 11, 1, "", + /* 35*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "16", -1, 0, 11, 11, 1, "", "11101110101" "11111111111" "11000000010" @@ -900,7 +1205,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00111100100" }, - /* 29*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "63", -1, 0, 11, 11, 1, "", + /* 36*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "63", -1, 0, 11, 11, 1, "", "11100101001" "11111111111" "11000000011" @@ -913,7 +1218,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00101010000" }, - /* 30*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "64", -1, 0, 11, 11, 1, "", + /* 37*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "64", -1, 0, 11, 11, 1, "", "11111010101" "11111111111" "01000000010" @@ -926,7 +1231,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00111011100" }, - /* 31*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "65", -1, 0, 11, 11, 1, "", + /* 38*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "65", -1, 0, 11, 11, 1, "", "11111010101" "11111111111" "11000000011" @@ -939,7 +1244,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00110111100" }, - /* 32*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "126", -1, 0, 11, 11, 1, "", + /* 39*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "126", -1, 0, 11, 11, 1, "", "11110101001" "11111111111" "01000000010" @@ -952,7 +1257,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00110111000" }, - /* 33*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "127", -1, 0, 11, 11, 1, "", + /* 40*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "127", -1, 0, 11, 11, 1, "", "11110101001" "11111111111" "11000000011" @@ -965,7 +1270,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00111011000" }, - /* 34*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "128", -1, 0, 11, 11, 1, "", + /* 41*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "128", -1, 0, 11, 11, 1, "", "11001010101" "11111111111" "11000000010" @@ -978,7 +1283,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00100010000" }, - /* 35*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "191", -1, 0, 11, 11, 1, "", + /* 42*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "191", -1, 0, 11, 11, 1, "", "11000101001" "11111111111" "01000000011" @@ -991,7 +1296,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00100010100" }, - /* 36*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "192", -1, 0, 11, 11, 1, "", + /* 43*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "192", -1, 0, 11, 11, 1, "", "11011010101" "11111111111" "11000000010" @@ -1004,7 +1309,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00110011000" }, - /* 37*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "225", -1, 0, 11, 11, 1, "", + /* 44*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "225", -1, 0, 11, 11, 1, "", "11010010101" "11111111111" "11000000011" @@ -1017,7 +1322,7 @@ static void test_encode(int index, int generate, int debug) { "01111111111" "00001100100" }, - /* 38*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "254", -1, 0, 11, 11, 1, "", + /* 45*/ { BARCODE_AZRUNE, UNICODE_MODE, -1, -1, -1, -1, "254", -1, 0, 11, 11, 1, "", "11010101001" "11111111111" "11000000010" @@ -1034,7 +1339,7 @@ static void test_encode(int index, int generate, int debug) { int data_size = ARRAY_SIZE(data); char escaped[1024]; - char bwipp_buf[16384]; + char bwipp_buf[32768]; char bwipp_msg[1024]; for (int i = 0; i < data_size; i++) { @@ -1524,12 +1829,116 @@ static void test_fuzz(int index, int debug) { testFinish(); } +#include + +#define TEST_PERF_ITERATIONS 1000 + +// Not a real test, just performance indicator +static void test_perf(int index, int debug) { + + if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */ + return; + } + + int ret; + struct item { + int symbology; + int input_mode; + int option_1; + int option_2; + char *data; + int ret; + + int expected_rows; + int expected_width; + char *comment; + }; + struct item data[] = { + /* 0*/ { BARCODE_AZTEC, -1, -1, -1, + "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + 0, 49, 49, "286 chars, 8-bit words, upper" }, + /* 1*/ { BARCODE_AZTEC, -1, -1, -1, + "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" + "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" + "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" + "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" + "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890" + "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", + 0, 79, 79, "900 chars, 10-bit words, numeric" }, + /* 2*/ { BARCODE_AZTEC, -1, -1, -1, + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377", + 0, 91, 91, "980 chars, 10-bit words, mixed" }, + /* 3*/ { BARCODE_AZTEC, -1, -1, -1, + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ~~~~~~~~~~~~~~~~~~~~~~~~~ ?????????????????????????? 12345678901234567890123456 \377\377\377\377\377\377", + 0, 113, 113, "1540 chars, 12-bit words, mixed" }, + }; + int data_size = ARRAY_SIZE(data); + + clock_t start, total_encode = 0, total_buffer = 0, diff_encode, diff_buffer; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + diff_encode = diff_buffer = 0; + + for (int j = 0; j < TEST_PERF_ITERATIONS; j++) { + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + int length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, data[i].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); + + 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); + + total_encode += diff_encode; + total_buffer += diff_buffer; + } + if (index != -1) { + printf("totals: encode %gms, buffer %gms\n", total_encode * 1000.0 / CLOCKS_PER_SEC, total_buffer * 1000.0 / CLOCKS_PER_SEC); + } +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ { "test_options", test_options, 1, 0, 1 }, { "test_encode", test_encode, 1, 1, 1 }, { "test_fuzz", test_fuzz, 1, 0, 1 }, + { "test_perf", test_perf, 1, 0, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_code1.c b/backend/tests/test_code1.c index cd1e025a..b4e8fc95 100644 --- a/backend/tests/test_code1.c +++ b/backend/tests/test_code1.c @@ -178,11 +178,12 @@ static void test_encode(int index, int generate, int debug) { int expected_rows; int expected_width; + int bwipp_cmp; char *comment; char *expected; }; struct item data[] = { - /* 0*/ { -1, "123456789012", -1, 0, 16, 18, "", + /* 0*/ { -1, "123456789012", -1, 0, 16, 18, 1, "", "100011101010111101" "111010010010100000" "110110100010001000" @@ -200,6 +201,54 @@ static void test_encode(int index, int generate, int debug) { "010111110100100111" "100010001101111100" }, + /* 1*/ { -1, "Code One", -1, 0, 16, 18, 1, "BWIPP example", + "010011011101100110" + "010010000001010110" + "001010010101100110" + "000110000011110110" + "100010100000111001" + "000010000000100000" + "111111111111111111" + "000000000000000000" + "011111111111111110" + "010000000000000010" + "011111111111111110" + "000100011110101101" + "101101000111101011" + "010100001110101100" + "100001100111100100" + "100000111000111000" + }, + /* 2*/ { 3, "1234567890ABCDEF", -1, 0, 28, 32, 0, "https://fr.wikipedia.org/wiki/Liste_des_symbologies, same; BWIPP **NOT SAME**, has unlatch to ASCII at end, no doc so don't know if necessary", + "10001110101011110111011110110101" + "11101001001010000011000110101001" + "11101001100010100010001000101000" + "10011011010100000100010001100001" + "10001010001000100010001000101000" + "00011000010001000100010001100001" + "10001010001000100010001000101000" + "00011000010001000100010001100001" + "10001010001000100010001000101000" + "00011000010001000100010001100001" + "00001000000000000000000000100000" + "11111111111111111111111111111111" + "00000000000000000000000000100000" + "11111111111111111111111111111111" + "00000000000000000000000000000000" + "01111111111111111111111111111110" + "01000000000000000000000000000010" + "01111111111111111111111111111110" + "10001010001000100010001000101000" + "00011000010001000100010001100001" + "10001010000101011110001101100110" + "00011000010010101010111011100100" + "11101011011100101001000110101100" + "01111000000000010001000111101111" + "00001010100010111100100100101100" + "10001000101110100001010011100110" + "00001011001001010100010001101111" + "00101101111001111011011001111010" + }, }; int data_size = ARRAY_SIZE(data); @@ -220,9 +269,9 @@ static void test_encode(int index, int generate, int debug) { assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %d, \"%s\", %d, %s, %d, %d, \"%s\",\n", + printf(" /*%3d*/ { %d, \"%s\", %d, %s, %d, %d, %d, \"%s\",\n", i, data[i].option_2, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].length, - testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment); + testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].bwipp_cmp, data[i].comment); testUtilModulesDump(symbol, " ", "\n"); printf(" },\n"); } else { @@ -235,12 +284,16 @@ static void test_encode(int index, int generate, int debug) { assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); if (do_bwipp && testUtilCanBwipp(i, symbol, -1, data[i].option_2, -1, debug)) { - ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf)); - assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); + if (!data[i].bwipp_cmp) { + if (debug & ZINT_DEBUG_TEST_PRINT) printf("i:%d %s not BWIPP compatible (%s)\n", i, testUtilBarcodeName(symbol->symbology), data[i].comment); + } else { + ret = testUtilBwipp(i, symbol, -1, data[i].option_2, -1, data[i].data, length, NULL, bwipp_buf, sizeof(bwipp_buf)); + assert_zero(ret, "i:%d %s testUtilBwipp ret %d != 0\n", i, testUtilBarcodeName(symbol->symbology), ret); - ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); - assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n actual: %s\nexpected: %s\n", - i, testUtilBarcodeName(symbol->symbology), ret, bwipp_msg, bwipp_buf, data[i].expected); + ret = testUtilBwippCmp(symbol, bwipp_msg, bwipp_buf, data[i].expected); + assert_zero(ret, "i:%d %s testUtilBwippCmp %d != 0 %s\n actual: %s\nexpected: %s\n", + i, testUtilBarcodeName(symbol->symbology), ret, bwipp_msg, bwipp_buf, data[i].expected); + } } } } diff --git a/backend/tests/test_common.c b/backend/tests/test_common.c index 090cd86d..9cc14636 100644 --- a/backend/tests/test_common.c +++ b/backend/tests/test_common.c @@ -41,7 +41,7 @@ static void test_utf8_to_unicode(int index, int debug) { int length; int disallow_4byte; int ret; - size_t ret_length; + int ret_length; unsigned int expected_vals[20]; char *comment; }; @@ -64,14 +64,14 @@ static void test_utf8_to_unicode(int index, int debug) { if (index != -1 && i != index) continue; int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; - size_t ret_length = length; + int ret_length = length; ret = utf8_to_unicode(&symbol, (unsigned char *) data[i].data, vals, &ret_length, data[i].disallow_4byte); assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); if (ret == 0) { - assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %ld != %ld\n", i, ret_length, data[i].ret_length); - for (size_t j = 0; j < ret_length; j++) { - assert_equal(vals[j], data[i].expected_vals[j], "i:%d vals[%zu] %04X != %04X\n", i, j, vals[j], data[i].expected_vals[j]); + assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %d != %d\n", i, ret_length, data[i].ret_length); + for (int j = 0; j < ret_length; j++) { + assert_equal(vals[j], data[i].expected_vals[j], "i:%d vals[%d] %04X != %04X\n", i, j, vals[j], data[i].expected_vals[j]); } } } @@ -103,8 +103,8 @@ static void test_debug_test_codeword_dump_int(int index, int debug) { if (index != -1 && i != index) continue; debug_test_codeword_dump_int(&symbol, data[i].codewords, data[i].length); - assert_nonzero(strlen(symbol.errtxt) < 92, "i:%d strlen(%s) >= 92 (%zu)\n", i, symbol.errtxt, strlen(symbol.errtxt)); - assert_zero(strcmp(symbol.errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0 (%zu, %zu)\n", i, symbol.errtxt, data[i].expected, strlen(symbol.errtxt), strlen(data[i].expected)); + assert_nonzero(strlen(symbol.errtxt) < 92, "i:%d strlen(%s) >= 92 (%d)\n", i, symbol.errtxt, (int) strlen(symbol.errtxt)); + assert_zero(strcmp(symbol.errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0 (%d, %d)\n", i, symbol.errtxt, data[i].expected, (int) strlen(symbol.errtxt), (int) strlen(data[i].expected)); } testFinish(); diff --git a/backend/tests/test_eci.c b/backend/tests/test_eci.c index 85e97a22..9aea1ff7 100644 --- a/backend/tests/test_eci.c +++ b/backend/tests/test_eci.c @@ -42,6 +42,7 @@ static void test_bom(int debug) { symbol->input_mode = UNICODE_MODE; symbol->option_1 = 4; symbol->option_2 = 1; + symbol->option_3 = 5 << 8; // Mask 100 (instead of automatic 010) symbol->debug |= debug; char data[] = "\xEF\xBB\xBF‹"; // U+FEFF BOM, with U+2039 (only in Windows pages) diff --git a/backend/tests/test_emf.c b/backend/tests/test_emf.c index cacd5261..42313772 100644 --- a/backend/tests/test_emf.c +++ b/backend/tests/test_emf.c @@ -32,69 +32,6 @@ #include "testcommon.h" #include -static void test_emf(int index, int debug) { - - testStart(""); - - if (!testUtilHaveLibreOffice()) { - testSkip("LibreOffice not available"); - return; - } - - int ret; - struct item { - int symbology; - int option_1; - int option_2; - char *fgcolour; - char *bgcolour; - float scale; - char *data; - }; - // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) - struct item data[] = { - /* 0*/ { BARCODE_EANX, -1, -1, "", "", 0, "210987654321+54321" }, // #185 Byte count, font data, HeaderExtension1/2 - /* 1*/ { BARCODE_MAXICODE, -1, 20, "E0E0E0", "700070", 0, "THIS IS A 93 CHARACTER CODE SET A MESSAGE THAT FILLS A MODE 4, UNAPPENDED, MAXICODE SYMBOL..." }, // #185 Maxicode scaling - }; - int data_size = ARRAY_SIZE(data); - - for (int i = 0; i < data_size; i++) { - - if (index != -1 && i != index) continue; - - struct zint_symbol *symbol = ZBarcode_Create(); - assert_nonnull(symbol, "Symbol not created\n"); - - int length = testUtilSetSymbol(symbol, data[i].symbology, -1 /*input_mode*/, -1 /*eci*/, data[i].option_1, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); - if (*data[i].fgcolour) { - strcpy(symbol->fgcolour, data[i].fgcolour); - } - if (*data[i].bgcolour) { - strcpy(symbol->bgcolour, data[i].bgcolour); - } - if (data[i].scale != 0) { - symbol->scale = data[i].scale; - } - - ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); - assert_zero(ret, "i:%d %s ZBarcode_Encode ret %d != 0 %s\n", i, testUtilBarcodeName(data[i].symbology), ret, symbol->errtxt); - - char *filename = "out.emf"; - strcpy(symbol->outfile, filename); - ret = ZBarcode_Print(symbol, 0); - assert_zero(ret, "i:%d %s ZBarcode_Print %s ret %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret); - - ret = testUtilVerifyLibreOffice(symbol->outfile, debug); // Slow - assert_zero(ret, "i:%d %s libreoffice %s ret %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret); - - assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile); - - ZBarcode_Delete(symbol); - } - - testFinish(); -} - static void test_print(int index, int generate, int debug) { testStart(""); @@ -115,26 +52,29 @@ static void test_print(int index, int generate, int debug) { char *fgcolour; char *bgcolour; int rotate_angle; - char* data; - char* expected_file; + char *data; + char *expected_file; + char *comment; }; struct item data[] = { - /* 0*/ { BARCODE_CODE128, UNICODE_MODE, BOLD_TEXT, -1, -1, -1, "", "", 0, "Égjpqy", "../data/emf/code128_egrave_bold.emf" }, - /* 1*/ { BARCODE_TELEPEN, -1, -1, -1, -1, -1, "147AD0", "FC9630", 0, "123", "../data/emf/telenum_fg_bg.emf" }, - /* 2*/ { BARCODE_ULTRA, -1, -1, 5, -1, -1, "147AD0", "FC9630", 0, "123", "../data/emf/ultracode_fg_bg.emf" }, - /* 3*/ { BARCODE_EANX, -1, -1, -1, -1, -1, "", "", 0, "9780877799306+54321", "../data/emf/ean13_5addon_ggs_5.2.2.5.2-2.emf" }, - /* 4*/ { BARCODE_UPCA, -1, -1, -1, -1, -1, "", "", 0, "012345678905+24", "../data/emf/upca_2addon_ggs_5.2.6.6-5.emf" }, - /* 5*/ { BARCODE_UPCE, -1, -1, -1, -1, -1, "", "", 0, "0123456+12", "../data/emf/upce_2addon.emf" }, - /* 6*/ { BARCODE_UPCE, -1, SMALL_TEXT | BOLD_TEXT, -1, -1, -1, "", "", 0, "0123456+12", "../data/emf/upce_2addon_small_bold.emf" }, - /* 7*/ { BARCODE_ITF14, -1, BOLD_TEXT, -1, -1, -1, "", "", 0, "123", "../data/emf/itf14_bold.emf" }, - /* 8*/ { BARCODE_CODE39, -1, -1, -1, -1, -1, "", "", 90, "123", "../data/emf/code39_rotate_90.emf" }, - /* 9*/ { BARCODE_CODE39, -1, -1, -1, -1, -1, "", "", 180, "123", "../data/emf/code39_rotate_180.emf" }, - /* 10*/ { BARCODE_CODE39, -1, -1, -1, -1, -1, "", "", 270, "123", "../data/emf/code39_rotate_270.emf" }, + /* 0*/ { BARCODE_CODE128, UNICODE_MODE, BOLD_TEXT, -1, -1, -1, "", "", 0, "Égjpqy", "../data/emf/code128_egrave_bold.emf", "" }, + /* 1*/ { BARCODE_TELEPEN, -1, -1, -1, -1, -1, "147AD0", "FC9630", 0, "123", "../data/emf/telenum_fg_bg.emf", "" }, + /* 2*/ { BARCODE_ULTRA, -1, -1, 5, -1, -1, "147AD0", "FC9630", 0, "123", "../data/emf/ultracode_fg_bg.emf", "" }, + /* 3*/ { BARCODE_EANX, -1, -1, -1, -1, -1, "", "", 0, "9780877799306+54321", "../data/emf/ean13_5addon_ggs_5.2.2.5.2-2.emf", "" }, + /* 4*/ { BARCODE_EANX, -1, -1, -1, -1, -1, "", "", 0, "210987654321+54321", "../data/emf/ean13_5addon_#185.emf", "#185 Byte count, font data, HeaderExtension1/2" }, + /* 5*/ { BARCODE_UPCA, -1, -1, -1, -1, -1, "", "", 0, "012345678905+24", "../data/emf/upca_2addon_ggs_5.2.6.6-5.emf", "" }, + /* 6*/ { BARCODE_UPCE, -1, -1, -1, -1, -1, "", "", 0, "0123456+12", "../data/emf/upce_2addon.emf", "" }, + /* 7*/ { BARCODE_UPCE, -1, SMALL_TEXT | BOLD_TEXT, -1, -1, -1, "", "", 0, "0123456+12", "../data/emf/upce_2addon_small_bold.emf", "" }, + /* 8*/ { BARCODE_ITF14, -1, BOLD_TEXT, -1, -1, -1, "", "", 0, "123", "../data/emf/itf14_bold.emf", "" }, + /* 9*/ { BARCODE_CODE39, -1, -1, -1, -1, -1, "", "", 90, "123", "../data/emf/code39_rotate_90.emf", "" }, + /* 10*/ { BARCODE_CODE39, -1, -1, -1, -1, -1, "", "", 180, "123", "../data/emf/code39_rotate_180.emf", "" }, + /* 11*/ { BARCODE_CODE39, -1, -1, -1, -1, -1, "", "", 270, "123", "../data/emf/code39_rotate_270.emf", "" }, + /* 12*/ { BARCODE_MAXICODE, -1, -1, -1, -1, 20, "E0E0E0", "700070", 0, "THIS IS A 93 CHARACTER CODE SET A MESSAGE THAT FILLS A MODE 4, UNAPPENDED, MAXICODE SYMBOL...", "../data/emf/maxicode_#185.emf", "#185 Maxicode scaling" }, }; int data_size = ARRAY_SIZE(data); - char* data_dir = "../data/emf"; - char* emf = "out.emf"; + char *data_dir = "../data/emf"; + char *emf = "out.emf"; char escaped[1024]; int escaped_size = 1024; @@ -171,12 +111,16 @@ static void test_print(int index, int generate, int debug) { assert_zero(ret, "i:%d %s ZBarcode_Print %s ret %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret); if (generate) { - printf(" /*%3d*/ { %s, %s, %s, %d, %d, %d, \"%s\", \"%s\", %d, \"%s\", \"%s\"},\n", - i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), testUtilOutputOptionsName(data[i].output_options), data[i].whitespace_width, - data[i].option_1, data[i].option_2, data[i].fgcolour, data[i].bgcolour, data[i].rotate_angle, testUtilEscape(data[i].data, length, escaped, escaped_size), data[i].expected_file); + printf(" /*%3d*/ { %s, %s, %s, %d, %d, %d, \"%s\", \"%s\", %d, \"%s\", \"%s\" \"%s\" },\n", + i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), + testUtilOutputOptionsName(data[i].output_options), data[i].whitespace_width, + data[i].option_1, data[i].option_2, data[i].fgcolour, data[i].bgcolour, data[i].rotate_angle, + testUtilEscape(data[i].data, length, escaped, escaped_size), data[i].expected_file, data[i].comment); ret = rename(symbol->outfile, data[i].expected_file); assert_zero(ret, "i:%d rename(%s, %s) ret %d != 0\n", i, symbol->outfile, data[i].expected_file, ret); if (have_libreoffice) { + // Note this will fail (on Ubuntu anyway) if LibreOffice Base/Calc/Impress/Writer running (i.e. anything but LibreOffice Draw) + // Doesn't seem to be a way to force Draw invocation through the command line ret = testUtilVerifyLibreOffice(data[i].expected_file, debug); assert_zero(ret, "i:%d %s libreoffice %s ret %d != 0\n", i, testUtilBarcodeName(data[i].symbology), data[i].expected_file, ret); } @@ -198,7 +142,6 @@ static void test_print(int index, int generate, int debug) { int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ - { "test_emf", test_emf, 1, 0, 1 }, { "test_print", test_print, 1, 1, 1 }, }; diff --git a/backend/tests/test_gb18030.c b/backend/tests/test_gb18030.c index 8e60ff90..ddd421ba 100644 --- a/backend/tests/test_gb18030.c +++ b/backend/tests/test_gb18030.c @@ -155,7 +155,7 @@ static void test_gb18030_utf8tomb(int index) { char *data; int length; int ret; - size_t ret_length; + int ret_length; unsigned int expected_gbdata[30]; char *comment; }; @@ -190,12 +190,12 @@ static void test_gb18030_utf8tomb(int index) { if (index != -1 && i != index) continue; int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; - size_t ret_length = length; + int ret_length = length; ret = gb18030_utf8tomb(&symbol, (unsigned char *) data[i].data, &ret_length, gbdata); assert_equal(ret, data[i].ret, "i:%d ret %d != %d (%s)\n", i, ret, data[i].ret, symbol.errtxt); if (ret == 0) { - assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %zu != %zu\n", i, ret_length, data[i].ret_length); + assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %d != %d\n", i, ret_length, data[i].ret_length); for (int j = 0; j < (int) ret_length; j++) { assert_equal(gbdata[j], data[i].expected_gbdata[j], "i:%d gbdata[%d] 0x%04X != 0x%04X\n", i, j, gbdata[j], data[i].expected_gbdata[j]); } @@ -216,7 +216,7 @@ static void test_gb18030_utf8tosb(int index) { char *data; int length; int ret; - size_t ret_length; + int ret_length; unsigned int expected_gbdata[30]; char *comment; }; @@ -265,12 +265,12 @@ static void test_gb18030_utf8tosb(int index) { if (index != -1 && i != index) continue; int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; - size_t ret_length = length; + int ret_length = length; ret = gb18030_utf8tosb(data[i].eci, (unsigned char *) data[i].data, &ret_length, gbdata, data[i].full_multibyte); assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); if (ret == 0) { - assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %zu != %zu\n", i, ret_length, data[i].ret_length); + assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %d != %d\n", i, ret_length, data[i].ret_length); for (int j = 0; j < (int) ret_length; j++) { assert_equal(gbdata[j], data[i].expected_gbdata[j], "i:%d gbdata[%d] %04X != %04X\n", i, j, gbdata[j], data[i].expected_gbdata[j]); } @@ -289,7 +289,7 @@ static void test_gb18030_cpy(int index) { char *data; int length; int ret; - size_t ret_length; + int ret_length; unsigned int expected_gbdata[30]; char *comment; }; @@ -316,10 +316,10 @@ static void test_gb18030_cpy(int index) { if (index != -1 && i != index) continue; int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; - size_t ret_length = length; + int ret_length = length; gb18030_cpy((unsigned char *) data[i].data, &ret_length, gbdata, data[i].full_multibyte); - assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %zu != %zu\n", i, ret_length, data[i].ret_length); + assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %d != %d\n", i, ret_length, data[i].ret_length); for (int j = 0; j < (int) ret_length; j++) { assert_equal(gbdata[j], data[i].expected_gbdata[j], "i:%d gbdata[%d] %04X != %04X\n", i, j, gbdata[j], data[i].expected_gbdata[j]); } diff --git a/backend/tests/test_gb2312.c b/backend/tests/test_gb2312.c index 56871c58..570de0f3 100644 --- a/backend/tests/test_gb2312.c +++ b/backend/tests/test_gb2312.c @@ -95,7 +95,7 @@ static void test_gb2312_utf8tomb(int index) { char *data; int length; int ret; - size_t ret_length; + int ret_length; unsigned int expected_gbdata[20]; char *comment; }; @@ -130,12 +130,12 @@ static void test_gb2312_utf8tomb(int index) { if (index != -1 && i != index) continue; int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; - size_t ret_length = length; + int ret_length = length; ret = gb2312_utf8tomb(&symbol, (unsigned char *) data[i].data, &ret_length, gbdata); assert_equal(ret, data[i].ret, "i:%d ret %d != %d (%s)\n", i, ret, data[i].ret, symbol.errtxt); if (ret == 0) { - assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %zu != %zu\n", i, ret_length, data[i].ret_length); + assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %d != %d\n", i, ret_length, data[i].ret_length); for (int j = 0; j < (int) ret_length; j++) { assert_equal(gbdata[j], data[i].expected_gbdata[j], "i:%d gbdata[%d] %04X != %04X\n", i, j, gbdata[j], data[i].expected_gbdata[j]); } @@ -156,7 +156,7 @@ static void test_gb2312_utf8tosb(int index) { char *data; int length; int ret; - size_t ret_length; + int ret_length; unsigned int expected_gbdata[20]; char *comment; }; @@ -203,12 +203,12 @@ static void test_gb2312_utf8tosb(int index) { if (index != -1 && i != index) continue; int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; - size_t ret_length = length; + int ret_length = length; ret = gb2312_utf8tosb(data[i].eci, (unsigned char *) data[i].data, &ret_length, gbdata, data[i].full_multibyte); assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); if (ret == 0) { - assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %zu != %zu\n", i, ret_length, data[i].ret_length); + assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %d != %d\n", i, ret_length, data[i].ret_length); for (int j = 0; j < (int) ret_length; j++) { assert_equal(gbdata[j], data[i].expected_gbdata[j], "i:%d gbdata[%d] %04X != %04X\n", i, j, gbdata[j], data[i].expected_gbdata[j]); } @@ -227,7 +227,7 @@ static void test_gb2312_cpy(int index) { char *data; int length; int ret; - size_t ret_length; + int ret_length; unsigned int expected_gbdata[20]; char *comment; }; @@ -254,10 +254,10 @@ static void test_gb2312_cpy(int index) { if (index != -1 && i != index) continue; int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; - size_t ret_length = length; + int ret_length = length; gb2312_cpy((unsigned char *) data[i].data, &ret_length, gbdata, data[i].full_multibyte); - assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %zu != %zu\n", i, ret_length, data[i].ret_length); + assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %d != %d\n", i, ret_length, data[i].ret_length); for (int j = 0; j < (int) ret_length; j++) { assert_equal(gbdata[j], data[i].expected_gbdata[j], "i:%d gbdata[%d] %04X != %04X\n", i, j, gbdata[j], data[i].expected_gbdata[j]); } diff --git a/backend/tests/test_gridmtx.c b/backend/tests/test_gridmtx.c index 719b117b..81e14822 100644 --- a/backend/tests/test_gridmtx.c +++ b/backend/tests/test_gridmtx.c @@ -210,7 +210,7 @@ static void test_input(int index, int generate, int debug) { /* 44*/ { UNICODE_MODE, 0, -1, " 200mA至", 0, 0, "2F 60 40 00 60 2B 78 63 41 7F 40", "M6 H1 (GB 2312)" }, /* 45*/ { UNICODE_MODE, 0, -1, "2A tel:86 019 82512738", 0, 0, "28 22 5F 4F 29 48 5F 6D 7E 6F 55 57 1F 28 63 0F 5A 11 64 0F 74", "M2 L5(with control) N15 (ASCII)" }, /* 46*/ { UNICODE_MODE, 0, -1, "至2A tel:86 019 82512738", 0, 0, "30 07 56 60 4C 48 13 6A 32 17 7B 3F 5B 75 35 67 6A 18 63 76 44 39 03 7D 00", "B4 L5(with control) N15 (GB 2312)" }, - /* 47*/ { UNICODE_MODE, 0, -1, "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738", 0, 0, "(62) 29 22 22 1C 4E 41 42 7E 0A 40 14 00 37 7E 6F 00 62 7E 2C 00 1C 7E 4B 00 41 7E 18 00", "M8 H11 M6 B4 L5(with control) N15 (GB 2312) (*NOT SAME* as D3 example, M8 H11 M6 H1 M3 L4(with control) N15, which uses a few more bits)" }, + /* 47*/ { UNICODE_MODE, 0, -1, "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738", 0, 0, "(62) 29 22 22 1C 4E 41 42 7E 0A 40 14 00 37 7E 6F 00 62 7E 2C 00 1C 7E 4B 00 41 7E 18 00", "M8 H11 M6 B4 L5(with control) N15 (GB 2312) (*NOT SAME* as D3 example Figure D.1, M8 H11 M6 H1 M3 L4(with control) N15, which uses a few more bits)" }, /* 48*/ { UNICODE_MODE, 0, -1, "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::", 0, 0, "(588) 37 68 68 68 68 68 74 7E 74 74 74 74 74 3A 3A 3A 3A 3A 3A 3A 1D 1D 1D 1D 1D 1D 1D 0E", "B512 (ASCII)" }, /* 49*/ { UNICODE_MODE, 0, -1, "::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\177", 0, 0, "(591) 37 68 68 68 68 68 74 7E 74 74 74 74 74 3A 3A 3A 3A 3A 3A 3A 1D 1D 1D 1D 1D 1D 1D 0E", "B513 (ASCII)" }, /* 50*/ { UNICODE_MODE, 0, -1, ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::至", 0, 0, "(591) 37 68 68 68 68 68 74 7C 74 74 74 74 74 3A 3A 3A 3A 3A 3A 3A 1D 1D 1D 1D 1D 1D 1D 0E", "B511 H1 (GB 2312)" }, @@ -297,7 +297,7 @@ static void test_encode(int index, int generate, int debug) { "111111000000100001" "111111000000111111" }, - /* 1*/ { "Grid Matrix", UNICODE_MODE, 5, -1, 0, 30, 30, "", + /* 1*/ { "Grid Matrix", UNICODE_MODE, 5, -1, 0, 30, 30, "AIMD014 Figure 1 **NOT SAME** different encodation, uses Upper and Lower whereas figure uses Mixed and Lower", "111111000000111111000000111111" "110111010110110111010110110011" "100011011110111111011110111111" @@ -329,7 +329,7 @@ static void test_encode(int index, int generate, int debug) { "101111010010100001010010110111" "111111000000111111000000111111" }, - /* 2*/ { "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738", UNICODE_MODE, 3, 3, 0, 42, 42, "", + /* 2*/ { "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738", UNICODE_MODE, 3, 3, 0, 42, 42, "AIMD014 Figure D.1 **NOT SAME** different encodation, see test_input dataset", "111111000000111111000000111111000000111111" "101101001100101111001010101011001100101101" "110001011010110101010000100011000000100001" @@ -423,6 +423,89 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +#include + +#define TEST_PERF_ITERATIONS 1000 + +// Not a real test, just performance indicator +static void test_perf(int index, int debug) { + + if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */ + return; + } + + int ret; + struct item { + int symbology; + int input_mode; + int option_1; + int option_2; + char *data; + int ret; + + int expected_rows; + int expected_width; + char *comment; + }; + struct item data[] = { + /* 0*/ { BARCODE_GRIDMATRIX, UNICODE_MODE, -1, -1, + "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738 AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738", + 0, 66, 66, "97 chars, mixed modes" }, + /* 1*/ { BARCODE_GRIDMATRIX, UNICODE_MODE, -1, -1, + "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738 AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738" + "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738 AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738" + "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738 AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738" + "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738 AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738" + "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738 AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738" + "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738 AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738" + "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738 AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738" + "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738 AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738" + "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738 AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738" + "AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738 AAT2556 电池充电器+降压转换器 200mA至2A tel:86 019 82512738", + 0, 162, 162, "970 chars, mixed modes" }, + }; + int data_size = ARRAY_SIZE(data); + + clock_t start, total_encode = 0, total_buffer = 0, diff_encode, diff_buffer; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + diff_encode = diff_buffer = 0; + + for (int j = 0; j < TEST_PERF_ITERATIONS; j++) { + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + int length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, data[i].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); + + 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); + + total_encode += diff_encode; + total_buffer += diff_buffer; + } + if (index != -1) { + printf("totals: encode %gms, buffer %gms\n", total_encode * 1000.0 / CLOCKS_PER_SEC, total_buffer * 1000.0 / CLOCKS_PER_SEC); + } +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ @@ -430,6 +513,7 @@ int main(int argc, char *argv[]) { { "test_options", test_options, 1, 0, 1 }, { "test_input", test_input, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_perf", test_perf, 1, 0, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_hanxin.c b/backend/tests/test_hanxin.c index d9568ffd..7f38fa33 100644 --- a/backend/tests/test_hanxin.c +++ b/backend/tests/test_hanxin.c @@ -88,29 +88,29 @@ static void test_options(int index, int debug) { int ret; struct item { - char *data; int option_1; int option_2; + char *data; int ret_encode; int ret_vector; int expected_size; }; // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { "12345", -1, -1, 0, 0, 23 }, // Default version 1, ECC auto-set to 4 - /* 1*/ { "12345", 1, -1, 0, 0, 23 }, - /* 2*/ { "12345", -1, 2, 0, 0, 25 }, - /* 3*/ { "12345", -1, 85, 0, 0, 23 }, // Version > max version 85 so ignored - /* 4*/ { "12345", -1, 84, 0, 0, 189 }, - /* 5*/ { "1234567890123456789012345678901234567890123", 1, 1, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 6*/ { "1234567890123456", 4, 1, ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 7*/ { "12345678901234567", 4, 2, 0, 0, 25 }, - /* 8*/ { "12345678901234567", 4, -1, 0, 0, 25 }, // Version auto-set to 2 - /* 9*/ { "12345678901234567", -1, -1, 0, 0, 23 }, // Version auto-set to 1, ECC auto-set to 3 - /* 10*/ { "12345678901234567", 5, -1, 0, 0, 23 }, // ECC > max ECC 4 so ignored and auto-settings version 1, ECC 3 used - /* 11*/ { "1234567890123456789012345678901234567890123", -1, -1, 0, 0, 25 }, // Version auto-set to 2, ECC auto-set to 2 + /* 0*/ { -1, -1, "12345", 0, 0, 23 }, // Default version 1, ECC auto-set to 4 + /* 1*/ { 1, -1, "12345", 0, 0, 23 }, + /* 2*/ { -1, 2, "12345", 0, 0, 25 }, + /* 3*/ { -1, 85, "12345", 0, 0, 23 }, // Version > max version 85 so ignored + /* 4*/ { -1, 84, "12345", 0, 0, 189 }, + /* 5*/ { 1, 1, "1234567890123456789012345678901234567890123", ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 6*/ { 4, 1, "1234567890123456", ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 7*/ { 4, 2, "12345678901234567", 0, 0, 25 }, + /* 8*/ { 4, -1, "12345678901234567", 0, 0, 25 }, // Version auto-set to 2 + /* 9*/ { -1, -1, "12345678901234567", 0, 0, 23 }, // Version auto-set to 1, ECC auto-set to 3 + /* 10*/ { 5, -1, "12345678901234567", 0, 0, 23 }, // ECC > max ECC 4 so ignored and auto-settings version 1, ECC 3 used + /* 11*/ { -1, -1, "1234567890123456789012345678901234567890123", 0, 0, 25 }, // Version auto-set to 2, ECC auto-set to 2 }; - int data_size = sizeof(data) / sizeof(struct item); + int data_size = ARRAY_SIZE(data); for (int i = 0; i < data_size; i++) { @@ -119,16 +119,7 @@ static void test_options(int index, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = BARCODE_HANXIN; - if (data[i].option_1 != -1) { - symbol->option_1 = data[i].option_1; - } - if (data[i].option_2 != -1) { - symbol->option_2 = data[i].option_2; - } - symbol->debug |= debug; - - int length = strlen(data[i].data); + int length = testUtilSetSymbol(symbol, BARCODE_HANXIN, -1 /*input_mode*/, -1 /*eci*/, data[i].option_1, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret_encode, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret_encode, symbol->errtxt); @@ -176,25 +167,25 @@ static void test_input(int index, int generate, int debug) { /* 1*/ { UNICODE_MODE, 3, -1, "é", -1, 0, 3, "80 33 00 0F 48 00 00 00 00", "ECI-3 B1 (ISO 8859-1)" }, /* 2*/ { UNICODE_MODE, 29, -1, "é", -1, 0, 29, "81 D4 FC FF FF 00 00 00 00", "ECI-29 H(1)1 (GB 18030) (Region One)" }, /* 3*/ { UNICODE_MODE, 26, -1, "é", -1, 0, 26, "81 A3 00 16 1D 48 00 00 00", "ECI-26 B2 (UTF-8)" }, - /* 4*/ { UNICODE_MODE, 26, 200, "é", -1, 0, 26, "81 A4 70 2F FF 00 00 00 00", "ECI-26 H(1)1 (Region One) (UTF-8) (full multibyte)" }, + /* 4*/ { UNICODE_MODE, 26, ZINT_FULL_MULTIBYTE, "é", -1, 0, 26, "81 A4 70 2F FF 00 00 00 00", "ECI-26 H(1)1 (Region One) (UTF-8) (full multibyte)" }, /* 5*/ { DATA_MODE, 0, -1, "é", -1, 0, 0, "30 01 61 D4 80 00 00 00 00", "B2 (UTF-8)" }, - /* 6*/ { DATA_MODE, 0, 200, "é", -1, 0, 0, "47 02 FF F0 00 00 00 00 00", "H(1)1 (UTF-8) (Region One) (full multibyte)" }, + /* 6*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "é", -1, 0, 0, "47 02 FF F0 00 00 00 00 00", "H(1)1 (UTF-8) (Region One) (full multibyte)" }, /* 7*/ { DATA_MODE, 0, -1, "\351", -1, 0, 0, "30 00 F4 80 00 00 00 00 00", "B1 (ISO 8859-1) (0xE9)" }, /* 8*/ { UNICODE_MODE, 0, -1, "β", -1, 0, 0, "30 01 53 61 00 00 00 00 00", "B2 (GB 18030) (2-byte Region)" }, /* 9*/ { UNICODE_MODE, 9, -1, "β", -1, 0, 9, "80 93 00 0F 10 00 00 00 00", "ECI-9 B1 (ISO 8859-7)" }, /* 10*/ { UNICODE_MODE, 29, -1, "β", -1, 0, 29, "81 D3 00 15 36 10 00 00 00", "ECI-29 B2 (GB 18030) (2-byte Region)" }, /* 11*/ { UNICODE_MODE, 26, -1, "β", -1, 0, 26, "81 A3 00 16 75 90 00 00 00", "ECI-26 B2 (UTF-8)" }, - /* 12*/ { UNICODE_MODE, 26, 200, "β", -1, 0, 26, "81 A4 B1 5F FF 00 00 00 00", "ECI-26 B2 (UTF-8) (full multibyte)" }, + /* 12*/ { UNICODE_MODE, 26, ZINT_FULL_MULTIBYTE, "β", -1, 0, 26, "81 A4 B1 5F FF 00 00 00 00", "ECI-26 B2 (UTF-8) (full multibyte)" }, /* 13*/ { DATA_MODE, 0, -1, "β", -1, 0, 0, "30 01 67 59 00 00 00 00 00", "B2 (UTF-8)" }, - /* 14*/ { DATA_MODE, 0, 200, "β", -1, 0, 0, "4B 15 FF F0 00 00 00 00 00", "H(1)1 (UTF-8) (Region One) (full multibyte)" }, + /* 14*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "β", -1, 0, 0, "4B 15 FF F0 00 00 00 00 00", "H(1)1 (UTF-8) (Region One) (full multibyte)" }, /* 15*/ { UNICODE_MODE, 0, -1, "ÿ", -1, 0, 0, "30 00 FF 80 00 00 00 00 00", "B1 (ISO 8859-1)" }, /* 16*/ { UNICODE_MODE, 0, -1, "ÿÿÿ", -1, 0, 0, "30 01 FF FF FF 80 00 00 00", "B3 (ISO 8859-1)" }, /* 17*/ { UNICODE_MODE, 0, -1, "\302\200", -1, 0, 0, "70 00 00 00 00 00 00 00 00", "H(f)1 (GB 18030) (4-byte Region) (not DATA_MODE so GB 18030 mapping)" }, - /* 18*/ { UNICODE_MODE, 0, 200, "\302\200", -1, 0, 0, "70 00 00 00 00 00 00 00 00", "H(f)1 (GB 18030) (4-byte Region)" }, + /* 18*/ { UNICODE_MODE, 0, ZINT_FULL_MULTIBYTE, "\302\200", -1, 0, 0, "70 00 00 00 00 00 00 00 00", "H(f)1 (GB 18030) (4-byte Region)" }, /* 19*/ { DATA_MODE, 0, 0, "\302\200", -1, 0, 0, "30 01 61 40 00 00 00 00 00", "B2 (UTF-8)" }, - /* 20*/ { DATA_MODE, 0, 200, "\302\200", -1, 0, 0, "30 01 61 40 00 00 00 00 00", "B2 (UTF-8) (full multibyte)" }, + /* 20*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "\302\200", -1, 0, 0, "30 01 61 40 00 00 00 00 00", "B2 (UTF-8) (full multibyte)" }, /* 21*/ { UNICODE_MODE, 0, -1, "\302\200�", -1, 0, 0, "70 00 00 38 26 7E 40 00 00", "H(f)2 (GB 18030) (both 4-byte Region) (not DATA_MODE so GB 18030 mapping)" }, - /* 22*/ { UNICODE_MODE, 0, 200, "\302\200�", -1, 0, 0, "70 00 00 38 26 7E 40 00 00", "H(f)2 (GB 18030) (both 4-byte Region)" }, + /* 22*/ { UNICODE_MODE, 0, ZINT_FULL_MULTIBYTE, "\302\200�", -1, 0, 0, "70 00 00 38 26 7E 40 00 00", "H(f)2 (GB 18030) (both 4-byte Region)" }, /* 23*/ { UNICODE_MODE, 0, -1, "啊亍齄丂\302\200", -1, 0, 0, "64 68 50 3C AC 28 80 00 FF FE E0 00 00 00 00 00 00", "H(d)4 H(f)1 (GB 18030)" }, /* 24*/ { DATA_MODE, 0, -1, "\177\177", -1, 0, 0, "2F BD F7 F0 00 00 00 00 00", "T2 (ASCII)" }, /* 25*/ { DATA_MODE, 0, -1, "\177\177\177", -1, 0, 0, "2F BD F7 DF C0 00 00 00 00", "T3 (ASCII)" }, @@ -205,9 +196,16 @@ static void test_input(int index, int generate, int debug) { /* 30*/ { DATA_MODE, 0, -1, "Summer Palace Ticket for 6 June 2015 13:00;2015年6月6日夜01時00分PM頤和園のチケット;2015년6월6일13시오후여름궁전티켓.2015年6月6号下午13:00的颐和园门票;", -1, 0, 0, "(209) 27 38 C3 0A 35 F9 CF 99 92 F9 26 A3 E7 3E 76 C9 AE A3 7F CC 15 04 0C CD EE 44 06 C4", "T20 B117 (UTF-8)" }, /* 31*/ { UNICODE_MODE, 0, -1, "\000\014\033 #/059:<@AMZ", 15, 0, 0, "2F 80 31 B7 1F AF E0 05 27 EB 2E CB E2 96 8F F0 00", "T15 (ASCII)" }, /* 32*/ { UNICODE_MODE, 0, -1, "Z[\\`alz{~\177", -1, 0, 0, "28 FE CF 4E 3E 92 FF 7E E7 CF 7F 00 00", "T10 (ASCII)" }, - /* 33*/ { UNICODE_MODE, 26, 200, "\202\061\203\063", -1, 0, 26, "81 A7 01 B1 D8 00 00 00 00", "ECI-26 H(f)1 (GB 18030) (Invalid UTF-8, forces GB 2312/18030 utf8tosb() difference)" }, + /* 33*/ { UNICODE_MODE, 26, ZINT_FULL_MULTIBYTE, "\202\061\203\063", -1, 0, 26, "81 A7 01 B1 D8 00 00 00 00", "ECI-26 H(f)1 (GB 18030) (Invalid UTF-8, forces GB 2312/18030 utf8tosb() difference)" }, + /* 34*/ { UNICODE_MODE, 128, 0, "A", -1, 0, 128, "88 08 02 2B F0 00 00 00 00", "ECI > 127" }, + /* 35*/ { UNICODE_MODE, 16364, 0, "A", -1, 0, 16364, "8B FE C2 2B F0 00 00 00 00", "ECI > 16363" }, + /* 36*/ { UNICODE_MODE, 0, -1, "啊啊啊亍", -1, 0, 0, "40 00 00 00 00 FF E0 00 FF F0 00 00 00", "Region 1 (FFE terminator) -> Region 2 (no indicator)" }, + /* 37*/ { UNICODE_MODE, 0, -1, "亍亍亍啊", -1, 0, 0, "50 00 00 00 00 FF E0 00 FF F0 00 00 00", "Region 2 (FFE terminator) -> Region 1 (no indicator)" }, + /* 38*/ { UNICODE_MODE, 0, -1, "啊啊啊啊亍亍啊", -1, 0, 0, "40 00 00 00 00 00 0F FE 00 00 00 FF E0 00 FF F0 00", "Region 1 (FFE) -> Region 2 (FFE) -> Region 1" }, + /* 39*/ { UNICODE_MODE, 0, -1, "亍亍亍亍啊啊亍", -1, 0, 0, "50 00 00 00 00 00 0F FE 00 00 00 FF E0 00 FF F0 00", "Region 2 (FFE) -> Region 1 (FFE) -> Region 2" }, + /* 40*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE | (2 << 8), "é", -1, 0, 0, "47 02 FF F0 00 00 00 00 00", "H(1)1 (UTF-8) (Region One) (full multibyte with mask)" }, }; - int data_size = sizeof(data) / sizeof(struct item); + int data_size = ARRAY_SIZE(data); char escaped[1024]; @@ -218,23 +216,17 @@ static void test_input(int index, int generate, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = BARCODE_HANXIN; - symbol->input_mode = data[i].input_mode; - symbol->eci = data[i].eci; - if (data[i].option_3 != -1) { - symbol->option_3 = data[i].option_3; - } - symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - symbol->debug |= debug; + debug |= ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; + int length = testUtilSetSymbol(symbol, BARCODE_HANXIN, data[i].input_mode, data[i].eci, -1 /*option_1*/, -1, data[i].option_3, -1 /*output_options*/, data[i].data, data[i].length, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, %d, %d, \"%s\", %d, %s, %d, \"%s\", \"%s\" },\n", - i, testUtilInputModeName(data[i].input_mode), data[i].eci, data[i].option_3, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].length, + printf(" /*%3d*/ { %s, %d, %s, \"%s\", %d, %s, %d, \"%s\", \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), data[i].eci, testUtilOption3Name(data[i].option_3), + testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].length, testUtilErrorName(data[i].ret), ret < 5 ? symbol->eci : -1, symbol->errtxt, data[i].comment); } else { if (ret < 5) { @@ -255,10 +247,11 @@ static void test_encode(int index, int generate, int debug) { int ret; struct item { - char *data; int input_mode; int option_1; int option_2; + int option_3; + char *data; int ret; int expected_rows; @@ -267,32 +260,82 @@ static void test_encode(int index, int generate, int debug) { char *expected; }; struct item data[] = { - /* 0*/ { "1234", UNICODE_MODE, -1, -1, 0, 23, 23, "", - "11111110101000101111111" - "10000000010001000000001" - "10111110101110001111101" - "10100000101011000000101" - "10101110010011101110101" - "10101110101111101110101" - "10101110011010001110101" - "00000000110001100000000" - "00010101111011001010101" - "01001010101101000111110" - "10101101001010101010100" - "11011101010100100010010" - "10101010010011101010100" - "01010100111110000011110" - "10101010001011110101000" - "00000000110111100000000" - "11111110011001001110101" - "00000010110000101110101" - "11111010101110001110101" - "00001010010110100000101" - "11101010001100101111101" - "11101010000011000000001" - "11101010101010101111111" - }, - /* 1*/ { "1234567890", UNICODE_MODE, 1, 1, 0, 23, 23, "**NOT SAME** as ISO 20830 Draft K.1 Example 1, uses masking pattern 2 instead of pattern 1; however matches pattern 2 example (excluding Function Info)", + /* 0*/ { UNICODE_MODE, -1, -1, -1, "1234", 0, 23, 23, "Mode nnnn, mask 10", + "11111110101011001111111" + "10000000000000100000001" + "10111110111011101111101" + "10100000010111100000101" + "10101110011101101110101" + "10101110000101001110101" + "10101110111001101110101" + "00000000100000000000000" + "00010101101110000010101" + "01010110110001011011101" + "00100011000100100100101" + "01110111111110001000111" + "01001001110000001001000" + "00100101001111110010000" + "10101000011110110101000" + "00000000001011100000000" + "11111110110111101110101" + "00000010011010001110101" + "11111010101101001110101" + "00001010100111000000101" + "11101010111001101111101" + "11101010111111000000001" + "11101010000100101111111" + }, + /* 1*/ { UNICODE_MODE, 1, 1, -1, "1234567890", 0, 23, 23, "ISO 20830 Draft K.1 Figure K8 (& K5) same (mask 01), except no alternating filler in structural info in figure", + "11111110001000001111111" + "10000000110001100000001" + "10111110001010101111101" + "10100000111011100000101" + "10101110010000101110101" + "10101110110101001110101" + "10101110001100001110101" + "00000000011101100000000" + "00010101001010011010101" + "01001101111101010101110" + "10101010101010100101101" + "01010010111101010101010" + "10101010101010101010100" + "10000011010101000011110" + "10101011001010010101000" + "00000000110100000000000" + "11111110011110001110101" + "00000010010101101110101" + "11111010101010001110101" + "00001010110010100000101" + "11101010100010001111101" + "11101010110101100000001" + "11101010001010001111111" + }, + /* 2*/ { UNICODE_MODE, 1, 1, 1 << 8, "1234567890", 0, 23, 23, "ISO 20830 Draft K.1 Figure K4, with explicit mask pattern 00, same except no alternating filler in figure", + "11111110100010101111111" + "10000000000100100000001" + "10111110000000101111101" + "10100000001110000000101" + "10101110111010101110101" + "10101110000000001110101" + "10101110000110001110101" + "00000000001000100000000" + "00010101000000100010101" + "00011000101000000000100" + "00000000000000001111000" + "00000111101000000000000" + "00000000000000000000001" + "11010110000000010110100" + "10101000100000010101000" + "00000000100001000000000" + "11111110010100001110101" + "00000010000000001110101" + "11111010100000101110101" + "00001010000111000000101" + "11101010101000001111101" + "11101010100000000000001" + "11101010100000101111111" + }, + /* 3*/ { UNICODE_MODE, 1, 1, 3 << 8, "1234567890", 0, 23, 23, "ISO 20830 Draft K.1 Figure K6, with explicit mask pattern 10, same except no alternating filler in figure", "11111110001011101111111" "10000000100000000000001" "10111110011111001111101" @@ -316,8 +359,33 @@ static void test_encode(int index, int generate, int debug) { "11101010010111001111101" "11101010001001100000001" "11101010100100001111111" - }, - /* 2*/ { "1234567890ABCDEFGabcdefg,Han Xin Code", UNICODE_MODE, 3, 10, 0, 41, 41, "Same as ISO 20830 Draft K.2 Example 2 (happens to use same mask pattern, 2)", + }, + /* 4*/ { UNICODE_MODE, 1, 1, 4 << 8, "1234567890", 0, 23, 23, "ISO 20830 Draft K.1 Figure K7, with explicit mask pattern 11, same except no alternating filler in figure", + "11111110101111001111111" + "10000000000011000000001" + "10111110000000001111101" + "10100000110110100000101" + "10101110100010101110101" + "10101110100111101110101" + "10101110111111101110101" + "00000000001111000000000" + "00010101000111101010101" + "00000010110000111000011" + "10011010011111001000011" + "11000010000111000111000" + "01000101101110111000110" + "00010001101101010001100" + "10101010110010010101000" + "00000000010011000000000" + "11111110100110101110101" + "00000010101101101110101" + "11111010101101101110101" + "00001010101010100000101" + "11101010011010001111101" + "11101010011010000000001" + "11101010011010101111111" + }, + /* 5*/ { UNICODE_MODE, 3, 10, -1, "1234567890ABCDEFGabcdefg,Han Xin Code", 0, 41, 41, "ISO 20830 Draft K.2 Figure K16 (& K14) (happens to use same mask pattern 10), same except for alternating filler", "11111110001011000000100000010101101111111" "10000000001011110010000000011010100000001" "10111110111111111010111011101111101111101" @@ -359,8 +427,137 @@ static void test_encode(int index, int generate, int debug) { "11101010111111111100101100001111101111101" "11101010101001001000101001001001000000001" "11101010100100100100111111111111001111111" - }, - /* 3*/ { "Summer Palace Ticket for 6 June 2015 13:00;2015年6月6日夜01時00分PM頤和園のチケット;2015년6월6일13시오후여름궁전티켓.2015年6月6号下午13:00的颐和园门票;", UNICODE_MODE, 2, 17, 0, 55, 55, "**NOT SAME** as ISO 20830 Draft K.3 Example 3, different encoding modes; if same encoding modes forced, uses masking pattern 1 instead of pattern 2, but matches pattern 1 example (excluding Function Info)", + }, + /* 6*/ { UNICODE_MODE, 3, 10, 1 << 8, "1234567890ABCDEFGabcdefg,Han Xin Code", 0, 41, 41, "ISO 20830 Draft K.2 Figure K12 explicit mask pattern 00, same except for alternating filler", + "11111110100010001000101001011100101111111" + "10000000101111010110000100111110000000001" + "10111110100000000101000100010000001111101" + "10100000100000000000000000000000100000101" + "10101110100000000001110110110011001110101" + "10101110001000001000000100010011001110101" + "10101110000110000000010100111010101110101" + "00000000011101000000000000000000000000000" + "00011110100000000000000110010000000010101" + "11111010010101111011000000101001000000000" + "11101000000000000000000000000000000000000" + "10000000110001010010100100001100100001001" + "11101000000000001000101000011011000000000" + "10000000000000000000000001000000101010111" + "11100000011101001111110000000000010111110" + "11111001000000000000000000000000000000000" + "10001111111010100111101001011101000000000" + "10000000111001101010000100000000000000000" + "10000000000000001111010000111110101001011" + "10011010000000000000000010101010111111100" + "11111111111111111111100000000000000000001" + "00000000000000000000100000000000000010000" + "01010010001101101110101100110010000000000" + "00000000010001101100111100000000000000000" + "00000000000000000100111000100110010100010" + "00001011000000000000100000101001101001010" + "00000000000000000000100000000000000110000" + "11011111101001100110110011010000000000000" + "00001101001000000110100000000000000000000" + "00000000000001001110100111001111001111010" + "01001000000000000000100010010101001101100" + "00000000000000000000100000000000001111011" + "10101000011010001010100100011101101111000" + "00000000011000000000100000000110000000000" + "11111110101111000000100000000000001110101" + "00000010000000000000100000000000001110101" + "11111010000000001000110110110010101110101" + "00001010100001011100101110000000100000101" + "11101010000000000010110011110000101111101" + "11101010000000000000100000000000100000001" + "11101010100000000000111111111111101111111" + }, + /* 7*/ { UNICODE_MODE, 3, 10, 2 << 8, "1234567890ABCDEFGabcdefg,Han Xin Code", 0, 41, 41, "ISO 20830 Draft K.2 Figure K13 explicit mask pattern 01, same except for alternating filler", + "11111110001000100010100011110110001111111" + "10000000011010000010000001101011000000001" + "10111110101010101111101110111010001111101" + "10100000010101010101010101010101000000101" + "10101110001010101011011100011001001110101" + "10101110111101011101010001000110001110101" + "10101110001100101010111110010000101110101" + "00000000001000010101010101010101000000000" + "00011110101010101010101100111010111010101" + "10101111000000101110010101111100010101010" + "11000010101010101010101010101010101010101" + "11010101100100000111110001011001110100011" + "11000010101010100010000010110001101010101" + "11010101010101010101010100010101111111101" + "11001010110111100101011010101010111101011" + "10101100010101010101010101010101010101010" + "10100101010000001101000011110111101010101" + "11010101101100111111010001010101010101010" + "10101010101010100101111010010100000011110" + "11001111010101010101010111111111101010100" + "11111111111111111111101010101010101010101" + "00000000000000000000110101010101010111000" + "11111000100111000100100110011000101010101" + "01010101000100111000101001010101010101010" + "10101010101010101110110010001100111110111" + "01011110010101010100110101111100111100000" + "10101010101010101010101010101010101100101" + "10001010111100110010100110000101010101010" + "10100111100010101100101010101010101010101" + "01010101010100011010110010011010011010000" + "11100010101010101010101000111111100111001" + "01010101010101010100110101010101011010001" + "10101011110000100000101110110111101111000" + "00000000001101010100110101010011000000000" + "11111110100101101010101010101010001110101" + "00000010010101010100110101010101101110101" + "11111010001010100010111100011000001110101" + "00001010010100001000111011010101000000101" + "11101010001010101000111001011010101111101" + "11101010010101010100110101010101000000001" + "11101010001010101010111111111111001111111" + }, + /* 8*/ { UNICODE_MODE, 3, 10, 4 << 8, "1234567890ABCDEFGabcdefg,Han Xin Code", 0, 41, 41, "ISO 20830 Draft K.2 Figure K15 explicit mask pattern 11, same except for alternating filler", + "11111110101111100100100100110001001111111" + "10000000101000010000000011111001100000001" + "10111110100000000101000100010000101111101" + "10100000011000111000111000111000000000101" + "10101110111000000111001101110011001110101" + "10101110101111001111000011010100101110101" + "10101110111111000111101100011101001110101" + "00000000011010000111000111000111100000000" + "00011110100111000000111110010111001010101" + "11100000001101000011111000010001111000111" + "11110010011111000111011000111000000111000" + "11000101011110010101100011001011100110001" + "10101101101110110000010001011100000111111" + "11000111101101000111000110000111101101111" + "11110000001111101000110111000000101111001" + "11101001010010011000111000111000111000111" + "10011111101000111000101110011010011000111" + "11001111110100000101000011000111000111000" + "11001111001101100001101000000110010000011" + "11011101001101101101000101101101111000100" + "11111111111111111111100111000111000111001" + "00000000000000000000111000111000111010100" + "11001000110111111100110011110101000111000" + "11000101010100000000110011000111000111000" + "01001101000101101000110110011110101100101" + "11000110000111101100101101101110101110010" + "10010010011000010010110010100111000001000" + "11001111110001110100100001001000111000111" + "10011101010000010100110010011111000111000" + "11000111100110000010101010100000001000010" + "00001111100111001100101111111011110101011" + "11000111100111001100101101101101001000011" + "10101010001010111000110110001111101111000" + "00000000101000111010110010010100000000000" + "11111110011111111010110010010010101110101" + "00000010101111000100101101101101101110101" + "11111010001111001100111011011111101110101" + "00001010001110011010100011101101000000101" + "11101010110010111010100001100010101111101" + "11101010110010111000110010010010100000001" + "11101010010010111000111111111111101111111" + }, + /* 9*/ { UNICODE_MODE, 2, 17, -1, "Summer Palace Ticket for 6 June 2015 13:00;2015年6月6日夜01時00分PM頤和園のチケット;2015년6월6일13시오후여름궁전티켓.2015年6月6号下午13:00的颐和园门票;", 0, 55, 55, "**NOT SAME** as ISO 20830 Draft K.3 Figure K23, different encoding modes; if same encoding modes forced, uses mask pattern 01 instead of pattern 10, but matches pattern 01 example Figure K20 (excluding alternating filler) (forced encoding mode: ttttttttttttttttttttttttttttttttttttttttttttttt1t1t11ttdtt1ttddddddddtttttfftfftffttffffffffffffffffffttttt1t1t111ttttt111111t)", "1111111001111111111011100100110101101010101100101111111" "1000000000000000001100011000011001000010101111100000001" "1011111011110010101110010110100000111010101101101111101" @@ -416,9 +613,804 @@ static void test_encode(int index, int generate, int debug) { "1110101010111000101011111101011101111100001110101111101" "1110101011010101001101010101010101000000001010000000001" "1110101011010001001111111111111111101000001110001111111" - }, + }, + /* 10*/ { UNICODE_MODE, -1, -1, -1, "汉信码标准", 0, 23, 23, "ISO 20830 Draft Figure 4, **NOT SAME**, uses mask 11 instead of 10 (note figure includes alternating filler)", + "11111110000101001111111" + "10000000001000100000001" + "10111110110001001111101" + "10100000100100000000101" + "10101110110011001110101" + "10101110111101101110101" + "10101110101100101110101" + "00000000011001100000000" + "00010101110110000010101" + "01010010101111101111001" + "11110010001011001101110" + "01010110010010010011001" + "11110011100000000111000" + "11100110010101000010101" + "10101000010010110101000" + "00000000110011000000000" + "11111110111011101110101" + "00000010101101101110101" + "11111010001100101110101" + "00001010011111100000101" + "11101010011010101111101" + "11101010111010000000001" + "11101010011010001111111" + }, + /* 11*/ { UNICODE_MODE, -1, -1, 3 << 8, "汉信码标准", 0, 23, 23, "ISO 20830 Draft Figure 4, explict mask 10, same", + "11111110100001101111111" + "10000000101011100000001" + "10111110101110001111101" + "10100000010101100000101" + "10101110001111001110101" + "10101110000101101110101" + "10101110111100101110101" + "00000000011010100000000" + "00010101101110111010101" + "00000001111110011110111" + "01001100110000101110001" + "01101100000010101011110" + "11111111000111110110110" + "00000101011100100001001" + "10101011111111110101000" + "00000000101000000000000" + "11111110101101101110101" + "00000010111111001110101" + "11111010001000001110101" + "00001010110110000000101" + "11101010010111101111101" + "11101010101001100000001" + "11101010100100101111111" + }, + /* 12*/ { UNICODE_MODE | ESCAPE_MODE, -1, 4, -1, "汉信码标准\015\012中国物品编码中心", 0, 29, 29, "ISO 20830 Draft Figure 5, **NOT SAME** uses mask 11 instead of 01", + "11111110000100101110101111111" + "10000000101110001001000000001" + "10111110111111111110001111101" + "10100000100100110100100000101" + "10101110001110001100101110101" + "10101110101111110111101110101" + "10101110111001111001101110101" + "00000000001000101101000000000" + "00011000111000000111100010101" + "10111010011011110000101001011" + "11100001011111000101000011011" + "10100000100100111100011010000" + "11001111001110010000001111100" + "11100000010111100111111000100" + "11111111111111101010110110101" + "00000000000000110101011111100" + "01111101011000101100111000101" + "01110101111110101110000100110" + "00000010111010111000111000110" + "00111111000100100010010110111" + "10101000100000111111100011000" + "00000000011110100101000000000" + "11111110100010100000101110101" + "00000010111100101101101110101" + "11111010101110110010001110101" + "00001010100000110011100000101" + "11101010011000100111101111101" + "11101010010110100010100000001" + "11101010111000111111001111111" + }, + /* 13*/ { UNICODE_MODE | ESCAPE_MODE, -1, 4, 2 << 8, "汉信码标准\015\012中国物品编码中心", 0, 29, 29, "ISO 20830 Draft Figure 5, explicit mask 01, same", + "11111110100010101001101111111" + "10000000011100001011100000001" + "10111110110101010100101111101" + "10100000101001011001100000101" + "10101110111100100000101110101" + "10101110111101100101001110101" + "10101110001010010100001110101" + "00000000011010111111100000000" + "00011000110101101101010010101" + "11110101010110011101000100110" + "11010001101010101000110001001" + "10110000011110101110001000010" + "10100000001010000010011100001" + "11110010101111110101101010100" + "11111111111111100111011011001" + "00000000000000111000110010000" + "01000111100000111001010101000" + "11101111100110110100010110100" + "11100111011100111100101010100" + "10101101011100111010000100101" + "10101001011000100111100011000" + "00000000110000100010000000000" + "11111110010010111000001110101" + "00000010001100110101101110101" + "11111010100000110101101110101" + "00001010110010101011100000101" + "11101010101010111111101111101" + "11101010111010100101000000001" + "11101010101010111111101111111" + }, + /* 14*/ { UNICODE_MODE | ESCAPE_MODE, -1, 24, -1, "汉信码标准\015\012中国物品编码中心\015\012北京网路畅想科技发展有限公司\015\012张成海、赵楠、黄燕滨、罗秋科、王毅、张铎、王越\015\012施煜、边峥、修兴强\015\012汉信码标准\015\012中国物品编码中心\015\012北京网路畅想科技发展有限公司", 0, 69, 69, "ISO 20830 Draft Figure 6 **NOT SAME** different encodation, Region 1 FFE terminators not used in figure", + "111111100000101101011111111111111111111001001110010100100010001111111" + "100000001100110100000000000000000010111100110000010001110101000000001" + "101111100111100011100101000110011011011110011110101101001000101111101" + "101000000010000111011010000110111010111100100011111100110000000000101" + "101011100000010010000110101000000011011100101011011111000111101110101" + "101011101101000100011000101010101011000000111001000110111100101110101" + "101011100010010010100011101010101010101010101010101010101010101110101" + "000000001110010000011101101011000011001011100111111010101010000000000" + "001011001010010010110100001010101011100110101000001010011011011010101" + "110101110101111001111100010010001010101010111011111111010100011010101" + "101101010101001001011100011011101010100011111000010100101101111011010" + "100101101010101100010100110001110010111010001001010101010101010101010" + "101010101000010100100100001011100011111110000101111011010000010011110" + "111110111100111000111001011101101011111001011111000111101100011101101" + "110010010110011111011010111110110010110010100010100110110101001010101" + "100111110010001001001110110110110010000011110011010011011101110001110" + "110000111000010110101010101010101010101010101010101011101100011110100" + "111111111111111111100101110001010011111111111111111111010100110100001" + "000000000000000001011011110011000000000000000000000110101001101000100" + "101010000010010001000000101101000011011110101100110111010101010110110" + "111000101001110101011100101110011100011100001001100101000011010110110" + "011001010011101101111111101011000111010001100010000111111110011110011" + "011010101010101001101010101010101010010011001110110101111011100000101" + "001111110001111101100000101001100010011110010011110110100000110010000" + "011000111100011101000000100010001011111101001110010111001100101001110" + "010011110011010101111111110000010010110000111100110111000100111001100" + "001010001110010101010000110111001011111001000010100110101010101010101" + "010101010000001101000101000000000110111100101101000100101011111000110" + "010100111011001001000010110111110010110101010100110100100000110011110" + "000110111011111001100011001111011111100010110110000101101111111010000" + "011010100001110001000111001000110110100111011010000101000101010010111" + "001111101110101101110101010101010101010101011010100101111100111001111" + "110001001111100101100010010001100011001111010010110110101101100011011" + "000000000010011001001101010111001111101010011001110111100101110111100" + "100010010011001001111111111111111111001000001100000111111111111111111" + "001000110111000000000000000000000011011111000001010000000000000000001" + "110110010101010011111001111011110011101011000100100110001101110000101" + "110101010101010101010101100011111011001011101100111000100010110010001" + "101111101000111110110100000000110011010100001101101010000000100100101" + "110010101010100000110111010011100010000001100010101010101001001100101" + "110100011010011000111011011010001010000001101001110000110001100001001" + "110001011100001010100111101010100011101001010101010101010101010100101" + "110101011110111110001010111011000011010101100010001111110111101001101" + "101000001011000111011000011101101010101011110100100110110000001011101" + "100000010000100111110110101100010011001010101100001111011010010000001" + "111011110101110011110111111110111010101001110101101001100000001100101" + "100111001001110010101010101010101010101011010011110101001001000011101" + "101010001010111111100110000011010010011110101111001010010110110110101" + "100101110111011101100110100001011011110010110001001101000111100001101" + "100100101100100101111001011110101011010110010010101000001010110011101" + "110010011100000000100100000110100010001010101011010100110010101010100" + "111111111111111111010101010101011011111111111111111110100101000000001" + "000000000000000001010000101001010000000000000000000101001000011110100" + "100000111111111001111001000110000111111100101111010101111001000000010" + "111000010111010101100110111110100001011110111111110101101011111010011" + "101100001011101001000000110010011011101100010010000111000101011011010" + "000100001101010001011010011111111010101010101010100110101011000011111" + "001001100001111001101010110100010111101000100001000100100100000000111" + "010100001000010101100010001011111010100100100111010111110110001101101" + "100000111101011001000100010101101000111111000001010111101110100001001" + "101010110100111101010001011011001110111111010011000110000101100110100" + "000000000010111101100011010101010101010101010101010101010000100000000" + "111111101101011001111010100000101000010101101111010100100100001110101" + "000000101101001001101001011100101111001111000000110101010100101110101" + "111110101101011001010101110100100010110111111100110111110101001110101" + "000010100111111001000111110110011100010110001010110110001110000000101" + "111010101001001001100110011111011101010101011011100101100011001111101" + "111010100100111101001001010101011000001101010101010101010101100000001" + "111010100010101001111111111111111010101010101010100111111111001111111" + }, + /* 15*/ { UNICODE_MODE | ESCAPE_MODE, -1, 40, -1, "本标准规定了一种矩阵式二维条码——汉信码的码制以及编译码方法。本标准中对汉信码的码图方案、信息编码方法、纠错编译码算法、信息排布方法、参考译码算法等内容进行了详细的描述,汉信码可高效表示《GB 18030—2000 信息技术 信息交换用汉字编码字符集基本集的扩充》中的汉字信息,并具有数据容量大、抗畸变和抗污损能力强、外观美观等特点,适合于在我国各行业的广泛应用。 测试文本,测试人:施煜,边峥,修兴强,袁娲,测试目的:汉字表示,测试版本:40\015\012", 0, 101, 101, "ISO 20830 Draft Figure 7 **NOT SAME** different encodation, Binary mode not used by figure", + "11111110111111111111100010101000011101101011111111111111111110101100101110110110101100011000101111111" + "10000000100000000000100101011001001001000000000000000000000011000001111101100010001100010100100000001" + "10111110110100010100111000101101010111011101101110011000011010100101110001010110001001010010101111101" + "10100000001101100000101100010000001100000111000000110110000010101010000000010011001110101110000000101" + "10101110000010000100110111111001010010101001000110010010000011110001011010010101110001001010001110101" + "10101110110111101000100011100000001010010101101010001101001010001111001000100001101111110110001110101" + "10101110000101010100110000111111110101101010110101000111100010110010010001000101111001110011101110101" + "00000000111000000000110111110101101001111101010101101011010011000100101100101111000110010101100000000" + "00111100101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "01010101010101010100110101010101010101101000101110100000110011000101101010000010101111010100000100001" + "10001101000100110010100010000000110000011011010011011001011011000011100100000110110001111011001100000" + "00111110111011110000101011100010001000000000110110111110110010101010110110011011010111100010111110100" + "10110100100100001000101010100010011011001001110000100101100010010010111001100000000101111110001101010" + "00101001001110010010111000011010010010000111100111111010101010100110010011000000000010111010100101010" + "01000001111100001100110101000100110000011010001111010010000011001110001111100101001010101000111101010" + "10001100100111010100110101010101010101010101010101010101010011010101010101010101010101010101010101010" + "10101010101010101010101010101010101010101000000010001100100011001101000100110100110111010100110110000" + "11000011000101101010110101100010101110001010010000010001010010000110001101100010010011000000011100010" + "10001110110000110000110011011101001110011000000100100011111011100110101011001001011010011010001111010" + "00010000101111000010100111011000110001001101101101001011000010011110100111010010011010000011101111100" + "10101110000101100110111111111111111111111101001101100111110011111111111111111111100111100011010100101" + "00101010011010110110000000000000000000001010111110101100100000000000000000000000101000110011111110100" + "10101110110111011101011010011110011001101001011101000111010000010010000000101010101010110011100011001" + "11000010111101010101010101010101010101001101010101010101010101010101010101010100110101010101010101010" + "10101010101010101010101010101010101001001101111111101110011000011100011101100010101110000001011110011" + "10110101101101100001000101101010000111001000111110001001111011011011001001110110110111011110110000110" + "10011000101110001110101100001001010101101111011011001001101110101100101001101100111010001101111001100" + "11111101001010110010101100010011011100101011110000000100011110000000110100011110101101001110100011000" + "11000101101000000100001011011011100010101001001110111000111011011001010110111100110111010110100011011" + "10001000111011101111000011010111000100101110010011111101001000011111101010000010110010010101010001000" + "10101011000010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "11010101010101010101010101010101010101001101011000111100000110000000001111101100101011001110110010100" + "10101011101111001011011110101101110111001101100110110100001111101110101101111110110001110111100110100" + "11010100100011011110011110001001110001101110101101100101011101001100010001001100111001010000001100000" + "10000101111110100100111001000011001010101011011110100011110101111001001000011100110000101111100000000" + "10101100011100000011110110100100110010001000110111001111001101010010101000010000101010011000001010100" + "11000010110000110100101001000111101100001110000101011011101100100000010111100000111000110001000010101" + "11001010101000001011010101010101010101001101010101010101010101010101010101010100110101010101010101010" + "10101010101010101010101010101010101010101010101010101011011000100111010010001000111010000001110110111" + "11101000101111001100000110110001111101001111000100010101000110111110011110100100111011010011101111010" + "11111111111111111111111011001111100000001111111111111111111110100100001011010010111111111111111111111" + "00000000000000000000100011011101011101000000000000000000000010000001111111100010000000000000000000001" + "10000010111011101010101101110110011000111010110000111111110010000111100111000010110001111100001001101" + "01100101110100000100111010010111100100001100010000000110111011000110110001001111001111010110011011001" + "00111011010111010010111011010010011101101001100101010111110010110100111011010101011111101100110011101" + "11001100100111001000100110101011010101011111011001101111010011010101010101010101010101010101010101001" + "10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010011000101" + "01001011101100110110100100100111010011110001010000101110001010011001110011010010111000111000111110001" + "10101110100110001110101010011100000000001101101100001101110010010100110010110001010100110100000000101" + "11011111111111010100111101011101001000101011010000110001111010000110011011010010001011001000111001101" + "11110000100101011000111001010111111101010000000001101011011010000011010101100111101010001100001011101" + "00100000000011000100100011001100100000110011001011011010011011101111001111011001100110001000110000001" + "01110111000011111000111101001000000111101000011010101011101011111111010110101010101010101010101010101" + "01010101010101010100110101010101010101010101010101010101010011010101010101010101010101010101010101001" + "10101010010001010100100111010110010010011100010010001010001010101110100011011101001011001110011110001" + "01111000100110000100111111111110000110111101001110011100111010110110110011001011100101101010101010001" + "10110101000000110000100111000010111011001010100110111101010011001100010110001011011000000100000101001" + "11010010110011010000110011100110100111010001010111000001100010111100011100010100101111100111001010101" + "00001101111011101010101011011011111110110010100110000001110011010111111110110100110001011101110011001" + "00111101010000110000110010100010100010011001001001101100101010101101010100100101010000011101010101000" + "10101010101010101010111111111111111111111010101010101010101011111111111111111111101010101010101010101" + "00010101010101010100000000000000000000001101010101010101010000000000000000000000110101010101010101000" + "10101010101010011001101111100110100010001110110001101001011001110010101001111010101110110101110001010" + "10101010011001000000011000110011000100101100110110110000010000001110000110011000111000010110100110000" + "10000001000100111010001011110110101001101001001010010110010011101100101000011100110001001110000111101" + "11110011000000111100111010101100001010001011010001011011011000010011000110111110110101011010101100111" + "10110011011001100100111000100000010111101010000111101110001010110100101101000000111011001010110111010" + "11010010001011100100110011101010010110001111101000110100100111010101010011001010101010011101010101010" + "10101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "11010101010101010101000100110001011010101101111100001010101001100011100011100110101101100100011001111" + "11100010010111111100110110111100101111101100001001100111111101110100000001111110110110011111011111100" + "11111101011011001011001100011111110101001010110101100100000000110110010000111100110110000100001101101" + "10111101111101010000110000000011101010001010110000111010010001110101101010100000111011000110000001010" + "10010010100110000101100001100110001101101000101101001010111000001001110000110010110100000011010100100" + "11101011110011011110010100011101110111001101110010001100101000101110101010101010101000101100000110101" + "11010101010101010101010101010101010101001101010101010101010101010101010101010100110101010101010101010" + "10101010101010101010101010101110000111101011001101000011001110000111011011100110110010101001110110010" + "11001110100110110000010111000001100110001111110001100010100110010000011001110100110011010000010001000" + "11111000010110000000100001110011110101001000011111000100100110011101111011000000100111101001001010111" + "11010001101111101100110100000101110101101010110011101011100100100001111010000010110100011110110010001" + "11111111111111111111100111100010101011001111111111111111111110111011101101001010111111111111111111111" + "00000000000000000000101011111010011010100000000000000000000011000100111100000110000000000000000000001" + "01011000001111110000100000011001011101000111001010001010010010110100011010011101111110010100100110101" + "10101101010101010010111101011001010101010101010101010101010011010101010101010101010101010101010101001" + "10101010101010101010101010101010101010101010101010101010101010101001001000001110111010111100000011101" + "10001001000111000110101101100100001101111110100001000110100010001000100000110011100100000110000100001" + "00110100100101011010101011011010001111001011011100011011000011001110101100010010111100110010001100101" + "00111110011110110110100100010001011100001001010001111011110010100010111010000011011101000111110000101" + "00101110111011010100110001101011010011001010010100011101000011001000100011010110000111010011010011101" + "00000011000110101010101010101011000000100100001101100001101010111110001111010001001010101001010101101" + "00111001011010110000101010101010101010100011101010101010101010101010101010101010101010101010101010101" + "01010101010101010100110101010101010101010101010101010101010011010101010101010101000111111011110011001" + "10101010100000010010100110100110011011111010001111111101111011010111011111110100111010101000100111100" + "00000000110000000000110101001111001001011111000010100110001010111011110011000101000111001110100000000" + "11111110110001100000111101111110000101000111011100100000101010000000101111110101100100111001001110101" + "00000010010110100000100110100110110000110110001111010110010011111001000101101100000100010110101110101" + "11111010011011110010111110110000100000100011011101001001010011101011101010010010000110011011001110101" + "00001010010011110110100011000110111000001010001000101000111011001010101011001010011100100110000000101" + "11101010110101101110111110000011000100000000010101111110111010011111011110101010101010101010101111101" + "11101010110101010100110101010101010101000001010101010101010011010101010101010100000101010101100000001" + "11101010101010101010111111111111111111101010101010101010101011111111111111111110101010101010101111111" + }, + /* 16*/ { UNICODE_MODE | ESCAPE_MODE, -1, 62, -1, "本标准规定了一种矩阵式二维条码——汉信码的码制以及编译码方法。本标准中对汉信码的码图方案、信息编码方法、纠错编译码算法、信息排布方法、参考译码算法等内容进行了详细的描述,汉信码可高效表示《GB 18030—2000 信息技术 信息交换用汉字编码字符集基本集的扩充》中的汉字信息,并具有数据容量大、抗畸变和抗污损能力强、外观美观等特点,适合于在我国各行业的广泛应用。 测试文本,测试人:施煜,边峥,修兴强,袁娲,测试目的:汉字表示,测试版本:40\015\012本标准规定了一种矩阵式二维条码——汉信码的码制以及编译码方法。本标准中对汉信码的码图方案、信息编码方法、纠错编译码算法、信息排布方法、参考译码算法等内容进行了详细的描述,汉信码可高效表示《GB 18030—2000 信息技术 信息交换用汉字编码字符集基本集的扩充》中的汉字信息,并具有数据容量大、抗畸变和抗污损能力强、外观美观等特点,适合于在我国各行业的广泛应用。 测试文本,测试人:施煜,边峥,修兴强,袁娲,测试目的:汉字表示,测试版本:40\015\012本标准规定了一种矩阵式二维条码——汉信码的码制以及编译码方法。本标准中对汉信码的码图方案、信息编码方法、纠错编译码算法RS、信息排布方法、参考译码算法等内容进行了详细的描述,汉信码可高效表示《GB 18030—2000 信息技术 122", 0, 145, 145, "ISO 20830 Draft Figure 8 **NOT SAME** different encodation, Binary mode not used by figure", + "1111111000001010101011111111111111111000011101101011001011111111111111111010111011011001101011111111111111111100111110101001101010010010101111111" + "1000000001000001100000000000000000001111011000100111000000000000000000001101101011101010000000000000000000001111010010101000100011101101000000001" + "1011111001100110000110100101110001001101100010010100100110110000011000101000000110000011100000011011000001001101000000001001100111010111101111101" + "1010000000000100001010111111001010001101010010001100100100001110001011001100101011100010010101011110100000101110000000101001010110101000000000101" + "1010111001101001000111100100010000101101111110110001010101010000111111101101011010101101010001111000110010001100010001011110011100111100101110101" + "1010111010000001011111010110100111101101010101101011110110101000101001101110001000100010010111010101011001101100001110010000001010000011001110101" + "1010111000011001100010111101000001101010011111100001001000001101111111101100101000000000001110110111100100001011111010000101101111100110101110101" + "0000000010111000010011011110110111101000000101111010001010111101010001101110111100110110011110111110011101101001110000101101101010110001100000000" + "0101001011111011001010111001100111101011011111100001011100100110011100101111110010100000110000111100101111101011111100000110010010100010100010101" + "1101101100001100000110111000011010101101111101010000101101000000111100001110110110101010101000111010001010101010110011110100111010101101010010001" + "1010110100111000011010100110000000101001101001100000101010000110000000001001111001010001010010011011111000001101010000111110011011101010100110011" + "1100001100110110101100111010011000101000011001101000011100011010011001101100010000010101000000001000011110001101010101010101010101010101010101010" + "1010101010101010101011010001011101001000011010001011010100000101011110101010000010000110001101000100110010001010000000110000011011010011011001011" + "1011110001101111100100111000010011001011111110000010001000011110100011101011101111111110010010000010011010101010010011001001010000111010000010110" + "1011010010010000100010101000100110101100100111000010010110000100101110001110000000010111111000110101000101001010011100100111000011010010010000111" + "1011000000101010101100110110011111101111101000101011010101101111100000101111001010101110110011111001011100001010110111101100011100000110101101011" + "1101001111110111001101000011011101101110110101011101101000011110011001001101011010111110011001000111110000001100000001110111111001100101111101111" + "1100110010100100001010111100111110001010000100000010111001111100000011101101101010101000000111000101011100101010011111101111011011010011000110100" + "1111111111111111111001101110111101101111111111111111111100111001001010101111111111111111111111011101000011001111111111111111111101011000101001101" + "0000000000000000001111100110000010100000000000000000001110111011111110100000000000000000001101010101101100000000000000000000001000110010001111100" + "0100110001110100001101110110100101100000011011011010001110000111001100011100100011010110001001100011010010100001111100000110001110101010010011001" + "1011001001100111101100111010110110011101001011000000001010010111110101110111110011000000001101010101000100101111011111000110101111010000110011100" + "0110110101100100001000011101111000000010011000001000001011100100001001101010110111110111001010110111101110001111011101111000101010101001101111101" + "0010000101010101001101010101010101010101010101010101001101010101010101111111011100110110101100101110110010110010001010110010001111100111100111010" + "0101001010011101001100011101011011111011101011111001101100100111011011001111111000111010101110001001111001110110010001011000101100111111011011100" + "0000011001010100101101101001011001011100001011011110101000011110110001001110011101100100101001011010011111000010110001011011001010111110001000000" + "1000111101001100001101100100110000011100001110010101101001010110010100100101000001010011001111011100110000000100101110110111001111010110100111100" + "1100110010111010001011101000001001000000010100110100001110111010100011111100100010011001001110100010001010011000100000111001101110111010100010110" + "1011000101011101001101001000110100000110110011110101001111101011001100100010111011011011101101100111010101000011001111110110101101011001101100001" + "1010011001100110101001111001101010010111100101000100101000110100101101000000000010000101101110110011111011101000110000101111101110010101010011100" + "0100110111001100101010110101001101011101000101110100101111001001000101010001110101011101001110110101010100010111110111010011101100001100100001001" + "1000100000100110101010011011100101001101110101110000101110010011001001010001101000111011001011100000100001110101000110011010101110011101101111000" + "1111100110010001101100101011111110011110010100001010001010001101100001100100011101100100001011110010100110011111111001011010101010111010001001000" + "0001001111001101001100010101011010011011100000010101001101010101010101010101010101010101001101010101010101001010111111110111001011000011100011101" + "1000101110000001001111100111001010010010011110111010001101011110001111000001110110000100101001001101100010001000100001001111001010011000101110001" + "0011010110000100101010101111101101100100110111010110001101001101101101000110111100110000001001011010100110101001110110010001101010000111111101110" + "1000011111110010101111111111111111111110000100101100001111111111111111111101110011110001001111111111111111111110100000010000101111111111111111111" + "0001101101110001000000000000000000001100100111011100000000000000000000001111011011001010100000000000000000001101111010111010100000000000000000001" + "1010111001000001000111011101111000001110101110001001110010011111101001001000111111010100000110010011100101001000111000010101111110000111110111101" + "1111011100100010010110000101010110101000111100111110001010011100101000101000011010001101110010100111001001001101111110000011001111101101001010101" + "1100101000100101100011101010101001101101101010111111100100110111101000001001100110000101101110110010001110101110110000001100101010000100011001101" + "1000001110010100010101100101001001001111100000110000001111011101111001101001011100011000001001110001101011101101011110111110100010010011001101101" + "1011000101011111001111111010010010001100010101010000101101000101001111101010111011100000111111000001100011001010000010010000111101000101010000001" + "1011011001100111101110101110100100001011011110010110110011101101111110001111001100001101001101111011110101001101010010011000100010011011101011101" + "1001010111001001001011010101001001101011011001101010101101100101001011101100101011001001010110100101011010101010101010101010101010101010101010101" + "1101010101010101010101001110000111101100111111111000001001101001100010001110101101010111011110010110111101001110111011101011001101101000011111001" + "1000101001000000011100010000110010101110101001000110111100111100010011101000111101011011001010111010011000101000100110110010100000011000001111001" + "1011111101001001110010000110010101001110111101000111101011110010010000101110100001011111000000001010011100001111111000010010110110011011111001001" + "1110011110011010100101010000100001001100110000010101000111101001111001001110101101110000100111001111010100101000100110111111010000111100111001101" + "1010001001100011111100111100111111101110011100100010111001000000011011001010100011000100111100000110011101001011100100110011010010101111110100001" + "1111110101111110110101100010110111001101011110110011011001011000010101001010001001011001100010111010101110001011011010110000000001011111101011101" + "1100101001101001110101110000001110101001001110110011011100000000111111001110011111110001110000000101110000001010010001001010111001100110111101001" + "1010111100011101010100100001011001001101011111010011010000001101001001101111011101101011010101011101101000001001110011011010111010111010101111101" + "1111110110001100000000110001011111101110101010100011001000010001110011001111101101101011000111100110001100001101000000000000110110011100101101000" + "1111111111111111111000000111110101001111111111111111111000100001000101101111111111111111111011001100110000001111111111111111111100011111110001001" + "0000000000000000001000101101000111000000000000000000001010010111001111000000000000000000001111001011111101000000000000000000001001000101001100000" + "0101001101110011001011101010101010101010101010101010101010101010101010101010101010110110001010011101001000100110100000011101101011100101110100001" + "1001111100100111001000010100011101110101011100100000101100001011010010010110001000010111001110011111000000010010000101101001101110010001010001011" + "1111100000000111001011111010001000101010010001001100101110001010011110000000011111000011001001111010011100000111101100100110101000101111101001011" + "0100001101111001101101111111001000011100100111011000001110000101001100100111000100101000101011000100101101100010010110011010101010000011001011000" + "1001010101000000101001100110000011001101100011011110001101010111100101101010001101110001001111011011110100010011011011100001001110100000111001010" + "0001001110001001001011010000101101100011010011011000001010111000010110110111100001111011101011111011111010110110111101001101101111111000111000000" + "0100001000111110101000011111101100000011110110001110101010010010110001011101000101001101001000111011011000000111100111100101101101111100111110101" + "0001110100011111001001100011010111010100000001101010101100010111000110000010101010001100101111111110010100011010100101001001101101011000000001011" + "0100011111111100101110111010101101110100100011100110101110100110100111010101101111011111101101101110111111010011100111010111101110011010011101010" + "1111010010111010101111010110011000010001101111001100101001111111111010111110100100111011001011010001110101100000100010011000101001000001101111100" + "0011001010001000101000110000111010011101011011010001101010010110101010101010101010101010101010101010101010101010101010101011001011101011010001001" + "1001001101101100001101100001110101111010001110110011001001100101101000111000111000001101001100010110011100010101100011111111101100100100111100100" + "0111010110011010001111010101100101111111100010000000001000101010001010001011011101010010101111001110000111100110010010110111001100110111000110000" + "0011110110101001101001101010000000101011111111100101001010011111001010100110000101011100101111010001101111111110011101111001101001101111100110011" + "0100100101100001001000110000100110011001110111001111101100010001111000001100010110111111001000101111001110011010001110010010001100001000010100101" + "0011100111010100101101101110101001101010000111101010001101101101010110101010111010011101101101101110000110100101111100111001101011100000111000011" + "1001001110110011001111111111111111111011111111001011101111111111111111111000100110111011101111111111111111111111011010100010101111111111111111111" + "0001110110010100000000000000000000001100111011110000000000000000000000001010010000000100100000000000000000001001001001011110100000000000000000001" + "1010110101110010111001101011001100101011111100000111001101111101000000101000100011010110001001011100001001001011001011000010111110000101010101001" + "1110011010111000000100110011011001101001001011100110100010011011000001101110100110001110110100110001111000101100001100000010111100000001100111101" + "1100000100011110111100111101100100101101000000110010101001101110001101101011001101101100000110111001000101001101010010001111111100110111110000001" + "1101011100000110011101101010010000001101111110010111001110011101010011101101010110001001111011010101011011001001011011110101010101010101010101001" + "1010101010101010101010101010101010101001000101010001110101100100100111001001001000101000101011101000110111001100101100111001111000111100010011001" + "1111010000000000111100100001011000101100011000100100100110011010001101001010101010101101001010111111001111101000111101000100110101011001000010101" + "1101001100010110001011011000000100001001010110100101100110100010011100101101001110100010101110000011000111101000111000101001011111001110010101001" + "1111001000010001010101001001000000001100110101100111111000101010000000001100101100111010001000110010000101001111100111011010111010111011001101101" + "1100110110010101011110110101011100101111101010011111001001110000100011101100100100101101110001111101110110101011010110000111001110110000101000001" + "1101000110111010110010001100000000101110110010011001100100100110011110001101101011011111010101000010000101001110000111010100100101010110111010101" + "1001000110000110010100001001000101101000101000011000001110011111011011001101011111101100110000111101001000001100100100111011010111111010010000101" + "1010000100010101110011011111010001101100100101101011101010111101000011101100101000011010100100000110110110101010001100110101001110000100001010101" + "1110010111110111110010111010001100101101100000100010110100000111011010001111110000000101100010110101001010101110110001110101001110101000110000001" + "1110010111100111000011011111101000001110010101111001000111110010011010001101011110101100100110110001111100101111110011000110000010111100001010001" + "1110101010000111010001001110101010101010101010101010101010101010101010101010101010101011001100100000110010101110110010011100101101001100011010101" + "1100111101011101101011100010101010101011001101111111001110011001110110001110010010011111011111100011110011001011001111010010110011110000001000100" + "1111111111111111111110001011101000001111111111111111111100101011001101101111111111111111111010110100110110001111111111111111111010011010111100001" + "0000000000000000001010001001110000100000000000000000001111010001100111100000000000000000001110000110001010100000000000000000001001111010111001000" + "1110100100100111101011001110010000001010100101010011001000110011011001100100111000100000001101111010000111101110001010110100101011010000011011001" + "0101101110100101101011101000110110011000101011010011001000101110010110110001001110010011101100001110100101000010011001001011101101010001011011101" + "1001000111100100101100110100010011001110001101010010001110111101100001010010111100111000001111101100110000111000001000100110101101110111101101001" + "0100000010110101001001100101100111110111010101100001101110100111001010001100100101111101001100110001000010011001000000101111001000010101011010000" + "1001110100101101001000100101100100011111100101100000101000110100011111110011010011001100101101010001110101110100000110001000001011101100011110111" + "1110100101110011001011110011010101001001000011101010001111110001011001011010110011110101001001111100111010101100010111001011101010111011101101001" + "0110000111000110001110010111001111000001000101010101101000011001110001001011000001111101001000001011111000111001000100110111001001000010011100010" + "1101001101110010101111010000000010100010111001000000101111010011100111111100010101010101001101010101010101010101010101010101001101010101011101100" + "1110100101001000001011110101010110011100011100011001001010011011100110000110001001011111101100110110111100101111110000100110001111111101110100000" + "0011111110110011101110111111000000010100100110100110001111000000010101101001010011011111101110010011011110000101001111011110001100100111101111101" + "0100001100000000101110101000101100001110100100011101001110101010000110110001100000010101101011010110011110100111100110011100101001110100101101010" + "0011111011000111101001100101111110010101101111010111101001101111001010001110111011101011101001000110010100010111010110000100101010101100100011011" + "1011001101010111001101111100110110011010011101011000101000011110010000000110101101001101001100000001101100110011111001000111001010011100010011100" + "1010011100001111001110101100100111001110110101100101001011010110110101100011011001010111001011001101111110011001101100100000001110100110101010101" + "1011011110101011001010000000110000101000101011000011101001000100110001100101010001010001101111010001001001001100000001101110101011001010110010000" + "0011010000011011001100001010000010010011110000101111101110101000101010100001001010011111101101000111101000101000111110000111101100010010110011101" + "1010110100100001001111111111111111111011000000100101101111111111111111111010010010111110001111111111111111111111110011110100101111111111111111111" + "0000001101100100100000000000000000001101001110010110100000000000000000001101110110101011100000000000000000001011011010010110000000000000000000001" + "1101110011101110011010111000100010001001010011000111011001100010011011101110100111110100011011110101001111101010100110100101101110101010101010101" + "1101010101010101010101010101010101001101010101011100001111011001101000001110011100001110110111001110010101001011101100100110001011001001111101001" + "1110000011001100111110001100010100101100100000110011101010011010000010001010000000111101001111111011110001101000010101111100000111011011001100001" + "1011110110000000111101001001010111001101110010000010011001011111010001001100101001100010100011011011110000101011111001011100001001101110001111001" + "1110101010011000100010010110100101101111010011010110001001111000001101001110000011111100000000011001011101001001110010100010100100110100011010001" + "1000100000011010110110010010101100001111111000011100000000110100110001101000001100110000101001100001001111101010011110101100110101110111010111101" + "1011001001000001110110110010000101001011010100010111111010100110011011101100011101001000011111001000011100101111111110101001110110011001011010101" + "1110000000010011000100001111100011101011001100010010101001111000001011101001011100110011001100110011110100101001111111100010000101100111010000101" + "1011101011001100011001010101101000101000100100110101110010111110000110001011001011101101000010010111010100001011111101110111111111011001010011001" + "1111110101011010000000001001011011001001001110010100110100001101001110101001001100111101100010100111001010101110010111010111010001010111001010101" + "1110001010111011100101111001000000101101100010000111010001010111001001001110110001000000011111000001110010001110101001010101111110110101101101001" + "1010101011001101010000000011100101001101010101010101010101010101010101001101010101010101010101010110110111101100010001010000111111000011101101101" + "1011100011011011001000011011111101001000100011010000010001000001100111001010000011000010000011010010010101101010101101101000111100101101110001101" + "1100111011000101001110110100001100101101110011011000001100001001001101101101110100011110110101110000100001101011101000101111100100010111000001101" + "1001001011101110110101010001101011001100110010100101000111010001001000101000110101100001110100110100111000001001100011010101010101010110000001001" + "1101111001001111001010000011100001001111011010101011010101001100011010001101001111100010010110111001101111101010000010101001011000000101111110000" + "1111111111111111111001101100110010001111111111111111111010100101101011101111111111111111111111111111111101001111111111111111111100110111011001101" + "0000000000000000001000011110001001000000000000000000001011100001010000000000000000000000001011010111000011000000000000000000001010001000101100100" + "0100110100100001101000001100000000101001010010101011101010101100111110110010111101110110001001110111000010110001110001101001001110001100111001110" + "1001101111010110101000001110001111110011011100110110101001101111000000100000011010101001101101110100110100001110101001101110101011110100010010101" + "1010000101000110101100001010011010010011010000011010101001010001011011011101110010101011001011101011010110111110100110110110001010011101100011000" + "1110001110110011101000001010111101011010110000001110001001011110001111011010011110010011001110100100101011001100001011000111001111110101011110001" + "0111101101100111101110001001010011011000100010101010101010010000000101101000010011110010101010101010101010101010101010101010101010101010101010101" + "1100000010000110001100000010010011010011001101111101001001111111101111101011101111111010001111010101000100000000010101001111001010010111110000101" + "0011000101110111101001100010100011100111010001100001101101111110000101000111011100100000101010000000101111110101100100111001101011010000001101001" + "1011000011011000101111010110010111100100010110110000001100010110110111100111110110000100001001000110111010010010101101011101001100100100001100110" + "1010100010001100001010011100111001000111110101110111001101110000110101010100110101100011001110010101001000000011111001110111101111110110101001010" + "0000000011101001001011000110010011001001010010001111001111011010010111111111101000010110101100110111001101010010110110100010101011011111100000000" + "1111111011110010001010101011010010000001001111100100001101001110111001100111001001110011101100110011111001011101100010001110101111101101001110101" + "0000001001111011001110111010001101101101000001011010101111100100100110101001100011100100001110010110100111111000010111111011101000110000101110101" + "1111101011101001001011011101011100010001101000001101101111010010100000010001100100011010101111110011100001001100011001111100001010010110001110101" + "0000101001100010101000100110111000101101000100111011001111000000001100010111101010001110001001101000011111011101100010011001001000010110000000101" + "1110101010101100001101110100101101001110000011011111001100110010111110010110000100111001001001010000010110110011110100000110101100111011001111101" + "1110101000010110101111100111011100000010111011110111001101000101010111000001011011001010101011010000000110000011001001000011001101010101000000001" + "1110101010101010101111111111111111101010101010101010101111111111111111101010101010101010101111111111111111101010101010101010101111111111001111111" + }, + /* 17*/ { UNICODE_MODE | ESCAPE_MODE, -1, 84, -1, "本标准规定了一种矩阵式二维条码——汉信码的码制以及编译码方法。本标准中对汉信码的码图方案、信息编码方法、纠错编译码算法、信息排布方法、参考译码算法等内容进行了详细的描述,汉信码可高效表示《GB 18030—2000 信息技术 信息交换用汉字编码字符集基本集的扩充》中的汉字信息,并具有数据容量大、抗畸变和抗污损能力强、外观美观等特点,适合于在我国各行业的广泛应用。 测试文本,测试人:施煜,边峥,修兴强,袁娲,测试目的:汉字表示,测试版本:84\015\012本标准规定了一种矩阵式二维条码——汉信码的码制以及编译码方法。本标准中对汉信码的码图方案、信息编码方法、纠错编译码算法、信息排布方法、参考译码算法等内容进行了详细的描述,汉信码可高效表示《GB 18030—2000 信息技术 信息交换用汉字编码字符集基本集的扩充》中的汉字信息,并具有数据容量大、抗畸变和抗污损能力强、外观美观等特点,适合于在我国各行业的广泛应用。 测试文本,测试人:施煜,边峥,修兴强,袁娲,测试目的:汉字表示,测试版本:84\015\012本标准规定了一种矩阵式二维条码——汉信码的码制以及编译码方法。本标准中对汉信码的码图方案、信息编码方法、纠错编译码算法、信息排布方法、参考译码算法等内容进行了详细的描述,汉信码可高效表示《GB 18030—2000 信息技术 信息交换用汉字编码字符集基本集的扩充》中的汉字信息,并具有数据容量大、抗畸变和抗污损能力强、外观美观等特点,适合于在我国各行业的广泛应用。 测试文本,测试人:施煜,边峥,修兴强,袁娲,测试目的:汉字表示,测试版本:40本标准规定了一种矩阵式二维条码——汉信码的码制以及编译码方法。本标准中对汉信码的码图方案、信息编码方法、纠错编译码算法、信息排布方法、参考译码算法等内容进行了详细的描述,汉信码可高效表示《GB 18030—2000 信息技术 信息交换用汉字编码字符集基本集的扩充》中的汉字信息,并具有数据容量大、抗畸变和抗污损能力强、外观美观等特点,适合于在我国各行业的广泛应用。 测试文本,测试人:施煜,边峥,修兴强,袁娲,测试目的:汉字表示,测试版本:84\015\012", 0, 189, 189, "ISO 20830 Draft Figure 9 **NOT SAME** different encodation, Binary mode not used by figure", + "111111100111111111100010101000011101011111111111111111000111101110100101111111111111111111100101100001010111111111111111101100011011101001011111111111111110100111001010010101111010101111111" + "100000001000000000111000010110101000000000000000000011110111100101100000000000000000001000111110110011000000000000000000110001110111000100000000000000000010001110000000010001110110100000001" + "101111100010010100101110011110110011111011110000000011110101010100001011100010110000001010100001111001101000000101101000110110001100001101001011001001110011110001101000100110111010001111101" + "101000000001110000100110001000100001111011010110111010101110011110101100001111011010101110110010001001111100001111000010111110110101010110101110110110101010101100011110000111110011100000101" + "101011100111011110100011110111000100111101000010111011011100111101000011001100001101001111100111110000100001010011010010111100000000110111001111001100111010110101001110101111110001001110101" + "101011101001111100111001000001111101110001001000100011100100001111101010001010000001101010010011111010010000001011100000100100000000001111010101000101110010111010001100011100000111101110101" + "101011100001011000111100011101111011110101110110000010111000010111101010000000010011101101111010110100001101111000100000111100100110010001010111011011010011011101010100100100011110101110101" + "000000001111101000111111110010010110101000010011001011001110111111111101100000101011001101101110001001001111111110001110110000101010100110111100001001001010110001001110010100100000100000000" + "011010001111110110110110001010011000001010100000111010011000101111000000101111011010001111000111010011110010100110010000100111110001010001011110001001111010100001110010000001000011001010101" + "001111101110101100100011110101010111001111110101100011010010001011001011000111101011001011100101001111011001000000111010110000100011111010110001001101001010110001101100001100110100011011011" + "000110010011010000110100001010001101100010101010110010011011010111101001110101110100001000000110010000110101000001010100101101000000010001110100000111110011000100010010101011000011100111000" + "110111100011011000101100101100111001111111000101101011111011100111010011000001100010001100111011011001000100001101000000110101100011011101100101100011001011001110101010110100000110101110001" + "001111100101010000110001110010111010010010001110011010011111101001000101101000101110001110100010000011111111101101000010101010101010011101111111110001101011001101101000011011110011100001011" + "001100111010101110110100100000111011011000101110101010111000001010101010101001110110001110000011100110000010001110010010111100101100101010110011111011110011011111010110100010111011000111110" + "101010111111011110111001101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "010101010101010100110101010101101000101110100011010011100100101000100111110101111011001000101111000001101011010010011100100001111001011001001011110101001011111001100010101111011100110100111" + "001001011001100010110000001000010000111010101101001011010011101001101010111001011100001001111111101110000010001011110100101000010101010100000110111010100011011101011011001001010110011001000" + "101011010011001100111111111111111111010110011110100011111111111111111110001001010101101111111111111111111001010110011010111111111111111111110101100001110011111111111111111110110000100011101" + "000001100101100100000000000000000001010111010000100000000000000000000101101000110111000000000000000000011100111011011010000000000000000001011101001011011000000000000000000101001111001001000" + "100001010110110010111101001011000001100011110010101000100001100101100100001101100001101000110111101100011101100111110011011010001110000001000011111101011101100000100101000110100010011010000" + "111010011001101111100111001110001001010110011001100001110001011110110100010110110010110100101110000111010010011111100010011010111011101001010000111011011010110000010010100111001010011101000" + "101101111101101011000000111011001001000010111110101111111011111111010111001101001000101001110001010010011001000110101010000110001111100101100010011111001011011111101010110101001001110111001" + "101000001001010111010111001100110001100011001000101010110110100000010110001010010100110011010100001100011011010110001010001111000100110101100101010110000010111010101111100100010111100000011" + "100011111110010010001110110000100101000110001011010110100100001001010100111000101100010111111110100011010111001011011101000100010100111101101010000100100111001000010110000110110001111110000" + "101000110110110110110011110000010001101101100111110101111111000011010101101100111101101111110000110111011101011101100101011010001011011101100101100101101101000101101100000101101001010000110" + "100000011011100101111001011000000001010000011101001011101010101110000110011101011111111100010001111000011000001010111101011010001111001001010110101000101101101001100110010101000110100010001" + "101001111001000110111001010000101101000101011001110001111001111101010100011000101100000011101101001000010101011110110100101100100110101101101100110110100000100001010110010110110001011010110" + "110001000100010111000100000010011101100000101000110100100000110011100110011001100001011000111100100001010111100101010110000010011010000001100000111011100111001000011101110100100000011001101" + "110100110111110010010101010110110001000000100101011011010101001010010101101110011010101000110001110111011010101010101010101010101010101001101010101010101010101010101010100110101010101010101" + "110101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011111110111000011010101001111110110100110101011110000010100100010101100110" + "101100111101010101001100011101000101110111011111000100110000010011110100100011011000101000000100010110010100110001000101101111101001101101000100101000001111111100000110100111001111001100010" + "101011001100000001011011011011101001100110001111011001110011111111000110110001011100101100010010110101010000011000101101100000011101001001111010010101110111011111011001010101000101001010110" + "110101000100011011111001111010010101011101001101011010000100010100100111110011111011010010111111000100010110011101010010011000110000001101011110100010101111010101110011100111011001010110011" + "100101010111000001100100011001010101000100101101010100000110100011110101100101000011011000001100111001011100110110101111110001110011111101011101100000100011100010111001000100100001000001110" + "111111111111111111100001001010100101111111111111111111110101101011010111111111111111111010100100001101011111111111111111100011101110011101111111111111111110111100101101000111111111111111111" + "000000000000000000111100111001001000000000000000000011100001011100000000000000000000001100000010100101000000000000000000110100110010011000000000000000000010011111111110100000000000000000001" + "111001110110011110101111101110101010111101010100111010110100101101010000111011110111001110000001101100100001100111100110100110011100010010010111110100111010100011010010100011110011011100001" + "111100101000001000100110011011000011110011110001011011011111010000111001011100110000101010111100000010001011111111100100101110101001000110100110011011111011011010010111100101011100101101001" + "111011110011101010100110100010000110111100110100111011101001000001111111000001110011001110000011011010000111101111110000101110010000010100100100110110000010101000011011100101000011000101101" + "000101010110110110110010111100111101100101110010010011101100011101110010101000001001001101110110110111110110001101010100110111001000101010100110001011100010100010111001101101110000101101101" + "001011110001011000100000100100001101000000010010111011101000001100011010001100100000001111101101010111110000001101111110110101100110110010000001000011110010001000100000010100000010101100001" + "010010010111111000110011100010101010111110001001100010101111010010000000011011101110101001011010010010110111100101001100111111101001011101010110010001011011001010000000111100111100010111101" + "111100001110100000100101001111100101101111001011011011111111001111010001010001010010101000011101010111110101010100010000111011000011010100110000110011010010100010001001011110100001001001101" + "111011001101010100111000000010101100010101010101010011010101010101010101010101010101001101010101010101010101010101010100110101010101010101010101010101010011010101010101010101010101010101001" + "101010101010101010101010101010101010101010100101011011111110110000100111101000000111001011010100000100101011100100010110101001100101101011111100101100010011000011010110011111101110010110101" + "110000101111101100111111100110011110010111001011000010010101101000100011000011011111101110000111010111010011010100101100111011000010111111001001010111001011011000011011101010001100100101001" + "111101011100101000100101001100101010111000001010111011100000010000011101001011110000001010101000010100111000100010001000100110010110100010011101011100110011101010101010001111011011110011001" + "101110011001110000100111000001101001101110111011101010101000010010110110010110011001101101101110100110000100110000001000111001101011110110011100110001001010101011011111110000000110100010101" + "110111000100100000101100111010010011101111111101010010111110111100011000110100111001001110101110010011001000111011110100110101110011001010110000111100000011000000110100011101100010111011001" + "111010101100111000101101011001011100110101100111011010011101110011010000110111011011001100110001110000011001110000011110100100010110110010011111001011001010100011001101100111000111111010101" + "001111000011011100101001011101110101000011010101111011001101000001011011010010001111101011111001111010011100101110111010101001110110011001101000011001110011101101011000010001100111010100100" + "100011111000010110111111111111111111010011111111100011111111111111111100011100011101101111111111111111110101010111111000111111111111111111011001000011011011111111111111111111110100111010101" + "001101111110000110000000000000000001101011111110010000000000000000000101000101111111000000000000000000010100111011110110000000000000000001110110101001111000000000000000000101111001111101000" + "110110000011011000001011111101100001010011001000100111101111000100010111111001110110110111010010011001010011000000001001101001000100011101000101010011000011001010000101000111010001010001100" + "101001110001010100000010011010110001101011010100100010001000110101000101010101001011111100010100011111010100011011001110011110010011111001101101101101000111111000110100110110001001111010111" + "101110011101011100110011001000110001111110100100100001110110000001010111111011101000100001101111111001010100111011101100010110010100101001100011010010000000001011111000110100000010110111101" + "111101001110111101101010010010100001101100111101011001100101101111010100101000000110001110111011111011010011011010100110110100100110011001100100110100011000101000100100110111011101001001001" + "101000101011100001101101100111011101001110101110111011011010001100110101101100101010111011101000011001010101010111101101101000010101010101010101010101010101010101010101010101010101010101010" + "101010101010101010101010101010101001101010101010101010101010101010100110101010101010101010101010101010011010101010101010101010101010100101110000111110001010010001001101010110001001010011001" + "100000111011010001001010100011010001101101110001011010111001111100000100001101000101001010110010010000010110101100011101001001100111011001101001100100110001100000000101010110100000011101001" + "101010011011101011101000001110001001110011011001100111001000101011010101010101000110001000101100011101011111100111011001110111001000111101100110100110110001000111110010100101110010100101011" + "101010111010001011101010101010001001011000110001111011001110101010110110010001100001010011101110000000010101001111110011011010000000001001100111011000110001100110110110110110010111101110100" + "110111110011001000000000001101001001110011001101110011001000111100100110100001101110100100011011110011010100000100010001110011111111001101001110010100100010011101111011000110100110100110011" + "100011010100100100011111011101010101000110010010111011111110010110000110011110011100100011111010010010011010000011010101110110011111100001110100000110011000011011011010110101000100101011100" + "111111100001101110001010100101010001001001110011010101010101101000000101001100110100111111010111001100010011111101000100000010010110111101111001100000111111010001110000100110110011111001110" + "111011001101000110001001001101101101111111100001100101100010010111010100011100101001101101011010010001010100110011100101110111010111010101101110101101010110000001011111000111101101101101011" + "101101111110011010010000011100000101001011100101011001100110000001000110101011011011011011111111100110011100000111000100000111011010011001110110111000101011000011110100010110001010011000010" + "110111001110000110010110000011111101111011000000001101111010100011000111011001100011011101011001110111010110101010100011000100000111101001000010000000010100011001110111010110010111110101110" + "111111111111111111110001010100110101111111111111111111111101001001000111111111111111111010001110010101011111111111111111100100011001111101111111111111111111111110010100110111111111111111111" + "000000000000000000100110000111010000000000000000000010101101101100100000000000000000001010011000011110000000000000000000111000111010100100000000000000000010001101111010100000000000000000001" + "010001001101110110110010010100100000000111011010110010101011000001110111100110000000101001011111110110000000101101000100101111011111000111100010000101000011101001011000101111110011000001101" + "101101000001010100110101101110011101001011101101110011001101010111011001010010011100001100110010001110111000010001011010101110101011001110110100101100111011001101001110010100100001110000001" + "000110010101001010110111101110101010101110011000100010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "010101010101010100110101010101010101010101010101010011010101010010011111111100100011001010010011100010011111100010111110101101100100011000110001110111001010000010011011010001111100100100001" + "001100111101001010101001110011010011101101011111001010110101001111010101010010000001101001100001100100001101001000100110101100100111101010111110100011111010110101110110000010111001100000101" + "100011001111010010111010111000010001100000000001110010001100110000001110001110110010001110100000010111111000111100010000101110101100111010100111001110100010101110000011110010000011101011101" + "010101010011100100100100011010011001111101000100111010011100101101111010100111101100001001001110011101011111111000010000111110100101010110111110111011110011101111010010010011000111011110001" + "001010000001011000110101110100011001001101011000111010110111000111011001000110101011101101010011001011001101110011010000111011011100111110111001000011010010111111001001010100000110100001001" + "110110001100101110110000101011110111010110011101010010010110101111101101110110010001101001001110011000111001110001011110101100110010000100110101001110101010011100101101001011100101001111101" + "001101010111101010111101011111110010000100011001011010111101010011110110110110001010101111111011111111110111100010100010110011101101101111111001101001110010110110110110100000011001001000001" + "110000001010000110110110111100010100110110110111010011001010100000011010011011100000101111011110110111000101101101110000100110001000001101111101100111011010110010101110111100001001010001101" + "000101110111010000100100001011100100110111011100110010010100111010000111101001101111001110101011000110001011010001001010110101001111001111101010011010001011101001110110100001000100110011101" + "000011011101101010100100100000110101101100000010110011110000010010001001110100110010101000001011011110011111100101011010111110101111010111011000000111011011101101001010111011100100010110101" + "111000011010010110111001010110011011111110110011011011011111000111011101111111101101101001011101100000000000001011000100101000100100000011000010110010110010111100101111110011010111100100101" + "000100110101111110101000110000011101000101110111000010100001110011111111010011001010001000001011111001101110011011100110100111010100000111010011100111010011111110000101001110101101111011000" + "100011000011010010111111111111111111011100110111111011111111111111111100110101110001001111111111111111111000100101000010111111111111111111010010111001000011111111111111111100001110011011101" + "001001110011011100000000000000000001000101000011101000000000000000000110101011011011000000000000000000011101000110101010000000000000000001101010101010101000000000000000000110101010101010100" + "110101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101011001110010100111101101100100101" + "101100101101010010101101111100010001001111001100010100001110101010110111100100111000110011001101000001010000001011011001000110111001110101001111000111110111101011001110110111100000010000010" + "111110100101011011110100010001010001011100000011011010011101101010010110110010111110101000011110110000011111110111000010000011000011110001011101100000001001110001001000110100100111001000111" + "110001100000011010010100111000001101100011010110011010101111001000000100101110100110000000010001011100011100010001101001100100111001010001101110101011111010000011010100110110000100001111010" + "101101101101010100111110110101111001000110011000000110000000111110000110101110010001110110000011001101011001001011000111000010100110011101110011100110000111111101101110100100000010001001011" + "110010010111100101111111110010100101110111000001100110100110001101010101000101110011011000010010100001011101001011110111101000010011101001111001000110000010111110011111010101000000001000101" + "100010110110100101101000100110000001011000011011001010001111100101000100110011101011000101110000001101010010111100001110100011101101111001110010101111101000101000110011010101010011010000010" + "101010001000001110101111011100000001011110000001011101101110100001100100101110010100101101011011000010010110010010011010010010101000110001001000101010001110010011000111010110110111100101010" + "111000111010010111101011001111100101001110011110111111001100110010110100001100110111111111001100010010010111010101110110110011011011011001101100100111111001001111111010110100001101111001110" + "101010001110010100010100010101101001111101111000101000010101101101100110110000010101110010010111001111011101010111011100001100010111101001110101010101111001110110000110010110010111111011111" + "101111111000111100000111001101101001100101100111011111100011011010110110110000010011010010011110100101011100001001100100111111000000001101010000101001001001110000000110010111101100101001011" + "111000100101010110000011000010111101111011010000111000111001001010010110101001101100011000100010101111010001010101100000100010110101000101100001100101001011010011101010000110000010010101110" + "110110000000111010010100111111100001000010100000011001101010011110000110011111011010101010100011010001011011001001110011111011111101011101011000010000111010011111110001000111111100101001101" + "101010111101100010101010101110111001001100101010101010101010101010100110101010101010101010101010101010011010101010101010101010101010101001101010101010101010101010101010100110101010101010101" + "110101010101010101010101010101010101010101010101010110111001000110110110001001001110101011001110001011011010000011011110100100111001100101100010001010111000000110111100100111111011100101110" + "111111111111111111100100001001111001111111111111111110110111111001100111111111111111111110011100111011011111111111111111111001011111100101111111111111111111111010100110110111111111111111111" + "000000000000000000100101001101010000000000000000000011100100010100110000000000000000001001000010110110000000000000000000110110000011101100000000000000000010001100001010110000000000000000001" + "010011001011111100111010010110100111001000000011110011010100011011011001010000010010101100000000101100110110010000001110100101110011100000100001001110010011100101010010101110110011111011001" + "111101010101101010111000110010000100101010101001000011001110101110101111001011110001001011111000100110111011001101111000101001001100011111110110011000100010001110011011110111011001110101101" + "101011100110101100100101101110100100111001101001100010011111110000110011011100110111001001010101101111001101011101100000100011010100000000000010101100011011110010110110000100101100100100001" + "101000110101100100100110100100111110101011100111001010101011011001100111101111101011101000001001100110110001001010011000111110111101001001000111100000000011000101011100111010110000000101101" + "101010000110100100101111110101010110110000110011101011001010101101101000001001000101101001010100110111001011010100100100110000000000011011011111010111110011110000100000100111101100101001001" + "111111110101011110111100010101110010100110101010001011001000101110000010110111011001101111001111100100110010110110001100101100010000000001100010000010101010010010011001110000110100001011001" + "010110101011011000110101101000001001101001110011101011010011100010111001001000000111101011100010101000011100110001001000101100010101010100001101010000011010101101100111111110010100001010101" + "010011101100011000101010100111000101110011001010111010001011011011001010101011000100101010100111111111101010011011101110111011000010011101100011101101100011001100100010010111110010110100101" + "101100100011001010110001111100111000010011000111010011101001001000001100110100110110001110011011010000011110000111111010110101001111011110000101101000000011100000001110010101001000100100101" + "100101101000011010110011000111101100101100011011100011100011000000111001011100110111101010110011101010100010101001010000101100110110111110010010110010011010100011100111010010101100010111101" + "110010101000010100101110011101001000000100000010010010001100100100000000010011101100001100011100010100101011000100010100110001111111011010100010101010100010111000111000101010101010101010101" + "010101010101010100110101010101010101010101010101010011010101010101010101010101010101001101010101010101010101010101010100110101010101010101010101010101010011010101010101010101001100111000001" + "110010001010101100110001110110001101011011101111110011111000111111000100010011011100101001011000011010101010000001110110110011010000010010011000000110110011000110001110001011100010010011101" + "000000000001011110110010110000000010010011010011011011111110111011011001001111011111001111010110001000011011101010110010101111001010101110000101011011000011011110110000010010101111010111101" + "001110110010011100101101010101000001110011101001010011000001100101111010101111000110101011010010010100010111011101001010101101001011101100000100000110001011001100010010000000100101000000000" + "101001010101000000111111111111111111110111000000111011111111111111111110001011101010001111111111111111110001101101001110111111111111111111010101001100110011111111111111111111110010111011001" + "000100001001001110000000000000000001010011100010001000000000000000000101101111000011100000000000000000011001001001110100000000000000000001000111011011000000000000000000000101100100010111100" + "110001111000000010011011010001011101001001001111110011001100000001100111110010100001011111100011001101010111011011100001110110111100111001001001001010011111011000111101010111111001111100111" + "100110010110001010111110001101000001111111001101110010110000111111110111010111001000111010001011100110010001111110101111000100110001010101010110000011000011000011010001010101100101010010001" + "111100000110000110100111011110001001110100111000111011101000001110110100101100001000111011010000101000010001000111101010011110001011100001110011010100110111110011011011010111101000000100001" + "101110101000000011111011101101110101000010001001000101010010001001100110100110001011011000000001011000010000001001011010111010000111011101001000100101101101111011000001000110001101101100010" + "100011011100010100010111111010111001111010100111000010010101111101100111110001101111001000000101011001010100110001001010110100101010101001001101110001100011100000011011100101110000000110111" + "100110111101011101110101101010011001001111000100000111001000010100100111010001001110111111000100110110010100001100011010011010101110011101111001010010110011010000011010110110001001010001101" + "100011011111011101000000101001010001101101101110110100111110101010010110111001111101000100010100100101011010000110100111011101100000011101001111100010000101001011110000010111110000101111111" + "101100001011111111111111011110010101000001101101101001100101101111100101111000100101010010000001010111010101100101101100100100100011011101101001011010100110100111001100010100011010110010111" + "100001001101001011001001110101110001101001010101000101000001110001010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010" + "101010101010101010101010101010101001101010101010101010101010101010100110111011001110101101111010011111011000011101111001000111010100111101100001000001110110010010000111010101101010011101011" + "101111010011010010000111101101100001100110111110000010001010001101110111000011101001101101011100000001011010101100100110100110110110011101010100011001101101101101010001000100111011110010011" + "100110110110110101101010011101101001001011111000110010110111001111000111000011010111011001001001110011011100111110111000100000001110110101100100101001010110000101100111110101000001001001100" + "101110111000000100001101001100001101100111001010101001010111000001010101010010000100000111110000110111011110011011001011011000010001010001100110001111110001001010111000110101001011110100111" + "101110011100111101100111011000101001010101011100111011010110110110110100110011000101100111111101011011011101011100111011110011010000101101111100001110011101101111110101010111010101111011100" + "110111011000010100100010101100010001111001010010011110111111100110000100111001000000111100111001010010010001011100111010011111001001110001111000001011001111010011110100000100011000110010101" + "111111111111111111101101110011001101111111111111111111100100010101010111111111111111111001001100110011011111111111111111101010111101010101111111111111111110101111100000000111111111111111111" + "000000000000000000110100101011001100000000000000000010010000111000110000000000000000001010111100101111000000000000000000101011010010011100000000000000000011011100101100100000000000000000001" + "011001010000110100111010100010100010111100010011001010001110110100001100110001011010001000001010100111111010000001100100101110001101000000111110100011111010111111000110101011011001010111001" + "111111110100100000111110010000110000001011111100100010011111010100101000101111000101101111010101001011110101111100111110101100010011111000001001100101101011001101110110101101011110100110001" + "110011111011000100101010000111010110101110100000010010011110000110111010011111000011001001000100001010001001011001001000110101010111110111101100110111000010011101101011110010111101011000001" + "100011011000011010110111111111100000111001000001101010101111001010111101001011111001001011101101010001010001010110111000101101110101110100010011001011010010111111101101100100110101100001101" + "101010100010100110111010110001001110011100011100000010111001000110010011001011111100101110100011110111001001101011010100100110011011001001010001011110000010101000101101111101111010100110101" + "011010011100111000110100011110001100101000011110100011010111101100111101101001011010001100110010001110101001000010010110100010101110011111001010111011001011110101010101111011101011100101001" + "101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101" + "010001111001111010101111111110110110010110011110000011000001010001101001000001000101001010001010011100001110100011001000101101101101001010001001101010011011001100110111000111011100010110101" + "110111101000000110111011010100000011000110110111100011101100101001001011000111001111001010001011010101001010100011011100100001110110111011110101001111010010101011001101011111111101011000101" + "101111111100000110111101010011001000010111001000001011111010001011111011111100001100101110100000001010101011010110000110111001001001001000001110010100011010110101010010101001000000111001001" + "000000111010010100111110000011011011111000011111010011011011011100111111010011111000001011110001100101010110000011010010111100011100101101011000010000010010001110111010111110011110110111001" + "111011010111101110101111010111100110101100101100000011100000010000110110000011100101001011111011000011100100000110111010110010110001010110010010111001010011101010010000111000101110010001101" + "101100010010011110111101111010011001011010001111011011000000001101110111111001110001001101101111101110001100111010110100110111011000011110001000011001001011110110111011000100100000101110101" + "111000001010001000101010001111011001010000000101000011100011111011011100101011011110101100100010101111101000011000100100111000100111100110000000000011110010000110111010011000010110110000101" + "001000011000001100101110100010101100000001000111010011101010001011000100111001101010101101000101110111001110101010110100100100011000011010010000110011010011111011000010111000100100100101100" + "101100010100000000111111111111111111111010001101110011111111111111111101111101001111101111111111111111110101011100010110111111111111111111101000100000100011111111111111111100101110101101101" + "000001010101000110000000000000000001100100010010000000000000000000000101110010111111000000000000000000010011000101010100000000000000000001111011011000010000000000000000000100101100001011000" + "101101111001000111000000001100010101010100110111101010011000000010100111011011010010101000100101001001010101111100001001000111101100100101100100110011011001111101111001110101111111111011011" + "101000011100011010000001001011010001100010100010111001010001010100010100101010111111001001100100101010010110110110111100011001010001011001011110011001101010110001000010010111010011011010001" + "100001101000100111001000000101000001100111110110101110001100111101000111000010001111101100111110001100010101011010011010110010000101111001110111111111111001001011101000010111010011100110110" + "101011101110001000100101101011000101011001111010001110000001011010100110000010101000100110101010101010011010101010101010101010101010101001101010101010101010101010101010100110101010101010101" + "110101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010110110111011100011010111110101100111001111101110010001100101011100111100111100100010101000100110" + "110010010101111101010000111010101001001101001011110001110011001100010110011100010110000101001100010110011100111101110101000110100101011001100101101100111010000101010101010100110110001100110" + "100010010010010111011011100100100001100010011001111111100111101000110111000000110101110101111001000010010111101010110101111000001101110101100000111010100101001011001000100110101001101111001" + "100100011001011101110111110001000001110011010111000101100110011010000100101001010101011001001001110010011101010011001111000000000110001101011011000011000001001001000111100110110111010101110" + "111000100101101001011110010110111101001111111000001011101010111110110101010001101001011000000110000100011000101110011000110110000011111101001001101010101011110110100101000101101111100110010" + "100011101100111001101001110100011001101111001111110011100111011110110100000001111010111010100000011001011100110010001110001011011010011101010101100111100011001100010111010101011001101011010" + "110010110010011111001010000001110001100010100010010001010010001000100101101001011101000010000110101011010100010011101100111110100011111101010111001100000000110011101001000111001010000011111" + "101111010010111011101011110000011001100010000010100101100111000010000101000000101011110100010010110101010100100110101001100100111011010101111111111000111100001001001011110100100101101100101" + "111100011100001101101111110100011001010011110001011110111001011001100101111111101000001001010000010110010110101001110010001001110101111101110110011010011011010001000011010100101000101100000" + "111011010001111000101101000110010101101111001010010011101111110101000111100101000110000100010011111111011001110010101000001000011000111001110011111000111111000111111001010111011010011100011" + "100111000001100000110010000000110101111000101001100010101111001111010100110011011110010111010101110110011110111110100011111111011111001001111110000100000111010000011000100110010110100001101" + "111111111111111111101001100101100001111111111111111111101000011111010111111111111111111010101011110001011111111111111111110111000100111101111111111111111111101100111010100111111111111111111" + "000000000000000000110100100110110100000000000000000011010100001001010000000000000000001101011011000111000000000000000000101000001010000100000000000000000010101100100101010000000000000000001" + "111100001011101000101100111111110010000000011110110011010001101011110111010111110110101100101001101100101000000110010100101111110100101001000100101001010010000111100111001010111011101101001" + "110000101110010100110101010101010101010101010101010011010101010101010101010101010101001101010101010101010101010101010100110101010101010101010101010101010011010101010101010101010101010101001" + "101010101010101010101110000000010001110100101101111011000011010000111001000001101010001100001110010100110101100110101110100001110110110001111001000110111011010110110011000101011001111110001" + "111110000010100010110101110110101101011010010000101010101100011011100011001101100101001111001100100001000010101111111010110001001111100111011010010001110011001001000100001100111010001111001" + "111111001011011000111011101011100111000011000111101011111111111001111110011110010110101001110010011000111001000001100000101111100110010101010110001011000011010101000101111000001010010110101" + "001010101100100110110001000001101000110011011000100010101110110111101111001010101011101011010010111000000110010100000110100000001001001101011001100010011010101011000010001101100100000000001" + "001110001001110000100110110001000110010001000111110010110011000001011100111101100110001001010011001110111100011111010110111011011010010100100000001001001010000101100110010010000011101001001" + "101000110011001110110100111000000111011001011011011011010111000001011101000011111000101010101100011010111110010011110010110001010010111010100111110111111010111100110000100101111001000001101" + "101010100101110000100000101111000100100011010101001011010010001100001000110000111011101111101010111000111011101110010010110110110001010010011001111001101010001011100000110011011110100010110" + "000000001100001110111001010000001011001011000010000011100111101000000110011001111110101010000001100010111110000001000100111101110011100000010110010100100010101011111011110101000000100000000" + "111111101111100110101011101111100101011100001000111011011010010110001011010100000101101111000110100111001111111011011010110111000000110010100001010101010010110100101100010100000011001110101" + "000000101010100010110000100011101010110011110001100010010111100010001010111010100000101001010011111100101110101000101110110101000101000011101101110111000011100100111100110010100111101110101" + "111110100001101010101001011111100101000001111101011010001111001001010110100100100100101000100010111011110110001100110010101101001101001110100100011011000011001110101001010111111001001110101" + "000010101101100110111111000100110100010111110000111011010010011101000001111111101111001010001100100100000011011110100000100010111101011100010101000000100010011100111100000010000010000000101" + "111010100010101100100001000111011001111101000101100010010010110010011100110011010010101111011001001011011110011110101010101110111100011111011000001001101011010100101111100010111011001111101" + "111010101011011100110101010010111000001100010010111011010101010101010001010101010101001101010101010101000101010101010100110101010101010100010101010101010011010101010101010001010101100000001" + "111010101010101010111111111111111101001010101010101011111111111111110100101010101010101111111111111111010010101010101010111111111111111101001010101010101011111111111111110100101010001111111" + }, + /* 18*/ { UNICODE_MODE | ESCAPE_MODE, -1, -1, 4 << 8, "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。它的主要技术特色是:1. 具有高度的汉字表示能力和汉字压缩效率。2. 信息容量大。 3. 编码范围广,可以将照片、指纹、掌纹、签字、声音、文字等凡可数字化的信息进行编码。4. 支持加密技术。5.抗污损和畸变能力强。6.修正错误能力强。7 .可供用户选择的纠错能力。8.容易制作且成本低。9.汉信码支持84个版本,可以由用户自主进行选择,最小码仅有指甲大小。10. 外形美观。", 0, 67, 67, "Previous draft Figure 1 **NOT SAME** different encodation, Binary mode not used by figure", + "1111111000010101011111111111111110001011011110010101111111001111111" + "1000000010000100000000000000000010100011101001010001101110000000001" + "1011111001100100110100001101111011111100101010000111111111101111101" + "1010000011010001001000011101000011111110111001011111100101000000101" + "1010111000011101100100100001110011111101011101101011011111101110101" + "1010111011110000000100000101110011100011100011100011110100101110101" + "1010111011000110000011001011001011110110001010100101101111001110101" + "0000000000010011100110010011011011000111101101001111111101000000000" + "0010101100110010001100111111010011001110010110000110100100111010101" + "1100010010001111111101001101001011111010010100110011001010010001100" + "1110001011001110000010010100101010110010010010111010001000000101000" + "1000010011000111111001000011111011101100011010010111110011110110111" + "1011101100011011001010101101100011111000011110101001011101101100100" + "1010101100001100101111110100010010110010011100000101100110011010100" + "1011100110100101010000001101011011001111001001011101101001010000010" + "1000110001000110010011101001111010011100010101100010001100001100000" + "1110111000011000010011111001000010011001001000111000000010000011100" + "1111111111111111011111011011011011111111111111111110101001010000101" + "0000000000000001101010110001000000000000000000000101110111011010000" + "1011000000111001101001011111000001001110001001110101011111101010000" + "1101111001111001101011110110000111101111111001110100111100001000111" + "0000010100000001111111001100011100100000001100100100111010110101000" + "0000000001011001010101010111101100010011010110110111100001001001001" + "1111100011110001010010111011111001010010000100100110111001111001110" + "0111000001000001101111001001110101001011111111000111000100111101001" + "0110100011111001110101110000010111101100110011110100101111011100011" + "1100110110011101000101011100101101010011100101010100100010100001100" + "1110000110010001001110011101110000011010100011110101011000011110111" + "0110111001111001000110110111100110111011101011100111111110110111010" + "0110001110100001000001011100011110101111101000000101000110011100000" + "0011100000010001010111100100001001111100101000110101001000101100001" + "0011001100010101010010000111000011110111000111100100001110000111110" + "0000101111100101010011001110010001011000000011100111010010111000010" + "0011101110110001011110110110000111011001000111100110101000000000100" + "1001100100000001111111111111111110111001100101110111111111111111111" + "0001010111111100000000000000000010011111111111110000000000000000001" + "1001000011000011000000100100011011100110100001010101100010010001101" + "1111010101001110010000110000000010110110001100111011001001000101001" + "1110010110101110101100101001001011000100000101010100000110111011001" + "1010100110000000010001111110110010111101101100000110110011110001001" + "1000111010101011001100101101010011100010110100111011110001100000001" + "1001000011100101100000001010111010001110110110100110100100000100101" + "1000111011000001101101100011001011101111110100010100101011110011001" + "1011111101100010000011100110111011111110110011100010011011101110001" + "1011000000001111011100100110011011010010111110000100100011100010001" + "1101100010000101111010111000100011110100101010110111011010110001001" + "1001000011001110100101100010101010111100101100011100010100111010101" + "1000000011010101101010100011111010011000011111111010100001101011001" + "1101000110100100011111001110111011001000000100100000111110010110001" + "1111110100001111111101100110111011010110010100000001101011010010101" + "1000001100001001001110011110111010001100000011011100101100100011000" + "1111111111111111111011011001111011111111111111111111100111000010001" + "0000000000000001011000100101010000000000000000000110011010110100100" + "0001110001101101011100101111100111111000010010000101000001011100110" + "0111010100110001000010100001101000001001010110000111111101100011100" + "0011011001010101001111011111001101101100101101010100101111001111110" + "0001101100100101011100001110111010011110010010100100100001000101001" + "1001011100010001101010010110011000110110111100000101110110000010000" + "1010101111000101011011011010010110000010111000110100011001011010100" + "0000000001101101011110101100001101100101100001110110110111000000000" + "1111111000111101000010111100100101111011111010010110011101101110101" + "0000001010111001111001001100110011010101111100110100010010101110101" + "1111101011100101001111011101111011001000100010100111101010001110101" + "0000101000011101111001100110101001011110101110010110100010100000101" + "1110101010010101000111011101001011100010000001100100010100001111101" + "1110101001101001000100110010101000000101000110010110110110100000001" + "1110101000010001111111111111111010010111110110110111111111001111111" + }, + /* 19*/ { DATA_MODE, -1, -1, ZINT_FULL_MULTIBYTE, "é", 0, 23, 23, "Mask automatic (01)", + "11111110100010101111111" + "10000000001010000000001" + "10111110111010001111101" + "10100000100101000000101" + "10101110001111101110101" + "10101110110100101110101" + "10101110011101001110101" + "00000000101010100000000" + "00010101101101001010101" + "00001011010010000111010" + "10100010010010101010010" + "10110101010101100010110" + "10101000010110101010100" + "10011111000110000101000" + "10101010000001110101000" + "00000000101001100000000" + "11111110001000001110101" + "00000010110000101110101" + "11111010110001001110101" + "00001010010000100000101" + "11101010010100101111101" + "11101010001001000000001" + "11101010101010101111111" + }, + /* 20*/ { DATA_MODE, -1, -1, ZINT_FULL_MULTIBYTE | (1 << 8), "é", 0, 23, 23, "Mask 00", + "11111110001000001111111" + "10000000111111000000001" + "10111110110000001111101" + "10100000010000100000101" + "10101110100101101110101" + "10101110000001101110101" + "10101110010111001110101" + "00000000111111100000000" + "00010101100111110010101" + "01011110000111010010000" + "00001000111000000000111" + "11100000000000110111100" + "00000010111100000000001" + "11001010010011010000010" + "10101001101011110101000" + "00000000111100100000000" + "11111110000010001110101" + "00000010100101001110101" + "11111010111011101110101" + "00001010100101000000101" + "11101010011110101111101" + "11101010011100100000001" + "11101010000000001111111" + }, + /* 21*/ { DATA_MODE, -1, -1, ZINT_FULL_MULTIBYTE | (4 << 8), "é", 0, 23, 23, "Mask 11", + "11111110000101101111111" + "10000000111000100000001" + "10111110110000101111101" + "10100000101000000000101" + "10101110111101101110101" + "10101110100110001110101" + "10101110101110101110101" + "00000000111000000000000" + "00010101100000111010101" + "01000100011111101010111" + "10010010100111000111100" + "00100101101111110000100" + "01000111010010111000110" + "00001101111110010111010" + "10101011111001110101000" + "00000000001110100000000" + "11111110110000101110101" + "00000010001000101110101" + "11111010110110101110101" + "00001010001000100000101" + "11101010101100101111101" + "11101010100110100000001" + "11101010111010001111111" + }, + /* 22*/ { DATA_MODE, -1, -1, ZINT_FULL_MULTIBYTE | (5 << 8), "é", 0, 23, 23, "Mask > 11 ignored", + "11111110100010101111111" + "10000000001010000000001" + "10111110111010001111101" + "10100000100101000000101" + "10101110001111101110101" + "10101110110100101110101" + "10101110011101001110101" + "00000000101010100000000" + "00010101101101001010101" + "00001011010010000111010" + "10100010010010101010010" + "10110101010101100010110" + "10101000010110101010100" + "10011111000110000101000" + "10101010000001110101000" + "00000000101001100000000" + "11111110001000001110101" + "00000010110000101110101" + "11111010110001001110101" + "00001010010000100000101" + "11101010010100101111101" + "11101010001001000000001" + "11101010101010101111111" + }, }; - int data_size = sizeof(data) / sizeof(struct item); + int data_size = ARRAY_SIZE(data); + + char escaped[8192]; for (int i = 0; i < data_size; i++) { @@ -427,27 +1419,18 @@ static void test_encode(int index, int generate, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = BARCODE_HANXIN; - symbol->input_mode = data[i].input_mode; - if (data[i].option_1 != -1) { - symbol->option_1 = data[i].option_1; - } - if (data[i].option_2 != -1) { - symbol->option_2 = data[i].option_2; - } - symbol->debug |= debug; - - int length = strlen(data[i].data); + int length = testUtilSetSymbol(symbol, BARCODE_HANXIN, data[i].input_mode, -1 /*eci*/, data[i].option_1, data[i].option_2, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { \"%s\", %s, %d, %d, %s, %d, %d, \"%s\",\n", - i, data[i].data, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_2, testUtilErrorName(data[i].ret), + printf(" /*%3d*/ { %s, %d, %d, %s, \"%s\", %s, %d, %d, \"%s\",\n", + i, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_2, testUtilOption3Name(data[i].option_3), + testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment); testUtilModulesDump(symbol, " ", "\n"); - printf(" },\n"); + printf(" },\n"); } else { if (ret < 5) { assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); @@ -467,6 +1450,106 @@ static void test_encode(int index, int generate, int debug) { testFinish(); } +#include + +#define TEST_PERF_ITERATIONS 1000 + +// Not a real test, just performance indicator +static void test_perf(int index, int debug) { + + if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */ + return; + } + + int ret; + struct item { + int symbology; + int input_mode; + int option_1; + int option_2; + char *data; + int ret; + + int expected_rows; + int expected_width; + char *comment; + }; + struct item data[] = { + /* 0*/ { BARCODE_HANXIN, UNICODE_MODE, -1, -1, + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。", + 0, 43, 43, "98 chars, Region 1 and Text" }, + /* 1*/ { BARCODE_HANXIN, UNICODE_MODE, -1, -1, + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。", + 0, 121, 121, "980 chars, Region 1 and Text" }, + /* 2*/ { BARCODE_HANXIN, UNICODE_MODE, -1, -1, + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。" + "汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。汉信码(Chinese-Sensible Code)是一种能够有效表示汉字、图像等信息的二维条码。", + 0, 147, 147, "1470 chars, Region 1 and Text" }, + }; + int data_size = ARRAY_SIZE(data); + + clock_t start, total_encode = 0, total_buffer = 0, diff_encode, diff_buffer; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + diff_encode = diff_buffer = 0; + + for (int j = 0; j < TEST_PERF_ITERATIONS; j++) { + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + int length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, data[i].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); + + 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); + + total_encode += diff_encode; + total_buffer += diff_buffer; + } + if (index != -1) { + printf("totals: encode %gms, buffer %gms\n", total_encode * 1000.0 / CLOCKS_PER_SEC, total_buffer * 1000.0 / CLOCKS_PER_SEC); + } +} + int main(int argc, char *argv[]) { testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ @@ -474,6 +1557,7 @@ int main(int argc, char *argv[]) { { "test_options", test_options, 1, 0, 1 }, { "test_input", test_input, 1, 1, 1 }, { "test_encode", test_encode, 1, 1, 1 }, + { "test_perf", test_perf, 1, 0, 1 }, }; testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); diff --git a/backend/tests/test_library.c b/backend/tests/test_library.c index 976ad68c..0ab54f92 100644 --- a/backend/tests/test_library.c +++ b/backend/tests/test_library.c @@ -241,11 +241,11 @@ static void test_cap(int index) { /* 0*/ { BARCODE_CODE128, ZINT_CAP_HRT, ZINT_CAP_HRT }, /* 1*/ { BARCODE_CODE128, ZINT_CAP_HRT | ZINT_CAP_STACKABLE | ZINT_CAP_GS1, ZINT_CAP_HRT | ZINT_CAP_STACKABLE }, /* 2*/ { BARCODE_PDF417, ZINT_CAP_HRT | ZINT_CAP_ECI | ZINT_CAP_GS1 | ZINT_CAP_READER_INIT | ZINT_CAP_FULL_MULTIBYTE, ZINT_CAP_ECI | ZINT_CAP_READER_INIT }, - /* 3*/ { BARCODE_QRCODE, ZINT_CAP_HRT | ZINT_CAP_ECI | ZINT_CAP_GS1 | ZINT_CAP_DOTTY | ZINT_CAP_READER_INIT | ZINT_CAP_FULL_MULTIBYTE, ZINT_CAP_ECI | ZINT_CAP_GS1 | ZINT_CAP_DOTTY | ZINT_CAP_FULL_MULTIBYTE }, + /* 3*/ { BARCODE_QRCODE, ZINT_CAP_HRT | ZINT_CAP_ECI | ZINT_CAP_GS1 | ZINT_CAP_DOTTY | ZINT_CAP_READER_INIT | ZINT_CAP_FULL_MULTIBYTE | ZINT_CAP_MASK, ZINT_CAP_ECI | ZINT_CAP_GS1 | ZINT_CAP_DOTTY | ZINT_CAP_FULL_MULTIBYTE | ZINT_CAP_MASK }, /* 4*/ { BARCODE_EANX_CC, ZINT_CAP_HRT | ZINT_CAP_COMPOSITE | ZINT_CAP_EXTENDABLE | ZINT_CAP_ECI | ZINT_CAP_GS1, ZINT_CAP_HRT | ZINT_CAP_COMPOSITE | ZINT_CAP_EXTENDABLE | ZINT_CAP_GS1 }, - /* 5*/ { BARCODE_HANXIN, ZINT_CAP_DOTTY | ZINT_CAP_FIXED_RATIO | ZINT_CAP_FULL_MULTIBYTE, ZINT_CAP_DOTTY | ZINT_CAP_FIXED_RATIO | ZINT_CAP_FULL_MULTIBYTE }, + /* 5*/ { BARCODE_HANXIN, ZINT_CAP_DOTTY | ZINT_CAP_FIXED_RATIO | ZINT_CAP_FULL_MULTIBYTE | ZINT_CAP_MASK, ZINT_CAP_DOTTY | ZINT_CAP_FIXED_RATIO | ZINT_CAP_FULL_MULTIBYTE | ZINT_CAP_MASK }, /* 6*/ { BARCODE_CODE11, ZINT_CAP_DOTTY | ZINT_CAP_FIXED_RATIO | ZINT_CAP_READER_INIT | ZINT_CAP_FULL_MULTIBYTE, 0 }, - /* 7*/ { BARCODE_POSTNET, ZINT_CAP_HRT | ZINT_CAP_STACKABLE | ZINT_CAP_EXTENDABLE | ZINT_CAP_COMPOSITE | ZINT_CAP_ECI | ZINT_CAP_GS1 | ZINT_CAP_DOTTY | ZINT_CAP_FIXED_RATIO | ZINT_CAP_READER_INIT | ZINT_CAP_FULL_MULTIBYTE, 0 }, + /* 7*/ { BARCODE_POSTNET, ZINT_CAP_HRT | ZINT_CAP_STACKABLE | ZINT_CAP_EXTENDABLE | ZINT_CAP_COMPOSITE | ZINT_CAP_ECI | ZINT_CAP_GS1 | ZINT_CAP_DOTTY | ZINT_CAP_FIXED_RATIO | ZINT_CAP_READER_INIT | ZINT_CAP_FULL_MULTIBYTE | ZINT_CAP_MASK, 0 }, /* 8*/ { 0, 0, 0 }, }; int data_size = ARRAY_SIZE(data); diff --git a/backend/tests/test_png.c b/backend/tests/test_png.c index 93739cdf..62deab6a 100644 --- a/backend/tests/test_png.c +++ b/backend/tests/test_png.c @@ -168,8 +168,8 @@ static void test_print(int index, int generate, int debug) { }; int data_size = ARRAY_SIZE(data); - char* data_dir = "../data/png"; - char* png = "out.png"; + char *data_dir = "../data/png"; + char *png = "out.png"; char escaped[1024]; int escaped_size = 1024; char *text; diff --git a/backend/tests/test_qr.c b/backend/tests/test_qr.c index ac506ae5..961cc06b 100644 --- a/backend/tests/test_qr.c +++ b/backend/tests/test_qr.c @@ -37,9 +37,9 @@ static void test_qr_options(int index, int debug) { int ret; struct item { - char *data; int option_1; int option_2; + char *data; int ret_encode; int ret_vector; int expected_size; @@ -47,40 +47,40 @@ static void test_qr_options(int index, int debug) { }; // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { "12345", -1, -1, 0, 0, 21, -1 }, // ECC auto-set to 1 (L), version auto-set to 1 - /* 1*/ { "12345", 5, -1, 0, 0, 21, 0 }, // ECC > 4 ignored - /* 2*/ { "12345", -1, 41, 0, 0, 21, 0 }, // Version > 40 ignored - /* 3*/ { "12345", -1, 2, 0, 0, 25, -1 }, // ECC auto-set to 4 (Q), version 2 - /* 4*/ { "12345", 4, 2, 0, 0, 25, 0 }, // ECC 4 (Q), version 2 - /* 5*/ { "12345", 1, 2, 0, 0, 25, 1 }, // ECC 1 (L), version 2 - /* 6*/ { "貫やぐ識禁", -1, -1, 0, 0, 21, -1 }, // ECC auto-set to 1 (L), version auto-set to 1 - /* 7*/ { "貫やぐ識禁", 1, -1, 0, 0, 21, 0 }, // Version auto-set to 1 - /* 8*/ { "貫やぐ識禁", -1, 1, 0, 0, 21, 0 }, // ECC auto-set to 1 (L) - /* 9*/ { "貫やぐ識禁", 1, 1, 0, 0, 21, 0 }, - /* 10*/ { "貫やぐ識禁", 2, 1, ZINT_ERROR_TOO_LONG, -1, 0, -1 }, // ECC 2 (M), version 1 - /* 11*/ { "貫やぐ識禁", 2, -1, 0, 0, 25, -1 }, // Version auto-set to 2 - /* 12*/ { "貫やぐ識禁", 2, 2, 0, 0, 25, 0 }, - /* 13*/ { "貫やぐ識禁", 1, 2, 0, 0, 25, 1 }, - /* 14*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", -1, -1, 0, 0, 29, -1 }, // ECC auto-set to 1 (L), version auto-set to 3 - /* 15*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 1, 3, 0, 0, 29, 0 }, - /* 16*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 2, -1, 0, 0, 33, -1 }, // ECC 2 (M), version auto-set to 4 - /* 17*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 2, 4, 0, 0, 33, 0 }, - /* 18*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 3, -1, 0, 0, 37, -1 }, // ECC 3 (Q), version auto-set to 5 - /* 19*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 3, 5, 0, 0, 37, 0 }, - /* 20*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 4, -1, 0, 0, 41, -1 }, // ECC 4 (H), version auto-set to 6 - /* 21*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 4, 6, 0, 0, 41, 0 }, - /* 22*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。", -1, -1, 0, 0, 69, -1 }, // ECC auto-set to 1, version auto-set to 13 - /* 23*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。", 1, 13, 0, 0, 69, 0 }, - /* 24*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。", 4, -1, 0, 0, 101, -1 }, // ECC 4, version auto-set to 21 - /* 25*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。", 4, 21, 0, 0, 101, 0 }, - /* 26*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。社ト可化モマ試音ばじご育青康演ぴぎ権型固スで能麩ぜらもほ河都しちほラ収90作の年要とだむ部動ま者断チ第41一1米索焦茂げむしれ。測フ物使だて目月国スリカハ夏検にいへ児72告物ゆは載核ロアメヱ登輸どべゃ催行アフエハ議歌ワ河倫剖だ。記タケウ因載ヒイホヤ禁3輩彦関トえび肝区勝ワリロ成禁ぼよ界白ウヒキレ中島べせぜい各安うしぽリ覧生テ基一でむしゃ中新トヒキソ声碁スしび起田ア信大未ゅもばち。", -1, -1, 0, 0, 105, -1 }, // ECC auto-set to 1, version auto-set to 22 - /* 27*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。社ト可化モマ試音ばじご育青康演ぴぎ権型固スで能麩ぜらもほ河都しちほラ収90作の年要とだむ部動ま者断チ第41一1米索焦茂げむしれ。測フ物使だて目月国スリカハ夏検にいへ児72告物ゆは載核ロアメヱ登輸どべゃ催行アフエハ議歌ワ河倫剖だ。記タケウ因載ヒイホヤ禁3輩彦関トえび肝区勝ワリロ成禁ぼよ界白ウヒキレ中島べせぜい各安うしぽリ覧生テ基一でむしゃ中新トヒキソ声碁スしび起田ア信大未ゅもばち。", 1, 22, 0, 0, 105, 0 }, - /* 28*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。社ト可化モマ試音ばじご育青康演ぴぎ権型固スで能麩ぜらもほ河都しちほラ収90作の年要とだむ部動ま者断チ第41一1米索焦茂げむしれ。測フ物使だて目月国スリカハ夏検にいへ児72告物ゆは載核ロアメヱ登輸どべゃ催行アフエハ議歌ワ河倫剖だ。記タケウ因載ヒイホヤ禁3輩彦関トえび肝区勝ワリロ成禁ぼよ界白ウヒキレ中島べせぜい各安うしぽリ覧生テ基一でむしゃ中新トヒキソ声碁スしび起田ア信大未ゅもばち。", 4, -1, 0, 0, 153, 1 }, // ECC 4, version auto-set 34 - /* 29*/ { "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。社ト可化モマ試音ばじご育青康演ぴぎ権型固スで能麩ぜらもほ河都しちほラ収90作の年要とだむ部動ま者断チ第41一1米索焦茂げむしれ。測フ物使だて目月国スリカハ夏検にいへ児72告物ゆは載核ロアメヱ登輸どべゃ催行アフエハ議歌ワ河倫剖だ。記タケウ因載ヒイホヤ禁3輩彦関トえび肝区勝ワリロ成禁ぼよ界白ウヒキレ中島べせぜい各安うしぽリ覧生テ基一でむしゃ中新トヒキソ声碁スしび起田ア信大未ゅもばち。", 4, 34, 0, 0, 153, 0 }, - /* 30*/ { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 4, -1, 0, 0, 177, -1 }, // 1852 alphanumerics max for ECC 4 (H) - /* 31*/ { "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 1, -1, 0, 0, 177, -1 }, // 4296 alphanumerics max for ECC 1 (L) + /* 0*/ { -1, -1, "12345", 0, 0, 21, -1 }, // ECC auto-set to 1 (L), version auto-set to 1 + /* 1*/ { 5, -1, "12345", 0, 0, 21, 0 }, // ECC > 4 ignored + /* 2*/ { -1, 41, "12345", 0, 0, 21, 0 }, // Version > 40 ignored + /* 3*/ { -1, 2, "12345", 0, 0, 25, -1 }, // ECC auto-set to 4 (Q), version 2 + /* 4*/ { 4, 2, "12345", 0, 0, 25, 0 }, // ECC 4 (Q), version 2 + /* 5*/ { 1, 2, "12345", 0, 0, 25, 1 }, // ECC 1 (L), version 2 + /* 6*/ { -1, -1, "貫やぐ識禁", 0, 0, 21, -1 }, // ECC auto-set to 1 (L), version auto-set to 1 + /* 7*/ { 1, -1, "貫やぐ識禁", 0, 0, 21, 0 }, // Version auto-set to 1 + /* 8*/ { -1, 1, "貫やぐ識禁", 0, 0, 21, 0 }, // ECC auto-set to 1 (L) + /* 9*/ { 1, 1, "貫やぐ識禁", 0, 0, 21, 0 }, + /* 10*/ { 2, 1, "貫やぐ識禁", ZINT_ERROR_TOO_LONG, -1, 0, -1 }, // ECC 2 (M), version 1 + /* 11*/ { 2, -1, "貫やぐ識禁", 0, 0, 25, -1 }, // Version auto-set to 2 + /* 12*/ { 2, 2, "貫やぐ識禁", 0, 0, 25, 0 }, + /* 13*/ { 1, 2, "貫やぐ識禁", 0, 0, 25, 1 }, + /* 14*/ { -1, -1, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 0, 0, 29, -1 }, // ECC auto-set to 1 (L), version auto-set to 3 + /* 15*/ { 1, 3, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 0, 0, 29, 0 }, + /* 16*/ { 2, -1, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 0, 0, 33, -1 }, // ECC 2 (M), version auto-set to 4 + /* 17*/ { 2, 4, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 0, 0, 33, 0 }, + /* 18*/ { 3, -1, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 0, 0, 37, -1 }, // ECC 3 (Q), version auto-set to 5 + /* 19*/ { 3, 5, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 0, 0, 37, 0 }, + /* 20*/ { 4, -1, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 0, 0, 41, -1 }, // ECC 4 (H), version auto-set to 6 + /* 21*/ { 4, 6, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 0, 0, 41, 0 }, + /* 22*/ { -1, -1, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。", 0, 0, 69, -1 }, // ECC auto-set to 1, version auto-set to 13 + /* 23*/ { 1, 13, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。", 0, 0, 69, 0 }, + /* 24*/ { 4, -1, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。", 0, 0, 101, -1 }, // ECC 4, version auto-set to 21 + /* 25*/ { 4, 21, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。", 0, 0, 101, 0 }, + /* 26*/ { -1, -1, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。社ト可化モマ試音ばじご育青康演ぴぎ権型固スで能麩ぜらもほ河都しちほラ収90作の年要とだむ部動ま者断チ第41一1米索焦茂げむしれ。測フ物使だて目月国スリカハ夏検にいへ児72告物ゆは載核ロアメヱ登輸どべゃ催行アフエハ議歌ワ河倫剖だ。記タケウ因載ヒイホヤ禁3輩彦関トえび肝区勝ワリロ成禁ぼよ界白ウヒキレ中島べせぜい各安うしぽリ覧生テ基一でむしゃ中新トヒキソ声碁スしび起田ア信大未ゅもばち。", 0, 0, 105, -1 }, // ECC auto-set to 1, version auto-set to 22 + /* 27*/ { 1, 22, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。社ト可化モマ試音ばじご育青康演ぴぎ権型固スで能麩ぜらもほ河都しちほラ収90作の年要とだむ部動ま者断チ第41一1米索焦茂げむしれ。測フ物使だて目月国スリカハ夏検にいへ児72告物ゆは載核ロアメヱ登輸どべゃ催行アフエハ議歌ワ河倫剖だ。記タケウ因載ヒイホヤ禁3輩彦関トえび肝区勝ワリロ成禁ぼよ界白ウヒキレ中島べせぜい各安うしぽリ覧生テ基一でむしゃ中新トヒキソ声碁スしび起田ア信大未ゅもばち。", 0, 0, 105, 0 }, + /* 28*/ { 4, -1, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。社ト可化モマ試音ばじご育青康演ぴぎ権型固スで能麩ぜらもほ河都しちほラ収90作の年要とだむ部動ま者断チ第41一1米索焦茂げむしれ。測フ物使だて目月国スリカハ夏検にいへ児72告物ゆは載核ロアメヱ登輸どべゃ催行アフエハ議歌ワ河倫剖だ。記タケウ因載ヒイホヤ禁3輩彦関トえび肝区勝ワリロ成禁ぼよ界白ウヒキレ中島べせぜい各安うしぽリ覧生テ基一でむしゃ中新トヒキソ声碁スしび起田ア信大未ゅもばち。", 0, 0, 153, 1 }, // ECC 4, version auto-set 34 + /* 29*/ { 4, 34, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。社ト可化モマ試音ばじご育青康演ぴぎ権型固スで能麩ぜらもほ河都しちほラ収90作の年要とだむ部動ま者断チ第41一1米索焦茂げむしれ。測フ物使だて目月国スリカハ夏検にいへ児72告物ゆは載核ロアメヱ登輸どべゃ催行アフエハ議歌ワ河倫剖だ。記タケウ因載ヒイホヤ禁3輩彦関トえび肝区勝ワリロ成禁ぼよ界白ウヒキレ中島べせぜい各安うしぽリ覧生テ基一でむしゃ中新トヒキソ声碁スしび起田ア信大未ゅもばち。", 0, 0, 153, 0 }, + /* 30*/ { 4, -1, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 0, 0, 177, -1 }, // 1852 alphanumerics max for ECC 4 (H) + /* 31*/ { 1, -1, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 0, 0, 177, -1 }, // 4296 alphanumerics max for ECC 1 (L) }; - int data_size = sizeof(data) / sizeof(struct item); + int data_size = ARRAY_SIZE(data); struct zint_symbol previous_symbol; @@ -91,16 +91,7 @@ static void test_qr_options(int index, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = BARCODE_QRCODE; - if (data[i].option_1 != -1) { - symbol->option_1 = data[i].option_1; - } - if (data[i].option_2 != -1) { - symbol->option_2 = data[i].option_2; - } - symbol->debug |= debug; - - int length = strlen(data[i].data); + int length = testUtilSetSymbol(symbol, BARCODE_QRCODE, -1 /*input_mode*/, -1 /*eci*/, data[i].option_1, data[i].option_2, -1, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret_encode, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret_encode, symbol->errtxt); @@ -216,7 +207,7 @@ static void test_qr_input(int index, int generate, int debug) { /* 60*/ { UNICODE_MODE, 26, -1, "点", 0, 26, "71 A4 03 E7 82 B9 00 EC 11", "ECI-26 B3 (UTF-8)" }, /* 61*/ { DATA_MODE, 0, -1, "点", 0, 0, "40 3E 78 2B 90 EC 11 EC 11", "B3 (UTF-8)" }, /* 62*/ { DATA_MODE, 0, -1, "\223\137", 0, 0, "40 29 35 F0 EC 11 EC 11 EC", "B2 (Shift JIS) (not full multibyte)" }, - /* 63*/ { DATA_MODE, 0, 200, "\223\137", 0, 0, "80 16 CF 80 EC 11 EC 11 EC", "K1 (Shift JIS)" }, + /* 63*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "\223\137", 0, 0, "80 16 CF 80 EC 11 EC 11 EC", "K1 (Shift JIS)" }, /* 64*/ { UNICODE_MODE, 0, -1, "¥・点", 0, 0, "40 45 CA 59 35 F0 EC 11 EC", "B4 (Shift JIS) (optimized to byte mode only)" }, /* 65*/ { UNICODE_MODE, 3, -1, "¥・点", ZINT_ERROR_INVALID_DATA, -1, "Error 575: Invalid characters in input data", "" }, /* 66*/ { UNICODE_MODE, 20, -1, "¥・点", 0, 20, "71 44 04 5C A5 93 5F 00 EC", "ECI-20 B4 (Shift JIS)" }, @@ -230,20 +221,21 @@ static void test_qr_input(int index, int generate, int debug) { /* 74*/ { UNICODE_MODE, 0, -1, "点茗テ点茗テ", 0, 0, "80 66 CF EA A8 34 AD 9F D5 50 69 40 EC", "K6 (Shift JIS)" }, /* 75*/ { UNICODE_MODE, 0, -1, "点茗テ点茗テソ", 0, 0, "80 66 CF EA A8 34 AD 9F D5 50 69 50 06 FC 00 EC", "K6 B1 (Shift JIS)" }, /* 76*/ { DATA_MODE, 0, -1, "\223\137\344\252\203\145\223\137\344\252\203\145\277", 0, 0, "40 D9 35 FE 4A A8 36 59 35 FE 4A A8 36 5B F0 EC", "B13 (Shift JIS)" }, - /* 77*/ { DATA_MODE, 0, 200, "\223\137\344\252\203\145\223\137\344\252\203\145\277", 0, 0, "80 66 CF EA A8 34 AD 9F D5 50 69 50 06 FC 00 EC", "K6 B1 (Shift JIS) (full multibyte)" }, + /* 77*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "\223\137\344\252\203\145\223\137\344\252\203\145\277", 0, 0, "80 66 CF EA A8 34 AD 9F D5 50 69 50 06 FC 00 EC", "K6 B1 (Shift JIS) (full multibyte)" }, /* 78*/ { DATA_MODE, 0, -1, "点茗テ点茗テソ", 0, 0, "41 5E 78 2B 9E 88 C9 7E 38 38 6E 78 2B 9E 88 C9 7E 38 38 6E FB DB F0 EC 11 EC 11 EC", "B21 (UTF-8)" }, /* 79*/ { DATA_MODE, 0, -1, "ÁȁȁȁȁȁȁȂ¢", 0, 0, "41 2C 38 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 2C 2A 20 EC 11", "B18 (UTF-8)" }, - /* 80*/ { DATA_MODE, 0, 200, "ÁȁȁȁȁȁȁȂ¢", 0, 0, "41 2C 38 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 2C 2A 20 EC 11", "B18 (UTF-8) (full multibyte)" }, + /* 80*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "ÁȁȁȁȁȁȁȂ¢", 0, 0, "41 2C 38 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 2C 2A 20 EC 11", "B18 (UTF-8) (full multibyte)" }, /* 81*/ { DATA_MODE, 0, -1, "ÁȁȁȁȁȁȁȁȂ¢", 0, 0, "41 4C 38 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 1C 88 2C 2A 20", "B20 (UTF-8)" }, - /* 82*/ { DATA_MODE, 0, 200, "ÁȁȁȁȁȁȁȁȂ¢", 0, 0, "40 1C 38 09 04 40 22 01 10 08 80 44 02 20 11 00 88 0A 12 00 D1 00", "B1 K9 B1 (UTF-8) (full multibyte)" }, + /* 82*/ { DATA_MODE, 0, ZINT_FULL_MULTIBYTE, "ÁȁȁȁȁȁȁȁȂ¢", 0, 0, "40 1C 38 09 04 40 22 01 10 08 80 44 02 20 11 00 88 0A 12 00 D1 00", "B1 K9 B1 (UTF-8) (full multibyte)" }, /* 83*/ { UNICODE_MODE, 0, -1, "ÁȁȁȁȁȁȁȂ¢", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 12 C3 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 82 C2 A2 00", "B18 (UTF-8)" }, - /* 84*/ { UNICODE_MODE, 0, 200, "ÁȁȁȁȁȁȁȂ¢", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 12 C3 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 82 C2 A2 00", "B18 (UTF-8)" }, + /* 84*/ { UNICODE_MODE, 0, ZINT_FULL_MULTIBYTE, "ÁȁȁȁȁȁȁȂ¢", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 12 C3 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 82 C2 A2 00", "B18 (UTF-8)" }, /* 85*/ { UNICODE_MODE, 0, -1, "ÁȁȁȁȁȁȁȁȂ¢", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 14 C3 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 81 C8 82 C2 A2 00 EC 11 EC 11", "B20 (UTF-8)" }, - /* 86*/ { UNICODE_MODE, 0, 200, "ÁȁȁȁȁȁȁȁȂ¢", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 01 C3 80 90 44 02 20 11 00 88 04 40 22 01 10 08 80 A1 20 0D 10 00 EC 11 EC 11", "B1 K9 B1 (UTF-8) (full multibyte)" }, + /* 86*/ { UNICODE_MODE, 0, ZINT_FULL_MULTIBYTE, "ÁȁȁȁȁȁȁȁȂ¢", ZINT_WARN_USES_ECI, 26, "Warning 71 A4 01 C3 80 90 44 02 20 11 00 88 04 40 22 01 10 08 80 A1 20 0D 10 00 EC 11 EC 11", "B1 K9 B1 (UTF-8) (full multibyte)" }, /* 87*/ { UNICODE_MODE, 0, -1, "áA", 0, 0, "40 2E 14 10 EC 11 EC 11 EC", "B2 (ISO 8859-1)" }, - /* 88*/ { UNICODE_MODE, 0, 200, "áA", 0, 0, "80 1C 00 80 EC 11 EC 11 EC", "K1 (ISO 8859-1) (full multibyte)" }, + /* 88*/ { UNICODE_MODE, 0, ZINT_FULL_MULTIBYTE, "áA", 0, 0, "80 1C 00 80 EC 11 EC 11 EC", "K1 (ISO 8859-1) (full multibyte)" }, + /* 89*/ { UNICODE_MODE, 0, -1, "A0B1C2D3E4F5G6H7I8J9KLMNOPQRSTUVWXYZ $%*+-./:", 0, 0, "(34) 21 69 C2 3E 08 79 26 27 A5 50 B5 98 23 32 6C 0E 65 FA C5 19 5B 42 6B 2D C1 C3 B9 E7", "A45" }, }; - int data_size = sizeof(data) / sizeof(struct item); + int data_size = ARRAY_SIZE(data); char escaped[1024]; @@ -254,23 +246,17 @@ static void test_qr_input(int index, int generate, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = BARCODE_QRCODE; - symbol->input_mode = data[i].input_mode; - symbol->eci = data[i].eci; - if (data[i].option_3 != -1) { - symbol->option_3 = data[i].option_3; - } - symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - symbol->debug |= debug; + debug |= ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - int length = strlen(data[i].data); + int length = testUtilSetSymbol(symbol, BARCODE_QRCODE, data[i].input_mode, data[i].eci, -1 /*option_1*/, -1, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d\n", i, ret, data[i].ret); if (generate) { - printf(" /*%3d*/ { %s, %d, %d, \"%s\", %s, %d, \"%s\", \"%s\" },\n", - i, testUtilInputModeName(data[i].input_mode), data[i].eci, data[i].option_3, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), + printf(" /*%3d*/ { %s, %d, %s, \"%s\", %s, %d, \"%s\", \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), data[i].eci, testUtilOption3Name(data[i].option_3), + testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), testUtilErrorName(data[i].ret), ret < 5 ? symbol->eci : -1, symbol->errtxt, data[i].comment); } else { if (ret < 5) { @@ -309,7 +295,7 @@ static void test_qr_gs1(int index, int generate, int debug) { /* 8*/ { "[91]A%%%%1234567890123AA%", 0, "52 05 99 63 D1 B5 36 A6 D4 98 40 D1 ED C8 C5 40 C3 20 21 CC DA 80", "A7(11) N13 A3(4)" }, /* 9*/ { "[91]%23%%6789%%%34567%%%%234%%%%%", 0, "(34) 52 17 19 6D A8 17 76 A6 D4 22 A5 C7 6A 6D 4D A8 22 C7 39 61 DA 9B 53 6A 6B 01 17 B5", "A31(46)" }, }; - int data_size = sizeof(data) / sizeof(struct item); + int data_size = ARRAY_SIZE(data); char escaped[1024]; @@ -320,12 +306,9 @@ static void test_qr_gs1(int index, int generate, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = BARCODE_QRCODE; - symbol->input_mode = GS1_MODE; - symbol->debug = ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - symbol->debug |= debug; + debug |= ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - int length = strlen(data[i].data); + int length = testUtilSetSymbol(symbol, BARCODE_QRCODE, GS1_MODE, -1 /*eci*/, -1 /*option_1*/, -1, -1, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d\n", i, ret, data[i].ret); @@ -352,45 +335,45 @@ static void test_qr_optimize(int index, int generate, int debug) { int ret; struct item { int input_mode; - char *data; int option_1; + char *data; int ret; char *expected; char *comment; }; struct item data[] = { - /* 0*/ { UNICODE_MODE, "1", -1, 0, "10 04 40 EC 11 EC 11 EC 11", "N1" }, - /* 1*/ { UNICODE_MODE, "AAA", -1, 0, "20 19 CC 28 00 EC 11 EC 11", "A3" }, - /* 2*/ { UNICODE_MODE, "0123456789", -1, 0, "10 28 0C 56 6A 69 00 EC 11", " N10 (nayuki.io - pure numeric)" }, - /* 3*/ { UNICODE_MODE, "ABCDEF", -1, 0, "20 31 CD 45 2A 14 00 EC 11", "A6 (nayuki.io - pure alphanumeric)" }, - /* 4*/ { UNICODE_MODE, "wxyz", -1, 0, "40 47 77 87 97 A0 EC 11 EC", "B4 (nayuki.io - pure byte)" }, - /* 5*/ { UNICODE_MODE, "「魔法少女まどか☆マギカ」って、 ИАИ desu κα?", 1, 0, "(55) 81 D0 1A C0 09 F8 0A ED 56 B8 57 02 8E 12 90 2C 86 F4 31 A1 8A 01 B0 50 42 88 00 10", "K29 (nayuki.io - pure kanji)" }, - /* 6*/ { UNICODE_MODE, "012345A", -1, 0, "20 38 01 0B A2 E4 A0 EC 11", "A7 (nayuki.io - alpha/numeric)" }, - /* 7*/ { UNICODE_MODE, "0123456A", -1, 0, "10 1C 0C 56 58 80 25 00 EC", "N7 A1 (nayuki.io - alpha/numeric) (note same bits as A8)" }, - /* 8*/ { UNICODE_MODE, "012a", -1, 0, "40 43 03 13 26 10 EC 11 EC", "B4 (nayuki.io - numeric/byte)" }, - /* 9*/ { UNICODE_MODE, "0123a", -1, 0, "10 10 0C 34 01 61 00 EC 11", "N4 B1 (nayuki.io - numeric/byte)" }, - /* 10*/ { UNICODE_MODE, "ABCDEa", -1, 0, "40 64 14 24 34 44 56 10 EC", "B6 (nayuki.io - alphanumeric/byte)" }, - /* 11*/ { UNICODE_MODE, "ABCDEFa", -1, 0, "20 31 CD 45 2A 15 00 58 40", "A6 B1 (nayuki.io - alphanumeric/byte)" }, - /* 12*/ { UNICODE_MODE, "THE SQUARE ROOT OF 2 IS 1.41421356237309504880168872420969807856967187537694807317667973799", 1, 0, "(55) 20 D5 2A 53 54 1A A8 4C DC DF 14 29 EC 47 CA D9 9A 88 05 71 10 59 E3 56 32 5D 45 F0", " A26 N65 (nayuki.io - alpha/numeric)" }, - /* 13*/ { UNICODE_MODE, "Golden ratio φ = 1.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374......", 1, 0, "(80) 41 44 76 F6 C6 46 56 E2 07 26 17 46 96 F2 08 3D 32 03 D2 03 12 E1 19 26 A0 87 DC BB", "B20 N100 A6 (nayuki.io - alpha/numeric/byte)" }, - /* 14*/ { UNICODE_MODE, "こんにちwa、世界! αβγδ", 1, 0, "(34) 41 B8 2B 18 2F 18 2C 98 2B F7 76 18 14 19 0A 28 A4 58 14 92 08 3B F8 3C 08 3C 18 3C", "B27 (nayuki.io - kanji/european **NOT SAME** K4 B2 K4 A1 K4, less bits as nayuki (1.5.0) miscounting byte-mode input as UTF-8)" }, - /* 15*/ { UNICODE_MODE, "こんにちテwa、世界! αβγδ", 1, 0, "(34) 80 50 98 85 C4 29 21 3F 0D 2A 09 BB B0 C0 A0 C8 51 45 22 C0 A4 90 41 DF C1 E0 41 E0", "K5 B19 (nayuki.io - kanji/european + extra leading kanji **NOT SAME** K5 B2 K4 A1 K4, same reason as above)" }, - /* 16*/ { UNICODE_MODE, "67128177921547861663com.acme35584af52fa3-88d0-093b-6c14-b37ddafb59c528908608sg.com.dash.www0530329356521790265903SG.COM.NETS46968696003522G33250183309051017567088693441243693268766948304B2AE13344004SG.SGQR209710339366720B439682.63667470805057501195235502733744600368027857918629797829126902859SG8236HELLO FOO2517Singapore3272B815", 1, 0, "(232) 10 52 9F 46 70 B3 5D DE 9A 1F A1 7B 1B 7B 69 73 0B 1B 6B 29 99 A9 A9 C1 A3 0B 31 A9", "N20 B47 N9 B15 N22 A11 N14 A1 N47 A19 N15 A8 N65 A20 B8 A8 (nayuki.io - SGQR alpha/numeric/byte)" }, - /* 17*/ { UNICODE_MODE, "纪", -1, ZINT_WARN_USES_ECI, "Warning 71 A4 03 E7 BA AA 00 EC 11", "ECI-26 B3 (UTF-8 E7BAAA, U+7EAA, not in Shift JIS)" }, - /* 18*/ { DATA_MODE, "纪", -1, 0, "40 3E 7B AA A0 EC 11 EC 11", "B3 (UTF-8 or Shift JIS, note ambiguous as 0xE7BA 0xAA happens to be valid Shift JIS 郤ェ as well)" }, - /* 19*/ { UNICODE_MODE, "郤ェ", -1, 0, "40 3E 7B AA A0 EC 11 EC 11", "B3 (Shift JIS or UTF-8 E7BAAA 纪, see above)" }, - /* 20*/ { UNICODE_MODE, "2004年大西洋颶風季是有纪录以来造成人员伤亡和财产损失最为惨重的大西洋飓风季之一,于2004年6月1日正式开始,同年11月30日结束,传统上这样的日期界定了一年中绝大多数热带气旋在大西洋形成的时间段lll ku", 1, ZINT_WARN_USES_ECI, "Warning (324) 71 A1 00 43 21 10 04 4B 96 E6 D3 96 92 9F A2 96 FF 9A D2 2F A6 8A DB A6 8A A3 96 B6", "ECI-26 N4 B274 (nayuki.io - kanji/byte/numeric **NOT SAME* N4 K9 B6 K5 etc mixing Shift JIS and UTF-8)" }, - /* 21*/ { UNICODE_MODE, "AB123456A", -1, 0, "20 49 CD 05 E2 2C 73 94 00", "A9" }, - /* 22*/ { UNICODE_MODE, "AB1234567890A", -1, 0, "20 69 CD 05 E2 2C 73 94 33 2A 50 00 EC", "A13" }, - /* 23*/ { UNICODE_MODE, "AB123456789012A", -1, 0, "20 79 CD 05 E2 2C 73 94 33 2A 0B CA 00", "A15" }, - /* 24*/ { UNICODE_MODE, "AB1234567890123A", -1, 0, "20 11 CD 10 34 7B 72 31 50 30 C8 02 50", "A2 N13 A1" }, - /* 25*/ { UNICODE_MODE, "テaABCD1", -1, 0, "40 88 36 56 14 14 24 34 43 10 EC 11 EC", "B8" }, - /* 26*/ { UNICODE_MODE, "テaABCDE1", -1, 0, "40 38 36 56 12 03 1C D4 52 9D C0 EC 11", "B3 A6" }, - /* 27*/ { UNICODE_MODE, "テéaABCDE1", -1, ZINT_WARN_USES_ECI, "Warning 71 A4 06 E3 83 86 C3 A9 61 20 31 CD 45 29 DC 00", "B6 A6" }, - /* 28*/ { UNICODE_MODE, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", -1, 0, "(44) 80 83 A8 85 88 25 CA 2F 40 B0 53 C2 44 98 41 00 4A 02 0E A8 F8 F5 0D 30 4C 35 A1 CC", "K8 N1 K8 B3" }, - /* 29*/ { UNICODE_MODE, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。社ト可化モマ試音ばじご育青康演ぴぎ権型固スで能麩ぜらもほ河都しちほラ収90作の年要とだむ部動ま者断チ第41一1米索焦茂げむしれ。測フ物使だて目月国スリカハ夏検にいへ児72告物ゆは載核ロアメヱ登輸どべゃ催行アフエハ議歌ワ河倫剖だ。記タケウ因載ヒイホヤ禁3輩彦関トえび肝区勝ワリロ成禁ぼよ界白ウヒキレ中島べせぜい各安うしぽリ覧生テ基一でむしゃ中新トヒキソ声碁スしび起田ア信大未ゅもばち。", -1, 0, "(589) 80 20 EA 21 62 09 72 8B D0 2C 14 F0 91 26 10 40 04 A0 08 3A A3 E3 D4 34 C1 30 D6 87", "K8 N1 K8 N1 K10 N2 K33 N2 K16 N1 K89 N2 K14 B5 K28 N2 K40 N1 K65" }, + /* 0*/ { UNICODE_MODE, -1, "1", 0, "10 04 40 EC 11 EC 11 EC 11", "N1" }, + /* 1*/ { UNICODE_MODE, -1, "AAA", 0, "20 19 CC 28 00 EC 11 EC 11", "A3" }, + /* 2*/ { UNICODE_MODE, -1, "0123456789", 0, "10 28 0C 56 6A 69 00 EC 11", " N10 (nayuki.io - pure numeric)" }, + /* 3*/ { UNICODE_MODE, -1, "ABCDEF", 0, "20 31 CD 45 2A 14 00 EC 11", "A6 (nayuki.io - pure alphanumeric)" }, + /* 4*/ { UNICODE_MODE, -1, "wxyz", 0, "40 47 77 87 97 A0 EC 11 EC", "B4 (nayuki.io - pure byte)" }, + /* 5*/ { UNICODE_MODE, 1, "「魔法少女まどか☆マギカ」って、 ИАИ desu κα?", 0, "(55) 81 D0 1A C0 09 F8 0A ED 56 B8 57 02 8E 12 90 2C 86 F4 31 A1 8A 01 B0 50 42 88 00 10", "K29 (nayuki.io - pure kanji)" }, + /* 6*/ { UNICODE_MODE, -1, "012345A", 0, "20 38 01 0B A2 E4 A0 EC 11", "A7 (nayuki.io - alpha/numeric)" }, + /* 7*/ { UNICODE_MODE, -1, "0123456A", 0, "10 1C 0C 56 58 80 25 00 EC", "N7 A1 (nayuki.io - alpha/numeric) (note same bits as A8)" }, + /* 8*/ { UNICODE_MODE, -1, "012a", 0, "40 43 03 13 26 10 EC 11 EC", "B4 (nayuki.io - numeric/byte)" }, + /* 9*/ { UNICODE_MODE, -1, "0123a", 0, "10 10 0C 34 01 61 00 EC 11", "N4 B1 (nayuki.io - numeric/byte)" }, + /* 10*/ { UNICODE_MODE, -1, "ABCDEa", 0, "40 64 14 24 34 44 56 10 EC", "B6 (nayuki.io - alphanumeric/byte)" }, + /* 11*/ { UNICODE_MODE, -1, "ABCDEFa", 0, "20 31 CD 45 2A 15 00 58 40", "A6 B1 (nayuki.io - alphanumeric/byte)" }, + /* 12*/ { UNICODE_MODE, 1, "THE SQUARE ROOT OF 2 IS 1.41421356237309504880168872420969807856967187537694807317667973799", 0, "(55) 20 D5 2A 53 54 1A A8 4C DC DF 14 29 EC 47 CA D9 9A 88 05 71 10 59 E3 56 32 5D 45 F0", " A26 N65 (nayuki.io - alpha/numeric)" }, + /* 13*/ { UNICODE_MODE, 1, "Golden ratio φ = 1.6180339887498948482045868343656381177203091798057628621354486227052604628189024497072072041893911374......", 0, "(80) 41 44 76 F6 C6 46 56 E2 07 26 17 46 96 F2 08 3D 32 03 D2 03 12 E1 19 26 A0 87 DC BB", "B20 N100 A6 (nayuki.io - alpha/numeric/byte)" }, + /* 14*/ { UNICODE_MODE, 1, "こんにちwa、世界! αβγδ", 0, "(34) 41 B8 2B 18 2F 18 2C 98 2B F7 76 18 14 19 0A 28 A4 58 14 92 08 3B F8 3C 08 3C 18 3C", "B27 (nayuki.io - kanji/european **NOT SAME** K4 B2 K4 A1 K4, less bits as nayuki (1.5.0) miscounting byte-mode input as UTF-8)" }, + /* 15*/ { UNICODE_MODE, 1, "こんにちテwa、世界! αβγδ", 0, "(34) 80 50 98 85 C4 29 21 3F 0D 2A 09 BB B0 C0 A0 C8 51 45 22 C0 A4 90 41 DF C1 E0 41 E0", "K5 B19 (nayuki.io - kanji/european + extra leading kanji **NOT SAME** K5 B2 K4 A1 K4, same reason as above)" }, + /* 16*/ { UNICODE_MODE, 1, "67128177921547861663com.acme35584af52fa3-88d0-093b-6c14-b37ddafb59c528908608sg.com.dash.www0530329356521790265903SG.COM.NETS46968696003522G33250183309051017567088693441243693268766948304B2AE13344004SG.SGQR209710339366720B439682.63667470805057501195235502733744600368027857918629797829126902859SG8236HELLO FOO2517Singapore3272B815", 0, "(232) 10 52 9F 46 70 B3 5D DE 9A 1F A1 7B 1B 7B 69 73 0B 1B 6B 29 99 A9 A9 C1 A3 0B 31 A9", "N20 B47 N9 B15 N22 A11 N14 A1 N47 A19 N15 A8 N65 A20 B8 A8 (nayuki.io - SGQR alpha/numeric/byte)" }, + /* 17*/ { UNICODE_MODE, -1, "纪", ZINT_WARN_USES_ECI, "Warning 71 A4 03 E7 BA AA 00 EC 11", "ECI-26 B3 (UTF-8 E7BAAA, U+7EAA, not in Shift JIS)" }, + /* 18*/ { DATA_MODE, -1, "纪", 0, "40 3E 7B AA A0 EC 11 EC 11", "B3 (UTF-8 or Shift JIS, note ambiguous as 0xE7BA 0xAA happens to be valid Shift JIS 郤ェ as well)" }, + /* 19*/ { UNICODE_MODE, -1, "郤ェ", 0, "40 3E 7B AA A0 EC 11 EC 11", "B3 (Shift JIS or UTF-8 E7BAAA 纪, see above)" }, + /* 20*/ { UNICODE_MODE, 1, "2004年大西洋颶風季是有纪录以来造成人员伤亡和财产损失最为惨重的大西洋飓风季之一,于2004年6月1日正式开始,同年11月30日结束,传统上这样的日期界定了一年中绝大多数热带气旋在大西洋形成的时间段lll ku", ZINT_WARN_USES_ECI, "Warning (324) 71 A1 00 43 21 10 04 4B 96 E6 D3 96 92 9F A2 96 FF 9A D2 2F A6 8A DB A6 8A A3 96 B6", "ECI-26 N4 B274 (nayuki.io - kanji/byte/numeric **NOT SAME* N4 K9 B6 K5 etc mixing Shift JIS and UTF-8)" }, + /* 21*/ { UNICODE_MODE, -1, "AB123456A", 0, "20 49 CD 05 E2 2C 73 94 00", "A9" }, + /* 22*/ { UNICODE_MODE, -1, "AB1234567890A", 0, "20 69 CD 05 E2 2C 73 94 33 2A 50 00 EC", "A13" }, + /* 23*/ { UNICODE_MODE, -1, "AB123456789012A", 0, "20 79 CD 05 E2 2C 73 94 33 2A 0B CA 00", "A15" }, + /* 24*/ { UNICODE_MODE, -1, "AB1234567890123A", 0, "20 11 CD 10 34 7B 72 31 50 30 C8 02 50", "A2 N13 A1" }, + /* 25*/ { UNICODE_MODE, -1, "テaABCD1", 0, "40 88 36 56 14 14 24 34 43 10 EC 11 EC", "B8" }, + /* 26*/ { UNICODE_MODE, -1, "テaABCDE1", 0, "40 38 36 56 12 03 1C D4 52 9D C0 EC 11", "B3 A6" }, + /* 27*/ { UNICODE_MODE, -1, "テéaABCDE1", ZINT_WARN_USES_ECI, "Warning 71 A4 06 E3 83 86 C3 A9 61 20 31 CD 45 29 DC 00", "B6 A6" }, + /* 28*/ { UNICODE_MODE, -1, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁", 0, "(44) 80 83 A8 85 88 25 CA 2F 40 B0 53 C2 44 98 41 00 4A 02 0E A8 F8 F5 0D 30 4C 35 A1 CC", "K8 N1 K8 B3" }, + /* 29*/ { UNICODE_MODE, -1, "貫やぐ識禁ぱい再2間変字全ノレ没無8裁花ほゃ過法ひなご札17能つーびれ投覧マ勝動エヨ額界よみ作皇ナヲニ打題ヌルヲ掲布益フが。入35能ト権話しこを断兆モヘ細情おじ名4減エヘイハ側機はょが意見想ハ業独案ユヲウ患職ヲ平美さ毎放どぽたけ家没べお化富べ町大シ情魚ッでれ一冬すぼめり。社ト可化モマ試音ばじご育青康演ぴぎ権型固スで能麩ぜらもほ河都しちほラ収90作の年要とだむ部動ま者断チ第41一1米索焦茂げむしれ。測フ物使だて目月国スリカハ夏検にいへ児72告物ゆは載核ロアメヱ登輸どべゃ催行アフエハ議歌ワ河倫剖だ。記タケウ因載ヒイホヤ禁3輩彦関トえび肝区勝ワリロ成禁ぼよ界白ウヒキレ中島べせぜい各安うしぽリ覧生テ基一でむしゃ中新トヒキソ声碁スしび起田ア信大未ゅもばち。", 0, "(589) 80 20 EA 21 62 09 72 8B D0 2C 14 F0 91 26 10 40 04 A0 08 3A A3 E3 D4 34 C1 30 D6 87", "K8 N1 K8 N1 K10 N2 K33 N2 K16 N1 K89 N2 K14 B5 K28 N2 K40 N1 K65" }, }; - int data_size = sizeof(data) / sizeof(struct item); + int data_size = ARRAY_SIZE(data); char escaped[1024]; @@ -401,23 +384,16 @@ static void test_qr_optimize(int index, int generate, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = BARCODE_QRCODE; - symbol->input_mode = data[i].input_mode; - if (data[i].option_1 != -1) { - symbol->option_1 = data[i].option_1; - } - symbol->option_3 = ZINT_FULL_MULTIBYTE; - symbol->debug = ZINT_DEBUG_TEST; - symbol->debug |= debug; + debug |= ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - int length = strlen(data[i].data); + int length = testUtilSetSymbol(symbol, BARCODE_QRCODE, data[i].input_mode, -1 /*eci*/, data[i].option_1, -1, ZINT_FULL_MULTIBYTE, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d\n", i, ret, data[i].ret); if (generate) { - printf(" /*%3d*/ { %s, \"%s\", %d, %s, \"%s\", \"%s\" },\n", - i, testUtilInputModeName(data[i].input_mode), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].option_1, + printf(" /*%3d*/ { %s, %d, \"%s\", %s, \"%s\", \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), data[i].option_1, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), testUtilErrorName(data[i].ret), symbol->errtxt, data[i].comment); } else { assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); @@ -435,10 +411,12 @@ static void test_qr_encode(int index, int generate, int debug) { int ret; struct item { + int symbology; int input_mode; - char *data; int option_1; int option_2; + int option_3; + char *data; int ret; int expected_rows; @@ -447,166 +425,401 @@ static void test_qr_encode(int index, int generate, int debug) { char *expected; }; struct item data[] = { - /* 0*/ { UNICODE_MODE, "01234567", 2, 1, 0, 21, 21, "ISO 18004 Annex I I.2 **NOT SAME** uses mask 000 not 010; if force to use 010, same", - "111111100011101111111" - "100000101110001000001" - "101110100110001011101" - "101110100101101011101" - "101110101101101011101" - "100000100001001000001" + /* 0*/ { BARCODE_QRCODE, UNICODE_MODE, -1, -1, -1, "QR Code Symbol", 0, 21, 21, "ISO 18004 Figure 1 **NOT SAME** uses mask 110 instead of 101", + "111111101001101111111" + "100000101001101000001" + "101110101100101011101" + "101110100010001011101" + "101110101001101011101" + "100000100001101000001" "111111101010101111111" - "000000000000000000000" - "101010100010100010010" - "110100001011010100010" - "000110111011011101110" - "110011010101110110010" - "001001110111011100001" - "000000001010001000010" - "111111100000100010001" - "100000100010001001011" + "000000000100100000000" + "100111111101010010111" + "100010001110001000111" + "010100110000101101011" + "110111001000010111110" + "011111111110001011011" + "000000001000011010101" + "111111101101101010100" + "100000101010011011100" + "101110101001110001110" + "101110101111001001100" + "101110100100101010011" + "100000100001101111111" + "111111101001011000000" + }, + /* 1*/ { BARCODE_QRCODE, UNICODE_MODE, -1, -1, 6 << 8, "QR Code Symbol", 0, 21, 21, "ISO 18004 Figure 1, explicit mask 101, same", + "111111100001101111111" + "100000101001101000001" "101110101110101011101" - "101110100101010101110" - "101110101101011100101" - "100000100001110111000" - "111111101001011100101" - }, - /* 1*/ { GS1_MODE, "[01]09501101530003[8200]http://example.com", -1, -1, 0, 25, 25, "GS1 General Specifications 20.0 Figure 5.1-7 **NOT SAME** TODO: investigate", - "1111111001101101001111111" - "1000001000110001101000001" - "1011101011101000101011101" - "1011101001100000101011101" - "1011101000110111001011101" - "1000001001011001101000001" - "1111111010101010101111111" - "0000000011100011000000000" - "1110111110110000011000100" - "0100110000101101111100111" - "0111101101000111001011110" - "0010110100000111010101111" - "1110001000010010100010100" - "0010110001010001000110010" - "1001011110000111001100001" - "0100110011000110001010110" - "1011001000000100111110001" - "0000000010001001100011000" - "1111111010000111101010011" - "1000001010110011100010010" - "1011101011011011111110001" - "1011101000100100100000000" - "1011101010100110101110101" - "1000001010100111110101000" - "1111111011101100010010111" - }, - /* 2*/ { UNICODE_MODE, "12345678901234567890123456789012345678901", -1, -1, 0, 21, 21, "Max capacity ECC 1 Version 1 41 numbers", - "111111100011001111111" - "100000100001001000001" - "101110101110001011101" - "101110100001001011101" - "101110100011001011101" - "100000100100001000001" + "101110101010001011101" + "101110100000101011101" + "100000100010101000001" "111111101010101111111" "000000001100100000000" - "111011111000011000100" - "111000000110111000001" - "001001111011110001000" - "001110011011011111001" - "001100101000001000011" - "000000001101100001010" - "111111101011011001011" - "100000101100010001011" - "101110101101010111100" - "101110100000111000010" - "101110101001100011101" - "100000101010111011000" - "111111101000100010101" - }, - /* 3*/ { UNICODE_MODE, "12345678901234567890123456789012345678901", 2, -1, 0, 25, 25, "ECC 2 auto-sets version 2", - "1111111010111111001111111" - "1000001001001110001000001" - "1011101001000001101011101" - "1011101010010001001011101" - "1011101010011010101011101" - "1000001010110000101000001" + "100000101111011001110" + "100010001110001000111" + "011101111001100100010" + "110100001011010100110" + "011111111110001011011" + "000000001000000010110" + "111111100111111000110" + "100000100010011011100" + "101110100000111000111" + "101110100100001010100" + "101110100100101010011" + "100000100001110111100" + "111111101011001010010" + }, + /* 2*/ { BARCODE_QRCODE, UNICODE_MODE, 2, -1, -1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0, 33, 33, "ISO 18004 Figure 29, same (mask 100)", + "111111101100110010010010101111111" + "100000100010111010111000101000001" + "101110100000001101101100001011101" + "101110101010000111000110001011101" + "101110101101100011010010001011101" + "100000101100010100001101101000001" + "111111101010101010101010101111111" + "000000001010000000011100100000000" + "100010111100001100100011011111001" + "100101000111001001000110000101100" + "010001100011111010101000011011001" + "101101011101010010000010010000000" + "001111110011010110010011101001100" + "011001000101001000111100110101001" + "101001111001111101001111000110111" + "100100010001000111100101111100000" + "110010111101110000011110111111100" + "010000010111100010001000010000111" + "111111111111010101000110010001111" + "001100010000000111100101010101110" + "111101111011101000111001010010001" + "100110000101001010010111000100001" + "000110111110111010010001011001000" + "001011010011101000011111011101111" + "111011111000010111001001111110000" + "000000001110110011111100100010100" + "111111101000110100101000101010011" + "100000100001010010001011100010000" + "101110101111011010000010111111100" + "101110100000111000111100000000101" + "101110100101010100001000010110100" + "100000100010110111000110101001001" + "111111101101101011010000111100011" + }, + /* 3*/ { BARCODE_QRCODE, UNICODE_MODE, 2, 1, -1, "01234567", 0, 21, 21, "ISO 18004 Annex I I.2, same (mask 010)", + "111111100101101111111" + "100000100111101000001" + "101110101000001011101" + "101110101100001011101" + "101110101011101011101" + "100000101000101000001" + "111111101010101111111" + "000000001001100000000" + "101111100100101111100" + "000101011010100101100" + "001000110101010011111" + "000010000100000111100" + "000111111001010010000" + "000000001011111001100" + "111111100110101100000" + "100000101011111000101" + "101110101000100101100" + "101110101100100100000" + "101110101011010010100" + "100000100000000110110" + "111111101111010010100" + }, + /* 4*/ { BARCODE_QRCODE, GS1_MODE, 1, -1, -1, "[01]09501101530003[8200]http://example.com", 0, 25, 25, "GS1 General Specifications 20.0 Figure 5.1-7 **NOT SAME** figure uses Byte encodation only", + "1111111001101101001111111" + "1000001010010101001000001" + "1011101011111010101011101" + "1011101001100000101011101" + "1011101010010011101011101" + "1000001011001011101000001" "1111111010101010101111111" - "0000000010001101100000000" - "1000101111110100111111001" - "1001010011110111010110000" - "1100011011001001111100010" - "1000100101101010111101101" - "1001011100010110100111011" - "1111010110101001100101010" - "0001101010011111010110111" - "0001010000110100101011101" - "1100111100101101111110011" - "0000000011000111100010001" - "1111111010100000101010000" - "1000001001001010100011111" - "1011101011010110111111000" - "1011101001101000011011001" - "1011101001111111001010110" - "1000001001110101001011000" - "1111111011101101111101001" - }, - /* 4*/ { UNICODE_MODE, "点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点", 4, 10, 0, 57, 57, "Max capacity ECC 4 Version 10 74 kanji", - "111111101100111011000010011000100111001001000011001111111" - "100000101111111001101100110100110101110011011101001000001" - "101110101011001110000011101100101110111011110011001011101" - "101110100011001100100010101101000000100111001001001011101" - "101110100010101101010001101111101111111001010101001011101" - "100000101111100000011000101000111010111011111110001000001" + "0000000011000111100000000" + "1101001100100010001110110" + "0100110000101101111100111" + "0011001001100011101111010" + "0000100110010101000111101" + "1110001000010010100010100" + "0110010101110101100010110" + "1011001100010101011110011" + "0100110011000110001010110" + "1111101100100000111110101" + "0000000010011011100011010" + "1111111010000111101010011" + "1000001000010111100010110" + "1011101001001001111110011" + "1011101010100100100000000" + "1011101000000010001010001" + "1000001010110101100111010" + "1111111011101100010010111" + }, + /* 5*/ { BARCODE_QRCODE, GS1_MODE, 2, -1, -1, "[01]00857674002010[8200]http://www.gs1.org/", 0, 29, 29, "GS1 General Specifications 20.0 Figure 5.1-7, same (mask 011)", + "11111110100101110101001111111" + "10000010111101001000001000001" + "10111010010000001110001011101" + "10111010101110110010101011101" + "10111010001010101011001011101" + "10000010011111011001101000001" + "11111110101010101010101111111" + "00000000110110011010100000000" + "10110111001001010000101001011" + "00100000101101110111011001111" + "11000110001011001101000011010" + "11010101110110001010010000111" + "11100111011100110101111011100" + "01001000100100101111101001110" + "10001011100111011100101111101" + "01000001011110101001001001011" + "10010010010100111011001000101" + "00000101101000101110001011001" + "10001111110011111111110010010" + "00111100001011100011110101000" + "01001110111001101000111111001" + "00000000100000011001100010100" + "11111110111110110001101011110" + "10000010110111110010100011001" + "10111010010010000110111111010" + "10111010100111000011111111110" + "10111010101000101001111001001" + "10000010010111010001110010100" + "11111110101111111011110100110" + }, + /* 6*/ { BARCODE_HIBC_QR, -1, 2, -1, -1, "H123ABC01234567890", 0, 21, 21, "ANSI/HIBC 2.6 - 2016 Figure C5 same (mask 001)", + "111111101010001111111" + "100000100100101000001" + "101110101011001011101" + "101110100010101011101" + "101110100001101011101" + "100000101110001000001" + "111111101010101111111" + "000000000110100000000" + "101000110001000100101" + "000110001111001000010" + "000101100101100111110" + "011100001100001101010" + "000101101111110110111" + "000000001011000001111" + "111111101111110111001" + "100000100101111000001" + "101110100010110101010" + "101110100111010101000" + "101110101101011001111" + "100000100100101111001" + "111111101111011001111" + }, + /* 7*/ { BARCODE_HIBC_QR, -1, 2, -1, -1, "/EU720060FF0/O523201", 0, 25, 25, "HIBC/PAS Section 2.2 2nd Purchase Order **NOT SAME** uses mask 100 instead of 011", + "1111111011011110101111111" + "1000001001001111001000001" + "1011101001010010001011101" + "1011101010000000101011101" + "1011101010011000001011101" + "1000001010010000001000001" + "1111111010101010101111111" + "0000000010101101100000000" + "1000101111010100011111001" + "1001110011101110100100100" + "1010111101000001001001110" + "0011010010110010111000100" + "1100011110000110101110011" + "1000100000101000011011110" + "0011111100111111101010010" + "0001100110010101011100101" + "1111101011001100111110001" + "0000000011000111100010010" + "1111111010000000101011100" + "1000001001101011100011101" + "1011101011110111111110000" + "1011101000101000000010001" + "1011101000111111110100110" + "1000001000010100100011111" + "1111111010101101111000001" + }, + /* 8*/ { BARCODE_HIBC_QR, -1, 2, -1, 4 << 8, "/EU720060FF0/O523201", 0, 25, 25, "HIBC/PAS Section 2.2 2nd Purchase Order same, explicit mask 011", + "1111111010011001101111111" + "1000001011010011001000001" + "1011101000000111001011101" + "1011101010111000001011101" + "1011101000000100001011101" + "1000001000111010101000001" + "1111111010101010101111111" + "0000000011001110000000000" + "1011011101111110101001011" + "1110110100101001100011100" + "1001011110100010101010010" + "0110000111100111101101110" + "1011011001000001101001011" + "0100110100110100000111101" + "0110101001101010111111000" + "1001010110101101100100010" + "0011111111010000111110010" + "0000000011101101100010111" + "1111111010111000101011011" + "1000001010001000100010001" + "1011101001011101111110101" + "1011101011101111000101001" + "1011101011011100010111010" + "1000001001000001110110101" + "1111111011101010111111001" + }, + /* 9*/ { BARCODE_HIBC_QR, -1, 2, -1, -1, "/KN12345", 0, 21, 21, "HIBC/PAS Section 2.2 Asset Tag **NOT SAME** uses mask 000 instead of 100", + "111111100000101111111" + "100000101010101000001" + "101110100011001011101" + "101110100001101011101" + "101110101110101011101" + "100000100010101000001" + "111111101010101111111" + "000000000111100000000" + "101010100011000010010" + "111010010000001100001" + "111010101110100011001" + "011000011010001011001" + "100001110010101001001" + "000000001001010110001" + "111111100001011100011" + "100000100101110101000" + "101110101001011000111" + "101110100010001001110" + "101110101100100111001" + "100000100100001100111" + "111111101000101110101" + }, + /* 10*/ { BARCODE_HIBC_QR, -1, 2, -1, 5 << 8, "/KN12345", 0, 21, 21, "HIBC/PAS Section 2.2 Asset Tag, same, explicit mask 100", + "111111101010101111111" + "100000100111001000001" + "101110100110101011101" + "101110101011101011101" + "101110101100101011101" + "100000101111001000001" + "111111101010101111111" + "000000001101100000000" + "100010111001011111001" + "010111011101100001100" + "010111100011001110100" + "001010001000011001011" + "110011100000111011011" + "000000001100111011100" + "111111101100110001110" + "100000100111100111010" + "101110101011001010101" + "101110100111100100011" + "101110100001001010100" + "100000100110011110101" + "111111101010111100111" + }, + /* 11*/ { BARCODE_QRCODE, UNICODE_MODE, -1, -1, -1, "12345678901234567890123456789012345678901", 0, 21, 21, "Max capacity ECC 1 Version 1 41 numbers", + "111111101001001111111" + "100000101100101000001" + "101110101011101011101" + "101110101011001011101" + "101110100001001011101" + "100000101001101000001" + "111111101010101111111" + "000000000110100000000" + "110011100010000101111" + "010101001011010101100" + "100100110110011100101" + "011100001001001101011" + "011110111010011010001" + "000000001000001100111" + "111111100110110100110" + "100000101110000011001" + "101110101111000101110" + "101110100101010101111" + "101110100100001110000" + "100000101000101001010" + "111111101010110000111" + }, + /* 12*/ { BARCODE_QRCODE, UNICODE_MODE, 2, -1, -1, "12345678901234567890123456789012345678901", 0, 25, 25, "ECC 2 auto-sets version 2", + "1111111011001110101111111" + "1000001001000000001000001" + "1011101011001111101011101" + "1011101001100000101011101" + "1011101001101011001011101" + "1000001010111110101000001" + "1111111010101010101111111" + "0000000001111100000000000" + "1010001100000101000100101" + "0111010101111001011000001" + "0010011101000111110010011" + "1001010100011011001100011" + "1000101101100111010110101" + "0001010000100111101011011" + "1111101100010001011000110" + "0000100001000101011010011" + "1101001101011100111111101" + "0000000011001001100010000" + "1111111010101110101010001" + "1000001000111011100010001" + "1011101000100111111110110" + "1011101001100110010101000" + "1011101011110001000100111" + "1000001000000100111010110" + "1111111010011100001100111" + }, + /* 13*/ { BARCODE_QRCODE, UNICODE_MODE, 4, 10, -1, "点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点", 0, 57, 57, "Max capacity ECC 4 Version 10 74 kanji", + "111111100111100000011001000011111100010010011011001111111" + "100000100011100101110000101000101001101111000001001000001" + "101110101001011100010001111110111100101001100011001011101" + "101110101101000010101100100011001110101001000101001011101" + "101110100011100100011000101111100110110000011101001011101" + "100000100000100111011111101000111101111100111010001000001" "111111101010101010101010101010101010101010101010101111111" - "000000001101101001101010111000101011001011001011100000000" - "001110101001110001011101101111101000011110010001111100111" - "111000010100110111100000110100100100100011011111001010111" - "010101110001111101010100011111010101011011111010011011010" - "001100001100010011000100001010100000010011111001011011001" - "010011110000011110101000101010110010011010001111110010010" - "100111011011110001111001011000011100011001010001001001000" - "101000110100110100001111010110101111110110111011011111011" - "110010000010100100010011000001111100011011111101111101101" - "010110101010000000001010001010110110001100001011010010010" - "000100010110111010111001111111000100111011111011001110010" - "010101110011111000011101111110000001110111011110110001011" - "111011001011101111000111000010000011010110111011011011101" - "110100111001000100101110001110000110001001011011100100011" - "010000001001000100111101101010111010111011010000011011010" - "001010101100100110101110001110011101100110001111111110001" - "110000000010010101100110110001100001010001011111010111001" - "110111100101101010101111111110110010001010100011011001100" - "011000011000011010000010011010000110010011011000011010011" - "000011111001011000101110011111111001011001001111111111000" - "010110001010110111111010101000101101000111001110100010111" - "101110101000111000001101111010100010011001010011101011001" - "100110001011111111011001011000111100011011111101100010011" - "000111111010000101100111001111110111101010001011111111111" - "111010011010000011111011100111010110011110001111110111000" - "001011110011010001011000011101011000011011010001011111011" - "010001000000011001100100110111111010110011111011001001010" - "100100101101111101000110100000110000101100011011011011001" - "101000000010101010110110100000100100101010001011010010010" - "111011101011000000100001011101000111011001011010111111011" - "010111001001001010011100011010011101010110111111011011011" - "011001110100111111110110001110110110001001000010001011101" - "000100001111101001101110110100101011111100010101011100010" - "111101100111011000111001110100100110001011101011010011011" - "011100000010100110111111110001110111011111010010101001011" - "011100101000100110110101100111010010110001011111011111101" - "110000010000001100000001000111010111010001011011100000011" - "010001110100100101000001111101001111011011010000010101111" - "111110010100001100001111110010110111011110001111101011011" - "101001111101101110110110011000100011010011010011110110111" - "111110001011001011010011001100110100001001000011011001010" - "000000101000111000011000101111100011010011111000111111001" - "000000001100010001110100111000110000011010001111100011111" - "111111100011101101000011011010110100011001010001101011000" - "100000100001001011111100001000111010110011010010100011011" - "101110101110111101110110011111101000110011111101111111101" - "101110101110110100011011111000011110000100001010000000010" - "101110101101001111001011110010011001011011111011111011100" - "100000100010000001101111010001101010110110010001011111000" - "111111100000011111000100011011010011011001011011001011001" - }, - /* 5*/ { UNICODE_MODE, "点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点", 4, 27, 0, 125, 125, "Max capacity ECC 4 Version 27 385 kanji", + "000000000001110101110110101000110111010111010111100000000" + "000110110011100011001111111111111010001100000011100001100" + "110110011010111001101110111010101010101101010001000100110" + "011100111000110100011101010110011100010010110011010010011" + "001011001011010100000011001101100111010100111110011100001" + "001000101011000101110011110001101001000001010100101001001" + "111011000111101101100101000100000000000101001101010101011" + "111010100110100110011101000100111101100100101001001101001" + "111100001100101010011101001111110010010101110011110011100" + "011111100011001001000011000011111111000101000010011011011" + "000011010001111101111110111000000011111100111100001001010" + "001110101000100011000110100101011010101100000101101010000" + "100111010111110011011011011110011111001010100111000111110" + "100110101011010110111100011100010100011011001001110110001" + "011110000111001010110011100100110100110101011110010101011" + "000011100101101111100111000111010100101111000110110111000" + "110111000101010010100001110110100110010110011000010000001" + "101100111110110001110100100101101001010001111000000010111" + "000100000100000110011110000110011010001111000100000110000" + "010011111011001010111100001111101011001011011101111111010" + "011010001100111001110100101000100011001001000000100010110" + "100110101001110001000100111010101011010000011010101010000" + "100010001100111000011110011000111011011100111010100011011" + "011111111001011110111100011111101100110001010000111110100" + "100110000110011111100111111011001010000010010011101011011" + "011001100001000011001010001111001010001001000011001101001" + "011111001110010111101010111001110100111101110101000111011" + "101101100100110100001111101001111001100101010010010010000" + "101111000101101101110001100111100011101101001100010101010" + "100000110000011011111010000110011100000010000001100100000" + "001011010101010110000000000110000001001010100011000111000" + "001011100110101101100100011100100100011011010000011001111" + "001010000001100111100000111010100101110010011011010010011" + "110100101110010001110000111101101111000010100010011010010" + "011011000101100001111000110110110000011000010101101110011" + "000111110011111101101110111100001001101010000100000100110" + "101100001100010000011101011011001011001101000111111100000" + "000011100110110111010011101111011101001001000010000111101" + "110000011010000010000001111100111001010000000001100101010" + "101001110100100111111111010001101010011010011010111111110" + "111110001100001100010100001011110011001110000100011110010" + "000000110011100011000011111111111000001000100011111110010" + "000000001000001101101000101000101100000110010011100011100" + "111111101001111111010001001010100110001011000011101011010" + "100000100111000101110010001000110100111101011100100011010" + "101110101111110100111111011111100001111010110100111110100" + "101110101001110011011100111111011001000011001101000111010" + "101110100110010100010000101001000010000000100000100000111" + "100000100110011101110011001101110110101010001101000011011" + "111111100010001101010110001001000001001011001001011001011" + }, + /* 14*/ { BARCODE_QRCODE, UNICODE_MODE, 4, 27, -1, "点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点", 0, 125, 125, "Max capacity ECC 4 Version 27 385 kanji", "11111110101001001100111100100011110001010011110000001100010110100011101010111000011101101001011111001111101101101001101111111" "10000010110001101110011001101111000101001011011001100110101000101010011110000000101000100101101110110000011110100110001000001" "10111010100000000100000101000101111001011001010100100100100000000101100011010001100111101010010101101101101101101101001011101" @@ -732,8 +945,8 @@ static void test_qr_encode(int index, int generate, int debug) { "10111010101000111001001000010000000000000111000110100011000101101001010000100010101101111111000001001100101101111110111111010" "10000010010111001111010001100001010001010110110001100000111101011100000010010111101001001100101101111011011001000001101001110" "11111110000000010001110110000001010111011111000000111111010101110100101000110111000101101011001100000101101101101001100111111" - }, - /* 6*/ { UNICODE_MODE, "点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点", 4, 40, 0, 177, 177, "Max capacity ECC 4 Version 40 784 kanji", + }, + /* 15*/ { BARCODE_QRCODE, UNICODE_MODE, 4, 40, -1, "点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点点", 0, 177, 177, "Max capacity ECC 4 Version 40 784 kanji", "111111101010001111111101101110111010110111001110101000010001011011011101001110110011111011010000010101001010011110010000010110111111001001011111101000010010111111001010001111111" "100000101010110001001000101111011001001100100110110000000111110101111011110001101110000111000100101111010011001111100111111001001011011011110011011111111001000010010010101000001" "101110101001001101111001110010010100000000111001001011111000001001111111101010000111011010011010010001111010111001100011000011110100101110001010110001011110011011011010001011101" @@ -912,9 +1125,78 @@ static void test_qr_encode(int index, int generate, int debug) { "100000100000010000101110000100011000011110011100010100000011111110010100001100010010001001110010000000110010100111101101010110111111001000101010011011011000011110111110000000000" "111111100000001110110110101010011010010100111111101001111101110111010110101111000111011001110100010111000100111000011011001011010011010011010101111010000011100001000011111011001" - }, + }, + /* 16*/ { BARCODE_QRCODE, UNICODE_MODE, -1, -1, ZINT_FULL_MULTIBYTE, "áA", 0, 21, 21, "Mask automatic (001)", + "111111100101101111111" + "100000101001101000001" + "101110101010101011101" + "101110101001101011101" + "101110101101001011101" + "100000101010001000001" + "111111101010101111111" + "000000000001100000000" + "001001111011010111110" + "101000001010010000100" + "100111100000110001111" + "110000000001000010000" + "011010110111010001111" + "000000001100011101100" + "111111101011111111000" + "100000101101010101110" + "101110100001000111111" + "101110100101010000000" + "101110101001111000111" + "100000100100111010000" + "111111100011001000110" + }, + /* 17*/ { BARCODE_QRCODE, UNICODE_MODE, -1, -1, ZINT_FULL_MULTIBYTE | (8 << 8), "áA", 0, 21, 21, "Mask 111", + "111111101000101111111" + "100000101110101000001" + "101110100110101011101" + "101110101100101011101" + "101110101010001011101" + "100000101110001000001" + "111111101010101111111" + "000000000110100000000" + "000100100111000111011" + "111101011111000101110" + "100000100111110110111" + "101100011101011110011" + "001111100010000100101" + "000000001011011010100" + "111111100111100011011" + "100000100000000000100" + "101110100110000000111" + "101110101001001100011" + "101110100100101101101" + "100000100011111101000" + "111111100111010100101" + }, + /* 18*/ { BARCODE_QRCODE, UNICODE_MODE, -1, -1, ZINT_FULL_MULTIBYTE | (9 << 8), "áA", 0, 21, 21, "Mask > 111 ignored", + "111111100101101111111" + "100000101001101000001" + "101110101010101011101" + "101110101001101011101" + "101110101101001011101" + "100000101010001000001" + "111111101010101111111" + "000000000001100000000" + "001001111011010111110" + "101000001010010000100" + "100111100000110001111" + "110000000001000010000" + "011010110111010001111" + "000000001100011101100" + "111111101011111111000" + "100000101101010101110" + "101110100001000111111" + "101110100101010000000" + "101110101001111000111" + "100000100100111010000" + "111111100011001000110" + }, }; - int data_size = sizeof(data) / sizeof(struct item); + int data_size = ARRAY_SIZE(data); for (int i = 0; i < data_size; i++) { @@ -923,27 +1205,18 @@ static void test_qr_encode(int index, int generate, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = BARCODE_QRCODE; - symbol->input_mode = data[i].input_mode; - if (data[i].option_1 != -1) { - symbol->option_1 = data[i].option_1; - } - if (data[i].option_2 != -1) { - symbol->option_2 = data[i].option_2; - } - symbol->debug |= debug; - - int length = strlen(data[i].data); + int length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, data[i].option_1, data[i].option_2, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, \"%s\", %d, %d, %s, %d, %d, \"%s\",\n", - i, testUtilInputModeName(data[i].input_mode), data[i].data, data[i].option_1, data[i].option_2, testUtilErrorName(data[i].ret), + printf(" /*%3d*/ { %s, %s, %d, %d, %s, \"%s\", %s, %d, %d, \"%s\",\n", + i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_2, testUtilOption3Name(data[i].option_3), + data[i].data, testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment); testUtilModulesDump(symbol, " ", "\n"); - printf(" },\n"); + printf(" },\n"); } else { if (ret < 5) { assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); @@ -963,6 +1236,88 @@ static void test_qr_encode(int index, int generate, int debug) { testFinish(); } +#include + +#define TEST_PERF_ITERATIONS 1000 + +// Not a real test, just performance indicator +static void test_qr_perf(int index, int debug) { + + if (!(debug & ZINT_DEBUG_TEST_PERFORMANCE)) { /* -d 256 */ + return; + } + + int ret; + struct item { + int symbology; + int input_mode; + int option_1; + int option_2; + char *data; + int ret; + + int expected_rows; + int expected_width; + char *comment; + }; + struct item data[] = { + /* 0*/ { BARCODE_QRCODE, UNICODE_MODE, -1, -1, + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 12345678901234567890123456 点点点点点点点点点点点点点点点点点点点点点点点点点点", + 0, 37, 37, "107 chars, Mixed modes" }, + /* 1*/ { BARCODE_QRCODE, UNICODE_MODE, -1, -1, + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 12345678901234567890123456 点点点点点点点点点点点点点点点点点点点点点点点点点点" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 12345678901234567890123456 点点点点点点点点点点点点点点点点点点点点点点点点点点" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 12345678901234567890123456 点点点点点点点点点点点点点点点点点点点点点点点点点点" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 12345678901234567890123456 点点点点点点点点点点点点点点点点点点点点点点点点点点" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 12345678901234567890123456 点点点点点点点点点点点点点点点点点点点点点点点点点点" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 12345678901234567890123456 点点点点点点点点点点点点点点点点点点点点点点点点点点" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 12345678901234567890123456 点点点点点点点点点点点点点点点点点点点点点点点点点点" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 12345678901234567890123456 点点点点点点点点点点点点点点点点点点点点点点点点点点" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 12345678901234567890123456 点点点点点点点点点点点点点点点点点点点点点点点点点点", + 0, 105, 105, "963 chars, Mixed modes" }, + }; + int data_size = ARRAY_SIZE(data); + + clock_t start, total_encode = 0, total_buffer = 0, diff_encode, diff_buffer; + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + diff_encode = diff_buffer = 0; + + for (int j = 0; j < TEST_PERF_ITERATIONS; j++) { + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + int length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, data[i].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); + + 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); + + total_encode += diff_encode; + total_buffer += diff_buffer; + } + if (index != -1) { + printf("totals: encode %gms, buffer %gms\n", total_encode * 1000.0 / CLOCKS_PER_SEC, total_buffer * 1000.0 / CLOCKS_PER_SEC); + } +} + static void test_microqr_options(int index, int debug) { testStart(""); @@ -1268,26 +1623,30 @@ static void test_microqr_optimize(int index, int generate, int debug) { int ret; struct item { int input_mode; - char *data; int option_1; int option_2; + int option_3; + char *data; int ret; char *expected; char *comment; }; struct item data[] = { - /* 0*/ { UNICODE_MODE, "1", -1, -1, 0, "22 00 00", "N1" }, - /* 1*/ { UNICODE_MODE, "A123", 1, 2, 0, "92 86 3D 80 EC", "A1 N3" }, - /* 2*/ { UNICODE_MODE, "AAAAAA", 1, -1, 0, "E3 98 73 0E 60", "A6" }, - /* 3*/ { UNICODE_MODE, "AA123456", 1, -1, 0, "A3 98 61 ED C8", "A2 N6" }, - /* 4*/ { UNICODE_MODE, "01a", 1, 3, 0, "04 06 16 10 00 EC 11 EC 11 EC 00", "N3 B1" }, - /* 5*/ { UNICODE_MODE, "01a", 1, 4, 0, "43 30 31 61 00 00 EC 11 EC 11 EC 11 EC 11 EC 11", "B3" }, - /* 6*/ { UNICODE_MODE, "こんwa、αβ", 1, -1, 0, "46 82 B1 82 F1 77 61 66 00 10 FF 88 00 00 EC 11", "B6 K3" }, - /* 7*/ { UNICODE_MODE, "こんにwa、αβ", 1, -1, 0, "66 13 10 B8 85 25 09 DD 85 98 00 43 FE 20 00 00", "K3 B2 K3" }, - /* 8*/ { UNICODE_MODE, "こんAB123\177", 1, 3, 0, "D0 4C 42 E2 91 CD 06 3D C2 FE 00", "K2 A2 N3 B1" }, - /* 9*/ { UNICODE_MODE, "こんAB123\177", 1, 4, 0, "64 13 10 B8 92 9C D0 5E 1A 0B F8 00 EC 11 EC 11", "K2 A5 B1" }, + /* 0*/ { UNICODE_MODE, -1, -1, -1, "1", 0, "22 00 00", "N1" }, + /* 1*/ { UNICODE_MODE, 1, 2, -1, "A123", 0, "92 86 3D 80 EC", "A1 N3" }, + /* 2*/ { UNICODE_MODE, 1, -1, -1, "AAAAAA", 0, "E3 98 73 0E 60", "A6" }, + /* 3*/ { UNICODE_MODE, 1, -1, -1, "AA123456", 0, "A3 98 61 ED C8", "A2 N6" }, + /* 4*/ { UNICODE_MODE, 1, 3, -1, "01a", 0, "04 06 16 10 00 EC 11 EC 11 EC 00", "N3 B1" }, + /* 5*/ { UNICODE_MODE, 1, 4, -1, "01a", 0, "43 30 31 61 00 00 EC 11 EC 11 EC 11 EC 11 EC 11", "B3" }, + /* 6*/ { UNICODE_MODE, 1, -1, -1, "こんwa、αβ", 0, "46 82 B1 82 F1 77 61 66 00 10 FF 88 00 00 EC 11", "B6 K3" }, + /* 7*/ { UNICODE_MODE, 1, -1, -1, "こんにwa、αβ", 0, "66 13 10 B8 85 25 09 DD 85 98 00 43 FE 20 00 00", "K3 B2 K3" }, + /* 8*/ { UNICODE_MODE, 1, 3, -1, "こんAB123\177", 0, "D0 4C 42 E2 91 CD 06 3D C2 FE 00", "K2 A2 N3 B1" }, + /* 9*/ { UNICODE_MODE, 1, 4, -1, "こんAB123\177", 0, "64 13 10 B8 92 9C D0 5E 1A 0B F8 00 EC 11 EC 11", "K2 A5 B1" }, + /* 10*/ { DATA_MODE, 1, -1, -1, "\223\137", 0, "8A 4D 7C 00 EC 11 EC 11 EC 11 00", "B2" }, + /* 11*/ { DATA_MODE, 1, -1, ZINT_FULL_MULTIBYTE, "\223\137", 0, "CB 67 C0 00 EC 11 EC 11 EC 11 00", "K1" }, + /* 12*/ { DATA_MODE, 1, -1, ZINT_FULL_MULTIBYTE | (1 << 8), "\223\137", 0, "CB 67 C0 00 EC 11 EC 11 EC 11 00", "K1" }, }; - int data_size = sizeof(data) / sizeof(struct item); + int data_size = ARRAY_SIZE(data); char escaped[1024]; @@ -1298,26 +1657,17 @@ static void test_microqr_optimize(int index, int generate, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = BARCODE_MICROQR; - symbol->input_mode = data[i].input_mode; - if (data[i].option_1 != -1) { - symbol->option_1 = data[i].option_1; - } - if (data[i].option_2 != -1) { - symbol->option_2 = data[i].option_2; - } - symbol->option_3 = ZINT_FULL_MULTIBYTE; - symbol->debug = ZINT_DEBUG_TEST; - symbol->debug |= debug; + debug |= ZINT_DEBUG_TEST; // Needed to get codeword dump in errtxt - int length = strlen(data[i].data); + int length = testUtilSetSymbol(symbol, BARCODE_MICROQR, data[i].input_mode, -1 /*eci*/, data[i].option_1, data[i].option_2, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, \"%s\", %d, %d, %s, \"%s\", \"%s\" },\n", - i, testUtilInputModeName(data[i].input_mode), testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].option_1, data[i].option_2, + printf(" /*%3d*/ { %s, %d, %d, %s, \"%s\", %s, \"%s\", \"%s\" },\n", + i, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_2, testUtilOption3Name(data[i].option_3), + testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), testUtilErrorName(data[i].ret), symbol->errtxt, data[i].comment); } else { assert_zero(strcmp(symbol->errtxt, data[i].expected), "i:%d strcmp(%s, %s) != 0\n", i, symbol->errtxt, data[i].expected); @@ -1336,9 +1686,10 @@ static void test_microqr_encode(int index, int generate, int debug) { int ret; struct item { int input_mode; - char *data; int option_1; int option_2; + int option_3; + char *data; int ret; int expected_rows; @@ -1347,7 +1698,112 @@ static void test_microqr_encode(int index, int generate, int debug) { char *expected; }; struct item data[] = { - /* 0*/ { UNICODE_MODE, "12345", -1, -1, 0, 11, 11, "Max capacity M1 5 numbers", + /* 0*/ { UNICODE_MODE, 1, -1, -1, "01234567", 0, 13, 13, "ISO 18004 Figure 2 (and I.2) (mask 01)", + "1111111010101" + "1000001011101" + "1011101001101" + "1011101001111" + "1011101011100" + "1000001010001" + "1111111001111" + "0000000001100" + "1101000010001" + "0110101010101" + "1110011111110" + "0001010000110" + "1110100110111" + }, + /* 1*/ { UNICODE_MODE, 2, -1, -1, "12345", 0, 13, 13, "ISO 18004 Figure 38 (mask 00)", + "1111111010101" + "1000001010000" + "1011101011101" + "1011101000011" + "1011101001110" + "1000001010001" + "1111111000101" + "0000000001011" + "1110011110000" + "0111100101100" + "1110000001110" + "0100100010101" + "1111111010011" + }, + /* 2*/ { UNICODE_MODE, 2, -1, 1 << 8, "12345", 0, 13, 13, "ISO 18004 Figure 38, explicit mask 00", + "1111111010101" + "1000001010000" + "1011101011101" + "1011101000011" + "1011101001110" + "1000001010001" + "1111111000101" + "0000000001011" + "1110011110000" + "0111100101100" + "1110000001110" + "0100100010101" + "1111111010011" + }, + /* 3*/ { UNICODE_MODE, 2, -1, ZINT_FULL_MULTIBYTE | 2 << 8, "12345", 0, 13, 13, "Explicit mask 01", + "1111111010101" + "1000001000001" + "1011101001100" + "1011101011101" + "1011101000000" + "1000001000000" + "1111111010100" + "0000000000101" + "1110001011110" + "0001101011101" + "1000001111111" + "0101010011011" + "1110001011101" + }, + /* 4*/ { UNICODE_MODE, 2, -1, 3 << 8, "12345", 0, 13, 13, "Explicit mask 10", + "1111111010101" + "1000001010001" + "1011101001111" + "1011101010110" + "1011101011010" + "1000001010110" + "1111111010101" + "0000000011010" + "1110110110010" + "0101001111001" + "1010100101010" + "0100011010010" + "1111111010011" + }, + /* 5*/ { UNICODE_MODE, 2, -1, ZINT_FULL_MULTIBYTE | 4 << 8, "12345", 0, 13, 13, "Explicit mask 11", + "1111111010101" + "1000001001110" + "1011101010101" + "1011101001001" + "1011101010000" + "1000001001001" + "1111111001111" + "0000000010101" + "1110100011000" + "0010110000110" + "1111110000000" + "0011100101101" + "1010101111001" + }, + /* 6*/ { UNICODE_MODE, 2, -1, 5 << 8, "12345", 0, 13, 13, "Mask > 4 ignored", + "1111111010101" + "1000001010000" + "1011101011101" + "1011101000011" + "1011101001110" + "1000001010001" + "1111111000101" + "0000000001011" + "1110011110000" + "0111100101100" + "1110000001110" + "0100100010101" + "1111111010011" + }, + /* 7*/ { UNICODE_MODE, -1, -1, -1, "12345", 0, 11, 11, "Max capacity M1 5 numbers", "11111110101" "10000010110" "10111010100" @@ -1359,8 +1815,8 @@ static void test_microqr_encode(int index, int generate, int debug) { "11001110011" "01010001100" "11110000011" - }, - /* 1*/ { UNICODE_MODE, "1234567890", -1, -1, 0, 13, 13, "Max capacity M2-L 10 numbers", + }, + /* 8*/ { UNICODE_MODE, -1, -1, -1, "1234567890", 0, 13, 13, "Max capacity M2-L 10 numbers", "1111111010101" "1000001010110" "1011101010001" @@ -1374,8 +1830,8 @@ static void test_microqr_encode(int index, int generate, int debug) { "1111001001101" "0110010100110" "1001101111111" - }, - /* 2*/ { UNICODE_MODE, "12345678", 2, -1, 0, 13, 13, "Max capacity M2-M 8 numbers", + }, + /* 9*/ { UNICODE_MODE, 2, -1, -1, "12345678", 0, 13, 13, "Max capacity M2-M 8 numbers", "1111111010101" "1000001011000" "1011101011101" @@ -1389,8 +1845,8 @@ static void test_microqr_encode(int index, int generate, int debug) { "1110010000111" "0101011001100" "1100110101001" - }, - /* 3*/ { UNICODE_MODE, "12345678901234567890123", -1, -1, 0, 15, 15, "Max capacity M3-L 23 numbers", + }, + /* 10*/ { UNICODE_MODE, -1, -1, -1, "12345678901234567890123", 0, 15, 15, "Max capacity M3-L 23 numbers", "111111101010101" "100000100110110" "101110100011111" @@ -1406,8 +1862,8 @@ static void test_microqr_encode(int index, int generate, int debug) { "110000101011000" "010011000101101" "100111010001111" - }, - /* 4*/ { UNICODE_MODE, "123456789012345678", 2, -1, 0, 15, 15, "Max capacity M3-L 18 numbers", + }, + /* 11*/ { UNICODE_MODE, 2, -1, -1, "123456789012345678", 0, 15, 15, "Max capacity M3-L 18 numbers", "111111101010101" "100000100010110" "101110101101111" @@ -1423,8 +1879,8 @@ static void test_microqr_encode(int index, int generate, int debug) { "110001101011001" "001110000101101" "110011111001111" - }, - /* 5*/ { UNICODE_MODE, "12345678901234567890123456789012345", -1, -1, 0, 17, 17, "Max capacity M4-L 35 numbers", + }, + /* 12*/ { UNICODE_MODE, -1, -1, -1, "12345678901234567890123456789012345", 0, 17, 17, "Max capacity M4-L 35 numbers", "11111110101010101" "10000010111010001" "10111010000011001" @@ -1442,8 +1898,8 @@ static void test_microqr_encode(int index, int generate, int debug) { "11100000000010011" "01110010010111010" "11001001111110111" - }, - /* 6*/ { UNICODE_MODE, "123456789012345678901234567890", 2, -1, 0, 17, 17, "Max capacity M4-M 30 numbers", + }, + /* 13*/ { UNICODE_MODE, 2, -1, -1, "123456789012345678901234567890", 0, 17, 17, "Max capacity M4-M 30 numbers", "11111110101010101" "10000010011010001" "10111010000011001" @@ -1461,8 +1917,8 @@ static void test_microqr_encode(int index, int generate, int debug) { "11010010101010000" "00001111000111000" "11100110111110111" - }, - /* 7*/ { UNICODE_MODE, "123456789012345678901", 3, -1, 0, 17, 17, "Max capacity M4-Q 21 numbers", + }, + /* 14*/ { UNICODE_MODE, 3, -1, -1, "123456789012345678901", 0, 17, 17, "Max capacity M4-Q 21 numbers", "11111110101010101" "10000010010101101" "10111010010010101" @@ -1480,8 +1936,8 @@ static void test_microqr_encode(int index, int generate, int debug) { "11110001010001110" "00000001110011011" "11011110011010100" - }, - /* 8*/ { UNICODE_MODE, "点茗テ点茗テ点茗テ", -1, -1, 0, 17, 17, "Max capacity M4-L 9 Kanji", + }, + /* 15*/ { UNICODE_MODE, -1, -1, -1, "点茗テ点茗テ点茗テ", 0, 17, 17, "Max capacity M4-L 9 Kanji", "11111110101010101" "10000010111110010" "10111010000011101" @@ -1499,9 +1955,9 @@ static void test_microqr_encode(int index, int generate, int debug) { "10000100101100011" "01011000000010111" "11001111011101001" - }, + }, }; - int data_size = sizeof(data) / sizeof(struct item); + int data_size = ARRAY_SIZE(data); for (int i = 0; i < data_size; i++) { @@ -1510,27 +1966,18 @@ static void test_microqr_encode(int index, int generate, int debug) { struct zint_symbol *symbol = ZBarcode_Create(); assert_nonnull(symbol, "Symbol not created\n"); - symbol->symbology = BARCODE_MICROQR; - symbol->input_mode = data[i].input_mode; - if (data[i].option_1 != -1) { - symbol->option_1 = data[i].option_1; - } - if (data[i].option_2 != -1) { - symbol->option_2 = data[i].option_2; - } - symbol->debug |= debug; - - int length = strlen(data[i].data); + int length = testUtilSetSymbol(symbol, BARCODE_MICROQR, data[i].input_mode, -1 /*eci*/, data[i].option_1, data[i].option_2, data[i].option_3, -1 /*output_options*/, data[i].data, -1, debug); ret = ZBarcode_Encode(symbol, (unsigned char *) data[i].data, length); assert_equal(ret, data[i].ret, "i:%d ZBarcode_Encode ret %d != %d (%s)\n", i, ret, data[i].ret, symbol->errtxt); if (generate) { - printf(" /*%3d*/ { %s, \"%s\", %d, %d, %s, %d, %d, \"%s\",\n", - i, testUtilInputModeName(data[i].input_mode), data[i].data, data[i].option_1, data[i].option_2, testUtilErrorName(data[i].ret), + printf(" /*%3d*/ { %s, %d, %d, %s, \"%s\", %s, %d, %d, \"%s\",\n", + i, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_2, testUtilOption3Name(data[i].option_3), + data[i].data, testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment); testUtilModulesDump(symbol, " ", "\n"); - printf(" },\n"); + printf(" },\n"); } else { if (ret < 5) { assert_equal(symbol->rows, data[i].expected_rows, "i:%d symbol->rows %d != %d (%s)\n", i, symbol->rows, data[i].expected_rows, data[i].data); @@ -2192,6 +2639,7 @@ int main(int argc, char *argv[]) { { "test_qr_gs1", test_qr_gs1, 1, 1, 1 }, { "test_qr_optimize", test_qr_optimize, 1, 1, 1 }, { "test_qr_encode", test_qr_encode, 1, 1, 1 }, + { "test_qr_perf", test_qr_perf, 1, 0, 1 }, { "test_microqr_options", test_microqr_options, 1, 0, 1 }, { "test_microqr_input", test_microqr_input, 1, 1, 1 }, diff --git a/backend/tests/test_reedsol.c b/backend/tests/test_reedsol.c new file mode 100644 index 00000000..6f42c15f --- /dev/null +++ b/backend/tests/test_reedsol.c @@ -0,0 +1,227 @@ +/* + libzint - the open source barcode library + Copyright (C) 2020 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + */ +/* vim: set ts=4 sw=4 et : */ + +#include "testcommon.h" +#include "../reedsol.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) { + int i; + const char *type = u16 ? "short" : "char"; + const char *format = u16 ? " 0x%04X," : " 0x%02X,"; + + printf("static const unsigned %s logt_%s[%d] = {", type, name, logmod + 1); + for (i = 0; i < logmod + 1; i++) { + if (i % 16 == 0) printf("\n "); + printf(format, i ? logt[i] : 0); + } + printf("\n};\n"); + + printf("static const unsigned %s alog_%s[%d] = {", type, name, logmod * 2); + for (i = 0; i < logmod; i++) { + if (i % 16 == 0) printf("\n "); + printf(format, alog[i]); + } + // Double antilog table + for (i = 0; i < logmod; i++) { + if (i % 16 == 0) printf("\n "); + printf(format, alog[i]); + } + printf("\n};\n"); + if (!last) { + printf("\n"); + } +} + +static void gen_logs(const unsigned int prime_poly, int logmod, unsigned int *logt, unsigned int *alog) { + int b, p, v; + + b = logmod + 1; + + // Calculate the log/alog tables + for (p = 1, v = 0; v < logmod; v++) { + alog[v] = p; + logt[p] = v; + p <<= 1; + if (p & b) + p ^= prime_poly; + } +} + +// Dummy to generate static log/antilog tables for "backend/reedsol_logs.h" +static void test_generate(int generate) { + + if (!generate) { + return; + } + + struct item { + const char *name; + int logmod; + unsigned int prime_poly; + int u16; + }; + struct item data[] = { + { "0x13", 15, 0x13, 0 }, + { "0x25", 31, 0x25, 0 }, + { "0x43", 63, 0x43, 0 }, + { "0x89", 127, 0x89, 0 }, + { "0x11d", 255, 0x11d, 0 }, + { "0x12d", 255, 0x12d, 0 }, + { "0x163", 255, 0x163, 0 }, + }; + int data_size = ARRAY_SIZE(data); + + unsigned int logt[4096]; + unsigned int alog[8192]; + + for (int i = 0; i < data_size; i++) { + gen_logs(data[i].prime_poly, data[i].logmod, logt, alog); + print_logs(data[i].name, data[i].logmod, logt, alog, data[i].u16, i + 1 == data_size); + } +} + +static void test_encoding(int index) { + + testStart(""); + + struct item { + unsigned int prime_poly; + int nsym; + int index; + int datalen; + unsigned char data[256]; + + unsigned char expected[256]; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { 0x43, 4, 1, 7, { 4, 20, 49, 37, 49, 38, 23 }, { 54, 17, 53, 58 } }, // AUSPOST Australia Post Customer Barcoding Technical Specifications Diagram 10 + /* 1*/ { 0x43, 7, 1, 10, { 9, 50, 1, 41, 47, 2, 39, 37, 1, 27 }, { 38, 50, 8, 16, 10, 20, 40 } }, // AZTEC ISO/IEC 24778:2008 Section G.4 + /* 2*/ { 0x13, 5, 1, 2, { 0, 9 }, { 12, 2, 3, 1, 9 } }, // AZTEC ISO/IEC 24778:2008 Section G.4 Mode Message + /* 3*/ { 0x12d, 5, 1, 3, { 142, 164, 186 }, { 114, 25, 5, 88, 102 } }, // DATAMATRIX ISO/IEC 16022:2006 Annex O + /* 4*/ { 0x89, 25, 1, 25, { 42, 13, 54, 39, 124, 91, 121, 65, 28, 40, 95, 48, 0, 126, 0, 126, 0, 126, 0, 126, 0, 126, 0, 126, 0 }, { 123, 47, 2, 20, 54, 112, 35, 23, 100, 89, 55, 17, 101, 4, 14, 33, 48, 62, 98, 52, 2, 79, 92, 70, 102 } }, // GRIDMATRIX AIMD014 Section 6.8 + /* 5*/ { 0x163, 4, 1, 21, { 0x11, 0xED, 0xC8, 0xC5, 0x40, 0x0F, 0xF4 }, { 0xEB, 0xB4, 0x68, 0x1D } }, // HANXIN ISO/IEC DIS 20830:2019 Annex K.1 + /* 6*/ { 0x163, 24, 1, 27, { 0x11, 0xED, 0xC8, 0xC5, 0x40, 0x0F, 0xF4, 0x8A, 0x2C, 0xC3, 0x4E, 0x3D, 0x09, 0x25, 0x9A, 0x7A, 0x29, 0xAB, 0xEA, 0x3E, 0x46, 0x4C, 0x7E, 0x73, 0xE8, 0x6C, 0xC7 }, { 0x08, 0x57, 0x0C, 0xE0, 0x7A, 0xA5, 0xDD, 0xA2, 0x99, 0xCF, 0xA4, 0x82, 0xAD, 0x11, 0xB0, 0x84, 0x74, 0x5D, 0x9A, 0x99, 0x0B, 0xCD, 0x49, 0x77 } }, // HANXIN ISO/IEC DIS 20830:2019 Annex K.2 1st block + /* 7*/ { 0x163, 24, 1, 27, { 0xE7, 0x3E, 0x33, 0x29, 0xE8, 0xFC, }, { 0xA2, 0xA7, 0x68, 0x8A, 0x5F, 0xE6, 0xAA, 0x11, 0xA6, 0x69, 0x4A, 0xCF, 0xCF, 0x20, 0x5D, 0x00, 0x1B, 0x79, 0xA1, 0xFE, 0xB7, 0x94, 0x03, 0x9B } }, // HANXIN ISO/IEC DIS 20830:2019 Annex K.2 2nd block + /* 8*/ { 0x163, 24, 1, 29, { 0x00 }, { 0x00 } }, // HANXIN ISO/IEC DIS 20830:2019 Annex K.2 3rd block + /* 9*/ { 0x25, 6, 1, 16, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4 }, { 14, 7, 23, 3, 23, 15 } }, // MAILMARK Royal Mail Mailmark barcode C encoding and decoding Example 2.3.1 + /* 10*/ { 0x25, 6, 1, 16, { 15, 22, 3, 25, 23, 26, 7, 3, 20, 14, 1, 4, 16, 3, 9, 28 }, { 27, 22, 24, 16, 6, 24 } }, // MAILMARK Royal Mail Mailmark barcode C encoding and decoding Example 2.3.2 + /* 11*/ { 0x25, 7, 1, 19, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4 }, { 20, 1, 20, 7, 14, 11, 18 } }, // MAILMARK Royal Mail Mailmark barcode L encoding and decoding Example 2.3.1 + /* 12*/ { 0x25, 7, 1, 19, { 0, 8, 21, 10, 29, 1, 29, 21, 2, 24, 15, 2, 19, 1, 4, 15, 11, 4, 16 }, { 19, 7, 9, 8, 6, 16, 16 } }, // MAILMARK Royal Mail Mailmark barcode L encoding and decoding Example 2.3.2 + /* 13*/ { 0x43, 10, 1, 10, { 4, 13, 63, 1, 24, 9, 59, 3, 15, 4 }, { 50, 2, 42, 51, 53, 34, 22, 20, 5, 16 } }, // MAXICODE Annex H Primary + /* 14*/ { 0x43, 20, 1, 42, { 5, 57, 49, 47, 8, 18, 59, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33 }, { 31, 2, 58, 6, 6, 39, 13, 63, 2, 30, 19, 19, 14, 19, 23, 17, 62, 8, 2, 23 } }, // MAXICODE Annex H Secondary odd + /* 15*/ { 0x43, 20, 1, 42, { 47, 40, 57, 3, 1, 19, 41, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33 }, { 1, 15, 22, 28, 39, 17, 60, 5, 35, 35, 4, 8, 0, 32, 51, 45, 63, 53, 61, 14 } }, // MAXICODE Annex H Secondary even + /* 16*/ { 0x11d, 10, 0, 16, { 0x10, 0x20, 0x0C, 0x56, 0x61, 0x80, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11, 0xEC, 0x11 }, { 0xA5, 0x24, 0xD4, 0xC1, 0xED, 0x36, 0xC7, 0x87, 0x2C, 0x55 } }, // QRCODE Annex I.2 + /* 17*/ { 0x11d, 5, 0, 5, { 0x40, 0x18, 0xAC, 0xC3, 0x00 }, { 0x86, 0x0D, 0x22, 0xAE, 0x30 } }, // QRCODE Annex I.3 + }; + int data_size = ARRAY_SIZE(data); + + for (int i = 0; i < data_size; i++) { + + rs_t rs; + unsigned char res[1024]; + + if (index != -1 && i != index) continue; + + rs_init_gf(&rs, data[i].prime_poly); + rs_init_code(&rs, data[i].nsym, data[i].index); + rs_encode(&rs, data[i].datalen, data[i].data, res); + + //fprintf(stderr, "res "); for (int j = data[i].nsym - 1; j >= 0; j--) fprintf(stderr, "%d ", res[j]); fprintf(stderr, "\n"); + //fprintf(stderr, "exp "); for (int j = 0; j < data[i].nsym; j++) fprintf(stderr, "%d ", data[i].expected[j]); fprintf(stderr, "\n"); + for (int j = 0; j < data[i].nsym; j++) { + int k = data[i].nsym - 1 - j; + assert_equal(res[k], data[i].expected[j], "i:%d res[%d] %d != expected[%d] %d\n", i, k, res[k], j, data[i].expected[j]); + } + } + + testFinish(); +} + +static void test_encoding_uint(int index) { + + testStart(""); + + struct item { + unsigned int prime_poly; + int logmod; + int nsym; + int index; + int datalen; + unsigned int data[256]; + + unsigned int expected[256]; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { 0x409, 1023, 4, 1, 7, { 0x3FF, 0x000, 0x100, 0x1FF, 0x3FF, 0x000, 0x123 }, { 229, 153, 993, 674 } }, + /* 1*/ { 0x1069, 4095, 4, 1, 7, { 0xFFF, 0x000, 0x700, 0x7FF, 0xFFF, 0x000, 0x123 }, { 3472, 2350, 3494, 575 } }, + }; + int data_size = ARRAY_SIZE(data); + + for (int i = 0; i < data_size; i++) { + + rs_uint_t rs_uint; + unsigned int res[1024]; + + if (index != -1 && i != index) continue; + + rs_uint_init_gf(&rs_uint, data[i].prime_poly, data[i].logmod); + rs_uint_init_code(&rs_uint, data[i].nsym, data[i].index); + rs_uint_encode(&rs_uint, data[i].datalen, data[i].data, res); + rs_uint_free(&rs_uint); + + //fprintf(stderr, "res "); for (int j = data[i].nsym - 1; j >= 0; j--) fprintf(stderr, "%d ", res[j]); fprintf(stderr, "\n"); + //fprintf(stderr, "exp "); for (int j = 0; j < data[i].nsym; j++) fprintf(stderr, "%d ", data[i].expected[j]); fprintf(stderr, "\n"); + for (int j = 0; j < data[i].nsym; j++) { + int k = data[i].nsym - 1 - j; + assert_equal(res[k], data[i].expected[j], "i:%d res[%d] %d != expected[%d] %d\n", i, k, res[k], j, data[i].expected[j]); + } + } + + testFinish(); +} + +int main(int argc, char *argv[]) { + + testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */ + { "test_generate", test_generate, 0, 1, 0 }, + { "test_encoding", test_encoding, 1, 0, 0 }, + { "test_encoding_uint", test_encoding_uint, 1, 0, 0 }, + }; + + testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); + + testReport(); + + return 0; +} diff --git a/backend/tests/test_sjis.c b/backend/tests/test_sjis.c index ea003c46..41bce887 100644 --- a/backend/tests/test_sjis.c +++ b/backend/tests/test_sjis.c @@ -115,7 +115,7 @@ static void test_sjis_utf8tomb(int index) { char *data; int length; int ret; - size_t ret_length; + int ret_length; unsigned int expected_jisdata[20]; char *comment; }; @@ -149,12 +149,12 @@ static void test_sjis_utf8tomb(int index) { if (index != -1 && i != index) continue; int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; - size_t ret_length = length; + int ret_length = length; ret = sjis_utf8tomb(&symbol, (unsigned char *) data[i].data, &ret_length, jisdata); assert_equal(ret, data[i].ret, "i:%d ret %d != %d (%s)\n", i, ret, data[i].ret, symbol.errtxt); if (ret == 0) { - assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %zu != %zu\n", i, ret_length, data[i].ret_length); + assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %d != %d\n", i, ret_length, data[i].ret_length); for (int j = 0; j < (int) ret_length; j++) { assert_equal(jisdata[j], data[i].expected_jisdata[j], "i:%d jisdata[%d] %04X != %04X\n", i, j, jisdata[j], data[i].expected_jisdata[j]); } @@ -175,7 +175,7 @@ static void test_sjis_utf8tosb(int index) { char *data; int length; int ret; - size_t ret_length; + int ret_length; unsigned int expected_jisdata[20]; char *comment; }; @@ -215,12 +215,12 @@ static void test_sjis_utf8tosb(int index) { if (index != -1 && i != index) continue; int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; - size_t ret_length = length; + int ret_length = length; ret = sjis_utf8tosb(data[i].eci, (unsigned char *) data[i].data, &ret_length, jisdata, data[i].full_multibyte); assert_equal(ret, data[i].ret, "i:%d ret %d != %d\n", i, ret, data[i].ret); if (ret == 0) { - assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %zu != %zu\n", i, ret_length, data[i].ret_length); + assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %d != %d\n", i, ret_length, data[i].ret_length); for (int j = 0; j < (int) ret_length; j++) { assert_equal(jisdata[j], data[i].expected_jisdata[j], "i:%d jisdata[%d] %04X != %04X\n", i, j, jisdata[j], data[i].expected_jisdata[j]); } @@ -239,7 +239,7 @@ static void test_sjis_cpy(int index) { char *data; int length; int ret; - size_t ret_length; + int ret_length; unsigned int expected_jisdata[20]; char *comment; }; @@ -265,10 +265,10 @@ static void test_sjis_cpy(int index) { if (index != -1 && i != index) continue; int length = data[i].length == -1 ? (int) strlen(data[i].data) : data[i].length; - size_t ret_length = length; + int ret_length = length; sjis_cpy((unsigned char *) data[i].data, &ret_length, jisdata, data[i].full_multibyte); - assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %zu != %zu\n", i, ret_length, data[i].ret_length); + assert_equal(ret_length, data[i].ret_length, "i:%d ret_length %d != %d\n", i, ret_length, data[i].ret_length); for (int j = 0; j < (int) ret_length; j++) { assert_equal(jisdata[j], data[i].expected_jisdata[j], "i:%d jisdata[%d] %04X != %04X\n", i, j, jisdata[j], data[i].expected_jisdata[j]); } diff --git a/backend/tests/test_vector.c b/backend/tests/test_vector.c index ef13283f..f22dc707 100644 --- a/backend/tests/test_vector.c +++ b/backend/tests/test_vector.c @@ -622,8 +622,8 @@ static void test_output_options(int index, int debug) { /* 12*/ { BARCODE_QRCODE, -1, -1, -1, "A123", 0, 21, 21, 21, 42, 42, 0, 0, 6 }, /* 13*/ { BARCODE_QRCODE, -1, 3, -1, "A123", 0, 21, 21, 21, 42, 42, 0, 0, 6 }, /* 14*/ { BARCODE_QRCODE, -1, 3, BARCODE_BIND, "A123", 0, 21, 21, 21, 42, 54, 1, 0, 6 }, - /* 15*/ { BARCODE_QRCODE, -1, 3, BARCODE_BIND, "A123", 0, 21, 21, 21, 42, 54, 0, 22, 6 }, - /* 16*/ { BARCODE_QRCODE, -1, 3, BARCODE_BOX, "A123", 0, 21, 21, 21, 54, 54, 1, 22, 6 }, + /* 15*/ { BARCODE_QRCODE, -1, 3, BARCODE_BIND, "A123", 0, 21, 21, 21, 42, 54, 0, 22, 8 }, + /* 16*/ { BARCODE_QRCODE, -1, 3, BARCODE_BOX, "A123", 0, 21, 21, 21, 54, 54, 1, 22, 8 }, /* 17*/ { BARCODE_QRCODE, -1, -1, -1, "A123", 0, 21, 21, 21, 42, 42, 0, 10, 12 }, /* 18*/ { BARCODE_QRCODE, 5, 6, BARCODE_BIND, "A123", 0, 21, 21, 21, 62, 66, 1, 10, 12 }, /* 19*/ { BARCODE_QRCODE, 5, 6, BARCODE_BIND, "A123", 0, 21, 21, 21, 62, 66, 0, 22, 12 }, diff --git a/backend/tests/testcommon.c b/backend/tests/testcommon.c index 6364231a..5325e56e 100644 --- a/backend/tests/testcommon.c +++ b/backend/tests/testcommon.c @@ -65,7 +65,7 @@ void testStartReal(const char *func, const char *name) { } void testEnd(int result) { - if (testName[0]) { + if (testName && testName[0]) { printf(".....%d: %s: %s ", tests, testFunc, testName); } else { printf(".....%d: %s: ", tests, testFunc); @@ -79,7 +79,7 @@ void testEnd(int result) { } void testFinish(void) { - if (testName[0]) { + if (testName && testName[0]) { printf(".....%d: %s: %s ", tests, testFunc, testName); } else { printf(".....%d: %s: ", tests, testFunc); @@ -94,7 +94,7 @@ void testFinish(void) { void testSkip(const char *msg) { skipped++; - if (testName[0]) { + if (testName && testName[0]) { printf(".....%d: %s: %s ", tests, testFunc, testName); } else { printf(".....%d: %s: ", tests, testFunc); @@ -486,17 +486,43 @@ const char *testUtilInputModeName(int input_mode) { } const char *testUtilOption3Name(int option_3) { - switch (option_3) { - case DM_SQUARE: return "DM_SQUARE"; - case DM_DMRE: return "DM_DMRE"; - case ZINT_FULL_MULTIBYTE: return "ZINT_FULL_MULTIBYTE"; - case ULTRA_COMPRESSION: return "ULTRA_COMPRESSION"; + static char buffer[64]; + + const char *name = NULL; + unsigned int high_byte = option_3 == -1 ? 0 : (option_3 >> 8) & 0xFF; + + switch (option_3 & 0xFF) { + case DM_SQUARE: + name = "DM_SQUARE"; + break; + case DM_DMRE: + name = "DM_DMRE"; + break; + case ZINT_FULL_MULTIBYTE: + name = "ZINT_FULL_MULTIBYTE"; + break; + case ULTRA_COMPRESSION: + name = "ULTRA_COMPRESSION"; + break; + default: + if (option_3 != -1 && (option_3 & 0xFF) != 0) { + fprintf(stderr, "testUtilOption3Name: unknown value (%d)\n", option_3); + abort(); + } + name = (option_3 & 0xFF) ? "-1" : "0"; + break; } - if (option_3 != -1 && option_3 != 0) { - fprintf(stderr, "testUtilOption3Name: unknown value (%d)\n", option_3); - abort(); + + if (high_byte) { + if (option_3 & 0xFF) { + sprintf(buffer, "%s | (%d << 8)", name, high_byte); + } else { + sprintf(buffer, "%d << 8", high_byte); + } + return buffer; } - return option_3 ? "-1" : "0"; + + return name; } const char *testUtilOutputOptionsName(int output_options) { @@ -1805,7 +1831,7 @@ static const char *testUtilBwippName(int index, const struct zint_symbol *symbol { "databarstackedomnicomposite", BARCODE_DBAR_OMNSTK_CC, 138, 1, 0, 0, 33 /*linear_row_height*/, 1, }, { "databarexpandedstackedcomposite", BARCODE_DBAR_EXPSTK_CC, 139, 1, 1, 0, 34 /*linear_row_height*/, 1, }, { "channelcode", BARCODE_CHANNEL, 140, 0, 0, 0, 0, 0, }, - { "codeone", BARCODE_CODEONE, 141, 0, 0, 0, 0, 0, }, + { "codeone", BARCODE_CODEONE, 141, 0, 1, 0, 0, 0, }, { "", BARCODE_GRIDMATRIX, 142, 0, 0, 0, 0, 0, }, { "", BARCODE_UPNQR, 143, 0, 0, 0, 0, 0, }, { "ultracode", BARCODE_ULTRA, 144, 0, 0, 0, 0, 0, }, @@ -2237,6 +2263,12 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int sprintf(bwipp_opts_buf + (int) strlen(bwipp_opts_buf), "%sformat=compact", strlen(bwipp_opts_buf) ? " " : ""); bwipp_opts = bwipp_opts_buf; } + } else if (symbology == BARCODE_CODEONE) { + if (option_2 >= 1 && option_2 <= 10) { + static char codeone_versions[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'S', 'T' }; + sprintf(bwipp_opts_buf + (int) strlen(bwipp_opts_buf), "%sversion=%c", strlen(bwipp_opts_buf) ? " " : "", codeone_versions[option_2 - 1]); + bwipp_opts = bwipp_opts_buf; + } } } diff --git a/backend/zint.h b/backend/zint.h index 5ff1c850..f4eb99f4 100644 --- a/backend/zint.h +++ b/backend/zint.h @@ -304,6 +304,7 @@ extern "C" { #define ZINT_CAP_FIXED_RATIO 0x0100 /* Aspect ratio */ #define ZINT_CAP_READER_INIT 0x0200 #define ZINT_CAP_FULL_MULTIBYTE 0x0400 +#define ZINT_CAP_MASK 0x0800 // Debug flags #define ZINT_DEBUG_PRINT 1 diff --git a/backend_tcl/zint.c b/backend_tcl/zint.c index 59bf724b..64f91bc3 100644 --- a/backend_tcl/zint.c +++ b/backend_tcl/zint.c @@ -430,6 +430,7 @@ static char help_message[] = "zint tcl(stub,obj) dll\n" " -rows integer: Codablock F: number of rows\n" " -vers integer: Symbology option\n" " -dmre bool: Allow Data Matrix Rectangular Extended\n" + " -mask integer: Mask pattern to use for QR (0..7), MicroQR (0..3) or HanXin (0..3)\n" " -separator 0..4 (default: 1) : Stacked symbologies: separator width\n" " -rotate angle: Image rotation by 0,90 or 270 degrees\n" " -secure integer: EC Level (PDF417, QR)\n" @@ -602,6 +603,7 @@ static int Encode(Tcl_Interp *interp, int objc, int fFullMultiByte = 0; int addon_gap = 0; int Separator = 1; + int Mask = 0; /*------------------------------------------------------------------------*/ /* >> Check if at least data and object is given and a pair number of */ /* >> options */ @@ -632,13 +634,13 @@ static int Encode(Tcl_Interp *interp, int objc, "-gssep", "-height", "-init", "-mode", "-nobackground", "-notext", "-primary", "-rotate", "-rows", "-scale", "-secure", "-smalltext", "-square", "-to", "-vers", "-whitesp", "-fullmultibyte", - "-separator", NULL}; + "-separator", "-mask", NULL}; enum iOption { iAddonGap, iBarcode, iBG, iBind, iBold, iBorder, iBox, iCols, iDMRE, iDotSize, iDotty, iECI, iFG, iFormat, iGSSep, iHeight, iInit, iMode, iNoBackground, iNoText, iPrimary, iRotate, iRows, iScale, iSecure, iSmallText, iSquare, iTo, iVers, - iWhiteSp, iFullMultiByte, iSeparator + iWhiteSp, iFullMultiByte, iSeparator, iMask }; int optionIndex; int intValue; @@ -711,6 +713,14 @@ static int Encode(Tcl_Interp *interp, int objc, fError = 1; } break; + case iMask: + /* >> Int */ + if (TCL_OK != Tcl_GetIntFromObj(interp, objv[optionPos+1], + &intValue)) + { + fError = 1; + } + break; case iPrimary: /* > Primary String up to 90 characters */ /* > Output filename up to 250 characters */ @@ -871,6 +881,15 @@ static int Encode(Tcl_Interp *interp, int objc, Separator = intValue; } break; + case iMask: + if (intValue < 0 || intValue > 7) { + Tcl_SetObjResult(interp, + Tcl_NewStringObj("Mask out of range", -1)); + fError = 1; + } else { + Mask = intValue + 1; + } + break; case iCols: case iVers: /* >> Int in Option 2 */ @@ -999,13 +1018,17 @@ static int Encode(Tcl_Interp *interp, int objc, } } /*------------------------------------------------------------------------*/ - /* >>> option_3 is set by two values depending on the symbology */ + /* >>> option_3 is set by three values depending on the symbology */ /* On wrong symbology, the option is ignored(as does the zint program)*/ - if (fFullMultiByte && ZBarcode_Cap(hSymbol->symbology, ZINT_CAP_FULL_MULTIBYTE)) { - hSymbol->option_3 = ZINT_FULL_MULTIBYTE; - } else if (Separator && ZBarcode_Cap(hSymbol->symbology, ZINT_CAP_STACKABLE)) { - hSymbol->option_3 = Separator; - } + if (fFullMultiByte && ZBarcode_Cap(hSymbol->symbology, ZINT_CAP_FULL_MULTIBYTE)) { + hSymbol->option_3 = ZINT_FULL_MULTIBYTE; + } + if (Mask && ZBarcode_Cap(hSymbol->symbology, ZINT_CAP_MASK)) { + hSymbol->option_3 |= Mask << 8; + } + if (Separator && ZBarcode_Cap(hSymbol->symbology, ZINT_CAP_STACKABLE)) { + hSymbol->option_3 = Separator; + } /*------------------------------------------------------------------------*/ /* >>> option_2 is set by two values depending on the symbology */ /* On wrong symbology, the option is ignored(as does the zint program)*/ diff --git a/docs/manual.txt b/docs/manual.txt index 13494e7c..f0364ecb 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -1259,6 +1259,7 @@ ZINT_CAP_FIXED_RATIO | Does the symbology have a fixed width-to-height | (aspect) ratio? ZINT_CAP_READER_INIT | Does the symbology support Reader Initialisation? ZINT_CAP_FULL_MULTIBYTE | Is the ZINT_FULL_MULTIBYTE option applicable? +ZINT_CAP_MASK | Is mask selection applicable? ------------------------------------------------------------------------------- For example: @@ -2172,6 +2173,12 @@ Non-ASCII data density may be maximized by using the --fullmultibyte switch or by setting option_3 to ZINT_FULL_MULTIBYTE, but check that your barcode reader supports this before using. +QR Code has eight different masks designed to minimize unwanted patterns. The +best mask to use is selected automatically by Zint but may be manually specified +by using the --mask= switch with values 0-7, or by setting option_3 to +(N + 1) << 8 where N is 0-7. To use with ZINT_FULL_MULTIBYTE set option_3 = +ZINT_FULL_MULTIBYTE | (N + 1) << 8. + 6.6.3 Micro QR Code (ISO 18004) ------------------------------- A miniature version of the QR Code symbol for short messages. ECC levels can be @@ -2195,6 +2202,12 @@ Input | Version | Symbol Size For barcode readers that support it, non-ASCII data density may be maximized by using the --fullmultibyte switch or by setting option_3 to ZINT_FULL_MULTIBYTE. +Micro QR Code has four different masks designed to minimize unwanted patterns. +The best mask to use is selected automatically by Zint but may be manually +specified by using the --mask= switch with values 0-3, or by setting option_3 +to (N + 1) << 8 where N is 0-3. To use with ZINT_FULL_MULTIBYTE set option_3 = +ZINT_FULL_MULTIBYTE | (N + 1) << 8. + 6.6.4 Rectangular Micro QR Code (rMQR) -------------------------------------- A rectangular version of QR Code. Like QR code rMQR supports encoding of GS1 @@ -2426,7 +2439,7 @@ Annex A. A matrix symbology developed by Ted Williams in 1992 which encodes data in a way similar to Data Matrix. Code One is able to encode the Latin-1 character set or GS1 data. There are two types of Code One symbol - variable -height symbols which are roughly square (versions A thought to H) and +height symbols which are roughly square (versions A through to H) and fixed-height versions (version S and T). These can be selected by using --vers= or setting option_2 as shown in the table below: @@ -2623,6 +2636,12 @@ Non-ASCII data density may be maximized by using the --fullmultibyte switch or by setting option_3 to ZINT_FULL_MULTIBYTE, but check that your barcode reader supports this before using. +Han Xin has four different masks designed to minimize unwanted patterns. The +best mask to use is selected automatically by Zint but may be manually specified +by using the --mask= switch with values 0-3, or by setting option_3 to +(N + 1) << 8 where N is 0-3. To use with ZINT_FULL_MULTIBYTE set option_3 = +ZINT_FULL_MULTIBYTE | (N + 1) << 8. + 6.6.13 Ultracode ---------------- This symbology uses a grid of coloured elements to encode data. ECI and GS1 diff --git a/frontend/main.c b/frontend/main.c index 8b1692cc..5da27f6b 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -124,6 +124,7 @@ static void usage(void) { " --height=NUMBER Set height of symbol in multiples of X-dimension\n" " -i, --input=FILE Read input data from FILE\n" " --init Create reader initialisation/programming symbol\n" + " --mask=NUMBER Set masking pattern to use (QR/Han Xin)\n" " --mirror Use batch data to determine filename\n" " --mode=NUMBER Set encoding mode (Maxicode/Composite)\n" " --nobackground Remove background (PNG/SVG/EPS only)\n" @@ -484,6 +485,7 @@ int main(int argc, char **argv) { int batch_mode = 0; int mirror_mode = 0; int fullmultibyte = 0; + int mask = 0; int separator = 0; int addon_gap = 0; char filetype[4] = {0}; @@ -539,6 +541,7 @@ int main(int argc, char **argv) { {"init", 0, 0, 0}, {"input", 1, 0, 'i'}, {"mirror", 0, 0, 0}, + {"mask", 1, 0, 0}, {"mode", 1, 0, 0}, {"nobackground", 0, 0, 0}, {"notext", 0, 0, 0}, @@ -609,6 +612,20 @@ int main(int argc, char **argv) { if (!strcmp(long_options[option_index].name, "fullmultibyte")) { fullmultibyte = 1; } + if (!strcmp(long_options[option_index].name, "mask")) { + error_number = validator(NESET, optarg); + if (error_number == ZINT_ERROR_INVALID_DATA) { + fprintf(stderr, "Error 148: Invalid mask value\n"); + exit(1); + } + mask = atoi(optarg) + 1; + if (mask <= 0 || mask > 8) { + /* Values >= 1 and <= 8 (i.e. mask pattern >= 0 and <= 7) only permitted */ + fprintf(stderr, "Warning 147: Invalid mask value\n"); + fflush(stderr); + mask = 0; + } + } if (!strcmp(long_options[option_index].name, "notext")) { my_symbol->show_hrt = 0; } @@ -941,10 +958,15 @@ int main(int argc, char **argv) { } if (data_arg_num) { - unsigned int cap = ZBarcode_Cap(my_symbol->symbology, ZINT_CAP_FULL_MULTIBYTE | ZINT_CAP_STACKABLE | ZINT_CAP_EXTENDABLE); + unsigned int cap = ZBarcode_Cap(my_symbol->symbology, ZINT_CAP_STACKABLE | ZINT_CAP_EXTENDABLE | + ZINT_CAP_FULL_MULTIBYTE | ZINT_CAP_MASK); if (fullmultibyte && (cap & ZINT_CAP_FULL_MULTIBYTE)) { my_symbol->option_3 = ZINT_FULL_MULTIBYTE; - } else if (separator && (cap & ZINT_CAP_STACKABLE)) { + } + if (mask && (cap & ZINT_CAP_MASK)) { + my_symbol->option_3 |= mask << 8; + } + if (separator && (cap & ZINT_CAP_STACKABLE)) { my_symbol->option_3 = separator; } if (addon_gap && (cap & ZINT_CAP_EXTENDABLE)) { diff --git a/frontend/tests/test_args.c b/frontend/tests/test_args.c index 4ffc6dea..1d342841 100644 --- a/frontend/tests/test_args.c +++ b/frontend/tests/test_args.c @@ -174,6 +174,7 @@ static void test_dump_args(int index, int debug) { int dmre; int eci; int fullmultibyte; + int mask; int mode; char *primary; int rows; @@ -185,41 +186,45 @@ static void test_dump_args(int index, int debug) { }; // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { -1, "123", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "D2 13 9B 39 65 C8 C9 8E B" }, - /* 1*/ { BARCODE_CODE128, "123", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "D2 13 9B 39 65 C8 C9 8E B" }, - /* 2*/ { BARCODE_CODE128, "123", "456", NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "D2 13 9B 39 65 C8 C9 8E B\nD2 19 3B 72 67 4E 4D 8E B" }, - /* 3*/ { BARCODE_CODE128, "123", NULL, NULL, NULL, -1, -1, 1, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "Warning 141: Can't use batch mode if data given, ignoring\nD2 13 9B 39 65 C8 C9 8E B" }, - /* 4*/ { BARCODE_CODE128, NULL, NULL, "123\n45\n", NULL, -1, -1, 1, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "D2 13 9B 39 65 C8 C9 8E B\nD3 97 62 3B 63 AC" }, - /* 5*/ { BARCODE_CODE128, NULL, NULL, "123\n45\n", "7\n",-1, -1, 1, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "Warning 144: Processing first input file 'test_dump_args1.txt' only\nD2 13 9B 39 65 C8 C9 8E B\nD3 97 62 3B 63 AC" }, - /* 6*/ { BARCODE_CODE128, "\t", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "D0 90 D2 1A 63 AC" }, - /* 7*/ { BARCODE_CODE128, "\\t", NULL, NULL, NULL, ESCAPE_MODE, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "D0 90 D2 1A 63 AC" }, - /* 8*/ { BARCODE_CODE128, "123", NULL, NULL, NULL, -1, BARCODE_BIND | BARCODE_BOX | SMALL_TEXT | BOLD_TEXT | CMYK_COLOUR, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "D2 13 9B 39 65 C8 C9 8E B" }, - /* 9*/ { BARCODE_CODE128, "123", NULL, NULL, NULL, -1, BARCODE_DOTTY_MODE, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "Error 224: Selected symbology cannot be rendered as dots" }, - /* 10*/ { BARCODE_CODABLOCKF, "ABCDEF", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "D0 97 BA 86 51 88 B1 11 AC 46 D8 C7 58\nD0 97 BB 12 46 88 C5 1A 3C 55 CC C7 58" }, - /* 11*/ { BARCODE_CODABLOCKF, "ABCDEF", NULL, NULL, NULL, -1, -1, 0, 10, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "D0 97 BA 86 51 88 B1 11 AC 44 68 BC 98 EB\nD0 97 BB 12 46 2B BD 7B A3 47 8A 8D 18 EB" }, - /* 12*/ { BARCODE_CODABLOCKF, "ABCDEF", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, 3, -1, 0, -1, "D0 97 BA 58 51 88 B1 11 AC 46 36 C7 58\nD0 97 BB 12 46 88 C5 77 AF 74 62 C7 58\nD0 97 BA CE 5D EB DD 1A 3C 56 88 C7 58" }, - /* 13*/ { BARCODE_CODE11, NULL, NULL, "123", NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "B2 D6 96 CA B5 6D 64" }, - /* 14*/ { BARCODE_CODE11, NULL, NULL, "123", NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, 1, "B2 D6 96 CA B5 64" }, - /* 15*/ { BARCODE_CODE11, "123", NULL, "456", NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, 2, "B2 D6 96 CA B2\nB2 B6 DA 9A B2" }, - /* 16*/ { BARCODE_CODE11, "123", "456", "789", "012", -1, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, 2, "B2 D6 96 CA B2\nB2 B6 DA 9A B2\nB2 A6 D2 D5 64\nB2 AD AD 2D 64" }, - /* 17*/ { BARCODE_PDF417, "123", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, 1, 0, 0, -1, "FF 54 7A BC 3D 4F 1D 5C 0F E8 A4\nFF 54 7A 90 2F D3 1F AB 8F E8 A4\nFF 54 6A F8 3A BF 15 3C 0F E8 A4\nFF 54 57 9E 24 E7 1A F7 CF E8 A4\nFF 54 7A E7 3D 0D 9D 73 0F E8 A4\nFF 54 7D 70 B9 CB DF 5E CF E8 A4" }, - /* 18*/ { BARCODE_DATAMATRIX, "ABC", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "AA 8\nB3 4\n8F 0\nB2 C\nA6 0\nBA C\nD6 0\nEB 4\nE2 8\nFF C" }, - /* 19*/ { BARCODE_DATAMATRIX, "ABC", NULL, NULL, NULL, -1, READER_INIT, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "AA A\nAC 7\n8A 4\nA0 3\nC2 2\nB5 1\n82 2\nBA 7\n8C C\nA0 5\n86 A\nFF F" }, - /* 20*/ { BARCODE_DATAMATRIX, "ABCDEFGHIJK", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "AA AA AA AA\nA6 C7 FA F9\nB2 AA C7 BA\n98 BF F4 0F\nE8 DA 90 C8\nC7 D5 B6 DF\nC5 50 B0 2C\nFF FF FF FF" }, - /* 21*/ { BARCODE_DATAMATRIX, "ABCDEFGHIJK", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 1, -1, "AA AA\nA6 D3\nB2 DA\n99 19\nA8 A6\n84 F7\nC0 8C\nF9 87\nFC 4C\nD8 A5\n83 E6\n99 75\nF7 82\nAE 65\n8D 6A\nFF FF" }, - /* 22*/ { BARCODE_DATAMATRIX, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "AA AA A8\nA6 94 BC\nB2 AD F0\n99 08 F4\nA9 E1 B8\n86 81 CC\nC2 F5 88\nF5 D5 3C\nF2 68 30\nDA 7A BC\nB7 FE 70\nA8 E7 34\n91 40 88\nD6 33 DC\nD2 89 20\nD1 6A 94\nE2 71 A8\nE4 3E EC\nF2 9D 70\nE5 8D FC\nB9 56 50\nFF FF FC" }, - /* 23*/ { BARCODE_DATAMATRIX, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF", NULL, NULL, NULL, -1, -1, 0, -1, 1, -1, 0, -1, NULL, -1, -1, 0, -1, "AA AA AA AA AA AA AA AA\nA6 D9 C8 0B FC 57 F3 17\nB2 BA A7 CA C9 18 87 BE\n99 2F EF 2B F1 A1 B9 DF\nA8 84 99 CA CF 4A BF 14\n86 D5 D9 87 A4 EF F4 9F\n85 44 BF 22 E7 58 C6 8A\nFF FF FF FF FF FF FF FF" }, - /* 24*/ { BARCODE_DATAMATRIX, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF", NULL, NULL, NULL, -1, -1, 0, -1, 1, -1, 0, -1, NULL, -1, -1, 1, -1, "AA AA A8\nA6 94 BC\nB2 AD F0\n99 08 F4\nA9 E1 B8\n86 81 CC\nC2 F5 88\nF5 D5 3C\nF2 68 30\nDA 7A BC\nB7 FE 70\nA8 E7 34\n91 40 88\nD6 33 DC\nD2 89 20\nD1 6A 94\nE2 71 A8\nE4 3E EC\nF2 9D 70\nE5 8D FC\nB9 56 50\nFF FF FC" }, - /* 25*/ { BARCODE_DATAMATRIX, "[91]12[92]34", NULL, NULL, NULL, GS1_MODE, -1, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "AA A8\nFA 9C\nBC 00\nD7 84\nED E0\nA4 E4\nA7 40\n9D 3C\nBF 50\nFA 24\nB1 68\nE5 04\n92 70\nFF FC" }, - /* 26*/ { BARCODE_DATAMATRIX, "[91]12[92]34", NULL, NULL, NULL, GS1_MODE, GS1_GS_SEPARATOR, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "AA A8\nF9 DC\nBF 20\nD6 C4\nED 10\nA0 0C\nA7 C0\n96 5C\nBA 70\nBB A4\nE2 18\nDD 14\n9C 40\nFF FC" }, - /* 27*/ { BARCODE_DATAMATRIX, "[9\\x31]12[92]34", NULL, NULL, NULL, GS1_MODE | ESCAPE_MODE, GS1_GS_SEPARATOR, 0, -1, 0, -1, 0, -1, NULL, -1, -1, 0, -1, "AA A8\nF9 DC\nBF 20\nD6 C4\nED 10\nA0 0C\nA7 C0\n96 5C\nBA 70\nBB A4\nE2 18\nDD 14\n9C 40\nFF FC" }, - /* 28*/ { BARCODE_EANX_CC, "[91]12", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, "12345678+12", -1, -1, 0, -1, "DB BC D3 9C 44 E9 D2 2C 19 E7 A2 D8 A0 00 00 00\nDB 31 1C 9C C7 29 92 47 D9 E9 40 C8 A0 00 00 00\nDA 3B EB 10 AF 09 9A 18 9D 7D 82 E8 A0 00 00 00\n10 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00\n20 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00\n10 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00\n14 68 D1 A6 49 BD 55 C9 D4 22 48 B9 40 59 94 98" }, - /* 29*/ { BARCODE_EANX_CC, "[91]12", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, 2, "12345678+12", -1, -1, 0, -1, "D3 A3 E9 DB F5 C9 DB 43 D9 CB 98 D2 20 00 00 00\nD3 25 0F 11 E4 49 D3 51 F1 AC FC D6 20 00 00 00\nD1 33 48 19 39 E9 93 18 49 D8 98 D7 20 00 00 00\nD1 A6 FC DA 1C 49 9B C5 05 E2 84 D7 A0 00 00 00\n10 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00\n20 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00\n10 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00\n14 68 D1 A6 49 BD 55 C9 D4 22 48 B9 40 59 94 98" }, - /* 30*/ { BARCODE_QRCODE, "点", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, NULL, -1, 1, 0, -1, "FE 4B F8\n82 92 08\nBA 42 E8\nBA 92 E8\nBA 3A E8\n82 EA 08\nFE AB F8\n00 38 00\nFB CD 50\nA5 89 18\n0B 74 B8\nFC 81 A0\n92 34 B8\n00 DE 48\nFE AB 10\n82 5E 50\nBA C9 20\nBA C9 20\nBA F4 E0\n82 81 A0\nFE B4 E8" }, - /* 31*/ { BARCODE_QRCODE, "点", NULL, NULL, NULL, -1, -1, 0, -1, 0, 26, 0, -1, NULL, -1, 1, 0, -1, "FE 5B F8\n82 72 08\nBA DA E8\nBA 52 E8\nBA 2A E8\n82 0A 08\nFE AB F8\n00 D8 00\nEF F6 20\nB5 C2 28\n36 28 88\nFD 42 10\n62 2A C8\n00 95 70\nFE B7 38\n82 FD D8\nBA 97 00\nBA 43 60\nBA C8 C8\n82 C3 68\nFE EA F8" }, - /* 32*/ { BARCODE_QRCODE, "\223\137", NULL, NULL, NULL, DATA_MODE, -1, 0, -1, 0, -1, 0, -1, NULL, -1, 1, 0, -1, "FE 2B F8\n82 0A 08\nBA A2 E8\nBA 0A E8\nBA 5A E8\n82 72 08\nFE AB F8\n00 A0 00\nEF AE 20\n75 B5 20\n82 F7 58\nF4 9D C8\n5E 17 28\n00 C2 20\nFE 88 80\n82 82 38\nBA EA A8\nBA 55 50\nBA D7 68\n82 BD D0\nFE B7 78" }, - /* 33*/ { BARCODE_QRCODE, "\223\137", NULL, NULL, NULL, DATA_MODE, -1, 0, -1, 0, -1, 1, -1, NULL, -1, 1, 0, -1, "FE 4B F8\n82 92 08\nBA 42 E8\nBA 92 E8\nBA 3A E8\n82 EA 08\nFE AB F8\n00 38 00\nFB CD 50\nA5 89 18\n0B 74 B8\nFC 81 A0\n92 34 B8\n00 DE 48\nFE AB 10\n82 5E 50\nBA C9 20\nBA C9 20\nBA F4 E0\n82 81 A0\nFE B4 E8" }, - /* 34*/ { BARCODE_QRCODE, "\\x93\\x5F", NULL, NULL, NULL, DATA_MODE | ESCAPE_MODE, -1, 0, -1, 0, -1, 1, -1, NULL, -1, 1, 0, -1, "FE 4B F8\n82 92 08\nBA 42 E8\nBA 92 E8\nBA 3A E8\n82 EA 08\nFE AB F8\n00 38 00\nFB CD 50\nA5 89 18\n0B 74 B8\nFC 81 A0\n92 34 B8\n00 DE 48\nFE AB 10\n82 5E 50\nBA C9 20\nBA C9 20\nBA F4 E0\n82 81 A0\nFE B4 E8" }, + /* 0*/ { -1, "123", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "D2 13 9B 39 65 C8 C9 8E B" }, + /* 1*/ { BARCODE_CODE128, "123", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "D2 13 9B 39 65 C8 C9 8E B" }, + /* 2*/ { BARCODE_CODE128, "123", "456", NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "D2 13 9B 39 65 C8 C9 8E B\nD2 19 3B 72 67 4E 4D 8E B" }, + /* 3*/ { BARCODE_CODE128, "123", NULL, NULL, NULL, -1, -1, 1, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "Warning 141: Can't use batch mode if data given, ignoring\nD2 13 9B 39 65 C8 C9 8E B" }, + /* 4*/ { BARCODE_CODE128, NULL, NULL, "123\n45\n", NULL, -1, -1, 1, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "D2 13 9B 39 65 C8 C9 8E B\nD3 97 62 3B 63 AC" }, + /* 5*/ { BARCODE_CODE128, NULL, NULL, "123\n45\n", "7\n",-1, -1, 1, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "Warning 144: Processing first input file 'test_dump_args1.txt' only\nD2 13 9B 39 65 C8 C9 8E B\nD3 97 62 3B 63 AC" }, + /* 6*/ { BARCODE_CODE128, "\t", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "D0 90 D2 1A 63 AC" }, + /* 7*/ { BARCODE_CODE128, "\\t", NULL, NULL, NULL, ESCAPE_MODE, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "D0 90 D2 1A 63 AC" }, + /* 8*/ { BARCODE_CODE128, "123", NULL, NULL, NULL, -1, BARCODE_BIND | BARCODE_BOX | SMALL_TEXT | BOLD_TEXT | CMYK_COLOUR, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "D2 13 9B 39 65 C8 C9 8E B" }, + /* 9*/ { BARCODE_CODE128, "123", NULL, NULL, NULL, -1, BARCODE_DOTTY_MODE, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "Error 224: Selected symbology cannot be rendered as dots" }, + /* 10*/ { BARCODE_CODABLOCKF, "ABCDEF", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "D0 97 BA 86 51 88 B1 11 AC 46 D8 C7 58\nD0 97 BB 12 46 88 C5 1A 3C 55 CC C7 58" }, + /* 11*/ { BARCODE_CODABLOCKF, "ABCDEF", NULL, NULL, NULL, -1, -1, 0, 10, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "D0 97 BA 86 51 88 B1 11 AC 44 68 BC 98 EB\nD0 97 BB 12 46 2B BD 7B A3 47 8A 8D 18 EB" }, + /* 12*/ { BARCODE_CODABLOCKF, "ABCDEF", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, 3, -1, 0, -1, "D0 97 BA 58 51 88 B1 11 AC 46 36 C7 58\nD0 97 BB 12 46 88 C5 77 AF 74 62 C7 58\nD0 97 BA CE 5D EB DD 1A 3C 56 88 C7 58" }, + /* 13*/ { BARCODE_CODE11, NULL, NULL, "123", NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "B2 D6 96 CA B5 6D 64" }, + /* 14*/ { BARCODE_CODE11, NULL, NULL, "123", NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, 1, "B2 D6 96 CA B5 64" }, + /* 15*/ { BARCODE_CODE11, "123", NULL, "456", NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, 2, "B2 D6 96 CA B2\nB2 B6 DA 9A B2" }, + /* 16*/ { BARCODE_CODE11, "123", "456", "789", "012", -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, 2, "B2 D6 96 CA B2\nB2 B6 DA 9A B2\nB2 A6 D2 D5 64\nB2 AD AD 2D 64" }, + /* 17*/ { BARCODE_PDF417, "123", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, 1, 0, 0, -1, "FF 54 7A BC 3D 4F 1D 5C 0F E8 A4\nFF 54 7A 90 2F D3 1F AB 8F E8 A4\nFF 54 6A F8 3A BF 15 3C 0F E8 A4\nFF 54 57 9E 24 E7 1A F7 CF E8 A4\nFF 54 7A E7 3D 0D 9D 73 0F E8 A4\nFF 54 7D 70 B9 CB DF 5E CF E8 A4" }, + /* 18*/ { BARCODE_DATAMATRIX, "ABC", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "AA 8\nB3 4\n8F 0\nB2 C\nA6 0\nBA C\nD6 0\nEB 4\nE2 8\nFF C" }, + /* 19*/ { BARCODE_DATAMATRIX, "ABC", NULL, NULL, NULL, -1, READER_INIT, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "AA A\nAC 7\n8A 4\nA0 3\nC2 2\nB5 1\n82 2\nBA 7\n8C C\nA0 5\n86 A\nFF F" }, + /* 20*/ { BARCODE_DATAMATRIX, "ABCDEFGHIJK", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "AA AA AA AA\nA6 C7 FA F9\nB2 AA C7 BA\n98 BF F4 0F\nE8 DA 90 C8\nC7 D5 B6 DF\nC5 50 B0 2C\nFF FF FF FF" }, + /* 21*/ { BARCODE_DATAMATRIX, "ABCDEFGHIJK", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 1, -1, "AA AA\nA6 D3\nB2 DA\n99 19\nA8 A6\n84 F7\nC0 8C\nF9 87\nFC 4C\nD8 A5\n83 E6\n99 75\nF7 82\nAE 65\n8D 6A\nFF FF" }, + /* 22*/ { BARCODE_DATAMATRIX, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "AA AA A8\nA6 94 BC\nB2 AD F0\n99 08 F4\nA9 E1 B8\n86 81 CC\nC2 F5 88\nF5 D5 3C\nF2 68 30\nDA 7A BC\nB7 FE 70\nA8 E7 34\n91 40 88\nD6 33 DC\nD2 89 20\nD1 6A 94\nE2 71 A8\nE4 3E EC\nF2 9D 70\nE5 8D FC\nB9 56 50\nFF FF FC" }, + /* 23*/ { BARCODE_DATAMATRIX, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF", NULL, NULL, NULL, -1, -1, 0, -1, 1, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "AA AA AA AA AA AA AA AA\nA6 D9 C8 0B FC 57 F3 17\nB2 BA A7 CA C9 18 87 BE\n99 2F EF 2B F1 A1 B9 DF\nA8 84 99 CA CF 4A BF 14\n86 D5 D9 87 A4 EF F4 9F\n85 44 BF 22 E7 58 C6 8A\nFF FF FF FF FF FF FF FF" }, + /* 24*/ { BARCODE_DATAMATRIX, "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEF", NULL, NULL, NULL, -1, -1, 0, -1, 1, -1, 0, -1, -1, NULL, -1, -1, 1, -1, "AA AA A8\nA6 94 BC\nB2 AD F0\n99 08 F4\nA9 E1 B8\n86 81 CC\nC2 F5 88\nF5 D5 3C\nF2 68 30\nDA 7A BC\nB7 FE 70\nA8 E7 34\n91 40 88\nD6 33 DC\nD2 89 20\nD1 6A 94\nE2 71 A8\nE4 3E EC\nF2 9D 70\nE5 8D FC\nB9 56 50\nFF FF FC" }, + /* 25*/ { BARCODE_DATAMATRIX, "[91]12[92]34", NULL, NULL, NULL, GS1_MODE, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "AA A8\nFA 9C\nBC 00\nD7 84\nED E0\nA4 E4\nA7 40\n9D 3C\nBF 50\nFA 24\nB1 68\nE5 04\n92 70\nFF FC" }, + /* 26*/ { BARCODE_DATAMATRIX, "[91]12[92]34", NULL, NULL, NULL, GS1_MODE, GS1_GS_SEPARATOR, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "AA A8\nF9 DC\nBF 20\nD6 C4\nED 10\nA0 0C\nA7 C0\n96 5C\nBA 70\nBB A4\nE2 18\nDD 14\n9C 40\nFF FC" }, + /* 27*/ { BARCODE_DATAMATRIX, "[9\\x31]12[92]34", NULL, NULL, NULL, GS1_MODE | ESCAPE_MODE, GS1_GS_SEPARATOR, 0, -1, 0, -1, 0, -1, -1, NULL, -1, -1, 0, -1, "AA A8\nF9 DC\nBF 20\nD6 C4\nED 10\nA0 0C\nA7 C0\n96 5C\nBA 70\nBB A4\nE2 18\nDD 14\n9C 40\nFF FC" }, + /* 28*/ { BARCODE_EANX_CC, "[91]12", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, "12345678+12", -1, -1, 0, -1, "DB BC D3 9C 44 E9 D2 2C 19 E7 A2 D8 A0 00 00 00\nDB 31 1C 9C C7 29 92 47 D9 E9 40 C8 A0 00 00 00\nDA 3B EB 10 AF 09 9A 18 9D 7D 82 E8 A0 00 00 00\n10 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00\n20 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00\n10 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00\n14 68 D1 A6 49 BD 55 C9 D4 22 48 B9 40 59 94 98" }, + /* 29*/ { BARCODE_EANX_CC, "[91]12", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, 2, "12345678+12", -1, -1, 0, -1, "D3 A3 E9 DB F5 C9 DB 43 D9 CB 98 D2 20 00 00 00\nD3 25 0F 11 E4 49 D3 51 F1 AC FC D6 20 00 00 00\nD1 33 48 19 39 E9 93 18 49 D8 98 D7 20 00 00 00\nD1 A6 FC DA 1C 49 9B C5 05 E2 84 D7 A0 00 00 00\n10 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00\n20 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00\n10 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00\n14 68 D1 A6 49 BD 55 C9 D4 22 48 B9 40 59 94 98" }, + /* 30*/ { BARCODE_QRCODE, "点", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, 1, 0, -1, "FE 2B F8\n82 AA 08\nBA B2 E8\nBA 0A E8\nBA FA E8\n82 E2 08\nFE AB F8\n00 80 00\nD3 3B B0\n60 95 68\n7A B3 A0\n1D 0F 98\nAA D7 30\n00 E6 A8\nFE DA D0\n82 42 20\nBA 0E 38\nBA C7 18\nBA 17 68\n82 B9 40\nFE C5 28" }, + /* 31*/ { BARCODE_QRCODE, "点", NULL, NULL, NULL, -1, -1, 0, -1, 0, 26, 0, -1, -1, NULL, -1, 1, 0, -1, "FE 5B F8\n82 72 08\nBA DA E8\nBA 52 E8\nBA 2A E8\n82 0A 08\nFE AB F8\n00 D8 00\nEF F6 20\nB5 C2 28\n36 28 88\nFD 42 10\n62 2A C8\n00 95 70\nFE B7 38\n82 FD D8\nBA 97 00\nBA 43 60\nBA C8 C8\n82 C3 68\nFE EA F8" }, + /* 32*/ { BARCODE_QRCODE, "\223\137", NULL, NULL, NULL, DATA_MODE, -1, 0, -1, 0, -1, 0, -1, -1, NULL, -1, 1, 0, -1, "FE 2B F8\n82 0A 08\nBA A2 E8\nBA 0A E8\nBA 5A E8\n82 72 08\nFE AB F8\n00 A0 00\nEF AE 20\n75 B5 20\n82 F7 58\nF4 9D C8\n5E 17 28\n00 C2 20\nFE 88 80\n82 82 38\nBA EA A8\nBA 55 50\nBA D7 68\n82 BD D0\nFE B7 78" }, + /* 33*/ { BARCODE_QRCODE, "\223\137", NULL, NULL, NULL, DATA_MODE, -1, 0, -1, 0, -1, 1, -1, -1, NULL, -1, 1, 0, -1, "FE 2B F8\n82 AA 08\nBA B2 E8\nBA 0A E8\nBA FA E8\n82 E2 08\nFE AB F8\n00 80 00\nD3 3B B0\n60 95 68\n7A B3 A0\n1D 0F 98\nAA D7 30\n00 E6 A8\nFE DA D0\n82 42 20\nBA 0E 38\nBA C7 18\nBA 17 68\n82 B9 40\nFE C5 28" }, + /* 34*/ { BARCODE_QRCODE, "\\x93\\x5F", NULL, NULL, NULL, DATA_MODE | ESCAPE_MODE, -1, 0, -1, 0, -1, 1, -1, -1, NULL, -1, 1, 0, -1, "FE 2B F8\n82 AA 08\nBA B2 E8\nBA 0A E8\nBA FA E8\n82 E2 08\nFE AB F8\n00 80 00\nD3 3B B0\n60 95 68\n7A B3 A0\n1D 0F 98\nAA D7 30\n00 E6 A8\nFE DA D0\n82 42 20\nBA 0E 38\nBA C7 18\nBA 17 68\n82 B9 40\nFE C5 28" }, + /* 35*/ { BARCODE_QRCODE, "点", NULL, NULL, NULL, -1, -1, 0, -1, 0, -1, 0, 2, -1, NULL, -1, 1, 0, -1, "FE 4B F8\n82 92 08\nBA 42 E8\nBA 92 E8\nBA 3A E8\n82 EA 08\nFE AB F8\n00 38 00\nFB CD 50\nA5 89 18\n0B 74 B8\nFC 81 A0\n92 34 B8\n00 DE 48\nFE AB 10\n82 5E 50\nBA C9 20\nBA C9 20\nBA F4 E0\n82 81 A0\nFE B4 E8" }, + /* 36*/ { BARCODE_HANXIN, "é", NULL, NULL, NULL, DATA_MODE, -1, 0, -1, 0, -1, 1, -1, -1, NULL, -1, -1, 0, -1, "FE 8A FE\n80 28 02\nBE E8 FA\nA0 94 0A\nAE 3E EA\nAE D2 EA\nAE 74 EA\n00 AA 00\n15 B4 AA\n0B 48 74\nA2 4A A4\nB5 56 2C\nA8 5A A8\n9F 18 50\nAA 07 50\n00 A6 00\nFE 20 EA\n02 C2 EA\nFA C4 EA\n0A 42 0A\nEA 52 FA\nEA 24 02\nEA AA FE" }, + /* 37*/ { BARCODE_HANXIN, "é", NULL, NULL, NULL, DATA_MODE, -1, 0, -1, 0, -1, 1, 3, -1, NULL, -1, -1, 0, -1, "FE 16 FE\n80 E2 02\nBE C2 FA\nA0 A0 0A\nAE F6 EA\nAE 98 EA\nAE BA EA\n00 E0 00\n15 83 AA\n44 7E AE\n92 9C 78\n25 BF 08\n47 4B 8C\n0D F9 74\nAB E7 50\n00 3A 00\nFE C2 EA\n02 22 EA\nFA DA EA\n0A 22 0A\nEA B2 FA\nEA 9A 02\nEA E8 FE" }, + /* 38*/ { BARCODE_HANXIN, "é", NULL, NULL, NULL, DATA_MODE, -1, 0, -1, 0, -1, 1, 4, -1, NULL, -1, -1, 0, -1, "FE 8A FE\n80 28 02\nBE E8 FA\nA0 94 0A\nAE 3E EA\nAE D2 EA\nAE 74 EA\n00 AA 00\n15 B4 AA\n0B 48 74\nA2 4A A4\nB5 56 2C\nA8 5A A8\n9F 18 50\nAA 07 50\n00 A6 00\nFE 20 EA\n02 C2 EA\nFA C4 EA\n0A 42 0A\nEA 52 FA\nEA 24 02\nEA AA FE" }, }; int data_size = ARRAY_SIZE(data); @@ -252,6 +257,7 @@ static void test_dump_args(int index, int debug) { arg_bool(cmd, "--dmre", data[i].dmre); arg_int(cmd, "--eci=", data[i].eci); arg_bool(cmd, "--fullmultibyte", data[i].fullmultibyte); + arg_int(cmd, "--mask=", data[i].mask); arg_int(cmd, "--mode=", data[i].mode); arg_data(cmd, "--primary=", data[i].primary); arg_int(cmd, "--rows=", data[i].rows); @@ -262,7 +268,7 @@ static void test_dump_args(int index, int debug) { strcat(cmd, " 2>&1"); assert_nonnull(exec(cmd, buf, sizeof(buf) - 1, debug, i), "i:%d exec(%s) NULL\n", i, cmd); - assert_zero(strcmp(buf, data[i].expected), "i:%d buf (%s) != expected (%s)\n", i, buf, data[i].expected); + assert_zero(strcmp(buf, data[i].expected), "i:%d buf (%s) != expected (%s) (%s)\n", i, buf, data[i].expected, cmd); if (have_input1) { assert_zero(remove(input1_filename), "i:%d remove(%s) != 0 (%d)\n", i, input1_filename, errno); @@ -473,6 +479,7 @@ static void test_checks(int index, int debug) { int eci; char *filetype; int height; + int mask; int mode; int rotate; int rows; @@ -486,34 +493,35 @@ static void test_checks(int index, int debug) { }; // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) struct item data[] = { - /* 0*/ { -2, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 139: Invalid add-on gap value" }, - /* 1*/ { 6, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 140: Invalid add-on gap value" }, - /* 2*/ { -1, -2, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 107: Invalid border width value" }, - /* 3*/ { -1, 1001, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 108: Border width out of range" }, - /* 4*/ { -1, -1, -1, 0.009, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 106: Invalid dot radius value" }, - /* 5*/ { -1, -1, -2, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 131: Invalid columns value" }, - /* 6*/ { -1, -1, 68, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 111: Number of columns out of range" }, - /* 7*/ { -1, -1, -1, -1, -2, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 138: Invalid ECI value" }, - /* 8*/ { -1, -1, -1, -1, 1000000, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 118: Invalid ECI code" }, - /* 9*/ { -1, -1, -1, -1, -1, "jpg", -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 142: File type 'jpg' not supported, ignoring" }, - /* 10*/ { -1, -1, -1, -1, -1, NULL, -2, -1, -1, -1, -1, -1, -1, -1, -1, "Error 109: Invalid symbol height value" }, - /* 11*/ { -1, -1, -1, -1, -1, NULL, 0, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 110: Symbol height out of range" }, - /* 12*/ { -1, -1, -1, -1, -1, NULL, -1, -2, -1, -1, -1, -1, -1, -1, -1, "Error 136: Invalid mode value" }, - /* 13*/ { -1, -1, -1, -1, -1, NULL, -1, 7, -1, -1, -1, -1, -1, -1, -1, "Warning 116: Invalid mode" }, - /* 14*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -2, -1, -1, -1, -1, -1, -1, "Error 117: Invalid rotation value" }, - /* 15*/ { -1, -1, -1, -1, -1, NULL, -1, -1, 45, -1, -1, -1, -1, -1, -1, "Warning 137: Invalid rotation parameter" }, - /* 16*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -2, -1, -1, -1, -1, -1, "Error 132: Invalid rows value" }, - /* 17*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, 45, -1, -1, -1, -1, -1, "Warning 112: Number of rows out of range" }, - /* 18*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -2, -1, -1, -1, -1, "Warning 105: Invalid scale value" }, - /* 19*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, 0.49, -1, -1, -1, -1, "Warning 146: Scaling less than 0.5 will be set to 0.5 for 'png' output" }, - /* 20*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -2, -1, -1, -1, "Error 134: Invalid ECC value" }, - /* 21*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, 9, -1, -1, -1, "Warning 114: ECC level out of range" }, - /* 22*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -2, -1, -1, "Error 128: Invalid separator value" }, - /* 23*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, 5, -1, -1, "Warning 127: Invalid separator value" }, - /* 24*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -2, -1, "Error 133: Invalid version value" }, - /* 25*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, 85, -1, "Warning 113: Invalid version" }, - /* 26*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -2, "Error 120: Invalid whitespace value '-2'" }, - /* 27*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, 1001, "Warning 121: Whitespace value out of range" }, + /* 0*/ { -2, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 139: Invalid add-on gap value" }, + /* 1*/ { 6, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 140: Invalid add-on gap value" }, + /* 2*/ { -1, -2, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 107: Invalid border width value" }, + /* 3*/ { -1, 1001, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 108: Border width out of range" }, + /* 4*/ { -1, -1, -1, 0.009, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 106: Invalid dot radius value" }, + /* 5*/ { -1, -1, -2, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 131: Invalid columns value" }, + /* 6*/ { -1, -1, 68, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 111: Number of columns out of range" }, + /* 7*/ { -1, -1, -1, -1, -2, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 138: Invalid ECI value" }, + /* 8*/ { -1, -1, -1, -1, 1000000, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 118: Invalid ECI code" }, + /* 9*/ { -1, -1, -1, -1, -1, "jpg", -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 142: File type 'jpg' not supported, ignoring" }, + /* 10*/ { -1, -1, -1, -1, -1, NULL, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Error 109: Invalid symbol height value" }, + /* 11*/ { -1, -1, -1, -1, -1, NULL, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 110: Symbol height out of range" }, + /* 12*/ { -1, -1, -1, -1, -1, NULL, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, "Error 148: Invalid mask value" }, + /* 13*/ { -1, -1, -1, -1, -1, NULL, -1, 8, -1, -1, -1, -1, -1, -1, -1, -1, "Warning 147: Invalid mask value" }, + /* 14*/ { -1, -1, -1, -1, -1, NULL, -1, -1, 7, -1, -1, -1, -1, -1, -1, -1, "Warning 116: Invalid mode" }, + /* 15*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, "Error 117: Invalid rotation value" }, + /* 16*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, 45, -1, -1, -1, -1, -1, -1, "Warning 137: Invalid rotation parameter" }, + /* 17*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -2, -1, -1, -1, -1, -1, "Error 132: Invalid rows value" }, + /* 18*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, 45, -1, -1, -1, -1, -1, "Warning 112: Number of rows out of range" }, + /* 19*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -2, -1, -1, -1, -1, "Warning 105: Invalid scale value" }, + /* 20*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, 0.49, -1, -1, -1, -1, "Warning 146: Scaling less than 0.5 will be set to 0.5 for 'png' output" }, + /* 21*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -2, -1, -1, -1, "Error 134: Invalid ECC value" }, + /* 22*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, "Warning 114: ECC level out of range" }, + /* 23*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -2, -1, -1, "Error 128: Invalid separator value" }, + /* 24*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, "Warning 127: Invalid separator value" }, + /* 25*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, "Error 133: Invalid version value" }, + /* 26*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, 85, -1, "Warning 113: Invalid version" }, + /* 27*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, "Error 120: Invalid whitespace value '-2'" }, + /* 28*/ { -1, -1, -1, -1, -1, NULL, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1001, "Warning 121: Whitespace value out of range" }, }; int data_size = ARRAY_SIZE(data); @@ -537,6 +545,7 @@ static void test_checks(int index, int debug) { arg_int(cmd, "--eci=", data[i].eci); arg_data(cmd, "--filetype=", data[i].filetype); arg_int(cmd, "--height=", data[i].height); + arg_int(cmd, "--mask=", data[i].mask); arg_int(cmd, "--mode=", data[i].mode); arg_int(cmd, "--rotate=", data[i].rotate); arg_int(cmd, "--rows=", data[i].rows); diff --git a/frontend_qt/grpHX.ui b/frontend_qt/grpHX.ui index 5effb1a8..2675c24e 100644 --- a/frontend_qt/grpHX.ui +++ b/frontend_qt/grpHX.ui @@ -503,6 +503,48 @@ + + + + &Mask: + + + cmbHXMask + + + + + + + 4 + + + + Automatic + + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + diff --git a/frontend_qt/grpMQR.ui b/frontend_qt/grpMQR.ui index 377497a8..de624693 100644 --- a/frontend_qt/grpMQR.ui +++ b/frontend_qt/grpMQR.ui @@ -94,6 +94,48 @@ + + + + &Mask: + + + cmbMQRMask + + + + + + + 4 + + + + Automatic + + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + diff --git a/frontend_qt/grpQR.ui b/frontend_qt/grpQR.ui index 2b0651bd..2c472595 100644 --- a/frontend_qt/grpQR.ui +++ b/frontend_qt/grpQR.ui @@ -283,6 +283,68 @@ + + + + &Mask: + + + cmbQRMask + + + + + + + 8 + + + + Automatic + + + + + 0 + + + + + 1 + + + + + 2 + + + + + 3 + + + + + 4 + + + + + 5 + + + + + 6 + + + + + 7 + + + + @@ -345,7 +407,7 @@ 20 - 43 + 20 diff --git a/frontend_qt/mainwindow.cpp b/frontend_qt/mainwindow.cpp index 7ee7daea..ad905eb7 100644 --- a/frontend_qt/mainwindow.cpp +++ b/frontend_qt/mainwindow.cpp @@ -811,6 +811,7 @@ void MainWindow::change_options() tabMain->insertTab(1,m_optionWidget,tr("QR Cod&e")); connect(m_optionWidget->findChild("cmbQRSize"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(m_optionWidget->findChild("cmbQRECC"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); + connect(m_optionWidget->findChild("cmbQRMask"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(m_optionWidget->findChild("radQRStand"), SIGNAL(clicked( bool )), SLOT(update_preview())); connect(m_optionWidget->findChild("radQRGS1"), SIGNAL(clicked( bool )), SLOT(update_preview())); connect(m_optionWidget->findChild("radQRHIBC"), SIGNAL(clicked( bool )), SLOT(update_preview())); @@ -842,6 +843,7 @@ void MainWindow::change_options() tabMain->insertTab(1,m_optionWidget,tr("Han Xin Cod&e")); connect(m_optionWidget->findChild("cmbHXSize"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(m_optionWidget->findChild("cmbHXECC"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); + connect(m_optionWidget->findChild("cmbHXMask"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(m_optionWidget->findChild("chkHXFullMultibyte"), SIGNAL(stateChanged( int )), SLOT(update_preview())); } @@ -855,6 +857,7 @@ void MainWindow::change_options() tabMain->insertTab(1,m_optionWidget,tr("Micro QR Cod&e")); connect(m_optionWidget->findChild("cmbMQRSize"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(m_optionWidget->findChild("cmbMQRECC"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); + connect(m_optionWidget->findChild("cmbMQRMask"), SIGNAL(currentIndexChanged( int )), SLOT(update_preview())); connect(m_optionWidget->findChild("chkMQRFullMultibyte"), SIGNAL(stateChanged( int )), SLOT(update_preview())); } @@ -1424,8 +1427,12 @@ void MainWindow::update_preview() if (item_val) { m_bc.bc.setSecurityLevel(item_val); } + item_val = m_optionWidget->findChild("cmbQRMask")->currentIndex(); + if (item_val) { + m_bc.bc.setOption3((item_val << 8) | m_bc.bc.option3()); + } if (m_optionWidget->findChild("chkQRFullMultibyte")->isChecked()) { - m_bc.bc.setOption3(ZINT_FULL_MULTIBYTE); + m_bc.bc.setOption3(ZINT_FULL_MULTIBYTE | m_bc.bc.option3()); } break; @@ -1439,8 +1446,12 @@ void MainWindow::update_preview() if (item_val) { m_bc.bc.setSecurityLevel(item_val); } + item_val = m_optionWidget->findChild("cmbMQRMask")->currentIndex(); + if (item_val) { + m_bc.bc.setOption3((item_val << 8) | m_bc.bc.option3()); + } if (m_optionWidget->findChild("chkMQRFullMultibyte")->isChecked()) { - m_bc.bc.setOption3(ZINT_FULL_MULTIBYTE); + m_bc.bc.setOption3(ZINT_FULL_MULTIBYTE | m_bc.bc.option3()); } break; @@ -1522,8 +1533,12 @@ void MainWindow::update_preview() if (item_val) { m_bc.bc.setSecurityLevel(item_val); } + item_val = m_optionWidget->findChild("cmbHXMask")->currentIndex(); + if (item_val) { + m_bc.bc.setOption3((item_val << 8) | m_bc.bc.option3()); + } if (m_optionWidget->findChild("chkHXFullMultibyte")->isChecked()) { - m_bc.bc.setOption3(ZINT_FULL_MULTIBYTE); + m_bc.bc.setOption3(ZINT_FULL_MULTIBYTE | m_bc.bc.option3()); } break; @@ -1951,6 +1966,7 @@ void MainWindow::save_sub_settings(QSettings &settings, int symbology) { case BARCODE_HIBC_QR: settings.setValue("studio/bc/qrcode/size", get_combobox_index("cmbQRSize")); settings.setValue("studio/bc/qrcode/ecc", get_combobox_index("cmbQRECC")); + settings.setValue("studio/bc/qrcode/mask", get_combobox_index("cmbQRMask")); settings.setValue("studio/bc/qrcode/encoding_mode", get_button_group_index(QStringList() << "radDM200Stand" << "radQRGS1" << "radQRHIBC")); settings.setValue("studio/bc/qrcode/chk_full_multibyte", get_checkbox_val("chkQRFullMultibyte")); break; @@ -1965,12 +1981,14 @@ void MainWindow::save_sub_settings(QSettings &settings, int symbology) { case BARCODE_HANXIN: settings.setValue("studio/bc/hanxin/size", get_combobox_index("cmbHXSize")); settings.setValue("studio/bc/hanxin/ecc", get_combobox_index("cmbHXECC")); + settings.setValue("studio/bc/hanxin/mask", get_combobox_index("cmbHXMask")); settings.setValue("studio/bc/hanxin/chk_full_multibyte", get_checkbox_val("chkHXFullMultibyte")); break; case BARCODE_MICROQR: settings.setValue("studio/bc/microqr/size", get_combobox_index("cmbMQRSize")); settings.setValue("studio/bc/microqr/ecc", get_combobox_index("cmbMQRECC")); + settings.setValue("studio/bc/microqr/mask", get_combobox_index("cmbMQRMask")); settings.setValue("studio/bc/microqr/chk_full_multibyte", get_checkbox_val("chkMQRFullMultibyte")); break; @@ -2174,6 +2192,7 @@ void MainWindow::load_sub_settings(QSettings &settings, int symbology) { case BARCODE_HIBC_QR: set_combobox_from_setting(settings, "studio/bc/qrcode/size", "cmbQRSize"); set_combobox_from_setting(settings, "studio/bc/qrcode/ecc", "cmbQRECC"); + set_combobox_from_setting(settings, "studio/bc/qrcode/mask", "cmbQRMask"); set_radiobutton_from_setting(settings, "studio/bc/qrcode/encoding_mode", QStringList() << "radDM200Stand" << "radQRGS1" << "radQRHIBC"); set_checkbox_from_setting(settings, "studio/bc/qrcode/chk_full_multibyte", "chkQRFullMultibyte"); break; @@ -2188,12 +2207,14 @@ void MainWindow::load_sub_settings(QSettings &settings, int symbology) { case BARCODE_HANXIN: set_combobox_from_setting(settings, "studio/bc/hanxin/size", "cmbHXSize"); set_combobox_from_setting(settings, "studio/bc/hanxin/ecc", "cmbHXECC"); + set_combobox_from_setting(settings, "studio/bc/hanxin/mask", "cmbHXMask"); set_checkbox_from_setting(settings, "studio/bc/hanxin/chk_full_multibyte", "chkHXFullMultibyte"); break; case BARCODE_MICROQR: set_combobox_from_setting(settings, "studio/bc/microqr/size", "cmbMQRSize"); set_combobox_from_setting(settings, "studio/bc/microqr/ecc", "cmbMQRECC"); + set_combobox_from_setting(settings, "studio/bc/microqr/mask", "cmbMQRMask"); set_checkbox_from_setting(settings, "studio/bc/microqr/chk_full_multibyte", "chkMQRFullMultibyte"); break; diff --git a/frontend_qt/qzint.cpp b/frontend_qt/qzint.cpp index 335153ef..6408d2b5 100644 --- a/frontend_qt/qzint.cpp +++ b/frontend_qt/qzint.cpp @@ -173,6 +173,10 @@ namespace Zint { m_option_2 = option; } + int QZint::option3() const { + return m_option_3; + } + void QZint::setOption3(int option) { m_option_3 = option; } diff --git a/frontend_qt/qzint.h b/frontend_qt/qzint.h index 24240b0b..b04ec7ed 100644 --- a/frontend_qt/qzint.h +++ b/frontend_qt/qzint.h @@ -53,6 +53,7 @@ public: int option2() const; void setOption2(int option); + int option3() const; void setOption3(int option); float scale() const; diff --git a/win32/libzint.vcxproj b/win32/libzint.vcxproj index 383c2ae2..eebce9ad 100644 --- a/win32/libzint.vcxproj +++ b/win32/libzint.vcxproj @@ -199,6 +199,7 @@ + diff --git a/win32/vs2008/libzint.vcproj b/win32/vs2008/libzint.vcproj index 23a46c85..ba643f22 100644 --- a/win32/vs2008/libzint.vcproj +++ b/win32/vs2008/libzint.vcproj @@ -569,6 +569,10 @@ RelativePath="..\backend\reedsol.h" > + + diff --git a/win32/vs2015/libzint.vcxproj b/win32/vs2015/libzint.vcxproj index 37e7bfbf..57044f08 100644 --- a/win32/vs2015/libzint.vcxproj +++ b/win32/vs2015/libzint.vcxproj @@ -137,7 +137,7 @@ %(AdditionalDependencies) $(OutDir)zintd.dll - ..\..\lpng\build\Release;..\..\..\zlib;%(AdditionalLibraryDirectories) + ..\..\..\lpng\build\Release;..\..\..\zlib;%(AdditionalLibraryDirectories) libcmtd.lib;%(IgnoreSpecificDefaultLibraries) true Windows @@ -171,7 +171,7 @@ zlibd.lib;%(AdditionalDependencies) $(OutDir)zintd.dll - ..\..\lpng\build\Release;..\..\..\zlib;%(AdditionalLibraryDirectories) + ..\..\..\lpng\build\Release;..\..\..\zlib;%(AdditionalLibraryDirectories) libcmtd.lib;%(IgnoreSpecificDefaultLibraries) true Windows @@ -378,6 +378,7 @@ + diff --git a/win32/vs2015/vsx/libzintMD.vcxproj b/win32/vs2015/vsx/libzintMD.vcxproj index d37121fd..44529719 100644 --- a/win32/vs2015/vsx/libzintMD.vcxproj +++ b/win32/vs2015/vsx/libzintMD.vcxproj @@ -146,6 +146,7 @@ + diff --git a/win32/vs2015/zint.vcxproj b/win32/vs2015/zint.vcxproj index 21614006..c423272f 100644 --- a/win32/vs2015/zint.vcxproj +++ b/win32/vs2015/zint.vcxproj @@ -158,7 +158,7 @@ - d:\opt\lib;%(AdditionalLibraryDirectories) + ..\..\..\lpng\build\Release;%(AdditionalLibraryDirectories) @@ -179,7 +179,7 @@ - d:\opt\lib;%(AdditionalLibraryDirectories) + ..\..\..\lpng\build\Release;%(AdditionalLibraryDirectories) diff --git a/win32/vs2019/libzint.vcxproj b/win32/vs2019/libzint.vcxproj index 7800f6cb..be871c2b 100644 --- a/win32/vs2019/libzint.vcxproj +++ b/win32/vs2019/libzint.vcxproj @@ -199,6 +199,7 @@ +