1 /* dotcode.c - Handles DotCode */
2
3 /*
4 libzint - the open source barcode library
5 Copyright (C) 2017 Robin Stuart <rstuart114@gmail.com>
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16 3. Neither the name of the project nor the names of its contributors
17 may be used to endorse or promote products derived from this software
18 without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 SUCH DAMAGE.
31 */
32
33 /*
34 * Attempts to encode DotCode according to AIMD013 Rev 1.34a, dated Feb 19, 2009
35 */
36
37 #include <stdio.h>
38 #include <string.h>
39 #include <stdlib.h>
40 #include <math.h>
41 #ifndef _MSC_VER
42 #include <stdint.h>
43 #else
44 #include "ms_stdint.h"
45 #include <malloc.h>
46 #endif
47 #include "common.h"
48 #include "gs1.h"
49
50 #define GF 113
51 #define PM 3
52
53 /* DotCode symbol character dot patterns, from Annex C */
54 static const unsigned short int dot_patterns[113] = {
55 0x155, 0x0ab, 0x0ad, 0x0b5, 0x0d5, 0x156, 0x15a, 0x16a, 0x1aa, 0x0ae,
56 0x0b6, 0x0ba, 0x0d6, 0x0da, 0x0ea, 0x12b, 0x12d, 0x135, 0x14b, 0x14d,
57 0x153, 0x159, 0x165, 0x169, 0x195, 0x1a5, 0x1a9, 0x057, 0x05b, 0x05d,
58 0x06b, 0x06d, 0x075, 0x097, 0x09b, 0x09d, 0x0a7, 0x0b3, 0x0b9, 0x0cb,
59 0x0cd, 0x0d3, 0x0d9, 0x0e5, 0x0e9, 0x12e, 0x136, 0x13a, 0x14e, 0x15c,
60 0x166, 0x16c, 0x172, 0x174, 0x196, 0x19a, 0x1a6, 0x1ac, 0x1b2, 0x1b4,
61 0x1ca, 0x1d2, 0x1d4, 0x05e, 0x06e, 0x076, 0x07a, 0x09e, 0x0bc, 0x0ce,
62 0x0dc, 0x0e6, 0x0ec, 0x0f2, 0x0f4, 0x117, 0x11b, 0x11d, 0x127, 0x133,
63 0x139, 0x147, 0x163, 0x171, 0x18b, 0x18d, 0x193, 0x199, 0x1a3, 0x1b1,
64 0x1c5, 0x1c9, 0x1d1, 0x02f, 0x037, 0x03b, 0x03d, 0x04f, 0x067, 0x073,
65 0x079, 0x08f, 0x0c7, 0x0e3, 0x0f1, 0x11e, 0x13c, 0x178, 0x18e, 0x19c,
66 0x1b8, 0x1c6, 0x1cc
67 };
68
get_dot(char Dots[],const int Hgt,const int Wid,const int x,const int y)69 static int get_dot(char Dots[], const int Hgt, const int Wid, const int x, const int y) {
70 int retval = 0;
71
72 if ((x >= 0) && (x < Wid) && (y >= 0) && (y < Hgt)) {
73 if (Dots[(y * Wid) + x] == '1') {
74 retval = 1;
75 }
76 }
77
78 return retval;
79 }
80
clr_col(char * Dots,const int Hgt,const int Wid,const int x)81 static int clr_col(char *Dots, const int Hgt, const int Wid, const int x) {
82 int y;
83 for (y = x & 1; y < Hgt; y += 2) {
84 if (get_dot(Dots, Hgt, Wid, x, y)) {
85 return 0;
86 }
87 }
88
89 return 1;
90 }
91
clr_row(char * Dots,const int Hgt,const int Wid,const int y)92 static int clr_row(char *Dots, const int Hgt, const int Wid, const int y) {
93 int x;
94 for (x = y & 1; x < Wid; x += 2) {
95 if (get_dot(Dots, Hgt, Wid, x, y)) {
96 return 0;
97 }
98 }
99
100 return 1;
101 }
102
103 /* Dot pattern scoring routine from Annex A */
score_array(char Dots[],int Hgt,int Wid)104 const int score_array(char Dots[], int Hgt, int Wid) {
105 int x, y, worstedge, first, last, sum;
106 int penalty_local = 0;
107 int penalty = 0;
108
109 // first, guard against "pathelogical" gaps in the array
110 if (Hgt & 1) {
111 if (Hgt < 12) {
112 sum = 0;
113 for (x = 1; x < Wid - 1; x++) {
114 if (!(clr_col(Dots, Hgt, Wid, x))) {
115 sum = 0;
116 if (penalty_local) {
117 penalty += penalty_local;
118 penalty_local = 0;
119 }
120 } else {
121 sum++;
122 if (sum == 1) {
123 penalty_local = Hgt;
124 } else {
125 penalty_local *= Hgt;
126 }
127 }
128 }
129 }
130 } else {
131 if (Wid < 12) {
132 sum = 0;
133 for (y = 1; y < Hgt - 1; y++) {
134 if (!(clr_row(Dots, Hgt, Wid, y))) {
135 sum = 0;
136 if (penalty_local) {
137 penalty += penalty_local;
138 penalty_local = 0;
139 }
140 } else {
141 sum++;
142 if (sum == 1) {
143 penalty_local = Wid;
144 } else {
145 penalty_local *= Wid;
146 }
147 }
148 }
149 }
150 }
151
152 sum = 0;
153 first = -1;
154 last = -1;
155
156 // across the top edge, count printed dots and measure their extent
157 for (x = 0; x < Wid; x += 2)
158 if (get_dot(Dots, Hgt, Wid, x, 0)) {
159 if (first < 0) {
160 first = x;
161 }
162 last = x;
163 sum++;
164 }
165 worstedge = sum + last - first;
166 worstedge *= Hgt;
167
168 sum = 0;
169 first = -1;
170 last = -1;
171
172 //across the bottom edge, ditto
173 for (x = Wid & 1; x < Wid; x += 2)
174 if (get_dot(Dots, Hgt, Wid, x, Hgt - 1)) {
175 if (first < 0) {
176 first = x;
177 }
178 last = x;
179 sum++;
180 }
181 sum += last - first;
182 sum *= Hgt;
183 if (sum < worstedge) {
184 worstedge = sum;
185 }
186
187 sum = 0;
188 first = -1;
189 last = -1;
190
191 //down the left edge, ditto
192 for (y = 0; y < Hgt; y += 2)
193 if (get_dot(Dots, Hgt, Wid, 0, y)) {
194 if (first < 0) {
195 first = y;
196 }
197 last = y;
198 sum++;
199 }
200 sum += last - first;
201 sum *= Wid;
202 if (sum < worstedge) {
203 worstedge = sum;
204 }
205
206 sum = 0;
207 first = -1;
208 last = -1;
209
210 //down the right edge, ditto
211 for (y = Hgt & 1; y < Hgt; y += 2)
212 if (get_dot(Dots, Hgt, Wid, Wid - 1, y)) {
213 if (first < 0) {
214 first = y;
215 }
216 last = y;
217 sum++;
218 }
219 sum += last - first;
220 sum *= Wid;
221 if (sum < worstedge) {
222 worstedge = sum;
223 }
224
225 // throughout the array, count the # of unprinted 5-somes (cross patterns)
226 // plus the # of printed dots surrounded by 8 unprinted neighbors
227 sum = 0;
228 for (y = 0; y < Hgt; y++) {
229 for (x = y & 1; x < Wid; x += 2) {
230 if ((!get_dot(Dots, Hgt, Wid, x - 1, y - 1))
231 && (!get_dot(Dots, Hgt, Wid, x + 1, y - 1))
232 && (!get_dot(Dots, Hgt, Wid, x - 1, y + 1))
233 && (!get_dot(Dots, Hgt, Wid, x + 1, y + 1))
234 && ((!get_dot(Dots, Hgt, Wid, x, y))
235 || ((!get_dot(Dots, Hgt, Wid, x - 2, y))
236 && (!get_dot(Dots, Hgt, Wid, x, y - 2))
237 && (!get_dot(Dots, Hgt, Wid, x + 2, y))
238 && (!get_dot(Dots, Hgt, Wid, x, y + 2))))) {
239 sum++;
240 }
241 }
242 }
243
244 return (worstedge - sum * sum - penalty);
245 }
246
247 //-------------------------------------------------------------------------
248 // "rsencode(nd,nc)" adds "nc" R-S check words to "nd" data words in wd[]
249 // employing Galois Field GF, where GF is prime, with a prime modulus of PM
250 //-------------------------------------------------------------------------
251
rsencode(int nd,int nc,unsigned char * wd)252 void rsencode(int nd, int nc, unsigned char *wd) {
253 int i, j, k, nw, start, step, root[GF], c[GF];
254
255 // Start by generating "nc" roots (antilogs):
256 root[0] = 1;
257 for (i = 1; (i <= nc) && (i < GF); i++)
258 root[i] = (PM * root[i - 1]) % GF;
259
260 // Here we compute how many interleaved R-S blocks will be needed
261 nw = nd + nc;
262 step = (nw + GF - 2) / (GF - 1);
263
264 // ...& then for each such block:
265 for (start = 0; start < step; start++) {
266 int ND = (nd - start + step - 1) / step, NW = (nw - start + step - 1) / step, NC = NW - ND;
267
268 // first compute the generator polynomial "c" of order "NC":
269 for (i = 1; i <= NC; i++)
270 c[i] = 0;
271 c[0] = 1;
272
273 for (i = 1; i <= NC; i++) {
274 for (j = NC; j >= 1; j--) {
275 c[j] = (GF + c[j] - (root[i] * c[j - 1]) % GF) % GF;
276 }
277 }
278
279 // & then compute the corresponding checkword values into wd[]
280 // ... (a) starting at wd[start] & (b) stepping by step
281 for (i = ND; i < NW; i++)
282 wd[start + i * step] = 0;
283 for (i = 0; i < ND; i++) {
284 k = (wd[start + i * step] + wd[start + ND * step]) % GF;
285 for (j = 0; j < NC - 1; j++) {
286 wd[start + (ND + j) * step] = (GF - ((c[j + 1] * k) % GF) + wd[start + (ND + j + 1) * step]) % GF;
287 }
288 wd[start + (ND + NC - 1) * step] = (GF - ((c[NC] * k) % GF)) % GF;
289 }
290 for (i = ND; i < NW; i++)
291 wd[start + i * step] = (GF - wd[start + i * step]) % GF;
292 }
293 }
294
295 /* Check if the next character is directly encodable in code set A (Annex F.II.D) */
datum_a(const unsigned char source[],int position,int length)296 int datum_a(const unsigned char source[], int position, int length) {
297 int retval = 0;
298
299 if (position < length) {
300 if (source[position] <= 95) {
301 retval = 1;
302 }
303 }
304
305 return retval;
306 }
307
308 /* Check if the next character is directly encodable in code set B (Annex F.II.D) */
datum_b(const unsigned char source[],int position,int length)309 int datum_b(const unsigned char source[], int position, int length) {
310 int retval = 0;
311
312 if (position < length) {
313 if ((source[position] >= 32) && (source[position] <= 127)) {
314 retval = 1;
315 }
316
317 switch (source[position]) {
318 case 9: // HT
319 case 28: // FS
320 case 29: // GS
321 case 30: // RS
322 retval = 1;
323 }
324
325 if (position != length - 2) {
326 if ((source[position] == 13) && (source[position + 1] == 10)) { // CRLF
327 retval = 1;
328 }
329 }
330 }
331
332 return retval;
333 }
334
335 /* Check if the next characters are directly encodable in code set C (Annex F.II.D) */
datum_c(const unsigned char source[],int position,int length)336 int datum_c(const unsigned char source[], int position, int length) {
337 int retval = 0;
338
339 if (position <= length - 2) {
340 if (((source[position] >= '0') && (source[position] <= '9'))
341 && ((source[position + 1] >= '0') && (source[position + 1] <= '9')))
342 retval = 1;
343 }
344
345 return retval;
346 }
347
348 /* Returns how many consecutive digits lie immediately ahead (Annex F.II.A) */
n_digits(const unsigned char source[],int position,int length)349 int n_digits(const unsigned char source[], int position, int length) {
350 int i;
351
352 for (i = position; ((source[i] >= '0') && (source[i] <= '9')) && (i < length); i++);
353
354 return i - position;
355 }
356
357 /* checks ahead for 10 or more digits starting "17xxxxxx10..." (Annex F.II.B) */
seventeen_ten(const unsigned char source[],int position,int length)358 int seventeen_ten(const unsigned char source[], int position, int length) {
359 int found = 0;
360
361 if (n_digits(source, position, length) >= 10) {
362 if (((source[position] == '1') && (source[position + 1] == '7'))
363 && ((source[position + 8] == '1') && (source[position + 9] == '0'))) {
364 found = 1;
365 }
366 }
367
368 return found;
369 }
370
371 /* checks how many characters ahead can be reached while datum_c is true,
372 * returning the resulting number of codewords (Annex F.II.E)
373 */
ahead_c(const unsigned char source[],int position,int length)374 int ahead_c(const unsigned char source[], int position, int length) {
375 int count = 0;
376 int i;
377
378 for (i = position; (i < length) && datum_c(source, i, length); i += 2) {
379 count++;
380 }
381
382 return count;
383 }
384
385 /* Annex F.II.F */
try_c(const unsigned char source[],int position,int length)386 int try_c(const unsigned char source[], int position, int length) {
387 int retval = 0;
388
389 if (n_digits(source, position, length) > 0) {
390 if (ahead_c(source, position, length) > ahead_c(source, position + 1, length)) {
391 retval = ahead_c(source, position, length);
392 }
393 }
394
395 return retval;
396 }
397
398 /* Annex F.II.G */
ahead_a(const unsigned char source[],int position,int length)399 int ahead_a(const unsigned char source[], int position, int length) {
400 int count = 0;
401 int i;
402
403 for (i = position; ((i < length) && datum_a(source, i, length))
404 && (try_c(source, i, length) < 2); i++) {
405 count++;
406 }
407
408 return count;
409 }
410
411 /* Annex F.II.H */
ahead_b(const unsigned char source[],int position,int length)412 int ahead_b(const unsigned char source[], int position, int length) {
413 int count = 0;
414 int i;
415
416 for (i = position; ((i < length) && datum_b(source, i, length))
417 && (try_c(source, i, length) < 2); i++) {
418 count++;
419 }
420
421 return count;
422 }
423
424 /* checks if the next character is in the range 128 to 255 (Annex F.II.I) */
binary(const unsigned char source[],int position)425 int binary(const unsigned char source[], int position) {
426 int retval = 0;
427
428 if (source[position] >= 128) {
429 retval = 1;
430 }
431
432 return retval;
433 }
434
435 /* Analyse input data stream and encode using algorithm from Annex F */
dotcode_encode_message(struct zint_symbol * symbol,const unsigned char source[],int length,unsigned char * codeword_array,int * binary_finish)436 int dotcode_encode_message(struct zint_symbol *symbol, const unsigned char source[], int length, unsigned char *codeword_array, int *binary_finish) {
437 int input_position, array_length, i;
438 char encoding_mode;
439 int inside_macro, done;
440 int debug = symbol->debug;
441 int binary_buffer_size = 0;
442 int lawrencium[6]; // Reversed radix 103 values
443
444 #if defined(_MSC_VER) && _MSC_VER == 1200
445 uint64_t binary_buffer = 0;
446 #else
447 uint64_t binary_buffer = 0ULL;
448 #endif
449
450 input_position = 0;
451 array_length = 0;
452 encoding_mode = 'C';
453 inside_macro = 0;
454
455 if (symbol->output_options & READER_INIT) {
456 codeword_array[array_length] = 109; // FNC3
457 array_length++;
458 }
459
460 if (symbol->input_mode != GS1_MODE) {
461 if (length > 2) {
462 if (((source[input_position] >= '0') && (source[input_position] <= '9')) &&
463 ((source[input_position + 1] >= '0') && (source[input_position + 1] <= '9'))) {
464 codeword_array[array_length] = 107; // FNC1
465 array_length++;
466 }
467 }
468 }
469
470 if (symbol->eci > 3) {
471 codeword_array[array_length] = 108; // FNC2
472 array_length++;
473 if (symbol->eci <= 39) {
474 codeword_array[array_length] = symbol->eci;
475 array_length++;
476 } else {
477 // the next three codewords valued A, B & C encode the ECI value of
478 // (A - 40) * 12769 + B * 113 + C + 40 (Section 5.2.1)
479 int a, b, c;
480 a = (symbol->eci - 40) % 12769;
481 b = ((symbol->eci - 40) - (12769 * a)) % 113;
482 c = (symbol->eci - 40) - (12769 * a) - (113 * b);
483
484 codeword_array[array_length] = a + 40;
485 array_length++;
486 codeword_array[array_length] = b;
487 array_length++;
488 codeword_array[array_length] = c;
489 array_length++;
490 }
491 }
492
493 // Prevent encodation as a macro if a special character is in first position
494 if (source[input_position] == 9) {
495 codeword_array[array_length] = 101; // Latch A
496 array_length++;
497 codeword_array[array_length] = 73; // HT
498 array_length++;
499 encoding_mode = 'A';
500 }
501
502 if (source[input_position] == 28) {
503 codeword_array[array_length] = 101; // Latch A
504 array_length++;
505 codeword_array[array_length] = 92; // FS
506 array_length++;
507 encoding_mode = 'A';
508 }
509
510 if (source[input_position] == 29) {
511 codeword_array[array_length] = 101; // Latch A
512 array_length++;
513 codeword_array[array_length] = 93; // GS
514 array_length++;
515 encoding_mode = 'A';
516 }
517
518 if (source[input_position] == 30) {
519 codeword_array[array_length] = 101; // Latch A
520 array_length++;
521 codeword_array[array_length] = 94; // RS
522 array_length++;
523 encoding_mode = 'A';
524 }
525
526 do {
527 done = 0;
528 /* Step A */
529 if ((input_position == length - 2) && (inside_macro != 0) && (inside_macro != 100)) {
530 // inside_macro only gets set to 97, 98 or 99 if the last two characters are RS/EOT
531 input_position += 2;
532 done = 1;
533 if (debug) {
534 printf("A ");
535 }
536 }
537
538 if ((input_position == length - 1) && (inside_macro == 100)) {
539 // inside_macro only gets set to 100 if the last character is EOT
540 input_position++;
541 done = 1;
542 if (debug) {
543 printf("A ");
544 }
545 }
546
547 /* Step B1 */
548 if ((!done) && (encoding_mode == 'C')) {
549 if ((array_length == 0) && (length > 9)) {
550 if ((source[input_position] == '[')
551 && (source[input_position + 1] == ')')
552 && (source[input_position + 2] == '>')
553 && (source[input_position + 3] == 30) // RS
554 && (source[length - 1] == 04)) { // EOT
555
556
557 if ((source[input_position + 6] == 29) && (source[length - 2] == 30)) { // GS/RS
558 if ((source[input_position + 4] == '0') && (source[input_position + 5] == '5')) {
559 codeword_array[array_length] = 102; // Shift B
560 array_length++;
561 codeword_array[array_length] = 97; // Macro
562 array_length++;
563 input_position += 7;
564 inside_macro = 97;
565 done = 1;
566 if (debug) {
567 printf("B1/1 ");
568 }
569 }
570
571 if ((source[input_position + 4] == '0') && (source[input_position + 5] == '6')) {
572 codeword_array[array_length] = 102; // Shift B
573 array_length++;
574 codeword_array[array_length] = 98; // Macro
575 array_length++;
576 input_position += 7;
577 inside_macro = 98;
578 done = 1;
579 if (debug) {
580 printf("B1/2 ");
581 }
582 }
583
584 if ((source[input_position + 4] == '1') && (source[input_position + 5] == '2')) {
585 codeword_array[array_length] = 102; // Shift B
586 array_length++;
587 codeword_array[array_length] = 99; // Macro
588 array_length++;
589 input_position += 7;
590 inside_macro = 99;
591 done = 1;
592 if (debug) {
593 printf("B1/3 ");
594 }
595 }
596 }
597
598 if ((!done) && (source[input_position] >= '0') && (source[input_position] <= '9') &&
599 (source[input_position + 1] >= '0') && (source[input_position + 1] <= '9')) {
600 codeword_array[array_length] = 102; // Shift B
601 array_length++;
602 codeword_array[array_length] = 100; // Macro
603 array_length++;
604 input_position += 4;
605 inside_macro = 100;
606 done = 1;
607 if (debug) {
608 printf("B1/4 ");
609 }
610 }
611 }
612 }
613 }
614
615 /* Step B2 */
616 if ((!done) && (encoding_mode == 'C')) {
617 if (seventeen_ten(source, input_position, length)) {
618 codeword_array[array_length] = 100; // (17)...(10)
619 array_length++;
620 codeword_array[array_length] = ((source[input_position + 2] - '0') * 10) + (source[input_position + 3] - '0');
621 array_length++;
622 codeword_array[array_length] = ((source[input_position + 4] - '0') * 10) + (source[input_position + 5] - '0');
623 array_length++;
624 codeword_array[array_length] = ((source[input_position + 6] - '0') * 10) + (source[input_position + 7] - '0');
625 array_length++;
626 input_position += 10;
627 done = 1;
628 if (debug) {
629 printf("B2/1 ");
630 }
631 }
632 }
633
634 if ((!done) && (encoding_mode == 'C')) {
635 if (datum_c(source, input_position, length) || ((source[input_position] == '[') && (symbol->input_mode == GS1_MODE))) {
636 if (source[input_position] == '[') {
637 codeword_array[array_length] = 107; // FNC1
638 input_position++;
639 } else {
640 codeword_array[array_length] = ((source[input_position] - '0') * 10) + (source[input_position + 1] - '0');
641 input_position += 2;
642 }
643 array_length++;
644 done = 1;
645 if (debug) {
646 printf("B2/2 ");
647 }
648 }
649 }
650
651 /* Setp B3 */
652 if ((!done) && (encoding_mode == 'C')) {
653 if (binary(source, input_position)) {
654 if (n_digits(source, input_position + 1, length) > 0) {
655 if ((source[input_position] - 128) < 32) {
656 codeword_array[array_length] = 110; // Bin Shift A
657 array_length++;
658 codeword_array[array_length] = source[input_position] - 128 + 64;
659 array_length++;
660 } else {
661 codeword_array[array_length] = 111; // Bin Shift B
662 array_length++;
663 codeword_array[array_length] = source[input_position] - 128 - 32;
664 array_length++;
665 }
666 input_position++;
667 } else {
668 codeword_array[array_length] = 112; // Bin Latch
669 array_length++;
670 encoding_mode = 'X';
671 }
672 done = 1;
673 if (debug) {
674 printf("B3 ");
675 }
676 }
677 }
678
679 /* Step B4 */
680 if ((!done) && (encoding_mode == 'C')) {
681 int m = ahead_a(source, input_position, length);
682 int n = ahead_b(source, input_position, length);
683 if (m > n) {
684 codeword_array[array_length] = 101; // Latch A
685 array_length++;
686 encoding_mode = 'A';
687 } else {
688 if (n <= 4) {
689 codeword_array[array_length] = 101 + n; // nx Shift B
690 array_length++;
691
692 for (i = 0; i < n; i++) {
693 codeword_array[array_length] = source[input_position] - 32;
694 array_length++;
695 input_position++;
696 }
697 } else {
698 codeword_array[array_length] = 106; // Latch B
699 array_length++;
700 encoding_mode = 'B';
701 }
702 }
703 done = 1;
704 if (debug) {
705 printf("B4 ");
706 }
707 }
708
709 /* Step C1 */
710 if ((!done) && (encoding_mode == 'B')) {
711 int n = try_c(source, input_position, length);
712
713 if (n >= 2) {
714 if (n <= 4) {
715 codeword_array[array_length] = 103 + (n - 2); // nx Shift C
716 array_length++;
717 for (i = 0; i < n; i++) {
718 codeword_array[array_length] = ((source[input_position] - '0') * 10) + (source[input_position + 1] - '0');
719 array_length++;
720 input_position += 2;
721 }
722 } else {
723 codeword_array[array_length] = 106; // Latch C
724 array_length++;
725 encoding_mode = 'C';
726 }
727 done = 1;
728 if (debug) {
729 printf("C1 ");
730 }
731 }
732 }
733
734 /* Step C2 */
735 if ((!done) && (encoding_mode == 'B')) {
736 if ((source[input_position] == '[') && (symbol->input_mode == GS1_MODE)) {
737 codeword_array[array_length] = 107; // FNC1
738 array_length++;
739 input_position++;
740 done = 1;
741 if (debug) {
742 printf("C2/1 ");
743 }
744 } else {
745 if (datum_b(source, input_position, length)) {
746
747 if ((source[input_position] >= 32) && (source[input_position] <= 127)) {
748 codeword_array[array_length] = source[input_position] - 32;
749 done = 1;
750
751 } else if (source[input_position] == 13) {
752 /* CR/LF */
753 codeword_array[array_length] = 96;
754 input_position++;
755 done = 1;
756
757 } else if (input_position != 0) {
758 /* HT, FS, GS and RS in the first data position would be interpreted as a macro (see table 2) */
759 switch(source[input_position]) {
760 case 9: // HT
761 codeword_array[array_length] = 97;
762 break;
763 case 28: // FS
764 codeword_array[array_length] = 98;
765 break;
766 case 29: // GS
767 codeword_array[array_length] = 99;
768 break;
769 case 30: // RS
770 codeword_array[array_length] = 100;
771 break;
772 }
773 done = 1;
774 }
775
776 if (done == 1) {
777 array_length++;
778 input_position++;
779 if (debug) {
780 printf("C2/2 ");
781 }
782 }
783 }
784 }
785 }
786
787 /* Step C3 */
788 if ((!done) && (encoding_mode == 'B')) {
789 if (binary(source, input_position)) {
790 if (datum_b(source, input_position + 1, length)) {
791 if ((source[input_position] - 128) < 32) {
792 codeword_array[array_length] = 110; // Bin Shift A
793 array_length++;
794 codeword_array[array_length] = source[input_position] - 128 + 64;
795 array_length++;
796 } else {
797 codeword_array[array_length] = 111; // Bin Shift B
798 array_length++;
799 codeword_array[array_length] = source[input_position] - 128 - 32;
800 array_length++;
801 }
802 input_position++;
803 } else {
804 codeword_array[array_length] = 112; // Bin Latch
805 array_length++;
806 encoding_mode = 'X';
807 }
808 done = 1;
809 if (debug) {
810 printf("C3 ");
811 }
812 }
813 }
814
815 /* Step C4 */
816 if ((!done) && (encoding_mode == 'B')) {
817 if (ahead_a(source, input_position, length) == 1) {
818 codeword_array[array_length] = 101; // Shift A
819 array_length++;
820 if (source[input_position] < 32) {
821 codeword_array[array_length] = source[input_position] + 64;
822 } else {
823 codeword_array[array_length] = source[input_position] - 32;
824 }
825 array_length++;
826 input_position++;
827 } else {
828 codeword_array[array_length] = 102; // Latch A
829 array_length++;
830 encoding_mode = 'A';
831 }
832 done = 1;
833 if (debug) {
834 printf("C4 ");
835 }
836 }
837
838 /* Step D1 */
839 if ((!done) && (encoding_mode == 'A')) {
840 int n = try_c(source, input_position, length);
841 if (n >= 2) {
842 if (n <= 4) {
843 codeword_array[array_length] = 103 + (n - 2); // nx Shift C
844 array_length++;
845 for (i = 0; i < n; i++) {
846 codeword_array[array_length] = ((source[input_position] - '0') * 10) + (source[input_position + 1] - '0');
847 array_length++;
848 input_position += 2;
849 }
850 } else {
851 codeword_array[array_length] = 106; // Latch C
852 array_length++;
853 encoding_mode = 'C';
854 }
855 done = 1;
856 if (debug) {
857 printf("D1 ");
858 }
859 }
860 }
861
862 /* Step D2 */
863 if ((!done) && (encoding_mode == 'A')) {
864 if ((source[input_position] == '[') && (symbol->input_mode == GS1_MODE)) {
865 codeword_array[array_length] = 107; // FNC1
866 array_length++;
867 input_position++;
868 done = 1;
869 if (debug) {
870 printf("D2/1 ");
871 }
872 } else {
873 if (datum_a(source, input_position, length)) {
874 if (source[input_position] < 32) {
875 codeword_array[array_length] = source[input_position] + 64;
876 } else {
877 codeword_array[array_length] = source[input_position] - 32;
878 }
879 array_length++;
880 input_position++;
881 done = 1;
882 if (debug) {
883 printf("D2/2 ");
884 }
885 }
886 }
887 }
888
889 /* Step D3 */
890 if ((!done) && (encoding_mode == 'A')) {
891 if (binary(source, input_position)) {
892 if (datum_a(source, input_position + 1, length)) {
893 if ((source[input_position] - 128) < 32) {
894 codeword_array[array_length] = 110; // Bin Shift A
895 array_length++;
896 codeword_array[array_length] = source[input_position] - 128 + 64;
897 array_length++;
898 } else {
899 codeword_array[array_length] = 111; // Bin Shift B
900 array_length++;
901 codeword_array[array_length] = source[input_position] - 128 - 32;
902 array_length++;
903 }
904 input_position++;
905 } else {
906 codeword_array[array_length] = 112; // Bin Latch
907 array_length++;
908 encoding_mode = 'X';
909 }
910 done = 1;
911 if (debug) {
912 printf("D3 ");
913 }
914 }
915 }
916
917 /* Step D4 */
918 if ((!done) && (encoding_mode == 'A')) {
919 int n = ahead_b(source, input_position, length);
920
921 if (n <= 6) {
922 codeword_array[array_length] = 95 + n; // nx Shift B
923 array_length++;
924 for (i = 0; i < n; i++) {
925 codeword_array[array_length] = source[input_position] - 32;
926 array_length++;
927 input_position++;
928 }
929 } else {
930 codeword_array[array_length] = 102; // Latch B
931 array_length++;
932 encoding_mode = 'B';
933 }
934 done = 1;
935 if (debug) {
936 printf("D4 ");
937 }
938 }
939
940 /* Step E1 */
941 if ((!done) && (encoding_mode == 'X')) {
942 int n = try_c(source, input_position, length);
943
944 if (n >= 2) {
945 /* Empty binary buffer */
946 for (i = 0; i < (binary_buffer_size + 1); i++) {
947 lawrencium[i] = binary_buffer % 103;
948 binary_buffer /= 103;
949 }
950
951 for (i = 0; i < (binary_buffer_size + 1); i++) {
952 codeword_array[array_length] = lawrencium[binary_buffer_size - i];
953 array_length++;
954 }
955 binary_buffer = 0;
956 binary_buffer_size = 0;
957
958 if (n <= 7) {
959 codeword_array[array_length] = 101 + n; // Interrupt for nx Shift C
960 array_length++;
961 for (i = 0; i < n; i++) {
962 codeword_array[array_length] = ((source[input_position] - '0') * 10) + (source[input_position + 1] - '0');
963 array_length++;
964 input_position += 2;
965 }
966 } else {
967 codeword_array[array_length] = 111; // Terminate with Latch to C
968 array_length++;
969 encoding_mode = 'C';
970 }
971 done = 1;
972 if (debug) {
973 printf("E1 ");
974 }
975 }
976 }
977
978 /* Step E2 */
979 /* Section 5.2.1.1 para D.2.i states:
980 * "Groups of six codewords, each valued between 0 and 102, are radix converted from
981 * base 103 into five base 259 values..."
982 */
983 if ((!done) && (encoding_mode == 'X')) {
984 if (binary(source, input_position)
985 || binary(source, input_position + 1)
986 || binary(source, input_position + 2)
987 || binary(source, input_position + 3)) {
988 binary_buffer *= 259;
989 binary_buffer += source[input_position];
990 binary_buffer_size++;
991
992 if (binary_buffer_size == 5) {
993 for (i = 0; i < 6; i++) {
994 lawrencium[i] = binary_buffer % 103;
995 binary_buffer /= 103;
996 }
997
998 for (i = 0; i < 6; i++) {
999 codeword_array[array_length] = lawrencium[5 - i];
1000 array_length++;
1001 }
1002 binary_buffer = 0;
1003 binary_buffer_size = 0;
1004 }
1005 input_position++;
1006 done = 1;
1007 if (debug) {
1008 printf("E2 ");
1009 }
1010 }
1011 }
1012
1013 /* Step E3 */
1014 if ((!done) && (encoding_mode == 'X')) {
1015 /* Empty binary buffer */
1016 for (i = 0; i < (binary_buffer_size + 1); i++) {
1017 lawrencium[i] = binary_buffer % 103;
1018 binary_buffer /= 103;
1019 }
1020
1021 for (i = 0; i < (binary_buffer_size + 1); i++) {
1022 codeword_array[array_length] = lawrencium[binary_buffer_size - i];
1023 array_length++;
1024 }
1025 binary_buffer = 0;
1026 binary_buffer_size = 0;
1027
1028 if (ahead_a(source, input_position, length) > ahead_b(source, input_position, length)) {
1029 codeword_array[array_length] = 109; // Terminate with Latch to A
1030 encoding_mode = 'A';
1031 } else {
1032 codeword_array[array_length] = 110; // Terminate with Latch to B
1033 encoding_mode = 'B';
1034 }
1035 array_length++;
1036 done = 1;
1037 if (debug) {
1038 printf("E3 ");
1039 }
1040 }
1041 } while (input_position < length);
1042
1043 if (encoding_mode == 'X') {
1044 if (binary_buffer_size != 0) {
1045 /* Empty binary buffer */
1046 for (i = 0; i < (binary_buffer_size + 1); i++) {
1047 lawrencium[i] = binary_buffer % 103;
1048 binary_buffer /= 103;
1049 }
1050
1051 for (i = 0; i < (binary_buffer_size + 1); i++) {
1052 codeword_array[array_length] = lawrencium[binary_buffer_size - i];
1053 array_length++;
1054 }
1055 }
1056 *(binary_finish) = 1;
1057 }
1058
1059 if (debug) {
1060 printf("\n\n");
1061 }
1062
1063 return array_length;
1064 }
1065
1066 /* Convert codewords to binary data stream */
make_dotstream(unsigned char masked_array[],int array_length,char dot_stream[])1067 static size_t make_dotstream(unsigned char masked_array[], int array_length, char dot_stream[]) {
1068 int i;
1069
1070 dot_stream[0] = '\0';
1071
1072 /* Mask value is encoded as two dots */
1073 bin_append(masked_array[0], 2, dot_stream);
1074
1075 /* The rest of the data uses 9-bit dot patterns from Annex C */
1076 for (i = 1; i < array_length; i++) {
1077 bin_append(dot_patterns[masked_array[i]], 9, dot_stream);
1078 }
1079
1080 return strlen(dot_stream);
1081 }
1082
1083 /* Determines if a given dot is a reserved corner dot
1084 * to be used by one of the last six bits
1085 */
is_corner(int column,int row,int width,int height)1086 int is_corner(int column, int row, int width, int height) {
1087 int corner = 0;
1088
1089 /* Top Left */
1090 if ((column == 0) && (row == 0)) {
1091 corner = 1;
1092 }
1093
1094 /* Top Right */
1095 if (height % 2) {
1096 if (((column == width - 2) && (row == 0))
1097 || ((column == width - 1) && (row == 1))) {
1098 corner = 1;
1099 }
1100 } else {
1101 if ((column == width - 1) && (row == 0)) {
1102 corner = 1;
1103 }
1104 }
1105
1106 /* Bottom Left */
1107 if (height % 2) {
1108 if ((column == 0) && (row == height - 1)) {
1109 corner = 1;
1110 }
1111 } else {
1112 if (((column == 0) && (row == height - 2))
1113 || ((column == 1) && (row == height - 1))) {
1114 corner = 1;
1115 }
1116 }
1117
1118 /* Bottom Right */
1119 if (((column == width - 2) && (row == height - 1))
1120 || ((column == width - 1) && (row == height - 2))) {
1121 corner = 1;
1122 }
1123
1124 return corner;
1125 }
1126
1127 /* Place the dots in the symbol*/
fold_dotstream(char dot_stream[],int width,int height,char dot_array[])1128 void fold_dotstream(char dot_stream[], int width, int height, char dot_array[]) {
1129 int column, row;
1130 int input_position = 0;
1131
1132 if (height % 2) {
1133 /* Horizontal folding */
1134 for (row = 0; row < height; row++) {
1135 for (column = 0; column < width; column++) {
1136 if (!((column + row) % 2)) {
1137 if (is_corner(column, row, width, height)) {
1138 dot_array[(row * width) + column] = 'C';
1139 } else {
1140 dot_array[((height - row - 1) * width) + column] = dot_stream[input_position];
1141 input_position++;
1142 }
1143 } else {
1144 dot_array[((height - row - 1) * width) + column] = ' '; // Non-data position
1145 }
1146 }
1147 }
1148
1149 /* Corners */
1150 dot_array[width - 2] = dot_stream[input_position];
1151 input_position++;
1152 dot_array[(height * width) - 2] = dot_stream[input_position];
1153 input_position++;
1154 dot_array[(width * 2) - 1] = dot_stream[input_position];
1155 input_position++;
1156 dot_array[((height - 1) * width) - 1] = dot_stream[input_position];
1157 input_position++;
1158 dot_array[0] = dot_stream[input_position];
1159 input_position++;
1160 dot_array[(height - 1) * width] = dot_stream[input_position];
1161 } else {
1162 /* Vertical folding */
1163 for (column = 0; column < width; column++) {
1164 for (row = 0; row < height; row++) {
1165 if (!((column + row) % 2)) {
1166 if (is_corner(column, row, width, height)) {
1167 dot_array[(row * width) + column] = 'C';
1168 } else {
1169 dot_array[(row * width) + column] = dot_stream[input_position];
1170 input_position++;
1171 }
1172 } else {
1173 dot_array[(row * width) + column] = ' '; // Non-data position
1174 }
1175 }
1176 }
1177
1178 /* Corners */
1179 dot_array[((height - 1) * width) - 1] = dot_stream[input_position];
1180 input_position++;
1181 dot_array[(height - 2) * width] = dot_stream[input_position];
1182 input_position++;
1183 dot_array[(height * width) - 2] = dot_stream[input_position];
1184 input_position++;
1185 dot_array[((height - 1) * width) + 1] = dot_stream[input_position];
1186 input_position++;
1187 dot_array[width - 1] = dot_stream[input_position];
1188 input_position++;
1189 dot_array[0] = dot_stream[input_position];
1190 }
1191 }
1192
dotcode(struct zint_symbol * symbol,const unsigned char source[],int length)1193 int dotcode(struct zint_symbol *symbol, const unsigned char source[], int length) {
1194 int i, j, k;
1195 size_t jc, n_dots;
1196 int data_length, ecc_length;
1197 int min_dots, min_area;
1198 int height, width;
1199 int mask_score[4];
1200 int weight;
1201 size_t dot_stream_length;
1202 int high_score, best_mask;
1203 int binary_finish = 0;
1204 int debug = 0;
1205 int padding_dots, is_first;
1206 #ifdef _MSC_VER
1207 unsigned char* masked_codeword_array;
1208 #endif
1209
1210 #ifndef _MSC_VER
1211 unsigned char codeword_array[length * 3];
1212 #else
1213 char* dot_stream;
1214 char* dot_array;
1215 unsigned char* codeword_array = (unsigned char *) _alloca(length * 3 * sizeof (unsigned char));
1216 #endif /* _MSC_VER */
1217
1218 if (symbol->eci > 811799) {
1219 strcpy(symbol->errtxt, "525: Invalid ECI");
1220 return ZINT_ERROR_INVALID_OPTION;
1221 }
1222
1223 data_length = dotcode_encode_message(symbol, source, length, codeword_array, &binary_finish);
1224
1225 ecc_length = 3 + (data_length / 2);
1226
1227 if (debug) {
1228 printf("Codeword length = %d, ECC length = %d\n", data_length, ecc_length);
1229 }
1230
1231 min_dots = 9 * (data_length + 3 + (data_length / 2)) + 2;
1232 min_area = min_dots * 2;
1233
1234 if (symbol->option_2 == 0) {
1235 /* Automatic sizing */
1236 /* Following Rule 3 (Section 5.2.2) and applying a recommended width to height ratio 3:2 */
1237 /* Eliminates under sized symbols */
1238
1239 float h = (float) (sqrt(min_area * 0.666));
1240 float w = (float) (sqrt(min_area * 1.5));
1241
1242 height = (int) h;
1243 width = (int) w;
1244
1245 if ((width + height) % 2 == 1) {
1246 if ((width * height) < min_area) {
1247 width++;
1248 height++;
1249 }
1250 } else {
1251 if ((h * width) < (w * height)) {
1252 width++;
1253 if ((width * height) < min_area) {
1254 width--;
1255 height++;
1256 if ((width * height) < min_area) {
1257 width += 2;
1258 }
1259 }
1260 } else {
1261 height++;
1262 if ((width * height) < min_area) {
1263 width++;
1264 height--;
1265 if ((width * height) < min_area) {
1266 height += 2;
1267 }
1268 }
1269 }
1270 }
1271
1272 } else {
1273 /* User defined width */
1274 /* Eliminates under sized symbols */
1275
1276 width = symbol->option_2;
1277 height = (min_area + (width - 1)) / width;
1278
1279 if (!((width + height) % 2)) {
1280 height++;
1281 }
1282 }
1283
1284 if ((height > 200) || (width > 200)) {
1285 strcpy(symbol->errtxt, "526: Specified symbol size is too large (E20)");
1286 return ZINT_ERROR_INVALID_OPTION;
1287 }
1288
1289 n_dots = (height * width) / 2;
1290
1291 #ifndef _MSC_VER
1292 char dot_stream[height * width * 3];
1293 char dot_array[width * height * sizeof (char) ];
1294 #else
1295 dot_stream = (char *) _alloca(height * width * 3);
1296 if (!dot_stream) return ZINT_ERROR_MEMORY;
1297
1298 dot_array = (char *) _alloca(width * height * sizeof (char));
1299 if (!dot_array) return ZINT_ERROR_MEMORY;
1300 #endif
1301
1302 /* Add pad characters */
1303 padding_dots = n_dots - min_dots; /* get the number of free dots available for padding */
1304 is_first = 1; /* first padding character flag */
1305
1306 while (padding_dots >= 9) {
1307 if (padding_dots < 18 && ((data_length % 2) == 0))
1308 padding_dots -= 9;
1309
1310 else if (padding_dots >= 18) {
1311 if ((data_length % 2) == 0)
1312 padding_dots -= 9;
1313 else
1314 padding_dots -= 18;
1315 } else
1316 break; /* not enough padding dots left for padding */
1317
1318 if ((is_first == 1) && (binary_finish == 1))
1319 codeword_array[data_length] = 109;
1320 else
1321 codeword_array[data_length] = 106;
1322
1323 data_length++;
1324 is_first = 0;
1325 }
1326
1327 ecc_length = 3 + (data_length / 2);
1328
1329 #ifndef _MSC_VER
1330 unsigned char masked_codeword_array[data_length + 1 + ecc_length];
1331 #else
1332 masked_codeword_array = (unsigned char *) _alloca((data_length + 1 + ecc_length) * sizeof (unsigned char));
1333 #endif /* _MSC_VER */
1334
1335 /* Evaluate data mask options */
1336 for (i = 0; i < 4; i++) {
1337 switch (i) {
1338 case 0:
1339 masked_codeword_array[0] = 0;
1340 for (j = 0; j < data_length; j++) {
1341 masked_codeword_array[j + 1] = codeword_array[j];
1342 }
1343 break;
1344 case 1:
1345 weight = 0;
1346 masked_codeword_array[0] = 1;
1347 for (j = 0; j < data_length; j++) {
1348 masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
1349 weight += 3;
1350 }
1351 break;
1352 case 2:
1353 weight = 0;
1354 masked_codeword_array[0] = 2;
1355 for (j = 0; j < data_length; j++) {
1356 masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
1357 weight += 7;
1358 }
1359 break;
1360 case 3:
1361 weight = 0;
1362 masked_codeword_array[0] = 3;
1363 for (j = 0; j < data_length; j++) {
1364 masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
1365 weight += 17;
1366 }
1367 break;
1368 }
1369
1370 rsencode(data_length + 1, ecc_length, masked_codeword_array);
1371
1372 dot_stream_length = make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream);
1373
1374 /* Add pad bits */
1375 for (jc = dot_stream_length; jc < n_dots; jc++) {
1376 strcat(dot_stream, "1");
1377 }
1378
1379 fold_dotstream(dot_stream, width, height, dot_array);
1380
1381 mask_score[i] = score_array(dot_array, height, width);
1382
1383 if (debug) {
1384 printf("Mask %d score is %d\n", i, mask_score[i]);
1385 }
1386 }
1387
1388 high_score = mask_score[0];
1389 best_mask = 0;
1390
1391 for (i = 1; i < 4; i++) {
1392 if (mask_score[i] > high_score) {
1393 high_score = mask_score[i];
1394 best_mask = i;
1395 }
1396 }
1397
1398 if (best_mask != 3) {
1399 /* Reprocess to get symbol with best mask */
1400 switch (best_mask) {
1401 case 0:
1402 masked_codeword_array[0] = 0;
1403 for (j = 0; j < data_length; j++) {
1404 masked_codeword_array[j + 1] = codeword_array[j];
1405 }
1406 break;
1407 case 1:
1408 weight = 0;
1409 masked_codeword_array[0] = 1;
1410 for (j = 0; j < data_length; j++) {
1411 masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
1412 weight += 3;
1413 }
1414 break;
1415 case 2:
1416 weight = 0;
1417 masked_codeword_array[0] = 2;
1418 for (j = 0; j < data_length; j++) {
1419 masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
1420 weight += 7;
1421 }
1422 break;
1423 }
1424
1425 rsencode(data_length + 1, ecc_length, masked_codeword_array);
1426 dot_stream_length = make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream);
1427
1428 /* Add pad bits */
1429 for (jc = dot_stream_length; jc < n_dots; jc++) {
1430 strcat(dot_stream, "1");
1431 }
1432
1433 fold_dotstream(dot_stream, width, height, dot_array);
1434 } /* else { the version with the best mask is already in memory } */
1435
1436 if (debug) {
1437 for (k = 0; k < height; k++) {
1438 for (j = 0; j < width; j++) {
1439 printf("%c", dot_array[(k * width) + j]);
1440 }
1441 printf("\n");
1442 }
1443 }
1444
1445 /* Copy values to symbol */
1446 symbol->width = width;
1447 symbol->rows = height;
1448
1449 for (k = 0; k < height; k++) {
1450 for (j = 0; j < width; j++) {
1451 if (dot_array[(k * width) + j] == '1') {
1452 set_module(symbol, k, j);
1453 }
1454 }
1455 symbol->row_height[k] = 1;
1456 }
1457
1458 if (!(symbol->output_options & BARCODE_DOTTY_MODE)) {
1459 symbol->output_options += BARCODE_DOTTY_MODE;
1460 }
1461
1462 return 0;
1463 }