comparison mupdf-source/thirdparty/zint/backend/gridmtx.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 /* gridmtx.c - Grid Matrix */
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 /* This file implements Grid Matrix as specified in
34 AIM Global Document Number AIMD014 Rev. 1.63 Revised 9 Dec 2008 */
35
36 #include <stdio.h>
37 #include "common.h"
38 #include "reedsol.h"
39 #include "gridmtx.h"
40 #include "eci.h"
41
42 static const char EUROPIUM[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ";
43 static const char EUROPIUM_UPR[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
44 static const char EUROPIUM_LWR[] = "abcdefghijklmnopqrstuvwxyz ";
45
46 /* gm_define_mode() stuff */
47
48 /* Bits multiplied by this for costs, so as to be whole integer divisible by 2 and 3 */
49 #define GM_MULT 6
50
51 /* Non-digit numeral set, excluding EOL (carriage return/linefeed) */
52 static const char gm_numeral_nondigits[] = " +-.,";
53
54 /* Whether in numeral or not. If in numeral, *p_numeral_end is set to position after numeral,
55 * and *p_numeral_cost is set to per-numeral cost */
56 static int gm_in_numeral(const unsigned int ddata[], const int length, const int in_posn,
57 unsigned int *p_numeral_end, unsigned int *p_numeral_cost) {
58 int i, digit_cnt, nondigit, nondigit_posn;
59
60 if (in_posn < (int) *p_numeral_end) {
61 return 1;
62 }
63
64 /* Attempt to calculate the average 'cost' of using numeric mode in number of bits (times GM_MULT) */
65 /* Also ensures that numeric mode is not selected when it cannot be used: for example in
66 a string which has "2.2.0" (cannot have more than one non-numeric character for each
67 block of three numeric characters) */
68 for (i = in_posn, digit_cnt = 0, nondigit = 0, nondigit_posn = 0; i < length && i < in_posn + 4 && digit_cnt < 3;
69 i++) {
70 if (z_isdigit(ddata[i])) {
71 digit_cnt++;
72 } else if (posn(gm_numeral_nondigits, (const char) ddata[i]) != -1) {
73 if (nondigit) {
74 break;
75 }
76 nondigit = 1;
77 nondigit_posn = i;
78 } else if (i < length - 1 && ddata[i] == 13 && ddata[i + 1] == 10) {
79 if (nondigit) {
80 break;
81 }
82 i++;
83 nondigit = 2;
84 nondigit_posn = i;
85 } else {
86 break;
87 }
88 }
89 if (digit_cnt == 0) { /* Must have at least one digit */
90 *p_numeral_end = 0;
91 return 0;
92 }
93 if (nondigit && nondigit_posn == i - 1) { /* Non-digit can't be at end */
94 nondigit = 0;
95 }
96 *p_numeral_end = in_posn + digit_cnt + nondigit;
97 /* Calculate per-numeral cost where 120 == (10 + 10) * GM_MULT, 60 == 10 * GM_MULT */
98 if (digit_cnt == 3) {
99 *p_numeral_cost = nondigit == 2 ? 24 /* (120 / 5) */ : nondigit == 1 ? 30 /* (120 / 4) */ : 20 /* (60 / 3) */;
100 } else if (digit_cnt == 2) {
101 *p_numeral_cost = nondigit == 2 ? 30 /* (120 / 4) */ : nondigit == 1 ? 40 /* (120 / 3) */ : 30 /* (60 / 2) */;
102 } else {
103 *p_numeral_cost = nondigit == 2 ? 40 /* (120 / 3) */ : nondigit == 1 ? 60 /* (120 / 2) */ : 60 /* (60 / 1) */;
104 }
105 return 1;
106 }
107
108 /* Encoding modes */
109 #define GM_CHINESE 'H'
110 #define GM_NUMBER 'N'
111 #define GM_LOWER 'L'
112 #define GM_UPPER 'U'
113 #define GM_MIXED 'M'
114 #define GM_BYTE 'B'
115 /* Note Control is a submode of Lower, Upper and Mixed modes */
116
117 /* Indexes into mode_types array */
118 #define GM_H 0 /* Chinese (Hanzi) */
119 #define GM_N 1 /* Numeral */
120 #define GM_L 2 /* Lower case */
121 #define GM_U 3 /* Upper case */
122 #define GM_M 4 /* Mixed */
123 #define GM_B 5 /* Byte */
124
125 #define GM_NUM_MODES 6
126
127 /* Calculate optimized encoding modes. Adapted from Project Nayuki */
128 /* Copyright (c) Project Nayuki. (MIT License) See qr.c for detailed notice */
129 static void gm_define_mode(char *mode, const unsigned int ddata[], const int length, const int debug_print) {
130 /* Must be in same order as GM_H etc */
131 static const char mode_types[] = { GM_CHINESE, GM_NUMBER, GM_LOWER, GM_UPPER, GM_MIXED, GM_BYTE, '\0' };
132
133 /* Initial mode costs */
134 static const unsigned int head_costs[GM_NUM_MODES] = {
135 /* H N (+pad prefix) L U M B (+byte count) */
136 4 * GM_MULT, (4 + 2) * GM_MULT, 4 * GM_MULT, 4 * GM_MULT, 4 * GM_MULT, (4 + 9) * GM_MULT
137 };
138
139 /* Cost of switching modes from k to j - see AIMD014 Rev. 1.63 Table 9 – Type conversion codes */
140 static const unsigned char switch_costs[GM_NUM_MODES][GM_NUM_MODES] = {
141 /* H N L U M B */
142 /*H*/ { 0, (13 + 2) * GM_MULT, 13 * GM_MULT, 13 * GM_MULT, 13 * GM_MULT, (13 + 9) * GM_MULT },
143 /*N*/ { 10 * GM_MULT, 0, 10 * GM_MULT, 10 * GM_MULT, 10 * GM_MULT, (10 + 9) * GM_MULT },
144 /*L*/ { 5 * GM_MULT, (5 + 2) * GM_MULT, 0, 5 * GM_MULT, 7 * GM_MULT, (7 + 9) * GM_MULT },
145 /*U*/ { 5 * GM_MULT, (5 + 2) * GM_MULT, 5 * GM_MULT, 0, 7 * GM_MULT, (7 + 9) * GM_MULT },
146 /*M*/ { 10 * GM_MULT, (10 + 2) * GM_MULT, 10 * GM_MULT, 10 * GM_MULT, 0, (10 + 9) * GM_MULT },
147 /*B*/ { 4 * GM_MULT, (4 + 2) * GM_MULT, 4 * GM_MULT, 4 * GM_MULT, 4 * GM_MULT, 0 },
148 };
149
150 /* Final end-of-data cost - see AIMD014 Rev. 1.63 Table 9 – Type conversion codes */
151 static const unsigned char eod_costs[GM_NUM_MODES] = {
152 /* H N L U M B */
153 13 * GM_MULT, 10 * GM_MULT, 5 * GM_MULT, 5 * GM_MULT, 10 * GM_MULT, 4 * GM_MULT
154 };
155
156 unsigned int numeral_end = 0, numeral_cost = 0, byte_count = 0; /* State */
157 int double_byte, space, numeric, lower, upper, control, double_digit, eol;
158
159 int i, j, k;
160 unsigned int min_cost;
161 char cur_mode;
162 unsigned int prev_costs[GM_NUM_MODES];
163 unsigned int cur_costs[GM_NUM_MODES];
164 char (*char_modes)[GM_NUM_MODES] = (char (*)[GM_NUM_MODES]) z_alloca(GM_NUM_MODES * length);
165
166 /* char_modes[i][j] represents the mode to encode the code point at index i such that the final segment
167 ends in mode_types[j] and the total number of bits is minimized over all possible choices */
168 memset(char_modes, 0, length * GM_NUM_MODES);
169
170 /* At the beginning of each iteration of the loop below, prev_costs[j] is the minimum number of 1/6 (1/XX_MULT)
171 * bits needed to encode the entire string prefix of length i, and end in mode_types[j] */
172 memcpy(prev_costs, head_costs, GM_NUM_MODES * sizeof(unsigned int));
173
174 /* Calculate costs using dynamic programming */
175 for (i = 0; i < length; i++) {
176 memset(cur_costs, 0, GM_NUM_MODES * sizeof(unsigned int));
177
178 space = numeric = lower = upper = control = double_digit = eol = 0;
179
180 double_byte = ddata[i] > 0xFF;
181 if (!double_byte) {
182 space = ddata[i] == ' ';
183 if (!space) {
184 numeric = z_isdigit(ddata[i]);
185 if (!numeric) {
186 lower = z_islower(ddata[i]);
187 if (!lower) {
188 upper = z_isupper(ddata[i]);
189 if (!upper) {
190 control = ddata[i] < 0x7F; /* Exclude DEL */
191 if (control && i + 1 < length) {
192 eol = ddata[i] == 13 && ddata[i + 1] == 10;
193 }
194 }
195 }
196 } else if (i + 1 < length) {
197 double_digit = z_isdigit(ddata[i + 1]);
198 }
199 }
200 }
201
202 /* Hanzi mode can encode anything */
203 cur_costs[GM_H] = prev_costs[GM_H] + (double_digit || eol ? 39 : 78); /* (6.5 : 13) * GM_MULT */
204 char_modes[i][GM_H] = GM_CHINESE;
205
206 /* Byte mode can encode anything */
207 if (byte_count == 512 || (double_byte && byte_count == 511)) {
208 cur_costs[GM_B] = head_costs[GM_B];
209 if (double_byte && byte_count == 511) {
210 cur_costs[GM_B] += 48; /* 8 * GM_MULT */
211 double_byte = 0; /* Splitting double-byte so mark as single */
212 }
213 byte_count = 0;
214 }
215 cur_costs[GM_B] += prev_costs[GM_B] + (double_byte ? 96 : 48); /* (16 : 8) * GM_MULT */
216 char_modes[i][GM_B] = GM_BYTE;
217 byte_count += double_byte ? 2 : 1;
218
219 if (gm_in_numeral(ddata, length, i, &numeral_end, &numeral_cost)) {
220 cur_costs[GM_N] = prev_costs[GM_N] + numeral_cost;
221 char_modes[i][GM_N] = GM_NUMBER;
222 }
223
224 if (control) {
225 cur_costs[GM_L] = prev_costs[GM_L] + 78; /* (7 + 6) * GM_MULT */
226 char_modes[i][GM_L] = GM_LOWER;
227 cur_costs[GM_U] = prev_costs[GM_U] + 78; /* (7 + 6) * GM_MULT */
228 char_modes[i][GM_U] = GM_UPPER;
229 cur_costs[GM_M] = prev_costs[GM_M] + 96; /* (10 + 6) * GM_MULT */
230 char_modes[i][GM_M] = GM_MIXED;
231 } else {
232 if (lower || space) {
233 cur_costs[GM_L] = prev_costs[GM_L] + 30; /* 5 * GM_MULT */
234 char_modes[i][GM_L] = GM_LOWER;
235 }
236 if (upper || space) {
237 cur_costs[GM_U] = prev_costs[GM_U] + 30; /* 5 * GM_MULT */
238 char_modes[i][GM_U] = GM_UPPER;
239 }
240 if (numeric || lower || upper || space) {
241 cur_costs[GM_M] = prev_costs[GM_M] + 36; /* 6 * GM_MULT */
242 char_modes[i][GM_M] = GM_MIXED;
243 }
244 }
245
246 if (i == length - 1) { /* Add end of data costs if last character */
247 for (j = 0; j < GM_NUM_MODES; j++) {
248 if (char_modes[i][j]) {
249 cur_costs[j] += eod_costs[j];
250 }
251 }
252 }
253
254 /* Start new segment at the end to switch modes */
255 for (j = 0; j < GM_NUM_MODES; j++) { /* To mode */
256 for (k = 0; k < GM_NUM_MODES; k++) { /* From mode */
257 if (j != k && char_modes[i][k]) {
258 const unsigned int new_cost = cur_costs[k] + switch_costs[k][j];
259 if (!char_modes[i][j] || new_cost < cur_costs[j]) {
260 cur_costs[j] = new_cost;
261 char_modes[i][j] = mode_types[k];
262 }
263 }
264 }
265 }
266
267 memcpy(prev_costs, cur_costs, GM_NUM_MODES * sizeof(unsigned int));
268 }
269
270 /* Find optimal ending mode */
271 min_cost = prev_costs[0];
272 cur_mode = mode_types[0];
273 for (i = 1; i < GM_NUM_MODES; i++) {
274 if (prev_costs[i] < min_cost) {
275 min_cost = prev_costs[i];
276 cur_mode = mode_types[i];
277 }
278 }
279
280 /* Get optimal mode for each code point by tracing backwards */
281 for (i = length - 1; i >= 0; i--) {
282 j = posn(mode_types, cur_mode);
283 cur_mode = char_modes[i][j];
284 mode[i] = cur_mode;
285 }
286
287 if (debug_print) {
288 printf(" Mode: %.*s\n", length, mode);
289 }
290 }
291
292 /* Add the length indicator for byte encoded blocks */
293 static void gm_add_byte_count(char binary[], const int byte_count_posn, const int byte_count) {
294 /* AIMD014 6.3.7: "Let L be the number of bytes of input data to be encoded in the 8-bit binary data set.
295 * First output (L-1) as a 9-bit binary prefix to record the number of bytes..." */
296 bin_append_posn(byte_count - 1, 9, binary, byte_count_posn);
297 }
298
299 /* Add a control character to the data stream */
300 static int gm_add_shift_char(char binary[], int bp, int shifty, const int debug_print) {
301 int i;
302 int glyph = 0;
303
304 if (shifty < 32) {
305 glyph = shifty;
306 } else {
307 for (i = 32; i < 64; i++) {
308 if (gm_shift_set[i] == shifty) {
309 glyph = i;
310 break;
311 }
312 }
313 }
314
315 if (debug_print) {
316 printf("SHIFT [%d] ", glyph);
317 }
318
319 bp = bin_append_posn(glyph, 6, binary, bp);
320
321 return bp;
322 }
323
324 static int gm_encode(unsigned int ddata[], const int length, char binary[], const int eci, int *p_bp,
325 const int debug_print) {
326 /* Create a binary stream representation of the input data.
327 7 sets are defined - Chinese characters, Numerals, Lower case letters, Upper case letters,
328 Mixed numerals and latters, Control characters and 8-bit binary data */
329 int sp = 0;
330 int current_mode = 0;
331 int last_mode;
332 unsigned int glyph = 0;
333 int c1, c2, done;
334 int p = 0, ppos;
335 int numbuf[3], punt = 0;
336 int number_pad_posn = 0;
337 int byte_count_posn = 0;
338 int byte_count = 0;
339 int shift;
340 int bp = *p_bp;
341 char *mode = (char *) z_alloca(length);
342
343 if (eci != 0) {
344 /* ECI assignment according to Table 8 */
345 bp = bin_append_posn(12, 4, binary, bp); /* ECI */
346 if (eci <= 1023) {
347 bp = bin_append_posn(eci, 11, binary, bp);
348 } else if (eci <= 32767) {
349 bp = bin_append_posn(2, 2, binary, bp);
350 bp = bin_append_posn(eci, 15, binary, bp);
351 } else {
352 bp = bin_append_posn(3, 2, binary, bp);
353 bp = bin_append_posn(eci, 20, binary, bp);
354 }
355 }
356
357 gm_define_mode(mode, ddata, length, debug_print);
358
359 do {
360 const int next_mode = mode[sp];
361
362 if (next_mode != current_mode) {
363 switch (current_mode) {
364 case 0:
365 switch (next_mode) {
366 case GM_CHINESE: bp = bin_append_posn(1, 4, binary, bp);
367 break;
368 case GM_NUMBER: bp = bin_append_posn(2, 4, binary, bp);
369 break;
370 case GM_LOWER: bp = bin_append_posn(3, 4, binary, bp);
371 break;
372 case GM_UPPER: bp = bin_append_posn(4, 4, binary, bp);
373 break;
374 case GM_MIXED: bp = bin_append_posn(5, 4, binary, bp);
375 break;
376 case GM_BYTE: bp = bin_append_posn(6, 4, binary, bp);
377 break;
378 }
379 break;
380 case GM_CHINESE:
381 switch (next_mode) {
382 case GM_NUMBER: bp = bin_append_posn(8161, 13, binary, bp);
383 break;
384 case GM_LOWER: bp = bin_append_posn(8162, 13, binary, bp);
385 break;
386 case GM_UPPER: bp = bin_append_posn(8163, 13, binary, bp);
387 break;
388 case GM_MIXED: bp = bin_append_posn(8164, 13, binary, bp);
389 break;
390 case GM_BYTE: bp = bin_append_posn(8165, 13, binary, bp);
391 break;
392 }
393 break;
394 case GM_NUMBER:
395 /* add numeric block padding value */
396 switch (p) {
397 case 1: binary[number_pad_posn] = '1';
398 binary[number_pad_posn + 1] = '0';
399 break; /* 2 pad digits */
400 case 2: binary[number_pad_posn] = '0';
401 binary[number_pad_posn + 1] = '1';
402 break; /* 1 pad digits */
403 case 3: binary[number_pad_posn] = '0';
404 binary[number_pad_posn + 1] = '0';
405 break; /* 0 pad digits */
406 }
407 switch (next_mode) {
408 case GM_CHINESE: bp = bin_append_posn(1019, 10, binary, bp);
409 break;
410 case GM_LOWER: bp = bin_append_posn(1020, 10, binary, bp);
411 break;
412 case GM_UPPER: bp = bin_append_posn(1021, 10, binary, bp);
413 break;
414 case GM_MIXED: bp = bin_append_posn(1022, 10, binary, bp);
415 break;
416 case GM_BYTE: bp = bin_append_posn(1023, 10, binary, bp);
417 break;
418 }
419 break;
420 case GM_LOWER:
421 case GM_UPPER:
422 switch (next_mode) {
423 case GM_CHINESE: bp = bin_append_posn(28, 5, binary, bp);
424 break;
425 case GM_NUMBER: bp = bin_append_posn(29, 5, binary, bp);
426 break;
427 case GM_LOWER:
428 case GM_UPPER: bp = bin_append_posn(30, 5, binary, bp);
429 break;
430 case GM_MIXED: bp = bin_append_posn(124, 7, binary, bp);
431 break;
432 case GM_BYTE: bp = bin_append_posn(126, 7, binary, bp);
433 break;
434 }
435 break;
436 case GM_MIXED:
437 switch (next_mode) {
438 case GM_CHINESE: bp = bin_append_posn(1009, 10, binary, bp);
439 break;
440 case GM_NUMBER: bp = bin_append_posn(1010, 10, binary, bp);
441 break;
442 case GM_LOWER: bp = bin_append_posn(1011, 10, binary, bp);
443 break;
444 case GM_UPPER: bp = bin_append_posn(1012, 10, binary, bp);
445 break;
446 case GM_BYTE: bp = bin_append_posn(1015, 10, binary, bp);
447 break;
448 }
449 break;
450 case GM_BYTE:
451 /* add byte block length indicator */
452 gm_add_byte_count(binary, byte_count_posn, byte_count);
453 byte_count = 0;
454 switch (next_mode) {
455 case GM_CHINESE: bp = bin_append_posn(1, 4, binary, bp);
456 break;
457 case GM_NUMBER: bp = bin_append_posn(2, 4, binary, bp);
458 break;
459 case GM_LOWER: bp = bin_append_posn(3, 4, binary, bp);
460 break;
461 case GM_UPPER: bp = bin_append_posn(4, 4, binary, bp);
462 break;
463 case GM_MIXED: bp = bin_append_posn(5, 4, binary, bp);
464 break;
465 }
466 break;
467 }
468 if (debug_print) {
469 switch (next_mode) {
470 case GM_CHINESE: fputs("CHIN ", stdout);
471 break;
472 case GM_NUMBER: fputs("NUMB ", stdout);
473 break;
474 case GM_LOWER: fputs("LOWR ", stdout);
475 break;
476 case GM_UPPER: fputs("UPPR ", stdout);
477 break;
478 case GM_MIXED: fputs("MIXD ", stdout);
479 break;
480 case GM_BYTE: fputs("BYTE ", stdout);
481 break;
482 }
483 }
484 }
485 last_mode = current_mode;
486 current_mode = next_mode;
487
488 switch (current_mode) {
489 case GM_CHINESE:
490 done = 0;
491 if (ddata[sp] > 0xff) {
492 /* GB2312 character */
493 c1 = (ddata[sp] & 0xff00) >> 8;
494 c2 = ddata[sp] & 0xff;
495
496 if ((c1 >= 0xa1) && (c1 <= 0xa9)) {
497 glyph = (0x60 * (c1 - 0xa1)) + (c2 - 0xa0);
498 } else if ((c1 >= 0xb0) && (c1 <= 0xf7)) {
499 glyph = (0x60 * (c1 - 0xb0 + 9)) + (c2 - 0xa0);
500 }
501 done = 1; /* GB 2312 always within above ranges */
502 /* Note not using the unallocated glyphs 7776 to 8191 mentioned in AIMD014 section 6.3.1.2 */
503 }
504 if (!(done)) {
505 if (sp != (length - 1)) {
506 if ((ddata[sp] == 13) && (ddata[sp + 1] == 10)) {
507 /* End of Line */
508 glyph = 7776;
509 sp++;
510 done = 1;
511 }
512 }
513 }
514 if (!(done)) {
515 if (sp != (length - 1)) {
516 if (z_isdigit(ddata[sp]) && z_isdigit(ddata[sp + 1])) {
517 /* Two digits */
518 glyph = 8033 + (10 * (ddata[sp] - '0')) + (ddata[sp + 1] - '0');
519 sp++;
520 done = 1;
521 }
522 }
523 }
524 if (!(done)) {
525 /* Byte value */
526 glyph = 7777 + ddata[sp];
527 }
528
529 if (debug_print) {
530 printf("[%d] ", (int) glyph);
531 }
532
533 bp = bin_append_posn(glyph, 13, binary, bp);
534 sp++;
535 break;
536
537 case GM_NUMBER:
538 if (last_mode != current_mode) {
539 /* Reserve a space for numeric digit padding value (2 bits) */
540 number_pad_posn = bp;
541 bp = bin_append_posn(0, 2, binary, bp);
542 }
543 p = 0;
544 ppos = -1;
545
546 /* Numeric compression can also include certain combinations of
547 non-numeric character */
548
549 numbuf[0] = '0';
550 numbuf[1] = '0';
551 numbuf[2] = '0';
552 do {
553 if (z_isdigit(ddata[sp])) {
554 numbuf[p] = ddata[sp];
555 p++;
556 } else if (posn(gm_numeral_nondigits, (const char) ddata[sp]) != -1) {
557 if (ppos != -1) {
558 break;
559 }
560 punt = ddata[sp];
561 ppos = p;
562 } else if (sp < (length - 1) && (ddata[sp] == 13) && (ddata[sp + 1] == 10)) {
563 /* <end of line> */
564 if (ppos != -1) {
565 break;
566 }
567 punt = ddata[sp];
568 sp++;
569 ppos = p;
570 } else {
571 break;
572 }
573 sp++;
574 } while ((p < 3) && (sp < length) && mode[sp] == GM_NUMBER);
575
576 if (ppos != -1) {
577 switch (punt) {
578 case ' ': glyph = 0;
579 break;
580 case '+': glyph = 3;
581 break;
582 case '-': glyph = 6;
583 break;
584 case '.': glyph = 9;
585 break;
586 case ',': glyph = 12;
587 break;
588 case 13: glyph = 15;
589 break;
590 }
591 glyph += ppos;
592 glyph += 1000;
593
594 if (debug_print) {
595 printf("[%d] ", (int) glyph);
596 }
597
598 bp = bin_append_posn(glyph, 10, binary, bp);
599 }
600
601 glyph = (100 * (numbuf[0] - '0')) + (10 * (numbuf[1] - '0')) + (numbuf[2] - '0');
602 if (debug_print) {
603 printf("[%d] ", (int) glyph);
604 }
605
606 bp = bin_append_posn(glyph, 10, binary, bp);
607 break;
608
609 case GM_BYTE:
610 if (last_mode != current_mode) {
611 /* Reserve space for byte block length indicator (9 bits) */
612 byte_count_posn = bp;
613 bp = bin_append_posn(0, 9, binary, bp);
614 }
615 glyph = ddata[sp];
616 if (byte_count == 512 || (glyph > 0xFF && byte_count == 511)) {
617 /* Maximum byte block size is 512 bytes. If longer is needed then start a new block */
618 if (glyph > 0xFF && byte_count == 511) { /* Split double-byte */
619 bp = bin_append_posn(glyph >> 8, 8, binary, bp);
620 glyph &= 0xFF;
621 byte_count++;
622 }
623 gm_add_byte_count(binary, byte_count_posn, byte_count);
624 bp = bin_append_posn(7, 4, binary, bp);
625 byte_count_posn = bp;
626 bp = bin_append_posn(0, 9, binary, bp);
627 byte_count = 0;
628 }
629
630 if (debug_print) {
631 printf("[%d] ", (int) glyph);
632 }
633 bp = bin_append_posn(glyph, glyph > 0xFF ? 16 : 8, binary, bp);
634 sp++;
635 byte_count++;
636 if (glyph > 0xFF) {
637 byte_count++;
638 }
639 break;
640
641 case GM_MIXED:
642 shift = 1;
643 if (z_isdigit(ddata[sp])) {
644 shift = 0;
645 } else if (z_isupper(ddata[sp])) {
646 shift = 0;
647 } else if (z_islower(ddata[sp])) {
648 shift = 0;
649 } else if (ddata[sp] == ' ') {
650 shift = 0;
651 }
652
653 if (shift == 0) {
654 /* Mixed Mode character */
655 glyph = posn(EUROPIUM, (const char) ddata[sp]);
656 if (debug_print) {
657 printf("[%d] ", (int) glyph);
658 }
659
660 bp = bin_append_posn(glyph, 6, binary, bp);
661 } else {
662 /* Shift Mode character */
663 bp = bin_append_posn(1014, 10, binary, bp); /* shift indicator */
664 bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print);
665 }
666
667 sp++;
668 break;
669
670 case GM_UPPER:
671 shift = 1;
672 if (z_isupper(ddata[sp])) {
673 shift = 0;
674 } else if (ddata[sp] == ' ') {
675 shift = 0;
676 }
677
678 if (shift == 0) {
679 /* Upper Case character */
680 glyph = posn(EUROPIUM_UPR, (const char) ddata[sp]);
681 if (debug_print) {
682 printf("[%d] ", (int) glyph);
683 }
684
685 bp = bin_append_posn(glyph, 5, binary, bp);
686 } else {
687 /* Shift Mode character */
688 bp = bin_append_posn(125, 7, binary, bp); /* shift indicator */
689 bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print);
690 }
691
692 sp++;
693 break;
694
695 case GM_LOWER:
696 shift = 1;
697 if (z_islower(ddata[sp])) {
698 shift = 0;
699 } else if (ddata[sp] == ' ') {
700 shift = 0;
701 }
702
703 if (shift == 0) {
704 /* Lower Case character */
705 glyph = posn(EUROPIUM_LWR, (const char) ddata[sp]);
706 if (debug_print) {
707 printf("[%d] ", (int) glyph);
708 }
709
710 bp = bin_append_posn(glyph, 5, binary, bp);
711 } else {
712 /* Shift Mode character */
713 bp = bin_append_posn(125, 7, binary, bp); /* shift indicator */
714 bp = gm_add_shift_char(binary, bp, ddata[sp], debug_print);
715 }
716
717 sp++;
718 break;
719 }
720 if (bp > 9191) {
721 return ZINT_ERROR_TOO_LONG;
722 }
723
724 } while (sp < length);
725
726 if (current_mode == GM_NUMBER) {
727 /* add numeric block padding value */
728 switch (p) {
729 case 1: binary[number_pad_posn] = '1';
730 binary[number_pad_posn + 1] = '0';
731 break; /* 2 pad digits */
732 case 2: binary[number_pad_posn] = '0';
733 binary[number_pad_posn + 1] = '1';
734 break; /* 1 pad digit */
735 case 3: binary[number_pad_posn] = '0';
736 binary[number_pad_posn + 1] = '0';
737 break; /* 0 pad digits */
738 }
739 }
740
741 if (current_mode == GM_BYTE) {
742 /* Add byte block length indicator */
743 gm_add_byte_count(binary, byte_count_posn, byte_count);
744 }
745
746 /* Add "end of data" character */
747 switch (current_mode) {
748 case GM_CHINESE: bp = bin_append_posn(8160, 13, binary, bp);
749 break;
750 case GM_NUMBER: bp = bin_append_posn(1018, 10, binary, bp);
751 break;
752 case GM_LOWER:
753 case GM_UPPER: bp = bin_append_posn(27, 5, binary, bp);
754 break;
755 case GM_MIXED: bp = bin_append_posn(1008, 10, binary, bp);
756 break;
757 case GM_BYTE: bp = bin_append_posn(0, 4, binary, bp);
758 break;
759 }
760
761 if (bp > 9191) {
762 return ZINT_ERROR_TOO_LONG;
763 }
764
765 *p_bp = bp;
766
767 if (debug_print) {
768 printf("\nBinary (%d): %.*s\n", bp, bp, binary);
769 }
770
771 return 0;
772 }
773
774 static int gm_encode_segs(unsigned int ddata[], const struct zint_seg segs[], const int seg_count, char binary[],
775 const int reader, const struct zint_structapp *p_structapp, int *p_bin_len, const int debug_print) {
776 int i;
777 unsigned int *dd = ddata;
778 int bp = 0;
779 int p;
780
781 if (reader && (!p_structapp || p_structapp->index == 1)) { /* Appears only in 1st symbol if Structured Append */
782 bp = bin_append_posn(10, 4, binary, bp); /* FNC3 - Reader Initialisation */
783 }
784
785 if (p_structapp) {
786 bp = bin_append_posn(9, 4, binary, bp); /* FNC2 - Structured Append */
787 bp = bin_append_posn(to_int((const unsigned char *) p_structapp->id, (int) strlen(p_structapp->id)), 8,
788 binary, bp); /* File signature */
789 bp = bin_append_posn(p_structapp->count - 1, 4, binary, bp);
790 bp = bin_append_posn(p_structapp->index - 1, 4, binary, bp);
791 }
792
793 for (i = 0; i < seg_count; i++) {
794 int error_number = gm_encode(dd, segs[i].length, binary, segs[i].eci, &bp, debug_print);
795 if (error_number != 0) {
796 return error_number;
797 }
798 dd += segs[i].length;
799 }
800
801 /* Add padding bits if required */
802 p = 7 - (bp % 7);
803 if (p % 7) {
804 bp = bin_append_posn(0, p, binary, bp);
805 }
806 /* Note bit-padding can't tip `bp` over max 9191 (1313 * 7) */
807
808 if (debug_print) {
809 printf("\nBinary (%d): %.*s\n", bp, bp, binary);
810 }
811
812 *p_bin_len = bp;
813
814 return 0;
815 }
816
817 static void gm_add_ecc(const char binary[], const int data_posn, const int layers, const int ecc_level,
818 unsigned char word[]) {
819 int data_cw, i, j, wp, p;
820 int n1, b1, n2, b2, e1, b3, e2;
821 int block_size, ecc_size;
822 unsigned char data[1320], block[130];
823 unsigned char data_block[115], ecc_block[70];
824 rs_t rs;
825
826 data_cw = gm_data_codewords[((layers - 1) * 5) + (ecc_level - 1)];
827
828 for (i = 0; i < 1320; i++) {
829 data[i] = 0;
830 }
831
832 /* Convert from binary stream to 7-bit codewords */
833 for (i = 0; i < data_posn; i++) {
834 for (p = 0; p < 7; p++) {
835 if (binary[i * 7 + p] == '1') {
836 data[i] += (0x40 >> p);
837 }
838 }
839 }
840
841 /* Add padding codewords */
842 data[data_posn] = 0x00;
843 for (i = (data_posn + 1); i < data_cw; i++) {
844 if (i & 1) {
845 data[i] = 0x7e;
846 } else {
847 data[i] = 0x00;
848 }
849 }
850
851 /* Get block sizes */
852 n1 = gm_n1[(layers - 1)];
853 b1 = gm_b1[(layers - 1)];
854 n2 = n1 - 1;
855 b2 = gm_b2[(layers - 1)];
856 e1 = gm_ebeb[((layers - 1) * 20) + ((ecc_level - 1) * 4)];
857 b3 = gm_ebeb[((layers - 1) * 20) + ((ecc_level - 1) * 4) + 1];
858 e2 = gm_ebeb[((layers - 1) * 20) + ((ecc_level - 1) * 4) + 2];
859
860 rs_init_gf(&rs, 0x89);
861
862 /* Split the data into blocks */
863 wp = 0;
864 for (i = 0; i < (b1 + b2); i++) {
865 int data_size;
866 if (i < b1) {
867 block_size = n1;
868 } else {
869 block_size = n2;
870 }
871 if (i < b3) {
872 ecc_size = e1;
873 } else {
874 ecc_size = e2;
875 }
876 data_size = block_size - ecc_size;
877
878 /* printf("block %d/%d: data %d / ecc %d\n", i + 1, (b1 + b2), data_size, ecc_size);*/
879
880 for (j = 0; j < data_size; j++) {
881 data_block[j] = data[wp];
882 wp++;
883 }
884
885 /* Calculate ECC data for this block */
886 rs_init_code(&rs, ecc_size, 1);
887 rs_encode(&rs, data_size, data_block, ecc_block);
888
889 /* Add error correction data */
890 for (j = 0; j < data_size; j++) {
891 block[j] = data_block[j];
892 }
893 for (j = 0; j < ecc_size; j++) {
894 block[j + data_size] = ecc_block[j];
895 }
896
897 for (j = 0; j < n2; j++) {
898 word[((b1 + b2) * j) + i] = block[j];
899 }
900 if (block_size == n1) {
901 word[((b1 + b2) * (n1 - 1)) + i] = block[(n1 - 1)];
902 }
903 }
904 }
905
906 static void gm_place_macromodule(char grid[], int x, int y, int word1, int word2, int size) {
907 int i, j;
908
909 i = (x * 6) + 1;
910 j = (y * 6) + 1;
911
912 if (word2 & 0x40) {
913 grid[(j * size) + i + 2] = '1';
914 }
915 if (word2 & 0x20) {
916 grid[(j * size) + i + 3] = '1';
917 }
918 if (word2 & 0x10) {
919 grid[((j + 1) * size) + i] = '1';
920 }
921 if (word2 & 0x08) {
922 grid[((j + 1) * size) + i + 1] = '1';
923 }
924 if (word2 & 0x04) {
925 grid[((j + 1) * size) + i + 2] = '1';
926 }
927 if (word2 & 0x02) {
928 grid[((j + 1) * size) + i + 3] = '1';
929 }
930 if (word2 & 0x01) {
931 grid[((j + 2) * size) + i] = '1';
932 }
933 if (word1 & 0x40) {
934 grid[((j + 2) * size) + i + 1] = '1';
935 }
936 if (word1 & 0x20) {
937 grid[((j + 2) * size) + i + 2] = '1';
938 }
939 if (word1 & 0x10) {
940 grid[((j + 2) * size) + i + 3] = '1';
941 }
942 if (word1 & 0x08) {
943 grid[((j + 3) * size) + i] = '1';
944 }
945 if (word1 & 0x04) {
946 grid[((j + 3) * size) + i + 1] = '1';
947 }
948 if (word1 & 0x02) {
949 grid[((j + 3) * size) + i + 2] = '1';
950 }
951 if (word1 & 0x01) {
952 grid[((j + 3) * size) + i + 3] = '1';
953 }
954 }
955
956 static void gm_place_data_in_grid(unsigned char word[], char grid[], int modules, int size) {
957 int x, y, macromodule, offset;
958
959 offset = 13 - ((modules - 1) / 2);
960 for (y = 0; y < modules; y++) {
961 for (x = 0; x < modules; x++) {
962 macromodule = gm_macro_matrix[((y + offset) * 27) + (x + offset)];
963 gm_place_macromodule(grid, x, y, word[macromodule * 2], word[(macromodule * 2) + 1], size);
964 }
965 }
966 }
967
968 /* Place the layer ID into each macromodule */
969 static void gm_place_layer_id(char *grid, int size, int layers, int modules, int ecc_level) {
970 int i, j, layer, start, stop;
971 int *layerid = (int *) z_alloca(sizeof(int) * (layers + 1));
972 int *id = (int *) z_alloca(sizeof(int) * (modules * modules));
973
974 /* Calculate Layer IDs */
975 for (i = 0; i <= layers; i++) {
976 if (ecc_level == 1) {
977 layerid[i] = 3 - (i % 4);
978 } else {
979 layerid[i] = (i + 5 - ecc_level) % 4;
980 }
981 }
982
983 for (i = 0; i < modules; i++) {
984 for (j = 0; j < modules; j++) {
985 id[(i * modules) + j] = 0;
986 }
987 }
988
989 /* Calculate which value goes in each macromodule */
990 start = modules / 2;
991 stop = modules / 2;
992 for (layer = 0; layer <= layers; layer++) {
993 for (i = start; i <= stop; i++) {
994 id[(start * modules) + i] = layerid[layer];
995 id[(i * modules) + start] = layerid[layer];
996 id[((modules - start - 1) * modules) + i] = layerid[layer];
997 id[(i * modules) + (modules - start - 1)] = layerid[layer];
998 }
999 start--;
1000 stop++;
1001 }
1002
1003 /* Place the data in the grid */
1004 for (i = 0; i < modules; i++) {
1005 for (j = 0; j < modules; j++) {
1006 if (id[(i * modules) + j] & 0x02) {
1007 grid[(((i * 6) + 1) * size) + (j * 6) + 1] = '1';
1008 }
1009 if (id[(i * modules) + j] & 0x01) {
1010 grid[(((i * 6) + 1) * size) + (j * 6) + 2] = '1';
1011 }
1012 }
1013 }
1014 }
1015
1016 INTERNAL int gridmatrix(struct zint_symbol *symbol, struct zint_seg segs[], const int seg_count) {
1017 int warn_number = 0;
1018 int size, modules, error_number;
1019 int auto_layers, min_layers, layers, auto_ecc_level, min_ecc_level, ecc_level;
1020 int x, y, i;
1021 int full_multibyte;
1022 char binary[9300];
1023 int data_cw, input_latch = 0;
1024 unsigned char word[1460] = {0};
1025 int data_max, reader = 0;
1026 const struct zint_structapp *p_structapp = NULL;
1027 int size_squared;
1028 int bin_len;
1029 const int debug_print = symbol->debug & ZINT_DEBUG_PRINT;
1030 const int eci_length_segs = get_eci_length_segs(segs, seg_count);
1031 struct zint_seg *local_segs = (struct zint_seg *) z_alloca(sizeof(struct zint_seg) * seg_count);
1032 unsigned int *ddata = (unsigned int *) z_alloca(sizeof(unsigned int) * eci_length_segs);
1033 char *grid;
1034
1035 segs_cpy(symbol, segs, seg_count, local_segs); /* Shallow copy (needed to set default ECIs & protect lengths) */
1036
1037 /* If ZINT_FULL_MULTIBYTE set use Hanzi mode in DATA_MODE or for non-GB 2312 in UNICODE_MODE */
1038 full_multibyte = (symbol->option_3 & 0xFF) == ZINT_FULL_MULTIBYTE;
1039
1040 if ((symbol->input_mode & 0x07) == DATA_MODE) {
1041 gb2312_cpy_segs(local_segs, seg_count, ddata, full_multibyte);
1042 } else {
1043 unsigned int *dd = ddata;
1044 for (i = 0; i < seg_count; i++) {
1045 int done = 0;
1046 if (local_segs[i].eci != 0 && local_segs[i].eci != 29) { /* Unless default or ECI 29 (GB 2312) */
1047 /* Try other conversions */
1048 error_number = gb2312_utf8_to_eci(local_segs[i].eci, local_segs[i].source, &local_segs[i].length,
1049 dd, full_multibyte);
1050 if (error_number == 0) {
1051 done = 1;
1052 } else {
1053 return errtxtf(error_number, symbol, 535, "Invalid character in input for ECI '%d'",
1054 local_segs[i].eci);
1055 }
1056 }
1057 if (!done) {
1058 /* Try GB 2312 (EUC-CN) */
1059 error_number = gb2312_utf8(symbol, local_segs[i].source, &local_segs[i].length, dd);
1060 if (error_number != 0) {
1061 return error_number;
1062 }
1063 }
1064 dd += local_segs[i].length;
1065 }
1066 }
1067
1068 if (symbol->output_options & READER_INIT) reader = 1;
1069
1070 if (symbol->structapp.count) {
1071 if (symbol->structapp.count < 2 || symbol->structapp.count > 16) {
1072 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 536,
1073 "Structured Append count '%d' out of range (2 to 16)", symbol->structapp.count);
1074 }
1075 if (symbol->structapp.index < 1 || symbol->structapp.index > symbol->structapp.count) {
1076 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 537,
1077 "Structured Append index '%1$d' out of range (1 to count %2$d)",
1078 symbol->structapp.index, symbol->structapp.count);
1079 }
1080 if (symbol->structapp.id[0]) {
1081 int id, id_len;
1082
1083 for (id_len = 1; id_len < 4 && symbol->structapp.id[id_len]; id_len++);
1084
1085 if (id_len > 3) { /* 255 (8 bits) */
1086 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 538,
1087 "Structured Append ID length %d too long (3 digit maximum)", id_len);
1088 }
1089
1090 id = to_int((const unsigned char *) symbol->structapp.id, id_len);
1091 if (id == -1) {
1092 return errtxt(ZINT_ERROR_INVALID_OPTION, symbol, 539, "Invalid Structured Append ID (digits only)");
1093 }
1094 if (id > 255) {
1095 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 530,
1096 "Structured Append ID value '%d' out of range (0 to 255)", id);
1097 }
1098 }
1099 p_structapp = &symbol->structapp;
1100 }
1101
1102 if (symbol->eci > 811799) {
1103 return errtxtf(ZINT_ERROR_INVALID_OPTION, symbol, 533, "ECI code '%d' out of range (0 to 811799)",
1104 symbol->eci);
1105 }
1106
1107 error_number = gm_encode_segs(ddata, local_segs, seg_count, binary, reader, p_structapp, &bin_len, debug_print);
1108 if (error_number != 0) {
1109 return errtxt(error_number, symbol, 531, "Input too long, requires too many codewords (maximum 1313)");
1110 }
1111
1112 /* Determine the size of the symbol */
1113 data_cw = bin_len / 7; /* Binary length always a multiple of 7 */
1114
1115 auto_layers = 13;
1116 for (i = 12; i > 0; i--) {
1117 if (gm_recommend_cw[(i - 1)] >= data_cw) {
1118 auto_layers = i;
1119 }
1120 }
1121 min_layers = 13;
1122 for (i = 12; i > 0; i--) {
1123 if (gm_max_cw[(i - 1)] >= data_cw) {
1124 min_layers = i;
1125 }
1126 }
1127 layers = auto_layers;
1128
1129 if ((symbol->option_2 >= 1) && (symbol->option_2 <= 13)) {
1130 input_latch = 1;
1131 if (symbol->option_2 >= min_layers) {
1132 layers = symbol->option_2;
1133 } else {
1134 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 534,
1135 "Input too long for Version %1$d, requires %2$d codewords (maximum %3$d)",
1136 symbol->option_2, data_cw, gm_max_cw[symbol->option_2 - 1]);
1137 }
1138 }
1139
1140 auto_ecc_level = 3;
1141 if (layers == 1) {
1142 auto_ecc_level = 5;
1143 } else if ((layers == 2) || (layers == 3)) {
1144 auto_ecc_level = 4;
1145 }
1146 ecc_level = auto_ecc_level;
1147
1148 min_ecc_level = 1;
1149 if (layers == 1) {
1150 min_ecc_level = 4;
1151 } else if (layers == 2) {
1152 min_ecc_level = 2;
1153 }
1154
1155 if ((symbol->option_1 >= 1) && (symbol->option_1 <= 5)) {
1156 if (symbol->option_1 >= min_ecc_level) {
1157 ecc_level = symbol->option_1;
1158 } else {
1159 ecc_level = min_ecc_level;
1160 }
1161 }
1162 if (data_cw > gm_data_codewords[(5 * (layers - 1)) + (ecc_level - 1)]) {
1163 /* If layers user-specified (option_2), try reducing ECC level first */
1164 if (input_latch && ecc_level > min_ecc_level) {
1165 do {
1166 ecc_level--;
1167 } while ((data_cw > gm_data_codewords[(5 * (layers - 1)) + (ecc_level - 1)])
1168 && (ecc_level > min_ecc_level));
1169 }
1170 while (data_cw > gm_data_codewords[(5 * (layers - 1)) + (ecc_level - 1)] && (layers < 13)) {
1171 layers++;
1172 }
1173 /* ECC min level 1 for layers > 2 */
1174 while (data_cw > gm_data_codewords[(5 * (layers - 1)) + (ecc_level - 1)] && ecc_level > 1) {
1175 ecc_level--;
1176 }
1177 }
1178
1179 data_max = 1313;
1180 switch (ecc_level) {
1181 case 2: data_max = 1167;
1182 break;
1183 case 3: data_max = 1021;
1184 break;
1185 case 4: data_max = 875;
1186 break;
1187 case 5: data_max = 729;
1188 break;
1189 }
1190
1191 if (data_cw > data_max) {
1192 return errtxtf(ZINT_ERROR_TOO_LONG, symbol, 532,
1193 "Input too long for ECC level %1$d, requires %2$d codewords (maximum %3$d)",
1194 ecc_level, data_cw, data_max);
1195 }
1196 if (debug_print) {
1197 printf("Layers: %d, ECC level: %d, Data Codewords: %d\n", layers, ecc_level, data_cw);
1198 }
1199
1200 gm_add_ecc(binary, data_cw, layers, ecc_level, word);
1201 #ifdef ZINT_TEST
1202 if (symbol->debug & ZINT_DEBUG_TEST) debug_test_codeword_dump(symbol, word, data_cw);
1203 #endif
1204 size = 6 + (layers * 12);
1205 modules = 1 + (layers * 2);
1206 size_squared = size * size;
1207
1208 grid = (char *) z_alloca(size_squared);
1209 memset(grid, '0', size_squared);
1210
1211 gm_place_data_in_grid(word, grid, modules, size);
1212 gm_place_layer_id(grid, size, layers, modules, ecc_level);
1213
1214 /* Add macromodule frames */
1215 for (x = 0; x < modules; x++) {
1216 int dark = 1 - (x & 1);
1217 for (y = 0; y < modules; y++) {
1218 if (dark == 1) {
1219 for (i = 0; i < 5; i++) {
1220 grid[((y * 6) * size) + (x * 6) + i] = '1';
1221 grid[(((y * 6) + 5) * size) + (x * 6) + i] = '1';
1222 grid[(((y * 6) + i) * size) + (x * 6)] = '1';
1223 grid[(((y * 6) + i) * size) + (x * 6) + 5] = '1';
1224 }
1225 grid[(((y * 6) + 5) * size) + (x * 6) + 5] = '1';
1226 dark = 0;
1227 } else {
1228 dark = 1;
1229 }
1230 }
1231 }
1232
1233 /* Copy values to symbol */
1234 symbol->width = size;
1235 symbol->rows = size;
1236
1237 for (x = 0; x < size; x++) {
1238 for (y = 0; y < size; y++) {
1239 if (grid[(y * size) + x] == '1') {
1240 set_module(symbol, y, x);
1241 }
1242 }
1243 symbol->row_height[x] = 1;
1244 }
1245 symbol->height = size;
1246
1247 return warn_number;
1248 }
1249
1250 /* vim: set ts=4 sw=4 et : */