1
0
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:
gitlost
2026-03-30 21:25:22 +01:00
parent 3c193d7306
commit f9a493522f
40 changed files with 1706 additions and 920 deletions

View File

@@ -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, &current_mode, gs1, debug_print);
&b256_start, &current_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, &current_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);
}