comparison mupdf-source/thirdparty/zint/backend/code128.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /* code128.c - Handles Code 128 and derivatives */
2 /*
3 libzint - the open source barcode library
4 Copyright (C) 2008-2024 Robin Stuart <rstuart114@gmail.com>
5 Bugfixes thanks to Christian Sakowski and BogDan Vatra
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16 3. Neither the name of the project nor the names of its contributors
17 may be used to endorse or promote products derived from this software
18 without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 SUCH DAMAGE.
31 */
32 /* SPDX-License-Identifier: BSD-3-Clause */
33
34 #include <assert.h>
35 #include <stdio.h>
36 #include "common.h"
37 #include "code128.h"
38 #include "gs1.h"
39
40 #define C128_SYMBOL_MAX 102 /* 102 * 10 + 10 (check digit) + 13 (Stop) = 1043 */
41 #define C128_SYMBOL_MAX_S "102" /* String version of above */
42
43 #define C128_VALUES_MAX (C128_SYMBOL_MAX + 2) /* Allow for debug/test check digit and Stop */
44
45 /* Code 128 tables checked against ISO/IEC 15417:2007 */
46
47 /* Code 128 character encodation - Table 1 (with final CODE16K-only character in place of Stop character) */
48 INTERNAL_DATA const char C128Table[107][6] = { /* Used by CODABLOCKF and CODE16K also */
49 {'2','1','2','2','2','2'}, {'2','2','2','1','2','2'}, {'2','2','2','2','2','1'}, {'1','2','1','2','2','3'},
50 {'1','2','1','3','2','2'}, {'1','3','1','2','2','2'}, {'1','2','2','2','1','3'}, {'1','2','2','3','1','2'},
51 {'1','3','2','2','1','2'}, {'2','2','1','2','1','3'}, {'2','2','1','3','1','2'}, {'2','3','1','2','1','2'},
52 {'1','1','2','2','3','2'}, {'1','2','2','1','3','2'}, {'1','2','2','2','3','1'}, {'1','1','3','2','2','2'},
53 {'1','2','3','1','2','2'}, {'1','2','3','2','2','1'}, {'2','2','3','2','1','1'}, {'2','2','1','1','3','2'},
54 {'2','2','1','2','3','1'}, {'2','1','3','2','1','2'}, {'2','2','3','1','1','2'}, {'3','1','2','1','3','1'},
55 {'3','1','1','2','2','2'}, {'3','2','1','1','2','2'}, {'3','2','1','2','2','1'}, {'3','1','2','2','1','2'},
56 {'3','2','2','1','1','2'}, {'3','2','2','2','1','1'}, {'2','1','2','1','2','3'}, {'2','1','2','3','2','1'},
57 {'2','3','2','1','2','1'}, {'1','1','1','3','2','3'}, {'1','3','1','1','2','3'}, {'1','3','1','3','2','1'},
58 {'1','1','2','3','1','3'}, {'1','3','2','1','1','3'}, {'1','3','2','3','1','1'}, {'2','1','1','3','1','3'},
59 {'2','3','1','1','1','3'}, {'2','3','1','3','1','1'}, {'1','1','2','1','3','3'}, {'1','1','2','3','3','1'},
60 {'1','3','2','1','3','1'}, {'1','1','3','1','2','3'}, {'1','1','3','3','2','1'}, {'1','3','3','1','2','1'},
61 {'3','1','3','1','2','1'}, {'2','1','1','3','3','1'}, {'2','3','1','1','3','1'}, {'2','1','3','1','1','3'},
62 {'2','1','3','3','1','1'}, {'2','1','3','1','3','1'}, {'3','1','1','1','2','3'}, {'3','1','1','3','2','1'},
63 {'3','3','1','1','2','1'}, {'3','1','2','1','1','3'}, {'3','1','2','3','1','1'}, {'3','3','2','1','1','1'},
64 {'3','1','4','1','1','1'}, {'2','2','1','4','1','1'}, {'4','3','1','1','1','1'}, {'1','1','1','2','2','4'},
65 {'1','1','1','4','2','2'}, {'1','2','1','1','2','4'}, {'1','2','1','4','2','1'}, {'1','4','1','1','2','2'},
66 {'1','4','1','2','2','1'}, {'1','1','2','2','1','4'}, {'1','1','2','4','1','2'}, {'1','2','2','1','1','4'},
67 {'1','2','2','4','1','1'}, {'1','4','2','1','1','2'}, {'1','4','2','2','1','1'}, {'2','4','1','2','1','1'},
68 {'2','2','1','1','1','4'}, {'4','1','3','1','1','1'}, {'2','4','1','1','1','2'}, {'1','3','4','1','1','1'},
69 {'1','1','1','2','4','2'}, {'1','2','1','1','4','2'}, {'1','2','1','2','4','1'}, {'1','1','4','2','1','2'},
70 {'1','2','4','1','1','2'}, {'1','2','4','2','1','1'}, {'4','1','1','2','1','2'}, {'4','2','1','1','1','2'},
71 {'4','2','1','2','1','1'}, {'2','1','2','1','4','1'}, {'2','1','4','1','2','1'}, {'4','1','2','1','2','1'},
72 {'1','1','1','1','4','3'}, {'1','1','1','3','4','1'}, {'1','3','1','1','4','1'}, {'1','1','4','1','1','3'},
73 {'1','1','4','3','1','1'}, {'4','1','1','1','1','3'}, {'4','1','1','3','1','1'}, {'1','1','3','1','4','1'},
74 {'1','1','4','1','3','1'}, {'3','1','1','1','4','1'}, {'4','1','1','1','3','1'}, {'2','1','1','4','1','2'},
75 {'2','1','1','2','1','4'}, {'2','1','1','2','3','2'}, {/* Only used by CODE16K */ '2','1','1','1','3','3'}
76 };
77
78 /* Code Set states */
79 #define C128_A0 1
80 #define C128_B0 2
81 #define C128_A1 3
82 #define C128_B1 4
83 #define C128_C0 5
84 #define C128_C1 6
85 #define C128_STATES 7
86
87 /* Helpers to characterize Code Set states */
88 #define C128_A0B0(cset) ((cset) <= C128_B0)
89 #define C128_C0C1(cset) ((cset) >= C128_C0)
90 #define C128_A0A1(cset) ((cset) & 1) /* Assuming !C */
91 #define C128_AB(cset) ((cset) >> ((cset) > C128_B0)) /* Assuming !C */
92
93 /* Code Set states are named A0, B0, A1, B1, C0 and C1. A, B, and C are the Code 128 Code Sets.
94 0 is for ASCII and 1 is for extended ASCII range */
95 static const char c128_latch_seq[C128_STATES][C128_STATES][3] = {
96 /* Current: A0 B0 A1 B1 C0 C1 Prior */
97 { {0} },
98 { {0}, { 0 }, {100 }, {101,101 }, {100,100,100}, { 99 }, {101,101, 99} }, /* A0 */
99 { {0}, {101 }, { 0 }, {101,101,101}, {100,100 }, { 99 }, {100,100, 99} }, /* B0 */
100 { {0}, {101,101 }, {100,100,100}, { 0 }, {100 }, {101,101, 99}, { 99 } }, /* A1 */
101 { {0}, {101,101,101}, {100,100 }, {101 }, { 0 }, {100,100, 99}, { 99 } }, /* B1 */
102 { {0}, {101 }, {100 }, {101,101,101}, {100,100,100}, { 0 }, { 0 } }, /* C0 */
103 { {0}, {101,101,101}, {100,100,100}, {101 }, {100 }, { 0 }, { 0 } }, /* C1 */
104 };
105 static const char c128_latch_len[C128_STATES][C128_STATES] = { /* Lengths of above */
106 /* Current: A0 B0 A1 B1 C0 C1 Prior */
107 { 0 },
108 { 0, 0, 1, 2, 3, 1, 3 }, /* A0 */
109 { 0, 1, 0, 3, 2, 1, 3 }, /* B0 */
110 { 0, 2, 3, 0, 1, 3, 1 }, /* A1 */
111 { 0, 3, 2, 1, 0, 3, 1 }, /* B1 */
112 { 0, 1, 1, 3, 3, 0, 64 }, /* C0 */
113 { 0, 3, 3, 1, 1, 64, 0 }, /* C1 */
114 };
115
116 /* Start sequences for normal, GS1_MODE and READER_INIT (mutually exclusive) */
117 static const char c128_start_latch_seq[3][C128_STATES][4] = {
118 /* A0 B0 A1 B1 C0 C1 (not used) */
119 { {0}, {103 }, {104 }, {103,101,101 }, {104,100,100 }, {105 } }, /* Normal */
120 { {0}, {103,102}, {104,102}, {103,102,101,101}, {104,102,100,100}, {105,102 } }, /* GS1_MODE */
121 { {0}, {103, 96}, {104, 96}, {103, 96,101,101}, {104, 96,100,100}, {104, 96,99} }, /* READER_INIT */
122 };
123 static const char c128_start_latch_len[3][C128_STATES] = { /* Lengths of above */
124 /* A0 B0 A1 B1 C0 C1 (not used) */
125 { 0, 1, 1, 3, 3, 1 }, /* Normal */
126 { 0, 2, 2, 4, 4, 2 }, /* GS1_MODE */
127 { 0, 2, 2, 4, 4, 3 }, /* READER_INIT */
128 };
129
130 /* Output cost (length) for Code Sets A/B */
131 static int c128_cost_ab(const int cset, const unsigned char ch, int *p_mode) {
132 const unsigned char mask_0x60 = ch & 0x60; /* 0 for (ch & 0x7F) < 32, 0x60 for (ch & 0x7F) >= 96 */
133 const int ga = C128_A0A1(cset);
134 int cost = 1;
135
136 assert(!C128_C0C1(cset));
137
138 /* SHIFT */
139 if ((ga && mask_0x60 == 0x60) || (!ga && !mask_0x60)) { /* A and (ch & 0x7F) >= 96, or B and (ch & 0x7F) < 32 */
140 cost++;
141 *p_mode |= 0x10;
142 }
143
144 /* FNC4 */
145 if (C128_A0B0(cset) == (ch >= 128)) { /* If A0/B0 and extended ASCII, or A1/B1 and ASCII */
146 cost++;
147 *p_mode |= 0x20;
148 }
149
150 return cost;
151 }
152
153 /* Calculate the cost of encoding from `i` starting in Code Set `prior_cset` (see `c128_set_values()` below) */
154 static int c128_cost(const unsigned char source[], const int length, const int i, const int prior_cset,
155 const int start_idx, const char priority[C128_STATES], const char fncs[C128_MAX],
156 const char manuals[C128_MAX], short (*costs)[C128_STATES], char (*modes)[C128_STATES]) {
157
158 const unsigned char ch = source[i];
159 const char *const latch_len = prior_cset == 0 ? c128_start_latch_len[start_idx] : c128_latch_len[prior_cset];
160 const int is_fnc1 = ch == '\x1D' && fncs[i];
161 const int can_c = is_fnc1 || (z_isdigit(ch) && z_isdigit(source[i + 1])); /* Assumes source NUL-terminated */
162 const int manual_c_fail = !can_c && manuals[i] == C128_C0; /* C requested but not doable */
163 int min_cost = 999999; /* Max possible cost less than 2 * 256 */
164 int min_mode = 0;
165 int p;
166
167 for (p = 0; priority[p]; p++) {
168 const int cset = priority[p];
169 if (C128_C0C1(cset)) {
170 if (can_c && (!manuals[i] || manuals[i] == C128_C0)) {
171 const int incr = 2 - is_fnc1;
172 int mode = prior_cset;
173 int cost = 1;
174 if (prior_cset != cset) {
175 cost += latch_len[cset];
176 mode = cset;
177 }
178 if (i + incr < length) {
179 /* Check if memoized */
180 if (costs[i + incr][cset]) {
181 cost += costs[i + incr][cset];
182 } else {
183 cost += c128_cost(source, length, i + incr, cset, 0 /*start_idx*/, priority, fncs, manuals,
184 costs, modes);
185 }
186 }
187 if (cost < min_cost) {
188 min_cost = cost;
189 min_mode = mode;
190 }
191 }
192 } else {
193 if (!manuals[i] || manuals[i] == C128_AB(cset) || manual_c_fail) {
194 int mode = cset;
195 int cost = is_fnc1 ? 1 : c128_cost_ab(cset, ch, &mode);
196 if (prior_cset != cset) {
197 cost += latch_len[cset];
198 }
199 if (i + 1 < length) {
200 /* Check if memoized */
201 if (costs[i + 1][cset]) {
202 cost += costs[i + 1][cset];
203 } else {
204 cost += c128_cost(source, length, i + 1, cset, 0 /*start_idx*/, priority, fncs, manuals,
205 costs, modes);
206 }
207 }
208 if (cost < min_cost) {
209 min_cost = cost;
210 min_mode = mode;
211 }
212 }
213 }
214 }
215 assert(min_cost != 999999);
216
217 costs[i][prior_cset] = min_cost;
218 modes[i][prior_cset] = min_mode;
219
220 return min_cost;
221 }
222
223 /* Minimal encoding using Divide-And-Conquer with Memoization by Alex Geller - see
224 https://github.com/zxing/zxing/commit/94fb277607003c070ffd1413754a782f3f87cbcd
225 Many ideas, especially enabling extended ASCII, taken from BWIPP minimal encoding by Bue Jensen - see
226 https://github.com/bwipp/postscriptbarcode/pull/278 */
227 static int c128_set_values(const unsigned char source[], const int length, const int start_idx,
228 const char priority[C128_STATES], const char fncs[C128_MAX], const char manuals[C128_MAX],
229 int values[C128_VALUES_MAX], int *p_final_cset) {
230
231 short (*costs)[C128_STATES] = (short (*)[C128_STATES]) z_alloca(sizeof(*costs) * length);
232 char (*modes)[C128_STATES] = (char (*)[C128_STATES]) z_alloca(sizeof(*modes) * length);
233 int glyph_count = 0;
234 int cset = 0;
235 int i;
236
237 memset(costs, 0, sizeof(*costs) * length);
238
239 c128_cost(source, length, 0 /*i*/, 0 /*prior_cset*/, start_idx, priority, fncs, manuals, costs, modes);
240
241 if (costs[0][0] > C128_SYMBOL_MAX) { /* Total minimal cost (glyph count) */
242 return costs[0][0];
243 }
244
245 /* Output codewords into `values` */
246 for (i = 0; i < length; i++) {
247 const unsigned char ch = source[i];
248 const int is_fnc1 = ch == '\x1D' && fncs[i];
249 const int mode = modes[i][cset];
250 const int prior_cset = cset;
251
252 cset = mode & 0x0F;
253 assert(cset);
254 if (cset != prior_cset) {
255 int j;
256 if (prior_cset == 0) {
257 for (j = 0; j < c128_start_latch_len[start_idx][cset]; j++) {
258 values[glyph_count++] = c128_start_latch_seq[start_idx][cset][j];
259 }
260 } else {
261 for (j = 0; j < c128_latch_len[prior_cset][cset]; j++) {
262 values[glyph_count++] = c128_latch_seq[prior_cset][cset][j];
263 }
264 }
265 }
266 if (mode >= 0x30) {
267 /* Extended Shift A/B */
268 values[glyph_count++] = 100 + C128_A0A1(cset); /* FNC4 */
269 values[glyph_count++] = 98; /* SHIFT */
270 } else if (mode >= 0x20) {
271 /* Extended A/B */
272 values[glyph_count++] = 100 + C128_A0A1(cset); /* FNC4 */
273 } else if (mode >= 0x10) {
274 /* Shift A/B */
275 values[glyph_count++] = 98; /* SHIFT */
276 }
277 if (is_fnc1) {
278 values[glyph_count++] = 102; /* FNC1 */
279 } else if (C128_C0C1(cset)) {
280 assert(i + 1 < length); /* Guaranteed by algorithm */
281 values[glyph_count++] = (ch - '0') * 10 + source[++i] - '0';
282 } else {
283 /* (ch & 0x7F) < 32 ? (ch & 0x7F) + 64 : (ch & 0x7F) - 32 */
284 values[glyph_count++] = (ch & 0x7F) + 96 * !(ch & 0x60) - 32;
285 }
286 }
287 assert(glyph_count == costs[0][0]);
288
289 if (p_final_cset) {
290 *p_final_cset = cset;
291 }
292
293 return glyph_count;
294 }
295
296 /* Helper to write out symbol, calculating check digit */
297 static void c128_expand(struct zint_symbol *symbol, int values[C128_VALUES_MAX], int glyph_count) {
298 char dest[640]; /* (102 + 1 (check digit)) * 6 + 7 (Stop) = 625 */
299 char *d = dest;
300 int total_sum;
301 int i;
302
303 /* Destination setting and check digit calculation */
304 memcpy(d, C128Table[values[0]], 6);
305 d += 6;
306 total_sum = values[0];
307
308 for (i = 1; i < glyph_count; i++, d += 6) {
309 memcpy(d, C128Table[values[i]], 6);
310 total_sum += values[i] * i; /* Note can't overflow as 106 * C128_SYMBOL_MAX * C128_SYMBOL_MAX = 1102824 */
311 }
312 total_sum %= 103;
313 memcpy(d, C128Table[total_sum], 6);
314 d += 6;
315 values[glyph_count++] = total_sum; /* For debug/test */
316
317 /* Stop character */
318 memcpy(d, "2331112", 7);
319 d += 7;
320 values[glyph_count++] = 106; /* For debug/test */
321
322 if (symbol->debug & ZINT_DEBUG_PRINT) {
323 fputs("Codewords:", stdout);
324 for (i = 0; i < glyph_count; i++) {
325 printf(" %d", values[i]);
326 }
327 printf(" (%d)\n", glyph_count);
328 printf("Barspaces: %.*s\n", (int) (d - dest), dest);
329 printf("Checksum: %d\n", total_sum);
330 }
331 #ifdef ZINT_TEST
332 if (symbol->debug & ZINT_DEBUG_TEST) {
333 debug_test_codeword_dump_int(symbol, values, glyph_count);
334 }
335 #endif
336
337 expand(symbol, dest, d - dest);
338 }
339
340 /* Helper to set `priority` array based on flags */
341 static void c128_set_priority(char priority[C128_STATES], const int have_a, const int have_b, const int have_c,
342 const int have_extended) {
343 int i = 0;
344 if (have_c) {
345 priority[i++] = C128_C0;
346 }
347 if (have_b || !have_a) {
348 priority[i++] = C128_B0;
349 }
350 if (have_a) {
351 priority[i++] = C128_A0;
352 }
353 if (have_extended) {
354 if (have_c) {
355 priority[i++] = C128_C1;
356 }
357 if (have_b || !have_a) {
358 priority[i++] = C128_B1;
359 }
360 if (have_a) {
361 priority[i++] = C128_A1;
362 }
363 }
364 priority[i] = 0;
365 }
366
367 /* Handle Code 128, 128AB and HIBC 128 */
368 INTERNAL int code128(struct zint_symbol *symbol, unsigned char source[], int length) {
369 int i;
370 int error_number;
371 char manuals[C128_MAX] = {0};
372 char fncs[C128_MAX] = {0}; /* Manual FNC1 positions */
373 int have_fnc1 = 0; /* Whether have at least 1 manual FNC1 */
374 int have_a = 0, have_b = 0, have_c = 0, have_extended = 0;
375 char priority[C128_STATES];
376 int values[C128_VALUES_MAX] = {0};
377 int glyph_count;
378 unsigned char src_buf[C128_MAX + 1];
379 unsigned char *src = source;
380 const int ab_only = symbol->symbology == BARCODE_CODE128AB;
381 const int start_idx = (symbol->output_options & READER_INIT) ? 2 : 0;
382
383 if (length > C128_MAX) {
384 /* This only blocks ridiculously long input - the actual length of the
385 resulting barcode depends on the type of data, so this is trapped later */
386 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 340, "Input length %d too long (maximum " C128_MAX_S ")", length);
387 }
388
389 /* Detect special Code Set escapes for Code 128 in extra escape mode only */
390 if ((symbol->input_mode & EXTRA_ESCAPE_MODE) && symbol->symbology == BARCODE_CODE128) {
391 char manual = 0;
392 int j = 0;
393 for (i = 0; i < length; i++) {
394 if (source[i] == '\\' && i + 2 < length && source[i + 1] == '^'
395 && ((source[i + 2] >= '@' && source[i + 2] <= 'C') || source[i + 2] == '1'
396 || source[i + 2] == '^')) {
397 if (source[i + 2] == '^') { /* Escape sequence '\^^' */
398 manuals[j] = manual;
399 src_buf[j++] = source[i++];
400 manuals[j] = manual;
401 src_buf[j++] = source[i++];
402 /* Drop second '^' */
403 } else if (source[i + 2] == '1') { /* FNC1 */
404 i += 2;
405 fncs[j] = have_fnc1 = 1;
406 manuals[j] = manual;
407 src_buf[j++] = '\x1D'; /* Manual FNC1 dummy */
408 } else { /* Manual mode A/B/C/@ */
409 i += 2;
410 manual = source[i] == 'C' ? C128_C0 : source[i] - '@'; /* Assuming A0 = 1, B0 = 2 */
411 }
412 } else {
413 manuals[j] = manual;
414 src_buf[j++] = source[i];
415 }
416 }
417 if (j != length) {
418 length = j;
419 if (length == 0) {
420 return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 842, "No input data");
421 }
422 src = src_buf;
423 src[length] = '\0';
424 if (symbol->debug & ZINT_DEBUG_PRINT) {
425 fputs("Manuals: ", stdout);
426 for (i = 0; i < length; i++) {
427 printf("%c", manuals[i] == C128_C0 ? 'C' : '@' + manuals[i]); /* Assuming A0 = 1, B0 = 2 */
428 }
429 fputc('\n', stdout);
430 }
431 }
432 }
433
434 /* Classify data to detect which Code Set states are needed */
435 if (ab_only) {
436 for (i = 0; i < length; i++) {
437 const unsigned char ch = src[i];
438 const unsigned char mask_0x60 = ch & 0x60; /* 0 for (ch & 0x7F) < 32, 0x60 for (ch & 0x7F) >= 96 */
439 have_extended |= ch & 0x80;
440 have_a |= !mask_0x60;
441 have_b |= mask_0x60 == 0x60;
442 }
443 } else {
444 int prev_digit, digit = 0;
445 for (i = 0; i < length; i++) {
446 const unsigned char ch = src[i];
447 const int is_fnc1 = ch == '\x1D' && fncs[i];
448 if (!is_fnc1) {
449 const unsigned char mask_0x60 = ch & 0x60; /* 0 for (ch & 0x7F) < 32, 0x60 for (ch & 0x7F) >= 96 */
450 const int manual = manuals[i];
451 have_extended |= ch & 0x80;
452 have_a |= !mask_0x60 || manual == C128_A0;
453 have_b |= mask_0x60 == 0x60 || manual == C128_B0;
454 prev_digit = digit;
455 digit = z_isdigit(ch);
456 have_c |= prev_digit && digit;
457 }
458 }
459 }
460 c128_set_priority(priority, have_a, have_b, have_c, have_extended);
461
462 glyph_count = c128_set_values(src, length, start_idx, priority, fncs, manuals, values, NULL /*p_final_cset*/);
463
464 if (symbol->debug & ZINT_DEBUG_PRINT) {
465 printf("Data (%d): %.*s", length, length >= 100 ? 1 : length >= 10 ? 2 : 3, " ");
466 debug_print_escape(src, length, NULL);
467 printf("\nGlyphs: %d\n", glyph_count);
468 }
469
470 /* Now we know how long the barcode is - stop it from being too long */
471 if (glyph_count > C128_SYMBOL_MAX) {
472 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 341,
473 "Input too long, requires %d symbol characters (maximum " C128_SYMBOL_MAX_S ")", glyph_count);
474 }
475
476 /* Now we can get on with it! */
477 c128_expand(symbol, values, glyph_count);
478
479 /* ISO/IEC 15417:2007 leaves dimensions/height as application specification */
480
481 /* HRT */
482 if (have_fnc1) {
483 /* Remove any manual FNC1 dummies ('\x1D') */
484 int j = 0;
485 for (i = 0; i < length; i++) {
486 if (!fncs[i]) {
487 src[j++] = src[i];
488 }
489 }
490 length = j;
491 }
492 error_number = hrt_cpy_iso8859_1(symbol, src, length);
493
494 return error_number;
495 }
496
497 /* Handle GS1-128 (formerly known as EAN-128), and composite version if `cc_mode` set */
498 INTERNAL int gs1_128_cc(struct zint_symbol *symbol, unsigned char source[], int length, const int cc_mode,
499 const int cc_rows) {
500 int i;
501 int error_number;
502 const char manuals[C128_MAX] = {0}; /* Dummy */
503 char fncs[C128_MAX]; /* Dummy, set to all 1s */
504 char priority[C128_STATES];
505 int values[C128_VALUES_MAX] = {0};
506 int glyph_count;
507 int final_cset;
508 int separator_row = 0;
509 int reduced_length;
510 unsigned char *reduced = (unsigned char *) z_alloca(length + 1);
511
512 if (length > C128_MAX) {
513 /* This only blocks ridiculously long input - the actual length of the
514 resulting barcode depends on the type of data, so this is trapped later */
515 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 342, "Input length %d too long (maximum " C128_MAX_S ")", length);
516 }
517
518 /* If part of a composite symbol make room for the separator pattern */
519 if (symbol->symbology == BARCODE_GS1_128_CC) {
520 separator_row = symbol->rows;
521 symbol->row_height[symbol->rows] = 1;
522 symbol->rows += 1;
523 }
524
525 error_number = gs1_verify(symbol, source, length, reduced);
526 if (error_number >= ZINT_ERROR) {
527 return error_number;
528 }
529
530 reduced_length = (int) ustrlen(reduced);
531 memset(fncs, 1, reduced_length);
532
533 /* Control and extended chars not allowed so only have B/C (+FNC1) */
534 c128_set_priority(priority, 0 /*have_a*/, 1 /*have_b*/, 1 /*have_c*/, 0 /*have_extended*/);
535
536 glyph_count = c128_set_values(reduced, reduced_length, 1 /*start_idx*/, priority, fncs, manuals, values,
537 &final_cset);
538
539 if (symbol->debug & ZINT_DEBUG_PRINT) {
540 printf("Data (%d): %.*s", reduced_length, reduced_length >= 100 ? 1 : reduced_length >= 10 ? 2 : 3, " ");
541 debug_print_escape(reduced, reduced_length, NULL);
542 printf("\nGlyphs: %d\n", glyph_count);
543 }
544
545 /* Now we can calculate how long the barcode is going to be - and stop it from
546 being too long */
547 if (glyph_count + (cc_mode != 0) > C128_SYMBOL_MAX) {
548 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 344,
549 "Input too long, requires %d symbol characters (maximum " C128_SYMBOL_MAX_S ")",
550 glyph_count + (cc_mode != 0));
551 }
552
553 /* "...note that the linkage flag is an extra Code Set character between
554 the last data character and the Symbol Check Character" (GS1 Specification) */
555
556 /* Linkage flags in GS1-128 are determined by ISO/IEC 24723 section 7.4 */
557 assert(final_cset == C128_B0 || final_cset == C128_C0);
558
559 switch (cc_mode) {
560 case 1:
561 case 2:
562 /* CC-A or CC-B 2D component */
563 switch (final_cset) {
564 case C128_B0:
565 values[glyph_count++] = 99;
566 break;
567 case C128_C0:
568 values[glyph_count++] = 101;
569 break;
570 }
571 break;
572 case 3:
573 /* CC-C 2D component */
574 switch (final_cset) {
575 case C128_B0:
576 values[glyph_count++] = 101;
577 break;
578 case C128_C0:
579 values[glyph_count++] = 100;
580 break;
581 }
582 break;
583 }
584
585 c128_expand(symbol, values, glyph_count);
586
587 /* Add the separator pattern for composite symbols */
588 if (symbol->symbology == BARCODE_GS1_128_CC) {
589 for (i = 0; i < symbol->width; i++) {
590 if (!(module_is_set(symbol, separator_row + 1, i))) {
591 set_module(symbol, separator_row, i);
592 }
593 }
594 }
595
596 if (reduced_length > 48) { /* GS1 General Specifications 5.4.4.3 */
597 if (error_number == 0) { /* Don't overwrite any `gs1_verify()` warning */
598 error_number = errtxtf(ZINT_WARN_NONCOMPLIANT, symbol, 843,
599 "Input too long, requires %d characters (maximum 48)", reduced_length);
600 }
601 }
602
603 if (symbol->output_options & COMPLIANT_HEIGHT) {
604 /* GS1 General Specifications 21.0.1 5.12.3.2 table 2, including footnote (**):
605 same as ITF-14: "in case of further space constraints" height 5.8mm / 1.016mm (X max) ~ 5.7;
606 default 31.75mm / 0.495mm ~ 64.14 */
607 const float min_height = 5.70866156f; /* 5.8 / 1.016 */
608 const float default_height = 64.1414108f; /* 31.75 / 0.495 */
609 if (symbol->symbology == BARCODE_GS1_128_CC) {
610 /* Pass back via temporary linear structure */
611 symbol->height = symbol->height ? min_height : default_height;
612 } else {
613 if (error_number == 0) { /* Don't overwrite any `gs1_verify()` warning */
614 error_number = set_height(symbol, min_height, default_height, 0.0f, 0 /*no_errtxt*/);
615 } else {
616 (void) set_height(symbol, min_height, default_height, 0.0f, 1 /*no_errtxt*/);
617 }
618 }
619 } else {
620 const float height = 50.0f;
621 if (symbol->symbology == BARCODE_GS1_128_CC) {
622 symbol->height = height - cc_rows * (cc_mode == 3 ? 3 : 2) - 1.0f;
623 } else {
624 (void) set_height(symbol, 0.0f, height, 0.0f, 1 /*no_errtxt*/);
625 }
626 }
627
628 /* If no other warnings flag use of READER_INIT in GS1_MODE */
629 if (error_number == 0 && (symbol->output_options & READER_INIT)) {
630 error_number = errtxt(ZINT_WARN_INVALID_OPTION, symbol, 845,
631 "Cannot use Reader Initialisation in GS1 mode, ignoring");
632 }
633
634 if (symbol->input_mode & GS1PARENS_MODE) {
635 i = length < (int) sizeof(symbol->text) ? length : (int) sizeof(symbol->text);
636 memcpy(symbol->text, source, i);
637 } else {
638 int bracket_level = 0; /* Non-compliant closing square brackets may be in text */
639 for (i = 0; i < length && i < (int) sizeof(symbol->text); i++) {
640 if (source[i] == '[') {
641 symbol->text[i] = '(';
642 bracket_level++;
643 } else if (source[i] == ']' && bracket_level) {
644 symbol->text[i] = ')';
645 bracket_level--;
646 } else {
647 symbol->text[i] = source[i];
648 }
649 }
650 }
651 if (i == sizeof(symbol->text)) {
652 /* Trumps all other warnings */
653 error_number = errtxt(ZINT_WARN_HRT_TRUNCATED, symbol, 844, "Human Readable Text truncated");
654 i--;
655 }
656 symbol->text[i] = '\0';
657
658 return error_number;
659 }
660
661 /* Handle GS1-128 (formerly known as EAN-128) */
662 INTERNAL int gs1_128(struct zint_symbol *symbol, unsigned char source[], int length) {
663 return gs1_128_cc(symbol, source, length, 0 /*cc_mode*/, 0 /*cc_rows*/);
664 }
665
666 /* Helper to do NVE18 or EAN14 */
667 static int nve18_or_ean14(struct zint_symbol *symbol, unsigned char source[], const int length, const int data_len) {
668 static const char prefix[2][2][5] = {
669 { "(01)", "[01]" }, /* EAN14 */
670 { "(00)", "[00]" }, /* NVE18 */
671 };
672 unsigned char ean128_equiv[23];
673 int error_number, zeroes;
674 int i;
675
676 if (length > data_len) {
677 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 345, "Input length %1$d too long (maximum %2$d)", length,
678 data_len);
679 }
680
681 if ((i = not_sane(NEON_F, source, length))) {
682 /* Note: for all "at position" error messages, escape sequences not accounted for */
683 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 346,
684 "Invalid character at position %d in input (digits only)", i);
685 }
686
687 zeroes = data_len - length;
688 ustrcpy(ean128_equiv, prefix[data_len == 17][!(symbol->input_mode & GS1PARENS_MODE)]);
689 memset(ean128_equiv + 4, '0', zeroes);
690 ustrcpy(ean128_equiv + 4 + zeroes, source);
691
692 ean128_equiv[data_len + 4] = gs1_check_digit(ean128_equiv + 4, data_len);
693 ean128_equiv[data_len + 5] = '\0';
694
695 error_number = gs1_128(symbol, ean128_equiv, data_len + 5);
696
697 return error_number;
698 }
699
700
701 /* Add check digit if encoding an NVE18 symbol */
702 INTERNAL int nve18(struct zint_symbol *symbol, unsigned char source[], int length) {
703 return nve18_or_ean14(symbol, source, length, 17 /*data_len*/);
704 }
705
706 /* EAN-14 - A version of EAN-128 */
707 INTERNAL int ean14(struct zint_symbol *symbol, unsigned char source[], int length) {
708 return nve18_or_ean14(symbol, source, length, 13 /*data_len*/);
709 }
710
711 static const char KRSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
712 #define KRSET_F (IS_NUM_F | IS_UPR_F)
713
714 /* DPD (Deutscher Paketdienst) Code */
715 /* Specification at https://esolutions.dpd.com/dokumente/DPD_Parcel_Label_Specification_2.4.1_EN.pdf
716 * and identification tag info (Barcode ID) at https://esolutions.dpd.com/dokumente/DPD_Routing_Database_1.3_EN.pdf */
717 INTERNAL int dpd(struct zint_symbol *symbol, unsigned char source[], int length) {
718 int error_number = 0;
719 int i, p;
720 unsigned char ident_tag;
721 unsigned char local_source_buf[29];
722 unsigned char *local_source;
723 const int mod = 36;
724 const int relabel = symbol->option_2 == 1; /* A "relabel" has no identification tag */
725 int cd; /* Check digit */
726
727 if ((length != 27 && length != 28) || (length == 28 && relabel)) {
728 if (relabel) {
729 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 830, "DPD relabel input length %d wrong (27 only)", length);
730 }
731 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 349, "DPD input length %d wrong (27 or 28 only)", length);
732 }
733
734 if (length == 27 && !relabel) {
735 local_source_buf[0] = '%';
736 ustrcpy(local_source_buf + 1, source);
737 local_source = local_source_buf;
738 length++;
739 } else {
740 local_source = source;
741 }
742
743 ident_tag = local_source[0];
744
745 to_upper(local_source + !relabel, length - !relabel);
746 if ((i = not_sane(KRSET_F, local_source + !relabel, length - !relabel))) {
747 if (local_source == local_source_buf || relabel) {
748 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 300,
749 "Invalid character at position %d in input (alphanumerics only)", i);
750 }
751 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 299,
752 "Invalid character at position %d in input (alphanumerics only after first)", i);
753 }
754
755 if ((ident_tag < 32) || (ident_tag > 127)) {
756 return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 343,
757 "Invalid DPD identification tag (first character), ASCII values 32 to 127 only");
758 }
759
760 (void) code128(symbol, local_source, length); /* Only error returned is for large text which can't happen */
761
762 if (!(symbol->output_options & (BARCODE_BOX | BARCODE_BIND | BARCODE_BIND_TOP))) {
763 /* If no option has been selected then uses default bind top option */
764 symbol->output_options |= BARCODE_BIND_TOP; /* Note won't extend over quiet zones for DPD */
765 if (symbol->border_width == 0) { /* Allow override if non-zero */
766 symbol->border_width = 3; /* From examples, not mentioned in spec */
767 }
768 }
769
770 if (symbol->output_options & COMPLIANT_HEIGHT) {
771 /* DPD Parcel Label Specification Version 2.4.1 (19.01.2021) Section 4.6.1.2
772 25mm / 0.4mm (X max) = 62.5 min, 25mm / 0.375 (X) ~ 66.66 default */
773 if (relabel) { /* If relabel then half-size */
774 const float default_height = 33.3333321f; /* 12.5 / 0.375 */
775 error_number = set_height(symbol, 31.25f, default_height, 0.0f, 0 /*no_errtxt*/);
776 } else {
777 const float default_height = 66.6666641f; /* 25.0 / 0.375 */
778 error_number = set_height(symbol, 62.5f, default_height, 0.0f, 0 /*no_errtxt*/);
779 }
780 } else {
781 (void) set_height(symbol, 0.0f, relabel ? 25.0f : 50.0f, 0.0f, 1 /*no_errtxt*/);
782 }
783
784 cd = mod;
785
786 p = 0;
787 for (i = !relabel; i < length; i++) {
788 symbol->text[p] = local_source[i];
789 p++;
790
791 cd += posn(KRSET, local_source[i]);
792 if (cd > mod) cd -= mod;
793 cd *= 2;
794 if (cd >= (mod + 1)) cd -= mod + 1;
795
796 switch (i + relabel) {
797 case 4:
798 case 7:
799 case 11:
800 case 15:
801 case 19:
802 case 21:
803 case 24:
804 case 27:
805 symbol->text[p++] = ' ';
806 break;
807 }
808 }
809
810 cd = mod + 1 - cd;
811 if (cd == mod) cd = 0;
812
813 if (cd < 10) {
814 symbol->text[p] = cd + '0';
815 } else {
816 symbol->text[p] = (cd - 10) + 'A';
817 }
818 p++;
819
820 symbol->text[p] = '\0';
821
822 /* Some compliance checks */
823 if (not_sane(NEON_F, local_source + length - 16, 16)) {
824 if (not_sane(NEON_F, local_source + length - 3, 3)) { /* 3-digit Country Code (ISO 3166-1) */
825 errtxt(0, symbol, 831, "Destination Country Code (last 3 characters) should be numeric");
826 } else if (not_sane(NEON_F, local_source + length - 6, 3)) { /* 3-digit Service Code */
827 errtxt(0, symbol, 832, "Service Code (characters 6-4 from end) should be numeric");
828 } else { /* Last 10 characters of Tracking No. */
829 errtxt(0, symbol, 833,
830 "Last 10 characters of Tracking Number (characters 16-7 from end) should be numeric");
831 }
832 error_number = ZINT_WARN_NONCOMPLIANT;
833 }
834
835 return error_number;
836 }
837
838 /* Universal Postal Union S10 */
839 /* https://www.upu.int/UPU/media/upu/files/postalSolutions/programmesAndServices/standards/S10-12.pdf */
840 INTERNAL int upu_s10(struct zint_symbol *symbol, unsigned char source[], int length) {
841 int i, j;
842 unsigned char local_source[13 + 1];
843 unsigned char have_check_digit = '\0';
844 int check_digit;
845 static const char weights[8] = { 8, 6, 4, 2, 3, 5, 9, 7 };
846 int error_number = 0;
847
848 if (length != 12 && length != 13) {
849 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 834, "Input length %d wrong (12 or 13 only)", length);
850 }
851 if (length == 13) { /* Includes check digit - remove for now */
852 have_check_digit = source[10];
853 memcpy(local_source, source, 10);
854 ustrcpy(local_source + 10, source + 11);
855 } else {
856 ustrcpy(local_source, source);
857 }
858 to_upper(local_source, length);
859
860 if (!z_isupper(local_source[0]) || !z_isupper(local_source[1])) {
861 return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 835,
862 "Invalid character in Service Indictor (first 2 characters) (alphabetic only)");
863 }
864 if (not_sane(NEON_F, local_source + 2, 12 - 4) || (have_check_digit && !z_isdigit(have_check_digit))) {
865 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 836,
866 "Invalid character in Serial Number (middle %d characters) (digits only)",
867 have_check_digit ? 9 : 8);
868 }
869 if (!z_isupper(local_source[10]) || !z_isupper(local_source[11])) {
870 return errtxt(ZINT_ERROR_INVALID_DATA, symbol, 837,
871 "Invalid character in Country Code (last 2 characters) (alphabetic only)");
872 }
873
874 check_digit = 0;
875 for (i = 2; i < 10; i++) { /* Serial Number only */
876 check_digit += ctoi(local_source[i]) * weights[i - 2];
877 }
878 check_digit %= 11;
879 check_digit = 11 - check_digit;
880 if (check_digit == 10) {
881 check_digit = 0;
882 } else if (check_digit == 11) {
883 check_digit = 5;
884 }
885 if (have_check_digit && ctoi(have_check_digit) != check_digit) {
886 return errtxtf(ZINT_ERROR_INVALID_CHECK, symbol, 838, "Invalid check digit '%1$c', expecting '%2$c'",
887 have_check_digit, itoc(check_digit));
888 }
889 /* Add in (back) check digit */
890 local_source[12] = local_source[11];
891 local_source[11] = local_source[10];
892 local_source[10] = itoc(check_digit);
893 local_source[13] = '\0';
894
895 /* Do some checks on the Service Indicator (first char only) and Country Code */
896 if (strchr("JKSTW", local_source[0]) != NULL) { /* These are reserved & cannot be assigned */
897 error_number = errtxt(ZINT_WARN_NONCOMPLIANT, symbol, 839,
898 "Invalid Service Indicator (first character should not be any of \"JKSTW\")");
899 } else if (strchr("FHIOXY", local_source[0]) != NULL) { /* These aren't allocated as of spec Oct 2017 */
900 error_number = errtxt(ZINT_WARN_NONCOMPLIANT, symbol, 840,
901 "Non-standard Service Indicator (first 2 characters)");
902 } else if (!gs1_iso3166_alpha2(local_source + 11)) {
903 error_number = errtxt(ZINT_WARN_NONCOMPLIANT, symbol, 841,
904 "Country code (last two characters) is not ISO 3166-1");
905 }
906
907 (void) code128(symbol, local_source, 13); /* Only error returned is for large text which can't happen */
908
909 j = 0;
910 for (i = 0; i < 13; i++) {
911 if (i == 2 || i == 5 || i == 8 || i == 11) {
912 symbol->text[j++] = ' ';
913 }
914 symbol->text[j++] = local_source[i];
915 }
916 symbol->text[j] = '\0';
917
918 if (symbol->output_options & COMPLIANT_HEIGHT) {
919 /* Universal Postal Union S10 Section 8, using max X 0.51mm & minimum height 12.5mm or 15% of width */
920 const float min_height_min = 24.5098038f; /* 12.5 / 0.51 */
921 float min_height = stripf(symbol->width * 0.15f);
922 if (min_height < min_height_min) {
923 min_height = min_height_min;
924 }
925 /* Using 50 as default as none recommended */
926 if (error_number == 0) {
927 error_number = set_height(symbol, min_height, min_height > 50.0f ? min_height : 50.0f, 0.0f,
928 0 /*no_errtxt*/);
929 } else {
930 (void) set_height(symbol, min_height, min_height > 50.0f ? min_height : 50.0f, 0.0f, 1 /*no_errtxt*/);
931 }
932 } else {
933 (void) set_height(symbol, 0.0f, 50.0f, 0.0f, 1 /*no_errtxt*/);
934 }
935
936 return error_number;
937 }
938
939 /* vim: set ts=4 sw=4 et : */