From 847fa6f33249c457661d7ed4c72f6ab7e6a857c3 Mon Sep 17 00:00:00 2001 From: Robin Stuart Date: Fri, 19 May 2017 21:30:31 +0100 Subject: [PATCH] Update DotCode to latest draft (April 24, 2017) --- backend/dotcode.c | 165 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 153 insertions(+), 12 deletions(-) diff --git a/backend/dotcode.c b/backend/dotcode.c index 07d03298..914ab7d3 100644 --- a/backend/dotcode.c +++ b/backend/dotcode.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2016 Robin Stuart + Copyright (C) 2017 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -78,10 +78,77 @@ int get_dot(char Dots[], int Hgt, int Wid, int x, int y) { return retval; } +int clr_col(char *Dots, int Hgt, int Wid, int x) { + int y; + for (y = x & 1; y < Hgt; y += 2) { + if (get_dot(Dots, Hgt, Wid, x, y)) { + return 0; + } + } + + return 1; +} + +int clr_row(char *Dots, int Hgt, int Wid, int y) { + int x; + for (x = y & 1; x < Wid; x += 2) { + if (get_dot(Dots, Hgt, Wid, x, y)) { + return 0; + } + } + + return 1; +} + /* Dot pattern scoring routine from Annex A */ int score_array(char Dots[], int Hgt, int Wid) { int x, y, worstedge, first, last, sum; + int penalty_local = 0; + int penalty = 0; + // first, guard against "pathelogical" gaps in the array + if (Hgt & 1) { + if (Hgt < 12) { + sum = 0; + for (x = 1; x < Wid - 1; x++) { + if (!(clr_col(Dots, Hgt, Wid, x))) { + sum = 0; + if (penalty_local) { + penalty += penalty_local; + penalty_local = 0; + } + } else { + sum++; + if (sum == 1) { + penalty_local = Hgt; + } else { + penalty_local *= Hgt; + } + } + } + } + } else { + if (Wid < 12) { + sum = 0; + for (y = 1; y < Hgt - 1; y++) { + if (!(clr_row(Dots, Hgt, Wid, y))) { + sum = 0; + if (penalty_local) { + penalty += penalty_local; + penalty_local = 0; + } + } else { + sum++; + if (sum == 1) { + penalty_local = Wid; + } else { + penalty_local *= Wid; + } + } + } + } + } + sum = 0; first = -1; last = -1; @@ -100,6 +167,7 @@ int score_array(char Dots[], int Hgt, int Wid) { sum = 0; first = -1; + last = -1; //across the bottom edge, ditto for (x = Wid & 1; x < Wid; x += 2) @@ -118,6 +186,7 @@ int score_array(char Dots[], int Hgt, int Wid) { sum = 0; first = -1; + last = -1; //down the left edge, ditto for (y = 0; y < Hgt; y += 2) @@ -136,6 +205,7 @@ int score_array(char Dots[], int Hgt, int Wid) { sum = 0; first = -1; + last = -1; //down the right edge, ditto for (y = Hgt & 1; y < Hgt; y += 2) @@ -171,7 +241,7 @@ int score_array(char Dots[], int Hgt, int Wid) { } } - return (worstedge - sum * sum); + return (worstedge - sum * sum - penalty); } //------------------------------------------------------------------------- @@ -240,7 +310,7 @@ int datum_b(const unsigned char source[], int position, int length) { int retval = 0; if (position < length) { - if (source[position] >= 32) { + if ((source[position] >= 32) && (source[position] <= 127)) { retval = 1; } @@ -388,20 +458,73 @@ int dotcode_encode_message(struct zint_symbol *symbol, const unsigned char sourc } if (symbol->input_mode != GS1_MODE) { - codeword_array[array_length] = 107; // FNC1 - array_length++; + if (length > 2) { + if (((source[input_position] >= '0') && (source[input_position] <= '9')) && + ((source[input_position + 1] >= '0') && (source[input_position + 1] <= '9'))) { + codeword_array[array_length] = 107; // FNC1 + array_length++; + } + } } if (symbol->eci > 3) { codeword_array[array_length] = 108; // FNC2 array_length++; - codeword_array[array_length] = symbol->eci; - array_length++; + if (symbol->eci <= 39) { + codeword_array[array_length] = symbol->eci; + array_length++; + } else { + // the next three codewords valued A, B & C encode the ECI value of + // (A - 40) * 12769 + B * 113 + C + 40 (Section 5.2.1) + int a, b, c; + a = (symbol->eci - 40) % 12769; + b = ((symbol->eci - 40) - (12769 * a)) % 113; + c = (symbol->eci - 40) - (12769 * a) - (113 * b); + + codeword_array[array_length] = a + 40; + array_length++; + codeword_array[array_length] = b; + array_length++; + codeword_array[array_length] = c; + array_length++; + } } + // Prevent encodation as a macro if a special character is in first position + if (source[input_position] == 9) { + codeword_array[array_length] = 101; // Latch A + array_length++; + codeword_array[array_length] = 73; // HT + array_length++; + encoding_mode = 'A'; + } + + if (source[input_position] == 28) { + codeword_array[array_length] = 101; // Latch A + array_length++; + codeword_array[array_length] = 92; // FS + array_length++; + encoding_mode = 'A'; + } + + if (source[input_position] == 29) { + codeword_array[array_length] = 101; // Latch A + array_length++; + codeword_array[array_length] = 93; // GS + array_length++; + encoding_mode = 'A'; + } + + if (source[input_position] == 30) { + codeword_array[array_length] = 101; // Latch A + array_length++; + codeword_array[array_length] = 94; // RS + array_length++; + encoding_mode = 'A'; + } + do { done = 0; - /* Step A */ if ((input_position == length - 2) && (inside_macro != 0) && (inside_macro != 100)) { // inside_macro only gets set to 97, 98 or 99 if the last two characters are RS/EOT @@ -430,12 +553,11 @@ int dotcode_encode_message(struct zint_symbol *symbol, const unsigned char sourc && (source[input_position + 3] == 30) // RS && (source[length - 1] == 04)) { // EOT - codeword_array[array_length] = 106; // Latch B - array_length++; - encoding_mode = 'B'; if ((source[input_position + 6] == 29) && (source[length - 2] == 30)) { // GS/RS if ((source[input_position + 4] == '0') && (source[input_position + 5] == '5')) { + codeword_array[array_length] = 102; // Shift B + array_length++; codeword_array[array_length] = 97; // Macro array_length++; input_position += 7; @@ -447,6 +569,8 @@ int dotcode_encode_message(struct zint_symbol *symbol, const unsigned char sourc } if ((source[input_position + 4] == '0') && (source[input_position + 5] == '6')) { + codeword_array[array_length] = 102; // Shift B + array_length++; codeword_array[array_length] = 98; // Macro array_length++; input_position += 7; @@ -458,6 +582,8 @@ int dotcode_encode_message(struct zint_symbol *symbol, const unsigned char sourc } if ((source[input_position + 4] == '1') && (source[input_position + 5] == '2')) { + codeword_array[array_length] = 102; // Shift B + array_length++; codeword_array[array_length] = 99; // Macro array_length++; input_position += 7; @@ -469,7 +595,10 @@ int dotcode_encode_message(struct zint_symbol *symbol, const unsigned char sourc } } - if (!done) { + if ((!done) && (source[input_position] >= '0') && (source[input_position] <= '9') && + (source[input_position + 1] >= '0') && (source[input_position + 1] <= '9')) { + codeword_array[array_length] = 102; // Shift B + array_length++; codeword_array[array_length] = 100; // Macro array_length++; input_position += 4; @@ -912,6 +1041,18 @@ int dotcode_encode_message(struct zint_symbol *symbol, const unsigned char sourc } while (input_position < length); if (encoding_mode == 'X') { + if (binary_buffer_size != 0) { + /* Empty binary buffer */ + for (i = 0; i < (binary_buffer_size + 1); i++) { + lawrencium[i] = binary_buffer % 103; + binary_buffer /= 103; + } + + for (i = 0; i < (binary_buffer_size + 1); i++) { + codeword_array[array_length] = lawrencium[binary_buffer_size - i]; + array_length++; + } + } *(binary_finish) = 1; }