int rssexpanded()

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;
		}