Composite changes encodation 10, 11, general field, CC-A/B shift

This commit is contained in:
gitlost 2019-10-29 22:54:18 +00:00
parent 1564cd7a34
commit 03d99ceb23
9 changed files with 1812 additions and 367 deletions

View file

@ -4,7 +4,7 @@ project(zint)
find_package(PNG)
set(zint_COMMON_SRCS common.c library.c render.c large.c reedsol.c gs1.c eci.c)
set(zint_COMMON_SRCS common.c library.c render.c large.c reedsol.c gs1.c eci.c general_field.c)
set(zint_ONEDIM_SRCS code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c)
set(zint_POSTAL_SRCS postal.c auspost.c imail.c mailmark.c)
set(zint_TWODIM_SRCS code16k.c codablock.c dmatrix.c pdf417.c qr.c maxicode.c composite.c aztec.c code49.c code1.c gridmtx.c hanxin.c dotcode.c ultra.c)

View file

@ -29,6 +29,7 @@
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/* vim: set ts=4 sw=4 et : */
/* The functions "getBit", "init928" and "encode928" are copyright BSI and are
released with permission under the following terms:
@ -60,10 +61,10 @@
#include "composite.h"
#include "pdf417.h"
#include "gs1.h"
#include "general_field.h"
#define UINT unsigned short
extern int general_rules(char type[]);
extern int eanx(struct zint_symbol *symbol, unsigned char source[], int length);
extern int ean_128(struct zint_symbol *symbol, unsigned char source[], const size_t length);
extern void ean_leading_zeroes(struct zint_symbol *symbol, unsigned char source[], unsigned char local_source[]);
@ -962,27 +963,30 @@ int calc_padding_ccc(int binary_length, int *cc_width, int lin_width, int *ecc)
}
static int cc_binary_string(struct zint_symbol *symbol, const char source[], char binary_string[], int cc_mode, int *cc_width, int *ecc, int lin_width) { /* Handles all data encodation from section 5 of ISO/IEC 24723 */
int encoding_method, read_posn, d1, d2, alpha_pad;
int i, j, ai_crop, fnc1_latch;
int ai90_mode, latch, remainder, binary_length;
int encoding_method, read_posn, alpha_pad;
int i, j, ai_crop, ai_crop_posn, fnc1_latch;
int ai90_mode, last_digit, remainder, binary_length;
int mode;
int source_len = strlen(source);
#ifndef _MSC_VER
char general_field[strlen(source) + 1], general_field_type[strlen(source) + 1];
char general_field[source_len + 1];
#else
char* general_field = (char*) _alloca(strlen(source) + 1);
char* general_field_type = (char*) _alloca(strlen(source) + 1);
char* general_field = (char*) _alloca(source_len + 1);
#endif
int target_bitsize;
encoding_method = 1;
read_posn = 0;
ai_crop = 0;
ai_crop_posn = -1;
fnc1_latch = 0;
alpha_pad = 0;
ai90_mode = 0;
*ecc = 0;
target_bitsize = 0;
mode = NUMERIC;
if ((source[0] == '1') && ((source[1] == '0') || (source[1] == '1') || (source[1] == '7')) && (strlen(source) > 8)) {
if ((source[0] == '1') && ((source[1] == '0') || (source[1] == '1') || (source[1] == '7'))) {
/* Source starts (10), (11) or (17) */
encoding_method = 2;
}
@ -1032,37 +1036,44 @@ static int cc_binary_string(struct zint_symbol *symbol, const char source[], cha
strcat(binary_string, "1");
}
read_posn = 8;
}
if ((source[read_posn] == '1') && (source[read_posn + 1] == '0')) {
/* Followed by AI 10 - strip this from general field */
read_posn += 2;
} else {
/* An FNC1 character needs to be inserted in the general field */
fnc1_latch = 1;
if ((source[read_posn] == '1') && (source[read_posn + 1] == '0')) {
/* Followed by AI 10 - strip this from general field */
read_posn += 2;
} else if (source[read_posn]) {
/* ISO/IEC 24723:2010 5.3.1 "If a lot number does not directly follow the date element string, a FNC1 is encoded following the date element string ..." */
fnc1_latch = 1;
} else {
/* "... even if no more data follows the date element string" */
/* So still need FNC1 character but can't do single FNC1 in numeric mode, so insert alphanumeric latch "0000" and alphanumeric FNC1 "01111"
(this implementation detail taken from BWIPP https://github.com/bwipp/postscriptbarcode Copyright (c) 2004-2019 Terry Burton) */
strcat(binary_string, "000001111");
/* Note an alphanumeric FNC1 is also a numeric latch, so now in numeric mode */
}
}
}
if (encoding_method == 3) {
/* Encodation Method field of "11" - AI 90 */
#ifndef _MSC_VER
char ninety[strlen(source) + 1];
char ninety[source_len + 1];
#else
char* ninety = (char*) _alloca(strlen(source) + 1);
char* ninety = (char*) _alloca(source_len + 1);
#endif
int alpha, alphanum, numeric, test1, test2, test3;
int ninety_len, alpha, alphanum, numeric, test1, test2, test3;
/* "This encodation method may be used if an element string with an AI
90 occurs at the start of the data message, and if the data field
following the two-digit AI 90 starts with an alphanumeric string which
complies with a specific format." (para 5.2.2) */
complies with a specific format." (para 5.3.2) */
i = 0;
do {
ninety[i] = source[i + 2];
i++;
} while ((strlen(source) > i + 2) && ('[' != source[i + 2]));
} while ((source_len > i + 2) && ('[' != source[i + 2]));
ninety[i] = '\0';
ninety_len = strlen(ninety);
/* Find out if the AI 90 data is alphabetic or numeric or both */
@ -1070,33 +1081,16 @@ static int cc_binary_string(struct zint_symbol *symbol, const char source[], cha
alphanum = 0;
numeric = 0;
for (i = 0; i < (int) strlen(ninety); i++) {
for (i = 0; i < ninety_len; i++) {
if ((ninety[i] >= 'A') && (ninety[i] <= 'Z')) {
/* Character is alphabetic */
alpha += 1;
}
if ((ninety[i] >= '0') && (ninety[i] <= '9')) {
} else if ((ninety[i] >= '0') && (ninety[i] <= '9')) {
/* Character is numeric */
numeric += 1;
}
switch (ninety[i]) {
case '*':
case ',':
case '-':
case '.':
case '/': alphanum += 1;
break;
}
if (!(((ninety[i] >= '0') && (ninety[i] <= '9')) || ((ninety[i] >= 'A') && (ninety[i] <= 'Z')))) {
if ((ninety[i] != '*') && (ninety[i] != ',') && (ninety[i] != '-') && (ninety[i] != '.') && (ninety[i] != '/')) {
/* An Invalid AI 90 character */
strcpy(symbol->errtxt, "440: Invalid AI 90 data");
return ZINT_ERROR_INVALID_DATA;
}
} else {
alphanum += 1;
}
}
@ -1135,26 +1129,25 @@ static int cc_binary_string(struct zint_symbol *symbol, const char source[], cha
/* Decide on numeric, alpha or alphanumeric mode */
/* Alpha mode is a special mode for AI 90 */
if (alphanum > 0) {
if (alphanum == 0 && alpha > numeric) {
/* Alphabetic mode */
strcat(binary_string, "11");
ai90_mode = 2;
} else if (alphanum == 0 && alpha == 0) {
/* Numeric mode */
strcat(binary_string, "10");
ai90_mode = 3;
} else {
/* Alphanumeric mode */
strcat(binary_string, "0");
ai90_mode = 1;
} else {
if (alpha > numeric) {
/* Alphabetic mode */
strcat(binary_string, "11");
ai90_mode = 2;
} else {
/* Numeric mode */
strcat(binary_string, "10");
ai90_mode = 3;
}
mode = ALPHA;
}
next_ai_posn = 2 + (int)strlen(ninety);
next_ai_posn = 2 + ninety_len;
if (source[next_ai_posn] == '[') {
/* There are more AIs afterwords */
/* There are more AIs afterwards */
if ((source[next_ai_posn + 1] == '2') && (source[next_ai_posn + 2] == '1')) {
/* AI 21 follows */
ai_crop = 1;
@ -1162,7 +1155,7 @@ static int cc_binary_string(struct zint_symbol *symbol, const char source[], cha
if ((source[next_ai_posn + 1] == '8') && (source[next_ai_posn + 2] == '0') && (source[next_ai_posn + 3] == '0') && (source[next_ai_posn + 4] == '4')) {
/* AI 8004 follows */
ai_crop = 2;
ai_crop = 3;
}
}
@ -1170,8 +1163,10 @@ static int cc_binary_string(struct zint_symbol *symbol, const char source[], cha
case 0: strcat(binary_string, "0");
break;
case 1: strcat(binary_string, "10");
ai_crop_posn = next_ai_posn + 1;
break;
case 2: strcat(binary_string, "11");
case 3: strcat(binary_string, "11");
ai_crop_posn = next_ai_posn + 1;
break;
}
@ -1192,14 +1187,14 @@ static int cc_binary_string(struct zint_symbol *symbol, const char source[], cha
}
if (table3_letter != -1) {
/* Encoding can be done according to 5.2.2 c) 2) */
/* Encoding can be done according to 5.3.2 c) 2) */
/* five bit binary string representing value before letter */
bin_append(numeric_value, 5, binary_string);
/* followed by four bit representation of letter from Table 3 */
bin_append(table3_letter, 4, binary_string);
} else {
/* Encoding is done according to 5.2.2 c) 3) */
/* Encoding is done according to 5.3.2 c) 3) */
bin_append(31, 5, binary_string);
/* ten bit representation of number */
bin_append(numeric_value, 10, binary_string);
@ -1209,6 +1204,26 @@ static int cc_binary_string(struct zint_symbol *symbol, const char source[], cha
}
read_posn = test1 + 3;
/* Do Alpha mode encoding of the rest of the AI 90 data field here */
if (ai90_mode == 2) {
/* Alpha encodation (section 5.3.3) */
do {
if ((source[read_posn] >= 'A') && (source[read_posn] <= 'Z')) {
bin_append(source[read_posn] - 65, 5, binary_string);
} else if ((source[read_posn] >= '0') && (source[read_posn] <= '9')) {
bin_append(source[read_posn] + 4, 6, binary_string);
} else if (source[read_posn] == '[') {
bin_append(31, 5, binary_string);
}
read_posn++;
} while ((source[read_posn - 1] != '[') && (source[read_posn - 1] != '\0'));
alpha_pad = 1; /* This is overwritten if a general field is encoded */
}
} else {
/* Use general field encodation instead */
strcat(binary_string, "0");
@ -1216,65 +1231,6 @@ static int cc_binary_string(struct zint_symbol *symbol, const char source[], cha
}
}
/* Now encode the rest of the AI 90 data field */
if (ai90_mode == 2) {
/* Alpha encodation (section 5.2.3) */
do {
if ((source[read_posn] >= '0') && (source[read_posn] <= '9')) {
bin_append(source[read_posn] + 4, 5, binary_string);
}
if ((source[read_posn] >= 'A') && (source[read_posn] <= 'Z')) {
bin_append(source[read_posn] - 65, 6, binary_string);
}
if (source[read_posn] == '[') {
bin_append(31, 5, binary_string);
}
read_posn++;
} while ((source[read_posn - 1] != '[') && (source[read_posn - 1] != '\0'));
alpha_pad = 1; /* This is overwritten if a general field is encoded */
}
if (ai90_mode == 1) {
/* Alphanumeric mode */
do {
if ((source[read_posn] >= '0') && (source[read_posn] <= '9')) {
bin_append(source[read_posn] - 43, 5, binary_string);
}
if ((source[read_posn] >= 'A') && (source[read_posn] <= 'Z')) {
bin_append(source[read_posn] - 33, 6, binary_string);
}
switch (source[read_posn]) {
case '[':
bin_append(15, 5, binary_string);
break;
case '*':
bin_append(58, 6, binary_string);
break;
case ',':
bin_append(59, 6, binary_string);
break;
case '-':
bin_append(60, 6, binary_string);
break;
case '.':
bin_append(61, 6, binary_string);
break;
case '/':
bin_append(62, 6, binary_string);
break;
}
read_posn++;
} while ((source[read_posn - 1] != '[') && (source[read_posn - 1] != '\0'));
}
read_posn += (2 * ai_crop);
/* The compressed data field has been processed if appropriate - the
rest of the data (if any) goes into a general-purpose data compaction field */
@ -1286,9 +1242,14 @@ static int cc_binary_string(struct zint_symbol *symbol, const char source[], cha
j++;
}
for (i = read_posn; i < (int) strlen(source); i++) {
general_field[j] = source[i];
j++;
for (i = read_posn; i < source_len; i++) {
/* Skip "[21" or "[8004" AIs if encodation method "11" used */
if (i == ai_crop_posn) {
i += ai_crop;
} else {
general_field[j] = source[i];
j++;
}
}
general_field[j] = '\0';
@ -1296,222 +1257,12 @@ static int cc_binary_string(struct zint_symbol *symbol, const char source[], cha
alpha_pad = 0;
}
latch = 0;
for (i = 0; i < (int) strlen(general_field); i++) {
/* Table 13 - ISO/IEC 646 encodation */
if ((general_field[i] < ' ') || (general_field[i] > 'z')) {
general_field_type[i] = INVALID_CHAR;
latch = 1;
} else {
general_field_type[i] = ISOIEC;
}
if (general_field[i] == '#') {
general_field_type[i] = INVALID_CHAR;
latch = 1;
}
if (general_field[i] == '$') {
general_field_type[i] = INVALID_CHAR;
latch = 1;
}
if (general_field[i] == '@') {
general_field_type[i] = INVALID_CHAR;
latch = 1;
}
if (general_field[i] == 92) {
general_field_type[i] = INVALID_CHAR;
latch = 1;
}
if (general_field[i] == '^') {
general_field_type[i] = INVALID_CHAR;
latch = 1;
}
if (general_field[i] == 96) {
general_field_type[i] = INVALID_CHAR;
latch = 1;
}
/* Table 12 - Alphanumeric encodation */
if ((general_field[i] >= 'A') && (general_field[i] <= 'Z')) {
general_field_type[i] = ALPHA_OR_ISO;
}
if (general_field[i] == '*') {
general_field_type[i] = ALPHA_OR_ISO;
}
if (general_field[i] == ',') {
general_field_type[i] = ALPHA_OR_ISO;
}
if (general_field[i] == '-') {
general_field_type[i] = ALPHA_OR_ISO;
}
if (general_field[i] == '.') {
general_field_type[i] = ALPHA_OR_ISO;
}
if (general_field[i] == '/') {
general_field_type[i] = ALPHA_OR_ISO;
}
/* Numeric encodation */
if ((general_field[i] >= '0') && (general_field[i] <= '9')) {
general_field_type[i] = ANY_ENC;
}
if (general_field[i] == '[') {
/* FNC1 can be encoded in any system */
general_field_type[i] = ANY_ENC;
}
}
general_field_type[strlen(general_field)] = '\0';
if (latch == 1) {
if (!general_field_encode(general_field, &mode, &last_digit, binary_string)) {
/* Invalid characters in input data */
strcpy(symbol->errtxt, "441: Invalid characters in input data");
return ZINT_ERROR_INVALID_DATA;
}
for (i = 0; i < (int) strlen(general_field); i++) {
if ((general_field_type[i] == ISOIEC) && (general_field[i + 1] == '[')) {
general_field_type[i + 1] = ISOIEC;
}
}
for (i = 0; i < (int) strlen(general_field); i++) {
if ((general_field_type[i] == ALPHA_OR_ISO) && (general_field[i + 1] == '[')) {
general_field_type[i + 1] = ALPHA_OR_ISO;
}
}
latch = general_rules(general_field_type);
i = 0;
do {
switch (general_field_type[i]) {
case NUMERIC:
if (i != 0) {
if ((general_field_type[i - 1] != NUMERIC) && (general_field[i - 1] != '[')) {
bin_append(0, 3, binary_string); /* Numeric latch */
}
}
if (general_field[i] != '[') {
d1 = ctoi(general_field[i]);
} else {
d1 = 10;
}
if (general_field[i + 1] != '[') {
d2 = ctoi(general_field[i + 1]);
} else {
d2 = 10;
}
bin_append((11 * d1) + d2 + 8, 7, binary_string);
i += 2;
break;
case ALPHA:
if (i != 0) {
if ((general_field_type[i - 1] == NUMERIC) || (general_field[i - 1] == '[')) {
bin_append(0, 4, binary_string); /* Alphanumeric latch */
}
if (general_field_type[i - 1] == ISOIEC) {
bin_append(4, 5, binary_string); /* ISO/IEC 646 latch */
}
} else {
bin_append(0, 4, binary_string); /* Alphanumeric latch */
}
if ((general_field[i] >= '0') && (general_field[i] <= '9')) {
bin_append(general_field[i] - 43, 5, binary_string);
}
if ((general_field[i] >= 'A') && (general_field[i] <= 'Z')) {
bin_append(general_field[i] - 33, 6, binary_string);
}
switch (general_field[i]) {
case '[':
bin_append(15, 5, binary_string);
break;
case '*':
bin_append(58, 6, binary_string);
break;
case ',':
bin_append(59, 6, binary_string);
break;
case '-':
bin_append(60, 6, binary_string);
break;
case '.':
bin_append(61, 6, binary_string);
break;
case '/':
bin_append(62, 6, binary_string);
break;
}
i++;
break;
case ISOIEC:
if (i != 0) {
if ((general_field_type[i - 1] == NUMERIC) || (general_field[i - 1] == '[')) {
bin_append(0, 4, binary_string); /* Alphanumeric latch */
bin_append(4, 5, binary_string); /* ISO/IEC 646 latch */
}
if (general_field_type[i - 1] == ALPHA) {
bin_append(4, 5, binary_string);; /* ISO/IEC 646 latch */
}
} else {
bin_append(0, 4, binary_string); /* Alphanumeric latch */
bin_append(4, 5, binary_string); /* ISO/IEC 646 latch */
}
if ((general_field[i] >= '0') && (general_field[i] <= '9')) {
bin_append(general_field[i] - 43, 5, binary_string);
}
if ((general_field[i] >= 'A') && (general_field[i] <= 'Z')) {
bin_append(general_field[i] - 1, 7, binary_string);
}
if ((general_field[i] >= 'a') && (general_field[i] <= 'z')) {
bin_append(general_field[i] - 7, 7, binary_string);
}
if (general_field[i] == '[') strcat(binary_string, "01111"); /* FNC1/Numeric latch */
if (general_field[i] == '!') strcat(binary_string, "11101000"); /* exclamation mark */
if (general_field[i] == 34) strcat(binary_string, "11101001"); /* quotation mark */
if (general_field[i] == 37) strcat(binary_string, "11101010"); /* percent sign */
if (general_field[i] == '&') strcat(binary_string, "11101011"); /* ampersand */
if (general_field[i] == 39) strcat(binary_string, "11101100"); /* apostrophe */
if (general_field[i] == '(') strcat(binary_string, "11101101"); /* left parenthesis */
if (general_field[i] == ')') strcat(binary_string, "11101110"); /* right parenthesis */
if (general_field[i] == '*') strcat(binary_string, "11101111"); /* asterisk */
if (general_field[i] == '+') strcat(binary_string, "11110000"); /* plus sign */
if (general_field[i] == ',') strcat(binary_string, "11110001"); /* comma */
if (general_field[i] == '-') strcat(binary_string, "11110010"); /* minus or hyphen */
if (general_field[i] == '.') strcat(binary_string, "11110011"); /* period or full stop */
if (general_field[i] == '/') strcat(binary_string, "11110100"); /* slash or solidus */
if (general_field[i] == ':') strcat(binary_string, "11110101"); /* colon */
if (general_field[i] == ';') strcat(binary_string, "11110110"); /* semicolon */
if (general_field[i] == '<') strcat(binary_string, "11110111"); /* less-than sign */
if (general_field[i] == '=') strcat(binary_string, "11111000"); /* equals sign */
if (general_field[i] == '>') strcat(binary_string, "11111001"); /* greater-than sign */
if (general_field[i] == '?') strcat(binary_string, "11111010"); /* question mark */
if (general_field[i] == '_') strcat(binary_string, "11111011"); /* underline or low line */
if (general_field[i] == ' ') strcat(binary_string, "11111100"); /* space */
i++;
break;
}
} while (i + latch < (int) strlen(general_field));
binary_length = (int)strlen(binary_string);
switch (cc_mode) {
case 1:
@ -1532,14 +1283,18 @@ static int cc_binary_string(struct zint_symbol *symbol, const char source[], cha
remainder = target_bitsize - binary_length;
if (latch == 1) {
i = 0;
if (last_digit) {
/* There is still one more numeric digit to encode */
if ((remainder >= 4) && (remainder <= 6)) {
bin_append(ctoi(general_field[i]) + 1, 4, binary_string);
/* ISO/IEC 24723:2010 5.4.1 c) 2) "If four to six bits remain, add 1 to the digit value and encode the result in the next four bits. ..." */
bin_append(ctoi(last_digit) + 1, 4, binary_string);
if (remainder > 4) {
/* "... The fifth and sixth bits, if present, shall be “0”s." (Covered by adding truncated alphanumeric latch below but do explicitly anyway) */
bin_append(0, remainder - 4, binary_string);
}
} else {
bin_append((11 * ctoi(general_field[i])) + 18, 7, binary_string);
bin_append((11 * ctoi(last_digit)) + 18, 7, binary_string);
/* This may push the symbol up to the next size */
}
}
@ -1549,7 +1304,6 @@ static int cc_binary_string(struct zint_symbol *symbol, const char source[], cha
return ZINT_ERROR_TOO_LONG;
}
binary_length = (int)strlen(binary_string);
switch (cc_mode) {
case 1:
@ -1573,10 +1327,10 @@ static int cc_binary_string(struct zint_symbol *symbol, const char source[], cha
if (alpha_pad == 1) {
strcat(binary_string, "11111");
alpha_pad = 0;
/* Extra FNC1 character required after Alpha encodation (section 5.2.3) */
/* Extra FNC1 character required after Alpha encodation (section 5.3.3) */
}
if ((strlen(general_field) != 0) && (general_field_type[strlen(general_field) - 1] == NUMERIC)) {
if (mode == NUMERIC) {
strcat(binary_string, "0000");
}
@ -1716,6 +1470,9 @@ int composite(struct zint_symbol *symbol, unsigned char source[], int length) {
i = cc_binary_string(symbol, (char *) source, binary_string, cc_mode, &cc_width, &ecc_level, linear_width);
if (i == ZINT_ERROR_TOO_LONG) {
cc_mode = 2;
memset(binary_string, 0, bs);
} else if (i != 0) {
return i;
}
}
@ -1725,17 +1482,19 @@ int composite(struct zint_symbol *symbol, unsigned char source[], int length) {
if (i == ZINT_ERROR_TOO_LONG) {
if (symbol->symbology != BARCODE_EAN128_CC) {
return ZINT_ERROR_TOO_LONG;
} else {
cc_mode = 3;
}
cc_mode = 3;
memset(binary_string, 0, bs);
} else if (i != 0) {
return i;
}
}
if (cc_mode == 3) {
/* If the data didn't fit in CC-B (and linear part is GS1-128) it is recalculated for CC-C */
i = cc_binary_string(symbol, (char *) source, binary_string, cc_mode, &cc_width, &ecc_level, linear_width);
if (i == ZINT_ERROR_TOO_LONG) {
return ZINT_ERROR_TOO_LONG;
if (i != 0) {
return i;
}
}
@ -1823,6 +1582,23 @@ int composite(struct zint_symbol *symbol, unsigned char source[], int length) {
break;
case BARCODE_EAN128_CC: if (cc_mode == 3) {
bottom_shift = 7;
} else {
/* ISO/IEC 24723:2010 12.3 g) "GS1-128 components linked to the right quiet zone of the CC-A or CC-B: the CC-A or CC-B component is
aligned with the last space module of one of the rightmost symbol characters of the linear component. To
calculate the target Code 128 symbol character position for alignment, number the positions from right to
left (0 is the Stop character, 1 is the Check character, etc.), and then Position = (total number of Code 128 symbol characters 9) div 2"
*/
int num_symbols = (linear_width - 2) / 11;
int position = (num_symbols - 9) / 2;
int calc_shift = linear->width - position * 11 - 1 - symbol->width; /* Less 1 to align with last space module */
if (position) {
calc_shift -= 2; /* Less additional stop modules */
}
if (calc_shift > 0) {
top_shift = calc_shift;
} else if (calc_shift < 0) {
bottom_shift = -calc_shift;
}
}
break;
case BARCODE_RSS14_CC: bottom_shift = 4;
@ -1895,5 +1671,3 @@ int composite(struct zint_symbol *symbol, unsigned char source[], int length) {
return error_number;
}

View file

@ -29,13 +29,7 @@
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#define NUMERIC 110
#define ALPHA 97
#define ISOIEC 105
#define INVALID_CHAR 100
#define ANY_ENC 120
#define ALPHA_OR_ISO 121
/* vim: set ts=4 sw=4 et : */
/* CC-A component coefficients from ISO/IEC 24728:2006 Annex F */
static const unsigned short int ccaCoeffs[30] = {

187
backend/general_field.c Normal file
View file

@ -0,0 +1,187 @@
/* general_field.c - Handles general field compaction (GS1 DataBar and composites) */
/*
libzint - the open source barcode library
Copyright (C) 2008-2019 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/* vim: set ts=4 sw=4 et : */
#include <string.h>
#include "common.h"
#include "general_field.h"
static char alphanum_puncs[] = "*,-./";
static char isoiec_puncs[] = "!\"%&'()*+,-./:;<=>?_ ";
/* Returns type of char at `i`. FNC1 counted as NUMERIC. Returns 0 if invalid char */
static int general_field_type(char* general_field, int i) {
if (general_field[i] == '[' || (general_field[i] >= '0' && general_field[i] <= '9')) {
return NUMERIC;
}
if ((general_field[i] >= 'A' && general_field[i] <= 'Z') || strchr(alphanum_puncs, general_field[i])) {
return ALPHA;
}
if ((general_field[i] >= 'a' && general_field[i] <= 'z') || strchr(isoiec_puncs, general_field[i])) {
return ISOIEC;
}
return 0;
}
/* Returns true if next (including `i`) `num` chars of type `type`, or if given (non-zero), `type2` */
static int general_field_next(char* general_field, int i, int general_field_len, int num, int type, int type2) {
if (i + num > general_field_len) {
return 0;
}
for (; i < general_field_len && num; i++, num--) {
int type_i = general_field_type(general_field, i);
if ((type_i != type && !type2) || (type_i != type && type_i != type2)) {
return 0;
}
}
return num == 0;
}
/* Returns true if next (including `i`) `num` up to `max_num` chars of type `type` and occur at end */
static int general_field_next_terminate(char* general_field, int i, int general_field_len, int num, int max_num, int type) {
if (i + max_num < general_field_len) {
return 0;
}
for (; i < general_field_len; i++, num--) {
if (general_field_type(general_field, i) != type) {
return 0;
}
}
return i == general_field_len && num <= 0;
}
/* Returns true if none of the next (including `i`) `num` chars (or end occurs) of type `type` */
static int general_field_next_none(char* general_field, int i, int general_field_len, int num, int type) {
for (; i < general_field_len && num; i++, num--) {
if (general_field_type(general_field, i) == type) {
return 0;
}
}
return num == 0 || i == general_field_len;
}
/* Attempts to apply encoding rules from sections 7.2.5.5.1 to 7.2.5.5.3
* of ISO/IEC 24724:2010 (same as sections 5.4.1 to 5.4.3 of ISO/IEC 24723:2010) */
int general_field_encode(char* general_field, int* p_mode, int* p_last_digit, char binary_string[]) {
int i, d1, d2;
int mode = *p_mode;
int last_digit = 0; /* Set to odd remaining digit at end if any */
int general_field_len = strlen(general_field);
for (i = 0; i < general_field_len; ) {
int type = general_field_type(general_field, i);
if (!type) {
return 0;
}
switch (mode) {
case NUMERIC:
if (i < general_field_len - 1) { /* If at least 2 characters remain */
if (type != NUMERIC || general_field_type(general_field, i + 1) != NUMERIC) { /* 7.2.5.5.1/5.4.1 a) */
strcat(binary_string, "0000"); /* Alphanumeric latch */
mode = ALPHA;
} else {
d1 = general_field[i] == '[' ? 10 : ctoi(general_field[i]);
d2 = general_field[i + 1] == '[' ? 10 : ctoi(general_field[i + 1]);
bin_append((11 * d1) + d2 + 8, 7, binary_string);
i += 2;
}
} else { /* If 1 character remains */
if (type != NUMERIC) { /* 7.2.5.5.1/5.4.1 b) */
strcat(binary_string, "0000"); /* Alphanumeric latch */
mode = ALPHA;
} else {
last_digit = general_field[i]; /* Ending with single digit. 7.2.5.5.1 c) and 5.4.1 c) dealt with separately outside this procedure */
i++;
}
}
break;
case ALPHA:
if (general_field[i] == '[') { /* 7.2.5.5.2/5.4.2 a) */
strcat(binary_string, "01111");
mode = NUMERIC;
i++;
} else if (type == ISOIEC) { /* 7.2.5.5.2/5.4.2 b) */
strcat(binary_string, "00100"); /* ISO/IEC 646 latch */
mode = ISOIEC;
} else if (general_field_next(general_field, i, general_field_len, 6, NUMERIC, 0)) { /* 7.2.5.5.2/5.4.2 c) */
strcat(binary_string, "000"); /* Numeric latch */
mode = NUMERIC;
} else if (general_field_next_terminate(general_field, i, general_field_len, 4, 5 /*Can limit to 5 max due to above*/, NUMERIC)) { /* 7.2.5.5.2/5.4.2 d) */
strcat(binary_string, "000"); /* Numeric latch */
mode = NUMERIC;
} else if ((general_field[i] >= '0') && (general_field[i] <= '9')) {
bin_append(general_field[i] - 43, 5, binary_string);
i++;
} else if ((general_field[i] >= 'A') && (general_field[i] <= 'Z')) {
bin_append(general_field[i] - 33, 6, binary_string);
i++;
} else {
bin_append(posn(alphanum_puncs, general_field[i]) + 58, 6, binary_string);
i++;
}
break;
case ISOIEC:
if (general_field[i] == '[') { /* 7.2.5.5.3/5.4.3 a) */
strcat(binary_string, "01111");
mode = NUMERIC;
i++;
} else {
int next_10_not_isoiec = general_field_next_none(general_field, i, general_field_len, 10, ISOIEC);
if (next_10_not_isoiec && general_field_next(general_field, i, general_field_len, 4, NUMERIC, 0)) { /* 7.2.5.5.3/5.4.3 b) */
strcat(binary_string, "000"); /* Numeric latch */
mode = NUMERIC;
} else if (next_10_not_isoiec && general_field_next(general_field, i, general_field_len, 5, ALPHA, NUMERIC)) { /* 7.2.5.5.3/5.4.3 c) */
/* Note this rule can produce longer bitstreams if most of the alphanumerics are numeric */
strcat(binary_string, "00100"); /* Alphanumeric latch */
mode = ALPHA;
} else if ((general_field[i] >= '0') && (general_field[i] <= '9')) {
bin_append(general_field[i] - 43, 5, binary_string);
i++;
} else if ((general_field[i] >= 'A') && (general_field[i] <= 'Z')) {
bin_append(general_field[i] - 1, 7, binary_string);
i++;
} else if ((general_field[i] >= 'a') && (general_field[i] <= 'z')) {
bin_append(general_field[i] - 7, 7, binary_string);
i++;
} else {
bin_append(posn(isoiec_puncs, general_field[i]) + 232, 8, binary_string);
i++;
}
}
break;
}
}
*p_mode = mode;
*p_last_digit = last_digit;
return 1;
}

47
backend/general_field.h Normal file
View file

@ -0,0 +1,47 @@
/*
libzint - the open source barcode library
Copyright (C) 2007-2017 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the project nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
/* vim: set ts=4 sw=4 et : */
#ifndef __GENERAL_FIELD_H
#define __GENERAL_FIELD_H
#define NUMERIC 110
#define ALPHA 97
#define ISOIEC 105
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
extern int general_field_encode(char* general_field, int* p_mode, int* p_last_digit, char binary_string[]);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GENERAL_FIELD_H */

File diff suppressed because it is too large Load diff

View file

@ -63,23 +63,23 @@ static void test_gs1_reduce(void)
"11010011100111101011101100110110010110011100100010110001110001011011000010100110111101101011001110010001011000111010111101100011101011"
},
/* 4*/ { BARCODE_EAN128_CC, -1, "[01]12345678901234", "[21]1234", 0, "Input mode ignored",
"1101101110110100001000001101001100111011000010011101001100001010001100010010011011000000110110001010000000000000000000000000000000000000000000000"
"1101101100111110100010011001101011100100000010011001001001111001011110011101011001000000110010001010000000000000000000000000000000000000000000000"
"1101101000101111100110000101001111010000001010011001101011101110011110010011110110000110111010001010000000000000000000000000000000000000000000000"
"0000000000000000000001101101110110100001000001101001100111011000010011101001100001010001100010010011011000000110110001010000000000000000000000000"
"0000000000000000000001101101100111110100010011001101011100100000010011001001001111001011110011101011001000000110010001010000000000000000000000000"
"0000000000000000000001101101000101111100110000101001111010000001010011001101011101110011110010011110110000110111010001010000000000000000000000000"
"0010110001100001010001001100100110100110001101110100111000111010010011110101100100001001010011000110111010011100010100001011010000110011100010100"
"1101001110011110101110110011011001011001110010001011000111000101101100001010011011110110101100111001000101100011101011110100101111001100011101011"
},
/* 5*/ { BARCODE_EAN128_CC, GS1_MODE, "[01]12345678901234", "[21]1234", 0, "Input mode ignored",
"1101101110110100001000001101001100111011000010011101001100001010001100010010011011000000110110001010000000000000000000000000000000000000000000000"
"1101101100111110100010011001101011100100000010011001001001111001011110011101011001000000110010001010000000000000000000000000000000000000000000000"
"1101101000101111100110000101001111010000001010011001101011101110011110010011110110000110111010001010000000000000000000000000000000000000000000000"
"0000000000000000000001101101110110100001000001101001100111011000010011101001100001010001100010010011011000000110110001010000000000000000000000000"
"0000000000000000000001101101100111110100010011001101011100100000010011001001001111001011110011101011001000000110010001010000000000000000000000000"
"0000000000000000000001101101000101111100110000101001111010000001010011001101011101110011110010011110110000110111010001010000000000000000000000000"
"0010110001100001010001001100100110100110001101110100111000111010010011110101100100001001010011000110111010011100010100001011010000110011100010100"
"1101001110011110101110110011011001011001110010001011000111000101101100001010011011110110101100111001000101100011101011110100101111001100011101011"
},
/* 6*/ { BARCODE_EAN128_CC, UNICODE_MODE, "[01]12345678901234", "[21]1234", 0, "Input mode ignored",
"1101101110110100001000001101001100111011000010011101001100001010001100010010011011000000110110001010000000000000000000000000000000000000000000000"
"1101101100111110100010011001101011100100000010011001001001111001011110011101011001000000110010001010000000000000000000000000000000000000000000000"
"1101101000101111100110000101001111010000001010011001101011101110011110010011110110000110111010001010000000000000000000000000000000000000000000000"
"0000000000000000000001101101110110100001000001101001100111011000010011101001100001010001100010010011011000000110110001010000000000000000000000000"
"0000000000000000000001101101100111110100010011001101011100100000010011001001001111001011110011101011001000000110010001010000000000000000000000000"
"0000000000000000000001101101000101111100110000101001111010000001010011001101011101110011110010011110110000110111010001010000000000000000000000000"
"0010110001100001010001001100100110100110001101110100111000111010010011110101100100001001010011000110111010011100010100001011010000110011100010100"
"1101001110011110101110110011011001011001110010001011000111000101101100001010011011110110101100111001000101100011101011110100101111001100011101011"
},
@ -233,8 +233,6 @@ static void test_hrt(void)
/* 1*/ { BARCODE_EAN128_CC, "[01]12345678901234[20]12", "[21]12345", "(01)12345678901234(20)12" },
/* 2*/ { BARCODE_RSS_EXP, "[01]12345678901234[20]12", "", "(01)12345678901234(20)12" },
/* 3*/ { BARCODE_RSS_EXP_CC, "[01]12345678901234", "[21]12345", "(01)12345678901234" },
/* 4*/ { BARCODE_RSS_EXPSTACK, "[20]12", "", "(20)12" },
/* 5*/ { BARCODE_RSS_EXPSTACK_CC, "[20]12", "[21]12345", "(20)12" },
};
int data_size = sizeof(data) / sizeof(struct item);

View file

@ -30,8 +30,6 @@
#include "testcommon.h"
extern int general_rules(char type[]);
//#define TEST_RSS_BINARY_DIV_MODULO_DIVISOR_GENERATE_EXPECTED 1
static void test_binary_div_modulo_divisor(void)

View file

@ -273,7 +273,7 @@ char* testUtilErrorName(int error_number) {
int val;
};
struct item data[] = {
{ -1, "", 0 },
{ 0, "0", 0 },
{ -1, "", 1 },
{ ZINT_WARN_INVALID_OPTION, "ZINT_WARN_INVALID_OPTION", 2 },
{ ZINT_WARN_USES_ECI, "ZINT_WARN_USES_ECI", 3 },