in Sharing/Src/External/zint-2.4.3/src/backend/rss.c [1863:2249]
int rssexpanded(struct zint_symbol *symbol, unsigned char source[], int src_len)
{ /* GS1 DataBar Expanded */
int i, j, k, l, data_chars, vs[21], group[21], v_odd[21], v_even[21];
char substring[21][14], latch;
int char_widths[21][8], checksum, check_widths[8], c_group;
int check_char, c_odd, c_even, elements[235], pattern_width, reader, writer;
int row, elements_in_sub, special_case_row, left_to_right;
int codeblocks, sub_elements[235], stack_rows, current_row, current_block;
int separator_row;
#ifndef _MSC_VER
char reduced[src_len], binary_string[7 * src_len];
#else
char* reduced = (char*)_alloca(src_len);
char* binary_string = (char*)_alloca(7 * src_len);
#endif
separator_row = 0;
reader=0;
if(symbol->input_mode != GS1_MODE) {
/* GS1 data has not been verified yet */
i = gs1_verify(symbol, source, src_len, reduced);
if(i != 0) { return i; }
}
if((symbol->symbology == BARCODE_RSS_EXP_CC) || (symbol->symbology == BARCODE_RSS_EXPSTACK_CC)) {
/* make space for a composite separator pattern */
separator_row = symbol->rows;
symbol->row_height[separator_row] = 1;
symbol->rows += 1;
}
strcpy(binary_string, "");
if(symbol->option_1 == 2) {
concat(binary_string, "1");
} else {
concat(binary_string, "0");
}
i = rss_binary_string(symbol, reduced, binary_string);
if(i != 0) {
return i;
}
data_chars = strlen(binary_string) / 12;
for(i = 0; i < data_chars; i++) {
for(j = 0; j < 12; j++) {
substring[i][j] = binary_string[(i * 12) + j];
}
substring[i][12] = '\0';
}
for(i = 0; i < data_chars; i++) {
vs[i] = 0;
if(substring[i][0] == '1') { vs[i] += 2048; }
if(substring[i][1] == '1') { vs[i] += 1024; }
if(substring[i][2] == '1') { vs[i] += 512; }
if(substring[i][3] == '1') { vs[i] += 256; }
if(substring[i][4] == '1') { vs[i] += 128; }
if(substring[i][5] == '1') { vs[i] += 64; }
if(substring[i][6] == '1') { vs[i] += 32; }
if(substring[i][7] == '1') { vs[i] += 16; }
if(substring[i][8] == '1') { vs[i] += 8; }
if(substring[i][9] == '1') { vs[i] += 4; }
if(substring[i][10] == '1') { vs[i] += 2; }
if(substring[i][11] == '1') { vs[i] += 1; }
}
for(i = 0; i < data_chars; i++) {
if(vs[i] <= 347) { group[i] = 1; }
if((vs[i] >= 348) && (vs[i] <= 1387)) { group[i] = 2; }
if((vs[i] >= 1388) && (vs[i] <= 2947)) { group[i] = 3; }
if((vs[i] >= 2948) && (vs[i] <= 3987)) { group[i] = 4; }
if(vs[i] >= 3988) { group[i] = 5; }
v_odd[i] = (vs[i] - g_sum_exp[group[i] - 1]) / t_even_exp[group[i] - 1];
v_even[i] = (vs[i] - g_sum_exp[group[i] - 1]) % t_even_exp[group[i] - 1];
getRSSwidths(v_odd[i], modules_odd_exp[group[i] - 1], 4, widest_odd_exp[group[i] - 1], 0);
char_widths[i][0] = widths[0];
char_widths[i][2] = widths[1];
char_widths[i][4] = widths[2];
char_widths[i][6] = widths[3];
getRSSwidths(v_even[i], modules_even_exp[group[i] - 1], 4, widest_even_exp[group[i] - 1], 1);
char_widths[i][1] = widths[0];
char_widths[i][3] = widths[1];
char_widths[i][5] = widths[2];
char_widths[i][7] = widths[3];
}
/* 7.2.6 Check character */
/* The checksum value is equal to the mod 211 residue of the weighted sum of the widths of the
elements in the data characters. */
checksum = 0;
for(i = 0; i < data_chars; i++) {
row = weight_rows[(((data_chars - 2) / 2) * 21) + i];
for(j = 0; j < 8; j++) {
checksum += (char_widths[i][j] * checksum_weight_exp[(row * 8) + j]);
}
}
check_char = (211 * ((data_chars + 1) - 4)) + (checksum % 211);
if(check_char <= 347) { c_group = 1; }
if((check_char >= 348) && (check_char <= 1387)) { c_group = 2; }
if((check_char >= 1388) && (check_char <= 2947)) { c_group = 3; }
if((check_char >= 2948) && (check_char <= 3987)) { c_group = 4; }
if(check_char >= 3988) { c_group = 5; }
c_odd = (check_char - g_sum_exp[c_group - 1]) / t_even_exp[c_group - 1];
c_even = (check_char - g_sum_exp[c_group - 1]) % t_even_exp[c_group - 1];
getRSSwidths(c_odd, modules_odd_exp[c_group - 1], 4, widest_odd_exp[c_group - 1], 0);
check_widths[0] = widths[0];
check_widths[2] = widths[1];
check_widths[4] = widths[2];
check_widths[6] = widths[3];
getRSSwidths(c_even, modules_even_exp[c_group - 1], 4, widest_even_exp[c_group - 1], 1);
check_widths[1] = widths[0];
check_widths[3] = widths[1];
check_widths[5] = widths[2];
check_widths[7] = widths[3];
/* Initialise element array */
pattern_width = ((((data_chars + 1) / 2) + ((data_chars + 1) & 1)) * 5) + ((data_chars + 1) * 8) + 4;
for(i = 0; i < pattern_width; i++) {
elements[i] = 0;
}
elements[0] = 1;
elements[1] = 1;
elements[pattern_width - 2] = 1;
elements[pattern_width - 1] = 1;
/* Put finder patterns in element array */
for(i = 0; i < (((data_chars + 1) / 2) + ((data_chars + 1) & 1)); i++) {
k = ((((((data_chars + 1) - 2) / 2) + ((data_chars + 1) & 1)) - 1) * 11) + i;
for(j = 0; j < 5; j++) {
elements[(21 * i) + j + 10] = finder_pattern_exp[((finder_sequence[k] - 1) * 5) + j];
}
}
/* Put check character in element array */
for(i = 0; i < 8; i++) {
elements[i + 2] = check_widths[i];
}
/* Put forward reading data characters in element array */
for(i = 1; i < data_chars; i += 2) {
for(j = 0; j < 8; j++) {
elements[(((i - 1) / 2) * 21) + 23 + j] = char_widths[i][j];
}
}
/* Put reversed data characters in element array */
for(i = 0; i < data_chars; i += 2) {
for(j = 0; j < 8; j++) {
elements[((i / 2) * 21) + 15 + j] = char_widths[i][7 - j];
}
}
if((symbol->symbology == BARCODE_RSS_EXP) || (symbol->symbology == BARCODE_RSS_EXP_CC)) {
/* Copy elements into symbol */
writer = 0;
latch = '0';
for(i = 0; i < pattern_width; i++) {
for(j = 0; j < elements[i]; j++) {
if(latch == '1') { set_module(symbol, symbol->rows, writer); } else { unset_module(symbol, symbol->rows, writer); }
writer++;
}
if(latch == '1') {
latch = '0';
} else {
latch = '1';
}
}
if(symbol->width < writer) { symbol->width = writer; }
symbol->rows = symbol->rows + 1;
if(symbol->symbology == BARCODE_RSS_EXP_CC) {
for(j = 4; j < (symbol->width - 4); j++) {
if(module_is_set(symbol, separator_row + 1, j)) {
unset_module(symbol, separator_row, j);
} else {
set_module(symbol, separator_row, j);
}
}
/* finder bar adjustment */
for(j = 0; j < (writer / 49); j++) {
k = (49 * j) + 18;
for(i = 0; i < 15; i++) {
if((!(module_is_set(symbol, separator_row + 1, i + k - 1))) &&
(!(module_is_set(symbol, separator_row + 1, i + k))) &&
module_is_set(symbol, separator_row, i + k - 1)) {
unset_module(symbol, separator_row, i + k);
}
}
}
}
/* Add human readable text */
for(i = 0; i <= src_len; i++) {
if((source[i] != '[') && (source[i] != ']')) {
symbol->text[i] = source[i];
} else {
if(source[i] == '[') {
symbol->text[i] = '(';
}
if(source[i] == ']') {
symbol->text[i] = ')';
}
}
}
} else {
/* RSS Expanded Stacked */
codeblocks = (data_chars + 1) / 2;
if((symbol->option_2 < 1) || (symbol->option_2 > 10)) {
symbol->option_2 = 2;
}
if((symbol->option_1 == 2) && (symbol->option_2 == 1)) {
/* "There shall be a minimum of four symbol characters in the
first row of an RSS Expanded Stacked symbol when it is the linear
component of an EAN.UCC Composite symbol." */
symbol->option_2 = 2;
}
stack_rows = codeblocks / symbol->option_2;
if(codeblocks % symbol->option_2 > 0) {
stack_rows++;
}
current_block = 0;
for(current_row = 1; current_row <= stack_rows; current_row++) {
for(i = 0; i < 235; i++) {
sub_elements[i] = 0;
}
special_case_row = 0;
/* Row Start */
sub_elements[0] = 1;
sub_elements[1] = 1;
elements_in_sub = 2;
/* Row Data */
reader = 0;
do {
if(((symbol->option_2 & 1) || (current_row & 1)) ||
((current_row == stack_rows) && (codeblocks != (current_row * symbol->option_2)) &&
(((current_row * symbol->option_2) - codeblocks) & 1))) {
/* left to right */
left_to_right = 1;
i = 2 + (current_block * 21);
for(j = 0; j < 21; j++) {
sub_elements[j + (reader * 21) + 2] = elements[i + j];
elements_in_sub++;
}
} else {
/* right to left */
left_to_right = 0;
if((current_row * symbol->option_2) < codeblocks) {
/* a full row */
i = 2 + (((current_row * symbol->option_2) - reader - 1) * 21);
for(j = 0; j < 21; j++) {
sub_elements[(20 - j) + (reader * 21) + 2] = elements[i + j];
elements_in_sub++;
}
} else {
/* a partial row */
k = ((current_row * symbol->option_2) - codeblocks);
l = (current_row * symbol->option_2) - reader - 1;
i = 2 + ((l - k) * 21);
for(j = 0; j < 21; j++) {
sub_elements[(20 - j) + (reader * 21) + 2] = elements[i + j];
elements_in_sub++;
}
}
}
reader++;
current_block++;
} while ((reader < symbol->option_2) && (current_block < codeblocks));
/* Row Stop */
sub_elements[elements_in_sub] = 1;
sub_elements[elements_in_sub + 1] = 1;
elements_in_sub += 2;
latch = current_row & 1 ? '0' : '1';
if ((current_row == stack_rows) && (codeblocks != (current_row * symbol->option_2)) &&
(((current_row * symbol->option_2) - codeblocks) & 1) ) {
/* Special case bottom row */
special_case_row = 1;
sub_elements[0] = 2;
latch = '0';
}
writer = 0;
for(i = 0; i < elements_in_sub; i++) {
for(j = 0; j < sub_elements[i]; j++) {
if(latch == '1') { set_module(symbol, symbol->rows, writer); } else { unset_module(symbol, symbol->rows, writer); }
writer++;
}
if(latch == '1') {
latch = '0';
} else {
latch = '1';
}
}
if(symbol->width < writer) { symbol->width = writer; }
if(current_row != 1) {
/* middle separator pattern (above current row) */
for(j = 5; j < (49 * symbol->option_2); j += 2) {
set_module(symbol, symbol->rows - 2, j);
}
symbol->row_height[symbol->rows - 2] = 1;
/* bottom separator pattern (above current row) */
for(j = 4; j < (writer - 4); j++) {
if(module_is_set(symbol, symbol->rows, j)) {
unset_module(symbol, symbol->rows - 1, j);
} else {
set_module(symbol, symbol->rows - 1, j);
}
}
symbol->row_height[symbol->rows - 1] = 1;
/* finder bar adjustment */
for(j = 0; j < reader; j++) {
k = (49 * j) + (special_case_row ? 19 : 18);
if(left_to_right) {
for(i = 0; i < 15; i++) {
if((!(module_is_set(symbol, symbol->rows, i + k - 1))) &&
(!(module_is_set(symbol, symbol->rows, i + k))) &&
module_is_set(symbol, symbol->rows - 1, i + k - 1)) {
unset_module(symbol, symbol->rows - 1, i + k);
}
}
} else {
for(i = 14; i >= 0; i--) {
if((!(module_is_set(symbol, symbol->rows, i + k + 1))) &&
(!(module_is_set(symbol, symbol->rows, i + k))) &&
module_is_set(symbol, symbol->rows - 1, i + k + 1)) {
unset_module(symbol, symbol->rows - 1, i + k);
}
}
}
}
}
if(current_row != stack_rows) {
/* top separator pattern (below current row) */
for(j = 4; j < (writer - 4); j++) {
if(module_is_set(symbol, symbol->rows, j)) {
unset_module(symbol, symbol->rows + 1, j);
} else {
set_module(symbol, symbol->rows + 1, j);
}
}
symbol->row_height[symbol->rows + 1] = 1;
/* finder bar adjustment */
for(j = 0; j < reader; j++) {
k = (49 * j) + 18;
if(left_to_right) {
for(i = 0; i < 15; i++) {
if((!(module_is_set(symbol, symbol->rows, i + k - 1))) &&
(!(module_is_set(symbol, symbol->rows, i + k))) &&
module_is_set(symbol, symbol->rows + 1, i + k - 1)) {
unset_module(symbol, symbol->rows + 1, i + k);
}
}
} else{
for(i = 14; i >= 0; i--) {
if((!(module_is_set(symbol, symbol->rows, i + k + 1))) &&
(!(module_is_set(symbol, symbol->rows, i + k))) &&
module_is_set(symbol, symbol->rows + 1, i + k + 1)) {
unset_module(symbol, symbol->rows + 1, i + k);
}
}
}
}
}
symbol->rows = symbol->rows + 4;
}