diff --git a/backend/maxicode.c b/backend/maxicode.c index b6d109ea..535bae35 100644 --- a/backend/maxicode.c +++ b/backend/maxicode.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2010-2020 Robin Stuart + Copyright (C) 2010-2021 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -104,10 +104,13 @@ static void maxi_do_secondary_chk_even(unsigned char maxi_codeword[144], const i } /* Moves everything up so that a shift or latch can be inserted */ -static void maxi_bump(unsigned char set[], unsigned char character[], const int bump_posn) { +static void maxi_bump(unsigned char set[], unsigned char character[], const int bump_posn, int *p_length) { - memmove(set + bump_posn + 1, set + bump_posn, 143 - bump_posn); - memmove(character + bump_posn + 1, character + bump_posn, 143 - bump_posn); + if (bump_posn < 143) { + memmove(set + bump_posn + 1, set + bump_posn, 143 - bump_posn); + memmove(character + bump_posn + 1, character + bump_posn, 143 - bump_posn); + } + (*p_length)++; /* Increment length regardless to make sure too long always triggered */ } /* If the value is present in array, return the value, else return badvalue */ @@ -141,7 +144,7 @@ static int bestSurroundingSet(const int index, const int length, const unsigned /* Format text according to Appendix A */ static int maxi_text_process(unsigned char maxi_codeword[144], const int mode, const unsigned char in_source[], int length, - const int eci, const int scm_vv) { + const int eci, const int scm_vv, const int debug_print) { unsigned char set[144], character[144] = {0}; int i, count, current_set, padding_set; @@ -205,7 +208,7 @@ static int maxi_text_process(unsigned char maxi_codeword[144], const int mode, c /* FS */ set[i] = bestSurroundingSet(i, length, set, set12345, 5); if (set[i] == 5) { - character[i] = 32; + character[i] = 32; } } else if (character[i] == 29) { @@ -213,11 +216,11 @@ static int maxi_text_process(unsigned char maxi_codeword[144], const int mode, c set[i] = bestSurroundingSet(i, length, set, set12345, 5); if (set[i] == 5) { character[i] = 33; - } + } } else if (character[i] == 30) { /* RS */ - set[i] = bestSurroundingSet(i, length, set, set12345, 5); + set[i] = bestSurroundingSet(i, length, set, set12345, 5); if (set[i] == 5) { character[i] = 34; } @@ -245,7 +248,7 @@ static int maxi_text_process(unsigned char maxi_codeword[144], const int mode, c set[i] = bestSurroundingSet(i, length, set, set12, 2); if (set[i] == 2) { character[i] = 49; - } + } } else if (character[i] == 47) { /* Slash */ @@ -281,7 +284,7 @@ static int maxi_text_process(unsigned char maxi_codeword[144], const int mode, c count++; if (count == 9) { /* Nine digits in a row can be compressed */ - memset(set + i - 8, 6, 9); + memset(set + i - 8, 6, 9); /* Set set of nine digits to 6 */ count = 0; } } else { @@ -297,106 +300,97 @@ static int maxi_text_process(unsigned char maxi_codeword[144], const int mode, c if ((set[i] != current_set) && (set[i] != 6)) { switch (set[i]) { case 1: - if (i + 1 < 144 && set[i + 1] == 1) { - if (i + 2 < 144 && set[i + 2] == 1) { - if (i + 3 < 144 && set[i + 3] == 1) { - /* Latch A */ - maxi_bump(set, character, i); - character[i] = 63; - current_set = 1; - length++; + if (current_set == 2) { /* Set B */ + if (i + 1 < 144 && set[i + 1] == 1) { + if (i + 2 < 144 && set[i + 2] == 1) { + if (i + 3 < 144 && set[i + 3] == 1) { + /* Latch A */ + maxi_bump(set, character, i, &length); + character[i] = 63; /* Set B Latch A */ + current_set = 1; + i += 3; /* Next 3 Set A so skip over */ + if (debug_print) printf("LCHA "); + } else { + /* 3 Shift A */ + maxi_bump(set, character, i, &length); + character[i] = 57; /* Set B triple shift A */ + i += 2; /* Next 2 Set A so skip over */ + if (debug_print) printf("3SHA "); + } } else { - /* 3 Shift A */ - maxi_bump(set, character, i); - character[i] = 57; - length++; - i += 2; + /* 2 Shift A */ + maxi_bump(set, character, i, &length); + character[i] = 56; /* Set B double shift A */ + i++; /* Next Set A so skip over */ + if (debug_print) printf("2SHA "); } } else { - /* 2 Shift A */ - maxi_bump(set, character, i); - character[i] = 56; - length++; - i++; + /* Shift A */ + maxi_bump(set, character, i, &length); + character[i] = 59; /* Set A Shift B */ + if (debug_print) printf("SHA "); } - } else { - /* Shift A */ - maxi_bump(set, character, i); - character[i] = 59; - length++; + } else { /* All sets other than B only have latch */ + /* Latch A */ + maxi_bump(set, character, i, &length); + character[i] = 58; /* Sets C,D,E Latch A */ + current_set = 1; + if (debug_print) printf("LCHA "); } break; - case 2: - if (i + 1 < 144 && set[i + 1] == 2) { + case 2: /* Set B */ + if (current_set != 1 || (i + 1 < 144 && set[i + 1] == 2)) { /* If not Set A or next Set B */ /* Latch B */ - maxi_bump(set, character, i); - character[i] = 63; + maxi_bump(set, character, i, &length); + character[i] = 63; /* Sets A,C,D,E Latch B */ current_set = 2; - length++; - } else { + if (debug_print) printf("LCHB "); + } else { /* Only available from Set A */ /* Shift B */ - maxi_bump(set, character, i); - character[i] = 59; - length++; + maxi_bump(set, character, i, &length); + character[i] = 59; /* Set B Shift A */ + if (debug_print) printf("SHB "); } break; - case 3: - if (i + 3 < 144 && set[i + 1] == 3 && set[i + 2] == 3 && set[i + 3] == 3) { - /* Lock in C */ - maxi_bump(set, character, i); - character[i] = 60; - maxi_bump(set, character, i); - character[i] = 60; - current_set = 3; - length++; - i += 3; + case 3: /* Set C */ + case 4: /* Set D */ + case 5: /* Set E */ + /* If first and next 3 same set, or not first and previous and next 2 same set */ + if ((i == 0 && i + 3 < 144 && set[i + 1] == set[i] && set[i + 2] == set[i] + && set[i + 3] == set[i]) + || (i > 0 && set[i - 1] == set[i] && i + 2 < 144 && set[i + 1] == set[i] + && set[i + 2] == set[i])) { + /* Lock in C/D/E */ + if (i == 0) { + maxi_bump(set, character, i, &length); + character[i] = 60 + set[i] - 3; + i++; /* Extra bump */ + maxi_bump(set, character, i, &length); + character[i] = 60 + set[i] - 3; + i += 3; /* Next 3 same set so skip over */ + } else { + /* Add single Shift to previous Shift */ + maxi_bump(set, character, i - 1, &length); + character[i - 1] = 60 + set[i] - 3; + i += 2; /* Next 2 same set so skip over */ + } + current_set = set[i]; + if (debug_print) printf("LCK%c ", 'C' + set[i] - 3); } else { - /* Shift C */ - maxi_bump(set, character, i); - character[i] = 60; - length++; - } - break; - case 4: - if (i + 3 < 144 && set[i + 1] == 4 && set[i + 2] == 4 && set[i + 3] == 4) { - /* Lock in D */ - maxi_bump(set, character, i); - character[i] = 61; - maxi_bump(set, character, i); - character[i] = 61; - current_set = 4; - length++; - i += 3; - } else { - /* Shift D */ - maxi_bump(set, character, i); - character[i] = 61; - length++; - } - break; - case 5: - if (i + 3 < 144 && set[i + 1] == 5 && set[i + 2] == 5 && set[i + 3] == 5) { - /* Lock in E */ - maxi_bump(set, character, i); - character[i] = 62; - maxi_bump(set, character, i); - character[i] = 62; - current_set = 5; - length++; - i += 3; - } else { - /* Shift E */ - maxi_bump(set, character, i); - character[i] = 62; - length++; + /* Shift C/D/E */ + maxi_bump(set, character, i, &length); + character[i] = 60 + set[i] - 3; + if (debug_print) printf("SH%c ", 'C' + set[i] - 3); } break; } - i++; + i++; /* Allow for bump */ } i++; } while (i < 144); + if (debug_print) printf("\n"); + /* Number compression has not been forgotten! - It's handled below */ i = 0; do { @@ -423,39 +417,37 @@ static int maxi_text_process(unsigned char maxi_codeword[144], const int mode, c /* Insert ECI at the beginning of message if needed */ /* Encode ECI assignment numbers according to table 3 */ if (eci != 0) { - maxi_bump(set, character, 0); + maxi_bump(set, character, 0, &length); character[0] = 27; // ECI if (eci <= 31) { - maxi_bump(set, character, 1); + maxi_bump(set, character, 1, &length); character[1] = eci; - length += 2; } else if (eci <= 1023) { - maxi_bump(set, character, 1); - maxi_bump(set, character, 1); + maxi_bump(set, character, 1, &length); + maxi_bump(set, character, 1, &length); character[1] = 0x20 | ((eci >> 6) & 0x0F); character[2] = eci & 0x3F; - length += 3; } else if (eci <= 32767) { - maxi_bump(set, character, 1); - maxi_bump(set, character, 1); - maxi_bump(set, character, 1); + maxi_bump(set, character, 1, &length); + maxi_bump(set, character, 1, &length); + maxi_bump(set, character, 1, &length); character[1] = 0x30 | ((eci >> 12) & 0x07); character[2] = (eci >> 6) & 0x3F; character[3] = eci & 0x3F; - length += 4; } else { - maxi_bump(set, character, 1); - maxi_bump(set, character, 1); - maxi_bump(set, character, 1); - maxi_bump(set, character, 1); + maxi_bump(set, character, 1, &length); + maxi_bump(set, character, 1, &length); + maxi_bump(set, character, 1, &length); + maxi_bump(set, character, 1, &length); character[1] = 0x38 | ((eci >> 18) & 0x03); character[2] = (eci >> 12) & 0x3F; character[3] = (eci >> 6) & 0x3F; character[4] = eci & 0x3F; - length += 5; } } + if (debug_print) printf("Length: %d\n", length); + if (((mode == 2) || (mode == 3)) && (length > 84)) { return ZINT_ERROR_TOO_LONG; @@ -639,7 +631,7 @@ INTERNAL int maxicode(struct zint_symbol *symbol, unsigned char source[], int le printf("Mode: %d\n", mode); } - i = maxi_text_process(maxi_codeword, mode, source, length, symbol->eci, scm_vv); + i = maxi_text_process(maxi_codeword, mode, source, length, symbol->eci, scm_vv, symbol->debug & ZINT_DEBUG_PRINT); if (i == ZINT_ERROR_TOO_LONG) { strcpy(symbol->errtxt, "553: Input data too long"); return i; diff --git a/backend/raster.c b/backend/raster.c index 211b47b9..cc23b347 100644 --- a/backend/raster.c +++ b/backend/raster.c @@ -296,10 +296,6 @@ static void draw_bullseye(unsigned char *pixelbuf, int image_width, int image_he /* Central bullseye in Maxicode symbols */ float x = 14.5f * scaler; float y = 15.0f * scaler; - if (scaler < 10) { - x = 16.0f * scaler; - y = 16.5f * scaler; - } draw_circle(pixelbuf, image_width, image_height, x + xoffset, y + yoffset, (4.571f * scaler) + 1.0f, DEFAULT_INK); draw_circle(pixelbuf, image_width, image_height, x + xoffset, y + yoffset, (3.779f * scaler) + 1.0f, DEFAULT_PAPER); diff --git a/backend/tests/data/png/maxicode_0.5.png b/backend/tests/data/png/maxicode_0.5.png new file mode 100644 index 00000000..9fb5b4df Binary files /dev/null and b/backend/tests/data/png/maxicode_0.5.png differ diff --git a/backend/tests/test_maxicode.c b/backend/tests/test_maxicode.c index 9cdfa3be..e084041b 100644 --- a/backend/tests/test_maxicode.c +++ b/backend/tests/test_maxicode.c @@ -52,10 +52,10 @@ static void test_large(int index, int debug) { /* 1*/ { -1, -1, "1", 139, "", ZINT_ERROR_TOO_LONG, -1, -1 }, /* 2*/ { -1, -1, "A", 93, "", 0, 33, 30 }, /* 3*/ { -1, -1, "A", 94, "", ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 4*/ { -1, -1, "\001", 91, "", 0, 33, 30 }, - /* 5*/ { -1, -1, "\001", 92, "", ZINT_ERROR_TOO_LONG, -1, -1 }, - /* 6*/ { -1, -1, "\200", 91, "", 0, 33, 30 }, - /* 7*/ { -1, -1, "\200", 92, "", ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 4*/ { -1, -1, "\001", 90, "", 0, 33, 30 }, + /* 5*/ { -1, -1, "\001", 91, "", ZINT_ERROR_TOO_LONG, -1, -1 }, + /* 6*/ { -1, -1, "\200", 90, "", 0, 33, 30 }, + /* 7*/ { -1, -1, "\200", 91, "", ZINT_ERROR_TOO_LONG, -1, -1 }, /* 8*/ { 2, -1, "1", 126, "123456789123123", 0, 33, 30 }, /* 9*/ { 2, -1, "1", 127, "123456789123123", ZINT_ERROR_TOO_LONG, -1, -1 }, /* 10*/ { 2, -1, "A", 84, "123456789123123", 0, 33, 30 }, @@ -214,6 +214,8 @@ static void test_encode(int index, int generate, int debug) { testStart(""); + int do_bwipp = (debug & ZINT_DEBUG_TEST_BWIPP) && testUtilHaveGhostscript(); // Only do BWIPP test if asked, too slow otherwise + int ret; struct item { int input_mode; @@ -226,11 +228,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, -1, -1, "THIS IS A 93 CHARACTER CODE SET A MESSAGE THAT FILLS A MODE 4, UNAPPENDED, MAXICODE SYMBOL...", -1, "", 0, 33, 30, "ISO/IEC 16023:2000 Figure 2, same", + /* 0*/ { -1, -1, -1, "THIS IS A 93 CHARACTER CODE SET A MESSAGE THAT FILLS A MODE 4, UNAPPENDED, MAXICODE SYMBOL...", -1, "", 0, 33, 30, 1, "ISO/IEC 16023:2000 Figure 2, same", "011111010000001000001000100111" "000100000001000000001010000000" "001011001100100110110010010010" @@ -265,7 +268,7 @@ static void test_encode(int index, int generate, int debug) { "001001101111101101101010011100" "001011000000111101100100001000" }, - /* 1*/ { -1, 4, -1, "MaxiCode (19 chars)", -1, "", 0, 33, 30, "ISO/IEC 16023:2000 Figure H1 **NOT SAME** different encodation (figure uses '3 Shift A' among other differences)", + /* 1*/ { -1, 4, -1, "MaxiCode (19 chars)", -1, "", 0, 33, 30, 0, "ISO/IEC 16023:2000 Figure H1 **NOT SAME** different encodation (figure uses '3 Shift A' among other differences); BWIPP different encodation again", "001101011111011100000010101111" "101100010001001100010000001100" "101100001010001111001001111101" @@ -300,7 +303,7 @@ static void test_encode(int index, int generate, int debug) { "010110010110001110100000010100" "010011110011000001010111100111" }, - /* 2*/ { DATA_MODE | ESCAPE_MODE, 2, 96, "1Z00004951\\GUPSN\\G06X610\\G159\\G1234567\\G1/1\\G\\GY\\G634 ALPHA DR\\GPITTSBURGH\\GPA\\R\\E", -1, "152382802840001", 0, 33, 30, "ISO/IEC 16023:2000 Figure B2 **NOT SAME** uses different encodation (figure uses Latch B/Latch A instead of Shift B for '>\\R', and precedes PAD chars with Latch B)", + /* 2*/ { DATA_MODE | ESCAPE_MODE, 2, 96, "1Z00004951\\GUPSN\\G06X610\\G159\\G1234567\\G1/1\\G\\GY\\G634 ALPHA DR\\GPITTSBURGH\\GPA\\R\\E", -1, "152382802840001", 0, 33, 30, 0, "ISO/IEC 16023:2000 Figure B2 **NOT SAME** uses different encodation (figure uses Latch B/Latch A instead of Shift B for '>\\R', and precedes PAD chars with Latch B); BWIPP different encodation again", "110101110110111110111111101111" "010101010111000011011000010010" "110110110001001010101010010011" @@ -335,7 +338,7 @@ static void test_encode(int index, int generate, int debug) { "010110101101000001111000100110" "110110100000010000001011110011" }, - /* 3*/ { -1, 3, -1, "CEN", -1, "B1050056999", 0, 33, 30, "ISO/IEC 16023:2000 B.1 Example (primary only given, data arbitrary); verified manually against BWIP and tec-it", + /* 3*/ { -1, 3, -1, "CEN", -1, "B1050056999", 0, 33, 30, 1, "ISO/IEC 16023:2000 B.1 Example (primary only given, data arbitrary); verified manually against tec-it", "000000010101010101010101010111" "001011000000000000000000000010" "111001101010101010101010101000" @@ -370,7 +373,7 @@ static void test_encode(int index, int generate, int debug) { "010010001001110010000101000010" "010001011010000011010010011100" }, - /* 4*/ { UNICODE_MODE | ESCAPE_MODE, -1, -1, "Comité Européen de Normalisation\034rue de Stassart 36\034B-1050 BRUXELLES\034TEL +3225196811", -1, "", 0, 33, 30, "ISO/IEC 16023:2000 Example F.5 **NOT SAME** uses different encodation (2 Shift A among other things)", + /* 4*/ { UNICODE_MODE | ESCAPE_MODE, -1, -1, "Comité Européen de Normalisation\034rue de Stassart 36\034B-1050 BRUXELLES\034TEL +3225196811", -1, "", 0, 33, 30, 0, "ISO/IEC 16023:2000 Example F.5 **NOT SAME** uses different encodation (2 Shift A among other things); BWIPP different encodation again", "010010100010110000000100001111" "001010001100110110111110100110" "001010011100101010011100100000" @@ -405,7 +408,7 @@ static void test_encode(int index, int generate, int debug) { "001011110011100001001001101100" "000010111011111010110011000011" }, - /* 5*/ { -1, -1, -1, "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", -1, "", 0, 33, 30, "Numeric compaction, verified manually against BWIPP and tec-it", + /* 5*/ { -1, -1, -1, "999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999", -1, "", 0, 33, 30, 1, "Numeric compaction, verified manually against tec-it", "010111101101010111101101010111" "111011110110111011110110111010" "001111111101001111111101001100" @@ -440,115 +443,362 @@ static void test_encode(int index, int generate, int debug) { "111010101011001101111001011010" "011110011111000011101011111011" }, - /* 6*/ { -1, 5, -1, "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\037\237\240\242\243\244\245\246\247\251\255\256\266\225\226\227\230\231\232\233\234\235\236", 51, "", 0, 33, 30, "Mode 5 set E; single difference from BWIPP - Zint uses Latch B at end before padding instead of Latch A", + /* 6*/ { -1, 5, -1, "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\037\237\240\242\243\244\245\246\247\251\255\256\266\225\226\227\230\231\232\233\234\235\236", 51, "", 0, 33, 30, 1, "Mode 5 set E", "000000000000000000101010101011" - "100101010111111111000000001000" - "110010011100100111001001110001" - "010101010101011010101010101000" - "010110101010001101010110101000" + "100101010111111111000000001010" + "110010011100100111001001110010" + "010101010101011010101010101010" + "010110101010001101010110101001" "100011011000110101100011011000" "010101010101111111111111111110" "010111111111000000001010101010" "011100100111001001110010011101" - "010101011011110000001011111100" - "000000001111110010010011010100" - "101010100110000010001011100000" - "010101110010000000001101010100" + "010101011011110000001011111110" + "000000001111110010010001010110" + "101010100110000010001001100000" + "010101110010000000001101010111" "000000111000000000001000000010" "101010110100000000001110101011" "010101010000000000001001010100" "000000001000000000001000000001" - "101010100000000000001010101010" - "010101100000000000001001010100" + "101010100000000000001010101000" + "010101100000000000001001010110" "000000000000000000000000000000" "101010100100000000011110101010" - "101100110100000001110101100110" - "011100010010110101110111010011" - "110011100010110001001000101010" - "110001101111100011111110101000" - "111110010101110100010110100000" - "110001110000111101111111000011" - "111001000100001011001011011110" - "101010110110100001110011010011" - "100100100001001100000001100000" - "010101001001000001111101011111" - "110110111000001000001101100100" - "100100010010000000010001010111" + "101100110100000001110101110110" + "011000000010110101110111000011" + "110111000010110001001000011010" + "100001101111010001110110101000" + "111110011001100100010110010010" + "100011110000001110111011000001" + "111001000110000011101000011000" + "101110110100100001100011011111" + "101100010011001000110000101100" + "110101001101000000111101001111" + "100111110000101000000001110100" + "100101010010100000010101000111" }, - /* 7*/ { -1, 6, -1, "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\241\250\253\257\260\264\267\270\273\277\212\213\214\215\216\217\220\221\222\223\224", -1, "", 0, 33, 30, "Mode 6 set D; single difference from BWIPP as above - Zint uses Latch B at end before padding instead of Latch A", + /* 7*/ { -1, 6, -1, "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377\241\250\253\257\260\264\267\270\273\277\212\213\214\215\216\217\220\221\222\223\224", -1, "", 0, 33, 30, 1, "Mode 6 set D", "000000000000000000101010101011" - "100101010111111111000000001000" + "100101010111111111000000001010" "110010011100100111001001110001" - "010101010101010110101010101000" + "010101010101010110101010101010" "101010100000000001010110101000" "110110001101100001100011011000" "010101010101010111111111111111" "010101011111111100000000101000" "001001110010011100100111001001" - "010111110111110000000011111100" - "000011011011110010011101101000" - "101011101110000001000100110100" - "010101110000000000000001010100" + "010111110111110000000011111110" + "000001011011110010011101101011" + "101001101110000001000100110110" + "010101110000000000000001010110" "000000101000000000000000000010" "101010110100000000000110101010" "010101010000000000001001010100" "000000001000000000001000000011" - "101010100000000000001010101000" - "010101101100000000001001010110" + "101010100000000000001010101010" + "010101101100000000001001010111" "000000101000000000001000000010" "101010010110000000011010101001" "010101011100000000111101010100" "000000001110110111011000000011" "101010100110110001100110101010" - "010101010101010101011101101100" - "000000000000000000001000010000" - "101010101010101010100110000001" - "101000111111101000101010110100" - "010100110011011001101100111001" - "100101010011111101011110000010" - "111101110110111101001001010101" - "011110000010110111001011110110" - "001110010110111101101011110010" + "010101010101010101011001011100" + "000000000000000000001000000000" + "101010101010101010101010100010" + "101100011100101000011001110100" + "011100110000010001111110111110" + "101101100000111001011101001010" + "001100111110101100001101010101" + "011111001010000101000011000110" + "101111010010011100100011110010" }, - /* 8*/ { -1, 6, -1, "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\252\254\261\262\263\265\271\272\274\275\276\200\201\202\203\204\205\206\207\210\211", -1, "", 0, 33, 30, "Mode 6 set C; single difference from BWIPP as above - Zint uses Latch B at end before padding instead of Latch A", + /* 8*/ { -1, 6, -1, "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337\252\254\261\262\263\265\271\272\274\275\276\200\201\202\203\204\205\206\207\210\211", -1, "", 0, 33, 30, 1, "Mode 6 set C", "000000000000000000101010101011" - "100101010111111111000000001000" + "100101010111111111000000001010" "110010011100100111001001110001" - "010101010101010110101010101000" + "010101010101010110101010101010" "101010100000000001010110101000" "110110001101100001100011011000" "010101010101010111111111111111" "010101011111111100000000101000" "001001110010011100100111001001" - "010111111111110000000111111100" - "000011010111110010010001101000" - "101011101010000001001100110100" - "010101100000000000000101010100" + "010111111111110000000111111110" + "000001010111110010010001101011" + "101001101010000001001100110110" + "010101100000000000000101010110" "000000011000000000000100000010" "101010110100000000000010101010" "010101010000000000001001010100" "000000001000000000001000000011" - "101010100000000000001010101000" - "010101110000000000001001010110" + "101010100000000000001010101010" + "010101110000000000001001010111" "000000111100000000001100000010" "101010110000000000010110101001" "010101010100000000101101010100" "000000001010110101011000000011" "101010100010110001010110101010" - "010101010101010101011101101100" - "000000000000000000001000010000" - "101010101010101010100110000001" - "101000111111101000101010110100" - "010100110011011001101100111001" - "100101010011111101011110000010" - "111101110110111101001001010101" - "011110000010110111001011110110" - "001110010110111101101011110010" + "010101010101010101011001011100" + "000000000000000000001000000000" + "101010101010101010101010100010" + "101100011100101000011001110100" + "011100110000010001111110111110" + "101101100000111001011101001010" + "001100111110101100001101010101" + "011111001010000101000011000110" + "101111010010011100100011110010" + }, + /* 9*/ { UNICODE_MODE, 4, -1, "ABCDabcdAabcABabcABCabcABCDaABCabABCabcABCéa", -1, "", 0, 33, 30, 1, "Mode 4 LCHB SHA 2SHA 3SHA LCHA SHB LCHB 3SHA 3SHA SHD", + "110000000011000000000011000011" + "010000000001000000000001000000" + "111010011100100110011110100101" + "000000001100000000110000000000" + "000000000110000000110000000010" + "110110101100110110111101101100" + "110000110000000000001100000000" + "110000010000000000000100000000" + "111001101001111001111010011110" + "010101010011000000001000001100" + "000000000001000010001000011111" + "101010100110000000010010101000" + "010101000010000000000001010101" + "000000001000000000101000000000" + "101010100000000000010010101010" + "010101011000000000001101010110" + "000000001000000000001000000001" + "101010001000000000001010101000" + "010101001100000000001001010111" + "000000111000000000011000000010" + "101010101000000000001110101000" + "010101010110000000010101010100" + "000000001110001111001100000001" + "101010101111000001101110101000" + "010101010101010101011101000110" + "000000000000000000000000000110" + "101010101010101010101101100100" + "000010001010001010000101010000" + "101000000111100010010001111100" + "101001111000010101010110110010" + "011101111110011111011100001000" + "110001000010011110111101111000" + "011010011011111110001000000010" + }, + /* 10*/ { UNICODE_MODE, 4, -1, "ÀÁÂÃ1", -1, "", 0, 33, 30, 1, "Mode 4 LCKC LCHA", + "010101010101010101010101010111" + "000000000000000000000000000000" + "101010101010101010101010101010" + "010101010101010101010101010110" + "000000000000000000000000000001" + "101010101010101010101010101000" + "010101010101010101010101010110" + "000000000000000000000000000010" + "101010101010101010101010101001" + "010101011111110000111001010100" + "000000001111110010001000000000" + "101010101010000000011110101010" + "010101000100000000000101010110" + "000000110000000000000100000000" + "101010011000000000001110101000" + "010101110000000000001001010110" + "000000101000000000001000000010" + "101010000000000000001110101000" + "010101001100000000000001010111" + "000000100100000000001000000010" + "101010010000000000010110101011" + "010101011100000000001101010100" + "000000001010110101111100000011" + "101010101010110001111110101010" + "010101010101010101011111010111" + "000000000000000000001111010110" + "101010101010101010100000000010" + "111111110000111100000101000000" + "010110101111000011110101010100" + "101010100000010101011111101010" + "111101011010000011110101101010" + "010110101111010110101010111100" + "010100000000010110101010010100" + }, + /* 11*/ { UNICODE_MODE, 4, -1, "ÀÁÂÃ123456789", -1, "", 0, 33, 30, 1, "Mode 4 LCKC NS", + "111110110101010101010101010111" + "111010010000000000000000000000" + "000010011010101010101010101000" + "010101010101010101010101010100" + "000000000000000000000000000001" + "101010101010101010101010101010" + "010101010101010101010101010101" + "000000000000000000000000000000" + "101010101010101010101010101001" + "010101010111110000110001010110" + "000000000011110010010000000010" + "101010100110000000111010101010" + "010101011000000000001001010101" + "000000101000000000001000000000" + "101010000100000000000110101011" + "010101010000000000001101010110" + "000000001000000000001000000000" + "101010100000000000001010101000" + "010101100000000000001001010100" + "000000001000000000001100000010" + "101010110000000000011010101001" + "010101010100000000011001010100" + "000000001110110101111000000000" + "101010101010110001000110101010" + "010101010101010101010000101101" + "000000000000000000001110011100" + "101010101010101010100111100010" + "011101100110110110100011110010" + "010001101101001001100100011011" + "100011011110110000101000000010" + "101101111000011101010000100101" + "000000111100011110100001110000" + "101000000010100111001011110101" + }, + /* 12*/ { UNICODE_MODE, 4, -1, "àáâã1", -1, "", 0, 33, 30, 1, "Mode 4 LCKD LCHA", + "010101010101010101010101010111" + "000000000000000000000000000000" + "101010101010101010101010101010" + "010101010101010101010101010110" + "000000000000000000000000000001" + "101010101010101010101010101000" + "010101010101010101010101010110" + "000000000000000000000000000010" + "101010101010101010101010101001" + "010101010111110000111101010100" + "000000000011110010000100000000" + "101010101110000000010110101010" + "010101010100000000000001010110" + "000000000000000000000000000000" + "101010011000000000001010101000" + "010101110000000000001001010110" + "000000101000000000001000000010" + "101010000000000000001110101000" + "010101010000000000000001010111" + "000000110000000000001100000010" + "101010110110000000011010101011" + "010101010100000000011101010100" + "000000001110110111111100000011" + "101010101110110001001110101010" + "010101010101010101011111010111" + "000000000000000000001111010110" + "101010101010101010100000000010" + "111111110000111100000101000000" + "010110101111000011110101010100" + "101010100000010101011111101010" + "111101011010000011110101101010" + "010110101111010110101010111100" + "010100000000010110101010010100" + }, + /* 13*/ { UNICODE_MODE, 4, -1, "¢£¤¥1", -1, "", 0, 33, 30, 1, "Mode 4 LCKE LCHA", + "010101010101010101010101010111" + "000000000000000000000000000000" + "101010101010101010101010101010" + "010101010101010101010101010110" + "000000000000000000000000000001" + "101010101010101010101010101000" + "010101010101010101010101010110" + "000000000000000000000000000010" + "101010101010101010101010101001" + "010101010111110100110001010100" + "000000000101110110000100000000" + "101010101010000000011110101010" + "010101010110000000001001010110" + "000000010000000000111000000000" + "101010011000000000001110101000" + "010101111000000000001001010110" + "000000101000000000001000000010" + "101010000000000000001110101000" + "010101111000000000001101010111" + "000000111100000000111000000010" + "101010001100000000111110101011" + "010101011110000001011101010100" + "000000001010110001011100000011" + "101010101010110101101010101010" + "010101010101010101011111010111" + "000000000000000000001111010110" + "101010101010101010100000000010" + "111111110000111100000101000000" + "010110101111000011110101010100" + "101010100000010101011111101010" + "111101011010000011110101101010" + "010110101111010110101010111100" + "010100000000010110101010010100" + }, + /* 14*/ { UNICODE_MODE, 4, -1, "¢£¤¥123456789", -1, "", 0, 33, 30, 1, "Mode 4 LCKE NS", + "111110110101010101010101010111" + "111010010000000000000000000000" + "000010011010101010101010101000" + "010101010101010101010101010100" + "000000000000000000000000000001" + "101010101010101010101010101010" + "010101010101010101010101010101" + "000000000000000000000000000000" + "101010101010101010101010101001" + "010101011111110100111001010110" + "000000001001110110011100000010" + "101010100110000000111010101010" + "010101001010000000000101010101" + "000000001000000000110100000000" + "101010000100000000000110101011" + "010101011000000000001101010110" + "000000001000000000001000000000" + "101010100000000000001010101000" + "010101010100000000000101010100" + "000000010000000000111100000010" + "101010101100000000110010101001" + "010101010110000001001001010100" + "000000001110110001011000000000" + "101010101010110101010010101010" + "010101010101010101010000101101" + "000000000000000000001110011100" + "101010101010101010100111100010" + "011101100110110110100011110010" + "010001101101001001100100011011" + "100011011110110000101000000010" + "101101111000011101010000100101" + "000000111100011110100001110000" + "101000000010100111001011110101" + }, + /* 15*/ { UNICODE_MODE, 4, -1, "ABCDE12abcde1ÀÁÂ⣤¥1àáâãabcde123A123456789àáâ㢣¤¥abc", -1, "", 0, 33, 30, 1, "Mode 4 mixed sets", + "000000001111111100000000111111" + "000010100100111100000000111100" + "011100101110000000100111010100" + "001100000000111111110101010110" + "001100000000111100010101101001" + "101111011000101010011000110110" + "000000001111111100100010111110" + "000010101100000000111010111000" + "011100101110011110111101000010" + "000000001011001100010111111010" + "000000000001000010000111111000" + "110110001110000000011110101010" + "111101000010000000001101010101" + "111110110000000000100110010100" + "010101101000000000010111001001" + "010100110000000000001100001110" + "000000101000000000001000001110" + "101011110000000000001101101110" + "010101101000000000000001010101" + "000000000100000000010000000000" + "101010100000000000000110101000" + "010101010100000000000101010100" + "000000001010001011100000000011" + "101010101011000001011010101000" + "010101010101010101010101001001" + "000000000000000000000010100000" + "101010101010101010101111110001" + "001110011111110100100011111000" + "011001101011100100010000010101" + "010000011110010110000011110010" + "110111100111000100111111001011" + "100011000001110011101110101000" + "001001110010111101100100010001" }, }; int data_size = ARRAY_SIZE(data); char escaped[1024]; + char bwipp_buf[8192]; + char bwipp_msg[1024]; for (int i = 0; i < data_size; i++) { @@ -564,9 +814,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*/ { %s, %d, %d, \"%s\", %d, \"%s\", %s, %d, %d, \"%s\",\n", + printf(" /*%3d*/ { %s, %d, %d, \"%s\", %d, \"%s\", %s, %d, %d, %d, \"%s\",\n", i, testUtilInputModeName(data[i].input_mode), data[i].option_1, data[i].option_2, testUtilEscape(data[i].data, length, escaped, sizeof(escaped)), data[i].length, - data[i].primary, testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].comment); + data[i].primary, testUtilErrorName(data[i].ret), symbol->rows, symbol->width, data[i].bwipp_cmp, data[i].comment); testUtilModulesPrint(symbol, " ", "\n"); printf(" },\n"); } else { @@ -577,6 +827,19 @@ static void test_encode(int index, int generate, int debug) { int width, row; ret = testUtilModulesCmp(symbol, data[i].expected, &width, &row); assert_zero(ret, "i:%d testUtilModulesCmp ret %d != 0 width %d row %d (%s)\n", i, ret, width, row, data[i].data); + + if (do_bwipp && testUtilCanBwipp(i, symbol, data[i].option_1, data[i].option_2, -1, debug)) { + if (!data[i].bwipp_cmp) { + if (debug & ZINT_DEBUG_TEST_PRINT) printf("i:%d %s not BWIPP compatible (%s)\n", i, testUtilBarcodeName(symbol->symbology), data[i].comment); + } else { + ret = testUtilBwipp(i, symbol, data[i].option_1, data[i].option_2, -1, data[i].data, length, data[i].primary, 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); + } + } } } @@ -699,6 +962,7 @@ static void test_fuzz(int index, int debug) { /* 2*/ { -1, "AaAaAaAaAaAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA123456789A", -1, ZINT_ERROR_TOO_LONG }, /* 3*/ { -1, "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", -1, ZINT_ERROR_TOO_LONG }, /* 4*/ { 32768, "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678", -1, ZINT_ERROR_TOO_LONG }, + /* 5*/ { -1, "AaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAaAa", -1, ZINT_ERROR_TOO_LONG }, }; int data_size = ARRAY_SIZE(data); diff --git a/backend/tests/test_png.c b/backend/tests/test_png.c index 18c66423..f7b734eb 100644 --- a/backend/tests/test_png.c +++ b/backend/tests/test_png.c @@ -172,6 +172,7 @@ static void test_print(int index, int generate, int debug) { /* 36*/ { BARCODE_ULTRA, -1, -1, -1, 2, -1, -1, -1, 0, 0, "0000007F", "FF0000", "12345", "", "../data/png/ultra_fgalpha.png", "" }, /* 37*/ { BARCODE_ULTRA, -1, -1, -1, -1, -1, -1, -1, 0, 0, "0000007F", "", "12345", "", "../data/png/ultra_fgalpha_nobg.png", "" }, /* 38*/ { BARCODE_ULTRA, -1, -1, -1, -1, -1, -1, -1, 0, 0.5f, "", "", "1", "", "../data/png/ultra_odd.png", "" }, + /* 39*/ { BARCODE_MAXICODE, -1, -1, -1, -1, -1, -1, -1, 0, 0.5f, "", "", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "", "../data/png/maxicode_0.5.png", "" }, }; int data_size = ARRAY_SIZE(data); diff --git a/backend/tests/testcommon.c b/backend/tests/testcommon.c index 8b01b2bf..5610b700 100644 --- a/backend/tests/testcommon.c +++ b/backend/tests/testcommon.c @@ -1789,7 +1789,7 @@ static const char *testUtilBwippName(int index, const struct zint_symbol *symbol { "", -1, 54, 0, 0, 0, 0, 0, }, { "pdf417", BARCODE_PDF417, 55, 1, 1, 0, 0, 0, }, { "pdf417compact", BARCODE_PDF417COMP, 56, 1, 1, 0, 0, 0, }, - { "maxicode", BARCODE_MAXICODE, 57, 0, 0, 0, 0, 0, }, + { "maxicode", BARCODE_MAXICODE, 57, 1, 1, 0, 0, 0, }, { "qrcode", BARCODE_QRCODE, 58, 0, 0, 0, 0, 0, }, { "", -1, 59, 0, 0, 0, 0, 0, }, { "", BARCODE_CODE128B, 60, 0, 0, 0, 0, 0, }, @@ -2070,7 +2070,7 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int int symbology = symbol->symbology; int data_len = length == -1 ? (int) strlen(data) : length; int primary_len = primary ? (int) strlen(primary) : 0; - int max_data_len = 4 + primary_len + 1 + 1 + data_len * 4 + 32; /* 4 AI prefix + primary + '|' + leading zero + escaped data + fudge */ + int max_data_len = 4 + primary_len + 1 + 1 + data_len * 4 + 64; /* 4 AI prefix + primary + '|' + leading zero + escaped data + fudge */ int eci_length = get_eci_length(symbol->eci, (const unsigned char *) data, data_len); char converted[eci_length + 1]; @@ -2106,7 +2106,11 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int } for (r = 0; r < symbol->rows; r++) { - bwipp_row_height[r] = symbol->row_height[r] ? symbol->row_height[r] : linear_row_height; + if (symbology == BARCODE_MAXICODE) { + bwipp_row_height[r] = 1; + } else { + bwipp_row_height[r] = symbol->row_height[r] ? symbol->row_height[r] : linear_row_height; + } //fprintf(stderr, "bwipp_row_height[%d] %d, symbol->row_height[%d] %d\n", r, bwipp_row_height[r], r, symbol->row_height[r]); } if (symbology == BARCODE_DBAR_EXP) { @@ -2388,6 +2392,71 @@ int testUtilBwipp(int index, const struct zint_symbol *symbol, int option_1, int sprintf(bwipp_opts_buf + (int) strlen(bwipp_opts_buf), "%sversion=%s", strlen(bwipp_opts_buf) ? " " : "", codeone_version); bwipp_opts = bwipp_opts_buf; } + } else if (symbology == BARCODE_MAXICODE) { + int have_scm = memcmp(bwipp_data, "[)>^03001^02996", 15) == 0; + int mode = option_1; + if (mode <= 0) { + if (primary_len == 0) { + mode = 4; + } else { + for (int i = 0; i < primary_len - 6; i++) { + if (((symbol->primary[i] < '0') || (symbol->primary[i] > '9')) && (symbol->primary[i] != ' ')) { + mode = 3; + break; + } + } + } + } + if (mode > 0) { + sprintf(bwipp_opts_buf + (int) strlen(bwipp_opts_buf), "%smode=%d", strlen(bwipp_opts_buf) ? " " : "", mode); + bwipp_opts = bwipp_opts_buf; + } + if (primary_len) { + char prefix_buf[30]; + int prefix_len; + int postcode_len = primary_len - 6; + char postcode[10]; + if (postcode_len >= 10) postcode_len = 9; + memcpy(postcode, primary, postcode_len); + postcode[postcode_len] = '\0'; + if (mode == 2) { + for (int i = 0; i < postcode_len; i++) { + if (postcode[i] == ' ') { + postcode[i] = '\0'; + } + } + } else { + postcode[6] = '\0'; + for (int i = postcode_len; i < 6; i++) { + postcode[i] = ' '; + } + } + sprintf(prefix_buf, "%s^029%.3s^029%.3s^029", postcode, primary + primary_len - 6, primary + primary_len - 3); + prefix_len = (int) strlen(prefix_buf); + if (have_scm) { + memmove(bwipp_data + 15 + prefix_len, bwipp_data, strlen(bwipp_data) - 15 + 1); + memcpy(bwipp_data + 15, prefix_buf, prefix_len); + } else { + memmove(bwipp_data + prefix_len, bwipp_data, strlen(bwipp_data) + 1); + memcpy(bwipp_data, prefix_buf, prefix_len); + } + if (!parse) { + sprintf(bwipp_opts_buf + (int) strlen(bwipp_opts_buf), "%sparse", strlen(bwipp_opts_buf) ? " " : ""); + bwipp_opts = bwipp_opts_buf; + parse = 1; + } + } + if (option_2 > 0) { + char scm_vv_buf[16]; + sprintf(scm_vv_buf, "[)>^03001^029%02d", option_2); /* [)>\R01\Gvv */ + memmove(bwipp_data + 15, bwipp_data, strlen(bwipp_data) + 1); + memcpy(bwipp_data, scm_vv_buf, 15); + if (!parse) { + sprintf(bwipp_opts_buf + (int) strlen(bwipp_opts_buf), "%sparse", strlen(bwipp_opts_buf) ? " " : ""); + bwipp_opts = bwipp_opts_buf; + parse = 1; + } + } } } diff --git a/backend/tests/tools/bwipp_dump-barcode.ps.diff b/backend/tests/tools/bwipp_dump-barcode.ps.diff index 78497aeb..9ceeeade 100644 --- a/backend/tests/tools/bwipp_dump-barcode.ps.diff +++ b/backend/tests/tools/bwipp_dump-barcode.ps.diff @@ -1,5 +1,5 @@ ---- ../../../../postscriptbarcode/build/monolithic/barcode.ps 2021-02-22 18:33:57.673232608 +0000 -+++ ../tools/bwipp_dump.ps 2021-02-22 19:03:00.083067838 +0000 +--- ../../../../postscriptbarcode/build/monolithic/barcode.ps 2021-03-22 15:06:47.498155878 +0000 ++++ ../tools/bwipp_dump.ps 2021-03-27 03:44:50.998203506 +0000 @@ -26198,34 +26198,80 @@ pop } ifelse @@ -1052,7 +1052,7 @@ end -@@ -28810,3 +29270,183 @@ +@@ -28810,3 +29270,189 @@ % --END ENCODER hibcazteccode-- % --END TEMPLATE-- @@ -1113,7 +1113,13 @@ + +% pixs is renmatrix input +ret /pixs known { -+ /pixs ret /pixs get def ++ b (maxicode) eq { ++ /pixs 990 array def ++ 0 1 989 { pixs exch 0 put } for ++ ret /pixs get { pixs exch 1 put } forall ++ } { ++ /pixs ret /pixs get def ++ } ifelse + + /xs systemdict /xs known { systemdict /xs get cvi } { 0 } ifelse def + /xe systemdict /xe known { systemdict /xe get cvi } { 0 } ifelse def diff --git a/backend/tests/tools/bwipp_dump.ps.tar.xz b/backend/tests/tools/bwipp_dump.ps.tar.xz index 9b46582e..b276afff 100644 Binary files a/backend/tests/tools/bwipp_dump.ps.tar.xz and b/backend/tests/tools/bwipp_dump.ps.tar.xz differ diff --git a/backend/tests/tools/run_bwipp_tests.sh b/backend/tests/tools/run_bwipp_tests.sh index 330411ff..ca495fcc 100755 --- a/backend/tests/tools/run_bwipp_tests.sh +++ b/backend/tests/tools/run_bwipp_tests.sh @@ -28,6 +28,7 @@ run_bwipp_test "test_dmatrix" run_bwipp_test "test_dotcode" "encode" run_bwipp_test "test_gs1" "gs1_reduce" run_bwipp_test "test_imail" "encode" +run_bwipp_test "test_maxicode" "encode" run_bwipp_test "test_medical" "encode" run_bwipp_test "test_pdf417" "encode" run_bwipp_test "test_plessey" "encode"