#include <assert.h>
#include <math.h>
#include <stdio.h>
#include "common.h"
#include "pdf417.h"
#include "gs1.h"
#include "general_field.h"
#include "composite.h"
INTERNAL int zint_gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_mode,
const int cc_rows);
INTERNAL int zint_eanx_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows);
INTERNAL int zint_ean_leading_zeroes(struct zint_symbol *symbol, const unsigned char source[], const int length,
unsigned char local_source[], int *p_with_addon, unsigned char *zfirst_part,
unsigned char *zsecond_part);
INTERNAL int zint_dbar_omnstk_set_height(struct zint_symbol *symbol, const int first_row);
INTERNAL int zint_dbar_omn_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows);
INTERNAL int zint_dbar_ltd_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows);
INTERNAL int zint_dbar_exp_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_rows);
INTERNAL int zint_dbar_exp_date(const unsigned char source[], const int length, const int position);
static int cc_min(const int first, const int second) {
if (first <= second)
return first;
else
return second;
}
static int cc_getBit(const unsigned short *bitStr, const int bitPos) {
return !!(bitStr[bitPos >> 4] & (0x8000 >> (bitPos & 15)));
}
static int cc_encode928(const unsigned short bitString[], unsigned short codeWords[], const int bitLng) {
int i, j, b, cwNdx, cwLng;
for (cwNdx = cwLng = b = 0; b < bitLng; b += 69, cwNdx += 7) {
const int bitCnt = cc_min(bitLng - b, 69);
int cwCnt;
cwLng += cwCnt = bitCnt / 10 + 1;
for (i = 0; i < cwCnt; i++)
codeWords[cwNdx + i] = 0;
for (i = 0; i < bitCnt; i++) {
if (cc_getBit(bitString, b + bitCnt - i - 1)) {
for (j = 0; j < cwCnt; j++)
codeWords[cwNdx + j] += cc_pwr928[i][j + 7 - cwCnt];
}
}
for (i = cwCnt - 1; i > 0; i--) {
codeWords[cwNdx + i - 1] += codeWords[cwNdx + i] / 928;
codeWords[cwNdx + i] %= 928;
}
}
return (cwLng);
}
static void cc_a(struct zint_symbol *symbol, const char source[], const int cc_width) {
int i, segment, bitlen, cwCnt, variant;
int k, offset, j, total, rsCodeWords[8] = {0};
int LeftRAPStart, RightRAPStart, CentreRAPStart, StartCluster;
int LeftRAP, RightRAP, CentreRAP, Cluster;
int loop;
unsigned short codeWords[28] = {0};
unsigned short bitStr[13] = {0};
char pattern[580];
int bp = 0;
const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
variant = 0;
bitlen = (int) strlen(source);
for (segment = 0; segment < 13; segment++) {
const int strpos = segment * 16;
if (strpos >= bitlen) {
break;
}
for (i = 0; i < 16 && strpos + i < bitlen; i++) {
if (source[strpos + i] == '1') {
bitStr[segment] |= (0x8000 >> i);
}
}
}
cwCnt = cc_encode928(bitStr, codeWords, bitlen);
switch (cc_width) {
case 2:
switch (cwCnt) {
case 6: variant = 0; break;
case 8: variant = 1; break;
case 9: variant = 2; break;
case 11: variant = 3; break;
case 12: variant = 4; break;
case 14: variant = 5; break;
case 17: variant = 6; break;
}
break;
case 3:
switch (cwCnt) {
case 8: variant = 7; break;
case 10: variant = 8; break;
case 12: variant = 9; break;
case 14: variant = 10; break;
case 17: variant = 11; break;
}
break;
case 4:
switch (cwCnt) {
case 8: variant = 12; break;
case 11: variant = 13; break;
case 14: variant = 14; break;
case 17: variant = 15; break;
case 20: variant = 16; break;
}
break;
}
symbol->rows = cc_aVariants[variant];
k = cc_aVariants[17 + variant];
offset = cc_aVariants[34 + variant];
for (i = 0; i < cwCnt; i++) {
total = (codeWords[i] + rsCodeWords[k - 1]) % 929;
for (j = k - 1; j >= 0; j--) {
if (j == 0) {
rsCodeWords[j] = (929 - (total * cc_aCoeffs[offset + j]) % 929) % 929;
} else {
rsCodeWords[j] = (rsCodeWords[j - 1] + 929 - (total * cc_aCoeffs[offset + j]) % 929) % 929;
}
}
}
for (j = 0; j < k; j++) {
if (rsCodeWords[j] != 0) {
rsCodeWords[j] = 929 - rsCodeWords[j];
}
}
for (i = k - 1; i >= 0; i--) {
codeWords[cwCnt] = rsCodeWords[i];
cwCnt++;
}
LeftRAPStart = cc_aRAPTable[variant];
CentreRAPStart = cc_aRAPTable[variant + 17];
RightRAPStart = cc_aRAPTable[variant + 34];
StartCluster = cc_aRAPTable[variant + 51] / 3;
LeftRAP = LeftRAPStart;
CentreRAP = CentreRAPStart;
RightRAP = RightRAPStart;
Cluster = StartCluster;
for (i = 0; i < symbol->rows; i++) {
bp = 0;
offset = 929 * Cluster;
k = i * cc_width;
if (cc_width != 3) {
bp = z_bin_append_posn(zint_pdf_rap_side[LeftRAP - 1], 10, pattern, bp);
}
bp = z_bin_append_posn(zint_pdf_bitpattern[offset + codeWords[k]], 16, pattern, bp);
pattern[bp++] = '0';
if (cc_width >= 2) {
if (cc_width == 3) {
bp = z_bin_append_posn(zint_pdf_rap_centre[CentreRAP - 1], 10, pattern, bp);
}
bp = z_bin_append_posn(zint_pdf_bitpattern[offset + codeWords[k + 1]], 16, pattern, bp);
pattern[bp++] = '0';
if (cc_width >= 3) {
if (cc_width == 4) {
bp = z_bin_append_posn(zint_pdf_rap_centre[CentreRAP - 1], 10, pattern, bp);
}
bp = z_bin_append_posn(zint_pdf_bitpattern[offset + codeWords[k + 2]], 16, pattern, bp);
pattern[bp++] = '0';
if (cc_width == 4) {
bp = z_bin_append_posn(zint_pdf_bitpattern[offset + codeWords[k + 3]], 16, pattern, bp);
pattern[bp++] = '0';
}
}
}
bp = z_bin_append_posn(zint_pdf_rap_side[RightRAP - 1], 10, pattern, bp);
pattern[bp++] = '1';
for (loop = 0; loop < bp; loop++) {
if (pattern[loop] == '1') {
z_set_module(symbol, i, loop);
}
}
symbol->row_height[i] = 2;
LeftRAP++;
CentreRAP++;
RightRAP++;
Cluster++;
if (LeftRAP == 53) {
LeftRAP = 1;
}
if (CentreRAP == 53) {
CentreRAP = 1;
}
if (RightRAP == 53) {
RightRAP = 1;
}
if (Cluster == 3) {
Cluster = 0;
}
}
symbol->width = bp;
if (debug_print) {
printf("CC-A Columns: %d, Rows: %d, Variant: %d, CodeWords: %d\n", cc_width, symbol->rows, variant, cwCnt);
}
}
static void cc_b(struct zint_symbol *symbol, const char source[], const int cc_width) {
const int length = (int) strlen(source) / 8;
int i;
unsigned char *data_string = (unsigned char *) z_alloca(length + 3);
short chainemc[180];
int mclength = 0;
int k, j, p, longueur, mccorrection[50] = {0}, offset;
int total;
char pattern[580];
int variant, LeftRAPStart, CentreRAPStart, RightRAPStart, StartCluster;
int LeftRAP, CentreRAP, RightRAP, Cluster, loop;
int columns;
int bp = 0;
const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
for (i = 0; i < length; i++) {
const int binloc = i * 8;
data_string[i] = 0;
for (p = 0; p < 8; p++) {
if (source[binloc + p] == '1') {
data_string[i] |= (0x80 >> p);
}
}
}
chainemc[mclength++] = 920;
zint_pdf_byteprocess(chainemc, &mclength, data_string, 0, length, 0);
variant = 0;
if (cc_width == 2) {
if (mclength <= 8) {
variant = 7;
} else if (mclength <= 13) {
variant = 8;
} else if (mclength <= 19) {
variant = 9;
} else if (mclength <= 24) {
variant = 10;
} else if (mclength <= 29) {
variant = 11;
} else if (mclength <= 33) {
variant = 12;
} else {
variant = 13;
}
} else if (cc_width == 3) {
if (mclength <= 6) {
variant = 14;
} else if (mclength <= 10) {
variant = 15;
} else if (mclength <= 14) {
variant = 16;
} else if (mclength <= 18) {
variant = 17;
} else if (mclength <= 24) {
variant = 18;
} else if (mclength <= 34) {
variant = 19;
} else if (mclength <= 46) {
variant = 20;
} else if (mclength <= 58) {
variant = 21;
} else if (mclength <= 70) {
variant = 22;
} else {
variant = 23;
}
} else if (cc_width == 4) {
if (mclength <= 8) {
variant = 24;
} else if (mclength <= 12) {
variant = 25;
} else if (mclength <= 18) {
variant = 26;
} else if (mclength <= 24) {
variant = 27;
} else if (mclength <= 30) {
variant = 28;
} else if (mclength <= 39) {
variant = 29;
} else if (mclength <= 54) {
variant = 30;
} else if (mclength <= 72) {
variant = 31;
} else if (mclength <= 90) {
variant = 32;
} else if (mclength <= 108) {
variant = 33;
} else {
variant = 34;
}
}
variant--;
assert(variant >= 0);
columns = zint_pdf_MicroVariants[variant];
symbol->rows = zint_pdf_MicroVariants[variant + 34];
k = zint_pdf_MicroVariants[variant + 68];
longueur = (columns * symbol->rows) - k;
i = longueur - mclength;
offset = zint_pdf_MicroVariants[variant + 102];
while (i > 0) {
chainemc[mclength++] = 900;
i--;
}
longueur = mclength;
for (i = 0; i < longueur; i++) {
total = (chainemc[i] + mccorrection[k - 1]) % 929;
for (j = k - 1; j >= 0; j--) {
if (j == 0) {
mccorrection[j] = (929 - (total * zint_pdf_Microcoeffs[offset + j]) % 929) % 929;
} else {
mccorrection[j] = (mccorrection[j - 1] + 929 - (total * zint_pdf_Microcoeffs[offset + j]) % 929)
% 929;
}
}
}
for (j = 0; j < k; j++) {
if (mccorrection[j] != 0) {
mccorrection[j] = 929 - mccorrection[j];
}
}
for (i = k - 1; i >= 0; i--) {
chainemc[mclength++] = mccorrection[i];
}
LeftRAPStart = zint_pdf_RAPTable[variant];
CentreRAPStart = zint_pdf_RAPTable[variant + 34];
RightRAPStart = zint_pdf_RAPTable[variant + 68];
StartCluster = zint_pdf_RAPTable[variant + 102] / 3;
LeftRAP = LeftRAPStart;
CentreRAP = CentreRAPStart;
RightRAP = RightRAPStart;
Cluster = StartCluster;
for (i = 0; i < symbol->rows; i++) {
bp = 0;
offset = 929 * Cluster;
k = i * columns;
bp = z_bin_append_posn(zint_pdf_rap_side[LeftRAP - 1], 10, pattern, bp);
bp = z_bin_append_posn(zint_pdf_bitpattern[offset + chainemc[k]], 16, pattern, bp);
pattern[bp++] = '0';
if (cc_width >= 2) {
if (cc_width == 3) {
bp = z_bin_append_posn(zint_pdf_rap_centre[CentreRAP - 1], 10, pattern, bp);
}
bp = z_bin_append_posn(zint_pdf_bitpattern[offset + chainemc[k + 1]], 16, pattern, bp);
pattern[bp++] = '0';
if (cc_width >= 3) {
if (cc_width == 4) {
bp = z_bin_append_posn(zint_pdf_rap_centre[CentreRAP - 1], 10, pattern, bp);
}
bp = z_bin_append_posn(zint_pdf_bitpattern[offset + chainemc[k + 2]], 16, pattern, bp);
pattern[bp++] = '0';
if (cc_width == 4) {
bp = z_bin_append_posn(zint_pdf_bitpattern[offset + chainemc[k + 3]], 16, pattern, bp);
pattern[bp++] = '0';
}
}
}
bp = z_bin_append_posn(zint_pdf_rap_side[RightRAP - 1], 10, pattern, bp);
pattern[bp++] = '1';
for (loop = 0; loop < bp; loop++) {
if (pattern[loop] == '1') {
z_set_module(symbol, i, loop);
}
}
symbol->row_height[i] = 2;
LeftRAP++;
CentreRAP++;
RightRAP++;
Cluster++;
if (LeftRAP == 53) {
LeftRAP = 1;
}
if (CentreRAP == 53) {
CentreRAP = 1;
}
if (RightRAP == 53) {
RightRAP = 1;
}
if (Cluster == 3) {
Cluster = 0;
}
}
symbol->width = bp;
if (debug_print) {
printf("CC-B Columns: %d, Rows: %d, Variant: %d, CodeWords: %d\n",
cc_width, symbol->rows, variant + 1, mclength);
}
}
static void cc_c(struct zint_symbol *symbol, const char source[], const int cc_width, const int ecc_level) {
const int length = (int) strlen(source) / 8;
int i, p;
unsigned char *data_string = (unsigned char *) z_alloca(length + 4);
short chainemc[1000];
int mclength = 0, k;
int offset, longueur, loop, total, j, mccorrection[520] = {0};
int c1, c2, c3, dummy[35];
char pattern[580];
int bp = 0;
const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
for (i = 0; i < length; i++) {
const int binloc = i * 8;
data_string[i] = 0;
for (p = 0; p < 8; p++) {
if (source[binloc + p] == '1') {
data_string[i] |= (0x80 >> p);
}
}
}
chainemc[mclength++] = 0;
chainemc[mclength++] = 920;
zint_pdf_byteprocess(chainemc, &mclength, data_string, 0, length, 0);
chainemc[0] = mclength;
if (debug_print) {
printf("CC-C Codewords (%d):", mclength);
for (i = 0; i < mclength; i++) printf(" %d", chainemc[i]);
fputc('\n', stdout);
}
k = 1;
for (i = 1; i <= (ecc_level + 1); i++) {
k *= 2;
}
switch (ecc_level) {
case 1: offset = 2; break;
case 2: offset = 6; break;
case 3: offset = 14; break;
case 4: offset = 30; break;
case 5: offset = 62; break;
case 6: offset = 126; break;
case 7: offset = 254; break;
case 8: offset = 510; break;
default: offset = 0; break;
}
longueur = mclength;
for (i = 0; i < longueur; i++) {
total = (chainemc[i] + mccorrection[k - 1]) % 929;
for (j = k - 1; j >= 0; j--) {
if (j == 0) {
mccorrection[j] = (929 - (total * zint_pdf_coefrs[offset + j]) % 929) % 929;
} else {
mccorrection[j] = (mccorrection[j - 1] + 929 - (total * zint_pdf_coefrs[offset + j]) % 929) % 929;
}
}
}
for (j = 0; j < k; j++) {
if (mccorrection[j] != 0) {
mccorrection[j] = 929 - mccorrection[j];
}
}
for (i = k - 1; i >= 0; i--) {
chainemc[mclength++] = mccorrection[i];
}
assert(cc_width > 0);
symbol->rows = mclength / cc_width;
c1 = (symbol->rows - 1) / 3;
c2 = ecc_level * 3 + (symbol->rows - 1) % 3;
c3 = cc_width - 1;
for (i = 0; i <= symbol->rows - 1; i++) {
for (j = 0; j < cc_width; j++) {
dummy[j + 1] = chainemc[i * cc_width + j];
}
k = (i / 3) * 30;
switch (i % 3) {
case 0:
dummy[0] = k + c1;
dummy[cc_width + 1] = k + c3;
offset = 0;
break;
case 1:
dummy[0] = k + c2;
dummy[cc_width + 1] = k + c1;
offset = 929;
break;
case 2:
dummy[0] = k + c3;
dummy[cc_width + 1] = k + c2;
offset = 1858;
break;
}
bp = 0;
bp = z_bin_append_posn(0x1FEA8, 17, pattern, bp);
for (j = 0; j <= cc_width + 1; j++) {
bp = z_bin_append_posn(zint_pdf_bitpattern[offset + dummy[j]], 16, pattern, bp);
pattern[bp++] = '0';
}
bp = z_bin_append_posn(0x3FA29, 18, pattern, bp);
for (loop = 0; loop < bp; loop++) {
if (pattern[loop] == '1') {
z_set_module(symbol, i, loop);
}
}
symbol->row_height[i] = 3;
}
symbol->width = bp;
if (debug_print) {
printf("CC-C Columns: %d, Rows: %d, CodeWords: %d, ECC Level: %d\n",
cc_width, symbol->rows, mclength, ecc_level);
}
}
static int cc_a_calc_padding(const int binary_length, const int cc_width) {
static const short bin_lens[3][7] = {
{ 59, 78, 88, 108, 118, 138, 167 },
{ 78, 98, 118, 138, 167, 0, 0 },
{ 78, 108, 138, 167, 197, 0, 0 },
};
const short *bin_len = bin_lens[cc_width - 2];
int target_bitsize = 0;
int i;
for (i = 0; i < ARRAY_SIZE(bin_lens[0]) && bin_len[i]; i++) {
if (binary_length <= bin_len[i]) {
target_bitsize = bin_len[i];
break;
}
}
return target_bitsize;
}
static int cc_b_calc_padding(const int binary_length, const int cc_width) {
static const short bin_lens[3][11] = {
{ 56, 104, 160, 208, 256, 296, 336, 0, 0, 0, 0 },
{ 32, 72, 112, 152, 208, 304, 416, 536, 648, 768, 0 },
{ 56, 96, 152, 208, 264, 352, 496, 672, 840, 1016, 1184 },
};
const short *bin_len = bin_lens[cc_width - 2];
int target_bitsize = 0;
int i;
for (i = 0; i < ARRAY_SIZE(bin_lens[0]) && bin_len[i]; i++) {
if (binary_length <= bin_len[i]) {
target_bitsize = bin_len[i];
break;
}
}
return target_bitsize;
}
static int cc_c_calc_padding(const int binary_length, int *p_cc_width, const int linear_width, int *p_ecc_level) {
int target_bitsize = 0;
int byte_length, codewords_used, ecc_level, ecc_codewords, rows;
int codewords_total, target_codewords, target_bytesize;
byte_length = binary_length / 8;
if (binary_length % 8 != 0) {
byte_length++;
}
codewords_used = (byte_length / 6) * 5;
codewords_used += byte_length % 6;
if (codewords_used <= 40) {
ecc_level = 2;
} else if (codewords_used <= 160) {
ecc_level = 3;
} else if (codewords_used <= 320) {
ecc_level = 4;
} else if (codewords_used <= 833) {
ecc_level = 5;
} else if (codewords_used <= 865) {
ecc_level = 4;
} else {
return 0;
}
*p_ecc_level = ecc_level;
ecc_codewords = 1 << (ecc_level + 1);
codewords_used += ecc_codewords;
codewords_used += 3;
assert(linear_width >= 68);
*p_cc_width = linear_width == 68 ? 1 : (linear_width - 52) / 17;
if (*p_cc_width > 30) {
*p_cc_width = 30;
}
assert(*p_cc_width > 0);
rows = (int) ceil((double) codewords_used / *p_cc_width);
while (rows > 30 && *p_cc_width < 30) {
(*p_cc_width)++;
rows = (int) ceil((double) codewords_used / *p_cc_width);
}
if (rows > 30) {
return 0;
}
if (rows < 3) {
rows = 3;
}
codewords_total = *p_cc_width * rows;
target_codewords = codewords_total - ecc_codewords;
target_codewords -= 3;
target_bytesize = 6 * (target_codewords / 5);
target_bytesize += target_codewords % 5;
target_bitsize = 8 * target_bytesize;
return target_bitsize;
}
static int cc_binary_string(struct zint_symbol *symbol, const unsigned char source[], const int length,
char binary_string[], const int cc_mode, int *p_cc_width, int *p_ecc_level, const int linear_width) {
int encoding_method, read_posn, alpha_pad;
int i, j, ai_crop, ai_crop_posn, fnc1_latch;
int ai90_mode, remainder;
char last_digit = '\0';
int mode;
char *general_field = (char *) z_alloca(length + 1);
int target_bitsize;
int bp = 0;
const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
encoding_method = 1;
read_posn = 0;
ai_crop = 0;
ai_crop_posn = -1;
fnc1_latch = 0;
alpha_pad = 0;
*p_ecc_level = 0;
target_bitsize = 0;
mode = GF_NUMERIC;
if (length > 1 && source[0] == '1' && (source[1] == '0' || source[1] == '1' || source[1] == '7')) {
if (source[1] == '0' || zint_dbar_exp_date(source, length, 2) >= 0) {
encoding_method = 2;
}
} else if (length > 1 && source[0] == '9' && source[1] == '0') {
encoding_method = 3;
}
if (encoding_method == 1) {
binary_string[bp++] = '0';
if (debug_print) printf("CC-%c Encodation Method: 0\n", 'A' + (cc_mode - 1));
} else if (encoding_method == 2) {
bp = z_bin_append_posn(2, 2, binary_string, bp);
if (source[1] == '0') {
bp = z_bin_append_posn(3, 2, binary_string, bp);
read_posn = 2;
} else {
assert(length >= 8);
bp = z_bin_append_posn(zint_dbar_exp_date(source, length, 2), 16, binary_string, bp);
if (source[1] == '1') {
binary_string[bp++] = '0';
} else {
binary_string[bp++] = '1';
}
read_posn = 8;
if (read_posn + 1 < length && source[read_posn] == '1' && source[read_posn + 1] == '0') {
read_posn += 2;
} else if (source[read_posn]) {
fnc1_latch = 1;
} else {
bp = z_bin_append_posn(15, 9, binary_string, bp);
}
}
if (debug_print) {
printf("CC-%c Encodation Method: 10, Compaction Field: %.*s\n", 'A' + (cc_mode - 1), read_posn, source);
}
} else if (encoding_method == 3) {
unsigned char *ninety = (unsigned char *) z_alloca(length + 1);
int ninety_len, alpha, alphanum, numeric, alpha_posn;
i = 0;
if (length > 2) {
do {
ninety[i] = source[i + 2];
i++;
} while (i + 2 < length && source[i + 2] != '\x1D');
}
ninety[i] = '\0';
ninety_len = i;
alpha = 0;
alphanum = 0;
numeric = 0;
for (i = 0; i < ninety_len; i++) {
if (z_isupper(ninety[i])) {
alpha += 1;
} else if (z_isdigit(ninety[i])) {
numeric += 1;
} else {
alphanum += 1;
}
}
alpha_posn = -1;
if (ninety_len && ninety[0] != '0') {
for (i = 0; i < ninety_len && i < 4; i++) {
if (z_isupper(ninety[i])) {
alpha_posn = i;
break;
}
if (!z_isdigit(ninety[i])) {
break;
}
}
}
if (alpha_posn != -1) {
int next_ai_posn;
int numeric_value;
int table3_letter;
bp = z_bin_append_posn(3, 2, binary_string, bp);
numeric -= alpha_posn;
alpha--;
if (alphanum == 0 && alpha > numeric) {
bp = z_bin_append_posn(3, 2, binary_string, bp);
ai90_mode = 2;
} else if (alphanum == 0 && alpha == 0) {
bp = z_bin_append_posn(2, 2, binary_string, bp);
ai90_mode = 3;
} else {
binary_string[bp++] = '0';
ai90_mode = 1;
mode = GF_ALPHANUMERIC;
}
next_ai_posn = 2 + ninety_len;
if (next_ai_posn < length && source[next_ai_posn] == '\x1D') {
if (next_ai_posn + 2 < length && source[next_ai_posn + 1] == '2' && source[next_ai_posn + 2] == '1') {
ai_crop = 1;
} else if (next_ai_posn + 4 < length
&& 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_crop = 3;
}
}
switch (ai_crop) {
case 0:
binary_string[bp++] = '0';
break;
case 1:
bp = z_bin_append_posn(2, 2, binary_string, bp);
ai_crop_posn = next_ai_posn + 1;
break;
case 3:
bp = z_bin_append_posn(3, 2, binary_string, bp);
ai_crop_posn = next_ai_posn + 1;
break;
}
numeric_value = alpha_posn ? z_to_int(ninety, alpha_posn) : 0;
table3_letter = -1;
if (numeric_value < 31) {
table3_letter = z_posn("BDHIJKLNPQRSTVWZ", ninety[alpha_posn]);
}
if (table3_letter != -1) {
bp = z_bin_append_posn(numeric_value, 5, binary_string, bp);
bp = z_bin_append_posn(table3_letter, 4, binary_string, bp);
} else {
bp = z_bin_append_posn(31, 5, binary_string, bp);
bp = z_bin_append_posn(numeric_value, 10, binary_string, bp);
bp = z_bin_append_posn(ninety[alpha_posn] - 65, 5, binary_string, bp);
}
read_posn = alpha_posn + 3;
if (ai90_mode == 2) {
do {
if (z_isupper(source[read_posn])) {
bp = z_bin_append_posn(source[read_posn] - 65, 5, binary_string, bp);
} else if (z_isdigit(source[read_posn])) {
bp = z_bin_append_posn(source[read_posn] + 4, 6, binary_string, bp);
} else if (source[read_posn] == '\x1D') {
bp = z_bin_append_posn(31, 5, binary_string, bp);
}
read_posn++;
} while (source[read_posn - 1] != '\x1D' && source[read_posn - 1] != '\0');
alpha_pad = 1;
}
if (debug_print) {
printf("CC-%c Encodation Method: 11, Compaction Field: %.*s, Binary: %.*s (%d)\n",
'A' + (cc_mode - 1), read_posn, source, bp, binary_string, bp);
}
} else {
binary_string[bp++] = '0';
read_posn = 0;
if (debug_print) printf("CC-%c Encodation Method: 0\n", 'A' + (cc_mode - 1));
}
}
j = 0;
if (fnc1_latch == 1) {
general_field[j] = '\x1D';
j++;
}
for (i = read_posn; i < length; i++) {
if (i == ai_crop_posn) {
i += ai_crop;
} else {
general_field[j] = source[i];
j++;
}
}
general_field[j] = '\0';
if (debug_print) {
printf("Mode %s, General Field: %.40s%s\n",
mode == GF_NUMERIC ? "NUMERIC" : mode == GF_ALPHANUMERIC ? "ALPHANUMERIC" : "ISO646",
general_field, j > 40 ? "..." : "");
}
if (j != 0) {
alpha_pad = 0;
if (!zint_general_field_encode(general_field, j, &mode, &last_digit, binary_string, &bp)) {
return z_errtxt(ZINT_ERROR_INVALID_DATA, symbol, 441, "Invalid character in input (2D component)");
}
}
switch (cc_mode) {
case 1:
target_bitsize = cc_a_calc_padding(bp, *p_cc_width);
break;
case 2:
target_bitsize = cc_b_calc_padding(bp, *p_cc_width);
break;
case 3:
target_bitsize = cc_c_calc_padding(bp, p_cc_width, linear_width, p_ecc_level);
break;
}
if (target_bitsize == 0) {
return z_errtxt(ZINT_ERROR_TOO_LONG, symbol, 442, "Input too long (2D component)");
}
remainder = target_bitsize - bp;
if (last_digit) {
if (remainder >= 4 && remainder <= 6) {
bp = z_bin_append_posn(z_ctoi(last_digit) + 1, 4, binary_string, bp);
if (remainder > 4) {
bp = z_bin_append_posn(0, remainder - 4, binary_string, bp);
}
} else {
bp = z_bin_append_posn(11 * z_ctoi(last_digit) + 18, 7, binary_string, bp);
}
}
switch (cc_mode) {
case 1: target_bitsize = cc_a_calc_padding(bp, *p_cc_width); break;
case 2: target_bitsize = cc_b_calc_padding(bp, *p_cc_width); break;
case 3: target_bitsize = cc_c_calc_padding(bp, p_cc_width, linear_width, p_ecc_level); break;
}
if (target_bitsize == 0) {
return z_errtxt(ZINT_ERROR_TOO_LONG, symbol, 444, "Input too long (2D component)");
}
if (bp < target_bitsize) {
if (alpha_pad == 1) {
bp = z_bin_append_posn(31, 5, binary_string, bp);
}
if (mode == GF_NUMERIC) {
bp = z_bin_append_posn(0, 4, binary_string, bp);
}
while (bp < target_bitsize) {
bp = z_bin_append_posn(4, 5, binary_string, bp);
}
}
binary_string[target_bitsize] = '\0';
if (debug_print) {
printf("ECC: %d, CC width %d\n", *p_ecc_level, *p_cc_width);
printf("Binary: %s (%d)\n", binary_string, target_bitsize);
}
return 0;
}
static int cc_linear_dummy_run(struct zint_symbol *symbol, unsigned char *source, int length) {
struct zint_symbol dummy = {0};
int error_number;
int linear_width;
dummy.symbology = BARCODE_GS1_128_CC;
dummy.option_1 = -1;
dummy.input_mode = symbol->input_mode | GS1NOCHECK_MODE;
dummy.debug = symbol->debug;
error_number = zint_gs1_128_cc(&dummy, source, length, 3 , 0 );
linear_width = dummy.width;
if (error_number >= ZINT_ERROR || (symbol->debug & ZINT_DEBUG_TEST)) {
(void) z_errtxt(0, symbol, -1, dummy.errtxt);
}
if (error_number >= ZINT_ERROR) {
return 0;
}
return linear_width;
}
INTERNAL int zint_composite(struct zint_symbol *symbol, unsigned char source[], int length) {
int error_number = 0, warn_number = 0;
int cc_mode, cc_width = 0, ecc_level = 0;
int j, i, k;
const unsigned int bs = 13 * length + 1000 + 1;
char *binary_string = (char *) z_alloca(bs);
int primary_len;
struct zint_symbol *linear;
int top_shift, bottom_shift;
int linear_width = 0;
const int content_segs = symbol->output_options & BARCODE_CONTENT_SEGS;
const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
if (debug_print) printf("Reduced length: %d\n", length);
primary_len = (int) strlen(symbol->primary);
if (primary_len == 0) {
return z_errtxt(ZINT_ERROR_INVALID_DATA, symbol, 445, "No primary (linear component)");
}
if (primary_len >= (int) sizeof(symbol->primary)) {
return z_errtxt(ZINT_ERROR_INVALID_DATA, symbol, 854,
"Invalid primary (linear component), must be NUL-terminated");
}
if (length > 2990) {
return z_errtxtf(ZINT_ERROR_TOO_LONG, symbol, 446,
"2D component input too long, requires %d characters (maximum 2990)", length);
}
cc_mode = symbol->option_1;
if (cc_mode == 3 && symbol->symbology != BARCODE_GS1_128_CC) {
return z_errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 447,
"Invalid mode (CC-C only valid with GS1-128 linear component)");
}
if (symbol->symbology == BARCODE_GS1_128_CC) {
linear_width = cc_linear_dummy_run(symbol, ZUCP(symbol->primary), primary_len);
if (linear_width == 0) {
return z_errtxt_adj(ZINT_ERROR_INVALID_DATA, symbol, "%1$s%2$s", " (linear component)");
}
if (debug_print) {
printf("GS1-128 linear width: %d\n", linear_width);
}
}
switch (symbol->symbology) {
case BARCODE_EANX_CC:
case BARCODE_EAN8_CC:
case BARCODE_EAN13_CC:
if (primary_len < 20) {
int padded_primary_len;
int with_addon;
unsigned char padded_primary[21];
if (!zint_ean_leading_zeroes(symbol, ZCUCP(symbol->primary), primary_len, padded_primary,
&with_addon, NULL, NULL)) {
return z_errtxt_adj(ZINT_ERROR_TOO_LONG, symbol, "%1$s%2$s", " (linear component)");
}
padded_primary_len = (int) z_ustrlen(padded_primary);
if (padded_primary_len <= 7 || symbol->symbology == BARCODE_EAN8_CC) {
cc_width = 3;
} else {
switch (padded_primary_len) {
case 10:
cc_width = 3;
break;
case 13:
cc_width = with_addon ? 3 : 4;
break;
case 12:
case 15:
case 16:
case 18:
case 19:
cc_width = 4;
break;
}
}
}
if (cc_width == 0) {
return z_errtxtf(ZINT_ERROR_TOO_LONG, symbol, 449, "Input length %d wrong (linear component)",
primary_len);
}
break;
case BARCODE_GS1_128_CC: cc_width = 4; break;
case BARCODE_DBAR_OMN_CC: cc_width = 4; break;
case BARCODE_DBAR_LTD_CC: cc_width = 3; break;
case BARCODE_DBAR_EXP_CC: cc_width = 4; break;
case BARCODE_UPCA_CC: cc_width = 4; break;
case BARCODE_UPCE_CC: cc_width = 2; break;
case BARCODE_DBAR_STK_CC: cc_width = 2; break;
case BARCODE_DBAR_OMNSTK_CC: cc_width = 2; break;
case BARCODE_DBAR_EXPSTK_CC: cc_width = 4; break;
}
if (cc_mode < 1 || cc_mode > 3) {
cc_mode = 1;
}
if (cc_mode == 1) {
i = cc_binary_string(symbol, source, length, binary_string, cc_mode, &cc_width, &ecc_level, linear_width);
if (i == ZINT_ERROR_TOO_LONG) {
symbol->errtxt[0] = '\0';
cc_mode = 2;
} else if (i != 0) {
return i;
}
}
if (cc_mode == 2) {
i = cc_binary_string(symbol, source, length, binary_string, cc_mode, &cc_width, &ecc_level, linear_width);
if (i == ZINT_ERROR_TOO_LONG) {
if (symbol->symbology != BARCODE_GS1_128_CC) {
return ZINT_ERROR_TOO_LONG;
}
symbol->errtxt[0] = '\0';
cc_mode = 3;
} else if (i != 0) {
return i;
}
}
if (cc_mode == 3) {
i = cc_binary_string(symbol, source, length, binary_string, cc_mode, &cc_width, &ecc_level, linear_width);
if (i != 0) {
return i;
}
}
symbol->rows = 0;
switch (cc_mode) {
case 1: cc_a(symbol, binary_string, cc_width); break;
case 2: cc_b(symbol, binary_string, cc_width); break;
case 3: cc_c(symbol, binary_string, cc_width, ecc_level); break;
default: assert(0); break;
}
if (symbol->option_1 >= 1 && symbol->option_1 <= 3 && symbol->option_1 != cc_mode) {
warn_number = ZEXT z_errtxtf(ZINT_WARN_INVALID_OPTION, symbol, 443,
"Composite type changed from CC-%1$c to CC-%2$c",
'A' + (symbol->option_1 - 1), 'A' + (cc_mode - 1));
}
symbol->option_1 = cc_mode;
linear = ZBarcode_Create();
linear->symbology = symbol->symbology;
linear->input_mode = symbol->input_mode;
#ifdef ZINT_HAVE_GS1SE
if (symbol->input_mode & GS1SYNTAXENGINE_MODE) {
linear->input_mode |= GS1NOCHECK_MODE;
}
#endif
linear->output_options = symbol->output_options;
linear->show_hrt = symbol->show_hrt;
linear->option_2 = symbol->option_2;
linear->option_3 = symbol->option_3;
linear->height = symbol->height;
linear->debug = symbol->debug;
if (linear->symbology != BARCODE_GS1_128_CC) {
linear->option_1 = 2;
}
switch (symbol->symbology) {
case BARCODE_EANX_CC:
case BARCODE_EAN8_CC:
case BARCODE_EAN13_CC:
error_number = zint_eanx_cc(linear, ZUCP(symbol->primary), primary_len, symbol->rows);
break;
case BARCODE_GS1_128_CC:
error_number = zint_gs1_128_cc(linear, ZUCP(symbol->primary), primary_len, cc_mode, symbol->rows);
break;
case BARCODE_DBAR_OMN_CC:
error_number = zint_dbar_omn_cc(linear, ZUCP(symbol->primary), primary_len, symbol->rows);
break;
case BARCODE_DBAR_LTD_CC:
error_number = zint_dbar_ltd_cc(linear, ZUCP(symbol->primary), primary_len, symbol->rows);
break;
case BARCODE_DBAR_EXP_CC:
error_number = zint_dbar_exp_cc(linear, ZUCP(symbol->primary), primary_len, symbol->rows);
break;
case BARCODE_UPCA_CC:
error_number = zint_eanx_cc(linear, ZUCP(symbol->primary), primary_len, symbol->rows);
break;
case BARCODE_UPCE_CC:
error_number = zint_eanx_cc(linear, ZUCP(symbol->primary), primary_len, symbol->rows);
break;
case BARCODE_DBAR_STK_CC:
error_number = zint_dbar_omn_cc(linear, ZUCP(symbol->primary), primary_len, symbol->rows);
break;
case BARCODE_DBAR_OMNSTK_CC:
error_number = zint_dbar_omn_cc(linear, ZUCP(symbol->primary), primary_len, symbol->rows);
break;
case BARCODE_DBAR_EXPSTK_CC:
error_number = zint_dbar_exp_cc(linear, ZUCP(symbol->primary), primary_len, symbol->rows);
break;
}
if (error_number) {
ZEXT z_errtxtf(0, symbol, -1, "%1$s%2$s", linear->errtxt, " (linear component)");
if (error_number >= ZINT_ERROR) {
ZBarcode_Delete(linear);
return error_number;
}
}
top_shift = 0;
bottom_shift = 0;
switch (symbol->symbology) {
case BARCODE_EANX_CC:
case BARCODE_EAN8_CC:
case BARCODE_EAN13_CC:
switch (linear->text_length) {
case 8:
case 11:
case 14:
if (cc_mode == 1) {
bottom_shift = 3;
} else {
bottom_shift = 13;
}
break;
case 13:
case 16:
case 19:
bottom_shift = 2;
break;
}
break;
case BARCODE_GS1_128_CC:
if (cc_mode == 3) {
bottom_shift = 7;
} else {
const int num_symbols = (linear_width - 2) / 11;
const int position = (num_symbols - 9) / 2;
int calc_shift = linear->width - position * 11 - 1 - symbol->width;
if (position) {
calc_shift -= 2;
}
if (calc_shift > 0) {
top_shift = calc_shift;
} else if (calc_shift < 0) {
bottom_shift = -calc_shift;
}
}
break;
case BARCODE_DBAR_OMN_CC:
bottom_shift = 4;
break;
case BARCODE_DBAR_LTD_CC:
if (cc_mode == 1) {
top_shift = 1;
} else {
bottom_shift = 9;
}
break;
case BARCODE_DBAR_EXP_CC:
for (k = 1; !z_module_is_set(linear, 1, k - 1) && z_module_is_set(linear, 1, k); k++);
top_shift = k;
break;
case BARCODE_UPCA_CC:
bottom_shift = 2;
break;
case BARCODE_UPCE_CC:
bottom_shift = 2;
break;
case BARCODE_DBAR_STK_CC:
top_shift = 1;
break;
case BARCODE_DBAR_OMNSTK_CC:
top_shift = 1;
break;
case BARCODE_DBAR_EXPSTK_CC:
for (k = 1; !z_module_is_set(linear, 1, k - 1) && z_module_is_set(linear, 1, k); k++);
top_shift = k;
break;
}
if (debug_print) {
printf("Top shift: %d, Bottom shift: %d\n", top_shift, bottom_shift);
}
if (top_shift != 0) {
for (i = 0; i < symbol->rows; i++) {
for (j = (symbol->width + top_shift); j >= top_shift; j--) {
if (z_module_is_set(symbol, i, j - top_shift)) {
z_set_module(symbol, i, j);
} else {
z_unset_module(symbol, i, j);
}
}
for (j = 0; j < top_shift; j++) {
z_unset_module(symbol, i, j);
}
}
}
for (i = 0; i < linear->rows; i++) {
symbol->row_height[symbol->rows + i] = linear->row_height[i];
for (j = 0; j <= linear->width; j++) {
if (z_module_is_set(linear, i, j)) {
z_set_module(symbol, i + symbol->rows, j + bottom_shift);
} else {
z_unset_module(symbol, i + symbol->rows, j + bottom_shift);
}
}
}
if (linear->width + bottom_shift > symbol->width + top_shift) {
symbol->width = linear->width + bottom_shift;
} else if (symbol->width + top_shift > linear->width + bottom_shift) {
symbol->width += top_shift;
}
symbol->rows += linear->rows;
if (symbol->output_options & COMPLIANT_HEIGHT) {
if (symbol->symbology == BARCODE_DBAR_STK_CC) {
error_number = zint_dbar_omnstk_set_height(symbol, symbol->rows - linear->rows + 1 );
} else if (symbol->symbology == BARCODE_DBAR_EXP_CC || symbol->symbology == BARCODE_DBAR_EXPSTK_CC) {
if (error_number == 0) {
error_number = z_set_height(symbol, symbol->height ? linear->height : 0.0f,
symbol->height ? 0.0f : linear->height, 0.0f, 0 );
} else {
(void) z_set_height(symbol, symbol->height ? linear->height : 0.0f,
symbol->height ? 0.0f : linear->height, 0.0f, 1 );
}
} else {
if (error_number == 0) {
error_number = z_set_height(symbol, symbol->height ? linear->height : 0.0f,
symbol->height ? 0.0f : linear->height, 0.0f, 0 );
} else {
(void) z_set_height(symbol, symbol->height ? linear->height : 0.0f,
symbol->height ? 0.0f : linear->height, 0.0f, 1 );
}
}
} else {
if (symbol->symbology == BARCODE_DBAR_STK_CC) {
(void) zint_dbar_omnstk_set_height(symbol, symbol->rows - linear->rows + 1 );
} else {
(void) z_set_height(symbol, symbol->height ? linear->height : 0.0f,
symbol->height ? 0.0f : linear->height, 0.0f, 1 );
}
}
z_hrt_cpy_nochk(symbol, linear->text, linear->text_length);
if (content_segs) {
assert(linear->content_segs && linear->content_segs[0].source);
if (z_ct_cpy_cat(symbol, linear->content_segs[0].source, linear->content_segs[0].length, '|', source,
length)) {
ZBarcode_Delete(linear);
return ZINT_ERROR_MEMORY;
}
}
ZBarcode_Delete(linear);
return error_number ? error_number : warn_number;
}