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 }