1 /* maxicode.c - Handles Maxicode */
2 
3 /*
4     libzint - the open source barcode library
5     Copyright (C) 2010-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 /* Includes corrections thanks to Monica Swanson @ Source Technologies */
34 
35 #include "common.h"
36 #include "maxicode.h"
37 #include "reedsol.h"
38 #include <string.h>
39 #include <stdlib.h>
40 
41 int maxi_codeword[144];
42 
43 /* Handles error correction of primary message */
maxi_do_primary_check()44 void maxi_do_primary_check() {
45     unsigned char data[15];
46     unsigned char results[15];
47     int j;
48     int datalen = 10;
49     int ecclen = 10;
50 
51     rs_init_gf(0x43);
52     rs_init_code(ecclen, 1);
53 
54     for (j = 0; j < datalen; j += 1)
55         data[j] = maxi_codeword[j];
56 
57     rs_encode(datalen, data, results);
58 
59     for (j = 0; j < ecclen; j += 1)
60         maxi_codeword[ datalen + j] = results[ecclen - 1 - j];
61     rs_free();
62 }
63 
64 /* Handles error correction of odd characters in secondary */
maxi_do_secondary_chk_odd(int ecclen)65 void maxi_do_secondary_chk_odd(int ecclen) {
66     unsigned char data[100];
67     unsigned char results[30];
68     int j;
69     int datalen = 68;
70 
71     rs_init_gf(0x43);
72     rs_init_code(ecclen, 1);
73 
74     if (ecclen == 20)
75         datalen = 84;
76 
77     for (j = 0; j < datalen; j += 1)
78         if (j & 1) // odd
79             data[(j - 1) / 2] = maxi_codeword[j + 20];
80 
81     rs_encode(datalen / 2, data, results);
82 
83     for (j = 0; j < (ecclen); j += 1)
84         maxi_codeword[ datalen + (2 * j) + 1 + 20 ] = results[ecclen - 1 - j];
85     rs_free();
86 }
87 
88 /* Handles error correction of even characters in secondary */
maxi_do_secondary_chk_even(int ecclen)89 void maxi_do_secondary_chk_even(int ecclen) {
90     unsigned char data[100];
91     unsigned char results[30];
92     int j;
93     int datalen = 68;
94 
95     if (ecclen == 20)
96         datalen = 84;
97 
98     rs_init_gf(0x43);
99     rs_init_code(ecclen, 1);
100 
101     for (j = 0; j < datalen + 1; j += 1)
102         if (!(j & 1)) // even
103             data[j / 2] = maxi_codeword[j + 20];
104 
105     rs_encode(datalen / 2, data, results);
106 
107     for (j = 0; j < (ecclen); j += 1)
108         maxi_codeword[ datalen + (2 * j) + 20] = results[ecclen - 1 - j];
109     rs_free();
110 }
111 
112 /* Moves everything up so that a shift or latch can be inserted */
maxi_bump(int set[],int character[],int bump_posn)113 void maxi_bump(int set[], int character[], int bump_posn) {
114     int i;
115 
116     for (i = 143; i > bump_posn; i--) {
117         set[i] = set[i - 1];
118         character[i] = character[i - 1];
119     }
120 }
121 
122 /* Format text according to Appendix A */
maxi_text_process(int mode,unsigned char source[],int length,int eci)123 int maxi_text_process(int mode, unsigned char source[], int length, int eci) {
124     /* This code doesn't make use of [Lock in C], [Lock in D]
125     and [Lock in E] and so is not always the most efficient at
126     compressing data, but should suffice for most applications */
127 
128     int set[144], character[144], i, j, done, count, current_set;
129 
130     if (length > 138) {
131         return ZINT_ERROR_TOO_LONG;
132     }
133 
134     for (i = 0; i < 144; i++) {
135         set[i] = -1;
136         character[i] = 0;
137     }
138 
139     for (i = 0; i < length; i++) {
140         /* Look up characters in table from Appendix A - this gives
141          value and code set for most characters */
142         set[i] = maxiCodeSet[source[i]];
143         character[i] = maxiSymbolChar[source[i]];
144     }
145 
146     /* If a character can be represented in more than one code set,
147     pick which version to use */
148     if (set[0] == 0) {
149         if (character[0] == 13) {
150             character[0] = 0;
151         }
152         set[0] = 1;
153     }
154 
155     for (i = 1; i < length; i++) {
156         if (set[i] == 0) {
157             done = 0;
158             /* Special character */
159             if (character[i] == 13) {
160                 /* Carriage Return */
161                 if (set[i - 1] == 5) {
162                     character[i] = 13;
163                     set[i] = 5;
164                 } else {
165                     if ((i != length - 1) && (set[i + 1] == 5)) {
166                         character[i] = 13;
167                         set[i] = 5;
168                     } else {
169                         character[i] = 0;
170                         set[i] = 1;
171                     }
172                 }
173                 done = 1;
174             }
175 
176             if ((character[i] == 28) && (done == 0)) {
177                 /* FS */
178                 if (set[i - 1] == 5) {
179                     character[i] = 32;
180                     set[i] = 5;
181                 } else {
182                     set[i] = set[i - 1];
183                 }
184                 done = 1;
185             }
186 
187             if ((character[i] == 29) && (done == 0)) {
188                 /* GS */
189                 if (set[i - 1] == 5) {
190                     character[i] = 33;
191                     set[i] = 5;
192                 } else {
193                     set[i] = set[i - 1];
194                 }
195                 done = 1;
196             }
197 
198             if ((character[i] == 30) && (done == 0)) {
199                 /* RS */
200                 if (set[i - 1] == 5) {
201                     character[i] = 34;
202                     set[i] = 5;
203                 } else {
204                     set[i] = set[i - 1];
205                 }
206                 done = 1;
207             }
208 
209             if ((character[i] == 32) && (done == 0)) {
210                 /* Space */
211                 if (set[i - 1] == 1) {
212                     character[i] = 32;
213                     set[i] = 1;
214                 }
215                 if (set[i - 1] == 2) {
216                     character[i] = 47;
217                     set[i] = 2;
218                 }
219                 if (set[i - 1] >= 3) {
220                     if (i != length - 1) {
221                         if (set[i + 1] == 1) {
222                             character[i] = 32;
223                             set[i] = 1;
224                         }
225                         if (set[i + 1] == 2) {
226                             character[i] = 47;
227                             set[i] = 2;
228                         }
229                         if (set[i + 1] >= 3) {
230                             character[i] = 59;
231                             set[i] = set[i - 1];
232                         }
233                     } else {
234                         character[i] = 59;
235                         set[i] = set[i - 1];
236                     }
237                 }
238                 done = 1;
239             }
240 
241             if ((character[i] == 44) && (done == 0)) {
242                 /* Comma */
243                 if (set[i - 1] == 2) {
244                     character[i] = 48;
245                     set[i] = 2;
246                 } else {
247                     if ((i != length - 1) && (set[i + 1] == 2)) {
248                         character[i] = 48;
249                         set[i] = 2;
250                     } else {
251                         set[i] = 1;
252                     }
253                 }
254                 done = 1;
255             }
256 
257             if ((character[i] == 46) && (done == 0)) {
258                 /* Full Stop */
259                 if (set[i - 1] == 2) {
260                     character[i] = 49;
261                     set[i] = 2;
262                 } else {
263                     if ((i != length - 1) && (set[i + 1] == 2)) {
264                         character[i] = 49;
265                         set[i] = 2;
266                     } else {
267                         set[i] = 1;
268                     }
269                 }
270                 done = 1;
271             }
272 
273             if ((character[i] == 47) && (done == 0)) {
274                 /* Slash */
275                 if (set[i - 1] == 2) {
276                     character[i] = 50;
277                     set[i] = 2;
278                 } else {
279                     if ((i != length - 1) && (set[i + 1] == 2)) {
280                         character[i] = 50;
281                         set[i] = 2;
282                     } else {
283                         set[i] = 1;
284                     }
285                 }
286                 done = 1;
287             }
288 
289             if ((character[i] == 58) && (done == 0)) {
290                 /* Colon */
291                 if (set[i - 1] == 2) {
292                     character[i] = 51;
293                     set[i] = 2;
294                 } else {
295                     if ((i != length - 1) && (set[i + 1] == 2)) {
296                         character[i] = 51;
297                         set[i] = 2;
298                     } else {
299                         set[i] = 1;
300                     }
301                 }
302                 done = 1;
303             }
304         }
305     }
306 
307     for (i = length; i < 144; i++) {
308         /* Add the padding */
309         if (set[length - 1] == 2) {
310             set[i] = 2;
311         } else {
312             set[i] = 1;
313         }
314         character[i] = 33;
315     }
316 
317     /* Find candidates for number compression */
318     if ((mode == 2) || (mode == 3)) {
319         j = 0;
320     } else {
321         j = 9;
322     }
323     /* Number compression not allowed in primary message */
324     count = 0;
325     for (i = j; i < 143; i++) {
326         if ((set[i] == 1) && ((character[i] >= 48) && (character[i] <= 57))) {
327             /* Character is a number */
328             count++;
329         } else {
330             count = 0;
331         }
332         if (count == 9) {
333             /* Nine digits in a row can be compressed */
334             set[i] = 6;
335             set[i - 1] = 6;
336             set[i - 2] = 6;
337             set[i - 3] = 6;
338             set[i - 4] = 6;
339             set[i - 5] = 6;
340             set[i - 6] = 6;
341             set[i - 7] = 6;
342             set[i - 8] = 6;
343             count = 0;
344         }
345     }
346 
347     /* Add shift and latch characters */
348     current_set = 1;
349     i = 0;
350     do {
351 
352         if ((set[i] != current_set) && (set[i] != 6)) {
353             switch (set[i]) {
354                 case 1:
355                     if (set[i + 1] == 1) {
356                         if (set[i + 2] == 1) {
357                             if (set[i + 3] == 1) {
358                                 /* Latch A */
359                                 maxi_bump(set, character, i);
360                                 character[i] = 63;
361                                 current_set = 1;
362                                 length++;
363                             } else {
364                                 /* 3 Shift A */
365                                 maxi_bump(set, character, i);
366                                 character[i] = 57;
367                                 length++;
368                                 i += 2;
369                             }
370                         } else {
371                             /* 2 Shift A */
372                             maxi_bump(set, character, i);
373                             character[i] = 56;
374                             length++;
375                             i++;
376                         }
377                     } else {
378                         /* Shift A */
379                         maxi_bump(set, character, i);
380                         character[i] = 59;
381                         length++;
382                     }
383                     break;
384                 case 2:
385                     if (set[i + 1] == 2) {
386                         /* Latch B */
387                         maxi_bump(set, character, i);
388                         character[i] = 63;
389                         current_set = 2;
390                         length++;
391                     } else {
392                         /* Shift B */
393                         maxi_bump(set, character, i);
394                         character[i] = 59;
395                         length++;
396                     }
397                     break;
398                 case 3:
399                     /* Shift C */
400                     maxi_bump(set, character, i);
401                     character[i] = 60;
402                     length++;
403                     break;
404                 case 4:
405                     /* Shift D */
406                     maxi_bump(set, character, i);
407                     character[i] = 61;
408                     length++;
409                     break;
410                 case 5:
411                     /* Shift E */
412                     maxi_bump(set, character, i);
413                     character[i] = 62;
414                     length++;
415                     break;
416             }
417             i++;
418         }
419         i++;
420     } while (i < 144);
421 
422     /* Number compression has not been forgotten! - It's handled below */
423     i = 0;
424     do {
425         if (set[i] == 6) {
426             /* Number compression */
427             char substring[11];
428             int value;
429 
430             for (j = 0; j < 9; j++) {
431                 substring[j] = character[i + j];
432             }
433             substring[9] = '\0';
434             value = atoi(substring);
435 
436             character[i] = 31; /* NS */
437             character[i + 1] = (value & 0x3f000000) >> 24;
438             character[i + 2] = (value & 0xfc0000) >> 18;
439             character[i + 3] = (value & 0x3f000) >> 12;
440             character[i + 4] = (value & 0xfc0) >> 6;
441             character[i + 5] = (value & 0x3f);
442 
443             i += 6;
444             for (j = i; j < 140; j++) {
445                 set[j] = set[j + 3];
446                 character[j] = character[j + 3];
447             }
448             length -= 3;
449         } else {
450             i++;
451         }
452     } while (i <= 143);
453 
454     /* Insert ECI at the beginning of message if needed */
455     /* Encode ECI assignment numbers according to table 3 */
456     if (eci != 3) {
457         maxi_bump(set, character, 0);
458         character[0] = 27; // ECI
459         if (eci <= 31) {
460             maxi_bump(set, character, 1);
461             character[1] = eci;
462             length += 2;
463         }
464         if ((eci >= 32) && (eci <= 1023)) {
465             maxi_bump(set, character, 1);
466             maxi_bump(set, character, 1);
467             character[1] = 0x20 + ((eci >> 6) & 0x0F);
468             character[2] = eci & 0x3F;
469             length += 3;
470         }
471         if ((eci >= 1024) && (eci <= 32767)) {
472             maxi_bump(set, character, 1);
473             maxi_bump(set, character, 1);
474             maxi_bump(set, character, 1);
475             character[1] = 0x30 + ((eci >> 12) & 0x03);
476             character[2] = (eci >> 6) & 0x3F;
477             character[3] = eci & 0x3F;
478             length += 4;
479         }
480         if (eci >= 32768) {
481             maxi_bump(set, character, 1);
482             maxi_bump(set, character, 1);
483             maxi_bump(set, character, 1);
484             maxi_bump(set, character, 1);
485             character[1] = 0x38 + ((eci >> 18) & 0x02);
486             character[2] = (eci >> 12) & 0x3F;
487             character[3] = (eci >> 6) & 0x3F;
488             character[4] = eci & 0x3F;
489             length += 5;
490         }
491     }
492 
493     if (((mode == 2) || (mode == 3)) && (length > 84)) {
494         return ZINT_ERROR_TOO_LONG;
495     }
496 
497     if (((mode == 4) || (mode == 6)) && (length > 93)) {
498         return ZINT_ERROR_TOO_LONG;
499     }
500 
501     if ((mode == 5) && (length > 77)) {
502         return ZINT_ERROR_TOO_LONG;
503     }
504 
505 
506     /* Copy the encoded text into the codeword array */
507     if ((mode == 2) || (mode == 3)) {
508         for (i = 0; i < 84; i++) { /* secondary only */
509             maxi_codeword[i + 20] = character[i];
510         }
511     }
512 
513     if ((mode == 4) || (mode == 6)) {
514         for (i = 0; i < 9; i++) { /* primary */
515             maxi_codeword[i + 1] = character[i];
516         }
517         for (i = 0; i < 84; i++) { /* secondary */
518             maxi_codeword[i + 20] = character[i + 9];
519         }
520     }
521 
522     if (mode == 5) {
523         for (i = 0; i < 9; i++) { /* primary */
524             maxi_codeword[i + 1] = character[i];
525         }
526         for (i = 0; i < 68; i++) { /* secondary */
527             maxi_codeword[i + 20] = character[i + 9];
528         }
529     }
530 
531     return 0;
532 }
533 
534 /* Format structured primary for Mode 2 */
maxi_do_primary_2(char postcode[],int country,int service)535 void maxi_do_primary_2(char postcode[], int country, int service) {
536     size_t postcode_length;
537    int    postcode_num, i;
538 
539     for (i = 0; i < 10; i++) {
540         if ((postcode[i] < '0') || (postcode[i] > '9')) {
541             postcode[i] = '\0';
542         }
543     }
544 
545     postcode_length = strlen(postcode);
546     postcode_num = atoi(postcode);
547 
548     maxi_codeword[0] = ((postcode_num & 0x03) << 4) | 2;
549     maxi_codeword[1] = ((postcode_num & 0xfc) >> 2);
550     maxi_codeword[2] = ((postcode_num & 0x3f00) >> 8);
551     maxi_codeword[3] = ((postcode_num & 0xfc000) >> 14);
552     maxi_codeword[4] = ((postcode_num & 0x3f00000) >> 20);
553     maxi_codeword[5] = ((postcode_num & 0x3c000000) >> 26) | ((postcode_length & 0x3) << 4);
554     maxi_codeword[6] = ((postcode_length & 0x3c) >> 2) | ((country & 0x3) << 4);
555     maxi_codeword[7] = (country & 0xfc) >> 2;
556     maxi_codeword[8] = ((country & 0x300) >> 8) | ((service & 0xf) << 2);
557     maxi_codeword[9] = ((service & 0x3f0) >> 4);
558 }
559 
560 /* Format structured primary for Mode 3 */
maxi_do_primary_3(char postcode[],int country,int service)561 void maxi_do_primary_3(char postcode[], int country, int service) {
562     int i, h;
563 
564     h = strlen(postcode);
565     to_upper((unsigned char*) postcode);
566     for (i = 0; i < h; i++) {
567         if ((postcode[i] >= 'A') && (postcode[i] <= 'Z')) {
568             /* (Capital) letters shifted to Code Set A values */
569             postcode[i] -= 64;
570         }
571         if (((postcode[i] == 27) || (postcode[i] == 31)) || ((postcode[i] == 33) || (postcode[i] >= 59))) {
572             /* Not a valid postcode character */
573             postcode[i] = ' ';
574         }
575         /* Input characters lower than 27 (NUL - SUB) in postcode are
576         interpreted as capital letters in Code Set A (e.g. LF becomes 'J') */
577     }
578 
579     maxi_codeword[0] = ((postcode[5] & 0x03) << 4) | 3;
580     maxi_codeword[1] = ((postcode[4] & 0x03) << 4) | ((postcode[5] & 0x3c) >> 2);
581     maxi_codeword[2] = ((postcode[3] & 0x03) << 4) | ((postcode[4] & 0x3c) >> 2);
582     maxi_codeword[3] = ((postcode[2] & 0x03) << 4) | ((postcode[3] & 0x3c) >> 2);
583     maxi_codeword[4] = ((postcode[1] & 0x03) << 4) | ((postcode[2] & 0x3c) >> 2);
584     maxi_codeword[5] = ((postcode[0] & 0x03) << 4) | ((postcode[1] & 0x3c) >> 2);
585     maxi_codeword[6] = ((postcode[0] & 0x3c) >> 2) | ((country & 0x3) << 4);
586     maxi_codeword[7] = (country & 0xfc) >> 2;
587     maxi_codeword[8] = ((country & 0x300) >> 8) | ((service & 0xf) << 2);
588     maxi_codeword[9] = ((service & 0x3f0) >> 4);
589 }
590 
maxicode(struct zint_symbol * symbol,unsigned char local_source[],int length)591 int maxicode(struct zint_symbol *symbol, unsigned char local_source[], int length) {
592     int i, j, block, bit, mode, countrycode = 0, service = 0, lp = 0;
593     int bit_pattern[7], internal_error = 0, eclen;
594     char postcode[12], countrystr[4], servicestr[4];
595 
596     mode = symbol->option_1;
597     strcpy(postcode, "");
598     strcpy(countrystr, "");
599     strcpy(servicestr, "");
600 
601     memset(maxi_codeword, 0, sizeof (maxi_codeword));
602 
603     if (mode == -1) { /* If mode is unspecified */
604         lp = strlen(symbol->primary);
605         if (lp == 0) {
606             mode = 4;
607         } else {
608             mode = 2;
609             for (i = 0; i < 10 && i < lp; i++) {
610                 if ((symbol->primary[i] < 48) || (symbol->primary[i] > 57)) {
611                     mode = 3;
612                     break;
613                 }
614             }
615         }
616     }
617 
618     if ((mode < 2) || (mode > 6)) { /* Only codes 2 to 6 supported */
619         strcpy(symbol->errtxt, "550: Invalid Maxicode Mode");
620         return ZINT_ERROR_INVALID_OPTION;
621     }
622 
623     if ((mode == 2) || (mode == 3)) { /* Modes 2 and 3 need data in symbol->primary */
624         if (lp == 0) { /* Mode set manually means lp doesn't get set */
625             lp = strlen(symbol->primary);
626         }
627         if (lp != 15) {
628             strcpy(symbol->errtxt, "551: Invalid Primary String");
629             return ZINT_ERROR_INVALID_DATA;
630         }
631 
632         for (i = 9; i < 15; i++) { /* check that country code and service are numeric */
633             if ((symbol->primary[i] < '0') || (symbol->primary[i] > '9')) {
634                 strcpy(symbol->errtxt, "552: Invalid Primary String");
635                 return ZINT_ERROR_INVALID_DATA;
636             }
637         }
638 
639         memcpy(postcode, symbol->primary, 9);
640         postcode[9] = '\0';
641 
642         if (mode == 2) {
643             for (i = 0; i < 10; i++) {
644                 if (postcode[i] == ' ') {
645                     postcode[i] = '\0';
646                 }
647             }
648         } else if (mode == 3) {
649             postcode[6] = '\0';
650         }
651 
652         countrystr[0] = symbol->primary[9];
653         countrystr[1] = symbol->primary[10];
654         countrystr[2] = symbol->primary[11];
655         countrystr[3] = '\0';
656 
657         servicestr[0] = symbol->primary[12];
658         servicestr[1] = symbol->primary[13];
659         servicestr[2] = symbol->primary[14];
660         servicestr[3] = '\0';
661 
662         countrycode = atoi(countrystr);
663         service = atoi(servicestr);
664 
665         if (mode == 2) {
666             maxi_do_primary_2(postcode, countrycode, service);
667         }
668         if (mode == 3) {
669             maxi_do_primary_3(postcode, countrycode, service);
670         }
671     } else {
672         maxi_codeword[0] = mode;
673     }
674 
675     i = maxi_text_process(mode, local_source, length, symbol->eci);
676     if (i == ZINT_ERROR_TOO_LONG) {
677         strcpy(symbol->errtxt, "553: Input data too long");
678         return i;
679     }
680 
681     /* All the data is sorted - now do error correction */
682     maxi_do_primary_check(); /* always EEC */
683 
684     if (mode == 5)
685         eclen = 56; // 68 data codewords , 56 error corrections
686     else
687         eclen = 40; // 84 data codewords,  40 error corrections
688 
689     maxi_do_secondary_chk_even(eclen / 2); // do error correction of even
690     maxi_do_secondary_chk_odd(eclen / 2); // do error correction of odd
691 
692     /* Copy data into symbol grid */
693     for (i = 0; i < 33; i++) {
694         for (j = 0; j < 30; j++) {
695             block = (MaxiGrid[(i * 30) + j] + 5) / 6;
696             bit = (MaxiGrid[(i * 30) + j] + 5) % 6;
697 
698             if (block != 0) {
699 
700                 bit_pattern[0] = (maxi_codeword[block - 1] & 0x20) >> 5;
701                 bit_pattern[1] = (maxi_codeword[block - 1] & 0x10) >> 4;
702                 bit_pattern[2] = (maxi_codeword[block - 1] & 0x8) >> 3;
703                 bit_pattern[3] = (maxi_codeword[block - 1] & 0x4) >> 2;
704                 bit_pattern[4] = (maxi_codeword[block - 1] & 0x2) >> 1;
705                 bit_pattern[5] = (maxi_codeword[block - 1] & 0x1);
706 
707                 if (bit_pattern[bit] != 0) {
708                     set_module(symbol, i, j);
709                 }
710             }
711         }
712     }
713 
714     /* Add orientation markings */
715     set_module(symbol, 0, 28); // Top right filler
716     set_module(symbol, 0, 29);
717     set_module(symbol, 9, 10); // Top left marker
718     set_module(symbol, 9, 11);
719     set_module(symbol, 10, 11);
720     set_module(symbol, 15, 7); // Left hand marker
721     set_module(symbol, 16, 8);
722     set_module(symbol, 16, 20); // Right hand marker
723     set_module(symbol, 17, 20);
724     set_module(symbol, 22, 10); // Bottom left marker
725     set_module(symbol, 23, 10);
726     set_module(symbol, 22, 17); // Bottom right marker
727     set_module(symbol, 23, 17);
728 
729     symbol->width = 30;
730     symbol->rows = 33;
731 
732     return internal_error;
733 }
734