mirror of
https://git.code.sf.net/p/zint/code
synced 2026-05-14 18:13:53 +00:00
DATAMATRIX: add new options DM_B256_START and DM_C40_START to
`options_3`, allowing forcing of Base 256 or C40 mode a la BWIPP for initial no. of characters specified in `option_1`, with 0 meaning all (CLI "--dmb256=" and "--dmc40=", GUI also (apart from MAILMARK_2D, which may be added later); export masks `DM_B256_C40_START_MASK` & `DM_SQUARE_DMRE_MASK` in "zint.h" ZBarcode_Encode_File: report filename (possibly truncated) in error message on failed open GUI: uniquify some accelerators and add some child widget getter helpers to "mainwindow.cpp" backend/DEVELOPER -> backend/README, with some expansion debian/copyright: a few more fixes BWIPP/pandoc: update to latest tests/fuzz: adjust for new DATAMATRIX options
This commit is contained in:
@@ -580,8 +580,6 @@ static int dm_edi_buffer_xfer(int process_buffer[8], int process_p, unsigned cha
|
||||
return process_p;
|
||||
}
|
||||
|
||||
#define DM_DMRE_SQUARE_MASK 0x65 /* 101 */
|
||||
|
||||
/* Get index of symbol size in codewords array `dm_matrixbytes`, as specified or
|
||||
else smallest containing `minimum` codewords */
|
||||
static int dm_get_symbolsize(struct zint_symbol *symbol, const int minimum) {
|
||||
@@ -595,10 +593,11 @@ static int dm_get_symbolsize(struct zint_symbol *symbol, const int minimum) {
|
||||
}
|
||||
for (i = minimum >= 62 ? 23 : 0; minimum > dm_matrixbytes[i]; i++);
|
||||
|
||||
if ((symbol->option_3 & DM_DMRE_SQUARE_MASK) == DM_DMRE) {
|
||||
/* `DM_DMRE` trumps `DM_SQUARE` */
|
||||
if ((symbol->option_3 & DM_SQUARE_DMRE_MASK) == DM_DMRE) {
|
||||
return i;
|
||||
}
|
||||
if ((symbol->option_3 & DM_DMRE_SQUARE_MASK) == DM_SQUARE) {
|
||||
if ((symbol->option_3 & DM_SQUARE_DMRE_MASK) == DM_SQUARE) {
|
||||
/* Skip rectangular symbols in square only mode */
|
||||
for (; dm_matrixH[i] != dm_matrixW[i]; i++);
|
||||
return i;
|
||||
@@ -775,9 +774,9 @@ static int dm_getEndMode(struct zint_symbol *symbol, const unsigned char *source
|
||||
#endif
|
||||
|
||||
/* Return number of C40/TEXT codewords needed to encode characters in full batches of 3 (or less if EOD).
|
||||
The number of characters encoded is returned in `len` */
|
||||
The number of characters encoded is returned in `p_len` */
|
||||
static int dm_getNumberOfC40Words(const unsigned char *source, const int length, const int from, const int mode,
|
||||
int *len) {
|
||||
int *p_len) {
|
||||
int thirdsCount = 0;
|
||||
int i;
|
||||
|
||||
@@ -797,11 +796,11 @@ static int dm_getNumberOfC40Words(const unsigned char *source, const int length,
|
||||
|
||||
remainder = thirdsCount % 3;
|
||||
if (remainder == 0 || (remainder == 2 && i + 1 == length)) {
|
||||
*len = i - from + 1;
|
||||
*p_len = i - from + 1;
|
||||
return ((thirdsCount + 2) / 3) * 2;
|
||||
}
|
||||
}
|
||||
*len = 0;
|
||||
*p_len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1248,8 +1247,7 @@ static int dm_minimalenc(struct zint_symbol *symbol, const unsigned char source[
|
||||
/* Encode using algorithm based on ISO/IEC 21471:2020 Annex J (was ISO/IEC 21471:2006 Annex P) */
|
||||
static int dm_isoenc(struct zint_symbol *symbol, const unsigned char source[], const int length, int *p_sp,
|
||||
unsigned char target[], int *p_tp, int process_buffer[8], int *p_process_p, int *p_b256_start,
|
||||
int *p_current_mode, const int gs1, const int debug_print) {
|
||||
const int mailmark = symbol->symbology == BARCODE_MAILMARK_2D;
|
||||
int *p_current_mode, const int gs1, const int b256_end, const int c40_end, const int debug_print) {
|
||||
int sp = *p_sp;
|
||||
int tp = *p_tp;
|
||||
int process_p = *p_process_p;
|
||||
@@ -1260,21 +1258,17 @@ static int dm_isoenc(struct zint_symbol *symbol, const unsigned char source[], c
|
||||
/* step (a) */
|
||||
int next_mode = DM_ASCII;
|
||||
|
||||
if (mailmark) { /* First 45 characters C40 */
|
||||
assert(length >= 45);
|
||||
assert(b256_end <= length && c40_end <= length && (b256_end == 0 || c40_end == 0));
|
||||
if (b256_end) {
|
||||
/* First characters in Base 256 */
|
||||
next_mode = DM_BASE256;
|
||||
tp = dm_switch_mode(next_mode, target, tp, p_b256_start, debug_print);
|
||||
current_mode = next_mode;
|
||||
} else if (c40_end) {
|
||||
/* First characters in C40 */
|
||||
next_mode = DM_C40;
|
||||
tp = dm_switch_mode(next_mode, target, tp, p_b256_start, debug_print);
|
||||
while (sp < 45) {
|
||||
assert(dm_isc40(source[sp]));
|
||||
process_buffer[process_p++] = dm_c40_value[source[sp]];
|
||||
|
||||
if (process_p >= 3) {
|
||||
process_p = dm_ctx_buffer_xfer(process_buffer, process_p, target, &tp, debug_print);
|
||||
}
|
||||
sp++;
|
||||
}
|
||||
current_mode = next_mode;
|
||||
not_first = 1;
|
||||
}
|
||||
|
||||
while (sp < length) {
|
||||
@@ -1322,7 +1316,7 @@ static int dm_isoenc(struct zint_symbol *symbol, const unsigned char source[], c
|
||||
} else if (current_mode == DM_C40 || current_mode == DM_TEXT) {
|
||||
|
||||
next_mode = current_mode;
|
||||
if (process_p == 0 && not_first) {
|
||||
if (process_p == 0 && not_first && (sp >= c40_end)) { /* `c40_end` only set if `current_mode` DM_C40 */
|
||||
next_mode = dm_look_ahead_test(source, length, sp, current_mode, process_p, gs1, debug_print);
|
||||
}
|
||||
|
||||
@@ -1456,7 +1450,7 @@ static int dm_isoenc(struct zint_symbol *symbol, const unsigned char source[], c
|
||||
next_mode = DM_ASCII;
|
||||
} else {
|
||||
next_mode = DM_BASE256;
|
||||
if (not_first) {
|
||||
if (not_first && sp >= b256_end) {
|
||||
next_mode = dm_look_ahead_test(source, length, sp, current_mode, tp - (*p_b256_start + 1), gs1,
|
||||
debug_print);
|
||||
}
|
||||
@@ -1473,12 +1467,7 @@ static int dm_isoenc(struct zint_symbol *symbol, const unsigned char source[], c
|
||||
tp = dm_switch_mode(next_mode, target, tp, p_b256_start, debug_print);
|
||||
not_first = 0;
|
||||
} else {
|
||||
if (gs1 == 2 && source[sp] == '\x1D') {
|
||||
target[tp++] = 29; /* GS */
|
||||
} else {
|
||||
target[tp++] = source[sp];
|
||||
}
|
||||
sp++;
|
||||
target[tp++] = source[sp++];
|
||||
not_first = 1;
|
||||
if (debug_print) printf("B%02X ", target[tp - 1]);
|
||||
}
|
||||
@@ -1501,8 +1490,9 @@ static int dm_isoenc(struct zint_symbol *symbol, const unsigned char source[], c
|
||||
|
||||
/* Encodes data using ASCII, C40, Text, X12, EDIFACT or Base 256 modes as appropriate
|
||||
Supports encoding FNC1 in supporting systems */
|
||||
static int dm_encode(struct zint_symbol *symbol, const unsigned char source[], const int length, const int eci,
|
||||
const int last_seg, const int gs1, unsigned char target[], int *p_tp) {
|
||||
static int dm_encode(struct zint_symbol *symbol, const unsigned char source[], const int length,
|
||||
const int eci, const int last_seg, const int gs1, const int b256_end, const int c40_end,
|
||||
unsigned char target[], int *p_tp) {
|
||||
int sp = 0;
|
||||
int tp = *p_tp;
|
||||
int current_mode = DM_ASCII;
|
||||
@@ -1531,9 +1521,9 @@ static int dm_encode(struct zint_symbol *symbol, const unsigned char source[], c
|
||||
}
|
||||
|
||||
/* If FAST_MODE or MAILMARK_2D, do Annex J-based encodation */
|
||||
if ((symbol->input_mode & FAST_MODE) || symbol->symbology == BARCODE_MAILMARK_2D) {
|
||||
if ((symbol->input_mode & FAST_MODE) || b256_end || c40_end) {
|
||||
error_number = dm_isoenc(symbol, source, length, &sp, target, &tp, process_buffer, &process_p,
|
||||
&b256_start, ¤t_mode, gs1, debug_print);
|
||||
&b256_start, ¤t_mode, gs1, b256_end, c40_end, debug_print);
|
||||
} else { /* Do default minimal encodation */
|
||||
error_number = dm_minimalenc(symbol, source, length, last_seg, &sp, target, &tp, process_buffer, &process_p,
|
||||
&b256_start, ¤t_mode, gs1, debug_print);
|
||||
@@ -1681,8 +1671,9 @@ static int dm_encode(struct zint_symbol *symbol, const unsigned char source[], c
|
||||
|
||||
#ifdef ZINT_TEST /* Wrapper for direct testing */
|
||||
INTERNAL int zint_test_dm_encode(struct zint_symbol *symbol, const unsigned char source[], const int length,
|
||||
const int eci, const int last_seg, const int gs1, unsigned char target[], int *p_tp) {
|
||||
return dm_encode(symbol, source, length, eci, last_seg, gs1, target, p_tp);
|
||||
const int eci, const int last_seg, const int gs1, const int b256_end, const int c40_end,
|
||||
unsigned char target[], int *p_tp) {
|
||||
return dm_encode(symbol, source, length, eci, last_seg, gs1, b256_end, c40_end, target, p_tp);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1694,9 +1685,13 @@ static int dm_encode_segs(struct zint_symbol *symbol, struct zint_seg segs[], co
|
||||
int i;
|
||||
int tp = 0;
|
||||
int in_macro = 0;
|
||||
int tot_length = 0, b256_have_fnc1 = 0;
|
||||
const struct zint_seg *last_seg = &segs[seg_count - 1];
|
||||
/* gs1 flag values: 0: no GS1, 1: GS1 with FNC1 serparator, 2: GS separator */
|
||||
const int gs1 = (symbol->input_mode & 0x07) == GS1_MODE ? 1 + !!(symbol->output_options & GS1_GS_SEPARATOR) : 0;
|
||||
const int mailmark = symbol->symbology == BARCODE_MAILMARK_2D;
|
||||
const int have_c40 = (symbol->option_3 & DM_C40_START) && symbol->option_1 >= 0;
|
||||
const int have_b256 = (symbol->option_3 & DM_B256_START) && symbol->option_1 >= 0;
|
||||
/* Raw text dealt with by `ZBarcode_Encode_Segs()`, except for `eci` feedback.
|
||||
Note not updating `eci` for GS1 mode as not converted */
|
||||
const int content_segs = !gs1 && (symbol->output_options & BARCODE_CONTENT_SEGS);
|
||||
@@ -1803,7 +1798,10 @@ static int dm_encode_segs(struct zint_symbol *symbol, struct zint_seg segs[], co
|
||||
}
|
||||
|
||||
for (i = 0; i < seg_count; i++) {
|
||||
const unsigned char *source;
|
||||
int length;
|
||||
int src_inc = 0, len_dec = 0;
|
||||
int b256_end = 0, c40_end = 0;
|
||||
if (in_macro) {
|
||||
if (i == 0) {
|
||||
src_inc = len_dec = 7; /* Skip over macro characters at beginning */
|
||||
@@ -1812,14 +1810,54 @@ static int dm_encode_segs(struct zint_symbol *symbol, struct zint_seg segs[], co
|
||||
len_dec += 2; /* Remove RS + EOT from end */
|
||||
}
|
||||
}
|
||||
if ((error_number = dm_encode(symbol, segs[i].source + src_inc, segs[i].length - len_dec, segs[i].eci,
|
||||
i + 1 == seg_count, gs1, target, &tp))) {
|
||||
source = segs[i].source + src_inc;
|
||||
length = segs[i].length - len_dec;
|
||||
|
||||
if (mailmark) {
|
||||
assert(seg_count == 1);
|
||||
assert(length >= 45);
|
||||
c40_end = 45; /* Min */
|
||||
/* Allow specifying greater than 45 */
|
||||
if (have_c40 && (symbol->option_1 == 0 || symbol->option_1 > 45)) {
|
||||
c40_end = symbol->option_1 > 0 && symbol->option_1 < length ? symbol->option_1 : length;
|
||||
}
|
||||
/* `DM_C40_START` trumps `DM_B256_START` */
|
||||
} else if (have_c40) {
|
||||
if (symbol->option_1 == 0) {
|
||||
c40_end = length;
|
||||
} else if (symbol->option_1 < tot_length) {
|
||||
c40_end = 0;
|
||||
} else {
|
||||
c40_end = symbol->option_1 - tot_length < length ? symbol->option_1 - tot_length : length;
|
||||
}
|
||||
} else if (have_b256) {
|
||||
if (b256_have_fnc1) {
|
||||
b256_end = 0;
|
||||
} else {
|
||||
if (symbol->option_1 == 0) {
|
||||
b256_end = length;
|
||||
} else if (symbol->option_1 < tot_length) {
|
||||
b256_end = 0;
|
||||
} else {
|
||||
b256_end = symbol->option_1 - tot_length < length ? symbol->option_1 - tot_length : length;
|
||||
}
|
||||
if (gs1 == 1) {
|
||||
/* Stop at first FNC1 */
|
||||
const int b256_len = b256_end;
|
||||
for (b256_end = 0; b256_end < b256_len && source[b256_end] != '\x1D'; b256_end++);
|
||||
b256_have_fnc1 = b256_end != b256_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((error_number = dm_encode(symbol, source, length, segs[i].eci, i + 1 == seg_count, gs1, b256_end, c40_end,
|
||||
target, &tp))) {
|
||||
assert(error_number >= ZINT_ERROR);
|
||||
return error_number;
|
||||
}
|
||||
if (content_segs && segs[i].eci) {
|
||||
z_ct_set_seg_eci(symbol, i, segs[i].eci);
|
||||
}
|
||||
tot_length += length;
|
||||
}
|
||||
|
||||
*p_binlen = tp;
|
||||
@@ -1973,7 +2011,7 @@ static int dm_ecc200(struct zint_symbol *symbol, struct zint_seg segs[], const i
|
||||
|
||||
INTERNAL int zint_datamatrix(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) {
|
||||
|
||||
if (symbol->option_1 <= 1) {
|
||||
if (symbol->option_1 <= 1 || (symbol->option_3 & DM_B256_C40_START_MASK)) {
|
||||
/* ECC 200 */
|
||||
return dm_ecc200(symbol, segs, seg_count);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user