1
0
mirror of https://git.code.sf.net/p/zint/code synced 2026-05-09 15:43:47 +00:00

DATAMATRIX: add manual FNC1 support

CODE128: error on unrecognized extra escape sequences instead of
  just passing them thru;
  fix possible shifting before manual FNC1 in 2nd position
  after single alpha (otherwise won't be recognized as AIM)
  fix not removing manual FNC1 in 1st/2nd position from content
  segs (as implied by symbology identifier)
CLI: warn if both "--dmre" and "--square" given (as "--square"
  overwrites "--dmre")
common: new routines `z_isalpha()`, `z_extra_escapes()` and
  `z_ct_set_seg_extra_escapes_eci()`
library: new helper `supports_extra_escape_mode()`;
  fix some error_number dups
BWIPP: update to latest, and allow for removal of DBAR_LTD_CC RHS
  quiet zones & extra row when have add-on in EAN/UPC composites
test suite: fix BWIPP escaping
manual/man/tcl: update for DATAMATRIX manual FNC1 support
Windows: resource scripts: make more consistent (libzint, CLI, GUI)
win32/README: update with MSVC 2026
This commit is contained in:
gitlost
2026-04-18 22:55:52 +01:00
parent f9a493522f
commit 7b076717f2
30 changed files with 1650 additions and 869 deletions

View File

@@ -226,7 +226,7 @@ static int c128_cost(const unsigned char source[], const int length, const int i
https://github.com/bwipp/postscriptbarcode/pull/278 */
static int c128_set_values(const unsigned char source[], const int length, const int start_idx,
const char priority[C128_STATES], const char fncs[C128_MAX], const char manuals[C128_MAX],
int values[C128_VALUES_MAX], int *p_final_cset) {
int values[C128_VALUES_MAX], int *p_first_cset, int *p_final_cset) {
short (*costs)[C128_STATES] = (short (*)[C128_STATES]) z_alloca(sizeof(*costs) * length);
char (*modes)[C128_STATES] = (char (*)[C128_STATES]) z_alloca(sizeof(*modes) * length);
@@ -243,6 +243,18 @@ static int c128_set_values(const unsigned char source[], const int length, const
return costs[0][0];
}
if (p_first_cset) {
*p_first_cset = modes[0][0];
}
/* Make sure FNC1 in 2nd position after single alpha does not switch modes before FNC1 */
if (length > 1 && !fncs[0] && fncs[1] && z_isalpha(source[0])) {
const int mode = modes[0][0];
if (mode == (mode & 0x0F) && mode != modes[1][mode]) {
modes[1][mode] = mode;
}
}
/* Output codewords into `values` */
for (i = 0; i < length; i++) {
const unsigned char ch = source[i];
@@ -377,6 +389,7 @@ INTERNAL int zint_code128(struct zint_symbol *symbol, unsigned char source[], in
char priority[C128_STATES];
int values[C128_VALUES_MAX] = {0};
int glyph_count;
int first_cset;
unsigned char src_buf[C128_MAX + 1];
unsigned char *src = source;
const int ab_only = symbol->symbology == BARCODE_CODE128AB;
@@ -397,23 +410,27 @@ INTERNAL int zint_code128(struct zint_symbol *symbol, unsigned char source[], in
char manual = 0;
int j = 0;
for (i = 0; i < length; i++) {
if (source[i] == '\\' && i + 2 < length && source[i + 1] == '^'
&& ((source[i + 2] >= '@' && source[i + 2] <= 'C') || source[i + 2] == '1'
|| source[i + 2] == '^')) {
if (source[i + 2] == '^') { /* Escape sequence '\^^' */
manuals[j] = manual;
src_buf[j++] = source[i++];
manuals[j] = manual;
src_buf[j++] = source[i++];
/* Drop second '^' */
} else if (source[i + 2] == '1') { /* FNC1 */
i += 2;
fncs[j] = have_fnc1 = 1;
manuals[j] = manual;
src_buf[j++] = '\x1D'; /* Manual FNC1 dummy */
} else { /* Manual mode A/B/C/@ */
i += 2;
manual = source[i] == 'C' ? C128_C0 : source[i] - '@'; /* Assuming A0 = 1, B0 = 2 */
if (source[i] == '\\' && i + 2 < length && source[i + 1] == '^') {
const unsigned char ch = source[i + 2];
if ((ch >= '@' && ch <= 'C') || ch == '1' || ch == '^') {
if (ch == '^') { /* Escape sequence '\^^' */
manuals[j] = manual;
src_buf[j++] = source[i++];
manuals[j] = manual;
src_buf[j++] = source[i++];
/* Drop second '^' */
} else if (ch == '1') { /* FNC1 */
i += 2;
fncs[j] = have_fnc1 = 1;
manuals[j] = manual;
src_buf[j++] = '\x1D'; /* Manual FNC1 dummy */
} else { /* Manual mode A/B/C/@ */
i += 2;
manual = ch == 'C' ? C128_C0 : ch - '@'; /* Assuming A0 = 1, B0 = 2 */
}
} else {
return z_errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 348, "Unrecognized extra escape \"\\^%c\"",
!z_isascii(ch) || z_iscntrl(ch) ? '?' : ch);
}
} else {
manuals[j] = manual;
@@ -468,7 +485,8 @@ INTERNAL int zint_code128(struct zint_symbol *symbol, unsigned char source[], in
}
c128_set_priority(priority, have_a, have_b, have_c, have_extended);
glyph_count = c128_set_values(src, length, start_idx, priority, fncs, manuals, values, NULL /*p_final_cset*/);
glyph_count = c128_set_values(src, length, start_idx, priority, fncs, manuals, values, &first_cset,
NULL /*p_final_cset*/);
if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("Data (%d): %.*s", length, length >= 100 ? 1 : length >= 10 ? 2 : 3, " ");
@@ -487,6 +505,36 @@ INTERNAL int zint_code128(struct zint_symbol *symbol, unsigned char source[], in
/* ISO/IEC 15417:2007 leaves dimensions/height as application specification */
/* Do content segs before HRT to deal with manual FNC1s in 1st position & 2nd position */
if (content_segs) {
if (have_fnc1) {
int mv_idx = 0;
assert(length > 0);
/* Remove manual FNC1 in 1st position */
if (fncs[0]) {
mv_idx = 1;
/* Remove manual FNC1 in 2nd position, alphabetic */
} else if (length > 1 && fncs[1] && z_isalpha(src[0])) {
mv_idx = 2;
/* Remove manual FNC1 in 2nd position, 2 digits */
} else if (first_cset == C128_C0 && length > 2 && fncs[2] && z_isdigit(src[0]) && z_isdigit(src[1])) {
mv_idx = 3;
}
if (mv_idx) {
memmove(src + (mv_idx - 1), src + mv_idx, length - mv_idx);
memmove(fncs + (mv_idx - 1), fncs + mv_idx, length - mv_idx);
length--;
}
}
if ((symbol->input_mode & 0x07) == DATA_MODE) {
if (z_ct_cpy(symbol, src, length)) {
return ZINT_ERROR_MEMORY; /* `z_ct_cpy()` only fails with OOM */
}
} else if (z_ct_cpy_iso8859_1(symbol, src, length)) {
return ZINT_ERROR_MEMORY; /* `z_ct_cpy_iso8859_1()` only fails with OOM */
}
}
/* HRT */
if (have_fnc1) {
/* Remove any manual FNC1 dummies ('\x1D') */
@@ -500,16 +548,6 @@ INTERNAL int zint_code128(struct zint_symbol *symbol, unsigned char source[], in
}
error_number = z_hrt_cpy_iso8859_1(symbol, src, length); /* Returns warning only */
if (content_segs) {
if ((symbol->input_mode & 0x07) == DATA_MODE) {
if (z_ct_cpy(symbol, src, length)) {
return ZINT_ERROR_MEMORY; /* `z_ct_cpy()` only fails with OOM */
}
} else if (z_ct_cpy_iso8859_1(symbol, src, length)) {
return ZINT_ERROR_MEMORY; /* `z_ct_cpy_iso8859_1()` only fails with OOM */
}
}
return error_number;
}
@@ -553,7 +591,7 @@ INTERNAL int zint_gs1_128_cc(struct zint_symbol *symbol, unsigned char source[],
c128_set_priority(priority, 0 /*have_a*/, 1 /*have_b*/, 1 /*have_c*/, 0 /*have_extended*/);
glyph_count = c128_set_values(reduced, reduced_length, 1 /*start_idx*/, priority, fncs, manuals, values,
&final_cset);
NULL /*p_first_cset*/, &final_cset);
if (symbol->debug & ZINT_DEBUG_PRINT) {
printf("Data (%d): %.*s", reduced_length, reduced_length >= 100 ? 1 : reduced_length >= 10 ? 2 : 3, " ");