mirror of
https://git.code.sf.net/p/zint/code
synced 2026-07-30 18:09:50 +00:00
GRIDMATRIX: fix byte latch 6 -> 7, & allowing more than one
non-digit in numeral (both caused misencodation); replace `gm_macro_matrix[]` array with calculation (marginally slower but saves ~1.4k); replace `gm_shift_set[]` use with simple compares (performance); change GM_CHINESE/etc defines to numbers so can index into new `gm_shift_set[]` array (simplifies mode switching code); GM_NUMBER -> GM_NUMERAL, modules -> macromodules_per_dim, various other renamings to hopefully more explanatory names; various other changes (mostly performance) test suite: make use of new zxing-cpp diagnostics2 branch Grid Matrix decoder manual: slight clarification of `--gs1nocheck` BWIPP: latest
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
Version 2.16.0.9 (dev) not released yet (2026-06-23)
|
Version 2.16.0.9 (dev) not released yet (2026-07-06)
|
||||||
====================================================
|
====================================================
|
||||||
|
|
||||||
**Incompatible changes**
|
**Incompatible changes**
|
||||||
@@ -75,6 +75,8 @@ Bugs
|
|||||||
minimum height
|
minimum height
|
||||||
- CLI: stop looping over data args when have error
|
- CLI: stop looping over data args when have error
|
||||||
- composite: preserve `gs1_verify()` warning (if any)
|
- composite: preserve `gs1_verify()` warning (if any)
|
||||||
|
- GRIDMATRIX: fix byte latch 6 -> 7, & allowing more than one non-digit in
|
||||||
|
numeral (both caused misencodation)
|
||||||
|
|
||||||
|
|
||||||
Version 2.16.0 (2025-12-19)
|
Version 2.16.0 (2025-12-19)
|
||||||
|
|||||||
+224
-409
@@ -40,11 +40,7 @@
|
|||||||
#include "gridmtx.h"
|
#include "gridmtx.h"
|
||||||
#include "eci.h"
|
#include "eci.h"
|
||||||
|
|
||||||
static const char EUROPIUM[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ";
|
/* `gm_define_modes()` stuff */
|
||||||
static const char EUROPIUM_UPR[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
|
|
||||||
static const char EUROPIUM_LWR[] = "abcdefghijklmnopqrstuvwxyz ";
|
|
||||||
|
|
||||||
/* gm_define_modes() stuff */
|
|
||||||
|
|
||||||
/* Bits multiplied by this for costs, so as to be whole integer divisible by 2 and 3 */
|
/* Bits multiplied by this for costs, so as to be whole integer divisible by 2 and 3 */
|
||||||
#define GM_MULT 6
|
#define GM_MULT 6
|
||||||
@@ -62,8 +58,8 @@ static int gm_in_numeral(const unsigned int ddata[], const int length, const int
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Attempt to calculate the average 'cost' of using numeric mode in number of bits (times GM_MULT) */
|
/* Attempt to calculate the average 'cost' of using numeral mode in number of bits (times GM_MULT) */
|
||||||
/* Also ensures that numeric mode is not selected when it cannot be used: for example in
|
/* Also ensures that numeral mode is not selected when it cannot be used: for example in
|
||||||
a string which has "2.2.0" (cannot have more than one non-numeric character for each
|
a string which has "2.2.0" (cannot have more than one non-numeric character for each
|
||||||
block of three numeric characters) */
|
block of three numeric characters) */
|
||||||
for (i = in_posn, digit_cnt = 0, nondigit = 0, nondigit_posn = 0; i < length && i < in_posn + 4 && digit_cnt < 3;
|
for (i = in_posn, digit_cnt = 0, nondigit = 0, nondigit_posn = 0; i < length && i < in_posn + 4 && digit_cnt < 3;
|
||||||
@@ -72,13 +68,15 @@ static int gm_in_numeral(const unsigned int ddata[], const int length, const int
|
|||||||
digit_cnt++;
|
digit_cnt++;
|
||||||
} else if (z_posn(gm_numeral_nondigits, (const char) ddata[i]) != -1) {
|
} else if (z_posn(gm_numeral_nondigits, (const char) ddata[i]) != -1) {
|
||||||
if (nondigit) {
|
if (nondigit) {
|
||||||
break;
|
*p_numeral_end = 0;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
nondigit = 1;
|
nondigit = 1;
|
||||||
nondigit_posn = i;
|
nondigit_posn = i;
|
||||||
} else if (i < length - 1 && ddata[i] == 13 && ddata[i + 1] == 10) {
|
} else if (i + 1 < length && ddata[i] == 13 && ddata[i + 1] == 10) {
|
||||||
if (nondigit) {
|
if (nondigit) {
|
||||||
break;
|
*p_numeral_end = 0;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
nondigit = 2;
|
nondigit = 2;
|
||||||
@@ -107,13 +105,13 @@ static int gm_in_numeral(const unsigned int ddata[], const int length, const int
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Encoding modes */
|
/* Encoding modes */
|
||||||
#define GM_CHINESE 'H'
|
#define GM_CHINESE 1
|
||||||
#define GM_NUMBER 'N'
|
#define GM_NUMERAL 2
|
||||||
#define GM_LOWER 'L'
|
#define GM_LOWER 3
|
||||||
#define GM_UPPER 'U'
|
#define GM_UPPER 4
|
||||||
#define GM_MIXED 'M'
|
#define GM_MIXED 5
|
||||||
#define GM_BYTE 'B'
|
#define GM_BYTE 6
|
||||||
/* Note Control is a submode of Lower, Upper and Mixed modes */
|
#define GM_EOD 7 /* Pseudo-mode, used to put end of data */
|
||||||
|
|
||||||
/* Indexes into mode_types array */
|
/* Indexes into mode_types array */
|
||||||
#define GM_H 0 /* Chinese (Hanzi) */
|
#define GM_H 0 /* Chinese (Hanzi) */
|
||||||
@@ -125,12 +123,14 @@ static int gm_in_numeral(const unsigned int ddata[], const int length, const int
|
|||||||
|
|
||||||
#define GM_NUM_MODES 6
|
#define GM_NUM_MODES 6
|
||||||
|
|
||||||
|
static const char gm_debug_modes[6][5] = { "HAN ", "NUM ", "LWR ", "UPR ", "MXD ", "BYT " };
|
||||||
|
|
||||||
/* Calculate optimized encoding modes. Adapted from Project Nayuki */
|
/* Calculate optimized encoding modes. Adapted from Project Nayuki */
|
||||||
/* Copyright (c) Project Nayuki. (MIT License) See qr.c for detailed notice */
|
/* Copyright (c) Project Nayuki. (MIT License) See qr.c for detailed notice */
|
||||||
/* SPDX-License-Identifier: MIT */
|
/* SPDX-License-Identifier: MIT */
|
||||||
static void gm_define_modes(char *modes, const unsigned int ddata[], const int length, const int debug_print) {
|
static void gm_define_modes(char *modes, const unsigned int ddata[], const int length, const int debug_print) {
|
||||||
/* Must be in same order as GM_H etc */
|
/* Must be in same order as GM_H etc */
|
||||||
static const char mode_types[] = { GM_CHINESE, GM_NUMBER, GM_LOWER, GM_UPPER, GM_MIXED, GM_BYTE, '\0' };
|
static const char mode_types[] = { GM_CHINESE, GM_NUMERAL, GM_LOWER, GM_UPPER, GM_MIXED, GM_BYTE, '\0' };
|
||||||
|
|
||||||
/* Initial mode costs */
|
/* Initial mode costs */
|
||||||
static const unsigned int head_costs[GM_NUM_MODES] = {
|
static const unsigned int head_costs[GM_NUM_MODES] = {
|
||||||
@@ -156,7 +156,7 @@ static void gm_define_modes(char *modes, const unsigned int ddata[], const int l
|
|||||||
};
|
};
|
||||||
|
|
||||||
unsigned int numeral_end = 0, numeral_cost = 0, byte_count = 0; /* State */
|
unsigned int numeral_end = 0, numeral_cost = 0, byte_count = 0; /* State */
|
||||||
int double_byte, space, numeric, lower, upper, control, double_digit, eol;
|
int double_byte, space, digit, lower, upper, control, double_digit, eol;
|
||||||
|
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
unsigned int min_cost;
|
unsigned int min_cost;
|
||||||
@@ -169,7 +169,7 @@ static void gm_define_modes(char *modes, const unsigned int ddata[], const int l
|
|||||||
ends in mode_types[j] and the total number of bits is minimized over all possible choices */
|
ends in mode_types[j] and the total number of bits is minimized over all possible choices */
|
||||||
memset(char_modes, 0, length * GM_NUM_MODES);
|
memset(char_modes, 0, length * GM_NUM_MODES);
|
||||||
|
|
||||||
/* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/XX_MULT)
|
/* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/GM_MULT)
|
||||||
* bits needed to encode the entire string prefix of length i, and end in mode_types[j] */
|
* bits needed to encode the entire string prefix of length i, and end in mode_types[j] */
|
||||||
memcpy(prev_costs, head_costs, GM_NUM_MODES * sizeof(unsigned int));
|
memcpy(prev_costs, head_costs, GM_NUM_MODES * sizeof(unsigned int));
|
||||||
|
|
||||||
@@ -177,27 +177,16 @@ static void gm_define_modes(char *modes, const unsigned int ddata[], const int l
|
|||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
memset(cur_costs, 0, GM_NUM_MODES * sizeof(unsigned int));
|
memset(cur_costs, 0, GM_NUM_MODES * sizeof(unsigned int));
|
||||||
|
|
||||||
space = numeric = lower = upper = control = double_digit = eol = 0;
|
space = digit = lower = upper = control = double_digit = eol = 0;
|
||||||
|
|
||||||
double_byte = ddata[i] > 0xFF;
|
if (!(double_byte = ddata[i] > 0xFF) && !(space = ddata[i] == ' ')) {
|
||||||
if (!double_byte) {
|
if (!(digit = z_isdigit(ddata[i]))) {
|
||||||
space = ddata[i] == ' ';
|
if (!(lower = z_islower(ddata[i])) && !(upper = z_isupper(ddata[i]))) {
|
||||||
if (!space) {
|
control = ddata[i] < 0x7F; /* Exclude DEL */
|
||||||
numeric = z_isdigit(ddata[i]);
|
eol = i + 1 < length && ddata[i] == 13 && ddata[i + 1] == 10;
|
||||||
if (!numeric) {
|
|
||||||
lower = z_islower(ddata[i]);
|
|
||||||
if (!lower) {
|
|
||||||
upper = z_isupper(ddata[i]);
|
|
||||||
if (!upper) {
|
|
||||||
control = ddata[i] < 0x7F; /* Exclude DEL */
|
|
||||||
if (control && i + 1 < length) {
|
|
||||||
eol = ddata[i] == 13 && ddata[i + 1] == 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (i + 1 < length) {
|
|
||||||
double_digit = z_isdigit(ddata[i + 1]);
|
|
||||||
}
|
}
|
||||||
|
} else if (i + 1 < length) {
|
||||||
|
double_digit = z_isdigit(ddata[i + 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +209,7 @@ static void gm_define_modes(char *modes, const unsigned int ddata[], const int l
|
|||||||
|
|
||||||
if (gm_in_numeral(ddata, length, i, &numeral_end, &numeral_cost)) {
|
if (gm_in_numeral(ddata, length, i, &numeral_end, &numeral_cost)) {
|
||||||
cur_costs[GM_N] = prev_costs[GM_N] + numeral_cost;
|
cur_costs[GM_N] = prev_costs[GM_N] + numeral_cost;
|
||||||
char_modes[i][GM_N] = GM_NUMBER;
|
char_modes[i][GM_N] = GM_NUMERAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (control) {
|
if (control) {
|
||||||
@@ -239,13 +228,13 @@ static void gm_define_modes(char *modes, const unsigned int ddata[], const int l
|
|||||||
cur_costs[GM_U] = prev_costs[GM_U] + 30; /* 5 * GM_MULT */
|
cur_costs[GM_U] = prev_costs[GM_U] + 30; /* 5 * GM_MULT */
|
||||||
char_modes[i][GM_U] = GM_UPPER;
|
char_modes[i][GM_U] = GM_UPPER;
|
||||||
}
|
}
|
||||||
if (numeric || lower || upper || space) {
|
if (digit || lower || upper || space) {
|
||||||
cur_costs[GM_M] = prev_costs[GM_M] + 36; /* 6 * GM_MULT */
|
cur_costs[GM_M] = prev_costs[GM_M] + 36; /* 6 * GM_MULT */
|
||||||
char_modes[i][GM_M] = GM_MIXED;
|
char_modes[i][GM_M] = GM_MIXED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == length - 1) { /* Add end of data costs if last character */
|
if (i + 1 == length) { /* Add end of data costs if last character */
|
||||||
for (j = 0; j < GM_NUM_MODES; j++) {
|
for (j = 0; j < GM_NUM_MODES; j++) {
|
||||||
if (char_modes[i][j]) {
|
if (char_modes[i][j]) {
|
||||||
cur_costs[j] += eod_costs[j];
|
cur_costs[j] += eod_costs[j];
|
||||||
@@ -287,7 +276,9 @@ static void gm_define_modes(char *modes, const unsigned int ddata[], const int l
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (debug_print) {
|
if (debug_print) {
|
||||||
printf(" Modes: %.*s\n", length, modes);
|
fputs(" Modes: ", stdout);
|
||||||
|
for (i = 0; i < length; i++) fputc(gm_debug_modes[modes[i] - 1][0], stdout);
|
||||||
|
fputc('\n', stdout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,18 +291,19 @@ static void gm_add_byte_count(char binary[], const int byte_count_posn, const in
|
|||||||
|
|
||||||
/* Add a control character to the data stream */
|
/* Add a control character to the data stream */
|
||||||
static int gm_add_shift_char(char binary[], int bp, const int shifty, const int debug_print) {
|
static int gm_add_shift_char(char binary[], int bp, const int shifty, const int debug_print) {
|
||||||
int i;
|
int glyph;
|
||||||
int glyph = 0;
|
|
||||||
|
|
||||||
if (shifty < 32) {
|
/* See Table 7 - Encoding of control characters */
|
||||||
|
if (shifty < ' ') {
|
||||||
glyph = shifty;
|
glyph = shifty;
|
||||||
|
} else if (shifty < '0') {
|
||||||
|
glyph = shifty - 1;
|
||||||
|
} else if (shifty < 'A') {
|
||||||
|
glyph = shifty - 11;
|
||||||
|
} else if (shifty < 'a') {
|
||||||
|
glyph = shifty - 46;
|
||||||
} else {
|
} else {
|
||||||
for (i = 32; i < 64; i++) {
|
glyph = shifty - 63;
|
||||||
if (gm_shift_set[i] == shifty) {
|
|
||||||
glyph = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug_print) {
|
if (debug_print) {
|
||||||
@@ -326,19 +318,16 @@ static int gm_add_shift_char(char binary[], int bp, const int shifty, const int
|
|||||||
static int gm_encode(const unsigned int ddata[], const int length, char binary[], const int eci, int *p_bp,
|
static int gm_encode(const unsigned int ddata[], const int length, char binary[], const int eci, int *p_bp,
|
||||||
const int debug_print) {
|
const int debug_print) {
|
||||||
/* Create a binary stream representation of the input data.
|
/* Create a binary stream representation of the input data.
|
||||||
7 sets are defined - Chinese characters, Numerals, Lower case letters, Upper case letters,
|
6 sets are defined - Chinese characters, Numerals, Lower case letters, Upper case letters,
|
||||||
Mixed numerals and latters, Control characters and 8-bit binary data */
|
Mixed numerals, letters & control characters, and 8-bit binary data */
|
||||||
int sp = 0;
|
int sp = 0;
|
||||||
int current_mode = 0;
|
int current_mode = 0;
|
||||||
int last_mode;
|
int last_mode;
|
||||||
unsigned int glyph = 0;
|
unsigned int glyph = 0;
|
||||||
int c1, c2, done;
|
int numeral_cnt = 0;
|
||||||
int p = 0, ppos;
|
int numeral_pad_posn = 0;
|
||||||
int numbuf[3], punt = 0;
|
|
||||||
int number_pad_posn = 0;
|
|
||||||
int byte_count_posn = 0;
|
int byte_count_posn = 0;
|
||||||
int byte_count = 0;
|
int byte_count = 0;
|
||||||
int shift;
|
|
||||||
int bp = *p_bp;
|
int bp = *p_bp;
|
||||||
char *modes = (char *) z_alloca(length);
|
char *modes = (char *) z_alloca(length);
|
||||||
|
|
||||||
@@ -360,96 +349,25 @@ static int gm_encode(const unsigned int ddata[], const int length, char binary[]
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
const int next_mode = modes[sp];
|
const int next_mode = modes[sp];
|
||||||
|
int numbuf[3], punt = 0, nondigit_posn;
|
||||||
|
int digit;
|
||||||
|
|
||||||
if (next_mode != current_mode) {
|
if (next_mode != current_mode) {
|
||||||
switch (current_mode) {
|
if (current_mode == GM_BYTE) {
|
||||||
case 0:
|
/* Add byte block length indicator */
|
||||||
switch (next_mode) {
|
gm_add_byte_count(binary, byte_count_posn, byte_count);
|
||||||
case GM_CHINESE: bp = z_bin_append_posn(1, 4, binary, bp); break;
|
byte_count = 0;
|
||||||
case GM_NUMBER: bp = z_bin_append_posn(2, 4, binary, bp); break;
|
} else if (current_mode == GM_NUMERAL && numeral_cnt) {
|
||||||
case GM_LOWER: bp = z_bin_append_posn(3, 4, binary, bp); break;
|
/* Set numeric block padding value */
|
||||||
case GM_UPPER: bp = z_bin_append_posn(4, 4, binary, bp); break;
|
(void) z_bin_append_posn(3 - numeral_cnt, 2, binary, numeral_pad_posn);
|
||||||
case GM_MIXED: bp = z_bin_append_posn(5, 4, binary, bp); break;
|
|
||||||
case GM_BYTE: bp = z_bin_append_posn(6, 4, binary, bp); break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GM_CHINESE:
|
|
||||||
switch (next_mode) {
|
|
||||||
case GM_NUMBER: bp = z_bin_append_posn(8161, 13, binary, bp); break;
|
|
||||||
case GM_LOWER: bp = z_bin_append_posn(8162, 13, binary, bp); break;
|
|
||||||
case GM_UPPER: bp = z_bin_append_posn(8163, 13, binary, bp); break;
|
|
||||||
case GM_MIXED: bp = z_bin_append_posn(8164, 13, binary, bp); break;
|
|
||||||
case GM_BYTE: bp = z_bin_append_posn(8165, 13, binary, bp); break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GM_NUMBER:
|
|
||||||
/* add numeric block padding value */
|
|
||||||
switch (p) {
|
|
||||||
case 1:
|
|
||||||
binary[number_pad_posn] = '1';
|
|
||||||
binary[number_pad_posn + 1] = '0';
|
|
||||||
break; /* 2 pad digits */
|
|
||||||
case 2:
|
|
||||||
binary[number_pad_posn] = '0';
|
|
||||||
binary[number_pad_posn + 1] = '1';
|
|
||||||
break; /* 1 pad digits */
|
|
||||||
case 3:
|
|
||||||
binary[number_pad_posn] = '0';
|
|
||||||
binary[number_pad_posn + 1] = '0';
|
|
||||||
break; /* 0 pad digits */
|
|
||||||
}
|
|
||||||
switch (next_mode) {
|
|
||||||
case GM_CHINESE: bp = z_bin_append_posn(1019, 10, binary, bp); break;
|
|
||||||
case GM_LOWER: bp = z_bin_append_posn(1020, 10, binary, bp); break;
|
|
||||||
case GM_UPPER: bp = z_bin_append_posn(1021, 10, binary, bp); break;
|
|
||||||
case GM_MIXED: bp = z_bin_append_posn(1022, 10, binary, bp); break;
|
|
||||||
case GM_BYTE: bp = z_bin_append_posn(1023, 10, binary, bp); break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GM_LOWER:
|
|
||||||
case GM_UPPER:
|
|
||||||
switch (next_mode) {
|
|
||||||
case GM_CHINESE: bp = z_bin_append_posn(28, 5, binary, bp); break;
|
|
||||||
case GM_NUMBER: bp = z_bin_append_posn(29, 5, binary, bp); break;
|
|
||||||
case GM_LOWER:
|
|
||||||
case GM_UPPER:
|
|
||||||
bp = z_bin_append_posn(30, 5, binary, bp);
|
|
||||||
break;
|
|
||||||
case GM_MIXED: bp = z_bin_append_posn(124, 7, binary, bp); break;
|
|
||||||
case GM_BYTE: bp = z_bin_append_posn(126, 7, binary, bp); break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GM_MIXED:
|
|
||||||
switch (next_mode) {
|
|
||||||
case GM_CHINESE: bp = z_bin_append_posn(1009, 10, binary, bp); break;
|
|
||||||
case GM_NUMBER: bp = z_bin_append_posn(1010, 10, binary, bp); break;
|
|
||||||
case GM_LOWER: bp = z_bin_append_posn(1011, 10, binary, bp); break;
|
|
||||||
case GM_UPPER: bp = z_bin_append_posn(1012, 10, binary, bp); break;
|
|
||||||
case GM_BYTE: bp = z_bin_append_posn(1015, 10, binary, bp); break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GM_BYTE:
|
|
||||||
/* add byte block length indicator */
|
|
||||||
gm_add_byte_count(binary, byte_count_posn, byte_count);
|
|
||||||
byte_count = 0;
|
|
||||||
switch (next_mode) {
|
|
||||||
case GM_CHINESE: bp = z_bin_append_posn(1, 4, binary, bp); break;
|
|
||||||
case GM_NUMBER: bp = z_bin_append_posn(2, 4, binary, bp); break;
|
|
||||||
case GM_LOWER: bp = z_bin_append_posn(3, 4, binary, bp); break;
|
|
||||||
case GM_UPPER: bp = z_bin_append_posn(4, 4, binary, bp); break;
|
|
||||||
case GM_MIXED: bp = z_bin_append_posn(5, 4, binary, bp); break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
bp = z_bin_append_posn(gm_mode_switch[current_mode][next_mode - 1],
|
||||||
|
gm_mode_len[current_mode][next_mode - 1], binary, bp);
|
||||||
if (debug_print) {
|
if (debug_print) {
|
||||||
switch (next_mode) {
|
fputs(gm_debug_modes[next_mode - 1], stdout);
|
||||||
case GM_CHINESE: fputs("CHIN ", stdout); break;
|
}
|
||||||
case GM_NUMBER: fputs("NUMB ", stdout); break;
|
if (bp > 9191) {
|
||||||
case GM_LOWER: fputs("LOWR ", stdout); break;
|
return ZINT_ERROR_TOO_LONG;
|
||||||
case GM_UPPER: fputs("UPPR ", stdout); break;
|
|
||||||
case GM_MIXED: fputs("MIXD ", stdout); break;
|
|
||||||
case GM_BYTE: fputs("BYTE ", stdout); break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last_mode = current_mode;
|
last_mode = current_mode;
|
||||||
@@ -457,41 +375,27 @@ static int gm_encode(const unsigned int ddata[], const int length, char binary[]
|
|||||||
|
|
||||||
switch (current_mode) {
|
switch (current_mode) {
|
||||||
case GM_CHINESE:
|
case GM_CHINESE:
|
||||||
done = 0;
|
|
||||||
if (ddata[sp] > 0xFF) {
|
if (ddata[sp] > 0xFF) {
|
||||||
/* GB2312 character */
|
/* GB2312 character */
|
||||||
c1 = (ddata[sp] & 0xFF00) >> 8;
|
const unsigned char c1 = (ddata[sp] >> 8) & 0xFF;
|
||||||
c2 = ddata[sp] & 0xFF;
|
const unsigned char c2 = ddata[sp] & 0xFF;
|
||||||
|
|
||||||
|
/* GB 2312 always within these ranges */
|
||||||
if (c1 >= 0xA1 && c1 <= 0xA9) {
|
if (c1 >= 0xA1 && c1 <= 0xA9) {
|
||||||
glyph = 0x60 * (c1 - 0xA1) + (c2 - 0xA0);
|
glyph = 0x60 * (c1 - 0xA1) + (c2 - 0xA0);
|
||||||
} else if (c1 >= 0xB0 && c1 <= 0xF7) {
|
} else if (c1 >= 0xB0 && c1 <= 0xF7) {
|
||||||
glyph = 0x60 * (c1 - 0xB0 + 9) + (c2 - 0xA0);
|
glyph = 0x60 * (c1 - 0xB0 + 9) + (c2 - 0xA0);
|
||||||
}
|
}
|
||||||
done = 1; /* GB 2312 always within above ranges */
|
|
||||||
/* Note not using the unallocated glyphs 7776 to 8191 mentioned in AIMD014 section 6.3.1.2 */
|
/* Note not using the unallocated glyphs 7776 to 8191 mentioned in AIMD014 section 6.3.1.2 */
|
||||||
}
|
} else if (sp + 1 < length && ddata[sp] == 13 && ddata[sp + 1] == 10) {
|
||||||
if (!done) {
|
/* End of Line */
|
||||||
if (sp != length - 1) {
|
glyph = 7776;
|
||||||
if (ddata[sp] == 13 && ddata[sp + 1] == 10) {
|
sp++;
|
||||||
/* End of Line */
|
} else if (sp + 1 < length && z_isdigit(ddata[sp]) && z_isdigit(ddata[sp + 1])) {
|
||||||
glyph = 7776;
|
/* Two digits */
|
||||||
sp++;
|
glyph = 8033 + (10 * (ddata[sp] - '0')) + (ddata[sp + 1] - '0');
|
||||||
done = 1;
|
sp++;
|
||||||
}
|
} else {
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!done) {
|
|
||||||
if (sp != length - 1) {
|
|
||||||
if (z_isdigit(ddata[sp]) && z_isdigit(ddata[sp + 1])) {
|
|
||||||
/* Two digits */
|
|
||||||
glyph = 8033 + (10 * (ddata[sp] - '0')) + (ddata[sp + 1] - '0');
|
|
||||||
sp++;
|
|
||||||
done = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!done) {
|
|
||||||
/* Byte value */
|
/* Byte value */
|
||||||
glyph = 7777 + ddata[sp];
|
glyph = 7777 + ddata[sp];
|
||||||
}
|
}
|
||||||
@@ -504,55 +408,49 @@ static int gm_encode(const unsigned int ddata[], const int length, char binary[]
|
|||||||
sp++;
|
sp++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GM_NUMBER:
|
case GM_NUMERAL:
|
||||||
if (last_mode != current_mode) {
|
if (last_mode != current_mode) {
|
||||||
/* Reserve a space for numeric digit padding value (2 bits) */
|
/* Reserve a space for numeric digit padding value (2 bits) */
|
||||||
number_pad_posn = bp;
|
numeral_pad_posn = bp;
|
||||||
bp = z_bin_append_posn(0, 2, binary, bp);
|
bp = z_bin_append_posn(0, 2, binary, bp);
|
||||||
}
|
}
|
||||||
p = 0;
|
numeral_cnt = 0;
|
||||||
ppos = -1;
|
nondigit_posn = -1;
|
||||||
|
|
||||||
/* Numeric compression can also include certain combinations of
|
/* Numeral compression can also include certain combinations of non-digits */
|
||||||
non-numeric character */
|
|
||||||
|
|
||||||
numbuf[0] = '0';
|
numbuf[0] = '0';
|
||||||
numbuf[1] = '0';
|
numbuf[1] = '0';
|
||||||
numbuf[2] = '0';
|
numbuf[2] = '0';
|
||||||
do {
|
do {
|
||||||
if (z_isdigit(ddata[sp])) {
|
if (z_isdigit(ddata[sp])) {
|
||||||
numbuf[p] = ddata[sp];
|
numbuf[numeral_cnt++] = ddata[sp];
|
||||||
p++;
|
|
||||||
} else if (z_posn(gm_numeral_nondigits, (const char) ddata[sp]) != -1) {
|
} else if (z_posn(gm_numeral_nondigits, (const char) ddata[sp]) != -1) {
|
||||||
if (ppos != -1) {
|
if (nondigit_posn != -1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
punt = ddata[sp];
|
punt = ddata[sp];
|
||||||
ppos = p;
|
nondigit_posn = numeral_cnt;
|
||||||
} else if (sp < length - 1 && ddata[sp] == 13 && ddata[sp + 1] == 10) {
|
} else if (sp + 1 < length && ddata[sp] == 13 && ddata[sp + 1] == 10) {
|
||||||
/* <end of line> */
|
/* <end of line> */
|
||||||
if (ppos != -1) {
|
if (nondigit_posn != -1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
punt = ddata[sp];
|
punt = ddata[sp++];
|
||||||
sp++;
|
nondigit_posn = numeral_cnt;
|
||||||
ppos = p;
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
sp++;
|
sp++;
|
||||||
} while (p < 3 && sp < length && modes[sp] == GM_NUMBER);
|
} while (numeral_cnt < 3 && sp < length && modes[sp] == GM_NUMERAL);
|
||||||
|
|
||||||
if (ppos != -1) {
|
if (nondigit_posn != -1) {
|
||||||
switch (punt) {
|
if (punt == 13) {
|
||||||
case ' ': glyph = 0; break;
|
glyph = 15;
|
||||||
case '+': glyph = 3; break;
|
} else {
|
||||||
case '-': glyph = 6; break;
|
glyph = z_posn(gm_numeral_nondigits, punt) * 3;
|
||||||
case '.': glyph = 9; break;
|
|
||||||
case ',': glyph = 12; break;
|
|
||||||
case 13: glyph = 15; break;
|
|
||||||
}
|
}
|
||||||
glyph += ppos;
|
glyph += nondigit_posn;
|
||||||
glyph += 1000;
|
glyph += 1000;
|
||||||
|
|
||||||
if (debug_print) {
|
if (debug_print) {
|
||||||
@@ -603,28 +501,17 @@ static int gm_encode(const unsigned int ddata[], const int length, char binary[]
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GM_MIXED:
|
case GM_MIXED:
|
||||||
shift = 1;
|
if (ddata[sp] == ' ' || (digit = z_isdigit(ddata[sp])) || z_isalpha(ddata[sp])) {
|
||||||
if (z_isdigit(ddata[sp])) {
|
|
||||||
shift = 0;
|
|
||||||
} else if (z_isupper(ddata[sp])) {
|
|
||||||
shift = 0;
|
|
||||||
} else if (z_islower(ddata[sp])) {
|
|
||||||
shift = 0;
|
|
||||||
} else if (ddata[sp] == ' ') {
|
|
||||||
shift = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shift == 0) {
|
|
||||||
/* Mixed Mode character */
|
/* Mixed Mode character */
|
||||||
glyph = z_posn(EUROPIUM, (const char) ddata[sp]);
|
glyph = ddata[sp] == ' ' ? 62
|
||||||
|
: ddata[sp] - (digit ? '0' : z_isupper(ddata[sp]) ? 'A' - 10 : 'a' - 36);
|
||||||
if (debug_print) {
|
if (debug_print) {
|
||||||
printf("[%d] ", (int) glyph);
|
printf("[%d] ", (int) glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
bp = z_bin_append_posn(glyph, 6, binary, bp);
|
bp = z_bin_append_posn(glyph, 6, binary, bp);
|
||||||
} else {
|
} else {
|
||||||
/* Shift Mode character */
|
/* Shift Mode character */
|
||||||
bp = z_bin_append_posn(1014, 10, binary, bp); /* shift indicator */
|
bp = z_bin_append_posn(1014, 10, binary, bp); /* Shift indicator */
|
||||||
bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print);
|
bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,24 +519,16 @@ static int gm_encode(const unsigned int ddata[], const int length, char binary[]
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GM_UPPER:
|
case GM_UPPER:
|
||||||
shift = 1;
|
if (ddata[sp] == ' ' || z_isupper(ddata[sp])) {
|
||||||
if (z_isupper(ddata[sp])) {
|
|
||||||
shift = 0;
|
|
||||||
} else if (ddata[sp] == ' ') {
|
|
||||||
shift = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shift == 0) {
|
|
||||||
/* Upper Case character */
|
/* Upper Case character */
|
||||||
glyph = z_posn(EUROPIUM_UPR, (const char) ddata[sp]);
|
glyph = ddata[sp] == ' ' ? 26 : ddata[sp] - 'A';
|
||||||
if (debug_print) {
|
if (debug_print) {
|
||||||
printf("[%d] ", (int) glyph);
|
printf("[%d] ", (int) glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
bp = z_bin_append_posn(glyph, 5, binary, bp);
|
bp = z_bin_append_posn(glyph, 5, binary, bp);
|
||||||
} else {
|
} else {
|
||||||
/* Shift Mode character */
|
/* Shift Mode character */
|
||||||
bp = z_bin_append_posn(125, 7, binary, bp); /* shift indicator */
|
bp = z_bin_append_posn(125, 7, binary, bp); /* Shift indicator */
|
||||||
bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print);
|
bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,24 +536,16 @@ static int gm_encode(const unsigned int ddata[], const int length, char binary[]
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GM_LOWER:
|
case GM_LOWER:
|
||||||
shift = 1;
|
if (ddata[sp] == ' ' || z_islower(ddata[sp])) {
|
||||||
if (z_islower(ddata[sp])) {
|
|
||||||
shift = 0;
|
|
||||||
} else if (ddata[sp] == ' ') {
|
|
||||||
shift = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shift == 0) {
|
|
||||||
/* Lower Case character */
|
/* Lower Case character */
|
||||||
glyph = z_posn(EUROPIUM_LWR, (const char) ddata[sp]);
|
glyph = ddata[sp] == ' ' ? 26 : ddata[sp] - 'a';
|
||||||
if (debug_print) {
|
if (debug_print) {
|
||||||
printf("[%d] ", (int) glyph);
|
printf("[%d] ", (int) glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
bp = z_bin_append_posn(glyph, 5, binary, bp);
|
bp = z_bin_append_posn(glyph, 5, binary, bp);
|
||||||
} else {
|
} else {
|
||||||
/* Shift Mode character */
|
/* Shift Mode character */
|
||||||
bp = z_bin_append_posn(125, 7, binary, bp); /* shift indicator */
|
bp = z_bin_append_posn(125, 7, binary, bp); /* Shift indicator */
|
||||||
bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print);
|
bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -687,40 +558,18 @@ static int gm_encode(const unsigned int ddata[], const int length, char binary[]
|
|||||||
|
|
||||||
} while (sp < length);
|
} while (sp < length);
|
||||||
|
|
||||||
if (current_mode == GM_NUMBER) {
|
|
||||||
/* add numeric block padding value */
|
|
||||||
switch (p) {
|
|
||||||
case 1:
|
|
||||||
binary[number_pad_posn] = '1';
|
|
||||||
binary[number_pad_posn + 1] = '0';
|
|
||||||
break; /* 2 pad digits */
|
|
||||||
case 2:
|
|
||||||
binary[number_pad_posn] = '0';
|
|
||||||
binary[number_pad_posn + 1] = '1';
|
|
||||||
break; /* 1 pad digit */
|
|
||||||
case 3:
|
|
||||||
binary[number_pad_posn] = '0';
|
|
||||||
binary[number_pad_posn + 1] = '0';
|
|
||||||
break; /* 0 pad digits */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_mode == GM_BYTE) {
|
if (current_mode == GM_BYTE) {
|
||||||
/* Add byte block length indicator */
|
/* Add byte block length indicator */
|
||||||
gm_add_byte_count(binary, byte_count_posn, byte_count);
|
gm_add_byte_count(binary, byte_count_posn, byte_count);
|
||||||
|
} else if (current_mode == GM_NUMERAL && numeral_cnt) {
|
||||||
|
/* HAN numeric block padding value */
|
||||||
|
(void) z_bin_append_posn(3 - numeral_cnt, 2, binary, numeral_pad_posn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add "end of data" character */
|
/* Add "end of data" character */
|
||||||
switch (current_mode) {
|
assert(current_mode >= GM_CHINESE && current_mode <= GM_BYTE);
|
||||||
case GM_CHINESE: bp = z_bin_append_posn(8160, 13, binary, bp); break;
|
bp = z_bin_append_posn(gm_mode_switch[GM_EOD][current_mode - 1], gm_mode_len[GM_EOD][current_mode - 1],
|
||||||
case GM_NUMBER: bp = z_bin_append_posn(1018, 10, binary, bp); break;
|
binary, bp);
|
||||||
case GM_LOWER:
|
|
||||||
case GM_UPPER:
|
|
||||||
bp = z_bin_append_posn(27, 5, binary, bp);
|
|
||||||
break;
|
|
||||||
case GM_MIXED: bp = z_bin_append_posn(1008, 10, binary, bp); break;
|
|
||||||
case GM_BYTE: bp = z_bin_append_posn(0, 4, binary, bp); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bp > 9191) {
|
if (bp > 9191) {
|
||||||
return ZINT_ERROR_TOO_LONG;
|
return ZINT_ERROR_TOO_LONG;
|
||||||
@@ -741,7 +590,7 @@ static int gm_encode_segs(const unsigned int ddata[], const struct zint_seg segs
|
|||||||
int i;
|
int i;
|
||||||
const unsigned int *dd = ddata;
|
const unsigned int *dd = ddata;
|
||||||
int bp = 0;
|
int bp = 0;
|
||||||
int p;
|
int padding;
|
||||||
|
|
||||||
if (reader && (!p_structapp || p_structapp->index == 1)) { /* Appears only in 1st symbol if Structured Append */
|
if (reader && (!p_structapp || p_structapp->index == 1)) { /* Appears only in 1st symbol if Structured Append */
|
||||||
bp = z_bin_append_posn(10, 4, binary, bp); /* FNC3 - Reader Initialisation */
|
bp = z_bin_append_posn(10, 4, binary, bp); /* FNC3 - Reader Initialisation */
|
||||||
@@ -764,9 +613,9 @@ static int gm_encode_segs(const unsigned int ddata[], const struct zint_seg segs
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Add padding bits if required */
|
/* Add padding bits if required */
|
||||||
p = 7 - (bp % 7);
|
padding = 7 - (bp % 7);
|
||||||
if (p % 7) {
|
if (padding % 7) {
|
||||||
bp = z_bin_append_posn(0, p, binary, bp);
|
bp = z_bin_append_posn(0, padding, binary, bp);
|
||||||
}
|
}
|
||||||
/* Note bit-padding can't tip `bp` over max 9191 (1313 * 7) */
|
/* Note bit-padding can't tip `bp` over max 9191 (1313 * 7) */
|
||||||
|
|
||||||
@@ -779,37 +628,27 @@ static int gm_encode_segs(const unsigned int ddata[], const struct zint_seg segs
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gm_add_ecc(const char binary[], const int data_posn, const int layers, const int ecc_level,
|
static void gm_add_ecc(const char binary[], const int num_data_cws, const int layers, const int ecc_level,
|
||||||
unsigned char word[]) {
|
unsigned char cws[]) {
|
||||||
int data_cws, i, j, wp, p;
|
int tot_data_cws, i, j, wp;
|
||||||
int n1, b1, n2, b2, e1, b3, e2;
|
int n1, b1, n2, b2, e1, b3, e2;
|
||||||
int block_size, ecc_size;
|
int num_blocks;
|
||||||
unsigned char data[1320], block[130];
|
unsigned char data[1313] = {0};
|
||||||
unsigned char data_block[115], ecc_block[70];
|
|
||||||
rs_t rs;
|
rs_t rs;
|
||||||
|
|
||||||
data_cws = gm_data_cws[layers - 1][ecc_level - 1];
|
|
||||||
|
|
||||||
for (i = 0; i < 1320; i++) {
|
|
||||||
data[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert from binary stream to 7-bit codewords */
|
/* Convert from binary stream to 7-bit codewords */
|
||||||
for (i = 0; i < data_posn; i++) {
|
for (i = 0; i < num_data_cws; i++) {
|
||||||
for (p = 0; p < 7; p++) {
|
for (j = 0; j < 7; j++) {
|
||||||
if (binary[i * 7 + p] == '1') {
|
data[i] |= (binary[i * 7 + j] == '1') << (6 - j);
|
||||||
data[i] += (0x40 >> p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tot_data_cws = gm_data_cws[layers - 1][ecc_level - 1];
|
||||||
|
|
||||||
/* Add padding codewords */
|
/* Add padding codewords */
|
||||||
data[data_posn] = 0x00;
|
for (i = num_data_cws + 1; i < tot_data_cws; i++) {
|
||||||
for (i = (data_posn + 1); i < data_cws; i++) {
|
|
||||||
if (i & 1) {
|
if (i & 1) {
|
||||||
data[i] = 0x7E;
|
data[i] = 0x7E;
|
||||||
} else {
|
|
||||||
data[i] = 0x00;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -822,155 +661,130 @@ static void gm_add_ecc(const char binary[], const int data_posn, const int layer
|
|||||||
b3 = gm_e1b3e2[layers - 1][ecc_level - 1][1];
|
b3 = gm_e1b3e2[layers - 1][ecc_level - 1][1];
|
||||||
e2 = gm_e1b3e2[layers - 1][ecc_level - 1][2];
|
e2 = gm_e1b3e2[layers - 1][ecc_level - 1][2];
|
||||||
|
|
||||||
|
num_blocks = b1 + b2;
|
||||||
|
|
||||||
zint_rs_init_gf(&rs, 0x89);
|
zint_rs_init_gf(&rs, 0x89);
|
||||||
|
|
||||||
/* Split the data into blocks */
|
/* Split the data into blocks */
|
||||||
wp = 0;
|
wp = 0;
|
||||||
for (i = 0; i < (b1 + b2); i++) {
|
for (i = 0; i < num_blocks; i++) {
|
||||||
int data_size;
|
unsigned char block[126];
|
||||||
if (i < b1) {
|
const int block_size = i < b1 ? n1 : n2;
|
||||||
block_size = n1;
|
const int ecc_size = i < b3 ? e1 : e2;
|
||||||
} else {
|
const int data_size = block_size - ecc_size;
|
||||||
block_size = n2;
|
|
||||||
}
|
|
||||||
if (i < b3) {
|
|
||||||
ecc_size = e1;
|
|
||||||
} else {
|
|
||||||
ecc_size = e2;
|
|
||||||
}
|
|
||||||
data_size = block_size - ecc_size;
|
|
||||||
|
|
||||||
for (j = 0; j < data_size; j++) {
|
memcpy(block, data + wp, data_size);
|
||||||
data_block[j] = data[wp];
|
wp += data_size;
|
||||||
wp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate ECC data for this block */
|
/* Calculate and add the ECC data for this block */
|
||||||
zint_rs_init_code(&rs, ecc_size, 1);
|
zint_rs_init_code(&rs, ecc_size, 1);
|
||||||
zint_rs_encode(&rs, data_size, data_block, ecc_block);
|
zint_rs_encode(&rs, data_size, block, block + data_size);
|
||||||
|
|
||||||
/* Add error correction data */
|
for (j = 0; j < block_size; j++) {
|
||||||
for (j = 0; j < data_size; j++) {
|
cws[num_blocks * j + i] = block[j];
|
||||||
block[j] = data_block[j];
|
|
||||||
}
|
|
||||||
for (j = 0; j < ecc_size; j++) {
|
|
||||||
block[j + data_size] = ecc_block[j];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (j = 0; j < n2; j++) {
|
|
||||||
word[((b1 + b2) * j) + i] = block[j];
|
|
||||||
}
|
|
||||||
if (block_size == n1) {
|
|
||||||
word[((b1 + b2) * (n1 - 1)) + i] = block[(n1 - 1)];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gm_place_macromodule(char grid[], const int x, const int y, const int word1, const int word2,
|
static void gm_place_macromodule(char grid[], const int size, const int x, const int y, const unsigned int cw) {
|
||||||
const int size) {
|
|
||||||
const int i = (x * 6) + 1;
|
const int i = (x * 6) + 1;
|
||||||
const int j = (y * 6) + 1;
|
const int j = ((y * 6) + 1) * size;
|
||||||
|
int r, c;
|
||||||
|
|
||||||
if (word2 & 0x40) {
|
if (cw & 0x2000) {
|
||||||
grid[(j * size) + i + 2] = '1';
|
grid[j + i + 2] = '1';
|
||||||
}
|
}
|
||||||
if (word2 & 0x20) {
|
if (cw & 0x1000) {
|
||||||
grid[(j * size) + i + 3] = '1';
|
grid[j + i + 3] = '1';
|
||||||
}
|
}
|
||||||
if (word2 & 0x10) {
|
for (r = 1; r < 4; r++) {
|
||||||
grid[((j + 1) * size) + i] = '1';
|
for (c = 0; c < 4; c++) {
|
||||||
}
|
if ((cw >> (15 - r * 4 - c)) & 1) {
|
||||||
if (word2 & 0x08) {
|
grid[j + r * size + i + c] = '1';
|
||||||
grid[((j + 1) * size) + i + 1] = '1';
|
}
|
||||||
}
|
}
|
||||||
if (word2 & 0x04) {
|
|
||||||
grid[((j + 1) * size) + i + 2] = '1';
|
|
||||||
}
|
|
||||||
if (word2 & 0x02) {
|
|
||||||
grid[((j + 1) * size) + i + 3] = '1';
|
|
||||||
}
|
|
||||||
if (word2 & 0x01) {
|
|
||||||
grid[((j + 2) * size) + i] = '1';
|
|
||||||
}
|
|
||||||
if (word1 & 0x40) {
|
|
||||||
grid[((j + 2) * size) + i + 1] = '1';
|
|
||||||
}
|
|
||||||
if (word1 & 0x20) {
|
|
||||||
grid[((j + 2) * size) + i + 2] = '1';
|
|
||||||
}
|
|
||||||
if (word1 & 0x10) {
|
|
||||||
grid[((j + 2) * size) + i + 3] = '1';
|
|
||||||
}
|
|
||||||
if (word1 & 0x08) {
|
|
||||||
grid[((j + 3) * size) + i] = '1';
|
|
||||||
}
|
|
||||||
if (word1 & 0x04) {
|
|
||||||
grid[((j + 3) * size) + i + 1] = '1';
|
|
||||||
}
|
|
||||||
if (word1 & 0x02) {
|
|
||||||
grid[((j + 3) * size) + i + 2] = '1';
|
|
||||||
}
|
|
||||||
if (word1 & 0x01) {
|
|
||||||
grid[((j + 3) * size) + i + 3] = '1';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gm_place_data_in_grid(const unsigned char word[], char grid[], const int modules, const int size) {
|
/* Get the macromodule index, `x` column, `y` row - see https://stackoverflow.com/a/63909183 */
|
||||||
int x, y, macromodule;
|
static int gm_macromodule(const int macromodules_per_dim, const int x, const int y) {
|
||||||
const int offset = 13 - ((modules - 1) / 2);
|
/* Ring 0-26 from outermost to inner */
|
||||||
|
const int r = x < y ? x < macromodules_per_dim - y - 1 ? x : macromodules_per_dim - y - 1
|
||||||
|
: y < macromodules_per_dim - x - 1 ? y : macromodules_per_dim - x - 1;
|
||||||
|
const int m = (((macromodules_per_dim - 1) >> 1) - r) * 2 + 1; /* Macromodules per dim for ring */
|
||||||
|
const int b = m * m - 1; /* Highest index in ring */
|
||||||
|
int idx;
|
||||||
|
|
||||||
for (y = 0; y < modules; y++) {
|
/* Left */
|
||||||
for (x = 0; x < modules; x++) {
|
if (x == r) {
|
||||||
macromodule = gm_macro_matrix[y + offset][x + offset];
|
idx = b - y + r;
|
||||||
gm_place_macromodule(grid, x, y, word[macromodule * 2], word[(macromodule * 2) + 1], size);
|
/* Top */
|
||||||
|
} else if (y == r) {
|
||||||
|
idx = b - (m - 1) * 4 + (x - r);
|
||||||
|
/* Right */
|
||||||
|
} else if (x == macromodules_per_dim - r - 1) {
|
||||||
|
idx = b - (m - 1) * 3 + (y - r);
|
||||||
|
/* Bottom */
|
||||||
|
} else {
|
||||||
|
assert(y == macromodules_per_dim - r - 1);
|
||||||
|
idx = b - (m - 1) - (x - r);
|
||||||
|
}
|
||||||
|
return idx << 1; /* 2 codewords per macromodule */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gm_place_data_in_grid(const unsigned char cws[], char grid[], const int size, const int layers) {
|
||||||
|
int x, y;
|
||||||
|
const int macromodules_per_dim = 1 + (layers << 1);
|
||||||
|
|
||||||
|
for (y = 0; y < macromodules_per_dim; y++) {
|
||||||
|
for (x = 0; x < macromodules_per_dim; x++) {
|
||||||
|
const int macromodule = gm_macromodule(macromodules_per_dim, x, y);
|
||||||
|
gm_place_macromodule(grid, size, x, y, ((unsigned int) cws[macromodule + 1]) << 7 | cws[macromodule]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Place the layer ID into each macromodule */
|
/* Place the layer ID into each macromodule */
|
||||||
static void gm_place_layer_id(char *grid, const int size, const int layers, const int ecc_level) {
|
static void gm_place_layer_id(char grid[], const int size, const int layers, const int ecc_level) {
|
||||||
int i, j, layer, start, stop;
|
int i, j, layer, start, stop;
|
||||||
const int modules = 1 + (layers << 1);
|
const int macromodules_per_dim = 1 + (layers << 1);
|
||||||
int *layerid = (int *) z_alloca(sizeof(int) * (layers + 1));
|
int *layer_ids = (int *) z_alloca(sizeof(int) * (layers + 1));
|
||||||
int *id = (int *) z_alloca(sizeof(int) * (modules * modules));
|
int *ids = (int *) z_alloca(sizeof(int) * (macromodules_per_dim * macromodules_per_dim));
|
||||||
|
|
||||||
|
assert(layers > 0); /* Suppress clang-tidy-23 warning clang-analyzer-core.UndefinedBinaryOperatorResult */
|
||||||
|
|
||||||
/* Calculate Layer IDs */
|
/* Calculate Layer IDs */
|
||||||
for (i = 0; i <= layers; i++) {
|
for (i = 0; i <= layers; i++) {
|
||||||
if (ecc_level == 1) {
|
if (ecc_level == 1) {
|
||||||
layerid[i] = 3 - (i % 4);
|
layer_ids[i] = 3 - (i & 0x03);
|
||||||
} else {
|
} else {
|
||||||
layerid[i] = (i + 5 - ecc_level) % 4;
|
layer_ids[i] = (i + 5 - ecc_level) & 0x03;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < modules; i++) {
|
|
||||||
for (j = 0; j < modules; j++) {
|
|
||||||
id[(i * modules) + j] = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate which value goes in each macromodule */
|
/* Calculate which value goes in each macromodule */
|
||||||
start = modules >> 1;
|
start = macromodules_per_dim >> 1;
|
||||||
stop = modules >> 1;
|
stop = macromodules_per_dim >> 1;
|
||||||
for (layer = 0; layer <= layers; layer++) {
|
for (layer = 0; layer <= layers; layer++) {
|
||||||
for (i = start; i <= stop; i++) {
|
for (i = start; i <= stop; i++) {
|
||||||
id[(start * modules) + i] = layerid[layer];
|
ids[(start * macromodules_per_dim) + i] = layer_ids[layer];
|
||||||
id[(i * modules) + start] = layerid[layer];
|
ids[(i * macromodules_per_dim) + start] = layer_ids[layer];
|
||||||
id[((modules - start - 1) * modules) + i] = layerid[layer];
|
ids[((macromodules_per_dim - start - 1) * macromodules_per_dim) + i] = layer_ids[layer];
|
||||||
id[(i * modules) + (modules - start - 1)] = layerid[layer];
|
ids[(i * macromodules_per_dim) + (macromodules_per_dim - start - 1)] = layer_ids[layer];
|
||||||
}
|
}
|
||||||
start--;
|
start--;
|
||||||
stop++;
|
stop++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Place the data in the grid */
|
/* Place the data in the grid */
|
||||||
for (i = 0; i < modules; i++) {
|
for (i = 0; i < macromodules_per_dim; i++) {
|
||||||
for (j = 0; j < modules; j++) {
|
for (j = 0; j < macromodules_per_dim; j++) {
|
||||||
if (id[(i * modules) + j] & 0x02) {
|
const int id = ids[(i * macromodules_per_dim) + j];
|
||||||
grid[(((i * 6) + 1) * size) + (j * 6) + 1] = '1';
|
if (id & 0x02) {
|
||||||
|
grid[(i * 6 + 1) * size + j * 6 + 1] = '1';
|
||||||
}
|
}
|
||||||
if (id[(i * modules) + j] & 0x01) {
|
if (id & 0x01) {
|
||||||
grid[(((i * 6) + 1) * size) + (j * 6) + 2] = '1';
|
grid[(i * 6 + 1) * size + j * 6 + 1 + 1] = '1';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -978,13 +792,13 @@ static void gm_place_layer_id(char *grid, const int size, const int layers, cons
|
|||||||
|
|
||||||
INTERNAL int zint_gridmatrix(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) {
|
INTERNAL int zint_gridmatrix(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) {
|
||||||
int warn_number = 0;
|
int warn_number = 0;
|
||||||
int size, modules, error_number;
|
int size, macromodules_per_dim, error_number;
|
||||||
int auto_layers, min_layers, layers, rec_ecc_level, min_rec_ecc_level, ecc_level;
|
int auto_layers, min_layers, layers, rec_ecc_level, min_rec_ecc_level, ecc_level;
|
||||||
int x, y, i;
|
int x, y, i;
|
||||||
int full_multibyte;
|
int full_multibyte;
|
||||||
char binary[9300];
|
char binary[9240]; /* 1313 * 7 = 9191 + 46 (max overflow (GM_BYTE) in `gm_encode()`) + 3 */
|
||||||
int data_cws;
|
int num_data_cws;
|
||||||
unsigned char word[1460] = {0};
|
unsigned char cws[1458] = {0};
|
||||||
int reader = 0;
|
int reader = 0;
|
||||||
const struct zint_structapp *p_structapp = NULL;
|
const struct zint_structapp *p_structapp = NULL;
|
||||||
int size_squared;
|
int size_squared;
|
||||||
@@ -1079,17 +893,18 @@ INTERNAL int zint_gridmatrix(struct zint_symbol *symbol, struct zint_seg segs[],
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Determine the size of the symbol */
|
/* Determine the size of the symbol */
|
||||||
data_cws = bin_len / 7; /* Binary length always a multiple of 7 */
|
assert(bin_len % 7 == 0); /* Binary length always a multiple of 7 */
|
||||||
|
num_data_cws = bin_len / 7;
|
||||||
|
|
||||||
auto_layers = 13;
|
auto_layers = 13;
|
||||||
for (i = 12; i > 0; i--) {
|
for (i = 12; i > 0; i--) {
|
||||||
if (gm_recommend_cws[i - 1] >= data_cws) {
|
if (gm_recommend_cws[i - 1] >= num_data_cws) {
|
||||||
auto_layers = i;
|
auto_layers = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
min_layers = 13;
|
min_layers = 13;
|
||||||
for (i = 12; i > 0; i--) {
|
for (i = 12; i > 0; i--) {
|
||||||
if (gm_max_cws[i - 1] >= data_cws) {
|
if (gm_max_cws[i - 1] >= num_data_cws) {
|
||||||
min_layers = i;
|
min_layers = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1101,7 +916,7 @@ INTERNAL int zint_gridmatrix(struct zint_symbol *symbol, struct zint_seg segs[],
|
|||||||
} else {
|
} else {
|
||||||
return ZEXT z_errtxtf(ZINT_ERROR_TOO_LONG, symbol, 534,
|
return ZEXT z_errtxtf(ZINT_ERROR_TOO_LONG, symbol, 534,
|
||||||
"Input too long for Version %1$d, requires %2$d codewords (maximum %3$d)",
|
"Input too long for Version %1$d, requires %2$d codewords (maximum %3$d)",
|
||||||
symbol->option_2, data_cws, gm_max_cws[symbol->option_2 - 1]);
|
symbol->option_2, num_data_cws, gm_max_cws[symbol->option_2 - 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1130,42 +945,42 @@ INTERNAL int zint_gridmatrix(struct zint_symbol *symbol, struct zint_seg segs[],
|
|||||||
ecc_level = min_rec_ecc_level;
|
ecc_level = min_rec_ecc_level;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data_cws > gm_data_cws[layers - 1][ecc_level - 1]) {
|
if (num_data_cws > gm_data_cws[layers - 1][ecc_level - 1]) {
|
||||||
/* Reduce ECC level */
|
/* Reduce ECC level */
|
||||||
const int min_ecc_level = layers > 1 ? 1 : 2; /* ECL 1 in version 1 symbols is invalid */
|
const int min_ecc_level = layers > 1 ? 1 : 2; /* ECL 1 in version 1 symbols is invalid */
|
||||||
do {
|
do {
|
||||||
ecc_level--;
|
ecc_level--;
|
||||||
} while (data_cws > gm_data_cws[layers - 1][ecc_level - 1] && ecc_level > min_ecc_level);
|
} while (num_data_cws > gm_data_cws[layers - 1][ecc_level - 1] && ecc_level > min_ecc_level);
|
||||||
assert(data_cws <= gm_data_cws[layers - 1][ecc_level - 1]);
|
assert(num_data_cws <= gm_data_cws[layers - 1][ecc_level - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (debug_print) {
|
if (debug_print) {
|
||||||
printf("Layers: %d, ECC level: %d, Data Codewords: %d\n", layers, ecc_level, data_cws);
|
printf("Layers: %d, ECC level: %d, Data Codewords: %d\n", layers, ecc_level, num_data_cws);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Feedback options */
|
/* Feedback options */
|
||||||
symbol->option_1 = ecc_level;
|
symbol->option_1 = ecc_level;
|
||||||
symbol->option_2 = layers;
|
symbol->option_2 = layers;
|
||||||
|
|
||||||
gm_add_ecc(binary, data_cws, layers, ecc_level, word);
|
gm_add_ecc(binary, num_data_cws, layers, ecc_level, cws);
|
||||||
#ifdef ZINT_TEST
|
#ifdef ZINT_TEST
|
||||||
if (symbol->debug & ZINT_DEBUG_TEST) z_debug_test_codeword_dump(symbol, word, data_cws);
|
if (symbol->debug & ZINT_DEBUG_TEST) z_debug_test_codeword_dump(symbol, cws, num_data_cws);
|
||||||
#endif
|
#endif
|
||||||
size = 6 + (layers * 12);
|
size = 6 + (layers * 12);
|
||||||
modules = 1 + (layers * 2);
|
macromodules_per_dim = 1 + (layers * 2);
|
||||||
size_squared = size * size;
|
size_squared = size * size;
|
||||||
|
|
||||||
grid = (char *) z_alloca(size_squared);
|
grid = (char *) z_alloca(size_squared);
|
||||||
memset(grid, '0', size_squared);
|
memset(grid, '0', size_squared);
|
||||||
|
|
||||||
gm_place_data_in_grid(word, grid, modules, size);
|
gm_place_data_in_grid(cws, grid, size, layers);
|
||||||
gm_place_layer_id(grid, size, layers, ecc_level);
|
gm_place_layer_id(grid, size, layers, ecc_level);
|
||||||
|
|
||||||
/* Add macromodule frames */
|
/* Add macromodule frames */
|
||||||
for (x = 0; x < modules; x++) {
|
for (x = 0; x < macromodules_per_dim; x++) {
|
||||||
const int x_offset = x * 6;
|
const int x_offset = x * 6;
|
||||||
int dark = !(x & 1);
|
int dark = !(x & 1);
|
||||||
for (y = 0; y < modules; y++) {
|
for (y = 0; y < macromodules_per_dim; y++) {
|
||||||
if (dark) {
|
if (dark) {
|
||||||
const int y_offset = y * 6 * size;
|
const int y_offset = y * 6 * size;
|
||||||
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 5; i++) {
|
||||||
|
|||||||
+40
-50
@@ -33,36 +33,31 @@
|
|||||||
#ifndef Z_GRIDMTX_H
|
#ifndef Z_GRIDMTX_H
|
||||||
#define Z_GRIDMTX_H
|
#define Z_GRIDMTX_H
|
||||||
|
|
||||||
/* From Table 7 - Encoding of control characters */
|
/* Following 2 tables based on Table 11 - Recommended error correction levels */
|
||||||
static const char gm_shift_set[] = {
|
|
||||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* NULL -> SI */
|
|
||||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* DLE -> US */
|
|
||||||
'!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':',
|
|
||||||
';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~'
|
|
||||||
};
|
|
||||||
|
|
||||||
static const short gm_recommend_cws[13] = {
|
static const short gm_recommend_cws[13] = {
|
||||||
9, 30, 59, 114, 170, 237, 315, 405, 506, 618, 741, 875, 1021
|
9, 30, 59, 114, 170, 237, 315, 405, 506, 618, 741, 875, 1021
|
||||||
};
|
};
|
||||||
|
|
||||||
static const short gm_max_cws[13] = {
|
static const short gm_max_cws[13] = {
|
||||||
11, 40, 79, 146, 218, 305, 405, 521, 650, 794, 953, 1125, 1313
|
11, 40, 89, 146, 218, 305, 405, 521, 650, 794, 953, 1125, 1313
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Maximum data codewords per ECL - ECL 1 not permitted for Version 1 */
|
||||||
static const short gm_data_cws[13][5] = {
|
static const short gm_data_cws[13][5] = {
|
||||||
{ 0, 15, 13, 11, 9 }, /* 1 */
|
/* 90% 80% 70% 60% 50% Total available codewords (Table 1) */
|
||||||
{ 45, 40, 35, 30, 25 }, /* 2 */
|
{ 0, 15, 13, 11, 9 }, /*1 18 */
|
||||||
{ 89, 79, 69, 59, 49 }, /* 3 */
|
{ 45, 40, 35, 30, 25 }, /*2 50 */
|
||||||
{ 146, 130, 114, 98, 81 }, /* 4 */
|
{ 89, 79, 69, 59, 49 }, /*3 98 */
|
||||||
{ 218, 194, 170, 146, 121 }, /* 5 */
|
{ 146, 130, 114, 98, 81 }, /*4 162 */
|
||||||
{ 305, 271, 237, 203, 169 }, /* 6 */
|
{ 218, 194, 170, 146, 121 }, /*5 242 */
|
||||||
{ 405, 360, 315, 270, 225 }, /* 7 */
|
{ 305, 271, 237, 203, 169 }, /*6 338 */
|
||||||
{ 521, 463, 405, 347, 289 }, /* 8 */
|
{ 405, 360, 315, 270, 225 }, /*7 450 */
|
||||||
{ 650, 578, 506, 434, 361 }, /* 9 */
|
{ 521, 463, 405, 347, 289 }, /*8 578 */
|
||||||
{ 794, 706, 618, 530, 441 }, /* 10 */
|
{ 650, 578, 506, 434, 361 }, /*9 722 */
|
||||||
{ 953, 847, 741, 635, 529 }, /* 11 */
|
{ 794, 706, 618, 530, 441 }, /*10 882 */
|
||||||
{ 1125, 1000, 875, 750, 625 }, /* 12 */
|
{ 953, 847, 741, 635, 529 }, /*11 1058 */
|
||||||
{ 1313, 1167, 1021, 875, 729 }, /* 13 */
|
{ 1125, 1000, 875, 750, 625 }, /*12 1250 */
|
||||||
|
{ 1313, 1167, 1021, 875, 729 }, /*13 1458 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Table A.1 N1 */
|
/* Table A.1 N1 */
|
||||||
@@ -98,34 +93,29 @@ static const char gm_e1b3e2[13][5][3] = {
|
|||||||
{ { 13, 1, 12 }, { 25, 3, 24 }, { 37, 5, 36 }, { 49, 7, 48 }, { 61, 9, 60 } } /* 13 */
|
{ { 13, 1, 12 }, { 25, 3, 24 }, { 37, 5, 36 }, { 49, 7, 48 }, { 61, 9, 60 } } /* 13 */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const short gm_macro_matrix[27][27] = {
|
/* Codewords to switch from `row` mode to `col` mode (Table 9 – Type conversion codes) */
|
||||||
{ 728, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650 },
|
static const short gm_mode_switch[8][6] = {
|
||||||
{ 727, 624, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 651 },
|
/* CHN NUM LWR UPR MXD BYT */
|
||||||
{ 726, 623, 528, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 553, 652 },
|
{ 1, 2, 3, 4, 5, 7 }, /* 0 */
|
||||||
{ 725, 622, 527, 440, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 463, 554, 653 },
|
{ 0, 8161, 8162, 8163, 8164, 8165 }, /* GM_CHINESE */
|
||||||
{ 724, 621, 526, 439, 360, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 381, 464, 555, 654 },
|
{ 1019, 0, 1020, 1021, 1022, 1023 }, /* GM_NUMERAL */
|
||||||
{ 723, 620, 525, 438, 359, 288, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 307, 382, 465, 556, 655 },
|
{ 28, 29, 0, 30, 124, 126 }, /* GM_LOWER */
|
||||||
{ 722, 619, 524, 437, 358, 287, 224, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 241, 308, 383, 466, 557, 656 },
|
{ 28, 29, 30, 0, 124, 126 }, /* GM_UPPER */
|
||||||
{ 721, 618, 523, 436, 357, 286, 223, 168, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 183, 242, 309, 384, 467, 558, 657 },
|
{ 1009, 1010, 1011, 1012, 0, 1015 }, /* GM_MIXED */
|
||||||
{ 720, 617, 522, 435, 356, 285, 222, 167, 120, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 133, 184, 243, 310, 385, 468, 559, 658 },
|
{ 1, 2, 3, 4, 5, 0 }, /* GM_BYTE */
|
||||||
{ 719, 616, 521, 434, 355, 284, 221, 166, 119, 80, 49, 50, 51, 52, 53, 54, 55, 56, 91, 134, 185, 244, 311, 386, 469, 560, 659 },
|
{ 8160, 1018, 27, 27, 1008, 0 }, /* GM_EOD (end of data) */
|
||||||
{ 718, 615, 520, 433, 354, 283, 220, 165, 118, 79, 48, 25, 26, 27, 28, 29, 30, 57, 92, 135, 186, 245, 312, 387, 470, 561, 660 },
|
};
|
||||||
{ 717, 614, 519, 432, 353, 282, 219, 164, 117, 78, 47, 24, 9, 10, 11, 12, 31, 58, 93, 136, 187, 246, 313, 388, 471, 562, 661 },
|
|
||||||
{ 716, 613, 518, 431, 352, 281, 218, 163, 116, 77, 46, 23, 8, 1, 2, 13, 32, 59, 94, 137, 188, 247, 314, 389, 472, 563, 662 },
|
/* Bit-lengths of above */
|
||||||
{ 715, 612, 517, 430, 351, 280, 217, 162, 115, 76, 45, 22, 7, 0, 3, 14, 33, 60, 95, 138, 189, 248, 315, 390, 473, 564, 663 },
|
static const char gm_mode_len[8][6] = {
|
||||||
{ 714, 611, 516, 429, 350, 279, 216, 161, 114, 75, 44, 21, 6, 5, 4, 15, 34, 61, 96, 139, 190, 249, 316, 391, 474, 565, 664 },
|
{ 4, 4, 4, 4, 4, 4 }, /* 0 */
|
||||||
{ 713, 610, 515, 428, 349, 278, 215, 160, 113, 74, 43, 20, 19, 18, 17, 16, 35, 62, 97, 140, 191, 250, 317, 392, 475, 566, 665 },
|
{ 0, 13, 13, 13, 13, 13 }, /* GM_CHINESE */
|
||||||
{ 712, 609, 514, 427, 348, 277, 214, 159, 112, 73, 42, 41, 40, 39, 38, 37, 36, 63, 98, 141, 192, 251, 318, 393, 476, 567, 666 },
|
{ 10, 0, 10, 10, 10, 10 }, /* GM_NUMERAL */
|
||||||
{ 711, 608, 513, 426, 347, 276, 213, 158, 111, 72, 71, 70, 69, 68, 67, 66, 65, 64, 99, 142, 193, 252, 319, 394, 477, 568, 667 },
|
{ 5, 5, 0, 5, 7, 7 }, /* GM_LOWER */
|
||||||
{ 710, 607, 512, 425, 346, 275, 212, 157, 110, 109, 108, 107, 106, 105, 104, 103, 102, 101, 100, 143, 194, 253, 320, 395, 478, 569, 668 },
|
{ 5, 5, 5, 0, 7, 7 }, /* GM_UPPER */
|
||||||
{ 709, 606, 511, 424, 345, 274, 211, 156, 155, 154, 153, 152, 151, 150, 149, 148, 147, 146, 145, 144, 195, 254, 321, 396, 479, 570, 669 },
|
{ 10, 10, 10, 10, 0, 10 }, /* GM_MIXED */
|
||||||
{ 708, 605, 510, 423, 344, 273, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, 197, 196, 255, 322, 397, 480, 571, 670 },
|
{ 4, 4, 4, 4, 4, 0 }, /* GM_BYTE */
|
||||||
{ 707, 604, 509, 422, 343, 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, 260, 259, 258, 257, 256, 323, 398, 481, 572, 671 },
|
{ 13, 10, 5, 5, 10, 4 }, /* GM_EOD (end of data) */
|
||||||
{ 706, 603, 508, 421, 342, 341, 340, 339, 338, 337, 336, 335, 334, 333, 332, 331, 330, 329, 328, 327, 326, 325, 324, 399, 482, 573, 672 },
|
|
||||||
{ 705, 602, 507, 420, 419, 418, 417, 416, 415, 414, 413, 412, 411, 410, 409, 408, 407, 406, 405, 404, 403, 402, 401, 400, 483, 574, 673 },
|
|
||||||
{ 704, 601, 506, 505, 504, 503, 502, 501, 500, 499, 498, 497, 496, 495, 494, 493, 492, 491, 490, 489, 488, 487, 486, 485, 484, 575, 674 },
|
|
||||||
{ 703, 600, 599, 598, 597, 596, 595, 594, 593, 592, 591, 590, 589, 588, 587, 586, 585, 584, 583, 582, 581, 580, 579, 578, 577, 576, 675 },
|
|
||||||
{ 702, 701, 700, 699, 698, 697, 696, 695, 694, 693, 692, 691, 690, 689, 688, 687, 686, 685, 684, 683, 682, 681, 680, 679, 678, 677, 676 }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* vim: set ts=4 sw=4 et : */
|
/* vim: set ts=4 sw=4 et : */
|
||||||
|
|||||||
+501
-320
File diff suppressed because it is too large
Load Diff
@@ -738,7 +738,7 @@ static void test_escape_char_process(const testCtx *const p_ctx) {
|
|||||||
/* 1*/ { BARCODE_CODABLOCKF, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\L\\e\\F\\G\\R\\N\\x81\\\\", "", 0, 101, "(54) 67 62 44 40 44 47 48 2B 6A 67 62 0B 49 4A 4B 4C 18 6A 67 62 0C 4D 50 5B 5C 20 6A 67", 0, "" },
|
/* 1*/ { BARCODE_CODABLOCKF, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\L\\e\\F\\G\\R\\N\\x81\\\\", "", 0, 101, "(54) 67 62 44 40 44 47 48 2B 6A 67 62 0B 49 4A 4B 4C 18 6A 67 62 0C 4D 50 5B 5C 20 6A 67", 0, "" },
|
||||||
/* 2*/ { BARCODE_CODE16K, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\L\\e\\F\\G\\R\\N\\x81\\\\", "", 0, 70, "(25) 21 64 68 71 72 73 74 75 76 77 80 91 92 93 94 95 101 65 60 103 103 103 103 38 59", 0, "" },
|
/* 2*/ { BARCODE_CODE16K, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\L\\e\\F\\G\\R\\N\\x81\\\\", "", 0, 70, "(25) 21 64 68 71 72 73 74 75 76 77 80 91 92 93 94 95 101 65 60 103 103 103 103 38 59", 0, "" },
|
||||||
/* 3*/ { BARCODE_DOTCODE, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\L\\e\\F\\G\\R\\N\\x81\\\\", "", 0, 29, "65 40 44 47 48 49 4A 4B 4C 4D 50 5B 5C 5D 5E 5F 6E 41 3C", 0, "" },
|
/* 3*/ { BARCODE_DOTCODE, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\L\\e\\F\\G\\R\\N\\x81\\\\", "", 0, 29, "65 40 44 47 48 49 4A 4B 4C 4D 50 5B 5C 5D 5E 5F 6E 41 3C", 0, "" },
|
||||||
/* 4*/ { BARCODE_GRIDMATRIX, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\L\\e\\F\\G\\R\\N\\x81\\\\", "", 0, 30, "30 20 00 02 01 61 00 48 28 16 0C 06 44 03 31 60 74 3C 1F 40 57 00", 0, "" },
|
/* 4*/ { BARCODE_GRIDMATRIX, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\L\\e\\F\\G\\R\\N\\x81\\\\", "", 0, 30, "38 20 00 02 01 61 00 48 28 16 0C 06 44 03 31 60 74 3C 1F 40 57 00", 0, "" },
|
||||||
/* 5*/ { BARCODE_HANXIN, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\L\\e\\F\\G\\R\\N\\x81\\\\", "", 0, 23, "2F 80 10 72 09 28 B3 0D 41 BF CC 00 C3 83 A3 C3 F0 2B 80 00 00", 0, "" },
|
/* 5*/ { BARCODE_HANXIN, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\L\\e\\F\\G\\R\\N\\x81\\\\", "", 0, 23, "2F 80 10 72 09 28 B3 0D 41 BF CC 00 C3 83 A3 C3 F0 2B 80 00 00", 0, "" },
|
||||||
/* 6*/ { BARCODE_MAXICODE, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\L\\e\\F\\G\\R\\N\\x81\\\\", "", 0, 30, "(144) 04 3E 3E 00 04 07 08 09 0A 0B 03 3D 2C 24 19 1E 23 1B 18 0E 0C 0D 10 1E 20 21 22 23", 0, "" },
|
/* 6*/ { BARCODE_MAXICODE, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\L\\e\\F\\G\\R\\N\\x81\\\\", "", 0, 30, "(144) 04 3E 3E 00 04 07 08 09 0A 0B 03 3D 2C 24 19 1E 23 1B 18 0E 0C 0D 10 1E 20 21 22 23", 0, "" },
|
||||||
/* 7*/ { BARCODE_PDF417, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\L\\e\\F\\G\\R\\N\\x81\\\\", "", 0, 120, "(27) 19 901 0 23 655 318 98 18 461 639 91 512 29 30 31 129 92 900 900 114 476 670 717 35", 0, "" },
|
/* 7*/ { BARCODE_PDF417, DATA_MODE, -1, "\\0\\E\\a\\b\\t\\n\\v\\f\\r\\L\\e\\F\\G\\R\\N\\x81\\\\", "", 0, 120, "(27) 19 901 0 23 655 318 98 18 461 639 91 512 29 30 31 129 92 900 900 114 476 670 717 35", 0, "" },
|
||||||
|
|||||||
@@ -4119,7 +4119,7 @@ static const char *testUtilZXingCPPName(int index, const struct zint_symbol *sym
|
|||||||
{ "", BARCODE_DBAR_EXPSTK_CC, 139, },
|
{ "", BARCODE_DBAR_EXPSTK_CC, 139, },
|
||||||
{ "", BARCODE_CHANNEL, 140, },
|
{ "", BARCODE_CHANNEL, 140, },
|
||||||
{ "", BARCODE_CODEONE, 141, },
|
{ "", BARCODE_CODEONE, 141, },
|
||||||
{ "", BARCODE_GRIDMATRIX, 142, },
|
{ "GridMatrix", BARCODE_GRIDMATRIX, 142, },
|
||||||
{ "QRCode", BARCODE_UPNQR, 143, },
|
{ "QRCode", BARCODE_UPNQR, 143, },
|
||||||
{ "", BARCODE_ULTRA, 144, },
|
{ "", BARCODE_ULTRA, 144, },
|
||||||
{ "RMQRCode", BARCODE_RMQR, 145, },
|
{ "RMQRCode", BARCODE_RMQR, 145, },
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ run_zxingcpp_test "test_dotcode" "large"
|
|||||||
run_zxingcpp_test "test_dotcode" "input"
|
run_zxingcpp_test "test_dotcode" "input"
|
||||||
run_zxingcpp_test "test_dotcode" "encode"
|
run_zxingcpp_test "test_dotcode" "encode"
|
||||||
run_zxingcpp_test "test_dotcode" "encode_segs"
|
run_zxingcpp_test "test_dotcode" "encode_segs"
|
||||||
|
run_zxingcpp_test "test_gridmtx"
|
||||||
run_zxingcpp_test "test_hanxin"
|
run_zxingcpp_test "test_hanxin"
|
||||||
run_zxingcpp_test "test_mailmark" "2d_encode"
|
run_zxingcpp_test "test_mailmark" "2d_encode"
|
||||||
run_zxingcpp_test "test_maxicode" "large"
|
run_zxingcpp_test "test_maxicode" "large"
|
||||||
|
|||||||
+3
-2
@@ -334,7 +334,7 @@
|
|||||||
<h1 class="title">Zint Barcode Generator and Zint Barcode Studio User
|
<h1 class="title">Zint Barcode Generator and Zint Barcode Studio User
|
||||||
Manual</h1>
|
Manual</h1>
|
||||||
<p class="author">Version 2.16.0.9</p>
|
<p class="author">Version 2.16.0.9</p>
|
||||||
<p class="date">June 2026</p>
|
<p class="date">July 2026</p>
|
||||||
</header>
|
</header>
|
||||||
<nav id="TOC" role="doc-toc">
|
<nav id="TOC" role="doc-toc">
|
||||||
<ul>
|
<ul>
|
||||||
@@ -3133,7 +3133,8 @@ Engine to strictly validate GS1 data, including GS1 Digital Link URIs
|
|||||||
that Zint was built with the <code>gs1encoders</code> library, otherwise
|
that Zint was built with the <code>gs1encoders</code> library, otherwise
|
||||||
the default built-in validation will be used.</p></li>
|
the default built-in validation will be used.</p></li>
|
||||||
<li><p><code>--gs1nocheck</code>, for use with legacy systems that have
|
<li><p><code>--gs1nocheck</code>, for use with legacy systems that have
|
||||||
data that does not conform to the current GS1 standard. Printable ASCII
|
data that does not conform to the current GS1 standard, this disables
|
||||||
|
checking for valid AIs, and AI data types and lengths. Printable ASCII
|
||||||
input is still checked for, as is the validity of GS1 data specified
|
input is still checked for, as is the validity of GS1 data specified
|
||||||
without AIs (e.g. linear data for GS1 DataBar
|
without AIs (e.g. linear data for GS1 DataBar
|
||||||
Omnidirectional/Limited/etc.). Also checked is GS1 DataBar Expanded and
|
Omnidirectional/Limited/etc.). Also checked is GS1 DataBar Expanded and
|
||||||
|
|||||||
+10
-10
@@ -1,6 +1,6 @@
|
|||||||
% Zint Barcode Generator and Zint Barcode Studio User Manual
|
% Zint Barcode Generator and Zint Barcode Studio User Manual
|
||||||
% Version 2.16.0.9
|
% Version 2.16.0.9
|
||||||
% June 2026
|
% July 2026
|
||||||
|
|
||||||
[//]: # ( vim: set ts=4 sw=4 et : )
|
[//]: # ( vim: set ts=4 sw=4 et : )
|
||||||
|
|
||||||
@@ -1631,17 +1631,17 @@ zint -b AZTEC -d "010952012345678810BCH4\G2107" --esc --gs1raw
|
|||||||
Apart from `--gs1`, `--gs1parens` and `--gs1raw` discussed above, there are two
|
Apart from `--gs1`, `--gs1parens` and `--gs1raw` discussed above, there are two
|
||||||
other GS1 options.
|
other GS1 options.
|
||||||
|
|
||||||
- `--gs1strict`, which enables the use the GS1 Syntax Engine to
|
- `--gs1strict`, which enables the use the GS1 Syntax Engine to strictly
|
||||||
strictly validate GS1 data, including GS1 Digital Link URIs (by default Zint
|
validate GS1 data, including GS1 Digital Link URIs (by default Zint does not
|
||||||
does not validate Digital Links at all). It requires that Zint was built with
|
validate Digital Links at all). It requires that Zint was built with the
|
||||||
the `gs1encoders` library, otherwise the default built-in validation will be
|
`gs1encoders` library, otherwise the default built-in validation will be used.
|
||||||
used.
|
|
||||||
|
|
||||||
- `--gs1nocheck`, for use with legacy systems that have data that does not
|
- `--gs1nocheck`, for use with legacy systems that have data that does not
|
||||||
conform to the current GS1 standard. Printable ASCII input is still checked for,
|
conform to the current GS1 standard, this disables checking for valid AIs, and
|
||||||
as is the validity of GS1 data specified without AIs (e.g. linear data for GS1
|
AI data types and lengths. Printable ASCII input is still checked for, as is the
|
||||||
DataBar Omnidirectional/Limited/etc.). Also checked is GS1 DataBar Expanded and
|
validity of GS1 data specified without AIs (e.g. linear data for GS1 DataBar
|
||||||
GS1 Composite input that is not in the GS1 encodable character set 82 (see GS1
|
Omnidirectional/Limited/etc.). Also checked is GS1 DataBar Expanded and GS1
|
||||||
|
Composite input that is not in the GS1 encodable character set 82 (see GS1
|
||||||
General Specifications 26.0 Table 7-2 "GS1 AI encodable character set 82"),
|
General Specifications 26.0 Table 7-2 "GS1 AI encodable character set 82"),
|
||||||
otherwise encodation would fail. In "Unbracketed AI" and raw mode, overlong AI
|
otherwise encodation would fail. In "Unbracketed AI" and raw mode, overlong AI
|
||||||
data will also fail.
|
data will also fail.
|
||||||
|
|||||||
+6
-5
@@ -1,6 +1,6 @@
|
|||||||
Zint Barcode Generator and Zint Barcode Studio User Manual
|
Zint Barcode Generator and Zint Barcode Studio User Manual
|
||||||
Version 2.16.0.9
|
Version 2.16.0.9
|
||||||
June 2026
|
July 2026
|
||||||
|
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
* For reference the following is a text-only version of the Zint manual, *
|
* For reference the following is a text-only version of the Zint manual, *
|
||||||
@@ -1668,9 +1668,10 @@ GS1 options.
|
|||||||
gs1encoders library, otherwise the default built-in validation will be used.
|
gs1encoders library, otherwise the default built-in validation will be used.
|
||||||
|
|
||||||
- --gs1nocheck, for use with legacy systems that have data that does not
|
- --gs1nocheck, for use with legacy systems that have data that does not
|
||||||
conform to the current GS1 standard. Printable ASCII input is still checked
|
conform to the current GS1 standard, this disables checking for valid AIs,
|
||||||
for, as is the validity of GS1 data specified without AIs (e.g. linear data
|
and AI data types and lengths. Printable ASCII input is still checked for,
|
||||||
for GS1 DataBar Omnidirectional/Limited/etc.). Also checked is GS1 DataBar
|
as is the validity of GS1 data specified without AIs (e.g. linear data for
|
||||||
|
GS1 DataBar Omnidirectional/Limited/etc.). Also checked is GS1 DataBar
|
||||||
Expanded and GS1 Composite input that is not in the GS1 encodable character
|
Expanded and GS1 Composite input that is not in the GS1 encodable character
|
||||||
set 82 (see GS1 General Specifications 26.0 Table 7-2 “GS1 AI encodable
|
set 82 (see GS1 General Specifications 26.0 Table 7-2 “GS1 AI encodable
|
||||||
character set 82”), otherwise encodation would fail. In “Unbracketed AI” and
|
character set 82”), otherwise encodation would fail. In “Unbracketed AI” and
|
||||||
@@ -5333,7 +5334,7 @@ configured barcode is updated when the "Generate" button is pressed.
|
|||||||
|
|
||||||
Annex D. Man Page ZINT(1)
|
Annex D. Man Page ZINT(1)
|
||||||
|
|
||||||
% ZINT(1) Version 2.16.0.9 % % June 2026
|
% ZINT(1) Version 2.16.0.9 % % July 2026
|
||||||
|
|
||||||
NAME
|
NAME
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
.\" Automatically generated by Pandoc 3.10
|
.\" Automatically generated by Pandoc 3.10
|
||||||
.\"
|
.\"
|
||||||
.TH "ZINT" "1" "June 2026" "Version 2.16.0.9"
|
.TH "ZINT" "1" "July 2026" "Version 2.16.0.9"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
\f[CR]zint\f[R] \- encode data as a barcode image
|
\f[CR]zint\f[R] \- encode data as a barcode image
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
% ZINT(1) Version 2.16.0.9
|
% ZINT(1) Version 2.16.0.9
|
||||||
%
|
%
|
||||||
% June 2026
|
% July 2026
|
||||||
|
|
||||||
[//]: # ( vim: set ts=4 sw=4 et : )
|
[//]: # ( vim: set ts=4 sw=4 et : )
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user