comparison mupdf-source/thirdparty/zint/backend/code49.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 /* code49.c - Handles Code 49 */
2 /*
3 libzint - the open source barcode library
4 Copyright (C) 2009-2024 Robin Stuart <rstuart114@gmail.com>
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions
8 are met:
9
10 1. Redistributions of source code must retain the above copyright
11 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 3. Neither the name of the project nor the names of its contributors
16 may be used to endorse or promote products derived from this software
17 without specific prior written permission.
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 SUCH DAMAGE.
30 */
31 /* SPDX-License-Identifier: BSD-3-Clause */
32
33 #include <stdio.h>
34 #include "common.h"
35 #include "code49.h"
36
37 static const char C49_INSET[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%!&*";
38
39 /* "!" represents Shift 1 and "&" represents Shift 2, "*" represents FNC1 */
40
41 INTERNAL int code49(struct zint_symbol *symbol, unsigned char source[], int length) {
42 int i, j, rows, M, x_count, y_count, z_count, posn_val, local_value;
43 char intermediate[170] = "";
44 char *d = intermediate;
45 int codewords[170], codeword_count;
46 int c_grid[8][8]; /* Refers to table 3 */
47 int w_grid[8][4]; /* Refets to table 2 */
48 int pad_count = 0;
49 char pattern[80];
50 int bp = 0; /* Initialize to suppress gcc -Wmaybe-uninitialized warning */
51 int gs1;
52 int h;
53 int error_number = 0;
54
55 if (length > 81) {
56 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 430, "Input length %d too long (maximum 81)", length);
57 }
58 if ((symbol->input_mode & 0x07) == GS1_MODE) {
59 gs1 = 1;
60 *d++ = '*'; /* FNC1 */
61 } else {
62 gs1 = 0;
63 }
64
65 for (i = 0; i < length; i++) {
66 if (source[i] > 127) {
67 return errtxtf(ZINT_ERROR_INVALID_DATA, symbol, 431,
68 "Invalid character at position %d in input, extended ASCII not allowed", i + 1);
69 }
70 if (gs1 && source[i] == '\x1D') {
71 *d++ = '*'; /* FNC1 */
72 } else {
73 const char *const entry = c49_table7[source[i]];
74 memcpy(d, entry, 2);
75 d += entry[1] ? 2 : 1;
76 }
77 }
78
79 codeword_count = 0;
80 i = 0;
81 h = d - intermediate;
82 do {
83 if (z_isdigit(intermediate[i])) {
84 /* Numeric data */
85 for (j = 0; z_isdigit(intermediate[i + j]); j++);
86 if (j >= 5) {
87 /* Use Numeric Encodation Method */
88 int block_count, c;
89 int block_remain;
90 int block_value;
91
92 codewords[codeword_count] = 48; /* Numeric Shift */
93 codeword_count++;
94
95 block_count = j / 5;
96 block_remain = j % 5;
97
98 for (c = 0; c < block_count; c++) {
99 if ((c == block_count - 1) && (block_remain == 2)) {
100 /* Rule (d) */
101 block_value = 100000;
102 block_value += ctoi(intermediate[i]) * 1000;
103 block_value += ctoi(intermediate[i + 1]) * 100;
104 block_value += ctoi(intermediate[i + 2]) * 10;
105 block_value += ctoi(intermediate[i + 3]);
106
107 codewords[codeword_count] = block_value / (48 * 48);
108 block_value = block_value - (48 * 48) * codewords[codeword_count];
109 codeword_count++;
110 codewords[codeword_count] = block_value / 48;
111 block_value = block_value - 48 * codewords[codeword_count];
112 codeword_count++;
113 codewords[codeword_count] = block_value;
114 codeword_count++;
115 i += 4;
116 block_value = ctoi(intermediate[i]) * 100;
117 block_value += ctoi(intermediate[i + 1]) * 10;
118 block_value += ctoi(intermediate[i + 2]);
119
120 codewords[codeword_count] = block_value / 48;
121 block_value = block_value - 48 * codewords[codeword_count];
122 codeword_count++;
123 codewords[codeword_count] = block_value;
124 codeword_count++;
125 i += 3;
126 } else {
127 block_value = ctoi(intermediate[i]) * 10000;
128 block_value += ctoi(intermediate[i + 1]) * 1000;
129 block_value += ctoi(intermediate[i + 2]) * 100;
130 block_value += ctoi(intermediate[i + 3]) * 10;
131 block_value += ctoi(intermediate[i + 4]);
132
133 codewords[codeword_count] = block_value / (48 * 48);
134 block_value = block_value - (48 * 48) * codewords[codeword_count];
135 codeword_count++;
136 codewords[codeword_count] = block_value / 48;
137 block_value = block_value - 48 * codewords[codeword_count];
138 codeword_count++;
139 codewords[codeword_count] = block_value;
140 codeword_count++;
141 i += 5;
142 }
143 }
144
145 switch (block_remain) {
146 case 1:
147 /* Rule (a) */
148 codewords[codeword_count] = posn(C49_INSET, intermediate[i]);
149 codeword_count++;
150 i++;
151 break;
152 case 3:
153 /* Rule (b) */
154 block_value = ctoi(intermediate[i]) * 100;
155 block_value += ctoi(intermediate[i + 1]) * 10;
156 block_value += ctoi(intermediate[i + 2]);
157
158 codewords[codeword_count] = block_value / 48;
159 block_value = block_value - 48 * codewords[codeword_count];
160 codeword_count++;
161 codewords[codeword_count] = block_value;
162 codeword_count++;
163 i += 3;
164 break;
165 case 4:
166 /* Rule (c) */
167 block_value = 100000;
168 block_value += ctoi(intermediate[i]) * 1000;
169 block_value += ctoi(intermediate[i + 1]) * 100;
170 block_value += ctoi(intermediate[i + 2]) * 10;
171 block_value += ctoi(intermediate[i + 3]);
172
173 codewords[codeword_count] = block_value / (48 * 48);
174 block_value = block_value - (48 * 48) * codewords[codeword_count];
175 codeword_count++;
176 codewords[codeword_count] = block_value / 48;
177 block_value = block_value - 48 * codewords[codeword_count];
178 codeword_count++;
179 codewords[codeword_count] = block_value;
180 codeword_count++;
181 i += 4;
182 break;
183 }
184 if (i < h) {
185 /* There is more to add */
186 codewords[codeword_count] = 48; /* Numeric Shift */
187 codeword_count++;
188 }
189 } else {
190 codewords[codeword_count] = posn(C49_INSET, intermediate[i]);
191 codeword_count++;
192 i++;
193 }
194 } else {
195 codewords[codeword_count] = posn(C49_INSET, intermediate[i]);
196 codeword_count++;
197 i++;
198 }
199 } while (i < h);
200
201 switch (codewords[0]) {
202 /* Set starting mode value */
203 case 48: M = 2;
204 break;
205 case 43: M = 4;
206 break;
207 case 44: M = 5;
208 break;
209 default: M = 0;
210 break;
211 }
212
213 if (M != 0) {
214 codeword_count--;
215 for (i = 0; i < codeword_count; i++) {
216 codewords[i] = codewords[i + 1];
217 }
218 }
219
220 if (codeword_count > 49) {
221 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 432, "Input too long, requires %d codewords (maximum 49)",
222 codeword_count);
223 }
224
225 /* Place codewords in code character array (c grid) */
226 rows = 0;
227 do {
228 for (i = 0; i < 7; i++) {
229 if (((rows * 7) + i) < codeword_count) {
230 c_grid[rows][i] = codewords[(rows * 7) + i];
231 } else {
232 c_grid[rows][i] = 48; /* Pad */
233 pad_count++;
234 }
235 }
236 rows++;
237 } while ((rows * 7) < codeword_count);
238
239 if ((((rows <= 6) && (pad_count < 5))) || (rows > 6) || (rows == 1)) {
240 /* Add a row */
241 for (i = 0; i < 7; i++) {
242 c_grid[rows][i] = 48; /* Pad */
243 }
244 rows++;
245 }
246
247 if (symbol->option_1 >= 2 && symbol->option_1 <= 8) { /* Minimum no. of rows */
248 if (symbol->option_1 > rows) {
249 for (j = symbol->option_1 - rows; j > 0; j--) {
250 for (i = 0; i < 7; i++) {
251 c_grid[rows][i] = 48; /* Pad */
252 }
253 rows++;
254 }
255 }
256 } else if (symbol->option_1 >= 1) {
257 strcpy(symbol->errtxt, "433: Minimum number of rows out of range (2 to 8)");
258 return ZINT_ERROR_INVALID_OPTION;
259 }
260
261 /* Add row count and mode character */
262 c_grid[rows - 1][6] = (7 * (rows - 2)) + M;
263
264 /* Add row check character */
265 for (i = 0; i < rows - 1; i++) {
266 int row_sum = 0;
267
268 for (j = 0; j < 7; j++) {
269 row_sum += c_grid[i][j];
270 }
271 c_grid[i][7] = row_sum % 49;
272 }
273
274 /* Calculate Symbol Check Characters */
275 posn_val = 0;
276 x_count = c_grid[rows - 1][6] * 20;
277 y_count = c_grid[rows - 1][6] * 16;
278 z_count = c_grid[rows - 1][6] * 38;
279 for (i = 0; i < rows - 1; i++) {
280 for (j = 0; j < 4; j++) {
281 local_value = (c_grid[i][2 * j] * 49) + c_grid[i][(2 * j) + 1];
282 x_count += c49_x_weight[posn_val] * local_value;
283 y_count += c49_y_weight[posn_val] * local_value;
284 z_count += c49_z_weight[posn_val] * local_value;
285 posn_val++;
286 }
287 }
288
289 if (rows > 6) {
290 /* Add Z Symbol Check */
291 c_grid[rows - 1][0] = (z_count % 2401) / 49;
292 c_grid[rows - 1][1] = (z_count % 2401) % 49;
293 }
294
295 local_value = (c_grid[rows - 1][0] * 49) + c_grid[rows - 1][1];
296 x_count += c49_x_weight[posn_val] * local_value;
297 y_count += c49_y_weight[posn_val] * local_value;
298 posn_val++;
299
300 /* Add Y Symbol Check */
301 c_grid[rows - 1][2] = (y_count % 2401) / 49;
302 c_grid[rows - 1][3] = (y_count % 2401) % 49;
303
304 local_value = (c_grid[rows - 1][2] * 49) + c_grid[rows - 1][3];
305 x_count += c49_x_weight[posn_val] * local_value;
306
307 /* Add X Symbol Check */
308 c_grid[rows - 1][4] = (x_count % 2401) / 49;
309 c_grid[rows - 1][5] = (x_count % 2401) % 49;
310
311 /* Add last row check character */
312 j = 0;
313 for (i = 0; i < 7; i++) {
314 j += c_grid[rows - 1][i];
315 }
316 c_grid[rows - 1][7] = j % 49;
317
318 if (symbol->debug & ZINT_DEBUG_PRINT) {
319 fputs("Codewords:\n", stdout);
320 for (i = 0; i < rows; i++) {
321 for (j = 0; j < 8; j++) {
322 printf(" %2d", c_grid[i][j]);
323 }
324 fputc('\n', stdout);
325 }
326 }
327 #ifdef ZINT_TEST
328 if (symbol->debug & ZINT_DEBUG_TEST) {
329 debug_test_codeword_dump_int(symbol, (int *)c_grid, rows * 8);
330 }
331 #endif
332
333 /* Transfer data to symbol character array (w grid) */
334 for (i = 0; i < rows; i++) {
335 for (j = 0; j < 4; j++) {
336 w_grid[i][j] = (c_grid[i][2 * j] * 49) + c_grid[i][(2 * j) + 1];
337 }
338 }
339
340 for (i = 0; i < rows; i++) {
341 bp = 0;
342 bp = bin_append_posn(2, 2, pattern, bp); /* Start character "10" */
343 for (j = 0; j < 4; j++) {
344 if (i != (rows - 1)) {
345 if (c49_table4[i][j] == 'E') {
346 /* Even Parity */
347 bp = bin_append_posn(c49_even_bitpattern[w_grid[i][j]], 16, pattern, bp);
348 } else {
349 /* Odd Parity */
350 bp = bin_append_posn(c49_odd_bitpattern[w_grid[i][j]], 16, pattern, bp);
351 }
352 } else {
353 /* Last row uses all even parity */
354 bp = bin_append_posn(c49_even_bitpattern[w_grid[i][j]], 16, pattern, bp);
355 }
356 }
357 bp = bin_append_posn(15, 4, pattern, bp); /* Stop character "1111" */
358
359 /* Expand into symbol */
360 for (j = 0; j < bp; j++) {
361 if (pattern[j] == '1') {
362 set_module(symbol, i, j);
363 }
364 }
365 }
366
367 symbol->rows = rows;
368 symbol->width = bp;
369
370 if (symbol->output_options & COMPLIANT_HEIGHT) {
371 /* ANSI/AIM BC6-2000 Section 2.6 minimum 8X; use 10X as default
372 Formula 2 H = ((h + g)r + g)X = rows * row_height + (rows - 1) * separator as borders not included
373 in symbol->height (added on) */
374 const int separator = symbol->option_3 >= 1 && symbol->option_3 <= 4 ? symbol->option_3 : 1;
375 const float min_row_height = stripf((8.0f * rows + separator * (rows - 1)) / rows);
376 const float default_height = 10.0f * rows + separator * (rows - 1);
377 error_number = set_height(symbol, min_row_height, default_height, 0.0f, 0 /*no_errtxt*/);
378 } else {
379 (void) set_height(symbol, 0.0f, 10.0f * rows, 0.0f, 1 /*no_errtxt*/);
380 }
381
382 symbol->output_options |= BARCODE_BIND;
383
384 if (symbol->border_width == 0) { /* Allow override if non-zero */
385 symbol->border_width = 1; /* ANSI/AIM BC6-2000 Section 2.1 (note change from previous default 2) */
386 }
387
388 return error_number;
389 }
390
391 /* vim: set ts=4 sw=4 et : */