diff --git a/backend/tests/data/print/emf/code128_aim.emf b/backend/tests/data/print/emf/code128_aim.emf index 18e06e11..8bc9b30f 100644 Binary files a/backend/tests/data/print/emf/code128_aim.emf and b/backend/tests/data/print/emf/code128_aim.emf differ diff --git a/backend/tests/data/print/emf/dotcode_aim_fig7.emf b/backend/tests/data/print/emf/dotcode_aim_fig7.emf index b687e6d5..05e65d47 100644 Binary files a/backend/tests/data/print/emf/dotcode_aim_fig7.emf and b/backend/tests/data/print/emf/dotcode_aim_fig7.emf differ diff --git a/backend/tests/data/print/emf/qr_v1_m.emf b/backend/tests/data/print/emf/qr_v1_m.emf index 443e51e5..33041d57 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/emf/ultracode_a.emf b/backend/tests/data/print/emf/ultracode_a.emf index dd807eb0..94ff6340 100644 Binary files a/backend/tests/data/print/emf/ultracode_a.emf and b/backend/tests/data/print/emf/ultracode_a.emf differ diff --git a/backend/tests/test_ultra.c b/backend/tests/test_ultra.c index 2d0dc6b9..61127103 100644 --- a/backend/tests/test_ultra.c +++ b/backend/tests/test_ultra.c @@ -65,13 +65,32 @@ static void test_input(void) /* 12*/ { UNICODE_MODE, 9, -1, -1, "βAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", 0, "(250) 263 226 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65 65", "249 chars EC2" }, /* 13*/ { UNICODE_MODE, 9, -1, ULTRA_COMPRESSION, "A", 0, "(2) 272 65", "Note ECI ignored and not outputted if ULTRA_COMPRESSION and all ASCII" }, /* 14*/ { UNICODE_MODE, 15, -1, -1, "Ŗ", 0, "(2) 268 170", "" }, - /* 15*/ { GS1_MODE, 0, -1, -1, "[01]03453120000011[17]20121125[10]ABCD1234", ZINT_ERROR_INVALID_DATA, "Error 259: Invalid data length for AI (17)", "AIMD/TSC15032-43 G.6 Invalid [17] 4-digit year used in example" }, - /* 16*/ { GS1_MODE, 0, -1, -1, "[01]03453120000011[17]121125[10]ABCD1234", 0, "(20) 273 129 131 173 159 148 128 128 139 145 140 139 153 138 65 66 67 68 140 162", "Mode: a (34)" }, - /* 17*/ { GS1_MODE, 0, -1, -1, "[17]120508[10]ABCD1234[410]9501101020917", 0, "(21) 273 145 140 133 136 138 65 66 67 68 140 162 272 169 137 178 139 129 130 137 145", "Mode: a (35)" }, - /* 18*/ { GS1_MODE, 0, -1, -1, "[17]120508[10]ABCDEFGHI[410]9501101020917", 0, "(24) 273 145 140 133 136 138 65 66 67 68 69 70 71 72 73 272 169 137 178 139 129 130 137 145", "Mode: a (36)" }, - /* 19*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "ftp://", 0, "(4) 272 280 269 165", "Mode: c (6)" }, - /* 20*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, ".cgi", 0, "(4) 272 280 274 131", "Mode: c (4)" }, - /* 21*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "ftp://a.cgi", 0, "(6) 272 280 269 165 6 107", "Mode: c (11)" }, + /* 15*/ { DATA_MODE, 898, -1, -1, "\001\002\003\004\377", 0, "(7) 278 130 1 2 3 4 255", "" }, + /* 16*/ { DATA_MODE, 899, -1, -1, "\001\002\003\004\377", 0, "(6) 280 1 2 3 4 255", "" }, + /* 17*/ { DATA_MODE, 900, -1, -1, "\001\002\003\004\377", 0, "(9) 257 274 137 128 1 2 3 4 255", "" }, + /* 18*/ { DATA_MODE, 9999, -1, -1, "\001\002\003\004\377", 0, "(9) 257 274 227 227 1 2 3 4 255", "" }, + /* 19*/ { DATA_MODE, 10000, -1, -1, "\001\002\003\004\377", 0, "(10) 257 275 129 128 128 1 2 3 4 255", "" }, + /* 20*/ { DATA_MODE, 811799, -1, -1, "\001\002\003\004\377", 0, "(10) 257 275 209 145 227 1 2 3 4 255", "" }, + /* 21*/ { DATA_MODE, 811800, -1, -1, "\001\002\003\004\377", ZINT_ERROR_INVALID_OPTION, "Error 590: ECI value not supported by Ultracode", "" }, + /* 22*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "123,456,789/12,/3,4,/5//", 0, "(15) 272 140 231 173 234 206 257 140 44 262 242 44 264 47 47", "Mode: a (24)" }, + /* 23*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "HEIMASÍÐA KENNARAHÁSKÓLA ÍSLANDS", 0, "(32) 257 256 46 151 78 210 205 208 258 5 148 28 72 2 167 52 127 193 83 75 211 267 76 65 32", "Mode: cccccc88cccccccccc8888aaa8cccccc (32)" }, + /* 24*/ { UNICODE_MODE, 0, -1, -1, "HEIMASÍÐA KENNARAHÁSKÓLA ÍSLANDS", 0, "(33) 257 72 69 73 77 65 83 205 208 65 32 75 69 78 78 65 82 65 72 193 83 75 211 76 65 32 205", "" }, + /* 25*/ { UNICODE_MODE, 10, -1, ULTRA_COMPRESSION, "אולטרה-קוד1234", 0, "(14) 264 224 229 236 232 248 228 45 247 229 227 267 140 162", "Mode: 8888888888aaaa (14); Figure G.3" }, + /* 26*/ { UNICODE_MODE, 10, -1, -1, "אולטרה-קוד1234", 0, "(15) 264 224 229 236 232 248 228 45 247 229 227 49 50 51 52", "" }, + /* 27*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "https://aimglobal.org/jcrv3tX", 0, "(16) 282 266 1 74 41 19 6 168 270 212 59 106 144 56 265 70", "Mode: c (21); Figure G.4a" }, + /* 28*/ { UNICODE_MODE, 0, -1, -1, "https://aimglobal.org/jcrv3tX", 0, "(22) 282 97 105 109 103 108 111 98 97 108 46 111 114 103 47 106 99 114 118 51 116 88", "" }, + /* 29*/ { GS1_MODE, 0, -1, -1, "[01]03453120000011[17]121125[10]ABCD1234", 0, "(20) 273 129 131 173 159 148 128 128 139 145 140 139 153 138 65 66 67 68 140 162", "Mode: a (34); Figure G.6 uses C43 for 6 of last 7 chars (same codeword count)" }, + /* 30*/ { GS1_MODE, 0, -1, -1, "[17]120508[10]ABCD1234[410]9501101020917", 0, "(21) 273 145 140 133 136 138 65 66 67 68 140 162 272 169 137 178 139 129 130 137 145", "Mode: a (35)" }, + /* 31*/ { GS1_MODE, 0, -1, -1, "[17]120508[10]ABCDEFGHI[410]9501101020917", 0, "(24) 273 145 140 133 136 138 65 66 67 68 69 70 71 72 73 272 169 137 178 139 129 130 137 145", "Mode: a (36)" }, + /* 32*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "ftp://", 0, "(4) 272 278 269 165", "Mode: c (6)" }, + /* 33*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, ".cgi", 0, "(4) 272 278 274 131", "Mode: c (4)" }, + /* 34*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "ftp://a.cgi", 0, "(6) 272 280 269 123 274 131", "Mode: c (11)" }, + /* 35*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "e: file:f.shtml !", 0, "(12) 272 280 30 94 236 235 72 233 39 52 267 250", "Mode: c (17)" }, + /* 36*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "Aaatel:", 0, "(6) 272 280 262 76 6 89", "Mode: c (7)" }, + /* 37*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "Aatel:a", 0, "(6) 272 280 262 76 271 161", "Mode: c (7)" }, + /* 38*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "Atel:aAa", 0, "(8) 272 275 6 89 275 148 0 42", "Mode: c (8)" }, + /* 39*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "tel:AAaa", 0, "(8) 272 275 271 161 6 28 262 118", "Mode: c (8)" }, + /* 40*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "AAaatel:aA", 0, "(10) 272 276 0 42 0 41 118 46 6 156", "Mode: c (10)" }, }; int data_size = sizeof(data) / sizeof(struct item); @@ -236,22 +255,37 @@ static void test_encode(void) "70170613653553116357" "77777777777777777777" }, - /* 6*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "https://aimglobal.org/jcrv3tX", 0, 13, 22, "AIMD/TSC15032-43 Figure G.4a **NOT SAME** different compression", - "7777777777777777777777" - "7057065133563156313037" - "7767051556651331566757" - "7037066611513613331017" - "7717053165666351655767" - "7037035651531533133057" - "7707070707070707070707" - "7067015511111161565017" - "7737036635335356151737" - "7067063111116533366057" - "7737031536633116511717" - "7017063363361363356057" - "7777777777777777777777" + /* 6*/ { UNICODE_MODE, 0, -1, ULTRA_COMPRESSION, "https://aimglobal.org/jcrv3tX", 0, 13, 20, "AIMD/TSC15032-43 Figure G.4a **NOT SAME** different compression; also DCC incorrect in figure", + "77777777777777777777" + "70570655115631563137" + "77670563356513315617" + "70170611665136133337" + "77570565116663516517" + "70370311355315331357" + "77070707070707070707" + "70670113111111615617" + "77370331553353561537" + "70570655311165333157" + "77370311136331165617" + "70170163363613633157" + "77777777777777777777" }, - /* 7*/ { UNICODE_MODE, 0, -1, -1, "A", 0, 13, 13, "Verified against bwipp", + /* 7*/ { GS1_MODE, 0, -1, -1, "[01]03453120000011[17]121125[10]ABCD1234", 0, 13, 23, "AIMD/TSC15032-43 Figure G.6 **NOT SAME** different compression and ECC; also DCC incorrect in figure", + "77777777777777777777777" + "70570616535355353310157" + "77670553116631616667617" + "70370331365353335550567" + "77570563516616556637657" + "70370656335135665360337" + "77070707070707070707077" + "70670161311353355110517" + "77570313153616611667137" + "70170635531563535550357" + "77370516316135616367117" + "70170335533356531510357" + "77777777777777777777777" + }, + /* 8*/ { UNICODE_MODE, 0, -1, -1, "A", 0, 13, 13, "Verified against bwipp", "7777777777777" "7057063335517" "7717035163667" @@ -266,7 +300,7 @@ static void test_encode(void) "7017033536357" "7777777777777" }, - /* 8*/ { UNICODE_MODE, 0, 2, -1, "12345678901234567890123", 0, 13, 25, "Length 23 == 26 MCC (C) with EC1 so 7 ECC by Table 12", + /* 9*/ { UNICODE_MODE, 0, 2, -1, "12345678901234567890123", 0, 13, 25, "Length 23 == 26 MCC (C) with EC1 so 7 ECC by Table 12", "7777777777777777777777777" "7057063655511111111011117" "7767031563666666666766667" @@ -281,7 +315,7 @@ static void test_encode(void) "7017035653363636636036657" "7777777777777777777777777" }, - /* 9*/ { UNICODE_MODE, 0, 1, -1, "1", 0, 13, 11, "Figure 3a min 2-row, EC0; verified against bwipp", + /* 10*/ { UNICODE_MODE, 0, 1, -1, "1", 0, 13, 11, "Figure 3a min 2-row, EC0; verified against bwipp", "77777777777" "70570661517" "77170355667" @@ -296,7 +330,7 @@ static void test_encode(void) "70170365567" "77777777777" }, - /* 10*/ { UNICODE_MODE, 0, 6, -1, "123456789012345678901", 0, 13, 27, "Figure 3a max 2-row, EC5", + /* 11*/ { UNICODE_MODE, 0, 6, -1, "123456789012345678901", 0, 13, 27, "Figure 3a max 2-row, EC5", "777777777777777777777777777" "705706316551651111101111117" "771703535313166666676666667" @@ -311,7 +345,7 @@ static void test_encode(void) "701705553563556363606363637" "777777777777777777777777777" }, - /* 11*/ { UNICODE_MODE, 0, 6, -1, "1234567890123456789012345678901234567890123456789012", 0, 19, 36, "Figure 3b max 3-row, EC5", + /* 12*/ { UNICODE_MODE, 0, 6, -1, "1234567890123456789012345678901234567890123456789012", 0, 19, 36, "Figure 3b max 3-row, EC5", "777777777777777777777777777777777777" "700706363653513111101111111111111117" "770703511165156356676666666666666667" @@ -332,7 +366,7 @@ static void test_encode(void) "700703155555336565303316566653331637" "777777777777777777777777777777777777" }, - /* 12*/ { UNICODE_MODE, 0, 6, -1, "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123", 0, 25, 49, "Figure 3c max 4-row, EC5", + /* 13*/ { UNICODE_MODE, 0, 6, -1, "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123", 0, 25, 49, "Figure 3c max 4-row, EC5", "7777777777777777777777777777777777777777777777777" "7007061565635135151011111111111111101111111111117" "7707035151513316566766666666666666676666666666667" @@ -359,7 +393,7 @@ static void test_encode(void) "7007016565561165166063366633666336606336663366637" "7777777777777777777777777777777777777777777777777" }, - /* 13*/ { UNICODE_MODE, 0, 6, -1, "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", 0, 31, 66, "Figure 3d max 5-row, EC5 **NOT SAME** Max columns due to 282 limit is 60 not 61 as shown", + /* 14*/ { UNICODE_MODE, 0, 6, -1, "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", 0, 31, 66, "Figure 3d max 5-row, EC5 **NOT SAME** Max columns due to 282 limit is 60 not 61 as shown", "777777777777777777777777777777777777777777777777777777777777777777" "700706655166656555306351111111111110111111111111111011111111111117" "770703331611363336575566666666666667666666666666666766666666666667" diff --git a/backend/ultra.c b/backend/ultra.c index 13e8936e..6e4caa31 100644 --- a/backend/ultra.c +++ b/backend/ultra.c @@ -214,6 +214,7 @@ static int ultra_find_fragment(const unsigned char source[], int source_length, for (k = 0; k < (int) strlen(fragment[j]); k++) { if (source[position + k] != fragment[j][k]) { latch = 0; + break; } } } @@ -308,13 +309,13 @@ static float look_ahead_ascii(unsigned char source[], int in_length, int in_locn codeword_count++; i += 2; done = 1; - } else if ((first_digit >= 0) && (first_digit <= 10) && (second_digit == 11)) { + } else if ((first_digit >= 0) && (first_digit <= 9) && (second_digit == 11)) { /* Single digit or decimal point followed by field deliminator */ cw[codeword_count] = first_digit + 248; codeword_count++; i += 2; done = 1; - } else if ((first_digit == 11) && (second_digit >= 0) && (second_digit <= 10)) { + } else if ((first_digit == 11) && (second_digit >= 0) && (second_digit <= 9)) { /* Field deliminator followed by single digit or decimal point */ cw[codeword_count] = second_digit + 259; codeword_count++; @@ -349,36 +350,79 @@ static float look_ahead_ascii(unsigned char source[], int in_length, int in_locn } } -static int get_subset(unsigned char source[], int in_length, int in_locn) { +/* Returns true if should latch to subset other than given `subset` */ +static int c43_should_latch_other(const unsigned char data[], const size_t length, const unsigned int locn, int subset, int gs1) { + unsigned int i, fraglen, predict_window; + int cnt, alt_cnt, fragno; + const char* set = subset == 1 ? ultra_c43_set1 : ultra_c43_set2; + const char* alt_set = subset == 2 ? ultra_c43_set1 : ultra_c43_set2; + + if (locn + 3 > length) { + return 0; + } + predict_window = locn + 3; + + for (i = locn, cnt = 0, alt_cnt = 0; i < predict_window; i++) { + if (data[i] <= 0x1F || data[i] >= 0x7F || (gs1 && data[i] == '[')) { + break; + } + + fragno = ultra_find_fragment(data, length, i); + if (fragno != -1 && fragno != 26) { + fraglen = strlen(fragment[fragno]); + predict_window += fraglen; + if (predict_window > length) { + predict_window = length; + } + i += fraglen - 1; + } else { + if (strchr(set, data[i]) != NULL) { + cnt++; + } + if (strchr(alt_set, data[i]) != NULL) { + alt_cnt++; + } + } + } + + return alt_cnt > cnt; +} + +static int get_subset(unsigned char source[], int in_length, int in_locn, int current_subset) { int fragno; int subset = 0; - if (posn(ultra_c43_set1, source[in_locn]) != -1) { - subset = 1; - } - - if (posn(ultra_c43_set2, source[in_locn]) != -1) { - subset = 2; - } - - if (posn(ultra_c43_set3, source[in_locn]) != -1) { - subset = 3; - } - fragno = ultra_find_fragment(source, in_length, in_locn); if ((fragno != -1) && (fragno != 26)) { subset = 3; + } else if (current_subset == 2) { + if (posn(ultra_c43_set2, source[in_locn]) != -1) { + subset = 2; + } else if (posn(ultra_c43_set1, source[in_locn]) != -1) { + subset = 1; + } + } else { + if (posn(ultra_c43_set1, source[in_locn]) != -1) { + subset = 1; + } else if (posn(ultra_c43_set2, source[in_locn]) != -1) { + subset = 2; + } + } + + if (subset == 0) { + if (posn(ultra_c43_set3, source[in_locn]) != -1) { + subset = 3; + } } return subset; } /* Encode characters in the C43 compaction submode */ -static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, char current_mode, int end_char, int cw[], int* cw_len, int* encoded, int gs1) { +static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, char current_mode, int end_char, int subset, int cw[], int* cw_len, int* encoded, int gs1, int debug) { int codeword_count = 0; int subcodeword_count = 0; int i; - int subset = 0; int fragno; int sublocn = in_locn; int new_subset; @@ -386,7 +430,6 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, int base43_value; int letters_encoded = 0; int pad; - int gs1_latch = 0; #ifndef _MSC_VER int subcw[(in_length + 3) * 2]; @@ -394,12 +437,6 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, int * subcw = (int *) _alloca((in_length + 3) * 2 * sizeof (int)); #endif /* _MSC_VER */ - subset = get_subset(source, in_length, sublocn); - - if (subset == 0) { - return 0.0; - } - if (current_mode == EIGHTBIT_MODE) { /* Check for permissable URL C43 macro sequences, otherwise encode directly */ fragno = ultra_find_fragment(source, in_length, sublocn); @@ -469,6 +506,34 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, unshift_set = subset; do { + /* Check for FNC1 */ + if (gs1 && source[sublocn] == '[') { + break; + } + + new_subset = get_subset(source, in_length, sublocn, subset); + + if (new_subset == 0) { + break; + } + + if ((new_subset != subset) && ((new_subset == 1) || (new_subset == 2))) { + if (c43_should_latch_other(source, in_length, sublocn, subset, gs1)) { + subcw[subcodeword_count] = 42; // Latch to other C43 set + subcodeword_count++; + unshift_set = new_subset; + } else { + subcw[subcodeword_count] = 40; // Shift to other C43 set for 1 char + subcodeword_count++; + subcw[subcodeword_count] = posn(new_subset == 1 ? ultra_c43_set1 : ultra_c43_set2, source[sublocn]); + subcodeword_count++; + sublocn++; + continue; + } + } + + subset = new_subset; + if (subset == 1) { subcw[subcodeword_count] = posn(ultra_c43_set1, source[sublocn]); subcodeword_count++; @@ -507,30 +572,7 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, subset = unshift_set; } - if (sublocn < in_length && sublocn < end_char) { - new_subset = get_subset(source, in_length, sublocn); - - if (((subset == 1) && (new_subset == 2)) && ((source[sublocn] == '.') || (source[sublocn] == ','))) { - /* and characters available in both subsets */ - new_subset = 1; - } - - if ((new_subset != subset) && ((new_subset == 1) || (new_subset == 2))) { - subcw[subcodeword_count] = 42; // Latch to other C43 set - subcodeword_count++; - unshift_set = new_subset; - } - - subset = new_subset; - } - - /* Check for FNC1 */ - if (sublocn < (in_length - 1)) { - if ((source[sublocn + 1] == '[') && gs1) { - gs1_latch = 1; - } - } - } while ((sublocn < in_length) && (sublocn < end_char) && (subset != 0) && (gs1_latch == 0)); + } while ((sublocn < in_length) && (sublocn < end_char)); pad = 3 - (subcodeword_count % 3); if (pad == 3) { @@ -542,6 +584,12 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, subcodeword_count++; } + if (debug & ZINT_DEBUG_PRINT) { + printf("C43 codewords %.*s: (%d)", in_length, source + in_locn, subcodeword_count); + for (i = 0; i < subcodeword_count; i++) printf( " %d", subcw[i]); + printf("\n"); + } + letters_encoded = sublocn - in_locn; if (encoded != NULL) { *encoded = letters_encoded; @@ -555,7 +603,6 @@ static float look_ahead_c43(unsigned char source[], int in_length, int in_locn, codeword_count++; } - *cw_len = codeword_count; if (codeword_count == 0) { @@ -573,6 +620,7 @@ static int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned c int input_locn = 0; char symbol_mode; char current_mode; + int subset; float eightbit_score; float ascii_score; float c43_score; @@ -593,13 +641,6 @@ static int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned c int * cw_fragment = (int *) _alloca((in_length * 2 + 1) * sizeof (int)); #endif /* _MSC_VER */ - /* Section 7.6.2 indicates that ECI \000003 to \811799 are supported */ - /* but this seems to contradict Table 5 which only shows up to \000898 */ - if (symbol->eci > 898) { - strcpy(symbol->errtxt, "592: ECI value out of range"); - return ZINT_ERROR_INVALID_OPTION; - } - if ((symbol->input_mode & 0x07) == GS1_MODE) { gs1 = 1; } @@ -638,7 +679,7 @@ static int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned c } } else { if ((symbol->eci >= 3) && (symbol->eci <= 18) && (symbol->eci != 14)) { - // ECI indicate use of character set within ISO/IEC 8859 + // ECI indicates use of character set within ISO/IEC 8859 codewords[0] = 257 + (symbol->eci - 3); if (codewords[0] > 267) { // Avoids ECI 14 for non-existant ISO/IEC 8859-12 @@ -646,11 +687,14 @@ static int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned c } } else if ((symbol->eci > 18) && (symbol->eci <= 898)) { // ECI indicates use of character set outside ISO/IEC 8859 - codewords[0] = 273 + (symbol->eci / 256); + codewords[0] = 275 + (symbol->eci / 256); codewords[1] = symbol->eci % 256; codeword_count++; - } else if ((symbol->eci > 898) && (symbol->eci <= 9999)) { - // ECI beyond 898 needs to use fixed length encodable ECI invocation (section 7.6.2) + } else if (symbol->eci == 899) { + // Non-language byte data + codewords[0] = 280; + } else if ((symbol->eci > 899) && (symbol->eci <= 9999)) { + // ECI beyond 899 needs to use fixed length encodable ECI invocation (section 7.6.2) // Encode as 3 codewords codewords[0] = 257; // ISO/IEC 8859-1 used to enter 8-bit mode codewords[1] = 274; // Encode ECI as 3 codewords @@ -727,7 +771,8 @@ static int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned c end_char = input_locn + PREDICT_WINDOW; eightbit_score = look_ahead_eightbit(crop_source, crop_length, input_locn, current_mode, end_char, cw_fragment, &fragment_length, gs1); ascii_score = look_ahead_ascii(crop_source, crop_length, input_locn, current_mode, symbol_mode, end_char, cw_fragment, &fragment_length, &ascii_encoded, gs1); - c43_score = look_ahead_c43(crop_source, crop_length, input_locn, current_mode, end_char, cw_fragment, &fragment_length, &c43_encoded, gs1); + subset = c43_should_latch_other(crop_source, crop_length, input_locn, 1 /*subset*/, gs1) ? 2 : 1; + c43_score = look_ahead_c43(crop_source, crop_length, input_locn, current_mode, end_char, subset, cw_fragment, &fragment_length, &c43_encoded, gs1, 0 /*debug*/); mode[input_locn] = 'a'; current_mode = ASCII_MODE; @@ -782,7 +827,8 @@ static int ultra_generate_codewords(struct zint_symbol *symbol, const unsigned c current_mode = ASCII_MODE; break; case 'c': - look_ahead_c43(crop_source, crop_length, input_locn, current_mode, input_locn + block_length, cw_fragment, &fragment_length, NULL, gs1); + subset = c43_should_latch_other(crop_source, crop_length, input_locn, 1 /*subset*/, gs1) ? 2 : 1; + look_ahead_c43(crop_source, crop_length, input_locn, current_mode, input_locn + block_length, subset, cw_fragment, &fragment_length, NULL, gs1, symbol->debug); /* Substitute temporary latch if possible */ if ((current_mode == EIGHTBIT_MODE) && (cw_fragment[0] == 260) && (fragment_length >= 5) && (fragment_length <= 11)) {