1 /* dmatrix.c Handles Data Matrix ECC 200 symbols */
2
3 /*
4 libzint - the open source barcode library
5 Copyright (C) 2009-2017 Robin Stuart <rstuart114@gmail.com>
6
7 developed from and including some functions from:
8 IEC16022 bar code generation
9 Adrian Kennard, Andrews & Arnold Ltd
10 with help from Cliff Hones on the RS coding
11
12 (c) 2004 Adrian Kennard, Andrews & Arnold Ltd
13 (c) 2006 Stefan Schmidt <stefan@datenfreihafen.org>
14
15 Redistribution and use in source and binary forms, with or without
16 modification, are permitted provided that the following conditions
17 are met:
18
19 1. Redistributions of source code must retain the above copyright
20 notice, this list of conditions and the following disclaimer.
21 2. Redistributions in binary form must reproduce the above copyright
22 notice, this list of conditions and the following disclaimer in the
23 documentation and/or other materials provided with the distribution.
24 3. Neither the name of the project nor the names of its contributors
25 may be used to endorse or promote products derived from this software
26 without specific prior written permission.
27
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
29 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
32 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 SUCH DAMAGE.
39 */
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <ctype.h>
44 #include <string.h>
45 #include <assert.h>
46 #include <math.h>
47 #ifdef _MSC_VER
48 #include <malloc.h>
49 /* ceilf (C99) not before MSVC++2013 (C++ 12.0) */
50 #if _MSC_VER < 1800
51 #define ceilf ceil
52 #endif
53 #endif
54 #include "reedsol.h"
55 #include "common.h"
56 #include "dmatrix.h"
57
58 /* Annex M placement alorithm low level */
ecc200placementbit(int * array,const int NR,const int NC,int r,int c,const int p,const char b)59 static void ecc200placementbit(int *array, const int NR, const int NC, int r, int c, const int p, const char b) {
60 if (r < 0) {
61 r += NR;
62 c += 4 - ((NR + 4) % 8);
63 }
64 if (c < 0) {
65 c += NC;
66 r += 4 - ((NC + 4) % 8);
67 }
68 // Necessary for 26x32,26x40,26x48,36x120,36x144,72x120,72x144
69 if (r >= NR) {
70 #ifdef DEBUG
71 fprintf(stderr, "r >= NR:%i,%i at r=%i->", p, b, r);
72 #endif
73 r -= NR;
74 #ifdef DEBUG
75 fprintf(stderr, "%i,c=%i\n", r, c);
76 #endif
77 }
78 #ifdef DEBUG
79 if (0 != array[r * NC + c]) {
80 int a = array[r * NC + c];
81 fprintf(stderr, "Double:%i,%i->%i,%i at r=%i,c=%i\n", a >> 3, a & 7, p, b, r, c);
82 return;
83 }
84 #endif
85 // Check index limits
86 assert(r < NR);
87 assert(c < NC);
88 // Check double-assignment
89 assert(0 == array[r * NC + c]);
90 array[r * NC + c] = (p << 3) + b;
91 }
92
ecc200placementblock(int * array,const int NR,const int NC,const int r,const int c,const int p)93 static void ecc200placementblock(int *array, const int NR, const int NC, const int r,
94 const int c, const int p) {
95 ecc200placementbit(array, NR, NC, r - 2, c - 2, p, 7);
96 ecc200placementbit(array, NR, NC, r - 2, c - 1, p, 6);
97 ecc200placementbit(array, NR, NC, r - 1, c - 2, p, 5);
98 ecc200placementbit(array, NR, NC, r - 1, c - 1, p, 4);
99 ecc200placementbit(array, NR, NC, r - 1, c - 0, p, 3);
100 ecc200placementbit(array, NR, NC, r - 0, c - 2, p, 2);
101 ecc200placementbit(array, NR, NC, r - 0, c - 1, p, 1);
102 ecc200placementbit(array, NR, NC, r - 0, c - 0, p, 0);
103 }
104
ecc200placementcornerA(int * array,const int NR,const int NC,const int p)105 static void ecc200placementcornerA(int *array, const int NR, const int NC, const int p) {
106 ecc200placementbit(array, NR, NC, NR - 1, 0, p, 7);
107 ecc200placementbit(array, NR, NC, NR - 1, 1, p, 6);
108 ecc200placementbit(array, NR, NC, NR - 1, 2, p, 5);
109 ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
110 ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
111 ecc200placementbit(array, NR, NC, 1, NC - 1, p, 2);
112 ecc200placementbit(array, NR, NC, 2, NC - 1, p, 1);
113 ecc200placementbit(array, NR, NC, 3, NC - 1, p, 0);
114 }
115
ecc200placementcornerB(int * array,const int NR,const int NC,const int p)116 static void ecc200placementcornerB(int *array, const int NR, const int NC, const int p) {
117 ecc200placementbit(array, NR, NC, NR - 3, 0, p, 7);
118 ecc200placementbit(array, NR, NC, NR - 2, 0, p, 6);
119 ecc200placementbit(array, NR, NC, NR - 1, 0, p, 5);
120 ecc200placementbit(array, NR, NC, 0, NC - 4, p, 4);
121 ecc200placementbit(array, NR, NC, 0, NC - 3, p, 3);
122 ecc200placementbit(array, NR, NC, 0, NC - 2, p, 2);
123 ecc200placementbit(array, NR, NC, 0, NC - 1, p, 1);
124 ecc200placementbit(array, NR, NC, 1, NC - 1, p, 0);
125 }
126
ecc200placementcornerC(int * array,const int NR,const int NC,const int p)127 static void ecc200placementcornerC(int *array, const int NR, const int NC, const int p) {
128 ecc200placementbit(array, NR, NC, NR - 3, 0, p, 7);
129 ecc200placementbit(array, NR, NC, NR - 2, 0, p, 6);
130 ecc200placementbit(array, NR, NC, NR - 1, 0, p, 5);
131 ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
132 ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
133 ecc200placementbit(array, NR, NC, 1, NC - 1, p, 2);
134 ecc200placementbit(array, NR, NC, 2, NC - 1, p, 1);
135 ecc200placementbit(array, NR, NC, 3, NC - 1, p, 0);
136 }
137
ecc200placementcornerD(int * array,const int NR,const int NC,const int p)138 static void ecc200placementcornerD(int *array, const int NR, const int NC, const int p) {
139 ecc200placementbit(array, NR, NC, NR - 1, 0, p, 7);
140 ecc200placementbit(array, NR, NC, NR - 1, NC - 1, p, 6);
141 ecc200placementbit(array, NR, NC, 0, NC - 3, p, 5);
142 ecc200placementbit(array, NR, NC, 0, NC - 2, p, 4);
143 ecc200placementbit(array, NR, NC, 0, NC - 1, p, 3);
144 ecc200placementbit(array, NR, NC, 1, NC - 3, p, 2);
145 ecc200placementbit(array, NR, NC, 1, NC - 2, p, 1);
146 ecc200placementbit(array, NR, NC, 1, NC - 1, p, 0);
147 }
148
149 /* Annex M placement alorithm main function */
ecc200placement(int * array,const int NR,const int NC)150 static void ecc200placement(int *array, const int NR, const int NC) {
151 int r, c, p;
152 // invalidate
153 for (r = 0; r < NR; r++)
154 for (c = 0; c < NC; c++)
155 array[r * NC + c] = 0;
156 // start
157 p = 1;
158 r = 4;
159 c = 0;
160 do {
161 // check corner
162 if (r == NR && !c)
163 ecc200placementcornerA(array, NR, NC, p++);
164 if (r == NR - 2 && !c && NC % 4)
165 ecc200placementcornerB(array, NR, NC, p++);
166 if (r == NR - 2 && !c && (NC % 8) == 4)
167 ecc200placementcornerC(array, NR, NC, p++);
168 if (r == NR + 4 && c == 2 && !(NC % 8))
169 ecc200placementcornerD(array, NR, NC, p++);
170 // up/right
171 do {
172 if (r < NR && c >= 0 && !array[r * NC + c])
173 ecc200placementblock(array, NR, NC, r, c, p++);
174 r -= 2;
175 c += 2;
176 } while (r >= 0 && c < NC);
177 r++;
178 c += 3;
179 // down/left
180 do {
181 if (r >= 0 && c < NC && !array[r * NC + c])
182 ecc200placementblock(array, NR, NC, r, c, p++);
183 r += 2;
184 c -= 2;
185 } while (r < NR && c >= 0);
186 r += 3;
187 c++;
188 } while (r < NR || c < NC);
189 // unfilled corner
190 if (!array[NR * NC - 1])
191 array[NR * NC - 1] = array[NR * NC - NC - 2] = 1;
192 }
193
194 /* calculate and append ecc code, and if necessary interleave */
ecc200(unsigned char * binary,const int bytes,const int datablock,const int rsblock,const int skew)195 static void ecc200(unsigned char *binary, const int bytes, const int datablock, const int rsblock, const int skew) {
196 int blocks = (bytes + 2) / datablock, b;
197 int n, p;
198 rs_init_gf(0x12d);
199 rs_init_code(rsblock, 1);
200 for (b = 0; b < blocks; b++) {
201 unsigned char buf[256], ecc[256];
202 p = 0;
203 for (n = b; n < bytes; n += blocks)
204 buf[p++] = binary[n];
205 rs_encode(p, buf, ecc);
206 p = rsblock - 1; // comes back reversed
207 for (n = b; n < rsblock * blocks; n += blocks) {
208 if (skew) {
209 /* Rotate ecc data to make 144x144 size symbols acceptable */
210 /* See http://groups.google.com/group/postscriptbarcode/msg/5ae8fda7757477da */
211 if (b < 8) {
212 binary[bytes + n + 2] = ecc[p--];
213 } else {
214 binary[bytes + n - 8] = ecc[p--];
215 }
216 } else {
217 binary[bytes + n] = ecc[p--];
218 }
219 }
220 }
221 rs_free();
222 }
223
224 /* Return true (1) if a character is valid in X12 set */
isX12(const int source)225 static int isX12(const int source) {
226
227 switch(source) {
228 case 13: // CR
229 case 42: // *
230 case 62: // >
231 case 32: // space
232 return 1;
233 }
234
235 if ((source >= '0') && (source <= '9')) {
236 return 1;
237 }
238 if ((source >= 'A') && (source <= 'Z')) {
239 return 1;
240 }
241
242 return 0;
243 }
244
245 /* Insert a character into the middle of a string at position posn */
dminsert(char binary_string[],const int posn,const char newbit)246 static void dminsert(char binary_string[], const int posn, const char newbit) {
247 int i, end;
248
249 end = (int) strlen(binary_string);
250 for (i = end + 1; i > posn; i--) {
251 binary_string[i] = binary_string[i - 1];
252 }
253 binary_string[posn] = newbit;
254 }
255
insert_value(unsigned char binary_stream[],const int posn,const int streamlen,const int newbit)256 static void insert_value(unsigned char binary_stream[], const int posn, const int streamlen, const int newbit) {
257 int i;
258
259 for(i = (int)streamlen; i > posn; i--) {
260 binary_stream[i] = binary_stream[i - 1];
261 }
262 binary_stream[posn] = (unsigned char) newbit;
263 }
264
p_r_6_2_1(const unsigned char inputData[],const size_t position,const size_t sourcelen)265 static int p_r_6_2_1(const unsigned char inputData[], const size_t position, const size_t sourcelen) {
266 /* Annex P section (r)(6)(ii)(I)
267 "If one of the three X12 terminator/separator characters first
268 occurs in the yet to be processed data before a non-X12 character..."
269 */
270
271 size_t i;
272 size_t nonX12Position = 0;
273 size_t specialX12Position = 0;
274 int retval = 0;
275
276 for (i = position; i < sourcelen; i++) {
277 if (nonX12Position == 0) {
278 if (isX12(inputData[i]) != 1) {
279 nonX12Position = i;
280 }
281 }
282
283 if (specialX12Position == 0) {
284 if ((inputData[i] == (char) 13) ||
285 (inputData[i] == '*') ||
286 (inputData[i] == '>')) {
287 specialX12Position = i;
288 }
289 }
290 }
291
292 if ((nonX12Position != 0) && (specialX12Position != 0)) {
293 if (specialX12Position < nonX12Position) {
294 retval = 1;
295 }
296 }
297
298 return retval;
299 }
300
301 /* 'look ahead test' from Annex P */
look_ahead_test(const unsigned char inputData[],const size_t sourcelen,const size_t position,const int current_mode,const int gs1)302 static int look_ahead_test(const unsigned char inputData[], const size_t sourcelen, const size_t position, const int current_mode, const int gs1) {
303 float ascii_count, c40_count, text_count, x12_count, edf_count, b256_count, best_count;
304 const float stiction = (1.0F / 24.0F); // smallest change to act on, to get around floating point inaccuracies
305 int best_scheme;
306 size_t sp;
307
308 best_scheme = DM_NULL;
309
310 /* step (j) */
311 if (current_mode == DM_ASCII) {
312 ascii_count = 0.0F;
313 c40_count = 1.0F;
314 text_count = 1.0F;
315 x12_count = 1.0F;
316 edf_count = 1.0F;
317 b256_count = 1.25F;
318 } else {
319 ascii_count = 1.0F;
320 c40_count = 2.0F;
321 text_count = 2.0F;
322 x12_count = 2.0F;
323 edf_count = 2.0F;
324 b256_count = 2.25F;
325 }
326
327 switch (current_mode) {
328 case DM_C40: c40_count = 0.0F;
329 break;
330 case DM_TEXT: text_count = 0.0F;
331 break;
332 case DM_X12: x12_count = 0.0F;
333 break;
334 case DM_EDIFACT: edf_count = 0.0F;
335 break;
336 case DM_BASE256: b256_count = 0.0F;
337 break;
338 }
339
340 sp = position;
341
342 do {
343 if (sp == sourcelen) {
344 /* At the end of data ... step (k) */
345 ascii_count = ceilf(ascii_count);
346 b256_count = ceilf(b256_count);
347 edf_count = ceilf(edf_count);
348 text_count = ceilf(text_count);
349 x12_count = ceilf(x12_count);
350 c40_count = ceilf(c40_count);
351
352 best_count = c40_count;
353 best_scheme = DM_C40; // (k)(7)
354
355 if (x12_count < (best_count - stiction)) {
356 best_count = x12_count;
357 best_scheme = DM_X12; // (k)(6)
358 }
359
360 if (text_count < (best_count - stiction)) {
361 best_count = text_count;
362 best_scheme = DM_TEXT; // (k)(5)
363 }
364
365 if (edf_count < (best_count - stiction)) {
366 best_count = edf_count;
367 best_scheme = DM_EDIFACT; // (k)(4)
368 }
369
370 if (b256_count < (best_count - stiction)) {
371 best_count = b256_count;
372 best_scheme = DM_BASE256; // (k)(3)
373 }
374
375 if (ascii_count <= (best_count + stiction)) {
376 best_scheme = DM_ASCII; // (k)(2)
377 }
378 } else {
379
380 /* ascii ... step (l) */
381 if ((inputData[sp] >= '0') && (inputData[sp] <= '9')) {
382 ascii_count += 0.5F; // (l)(1)
383 } else {
384 if (inputData[sp] > 127) {
385 ascii_count = ceilf(ascii_count) + 2.0F; // (l)(2)
386 } else {
387 ascii_count = ceilf(ascii_count) + 1.0F; // (l)(3)
388 }
389 }
390
391 /* c40 ... step (m) */
392 if ((inputData[sp] == ' ') ||
393 (((inputData[sp] >= '0') && (inputData[sp] <= '9')) ||
394 ((inputData[sp] >= 'A') && (inputData[sp] <= 'Z')))) {
395 c40_count += (2.0F / 3.0F); // (m)(1)
396 } else {
397 if (inputData[sp] > 127) {
398 c40_count += (8.0F / 3.0F); // (m)(2)
399 } else {
400 c40_count += (4.0F / 3.0F); // (m)(3)
401 }
402 }
403
404 /* text ... step (n) */
405 if ((inputData[sp] == ' ') ||
406 (((inputData[sp] >= '0') && (inputData[sp] <= '9')) ||
407 ((inputData[sp] >= 'a') && (inputData[sp] <= 'z')))) {
408 text_count += (2.0F / 3.0F); // (n)(1)
409 } else {
410 if (inputData[sp] > 127) {
411 text_count += (8.0F / 3.0F); // (n)(2)
412 } else {
413 text_count += (4.0F / 3.0F); // (n)(3)
414 }
415 }
416
417 /* x12 ... step (o) */
418 if (isX12(inputData[sp])) {
419 x12_count += (2.0F / 3.0F); // (o)(1)
420 } else {
421 if (inputData[sp] > 127) {
422 x12_count += (13.0F / 3.0F); // (o)(2)
423 } else {
424 x12_count += (10.0F / 3.0F); // (o)(3)
425 }
426 }
427
428 /* edifact ... step (p) */
429 if ((inputData[sp] >= ' ') && (inputData[sp] <= '^')) {
430 edf_count += (3.0F / 4.0F); // (p)(1)
431 } else {
432 if (inputData[sp] > 127) {
433 edf_count += 17.0F; // (p)(2) > Value changed from ISO
434 } else {
435 edf_count += 13.0F; // (p)(3) > Value changed from ISO
436 }
437 }
438 if ((gs1 == 1) && (inputData[sp] == '[')) {
439 edf_count += 13.0F; // > Value changed from ISO
440 }
441
442 /* base 256 ... step (q) */
443 if ((gs1 == 1) && (inputData[sp] == '[')) {
444 b256_count += 4.0F; // (q)(1)
445 } else {
446 b256_count += 1.0F; // (q)(2)
447 }
448 }
449
450
451 if (sp > (position + 3)) {
452 /* 4 data characters processed ... step (r) */
453
454 /* step (r)(6) */
455 if (((c40_count + 1.0F) < (ascii_count - stiction)) &&
456 ((c40_count + 1.0F) < (b256_count - stiction)) &&
457 ((c40_count + 1.0F) < (edf_count - stiction)) &&
458 ((c40_count + 1.0F) < (text_count - stiction))) {
459
460 if (c40_count < (x12_count - stiction)) {
461 best_scheme = DM_C40;
462 }
463
464 if ((c40_count >= (x12_count - stiction))
465 && (c40_count <= (x12_count + stiction))) {
466 if (p_r_6_2_1(inputData, sp, sourcelen) == 1) {
467 // Test (r)(6)(ii)(i)
468 best_scheme = DM_X12;
469 } else {
470 best_scheme = DM_C40;
471 }
472 }
473 }
474
475 /* step (r)(5) */
476 if (((x12_count + 1.0F) < (ascii_count - stiction)) &&
477 ((x12_count + 1.0F) < (b256_count - stiction)) &&
478 ((x12_count + 1.0F) < (edf_count - stiction)) &&
479 ((x12_count + 1.0F) < (text_count - stiction)) &&
480 ((x12_count + 1.0F) < (c40_count - stiction))) {
481 best_scheme = DM_X12;
482 }
483
484 /* step (r)(4) */
485 if (((text_count + 1.0F) < (ascii_count - stiction)) &&
486 ((text_count + 1.0F) < (b256_count - stiction)) &&
487 ((text_count + 1.0F) < (edf_count - stiction)) &&
488 ((text_count + 1.0F) < (x12_count - stiction)) &&
489 ((text_count + 1.0F) < (c40_count - stiction))) {
490 best_scheme = DM_TEXT;
491 }
492
493 /* step (r)(3) */
494 if (((edf_count + 1.0F) < (ascii_count - stiction)) &&
495 ((edf_count + 1.0F) < (b256_count - stiction)) &&
496 ((edf_count + 1.0F) < (text_count - stiction)) &&
497 ((edf_count + 1.0F) < (x12_count - stiction)) &&
498 ((edf_count + 1.0F) < (c40_count - stiction))) {
499 best_scheme = DM_EDIFACT;
500 }
501
502 /* step (r)(2) */
503 if (((b256_count + 1.0F) <= (ascii_count + stiction)) ||
504 (((b256_count + 1.0F) < (edf_count - stiction)) &&
505 ((b256_count + 1.0F) < (text_count - stiction)) &&
506 ((b256_count + 1.0F) < (x12_count - stiction)) &&
507 ((b256_count + 1.0F) < (c40_count - stiction)))) {
508 best_scheme = DM_BASE256;
509 }
510
511 /* step (r)(1) */
512 if (((ascii_count + 1.0F) <= (b256_count + stiction)) &&
513 ((ascii_count + 1.0F) <= (edf_count + stiction)) &&
514 ((ascii_count + 1.0F) <= (text_count + stiction)) &&
515 ((ascii_count + 1.0F) <= (x12_count + stiction)) &&
516 ((ascii_count + 1.0F) <= (c40_count + stiction))) {
517 best_scheme = DM_ASCII;
518 }
519 }
520
521 sp++;
522 } while (best_scheme == DM_NULL); // step (s)
523
524 return best_scheme;
525 }
526
527 /* Encodes data using ASCII, C40, Text, X12, EDIFACT or Base 256 modes as appropriate
528 Supports encoding FNC1 in supporting systems */
dm200encode(struct zint_symbol * symbol,const unsigned char source[],unsigned char target[],int * last_mode,size_t * length_p,int process_buffer[],int * process_p)529 static int dm200encode(struct zint_symbol *symbol, const unsigned char source[], unsigned char target[], int *last_mode, size_t *length_p, int process_buffer[], int *process_p) {
530
531 size_t sp;
532 int tp, i, gs1;
533 int current_mode, next_mode;
534 size_t inputlen = *length_p;
535 int debug = symbol->debug;
536 #ifndef _MSC_VER
537 char binary[2 * inputlen];
538 #else
539 char* binary = (char*) _alloca(2 * inputlen);
540 #endif
541
542 sp = 0;
543 tp = 0;
544 memset(process_buffer, 0, 8);
545 *process_p = 0;
546 strcpy(binary, "");
547
548 /* step (a) */
549 current_mode = DM_ASCII;
550 next_mode = DM_ASCII;
551
552 if (symbol->input_mode == GS1_MODE) {
553 gs1 = 1;
554 } else {
555 gs1 = 0;
556 }
557
558 if (gs1) {
559 target[tp] = 232;
560 tp++;
561 strcat(binary, " ");
562 if (debug) printf("FN1 ");
563 } /* FNC1 */
564
565 if (symbol->output_options & READER_INIT) {
566 if (gs1) {
567 strcpy(symbol->errtxt, "519: Cannot encode in GS1 mode and Reader Initialisation at the same time");
568 return ZINT_ERROR_INVALID_OPTION;
569 } else {
570 target[tp] = 234;
571 tp++; /* Reader Programming */
572 strcat(binary, " ");
573 if (debug) printf("RP ");
574 }
575 }
576
577 if (symbol->eci > 3) {
578 /* Encode ECI numbers according to Table 6 */
579 target[tp] = 241; /* ECI Character */
580 tp++;
581 if (symbol->eci <= 126) {
582 target[tp] = (unsigned char) symbol->eci + 1;
583 tp++;
584 }
585 if ((symbol->eci >= 127) && (symbol->eci <= 16382)) {
586 target[tp] = (unsigned char) ((symbol->eci - 127) / 254) + 128;
587 tp++;
588 target[tp] = (unsigned char) ((symbol->eci - 127) % 254) + 1;
589 tp++;
590 }
591 if (symbol->eci >= 16383) {
592 target[tp] = (unsigned char) ((symbol->eci - 16383) / 64516) + 192;
593 tp++;
594 target[tp] = (unsigned char) (((symbol->eci - 16383) / 254) % 254) + 1;
595 tp++;
596 target[tp] = (unsigned char) ((symbol->eci - 16383) % 254) + 1;
597 tp++;
598 }
599 if (debug) printf("ECI %d ", symbol->eci + 1);
600 }
601
602 /* Check for Macro05/Macro06 */
603 /* "[)>[RS]05[GS]...[RS][EOT]" -> CW 236 */
604 /* "[)>[RS]06[GS]...[RS][EOT]" -> CW 237 */
605 if (tp == 0 && sp == 0 && inputlen >= 9
606 && source[0] == '[' && source[1] == ')' && source[2] == '>'
607 && source[3] == '\x1e' && source[4] == '0'
608 && (source[5] == '5' || source[5] == '6')
609 && source[6] == '\x1d'
610 && source[inputlen - 2] == '\x1e' && source[inputlen - 1] == '\x04') {
611 /* Output macro Codeword */
612 if (source[5] == '5') {
613 target[tp] = 236;
614 if (debug) printf("Macro05 ");
615 } else {
616 target[tp] = 237;
617 if (debug) printf("Macro06 ");
618 }
619 tp++;
620 strcat(binary, " ");
621 /* Remove macro characters from input string */
622 sp = 7;
623 inputlen -= 2;
624 *length_p -= 2;
625 }
626
627
628 while (sp < inputlen) {
629
630 current_mode = next_mode;
631
632 /* step (b) - ASCII encodation */
633 if (current_mode == DM_ASCII) {
634 next_mode = DM_ASCII;
635
636 if (istwodigits(source, sp) && ((sp + 1) != inputlen)) {
637 target[tp] = (unsigned char) ((10 * ctoi(source[sp])) + ctoi(source[sp + 1]) + 130);
638 if (debug) printf("N%d ", target[tp] - 130);
639 tp++;
640 strcat(binary, " ");
641 sp += 2;
642 } else {
643 next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
644
645 if (next_mode != DM_ASCII) {
646 switch (next_mode) {
647 case DM_C40: target[tp] = 230;
648 tp++;
649 strcat(binary, " ");
650 if (debug) printf("C40 ");
651 break;
652 case DM_TEXT: target[tp] = 239;
653 tp++;
654 strcat(binary, " ");
655 if (debug) printf("TEX ");
656 break;
657 case DM_X12: target[tp] = 238;
658 tp++;
659 strcat(binary, " ");
660 if (debug) printf("X12 ");
661 break;
662 case DM_EDIFACT: target[tp] = 240;
663 tp++;
664 strcat(binary, " ");
665 if (debug) printf("EDI ");
666 break;
667 case DM_BASE256: target[tp] = 231;
668 tp++;
669 strcat(binary, " ");
670 if (debug) printf("BAS ");
671 break;
672 }
673 } else {
674 if (source[sp] > 127) {
675 target[tp] = 235; /* FNC4 */
676 if (debug) printf("FN4 ");
677 tp++;
678 target[tp] = (source[sp] - 128) + 1;
679 if (debug) printf("A%02X ", target[tp] - 1);
680 tp++;
681 strcat(binary, " ");
682 } else {
683 if (gs1 && (source[sp] == '[')) {
684 target[tp] = 232; /* FNC1 */
685 if (debug) printf("FN1 ");
686 } else {
687 target[tp] = source[sp] + 1;
688 if (debug) printf("A%02X ", target[tp] - 1);
689 }
690 tp++;
691 strcat(binary, " ");
692 }
693 sp++;
694 }
695 }
696
697 }
698
699 /* step (c) C40 encodation */
700 if (current_mode == DM_C40) {
701 int shift_set, value;
702
703 next_mode = DM_C40;
704 if (*process_p == 0) {
705 next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
706 }
707
708 if (next_mode != DM_C40) {
709 target[tp] = 254;
710 tp++;
711 strcat(binary, " "); /* Unlatch */
712 next_mode = DM_ASCII;
713 if (debug) printf("ASC ");
714 } else {
715 if (source[sp] > 127) {
716 process_buffer[*process_p] = 1;
717 (*process_p)++;
718 process_buffer[*process_p] = 30;
719 (*process_p)++; /* Upper Shift */
720 shift_set = c40_shift[source[sp] - 128];
721 value = c40_value[source[sp] - 128];
722 } else {
723 shift_set = c40_shift[source[sp]];
724 value = c40_value[source[sp]];
725 }
726
727 if (gs1 && (source[sp] == '[')) {
728 shift_set = 2;
729 value = 27; /* FNC1 */
730 }
731
732 if (shift_set != 0) {
733 process_buffer[*process_p] = shift_set - 1;
734 (*process_p)++;
735 }
736 process_buffer[*process_p] = value;
737 (*process_p)++;
738
739 if (*process_p >= 3) {
740 int iv;
741
742 iv = (1600 * process_buffer[0]) + (40 * process_buffer[1]) + (process_buffer[2]) + 1;
743 target[tp] = (unsigned char) (iv / 256);
744 tp++;
745 target[tp] = iv % 256;
746 tp++;
747 strcat(binary, " ");
748 if (debug) printf("[%d %d %d] ", process_buffer[0], process_buffer[1], process_buffer[2]);
749
750 process_buffer[0] = process_buffer[3];
751 process_buffer[1] = process_buffer[4];
752 process_buffer[2] = process_buffer[5];
753 process_buffer[3] = 0;
754 process_buffer[4] = 0;
755 process_buffer[5] = 0;
756 *process_p -= 3;
757 }
758 sp++;
759 }
760 }
761
762 /* step (d) Text encodation */
763 if (current_mode == DM_TEXT) {
764 int shift_set, value;
765
766 next_mode = DM_TEXT;
767 if (*process_p == 0) {
768 next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
769 }
770
771 if (next_mode != DM_TEXT) {
772 target[tp] = 254;
773 tp++;
774 strcat(binary, " "); /* Unlatch */
775 next_mode = DM_ASCII;
776 if (debug) printf("ASC ");
777 } else {
778 if (source[sp] > 127) {
779 process_buffer[*process_p] = 1;
780 (*process_p)++;
781 process_buffer[*process_p] = 30;
782 (*process_p)++; /* Upper Shift */
783 shift_set = text_shift[source[sp] - 128];
784 value = text_value[source[sp] - 128];
785 } else {
786 shift_set = text_shift[source[sp]];
787 value = text_value[source[sp]];
788 }
789
790 if (gs1 && (source[sp] == '[')) {
791 shift_set = 2;
792 value = 27; /* FNC1 */
793 }
794
795 if (shift_set != 0) {
796 process_buffer[*process_p] = shift_set - 1;
797 (*process_p)++;
798 }
799 process_buffer[*process_p] = value;
800 (*process_p)++;
801
802 if (*process_p >= 3) {
803 int iv;
804
805 iv = (1600 * process_buffer[0]) + (40 * process_buffer[1]) + (process_buffer[2]) + 1;
806 target[tp] = (unsigned char) (iv / 256);
807 tp++;
808 target[tp] = iv % 256;
809 tp++;
810 strcat(binary, " ");
811 if (debug) printf("[%d %d %d] ", process_buffer[0], process_buffer[1], process_buffer[2]);
812
813 process_buffer[0] = process_buffer[3];
814 process_buffer[1] = process_buffer[4];
815 process_buffer[2] = process_buffer[5];
816 process_buffer[3] = 0;
817 process_buffer[4] = 0;
818 process_buffer[5] = 0;
819 *process_p -= 3;
820 }
821 sp++;
822 }
823 }
824
825 /* step (e) X12 encodation */
826 if (current_mode == DM_X12) {
827 int value = 0;
828
829 next_mode = DM_X12;
830 if (*process_p == 0) {
831 next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
832 }
833
834 if (next_mode != DM_X12) {
835 target[tp] = 254;
836 tp++;
837 strcat(binary, " "); /* Unlatch */
838 next_mode = DM_ASCII;
839 if (debug) printf("ASC ");
840 } else {
841 if (source[sp] == 13) {
842 value = 0;
843 }
844 if (source[sp] == '*') {
845 value = 1;
846 }
847 if (source[sp] == '>') {
848 value = 2;
849 }
850 if (source[sp] == ' ') {
851 value = 3;
852 }
853 if ((source[sp] >= '0') && (source[sp] <= '9')) {
854 value = (source[sp] - '0') + 4;
855 }
856 if ((source[sp] >= 'A') && (source[sp] <= 'Z')) {
857 value = (source[sp] - 'A') + 14;
858 }
859
860 process_buffer[*process_p] = value;
861 (*process_p)++;
862
863 if (*process_p >= 3) {
864 int iv;
865
866 iv = (1600 * process_buffer[0]) + (40 * process_buffer[1]) + (process_buffer[2]) + 1;
867 target[tp] = (unsigned char) (iv / 256);
868 tp++;
869 target[tp] = iv % 256;
870 tp++;
871 strcat(binary, " ");
872 if (debug) printf("[%d %d %d] ", process_buffer[0], process_buffer[1], process_buffer[2]);
873
874 process_buffer[0] = process_buffer[3];
875 process_buffer[1] = process_buffer[4];
876 process_buffer[2] = process_buffer[5];
877 process_buffer[3] = 0;
878 process_buffer[4] = 0;
879 process_buffer[5] = 0;
880 *process_p -= 3;
881 }
882 sp++;
883 }
884 }
885
886 /* step (f) EDIFACT encodation */
887 if (current_mode == DM_EDIFACT) {
888 int value = 0;
889
890 next_mode = DM_EDIFACT;
891 if (*process_p == 3) {
892 next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
893 }
894
895 if (next_mode != DM_EDIFACT) {
896 process_buffer[*process_p] = 31;
897 (*process_p)++;
898 next_mode = DM_ASCII;
899 } else {
900 value = source[sp];
901
902 if (source[sp] >= 64) { // '@'
903 value -= 64;
904 }
905
906 process_buffer[*process_p] = value;
907 (*process_p)++;
908 sp++;
909 }
910
911 if (*process_p >= 4) {
912 target[tp] = (unsigned char) ((process_buffer[0] << 2) + ((process_buffer[1] & 0x30) >> 4));
913 tp++;
914 target[tp] = ((process_buffer[1] & 0x0f) << 4) + ((process_buffer[2] & 0x3c) >> 2);
915 tp++;
916 target[tp] = (unsigned char) (((process_buffer[2] & 0x03) << 6) + process_buffer[3]);
917 tp++;
918 strcat(binary, " ");
919 if (debug) printf("[%d %d %d %d] ", process_buffer[0], process_buffer[1], process_buffer[2], process_buffer[3]);
920
921 process_buffer[0] = process_buffer[4];
922 process_buffer[1] = process_buffer[5];
923 process_buffer[2] = process_buffer[6];
924 process_buffer[3] = process_buffer[7];
925 process_buffer[4] = 0;
926 process_buffer[5] = 0;
927 process_buffer[6] = 0;
928 process_buffer[7] = 0;
929 *process_p -= 4;
930 }
931 }
932
933 /* step (g) Base 256 encodation */
934 if (current_mode == DM_BASE256) {
935 next_mode = look_ahead_test(source, inputlen, sp, current_mode, gs1);
936
937 if (next_mode == DM_BASE256) {
938 target[tp] = source[sp];
939 if (debug) printf("B%02X ", target[tp]);
940 tp++;
941 sp++;
942 strcat(binary, "b");
943 } else {
944 next_mode = DM_ASCII;
945 if (debug) printf("ASC ");
946 }
947 }
948
949 if (tp > 1558) {
950 return 0;
951 }
952
953 } /* while */
954
955 /* Add length and randomising algorithm to b256 */
956 i = 0;
957 while (i < tp) {
958 if (binary[i] == 'b') {
959 if ((i == 0) || (binary[i - 1] != 'b')) {
960 /* start of binary data */
961 int binary_count; /* length of b256 data */
962
963 for (binary_count = 0; binary_count + i < tp && binary[binary_count + i] == 'b'; binary_count++);
964
965 if (binary_count <= 249) {
966 dminsert(binary, i, 'b');
967 insert_value(target, i, tp, binary_count);
968 tp++;
969 } else {
970 dminsert(binary, i, 'b');
971 dminsert(binary, i + 1, 'b');
972 insert_value(target, i, tp, (binary_count / 250) + 249);
973 tp++;
974 insert_value(target, i + 1, tp, binary_count % 250);
975 tp++;
976 }
977 }
978 }
979 i++;
980 }
981
982 for (i = 0; i < tp; i++) {
983 if (binary[i] == 'b') {
984 int prn, temp;
985
986 prn = ((149 * (i + 1)) % 255) + 1;
987 temp = target[i] + prn;
988 if (temp <= 255) {
989 target[i] = (unsigned char) (temp);
990 } else {
991 target[i] = (unsigned char) (temp - 256);
992 }
993 }
994 }
995
996 *(last_mode) = current_mode;
997 return tp;
998 }
999
dm200encode_remainder(unsigned char target[],int target_length,const unsigned char source[],const size_t inputlen,const int last_mode,const int process_buffer[],const int process_p,const int symbols_left)1000 static int dm200encode_remainder(unsigned char target[], int target_length, const unsigned char source[], const size_t inputlen, const int last_mode, const int process_buffer[], const int process_p, const int symbols_left) {
1001 int debug = 0;
1002
1003 switch (last_mode) {
1004 case DM_C40:
1005 case DM_TEXT:
1006 if (process_p == 1) // 1 data character left to encode.
1007 {
1008 if (symbols_left > 1) {
1009 target[target_length] = 254;
1010 target_length++; // Unlatch and encode remaining data in ascii.
1011 }
1012 target[target_length] = source[inputlen - 1] + 1;
1013 target_length++;
1014 } else if (process_p == 2) // 2 data characters left to encode.
1015 {
1016 // Pad with shift 1 value (0) and encode as double.
1017 int intValue = (1600 * process_buffer[0]) + (40 * process_buffer[1]) + 1; // ie (0 + 1).
1018 target[target_length] = (unsigned char) (intValue / 256);
1019 target_length++;
1020 target[target_length] = (unsigned char) (intValue % 256);
1021 target_length++;
1022 if (symbols_left > 2) {
1023 target[target_length] = 254; // Unlatch
1024 target_length++;
1025 }
1026 } else {
1027 if (symbols_left > 0) {
1028 target[target_length] = 254; // Unlatch
1029 target_length++;
1030 }
1031 }
1032 break;
1033
1034 case DM_X12:
1035 if ((symbols_left == process_p) && (process_p == 1)) {
1036 // Unlatch not required!
1037 target[target_length] = source[inputlen - 1] + 1;
1038 target_length++;
1039 } else {
1040 target[target_length] = (254);
1041 target_length++; // Unlatch.
1042
1043 if (process_p == 1) {
1044 target[target_length] = source[inputlen - 1] + 1;
1045 target_length++;
1046 }
1047
1048 if (process_p == 2) {
1049 target[target_length] = source[inputlen - 2] + 1;
1050 target_length++;
1051 target[target_length] = source[inputlen - 1] + 1;
1052 target_length++;
1053 }
1054 }
1055 break;
1056
1057 case DM_EDIFACT:
1058 if (symbols_left <= 2) // Unlatch not required!
1059 {
1060 if (process_p == 1) {
1061 target[target_length] = source[inputlen - 1] + 1;
1062 target_length++;
1063 }
1064
1065 if (process_p == 2) {
1066 target[target_length] = source[inputlen - 2] + 1;
1067 target_length++;
1068 target[target_length] = source[inputlen - 1] + 1;
1069 target_length++;
1070 }
1071 } else {
1072 // Append edifact unlatch value (31) and empty buffer
1073 if (process_p == 0) {
1074 target[target_length] = (unsigned char) (31 << 2);
1075 target_length++;
1076 }
1077
1078 if (process_p == 1) {
1079 target[target_length] = (unsigned char) ((process_buffer[0] << 2) + ((31 & 0x30) >> 4));
1080 target_length++;
1081 target[target_length] = (unsigned char) ((31 & 0x0f) << 4);
1082 target_length++;
1083 }
1084
1085 if (process_p == 2) {
1086 target[target_length] = (unsigned char) ((process_buffer[0] << 2) + ((process_buffer[1] & 0x30) >> 4));
1087 target_length++;
1088 target[target_length] = (unsigned char) (((process_buffer[1] & 0x0f) << 4) + ((31 & 0x3c) >> 2));
1089 target_length++;
1090 target[target_length] = (unsigned char) (((31 & 0x03) << 6));
1091 target_length++;
1092 }
1093
1094 if (process_p == 3) {
1095 target[target_length] = (unsigned char) ((process_buffer[0] << 2) + ((process_buffer[1] & 0x30) >> 4));
1096 target_length++;
1097 target[target_length] = (unsigned char) (((process_buffer[1] & 0x0f) << 4) + ((process_buffer[2] & 0x3c) >> 2));
1098 target_length++;
1099 target[target_length] = (unsigned char) (((process_buffer[2] & 0x03) << 6) + 31);
1100 target_length++;
1101 }
1102 }
1103 break;
1104 }
1105
1106 if (debug) {
1107 int i;
1108 printf("\n\n");
1109 for (i = 0; i < target_length; i++)
1110 printf("%03d ", target[i]);
1111
1112 printf("\n");
1113 }
1114
1115 return target_length;
1116 }
1117
1118 /* add pad bits */
add_tail(unsigned char target[],int tp,const int tail_length)1119 static void add_tail(unsigned char target[], int tp, const int tail_length) {
1120 int i, prn, temp;
1121
1122 for (i = tail_length; i > 0; i--) {
1123 if (i == tail_length) {
1124 target[tp] = 129;
1125 tp++; /* Pad */
1126 } else {
1127 prn = ((149 * (tp + 1)) % 253) + 1;
1128 temp = 129 + prn;
1129 if (temp <= 254) {
1130 target[tp] = (unsigned char) (temp);
1131 tp++;
1132 } else {
1133 target[tp] = (unsigned char) (temp - 254);
1134 tp++;
1135 }
1136 }
1137 }
1138 }
1139
data_matrix_200(struct zint_symbol * symbol,const unsigned char source[],const size_t in_length)1140 int data_matrix_200(struct zint_symbol *symbol,const unsigned char source[], const size_t in_length) {
1141 int i, skew = 0;
1142 size_t inputlen=in_length;
1143 unsigned char binary[2200];
1144 int binlen;
1145 int process_buffer[8]; /* holds remaining data to finalised */
1146 int process_p; /* number of characters left to finalise */
1147 int symbolsize, optionsize, calcsize;
1148 int taillength, error_number = 0;
1149 int H, W, FH, FW, datablock, bytes, rsblock;
1150 int last_mode = DM_ASCII;
1151 unsigned char *grid = 0;
1152 int symbols_left;
1153
1154 /* inputlen may be decremented by 2 if macro character is used */
1155 binlen = dm200encode(symbol, source, binary, &last_mode, &inputlen, process_buffer, &process_p);
1156
1157 if (binlen == 0) {
1158 strcpy(symbol->errtxt, "520: Data too long to fit in symbol");
1159 return ZINT_ERROR_TOO_LONG;
1160 }
1161
1162 if ((symbol->option_2 >= 1) && (symbol->option_2 <= DMSIZESCOUNT)) {
1163 optionsize = intsymbol[symbol->option_2 - 1];
1164 } else {
1165 optionsize = -1;
1166 }
1167
1168 calcsize = DMSIZESCOUNT - 1;
1169 for (i = DMSIZESCOUNT - 1; i > -1; i--) {
1170 if (matrixbytes[i] >= (binlen + process_p)) {
1171 // Allow for the remaining data characters
1172 calcsize = i;
1173 }
1174 }
1175
1176 if (symbol->option_3 == DM_SQUARE) {
1177 /* Skip rectangular symbols in square only mode */
1178 while (matrixH[calcsize] != matrixW[calcsize]) {
1179 calcsize++;
1180 }
1181 if (optionsize != -1) {
1182 strcpy(symbol->errtxt, "521: Can not force square symbols when symbol size is selected");
1183 error_number = ZINT_WARN_INVALID_OPTION;
1184 }
1185 } else if (symbol->option_3 != DM_DMRE) {
1186 /* Skip DMRE symbols */
1187 while (isDMRE[calcsize]) {
1188 calcsize++;
1189 }
1190 }
1191
1192 symbolsize = optionsize;
1193 if (calcsize > optionsize) {
1194 symbolsize = calcsize;
1195 if (optionsize != -1) {
1196 strcpy(symbol->errtxt, "522: Input too long for selected symbol size");
1197 return ZINT_ERROR_TOO_LONG;
1198 }
1199 }
1200
1201 // Now we know the symbol size we can handle the remaining data in the process buffer.
1202 symbols_left = matrixbytes[symbolsize] - binlen;
1203 binlen = dm200encode_remainder(binary, binlen, source, inputlen, last_mode, process_buffer, process_p, symbols_left);
1204
1205 if (binlen > matrixbytes[symbolsize]) {
1206 strcpy(symbol->errtxt, "523: Data too long to fit in symbol");
1207 return ZINT_ERROR_TOO_LONG;
1208 }
1209
1210 H = matrixH[symbolsize];
1211 W = matrixW[symbolsize];
1212 FH = matrixFH[symbolsize];
1213 FW = matrixFW[symbolsize];
1214 bytes = matrixbytes[symbolsize];
1215 datablock = matrixdatablock[symbolsize];
1216 rsblock = matrixrsblock[symbolsize];
1217
1218 taillength = bytes - binlen;
1219
1220 if (taillength != 0) {
1221 add_tail(binary, binlen, taillength);
1222 }
1223
1224 // ecc code
1225 if (symbolsize == INTSYMBOL144) {
1226 skew = 1;
1227 }
1228 ecc200(binary, bytes, datablock, rsblock, skew);
1229 // Print Codewords
1230 #ifdef DEBUG
1231 {
1232 int CWCount;
1233 int posCur;
1234 if (skew)
1235 CWCount = 1558 + 620;
1236 else
1237 CWCount = bytes + rsblock * (bytes / datablock);
1238 printf("Codewords (%i):", CWCount);
1239 for (posCur = 0; posCur < CWCount; posCur++)
1240 printf(" %3i", binary[posCur]);
1241 puts("\n");
1242 }
1243 #endif
1244 { // placement
1245 int x, y, NC, NR, *places;
1246 NC = W - 2 * (W / FW);
1247 NR = H - 2 * (H / FH);
1248 places = (int*) malloc(NC * NR * sizeof (int));
1249 ecc200placement(places, NR, NC);
1250 grid = (unsigned char*) malloc(W * H);
1251 memset(grid, 0, W * H);
1252 for (y = 0; y < H; y += FH) {
1253 for (x = 0; x < W; x++)
1254 grid[y * W + x] = 1;
1255 for (x = 0; x < W; x += 2)
1256 grid[(y + FH - 1) * W + x] = 1;
1257 }
1258 for (x = 0; x < W; x += FW) {
1259 for (y = 0; y < H; y++)
1260 grid[y * W + x] = 1;
1261 for (y = 0; y < H; y += 2)
1262 grid[y * W + x + FW - 1] = 1;
1263 }
1264 #ifdef DEBUG
1265 // Print position matrix as in standard
1266 for (y = NR - 1; y >= 0; y--) {
1267 for (x = 0; x < NC; x++) {
1268 int v;
1269 if (x != 0)
1270 fprintf(stderr, "|");
1271 v = places[(NR - y - 1) * NC + x];
1272 fprintf(stderr, "%3d.%2d", (v >> 3), 8 - (v & 7));
1273 }
1274 fprintf(stderr, "\n");
1275 }
1276 #endif
1277 for (y = 0; y < NR; y++) {
1278 for (x = 0; x < NC; x++) {
1279 int v = places[(NR - y - 1) * NC + x];
1280 //fprintf (stderr, "%4d", v);
1281 if (v == 1 || (v > 7 && (binary[(v >> 3) - 1] & (1 << (v & 7)))))
1282 grid[(1 + y + 2 * (y / (FH - 2))) * W + 1 + x + 2 * (x / (FW - 2))] = 1;
1283 }
1284 //fprintf (stderr, "\n");
1285 }
1286 for (y = H - 1; y >= 0; y--) {
1287 int x;
1288 for (x = 0; x < W; x++) {
1289 if (grid[W * y + x]) {
1290 set_module(symbol, (H - y) - 1, x);
1291 }
1292 }
1293 symbol->row_height[(H - y) - 1] = 1;
1294 }
1295 free(grid);
1296 free(places);
1297 }
1298
1299 symbol->rows = H;
1300 symbol->width = W;
1301
1302 return error_number;
1303 }
1304
dmatrix(struct zint_symbol * symbol,const unsigned char source[],const size_t in_length)1305 int dmatrix(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length) {
1306 int error_number;
1307
1308 if (symbol->option_1 <= 1) {
1309 /* ECC 200 */
1310 error_number = data_matrix_200(symbol, source, in_length);
1311 } else {
1312 /* ECC 000 - 140 */
1313 strcpy(symbol->errtxt, "524: Older Data Matrix standards are no longer supported");
1314 error_number = ZINT_ERROR_INVALID_OPTION;
1315 }
1316
1317 return error_number;
1318 }
1319