comparison mupdf-source/thirdparty/zint/backend/dmatrix.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 /* dmatrix.c Handles Data Matrix ECC 200 symbols */
2 /*
3 libzint - the open source barcode library
4 Copyright (C) 2009-2024 Robin Stuart <rstuart114@gmail.com>
5
6 developed from and including some functions from:
7 IEC16022 bar code generation
8 Adrian Kennard, Andrews & Arnold Ltd
9 with help from Cliff Hones on the RS coding
10
11 (c) 2004 Adrian Kennard, Andrews & Arnold Ltd
12 (c) 2006 Stefan Schmidt <stefan@datenfreihafen.org>
13
14 Redistribution and use in source and binary forms, with or without
15 modification, are permitted provided that the following conditions
16 are met:
17
18 1. Redistributions of source code must retain the above copyright
19 notice, this list of conditions and the following disclaimer.
20 2. Redistributions in binary form must reproduce the above copyright
21 notice, this list of conditions and the following disclaimer in the
22 documentation and/or other materials provided with the distribution.
23 3. Neither the name of the project nor the names of its contributors
24 may be used to endorse or promote products derived from this software
25 without specific prior written permission.
26
27 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
28 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
31 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 SUCH DAMAGE.
38 */
39 /* SPDX-License-Identifier: BSD-3-Clause */
40
41 #include <assert.h>
42 #include <limits.h>
43 #include <stdio.h>
44 #include "common.h"
45 #include "reedsol.h"
46 #include "dmatrix.h"
47
48 /* Annex F placement algorithm low level */
49 static void dm_placementbit(int *array, const int NR, const int NC, int r, int c, const int p, const char b) {
50 if (r < 0) {
51 r += NR;
52 c += 4 - ((NR + 4) % 8);
53 }
54 if (c < 0) {
55 c += NC;
56 r += 4 - ((NC + 4) % 8);
57 }
58 /* Necessary for DMRE (ISO/IEC 21471:2020 Annex E) */
59 if (r >= NR) {
60 r -= NR;
61 }
62 /* Check index limits */
63 assert(r < NR);
64 assert(c < NC);
65 /* Check double-assignment */
66 assert(0 == array[r * NC + c]);
67 array[r * NC + c] = (p << 3) + b;
68 }
69
70 static void dm_placementblock(int *array, const int NR, const int NC, const int r,
71 const int c, const int p) {
72 dm_placementbit(array, NR, NC, r - 2, c - 2, p, 7);
73 dm_placementbit(array, NR, NC, r - 2, c - 1, p, 6);
74 dm_placementbit(array, NR, NC, r - 1, c - 2, p, 5);
75 dm_placementbit(array, NR, NC, r - 1, c - 1, p, 4);
76 dm_placementbit(array, NR, NC, r - 1, c - 0, p, 3);
77 dm_placementbit(array, NR, NC, r - 0, c - 2, p, 2);
78 dm_placementbit(array, NR, NC, r - 0, c - 1, p, 1);
79 dm_placementbit(array, NR, NC, r - 0, c - 0, p, 0);
80 }
81
82 static void dm_placementcornerA(int *array, const int NR, const int NC, const int p) {
83 dm_placementbit(array, NR, NC, NR - 1, 0, p, 7);
84 dm_placementbit(array, NR, NC, NR - 1, 1, p, 6);
85 dm_placementbit(array, NR, NC, NR - 1, 2, p, 5);
86 dm_placementbit(array, NR, NC, 0, NC - 2, p, 4);
87 dm_placementbit(array, NR, NC, 0, NC - 1, p, 3);
88 dm_placementbit(array, NR, NC, 1, NC - 1, p, 2);
89 dm_placementbit(array, NR, NC, 2, NC - 1, p, 1);
90 dm_placementbit(array, NR, NC, 3, NC - 1, p, 0);
91 }
92
93 static void dm_placementcornerB(int *array, const int NR, const int NC, const int p) {
94 dm_placementbit(array, NR, NC, NR - 3, 0, p, 7);
95 dm_placementbit(array, NR, NC, NR - 2, 0, p, 6);
96 dm_placementbit(array, NR, NC, NR - 1, 0, p, 5);
97 dm_placementbit(array, NR, NC, 0, NC - 4, p, 4);
98 dm_placementbit(array, NR, NC, 0, NC - 3, p, 3);
99 dm_placementbit(array, NR, NC, 0, NC - 2, p, 2);
100 dm_placementbit(array, NR, NC, 0, NC - 1, p, 1);
101 dm_placementbit(array, NR, NC, 1, NC - 1, p, 0);
102 }
103
104 static void dm_placementcornerC(int *array, const int NR, const int NC, const int p) {
105 dm_placementbit(array, NR, NC, NR - 3, 0, p, 7);
106 dm_placementbit(array, NR, NC, NR - 2, 0, p, 6);
107 dm_placementbit(array, NR, NC, NR - 1, 0, p, 5);
108 dm_placementbit(array, NR, NC, 0, NC - 2, p, 4);
109 dm_placementbit(array, NR, NC, 0, NC - 1, p, 3);
110 dm_placementbit(array, NR, NC, 1, NC - 1, p, 2);
111 dm_placementbit(array, NR, NC, 2, NC - 1, p, 1);
112 dm_placementbit(array, NR, NC, 3, NC - 1, p, 0);
113 }
114
115 static void dm_placementcornerD(int *array, const int NR, const int NC, const int p) {
116 dm_placementbit(array, NR, NC, NR - 1, 0, p, 7);
117 dm_placementbit(array, NR, NC, NR - 1, NC - 1, p, 6);
118 dm_placementbit(array, NR, NC, 0, NC - 3, p, 5);
119 dm_placementbit(array, NR, NC, 0, NC - 2, p, 4);
120 dm_placementbit(array, NR, NC, 0, NC - 1, p, 3);
121 dm_placementbit(array, NR, NC, 1, NC - 3, p, 2);
122 dm_placementbit(array, NR, NC, 1, NC - 2, p, 1);
123 dm_placementbit(array, NR, NC, 1, NC - 1, p, 0);
124 }
125
126 /* Annex F placement algorithm main function */
127 static void dm_placement(int *array, const int NR, const int NC) {
128 int r, c, p;
129 /* start */
130 p = 1;
131 r = 4;
132 c = 0;
133 do {
134 /* check corner */
135 if (r == NR && !c)
136 dm_placementcornerA(array, NR, NC, p++);
137 if (r == NR - 2 && !c && NC % 4)
138 dm_placementcornerB(array, NR, NC, p++);
139 if (r == NR - 2 && !c && (NC % 8) == 4)
140 dm_placementcornerC(array, NR, NC, p++);
141 if (r == NR + 4 && c == 2 && !(NC % 8))
142 dm_placementcornerD(array, NR, NC, p++);
143 /* up/right */
144 do {
145 if (r < NR && c >= 0 && !array[r * NC + c])
146 dm_placementblock(array, NR, NC, r, c, p++);
147 r -= 2;
148 c += 2;
149 } while (r >= 0 && c < NC);
150 r++;
151 c += 3;
152 /* down/left */
153 do {
154 if (r >= 0 && c < NC && !array[r * NC + c])
155 dm_placementblock(array, NR, NC, r, c, p++);
156 r += 2;
157 c -= 2;
158 } while (r < NR && c >= 0);
159 r += 3;
160 c++;
161 } while (r < NR || c < NC);
162 /* unfilled corner */
163 if (!array[NR * NC - 1])
164 array[NR * NC - 1] = array[NR * NC - NC - 2] = 1;
165 }
166
167 /* calculate and append ecc code, and if necessary interleave */
168 static void dm_ecc(unsigned char *binary, const int bytes, const int datablock, const int rsblock, const int skew) {
169 int blocks = (bytes + 2) / datablock, b;
170 int rsblocks = rsblock * blocks;
171 int n;
172 rs_t rs;
173
174 rs_init_gf(&rs, 0x12d);
175 rs_init_code(&rs, rsblock, 1);
176 for (b = 0; b < blocks; b++) {
177 unsigned char buf[256], ecc[256];
178 int p = 0;
179 for (n = b; n < bytes; n += blocks)
180 buf[p++] = binary[n];
181 rs_encode(&rs, p, buf, ecc);
182 if (skew) {
183 /* Rotate ecc data to make 144x144 size symbols acceptable */
184 /* See http://groups.google.com/group/postscriptbarcode/msg/5ae8fda7757477da
185 or https://github.com/nu-book/zxing-cpp/issues/259 */
186 for (n = b, p = 0; n < rsblocks; n += blocks, p++) {
187 if (b < 8) {
188 binary[bytes + n + 2] = ecc[p];
189 } else {
190 binary[bytes + n - 8] = ecc[p];
191 }
192 }
193 } else {
194 for (n = b, p = 0; n < rsblocks; n += blocks, p++) {
195 binary[bytes + n] = ecc[p];
196 }
197 }
198 }
199 }
200
201 /* Is basic (non-shifted) C40? */
202 static int dm_isc40(const unsigned char input) {
203 if (input <= '9') {
204 return input >= '0' || input == ' ';
205 }
206 return z_isupper(input);
207 }
208
209 /* Is basic (non-shifted) TEXT? */
210 static int dm_istext(const unsigned char input) {
211 if (input <= '9') {
212 return input >= '0' || input == ' ';
213 }
214 return z_islower(input);
215 }
216
217 /* Is basic (non-shifted) C40/TEXT? */
218 static int dm_isc40text(const int current_mode, const unsigned char input) {
219 return current_mode == DM_C40 ? dm_isc40(input) : dm_istext(input);
220 }
221
222 /* Return true (1) if a character is valid in X12 set */
223 static int dm_isX12(const unsigned char input) {
224 return dm_isc40(input) || input == 13 || input == '*' || input == '>';
225 }
226
227 /* Return true (1) if a character is valid in EDIFACT set */
228 static int dm_isedifact(const unsigned char input) {
229 return input >= ' ' && input <= '^';
230 }
231
232 /* Does Annex J section (r)(6)(ii)(I) apply? */
233 static int dm_substep_r_6_2_1(const unsigned char source[], const int length, const int sp) {
234 /* Annex J section (r)(6)(ii)(I)
235 "If one of the three X12 terminator/separator characters first
236 occurs in the yet to be processed data before a non-X12 character..."
237 */
238 int i;
239
240 for (i = sp; i < length && dm_isX12(source[i]); i++) {
241 if (source[i] == 13 || source[i] == '*' || source[i] == '>') {
242 return 1;
243 }
244 }
245
246 return 0;
247 }
248
249 /* Count number of TEXT characters around `sp` between `position` and `length`
250 - helper to avoid exiting from Base 256 too early if have series of TEXT characters */
251 static int dm_text_sp_cnt(const unsigned char source[], const int position, const int length, const int sp) {
252 int i;
253 int cnt = 0;
254
255 /* Count from `sp` forward */
256 for (i = sp; i < length && dm_istext(source[i]); i++, cnt++);
257 /* Count backwards from `sp` */
258 for (i = sp - 1; i >= position && dm_istext(source[i]); i--, cnt++);
259
260 return cnt;
261 }
262
263 /* Character counts are multiplied by this, so as to be whole integer divisible by 2, 3 and 4 */
264 #define DM_MULT 12
265
266 #define DM_MULT_1_DIV_2 6
267 #define DM_MULT_2_DIV_3 8
268 #define DM_MULT_3_DIV_4 9
269 #define DM_MULT_1 12
270 #define DM_MULT_4_DIV_3 16
271 #define DM_MULT_2 24
272 #define DM_MULT_8_DIV_3 32
273 #define DM_MULT_3 26
274 #define DM_MULT_13_DIV_4 39
275 #define DM_MULT_10_DIV_3 40
276 #define DM_MULT_4 48
277 #define DM_MULT_17_DIV_4 51
278 #define DM_MULT_13_DIV_3 52
279
280 #define DM_MULT_MINUS_1 11
281 #define DM_MULT_CEIL(n) ((((n) + DM_MULT_MINUS_1) / DM_MULT) * DM_MULT)
282
283 /* 'look ahead test' from Annex J */
284 static int dm_look_ahead_test(const unsigned char source[], const int length, const int position,
285 const int current_mode, const int mode_arg, const int gs1, const int debug_print) {
286 int ascii_count, c40_count, text_count, x12_count, edf_count, b256_count;
287 int ascii_rnded, c40_rnded, text_rnded, x12_rnded, edf_rnded, b256_rnded;
288 int cnt_1;
289 int sp;
290
291 /* step (j) */
292 if (current_mode == DM_ASCII || current_mode == DM_BASE256) { /* Adjusted to use for DM_BASE256 also */
293 ascii_count = 0;
294 c40_count = DM_MULT_1;
295 text_count = DM_MULT_1;
296 x12_count = DM_MULT_1;
297 edf_count = DM_MULT_1;
298 b256_count = DM_MULT_2; /* Adjusted from DM_MULT_5_DIV_4 (1.25) */
299 } else {
300 ascii_count = DM_MULT_1;
301 c40_count = DM_MULT_2;
302 text_count = DM_MULT_2;
303 x12_count = DM_MULT_2;
304 edf_count = DM_MULT_2;
305 b256_count = DM_MULT_3; /* Adjusted from DM_MULT_9_DIV_4 (2.25) */
306 }
307
308 switch (current_mode) {
309 case DM_C40: c40_count = 0;
310 break;
311 case DM_TEXT: text_count = 0;
312 break;
313 case DM_X12: x12_count = 0;
314 break;
315 case DM_EDIFACT: edf_count = 0;
316 break;
317 case DM_BASE256:
318 b256_count = mode_arg == 249 ? DM_MULT_1 : 0; /* Adjusted to use no. of bytes written */
319 break;
320 }
321
322 for (sp = position; sp < length; sp++) {
323 const unsigned char c = source[sp];
324 const int is_extended = c & 0x80;
325
326 /* ascii ... step (l) */
327 if (z_isdigit(c)) {
328 ascii_count += DM_MULT_1_DIV_2; /* (l)(1) */
329 } else {
330 if (is_extended) {
331 ascii_count = DM_MULT_CEIL(ascii_count) + DM_MULT_2; /* (l)(2) */
332 } else {
333 ascii_count = DM_MULT_CEIL(ascii_count) + DM_MULT_1; /* (l)(3) */
334 }
335 }
336
337 /* c40 ... step (m) */
338 if (dm_isc40(c)) {
339 c40_count += DM_MULT_2_DIV_3; /* (m)(1) */
340 } else {
341 if (is_extended) {
342 c40_count += DM_MULT_8_DIV_3; /* (m)(2) */
343 } else {
344 c40_count += DM_MULT_4_DIV_3; /* (m)(3) */
345 }
346 }
347
348 /* text ... step (n) */
349 if (dm_istext(c)) {
350 text_count += DM_MULT_2_DIV_3; /* (n)(1) */
351 } else {
352 if (is_extended) {
353 text_count += DM_MULT_8_DIV_3; /* (n)(2) */
354 } else {
355 text_count += DM_MULT_4_DIV_3; /* (n)(3) */
356 }
357 }
358
359 /* x12 ... step (o) */
360 if (dm_isX12(c)) {
361 x12_count += DM_MULT_2_DIV_3; /* (o)(1) */
362 } else {
363 if (is_extended) {
364 x12_count += DM_MULT_13_DIV_3; /* (o)(2) */
365 } else {
366 x12_count += DM_MULT_10_DIV_3; /* (o)(3) */
367 }
368 }
369
370 /* edifact ... step (p) */
371 if (dm_isedifact(c)) {
372 edf_count += DM_MULT_3_DIV_4; /* (p)(1) */
373 } else {
374 if (is_extended) {
375 edf_count += DM_MULT_17_DIV_4; /* (p)(2) */
376 } else {
377 edf_count += DM_MULT_13_DIV_4; /* (p)(3) */
378 }
379 }
380
381 /* base 256 ... step (q) */
382 if (gs1 == 1 && c == '\x1D') {
383 /* FNC1 separator */
384 b256_count += DM_MULT_4; /* (q)(1) */
385 } else {
386 b256_count += DM_MULT_1; /* (q)(2) */
387 }
388
389 if (sp >= position + 3) {
390 /* At least 4 data characters processed ... step (r) */
391 /* NOTE: previous behaviour was at least 5 (same as BWIPP) */
392
393 if (debug_print) {
394 printf("\n(m:%d, p:%d, sp:%d, a:%d): ascii_count %d, b256_count %d, edf_count %d, text_count %d"
395 ", x12_count %d, c40_count %d ",
396 current_mode, position, sp, mode_arg, ascii_count, b256_count, edf_count, text_count,
397 x12_count, c40_count);
398 }
399
400 cnt_1 = ascii_count + DM_MULT_1;
401 /* Adjusted from <= b256_count */
402 if (cnt_1 < b256_count && cnt_1 <= edf_count && cnt_1 <= text_count && cnt_1 <= x12_count
403 && cnt_1 <= c40_count) {
404 if (debug_print) fputs("ASC->", stdout);
405 return DM_ASCII; /* step (r)(1) */
406 }
407 cnt_1 = b256_count + DM_MULT_1;
408 if (cnt_1 <= ascii_count || (cnt_1 < edf_count && cnt_1 < text_count && cnt_1 < x12_count
409 && cnt_1 < c40_count)) {
410 if (debug_print) fputs("BAS->", stdout);
411 return DM_BASE256; /* step (r)(2) */
412 }
413 cnt_1 = edf_count + DM_MULT_1;
414 if (cnt_1 < ascii_count && cnt_1 < b256_count && cnt_1 < text_count && cnt_1 < x12_count
415 && cnt_1 < c40_count) {
416 if (debug_print) fputs("EDI->", stdout);
417 return DM_EDIFACT; /* step (r)(3) */
418 }
419 cnt_1 = text_count + DM_MULT_1;
420 if (cnt_1 < ascii_count && cnt_1 < b256_count && cnt_1 < edf_count && cnt_1 < x12_count
421 && cnt_1 < c40_count) {
422 /* Adjusted to avoid early exit from Base 256 if have less than break-even sequence of TEXT chars */
423 if (current_mode == DM_BASE256 && position + 6 < length) {
424 if (dm_text_sp_cnt(source, position, length, sp) >= 12) {
425 if (debug_print) fputs("TEX->", stdout);
426 return DM_TEXT; /* step (r)(4) */
427 }
428 } else {
429 if (debug_print) fputs("TEX->", stdout);
430 return DM_TEXT; /* step (r)(4) */
431 }
432 }
433 cnt_1 = x12_count + DM_MULT_1;
434 if (cnt_1 < ascii_count && cnt_1 < b256_count && cnt_1 < edf_count && cnt_1 < text_count
435 && cnt_1 < c40_count) {
436 if (debug_print) fputs("X12->", stdout);
437 return DM_X12; /* step (r)(5) */
438 }
439 cnt_1 = c40_count + DM_MULT_1;
440 if (cnt_1 < ascii_count && cnt_1 < b256_count && cnt_1 < edf_count && cnt_1 < text_count) {
441 if (c40_count < x12_count) {
442 if (debug_print) fputs("C40->", stdout);
443 return DM_C40; /* step (r)(6)(i) */
444 }
445 if (c40_count == x12_count) {
446 if (dm_substep_r_6_2_1(source, length, sp) == 1) {
447 if (debug_print) fputs("X12->", stdout);
448 return DM_X12; /* step (r)(6)(ii)(I) */
449 }
450 if (debug_print) fputs("C40->", stdout);
451 return DM_C40; /* step (r)(6)(ii)(II) */
452 }
453 }
454 }
455 }
456
457 /* At the end of data ... step (k) */
458 /* step (k)(1) */
459 ascii_rnded = DM_MULT_CEIL(ascii_count);
460 b256_rnded = DM_MULT_CEIL(b256_count);
461 edf_rnded = DM_MULT_CEIL(edf_count);
462 text_rnded = DM_MULT_CEIL(text_count);
463 x12_rnded = DM_MULT_CEIL(x12_count);
464 c40_rnded = DM_MULT_CEIL(c40_count);
465 if (debug_print) {
466 printf("\nEOD(m:%d, p:%d, a:%d): ascii_rnded %d, b256_rnded %d, edf_rnded %d, text_rnded %d"
467 ", x12_rnded %d (%d), c40_rnded %d (%d) ",
468 current_mode, position, mode_arg, ascii_rnded, b256_rnded, edf_rnded, text_rnded,
469 x12_rnded, x12_count, c40_rnded, c40_count);
470 }
471
472 if (ascii_rnded <= b256_rnded && ascii_rnded <= edf_rnded && ascii_rnded <= text_rnded && ascii_rnded <= x12_rnded
473 && ascii_rnded <= c40_rnded) {
474 if (debug_print) fputs("ASC->", stdout);
475 return DM_ASCII; /* step (k)(2) */
476 }
477 if (b256_rnded < ascii_rnded && b256_rnded < edf_rnded && b256_rnded < text_rnded && b256_rnded < x12_rnded
478 && b256_rnded < c40_rnded) {
479 if (debug_print) fputs("BAS->", stdout);
480 return DM_BASE256; /* step (k)(3) */
481 }
482 /* Adjusted from < x12_rnded */
483 if (edf_rnded < ascii_rnded && edf_rnded < b256_rnded && edf_rnded < text_rnded && edf_rnded <= x12_rnded
484 && edf_rnded < c40_rnded) {
485 if (debug_print) fputs("EDI->", stdout);
486 return DM_EDIFACT; /* step (k)(4) */
487 }
488 if (text_rnded < ascii_rnded && text_rnded < b256_rnded && text_rnded < edf_rnded && text_rnded < x12_rnded
489 && text_rnded < c40_rnded) {
490 if (debug_print) fputs("TEX->", stdout);
491 return DM_TEXT; /* step (k)(5) */
492 }
493 /* Adjusted from < edf_rnded */
494 if (x12_rnded < ascii_rnded && x12_rnded < b256_rnded && x12_rnded <= edf_rnded && x12_rnded < text_rnded
495 && x12_rnded < c40_rnded) {
496 if (debug_print) fputs("X12->", stdout);
497 return DM_X12; /* step (k)(6) */
498 }
499 if (debug_print) fputs("C40->", stdout);
500 return DM_C40; /* step (k)(7) */
501 }
502
503 /* Copy C40/TEXT/X12 triplets from buffer to target. Returns elements left in buffer (< 3) */
504 static int dm_ctx_buffer_xfer(int process_buffer[8], int process_p, unsigned char target[], int *p_tp,
505 const int debug_print) {
506 int i, process_e;
507 int tp = *p_tp;
508
509 process_e = (process_p / 3) * 3;
510
511 for (i = 0; i < process_e; i += 3) {
512 int iv = (1600 * process_buffer[i]) + (40 * process_buffer[i + 1]) + (process_buffer[i + 2]) + 1;
513 target[tp++] = (unsigned char) (iv >> 8);
514 target[tp++] = (unsigned char) (iv & 0xFF);
515 if (debug_print) {
516 printf("[%d %d %d (%d %d)] ", process_buffer[i], process_buffer[i + 1], process_buffer[i + 2],
517 target[tp - 2], target[tp - 1]);
518 }
519 }
520
521 process_p -= process_e;
522
523 if (process_p) {
524 memmove(process_buffer, process_buffer + process_e, sizeof(int) * process_p);
525 }
526
527 *p_tp = tp;
528
529 return process_p;
530 }
531
532 /* Copy EDIFACT quadruplets from buffer to target. Returns elements left in buffer (< 4) */
533 static int dm_edi_buffer_xfer(int process_buffer[8], int process_p, unsigned char target[], int *p_tp,
534 const int empty, const int debug_print) {
535 int i, process_e;
536 int tp = *p_tp;
537
538 process_e = (process_p / 4) * 4;
539
540 for (i = 0; i < process_e; i += 4) {
541 target[tp++] = (unsigned char) (process_buffer[i] << 2 | (process_buffer[i + 1] & 0x30) >> 4);
542 target[tp++] = (unsigned char) ((process_buffer[i + 1] & 0x0f) << 4 | (process_buffer[i + 2] & 0x3c) >> 2);
543 target[tp++] = (unsigned char) ((process_buffer[i + 2] & 0x03) << 6 | process_buffer[i + 3]);
544 if (debug_print) {
545 printf("[%d %d %d %d (%d %d %d)] ", process_buffer[i], process_buffer[i + 1], process_buffer[i + 2],
546 process_buffer[i + 3], target[tp - 3], target[tp - 2], target[tp - 1]);
547 }
548 }
549
550 process_p -= process_e;
551
552 if (process_p) {
553 memmove(process_buffer, process_buffer + process_e, sizeof(int) * process_p);
554 if (empty) {
555 if (process_p == 3) {
556 target[tp++] = (unsigned char) (process_buffer[i] << 2 | (process_buffer[i + 1] & 0x30) >> 4);
557 target[tp++] = (unsigned char) ((process_buffer[i + 1] & 0x0f) << 4
558 | (process_buffer[i + 2] & 0x3c) >> 2);
559 target[tp++] = (unsigned char) ((process_buffer[i + 2] & 0x03) << 6);
560 if (debug_print) {
561 printf("[%d %d %d (%d %d %d)] ", process_buffer[i], process_buffer[i + 1], process_buffer[i + 2],
562 target[tp - 3], target[tp - 2], target[tp - 1]);
563 }
564 } else if (process_p == 2) {
565 target[tp++] = (unsigned char) (process_buffer[i] << 2 | (process_buffer[i + 1] & 0x30) >> 4);
566 target[tp++] = (unsigned char) ((process_buffer[i + 1] & 0x0f) << 4);
567 if (debug_print) {
568 printf("[%d %d (%d %d)] ", process_buffer[i], process_buffer[i + 1], target[tp - 2],
569 target[tp - 1]);
570 }
571 } else {
572 target[tp++] = (unsigned char) (process_buffer[i] << 2);
573 if (debug_print) printf("[%d (%d)] ", process_buffer[i], target[tp - 1]);
574 }
575 process_p = 0;
576 }
577 }
578
579 *p_tp = tp;
580
581 return process_p;
582 }
583
584 /* Get index of symbol size in codewords array `dm_matrixbytes`, as specified or
585 else smallest containing `minimum` codewords */
586 static int dm_get_symbolsize(struct zint_symbol *symbol, const int minimum) {
587 int i;
588
589 if ((symbol->option_2 >= 1) && (symbol->option_2 <= DMSIZESCOUNT)) {
590 return dm_intsymbol[symbol->option_2 - 1];
591 }
592 if (minimum > 1304) {
593 return minimum <= 1558 ? DMSIZESCOUNT - 1 : 0;
594 }
595 for (i = minimum >= 62 ? 23 : 0; minimum > dm_matrixbytes[i]; i++);
596
597 if ((symbol->option_3 & 0x7F) == DM_DMRE) {
598 return i;
599 }
600 if ((symbol->option_3 & 0x7F) == DM_SQUARE) {
601 /* Skip rectangular symbols in square only mode */
602 for (; dm_matrixH[i] != dm_matrixW[i]; i++);
603 return i;
604 }
605 /* Skip DMRE symbols in no dmre mode */
606 for (; dm_isDMRE[i]; i++);
607 return i;
608 }
609
610 /* Number of codewords remaining in a particular version (may be negative) */
611 static int dm_codewords_remaining(struct zint_symbol *symbol, const int tp, const int process_p) {
612 int symbolsize = dm_get_symbolsize(symbol, tp + process_p); /* Allow for the remaining data characters */
613
614 return dm_matrixbytes[symbolsize] - tp;
615 }
616
617 /* Number of C40/TEXT elements needed to encode `input` */
618 static int dm_c40text_cnt(const int current_mode, const int gs1, unsigned char input) {
619 int cnt;
620
621 if (gs1 && input == '\x1D') {
622 return 2;
623 }
624 cnt = 1;
625 if (input & 0x80) {
626 cnt += 2;
627 input = input - 128;
628 }
629 if ((current_mode == DM_C40 && dm_c40_shift[input]) || (current_mode == DM_TEXT && dm_text_shift[input])) {
630 cnt += 1;
631 }
632
633 return cnt;
634 }
635
636 /* Update Base 256 field length */
637 static int dm_update_b256_field_length(unsigned char target[], int tp, int b256_start) {
638 int b256_count = tp - (b256_start + 1);
639 if (b256_count <= 249) {
640 target[b256_start] = b256_count;
641 } else {
642 /* Insert extra codeword */
643 memmove(target + b256_start + 2, target + b256_start + 1, b256_count);
644 target[b256_start] = (unsigned char) (249 + (b256_count / 250));
645 target[b256_start + 1] = (unsigned char) (b256_count % 250);
646 tp++;
647 }
648
649 return tp;
650 }
651
652 /* Switch from ASCII or Base 256 to another mode */
653 static int dm_switch_mode(const int next_mode, unsigned char target[], int tp, int *p_b256_start,
654 const int debug_print) {
655 switch (next_mode) {
656 case DM_ASCII:
657 if (debug_print) fputs("ASC ", stdout);
658 break;
659 case DM_C40: target[tp++] = 230;
660 if (debug_print) fputs("C40 ", stdout);
661 break;
662 case DM_TEXT: target[tp++] = 239;
663 if (debug_print) fputs("TEX ", stdout);
664 break;
665 case DM_X12: target[tp++] = 238;
666 if (debug_print) fputs("X12 ", stdout);
667 break;
668 case DM_EDIFACT: target[tp++] = 240;
669 if (debug_print) fputs("EDI ", stdout);
670 break;
671 case DM_BASE256: target[tp++] = 231;
672 *p_b256_start = tp;
673 target[tp++] = 0; /* Byte count holder (may be expanded to 2 codewords) */
674 if (debug_print) fputs("BAS ", stdout);
675 break;
676 }
677
678 return tp;
679 }
680
681 /* Minimal encoding using Dijkstra-based algorithm by Alex Geller
682 Note due to the complicated end-of-data (EOD) conditions that Data Matrix has, this may not be fully minimal;
683 however no counter-examples are known at present */
684
685 #define DM_NUM_MODES 6
686
687 static const char dm_smodes[DM_NUM_MODES + 1][6] = { "?", "ASCII", "C40", "TEXT", "X12", "EDF", "B256" };
688
689 /* The size of this structure could be significantly reduced using techniques pointed out by Alex Geller,
690 but not done currently to avoid the processing overhead */
691 struct dm_edge {
692 unsigned char mode;
693 unsigned char endMode; /* Mode returned by `dm_getEndMode()` */
694 unsigned short from; /* Position in input data, 0-based */
695 unsigned short len;
696 unsigned short size; /* Cumulative number of codewords */
697 unsigned short bytes; /* DM_BASE256 byte count, kept to avoid runtime calc */
698 unsigned short previous; /* Index into edges array */
699 };
700
701 /* Note 1st row of edges not used so valid previous cannot point there, i.e. won't be zero */
702 #define DM_PREVIOUS(edges, edge) \
703 ((edge)->previous ? (edges) + (edge)->previous : NULL)
704
705 /* Determine if next 1 to 4 chars are at EOD and can be encoded as 1 or 2 ASCII codewords */
706 static int dm_last_ascii(const unsigned char source[], const int length, const int from) {
707 if (length - from > 4 || from >= length) {
708 return 0;
709 }
710 if (length - from == 1) {
711 if (source[from] & 0x80) {
712 return 0;
713 }
714 return 1;
715 }
716 if (length - from == 2) {
717 if ((source[from] & 0x80) || (source[from + 1] & 0x80)) {
718 return 0;
719 }
720 if (z_isdigit(source[from]) && z_isdigit(source[from + 1])) {
721 return 1;
722 }
723 return 2;
724 }
725 if (length - from == 3) {
726 if (z_isdigit(source[from]) && z_isdigit(source[from + 1]) && !(source[from + 2] & 0x80)) {
727 return 2;
728 }
729 if (z_isdigit(source[from + 1]) && z_isdigit(source[from + 2]) && !(source[from] & 0x80)) {
730 return 2;
731 }
732 return 0;
733 }
734 if (z_isdigit(source[from]) && z_isdigit(source[from + 1]) && z_isdigit(source[from + 2])
735 && z_isdigit(source[from + 3])) {
736 return 2;
737 }
738 return 0;
739 }
740
741 /* Treat EDIFACT edges specially, returning DM_ASCII mode if not full (i.e. encoding < 4 chars), or if
742 full and at EOD where 1 or 2 ASCII chars can be encoded */
743 static int dm_getEndMode(struct zint_symbol *symbol, const unsigned char *source, const int length, const int mode,
744 const int from, const int len, const int size) {
745 if (mode == DM_EDIFACT) {
746 int last_ascii;
747 if (len < 4) {
748 return DM_ASCII;
749 }
750 last_ascii = dm_last_ascii(source, length, from + len);
751 if (last_ascii) { /* At EOD with remaining chars ASCII-encodable in 1 or 2 codewords */
752 const int symbols_left = dm_codewords_remaining(symbol, size + last_ascii, 0);
753 /* If no codewords left and 1 or 2 ASCII-encodables or 1 codeword left and 1 ASCII-encodable */
754 if (symbols_left <= 2 - last_ascii) {
755 return DM_ASCII;
756 }
757 }
758 }
759 return mode;
760 }
761
762 #if 0
763 #define DM_TRACE
764 #endif
765 #include "dmatrix_trace.h"
766
767 /* Return number of C40/TEXT codewords needed to encode characters in full batches of 3 (or less if EOD).
768 The number of characters encoded is returned in `len` */
769 static int dm_getNumberOfC40Words(const unsigned char *source, const int length, const int from, const int mode,
770 int *len) {
771 int thirdsCount = 0;
772 int i;
773
774 for (i = from; i < length; i++) {
775 const unsigned char ci = source[i];
776 int remainder;
777
778 if (dm_isc40text(mode, ci)) {
779 thirdsCount++; /* Native */
780 } else if (!(ci & 0x80)) {
781 thirdsCount += 2; /* Shift */
782 } else if (dm_isc40text(mode, (unsigned char) (ci & 0x7F))) {
783 thirdsCount += 3; /* Shift, Upper shift */
784 } else {
785 thirdsCount += 4; /* Shift, Upper shift, shift */
786 }
787
788 remainder = thirdsCount % 3;
789 if (remainder == 0 || (remainder == 2 && i + 1 == length)) {
790 *len = i - from + 1;
791 return ((thirdsCount + 2) / 3) * 2;
792 }
793 }
794 *len = 0;
795 return 0;
796 }
797
798 /* Initialize a new edge. Returns endMode */
799 static int dm_new_Edge(struct zint_symbol *symbol, const unsigned char *source, const int length,
800 struct dm_edge *edges, const int mode, const int from, const int len, struct dm_edge *previous,
801 struct dm_edge *edge, const int cwds) {
802 int previousMode;
803 int size;
804 int last_ascii, symbols_left;
805
806 edge->mode = mode;
807 edge->endMode = mode;
808 edge->from = from;
809 edge->len = len;
810 edge->bytes = 0;
811 if (previous) {
812 assert(previous->mode && previous->len && previous->size && previous->endMode);
813 previousMode = previous->endMode;
814 edge->previous = previous - edges;
815 size = previous->size;
816 } else {
817 previousMode = DM_ASCII;
818 edge->previous = 0;
819 size = 0;
820 }
821
822 switch (mode) {
823 case DM_ASCII:
824 assert(previousMode != DM_EDIFACT);
825 size++;
826 if (source[from] & 0x80) {
827 size++;
828 }
829 if (previousMode != DM_ASCII && previousMode != DM_BASE256) {
830 size++; /* Unlatch to ASCII */
831 }
832 break;
833
834 case DM_BASE256:
835 assert(previousMode != DM_EDIFACT);
836 size++;
837 if (previousMode != DM_BASE256) {
838 size += 2; /* Byte count + latch to BASE256 */
839 if (previousMode != DM_ASCII) {
840 size++; /* Unlatch to ASCII */
841 }
842 edge->bytes = 1;
843 } else {
844 assert(previous);
845 edge->bytes = 1 + previous->bytes;
846 if (edge->bytes == 250) {
847 size++; /* Extra byte count */
848 }
849 }
850 break;
851
852 case DM_C40:
853 case DM_TEXT:
854 assert(previousMode != DM_EDIFACT);
855 size += cwds;
856 if (previousMode != mode) {
857 size++; /* Latch to this mode */
858 if (previousMode != DM_ASCII && previousMode != DM_BASE256) {
859 size++; /* Unlatch to ASCII */
860 }
861 }
862 if (from + len + 2 >= length) { /* If less than batch of 3 away from EOD */
863 last_ascii = dm_last_ascii(source, length, from + len);
864 symbols_left = dm_codewords_remaining(symbol, size + last_ascii, 0);
865 if (symbols_left > 0) {
866 size++; /* We need an extra unlatch at the end */
867 }
868 }
869 break;
870
871 case DM_X12:
872 assert(previousMode != DM_EDIFACT);
873 size += 2;
874 if (previousMode != DM_X12) {
875 size++; /* Latch to this mode */
876 if (previousMode != DM_ASCII && previousMode != DM_BASE256) {
877 size++; /* Unlatch to ASCII */
878 }
879 }
880 if (from + len + 2 >= length) { /* If less than batch of 3 away from EOD */
881 last_ascii = dm_last_ascii(source, length, from + len);
882 if (last_ascii == 2) { /* Only 1 ASCII-encodable allowed at EOD for X12, unlike C40/TEXT */
883 size++; /* We need an extra unlatch at the end */
884 } else {
885 symbols_left = dm_codewords_remaining(symbol, size + last_ascii, 0);
886 if (symbols_left > 0) {
887 size++; /* We need an extra unlatch at the end */
888 }
889 }
890 }
891 break;
892
893 case DM_EDIFACT:
894 size += 3;
895 if (previousMode != DM_EDIFACT) {
896 size++; /* Latch to this mode */
897 if (previousMode != DM_ASCII && previousMode != DM_BASE256) {
898 size++; /* Unlatch to ASCII */
899 }
900 }
901 edge->endMode = dm_getEndMode(symbol, source, length, mode, from, len, size);
902 break;
903 }
904 edge->size = size;
905
906 return edge->endMode;
907 }
908
909 /* Add an edge for a mode at a vertex if no existing edge or if more optimal than existing edge */
910 static void dm_addEdge(struct zint_symbol *symbol, const unsigned char *source, const int length,
911 struct dm_edge *edges, const int mode, const int from, const int len, struct dm_edge *previous,
912 const int cwds) {
913 struct dm_edge edge;
914 const int endMode = dm_new_Edge(symbol, source, length, edges, mode, from, len, previous, &edge, cwds);
915 const int vertexIndex = from + len;
916 const int v_ij = vertexIndex * DM_NUM_MODES + endMode - 1;
917
918 if (edges[v_ij].mode == 0 || edges[v_ij].size > edge.size) {
919 DM_TRACE_AddEdge(source, length, edges, previous, vertexIndex, &edge);
920 edges[v_ij] = edge;
921 } else {
922 DM_TRACE_NotAddEdge(source, length, edges, previous, vertexIndex, v_ij, &edge);
923 }
924 }
925
926 /* Add edges for the various modes at a vertex */
927 static void dm_addEdges(struct zint_symbol *symbol, const unsigned char source[], const int length,
928 struct dm_edge *edges, const int from, struct dm_edge *previous, const int gs1) {
929 int i, pos;
930
931 /* Not possible to unlatch a full EDF edge to something else */
932 if (previous == NULL || previous->endMode != DM_EDIFACT) {
933
934 static const char c40text_modes[] = { DM_C40, DM_TEXT };
935
936 if (z_isdigit(source[from]) && from + 1 < length && z_isdigit(source[from + 1])) {
937 dm_addEdge(symbol, source, length, edges, DM_ASCII, from, 2, previous, 0);
938 /* If ASCII vertex, don't bother adding other edges as this will be optimal; suggested by Alex Geller */
939 if (previous && previous->mode == DM_ASCII) {
940 return;
941 }
942 } else {
943 dm_addEdge(symbol, source, length, edges, DM_ASCII, from, 1, previous, 0);
944 }
945
946 for (i = 0; i < ARRAY_SIZE(c40text_modes); i++) {
947 int len;
948 int cwds = dm_getNumberOfC40Words(source, length, from, c40text_modes[i], &len);
949 if (cwds) {
950 dm_addEdge(symbol, source, length, edges, c40text_modes[i], from, len, previous, cwds);
951 }
952 }
953
954 if (from + 2 < length && dm_isX12(source[from]) && dm_isX12(source[from + 1]) && dm_isX12(source[from + 2])) {
955 dm_addEdge(symbol, source, length, edges, DM_X12, from, 3, previous, 0);
956 }
957
958 if (gs1 != 1 || source[from] != '\x1D') {
959 dm_addEdge(symbol, source, length, edges, DM_BASE256, from, 1, previous, 0);
960 }
961 }
962
963 if (dm_isedifact(source[from])) {
964 /* We create 3 EDF edges, 2, 3 or 4 characters length. The 4-char normally doesn't have a latch to ASCII
965 unless it is 2 characters away from the end of the input. */
966 for (i = 1, pos = from + i; i < 4 && pos < length && dm_isedifact(source[pos]); i++, pos++) {
967 dm_addEdge(symbol, source, length, edges, DM_EDIFACT, from, i + 1, previous, 0);
968 }
969 }
970 }
971
972 /* Calculate optimized encoding modes */
973 static int dm_define_mode(struct zint_symbol *symbol, char modes[], const unsigned char source[], const int length,
974 const int gs1, const int debug_print) {
975
976 int i, j, v_i;
977 int minimalJ, minimalSize;
978 struct dm_edge *edge;
979 int current_mode;
980 int mode_end, mode_len;
981
982 struct dm_edge *edges = (struct dm_edge *) calloc((length + 1) * DM_NUM_MODES, sizeof(struct dm_edge));
983 if (!edges) {
984 return 0;
985 }
986 dm_addEdges(symbol, source, length, edges, 0, NULL, gs1);
987
988 DM_TRACE_Edges("DEBUG Initial situation\n", source, length, edges, 0);
989
990 for (i = 1; i < length; i++) {
991 v_i = i * DM_NUM_MODES;
992 for (j = 0; j < DM_NUM_MODES; j++) {
993 if (edges[v_i + j].mode) {
994 dm_addEdges(symbol, source, length, edges, i, edges + v_i + j, gs1);
995 }
996 }
997 DM_TRACE_Edges("DEBUG situation after adding edges to vertices at position %d\n", source, length, edges, i);
998 }
999
1000 DM_TRACE_Edges("DEBUG Final situation\n", source, length, edges, length);
1001
1002 v_i = length * DM_NUM_MODES;
1003 minimalJ = -1;
1004 minimalSize = INT_MAX;
1005 for (j = 0; j < DM_NUM_MODES; j++) {
1006 edge = edges + v_i + j;
1007 if (edge->mode) {
1008 if (debug_print) printf("edges[%d][%d][0] size %d\n", length, j, edge->size);
1009 if (edge->size < minimalSize) {
1010 minimalSize = edge->size;
1011 minimalJ = j;
1012 if (debug_print) printf(" set minimalJ %d\n", minimalJ);
1013 }
1014 } else {
1015 if (debug_print) printf("edges[%d][%d][0] NULL\n", length, j);
1016 }
1017 }
1018 assert(minimalJ >= 0);
1019
1020 edge = edges + v_i + minimalJ;
1021 mode_len = 0;
1022 mode_end = length;
1023 while (edge) {
1024 current_mode = edge->mode;
1025 mode_len += edge->len;
1026 edge = DM_PREVIOUS(edges, edge);
1027 if (!edge || edge->mode != current_mode) {
1028 for (i = mode_end - mode_len; i < mode_end; i++) {
1029 modes[i] = current_mode;
1030 }
1031 mode_end = mode_end - mode_len;
1032 mode_len = 0;
1033 }
1034 }
1035
1036 if (debug_print) {
1037 printf("modes (%d): ", length);
1038 for (i = 0; i < length; i++) printf("%c", dm_smodes[(int) modes[i]][0]);
1039 fputc('\n', stdout);
1040 }
1041 assert(mode_end == 0);
1042
1043 free(edges);
1044
1045 return 1;
1046 }
1047
1048 /* Do default minimal encodation */
1049 static int dm_minimalenc(struct zint_symbol *symbol, const unsigned char source[], const int length, int *p_sp,
1050 unsigned char target[], int *p_tp, int process_buffer[8], int *p_process_p, int *p_b256_start,
1051 int *p_current_mode, const int gs1, const int debug_print) {
1052 int sp = *p_sp;
1053 int tp = *p_tp;
1054 int process_p = *p_process_p;
1055 int current_mode = *p_current_mode;
1056 int last_ascii, symbols_left;
1057 int i;
1058 char *modes = (char *) z_alloca(length);
1059
1060 assert(length <= 10921); /* Can only handle (10921 + 1) * 6 = 65532 < 65536 (2*16) due to sizeof(previous) */
1061
1062 if (!dm_define_mode(symbol, modes, source, length, gs1, debug_print)) {
1063 return errtxt(ZINT_ERROR_MEMORY, symbol, 728, "Insufficient memory for mode buffers");
1064 }
1065
1066 while (sp < length) {
1067
1068 if (modes[sp] != current_mode) {
1069 switch (current_mode) {
1070 case DM_C40:
1071 case DM_TEXT:
1072 case DM_X12:
1073 process_p = 0; /* Throw away buffer if any */
1074 target[tp++] = 254; /* Unlatch */
1075 break;
1076 case DM_EDIFACT:
1077 last_ascii = dm_last_ascii(source, length, sp);
1078 if (!last_ascii) {
1079 process_buffer[process_p++] = 31; /* Unlatch */
1080 } else {
1081 symbols_left = dm_codewords_remaining(symbol, tp + last_ascii, process_p);
1082 if (debug_print) {
1083 printf("process_p %d, last_ascii %d, symbols_left %d\n",
1084 process_p, last_ascii, symbols_left);
1085 }
1086 if (symbols_left > 2 - last_ascii) {
1087 process_buffer[process_p++] = 31; /* Unlatch */
1088 }
1089 }
1090 process_p = dm_edi_buffer_xfer(process_buffer, process_p, target, &tp, 1 /*empty*/, debug_print);
1091 break;
1092 case DM_BASE256:
1093 tp = dm_update_b256_field_length(target, tp, *p_b256_start);
1094 /* B.2.1 255-state randomising algorithm */
1095 for (i = *p_b256_start; i < tp; i++) {
1096 const int prn = ((149 * (i + 1)) % 255) + 1;
1097 target[i] = (unsigned char) ((target[i] + prn) & 0xFF);
1098 }
1099 break;
1100 }
1101 tp = dm_switch_mode(modes[sp], target, tp, p_b256_start, debug_print);
1102 }
1103
1104 current_mode = modes[sp];
1105 assert(current_mode);
1106
1107 if (current_mode == DM_ASCII) {
1108
1109 if (is_twodigits(source, length, sp)) {
1110 target[tp++] = (unsigned char) ((10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130);
1111 if (debug_print) printf("N%02d ", target[tp - 1] - 130);
1112 sp += 2;
1113 } else {
1114 if (source[sp] & 0x80) {
1115 target[tp++] = 235; /* FNC4 */
1116 target[tp++] = (source[sp] - 128) + 1;
1117 if (debug_print) printf("FN4 A%02X ", target[tp - 1] - 1);
1118 } else {
1119 if (gs1 && source[sp] == '\x1D') {
1120 if (gs1 == 2) {
1121 target[tp++] = 29 + 1; /* GS */
1122 if (debug_print) fputs("GS ", stdout);
1123 } else {
1124 target[tp++] = 232; /* FNC1 */
1125 if (debug_print) fputs("FN1 ", stdout);
1126 }
1127 } else {
1128 target[tp++] = source[sp] + 1;
1129 if (debug_print) printf("A%02X ", target[tp - 1] - 1);
1130 }
1131 }
1132 sp++;
1133 }
1134
1135 } else if (current_mode == DM_C40 || current_mode == DM_TEXT) {
1136
1137 int shift_set, value;
1138 const char *ct_shift, *ct_value;
1139
1140 if (current_mode == DM_C40) {
1141 ct_shift = dm_c40_shift;
1142 ct_value = dm_c40_value;
1143 } else {
1144 ct_shift = dm_text_shift;
1145 ct_value = dm_text_value;
1146 }
1147
1148 if (source[sp] & 0x80) {
1149 process_buffer[process_p++] = 1;
1150 process_buffer[process_p++] = 30; /* Upper Shift */
1151 shift_set = ct_shift[source[sp] - 128];
1152 value = ct_value[source[sp] - 128];
1153 } else {
1154 if (gs1 && source[sp] == '\x1D') {
1155 if (gs1 == 2) {
1156 shift_set = ct_shift[29];
1157 value = ct_value[29]; /* GS */
1158 } else {
1159 shift_set = 2;
1160 value = 27; /* FNC1 */
1161 }
1162 } else {
1163 shift_set = ct_shift[source[sp]];
1164 value = ct_value[source[sp]];
1165 }
1166 }
1167
1168 if (shift_set != 0) {
1169 process_buffer[process_p++] = shift_set - 1;
1170 }
1171 process_buffer[process_p++] = value;
1172
1173 if (process_p >= 3) {
1174 process_p = dm_ctx_buffer_xfer(process_buffer, process_p, target, &tp, debug_print);
1175 }
1176 sp++;
1177
1178 } else if (current_mode == DM_X12) {
1179
1180 static const char x12_nonalphanum_chars[] = "\015*> ";
1181 int value = 0;
1182
1183 if (z_isdigit(source[sp])) {
1184 value = (source[sp] - '0') + 4;
1185 } else if (z_isupper(source[sp])) {
1186 value = (source[sp] - 'A') + 14;
1187 } else {
1188 value = posn(x12_nonalphanum_chars, source[sp]);
1189 }
1190
1191 process_buffer[process_p++] = value;
1192
1193 if (process_p >= 3) {
1194 process_p = dm_ctx_buffer_xfer(process_buffer, process_p, target, &tp, debug_print);
1195 }
1196 sp++;
1197
1198 } else if (current_mode == DM_EDIFACT) {
1199
1200 int value = source[sp];
1201
1202 if (value >= 64) { /* '@' */
1203 value -= 64;
1204 }
1205
1206 process_buffer[process_p++] = value;
1207 sp++;
1208
1209 if (process_p >= 4) {
1210 process_p = dm_edi_buffer_xfer(process_buffer, process_p, target, &tp, 0 /*empty*/, debug_print);
1211 }
1212
1213 } else if (current_mode == DM_BASE256) {
1214
1215 target[tp++] = source[sp++];
1216 if (debug_print) printf("B%02X ", target[tp - 1]);
1217 }
1218
1219 if (tp > 1558) {
1220 return errtxt(ZINT_ERROR_TOO_LONG, symbol, 729,
1221 "Input too long, requires too many codewords (maximum 1558)");
1222 }
1223
1224 } /* while */
1225
1226 *p_sp = sp;
1227 *p_tp = tp;
1228 *p_process_p = process_p;
1229 *p_current_mode = current_mode;
1230
1231 return 0;
1232 }
1233
1234 /* Encode using algorithm based on ISO/IEC 21471:2020 Annex J (was ISO/IEC 21471:2006 Annex P) */
1235 static int dm_isoenc(struct zint_symbol *symbol, const unsigned char source[], const int length, int *p_sp,
1236 unsigned char target[], int *p_tp, int process_buffer[8], int *p_process_p, int *p_b256_start,
1237 int *p_current_mode, const int gs1, const int debug_print) {
1238 const int mailmark = symbol->symbology == BARCODE_MAILMARK_2D;
1239 int sp = *p_sp;
1240 int tp = *p_tp;
1241 int process_p = *p_process_p;
1242 int current_mode = *p_current_mode;
1243 int not_first = 0;
1244 int i;
1245
1246 /* step (a) */
1247 int next_mode = DM_ASCII;
1248
1249 if (mailmark) { /* First 45 characters C40 */
1250 assert(length >= 45);
1251 next_mode = DM_C40;
1252 tp = dm_switch_mode(next_mode, target, tp, p_b256_start, debug_print);
1253 while (sp < 45) {
1254 assert(!(sp & 0x80));
1255 process_buffer[process_p++] = dm_c40_value[source[sp]];
1256
1257 if (process_p >= 3) {
1258 process_p = dm_ctx_buffer_xfer(process_buffer, process_p, target, &tp, debug_print);
1259 }
1260 sp++;
1261 }
1262 current_mode = next_mode;
1263 not_first = 1;
1264 }
1265
1266 while (sp < length) {
1267
1268 current_mode = next_mode;
1269
1270 /* step (b) - ASCII encodation */
1271 if (current_mode == DM_ASCII) {
1272 next_mode = DM_ASCII;
1273
1274 if (is_twodigits(source, length, sp)) {
1275 target[tp++] = (unsigned char) ((10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130);
1276 if (debug_print) printf("N%02d ", target[tp - 1] - 130);
1277 sp += 2;
1278 } else {
1279 next_mode = dm_look_ahead_test(source, length, sp, current_mode, 0, gs1, debug_print);
1280
1281 if (next_mode != DM_ASCII) {
1282 tp = dm_switch_mode(next_mode, target, tp, p_b256_start, debug_print);
1283 not_first = 0;
1284 } else {
1285 if (source[sp] & 0x80) {
1286 target[tp++] = 235; /* FNC4 */
1287 target[tp++] = (source[sp] - 128) + 1;
1288 if (debug_print) printf("FN4 A%02X ", target[tp - 1] - 1);
1289 } else {
1290 if (gs1 && source[sp] == '\x1D') {
1291 if (gs1 == 2) {
1292 target[tp++] = 29 + 1; /* GS */
1293 if (debug_print) fputs("GS ", stdout);
1294 } else {
1295 target[tp++] = 232; /* FNC1 */
1296 if (debug_print) fputs("FN1 ", stdout);
1297 }
1298 } else {
1299 target[tp++] = source[sp] + 1;
1300 if (debug_print) printf("A%02X ", target[tp - 1] - 1);
1301 }
1302 }
1303 sp++;
1304 }
1305 }
1306
1307 /* step (c)/(d) C40/TEXT encodation */
1308 } else if (current_mode == DM_C40 || current_mode == DM_TEXT) {
1309
1310 next_mode = current_mode;
1311 if (process_p == 0 && not_first) {
1312 next_mode = dm_look_ahead_test(source, length, sp, current_mode, process_p, gs1, debug_print);
1313 }
1314
1315 if (next_mode != current_mode) {
1316 target[tp++] = 254; /* Unlatch */
1317 next_mode = DM_ASCII;
1318 if (debug_print) fputs("ASC ", stdout);
1319 } else {
1320 int shift_set, value;
1321 const char *ct_shift, *ct_value;
1322
1323 if (current_mode == DM_C40) {
1324 ct_shift = dm_c40_shift;
1325 ct_value = dm_c40_value;
1326 } else {
1327 ct_shift = dm_text_shift;
1328 ct_value = dm_text_value;
1329 }
1330
1331 if (source[sp] & 0x80) {
1332 process_buffer[process_p++] = 1;
1333 process_buffer[process_p++] = 30; /* Upper Shift */
1334 shift_set = ct_shift[source[sp] - 128];
1335 value = ct_value[source[sp] - 128];
1336 } else {
1337 if (gs1 && source[sp] == '\x1D') {
1338 if (gs1 == 2) {
1339 shift_set = ct_shift[29];
1340 value = ct_value[29]; /* GS */
1341 } else {
1342 shift_set = 2;
1343 value = 27; /* FNC1 */
1344 }
1345 } else {
1346 shift_set = ct_shift[source[sp]];
1347 value = ct_value[source[sp]];
1348 }
1349 }
1350
1351 if (shift_set != 0) {
1352 process_buffer[process_p++] = shift_set - 1;
1353 }
1354 process_buffer[process_p++] = value;
1355
1356 if (process_p >= 3) {
1357 process_p = dm_ctx_buffer_xfer(process_buffer, process_p, target, &tp, debug_print);
1358 }
1359 sp++;
1360 not_first = 1;
1361 }
1362
1363 /* step (e) X12 encodation */
1364 } else if (current_mode == DM_X12) {
1365
1366 if (!dm_isX12(source[sp])) {
1367 next_mode = DM_ASCII;
1368 } else {
1369 next_mode = DM_X12;
1370 if (process_p == 0 && not_first) {
1371 next_mode = dm_look_ahead_test(source, length, sp, current_mode, process_p, gs1, debug_print);
1372 }
1373 }
1374
1375 if (next_mode != DM_X12) {
1376 sp -= process_p; /* About to throw away buffer, need to re-process input, cf Okapi commit [fb7981e] */
1377 process_p = 0; /* Throw away buffer if any */
1378 target[tp++] = 254; /* Unlatch */
1379 next_mode = DM_ASCII;
1380 if (debug_print) fputs("ASC ", stdout);
1381 } else {
1382 static const char x12_nonalphanum_chars[] = "\015*> ";
1383 int value = 0;
1384
1385 if (z_isdigit(source[sp])) {
1386 value = (source[sp] - '0') + 4;
1387 } else if (z_isupper(source[sp])) {
1388 value = (source[sp] - 'A') + 14;
1389 } else {
1390 value = posn(x12_nonalphanum_chars, source[sp]);
1391 }
1392
1393 process_buffer[process_p++] = value;
1394
1395 if (process_p >= 3) {
1396 process_p = dm_ctx_buffer_xfer(process_buffer, process_p, target, &tp, debug_print);
1397 }
1398 sp++;
1399 not_first = 1;
1400 }
1401
1402 /* step (f) EDIFACT encodation */
1403 } else if (current_mode == DM_EDIFACT) {
1404
1405 if (!dm_isedifact(source[sp])) {
1406 next_mode = DM_ASCII;
1407 } else {
1408 next_mode = DM_EDIFACT;
1409 if (process_p == 3) {
1410 /* Note different than spec Step (f)(2), which suggests checking when 0, but this seems to
1411 work better in many cases as the switch to ASCII is "free" */
1412 next_mode = dm_look_ahead_test(source, length, sp, current_mode, process_p, gs1, debug_print);
1413 }
1414 }
1415
1416 if (next_mode != DM_EDIFACT) {
1417 process_buffer[process_p++] = 31;
1418 process_p = dm_edi_buffer_xfer(process_buffer, process_p, target, &tp, 1 /*empty*/, debug_print);
1419 next_mode = DM_ASCII;
1420 if (debug_print) fputs("ASC ", stdout);
1421 } else {
1422 int value = source[sp];
1423
1424 if (value >= 64) { /* '@' */
1425 value -= 64;
1426 }
1427
1428 process_buffer[process_p++] = value;
1429 sp++;
1430 not_first = 1;
1431
1432 if (process_p >= 4) {
1433 process_p = dm_edi_buffer_xfer(process_buffer, process_p, target, &tp, 0 /*empty*/,
1434 debug_print);
1435 }
1436 }
1437
1438 /* step (g) Base 256 encodation */
1439 } else if (current_mode == DM_BASE256) {
1440
1441 if (gs1 == 1 && source[sp] == '\x1D') {
1442 next_mode = DM_ASCII;
1443 } else {
1444 next_mode = DM_BASE256;
1445 if (not_first) {
1446 next_mode = dm_look_ahead_test(source, length, sp, current_mode, tp - (*p_b256_start + 1), gs1,
1447 debug_print);
1448 }
1449 }
1450
1451 if (next_mode != DM_BASE256) {
1452 tp = dm_update_b256_field_length(target, tp, *p_b256_start);
1453 /* B.2.1 255-state randomising algorithm */
1454 for (i = *p_b256_start; i < tp; i++) {
1455 const int prn = ((149 * (i + 1)) % 255) + 1;
1456 target[i] = (unsigned char) ((target[i] + prn) & 0xFF);
1457 }
1458 /* We switch directly here to avoid flipping back to Base 256 due to `dm_text_sp_cnt()` */
1459 tp = dm_switch_mode(next_mode, target, tp, p_b256_start, debug_print);
1460 not_first = 0;
1461 } else {
1462 if (gs1 == 2 && source[sp] == '\x1D') {
1463 target[tp++] = 29; /* GS */
1464 } else {
1465 target[tp++] = source[sp];
1466 }
1467 sp++;
1468 not_first = 1;
1469 if (debug_print) printf("B%02X ", target[tp - 1]);
1470 }
1471 }
1472
1473 if (tp > 1558) {
1474 return errtxt(ZINT_ERROR_TOO_LONG, symbol, 520,
1475 "Input too long, requires too many codewords (maximum 1558)");
1476 }
1477
1478 } /* while */
1479
1480 *p_sp = sp;
1481 *p_tp = tp;
1482 *p_process_p = process_p;
1483 *p_current_mode = current_mode;
1484
1485 return 0;
1486 }
1487
1488 /* Encodes data using ASCII, C40, Text, X12, EDIFACT or Base 256 modes as appropriate
1489 Supports encoding FNC1 in supporting systems */
1490 static int dm_encode(struct zint_symbol *symbol, const unsigned char source[], const int length, const int eci,
1491 const int gs1, unsigned char target[], int *p_tp) {
1492 int sp = 0;
1493 int tp = *p_tp;
1494 int current_mode = DM_ASCII;
1495 int i;
1496 int process_buffer[8]; /* holds remaining data to finalised */
1497 int process_p = 0; /* number of characters left to finalise */
1498 int b256_start = 0;
1499 int symbols_left;
1500 int error_number;
1501 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
1502
1503 if (eci > 0) {
1504 /* Encode ECI numbers according to Table 6 */
1505 target[tp++] = 241; /* ECI Character */
1506 if (eci <= 126) {
1507 target[tp++] = (unsigned char) (eci + 1);
1508 } else if (eci <= 16382) {
1509 target[tp++] = (unsigned char) ((eci - 127) / 254 + 128);
1510 target[tp++] = (unsigned char) ((eci - 127) % 254 + 1);
1511 } else {
1512 target[tp++] = (unsigned char) ((eci - 16383) / 64516 + 192);
1513 target[tp++] = (unsigned char) (((eci - 16383) / 254) % 254 + 1);
1514 target[tp++] = (unsigned char) ((eci - 16383) % 254 + 1);
1515 }
1516 if (debug_print) printf("ECI %d ", eci + 1);
1517 }
1518
1519 /* If FAST_MODE or MAILMARK_2D, do Annex J-based encodation */
1520 if ((symbol->input_mode & FAST_MODE) || symbol->symbology == BARCODE_MAILMARK_2D) {
1521 error_number = dm_isoenc(symbol, source, length, &sp, target, &tp, process_buffer, &process_p,
1522 &b256_start, &current_mode, gs1, debug_print);
1523 } else { /* Do default minimal encodation */
1524 error_number = dm_minimalenc(symbol, source, length, &sp, target, &tp, process_buffer, &process_p,
1525 &b256_start, &current_mode, gs1, debug_print);
1526 }
1527 if (error_number != 0) {
1528 return error_number;
1529 }
1530
1531 symbols_left = dm_codewords_remaining(symbol, tp, process_p);
1532
1533 if (debug_print) printf("\nsymbols_left %d, tp %d, process_p %d ", symbols_left, tp, process_p);
1534
1535 if (current_mode == DM_C40 || current_mode == DM_TEXT) {
1536 /* NOTE: changed to follow spec exactly here, only using Shift 1 padded triplets when 2 symbol chars remain.
1537 This matches the behaviour of BWIPP but not tec-it, nor figures 4.15.1-1 and 4.15-1-2 in GS1 General
1538 Specifications 21.0.1.
1539 */
1540 if (debug_print) printf("%s ", current_mode == DM_C40 ? "C40" : "TEX");
1541 if (process_p == 0) {
1542 if (symbols_left > 0) {
1543 target[tp++] = 254; /* Unlatch */
1544 if (debug_print) fputs("ASC ", stdout);
1545 }
1546 } else {
1547 if (process_p == 2 && symbols_left == 2) {
1548 /* 5.2.5.2 (b) */
1549 process_buffer[process_p++] = 0; /* Shift 1 */
1550 (void) dm_ctx_buffer_xfer(process_buffer, process_p, target, &tp, debug_print);
1551
1552 } else if (process_p == 1 && symbols_left <= 2 && dm_isc40text(current_mode, source[length - 1])) {
1553 /* 5.2.5.2 (c)/(d) */
1554 if (symbols_left > 1) {
1555 /* 5.2.5.2 (c) */
1556 target[tp++] = 254; /* Unlatch and encode remaining data in ascii. */
1557 if (debug_print) fputs("ASC ", stdout);
1558 }
1559 target[tp++] = source[length - 1] + 1;
1560 if (debug_print) printf("A%02X ", target[tp - 1] - 1);
1561
1562 } else {
1563 int cnt, total_cnt = 0;
1564 /* Backtrack to last complete triplet (same technique as BWIPP) */
1565 while (sp > 0 && process_p % 3) {
1566 sp--;
1567 cnt = dm_c40text_cnt(current_mode, gs1, source[sp]);
1568 total_cnt += cnt;
1569 process_p -= cnt;
1570 }
1571 if (debug_print) printf("Mode %d, backtracked %d\n", current_mode, (total_cnt / 3) * 2);
1572 tp -= (total_cnt / 3) * 2;
1573
1574 target[tp++] = 254; /* Unlatch */
1575 if (debug_print) fputs("ASC ", stdout);
1576 for (; sp < length; sp++) {
1577 if (is_twodigits(source, length, sp)) {
1578 target[tp++] = (unsigned char) ((10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130);
1579 if (debug_print) printf("N%02d ", target[tp - 1] - 130);
1580 sp++;
1581 } else if (source[sp] & 0x80) {
1582 target[tp++] = 235; /* FNC4 */
1583 target[tp++] = (source[sp] - 128) + 1;
1584 if (debug_print) printf("FN4 A%02X ", target[tp - 1] - 1);
1585 } else if (gs1 && source[sp] == '\x1D') {
1586 if (gs1 == 2) {
1587 target[tp++] = 29 + 1; /* GS */
1588 if (debug_print) fputs("GS ", stdout);
1589 } else {
1590 target[tp++] = 232; /* FNC1 */
1591 if (debug_print) fputs("FN1 ", stdout);
1592 }
1593 } else {
1594 target[tp++] = source[sp] + 1;
1595 if (debug_print) printf("A%02X ", target[tp - 1] - 1);
1596 }
1597 }
1598 }
1599 }
1600
1601 } else if (current_mode == DM_X12) {
1602 if (debug_print) fputs("X12 ", stdout);
1603 if ((symbols_left == 1) && (process_p == 1)) {
1604 /* Unlatch not required! */
1605 target[tp++] = source[length - 1] + 1;
1606 if (debug_print) printf("A%02X ", target[tp - 1] - 1);
1607 } else {
1608 if (symbols_left > 0) {
1609 target[tp++] = (254); /* Unlatch. */
1610 if (debug_print) fputs("ASC ", stdout);
1611 }
1612
1613 if (process_p == 1) {
1614 target[tp++] = source[length - 1] + 1;
1615 if (debug_print) printf("A%02X ", target[tp - 1] - 1);
1616 } else if (process_p == 2) {
1617 target[tp++] = source[length - 2] + 1;
1618 target[tp++] = source[length - 1] + 1;
1619 if (debug_print) printf("A%02X A%02X ", target[tp - 2] - 1, target[tp - 1] - 1);
1620 }
1621 }
1622
1623 } else if (current_mode == DM_EDIFACT) {
1624 if (debug_print) fputs("EDI ", stdout);
1625 if (symbols_left <= 2 && process_p <= symbols_left) { /* Unlatch not required! */
1626 if (process_p == 1) {
1627 target[tp++] = source[length - 1] + 1;
1628 if (debug_print) printf("A%02X ", target[tp - 1] - 1);
1629 } else if (process_p == 2) {
1630 target[tp++] = source[length - 2] + 1;
1631 target[tp++] = source[length - 1] + 1;
1632 if (debug_print) printf("A%02X A%02X ", target[tp - 2] - 1, target[tp - 1] - 1);
1633 }
1634 } else {
1635 /* Append edifact unlatch value (31) and empty buffer */
1636 if (process_p <= 3) {
1637 process_buffer[process_p++] = 31;
1638 }
1639 (void) dm_edi_buffer_xfer(process_buffer, process_p, target, &tp, 1 /*empty*/, debug_print);
1640 }
1641
1642 } else if (current_mode == DM_BASE256) {
1643 if (symbols_left > 0) {
1644 tp = dm_update_b256_field_length(target, tp, b256_start);
1645 }
1646 /* B.2.1 255-state randomising algorithm */
1647 for (i = b256_start; i < tp; i++) {
1648 int prn = ((149 * (i + 1)) % 255) + 1;
1649 target[i] = (unsigned char) ((target[i] + prn) & 0xFF);
1650 }
1651 }
1652
1653 if (debug_print) {
1654 printf("\nData (%d):", tp);
1655 for (i = 0; i < tp; i++)
1656 printf(" %d", target[i]);
1657
1658 fputc('\n', stdout);
1659 }
1660
1661 *p_tp = tp;
1662
1663 return 0;
1664 }
1665
1666 #ifdef ZINT_TEST /* Wrapper for direct testing */
1667 INTERNAL int dm_encode_test(struct zint_symbol *symbol, const unsigned char source[], const int length, const int eci,
1668 const int gs1, unsigned char target[], int *p_tp) {
1669 return dm_encode(symbol, source, length, eci, gs1, target, p_tp);
1670 }
1671 #endif
1672
1673 /* Call `dm_encode()` for each segment, dealing with Structured Append, GS1, READER_INIT and macro headers
1674 beforehand */
1675 static int dm_encode_segs(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count,
1676 unsigned char target[], int *p_binlen) {
1677 int error_number;
1678 int i;
1679 int tp = 0;
1680 int gs1;
1681 int in_macro = 0;
1682 const struct zint_seg *last_seg = &segs[seg_count - 1];
1683 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
1684
1685 if ((i = segs_length(segs, seg_count)) > 3116) { /* Max is 3166 digits */
1686 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 719, "Input length %d too long (maximum 3116)", i);
1687 }
1688
1689 if (symbol->structapp.count) {
1690 int id1, id2;
1691
1692 if (symbol->structapp.count < 2 || symbol->structapp.count > 16) {
1693 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 720,
1694 "Structured Append count '%d' out of range (2 to 16)", symbol->structapp.count);
1695 }
1696 if (symbol->structapp.index < 1 || symbol->structapp.index > symbol->structapp.count) {
1697 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 721,
1698 "Structured Append index '%1$d' out of range (1 to count %2$d)",
1699 symbol->structapp.index, symbol->structapp.count);
1700 }
1701 if (symbol->structapp.id[0]) {
1702 int id, id_len, id1_err, id2_err;
1703
1704 for (id_len = 1; id_len < 7 && symbol->structapp.id[id_len]; id_len++);
1705
1706 if (id_len > 6) { /* ID1 * 1000 + ID2 */
1707 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 722,
1708 "Structured Append ID length %d too long (6 digit maximum)", id_len);
1709 }
1710
1711 id = to_int((const unsigned char *) symbol->structapp.id, id_len);
1712 if (id == -1) {
1713 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 723, "Invalid Structured Append ID (digits only)");
1714 }
1715 id1 = id / 1000;
1716 id2 = id % 1000;
1717 id1_err = id1 < 1 || id1 > 254;
1718 id2_err = id2 < 1 || id2 > 254;
1719 if (id1_err || id2_err) {
1720 if (id1_err && id2_err) {
1721 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 724,
1722 "Structured Append ID1 '%1$03d' and ID2 '%2$03d' out of range (001 to 254)"
1723 " (ID \"%3$03d%4$03d\")",
1724 id1, id2, id1, id2);
1725 }
1726 if (id1_err) {
1727 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 725,
1728 "Structured Append ID1 '%1$03d' out of range (001 to 254) (ID \"%2$03d%3$03d\")",
1729 id1, id1, id2);
1730 }
1731 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 726,
1732 "Structured Append ID2 '%1$03d' out of range (001 to 254) (ID \"%2$03d%3$03d\")",
1733 id2, id1, id2);
1734 }
1735 } else {
1736 id1 = id2 = 1;
1737 }
1738
1739 target[tp++] = 233;
1740 target[tp++] = (17 - symbol->structapp.count) | ((symbol->structapp.index - 1) << 4);
1741 target[tp++] = id1;
1742 target[tp++] = id2;
1743 }
1744
1745 /* gs1 flag values: 0: no gs1, 1: gs1 with FNC1 serparator, 2: GS separator */
1746 if ((symbol->input_mode & 0x07) == GS1_MODE) {
1747 if (symbol->output_options & GS1_GS_SEPARATOR) {
1748 gs1 = 2;
1749 } else {
1750 gs1 = 1;
1751 }
1752 } else {
1753 gs1 = 0;
1754 }
1755
1756 if (gs1) {
1757 target[tp++] = 232;
1758 if (debug_print) fputs("FN1 ", stdout);
1759 } /* FNC1 */
1760
1761 if (symbol->output_options & READER_INIT) {
1762 if (gs1) {
1763 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 521, "Cannot use Reader Initialisation in GS1 mode");
1764 }
1765 if (symbol->structapp.count) {
1766 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 727,
1767 "Cannot have Structured Append and Reader Initialisation at the same time");
1768 }
1769 target[tp++] = 234; /* Reader Programming */
1770 if (debug_print) fputs("RP ", stdout);
1771 }
1772
1773 /* Check for Macro05/Macro06 */
1774 /* "[)>[RS]05[GS]...[RS][EOT]" -> CW 236 */
1775 /* "[)>[RS]06[GS]...[RS][EOT]" -> CW 237 */
1776 if (tp == 0 && segs[0].length >= 9 && last_seg->length >= 2
1777 && segs[0].source[0] == '[' && segs[0].source[1] == ')' && segs[0].source[2] == '>'
1778 && segs[0].source[3] == '\x1e' /*RS*/ && segs[0].source[4] == '0'
1779 && (segs[0].source[5] == '5' || segs[0].source[5] == '6')
1780 && segs[0].source[6] == '\x1d' /*GS*/
1781 && last_seg->source[last_seg->length - 1] == '\x04' /*EOT*/
1782 && last_seg->source[last_seg->length - 2] == '\x1e' /*RS*/) {
1783
1784 /* Output macro Codeword */
1785 if (segs[0].source[5] == '5') {
1786 target[tp++] = 236;
1787 if (debug_print) fputs("Macro05 ", stdout);
1788 } else {
1789 target[tp++] = 237;
1790 if (debug_print) fputs("Macro06 ", stdout);
1791 }
1792 /* Remove macro characters from input string */
1793 in_macro = 1;
1794 }
1795
1796 for (i = 0; i < seg_count; i++) {
1797 int src_inc = 0, len_dec = 0;
1798 if (in_macro) {
1799 if (i == 0) {
1800 src_inc = len_dec = 7; /* Skip over macro characters at beginning */
1801 }
1802 if (i + 1 == seg_count) {
1803 len_dec += 2; /* Remove RS + EOT from end */
1804 }
1805 }
1806 error_number = dm_encode(symbol, segs[i].source + src_inc, segs[i].length - len_dec, segs[i].eci, gs1,
1807 target, &tp);
1808 if (error_number != 0) {
1809 return error_number;
1810 }
1811 }
1812
1813 *p_binlen = tp;
1814
1815 return 0;
1816 }
1817
1818 /* add pad bits */
1819 static void dm_add_tail(unsigned char target[], int tp, const int tail_length) {
1820 int i, prn, temp;
1821
1822 target[tp++] = 129; /* Pad */
1823 for (i = 1; i < tail_length; i++) {
1824 /* B.1.1 253-state randomising algorithm */
1825 prn = ((149 * (tp + 1)) % 253) + 1;
1826 temp = 129 + prn;
1827 if (temp <= 254) {
1828 target[tp++] = (unsigned char) (temp);
1829 } else {
1830 target[tp++] = (unsigned char) (temp - 254);
1831 }
1832 }
1833 }
1834
1835 static int dm_ecc200(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) {
1836 int i, skew = 0;
1837 unsigned char binary[2200];
1838 int binlen = 0; /* Suppress clang-tidy-20 uninitialized value false positive */
1839 int symbolsize;
1840 int taillength, error_number;
1841 int H, W, FH, FW, datablock, bytes, rsblock;
1842 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
1843
1844 /* `length` may be decremented by 2 if macro character is used */
1845 error_number = dm_encode_segs(symbol, segs, seg_count, binary, &binlen);
1846 if (error_number != 0) {
1847 return error_number;
1848 }
1849
1850 symbolsize = dm_get_symbolsize(symbol, binlen);
1851
1852 if (binlen > dm_matrixbytes[symbolsize]) {
1853 if ((symbol->option_2 >= 1) && (symbol->option_2 <= DMSIZESCOUNT)) {
1854 /* The symbol size was given by --ver (option_2) */
1855 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 522,
1856 "Input too long for Version %1$d, requires %2$d codewords (maximum %3$d)",
1857 symbol->option_2, binlen, dm_matrixbytes[symbolsize]);
1858 }
1859 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 523, "Input too long, requires %d codewords (maximum 1558)",
1860 binlen);
1861 }
1862
1863 H = dm_matrixH[symbolsize];
1864 W = dm_matrixW[symbolsize];
1865 FH = dm_matrixFH[symbolsize];
1866 FW = dm_matrixFW[symbolsize];
1867 bytes = dm_matrixbytes[symbolsize];
1868 datablock = dm_matrixdatablock[symbolsize];
1869 rsblock = dm_matrixrsblock[symbolsize];
1870
1871 taillength = bytes - binlen;
1872
1873 if (taillength != 0) {
1874 dm_add_tail(binary, binlen, taillength);
1875 }
1876 if (debug_print) {
1877 printf("Pads (%d): ", taillength);
1878 for (i = binlen; i < binlen + taillength; i++) printf("%d ", binary[i]);
1879 fputc('\n', stdout);
1880 }
1881
1882 /* ecc code */
1883 if (symbolsize == DMINTSYMBOL144 && !(symbol->option_3 & DM_ISO_144)) {
1884 skew = 1;
1885 }
1886 dm_ecc(binary, bytes, datablock, rsblock, skew);
1887 if (debug_print) {
1888 printf("ECC (%d): ", rsblock * (bytes / datablock));
1889 for (i = bytes; i < bytes + rsblock * (bytes / datablock); i++) printf("%d ", binary[i]);
1890 fputc('\n', stdout);
1891 }
1892
1893 #ifdef ZINT_TEST
1894 if (symbol->debug & ZINT_DEBUG_TEST) {
1895 debug_test_codeword_dump(symbol, binary, skew ? 1558 + 620 : bytes + rsblock * (bytes / datablock));
1896 }
1897 #endif
1898 { /* placement */
1899 const int NC = W - 2 * (W / FW);
1900 const int NR = H - 2 * (H / FH);
1901 int x, y, *places;
1902 if (!(places = (int *) calloc(NC * NR, sizeof(int)))) {
1903 return errtxt(ZINT_ERROR_MEMORY, symbol, 718, "Insufficient memory for placement array");
1904 }
1905 dm_placement(places, NR, NC);
1906 for (y = 0; y < H; y += FH) {
1907 for (x = 0; x < W; x++)
1908 set_module(symbol, (H - y) - 1, x);
1909 for (x = 0; x < W; x += 2)
1910 set_module(symbol, y, x);
1911 }
1912 for (x = 0; x < W; x += FW) {
1913 for (y = 0; y < H; y++)
1914 set_module(symbol, (H - y) - 1, x);
1915 for (y = 0; y < H; y += 2)
1916 set_module(symbol, (H - y) - 1, x + FW - 1);
1917 }
1918 #ifdef DM_DEBUG
1919 /* Print position matrix as in standard */
1920 for (y = NR - 1; y >= 0; y--) {
1921 for (x = 0; x < NC; x++) {
1922 const int v = places[(NR - y - 1) * NC + x];
1923 if (x != 0) fprintf(stderr, "|");
1924 fprintf(stderr, "%3d.%2d", (v >> 3), 8 - (v & 7));
1925 }
1926 fprintf(stderr, "\n");
1927 }
1928 #endif
1929 for (y = 0; y < NR; y++) {
1930 for (x = 0; x < NC; x++) {
1931 const int v = places[(NR - y - 1) * NC + x];
1932 if (v == 1 || (v > 7 && (binary[(v >> 3) - 1] & (1 << (v & 7))))) {
1933 set_module(symbol, H - (1 + y + 2 * (y / (FH - 2))) - 1, 1 + x + 2 * (x / (FW - 2)));
1934 }
1935 }
1936 }
1937 for (y = 0; y < H; y++) {
1938 symbol->row_height[y] = 1;
1939 }
1940 free(places);
1941 }
1942
1943 symbol->height = H;
1944 symbol->rows = H;
1945 symbol->width = W;
1946
1947 return error_number;
1948 }
1949
1950 INTERNAL int datamatrix(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) {
1951
1952 if (symbol->option_1 <= 1) {
1953 /* ECC 200 */
1954 return dm_ecc200(symbol, segs, seg_count);
1955 }
1956 /* ECC 000 - 140 */
1957 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 524, "Older Data Matrix standards are no longer supported");
1958 }
1959
1960 /* vim: set ts=4 sw=4 et : */