1 /*  hanxin.c - Han Xin Code
2 
3     libzint - the open source barcode library
4     Copyright (C) 2009-2017 Robin Stuart <rstuart114@gmail.com>
5 
6     Redistribution and use in source and binary forms, with or without
7     modification, are permitted provided that the following conditions
8     are met:
9 
10     1. Redistributions of source code must retain the above copyright
11        notice, this list of conditions and the following disclaimer.
12     2. Redistributions in binary form must reproduce the above copyright
13        notice, this list of conditions and the following disclaimer in the
14        documentation and/or other materials provided with the distribution.
15     3. Neither the name of the project nor the names of its contributors
16        may be used to endorse or promote products derived from this software
17        without specific prior written permission.
18 
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22     ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29     SUCH DAMAGE.
30  */
31 
32 /* This code attempts to implement Han Xin Code according to AIMD-015:2010 (Rev 0.8) */
33 
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #ifdef _MSC_VER
38 #include <malloc.h>
39 #endif
40 #include "common.h"
41 #include "reedsol.h"
42 #include "hanxin.h"
43 #include "gb2312.h"
44 #include "gb18030.h"
45 #include "assert.h"
46 
47 /* Find which submode to use for a text character */
getsubmode(char input)48 int getsubmode(char input) {
49     int submode = 2;
50 
51     if ((input >= '0') && (input <= '9')) {
52         submode = 1;
53     }
54 
55     if ((input >= 'A') && (input <= 'Z')) {
56         submode = 1;
57     }
58 
59     if ((input >= 'a') && (input <= 'z')) {
60         submode = 1;
61     }
62 
63     return submode;
64 }
65 
66 /* Calculate the approximate length of the binary string */
calculate_binlength(char mode[],int source[],const size_t length,int eci)67 static int calculate_binlength(char mode[], int source[], const size_t length, int eci) {
68     size_t i;
69     char lastmode = 't';
70     int est_binlen = 0;
71     int submode = 1;
72 
73     if (eci != 3) {
74         est_binlen += 12;
75     }
76 
77     i = 0;
78     do {
79         switch (mode[i]) {
80             case 'n':
81                 if (lastmode != 'n') {
82                     est_binlen += 14;
83                     lastmode = 'n';
84                 }
85                 est_binlen += 4;
86                 break;
87             case 't':
88                 if (lastmode != 't') {
89                     est_binlen += 10;
90                     lastmode = 't';
91                     submode = 1;
92                 }
93                 if (getsubmode((char) source[i]) != submode) {
94                     est_binlen += 6;
95                     submode = getsubmode((char) source[i]);
96                 }
97                 est_binlen += 6;
98                 break;
99             case 'b':
100                 if (lastmode != 'b') {
101                     est_binlen += 17;
102                     lastmode = 'b';
103                 }
104                 est_binlen += 8;
105                 break;
106             case '1':
107                 if (lastmode != '1') {
108                     est_binlen += 16;
109                     lastmode = '1';
110                 }
111                 est_binlen += 12;
112                 break;
113             case '2':
114                 if (lastmode != '2') {
115                     est_binlen += 16;
116                     lastmode = '2';
117                 }
118                 est_binlen += 12;
119                 break;
120             case 'd':
121                 if (lastmode != 'd') {
122                     est_binlen += 16;
123                     lastmode = 'd';
124                 }
125                 est_binlen += 15;
126                 break;
127             case 'f':
128                 if (lastmode != 'f') {
129                     est_binlen += 4;
130                     lastmode = 'f';
131                 }
132                 est_binlen += 21;
133                 i++;
134                 break;
135         }
136         i++;
137     } while (i < length);
138 
139     return est_binlen;
140 }
141 
isRegion1(int glyph)142 int isRegion1(int glyph) {
143     int first_byte, second_byte;
144     int valid = 0;
145 
146     first_byte = (glyph & 0xff00) >> 8;
147     second_byte = glyph & 0xff;
148 
149     if ((first_byte >= 0xb0) && (first_byte <= 0xd7)) {
150         if ((second_byte >= 0xa1) && (second_byte <= 0xfe)) {
151             valid = 1;
152         }
153     }
154 
155     if ((first_byte >= 0xa1) && (first_byte <= 0xa3)) {
156         if ((second_byte >= 0xa1) && (second_byte <= 0xfe)) {
157             valid = 1;
158         }
159     }
160 
161     if ((glyph >= 0xa8a1) && (glyph <= 0xa8c0)) {
162         valid = 1;
163     }
164 
165     return valid;
166 }
167 
isRegion2(int glyph)168 int isRegion2(int glyph) {
169     int first_byte, second_byte;
170     int valid = 0;
171 
172     first_byte = (glyph & 0xff00) >> 8;
173     second_byte = glyph & 0xff;
174 
175     if ((first_byte >= 0xd8) && (first_byte <= 0xf7)) {
176         if ((second_byte >= 0xa1) && (second_byte <= 0xfe)) {
177             valid = 1;
178         }
179     }
180 
181     return valid;
182 }
183 
isDoubleByte(int glyph)184 int isDoubleByte(int glyph) {
185     int first_byte, second_byte;
186     int valid = 0;
187 
188     first_byte = (glyph & 0xff00) >> 8;
189     second_byte = glyph & 0xff;
190 
191     if ((first_byte >= 0x81) && (first_byte <= 0xfe)) {
192         if ((second_byte >= 0x40) && (second_byte <= 0x7e)) {
193             valid = 1;
194         }
195 
196         if ((second_byte >= 0x80) && (second_byte <= 0xfe)) {
197             valid = 1;
198         }
199     }
200 
201     return valid;
202 }
203 
isFourByte(int glyph,int glyph2)204 int isFourByte(int glyph, int glyph2) {
205     int first_byte, second_byte;
206     int third_byte, fourth_byte;
207     int valid = 0;
208 
209     first_byte = (glyph & 0xff00) >> 8;
210     second_byte = glyph & 0xff;
211     third_byte = (glyph2 & 0xff00) >> 8;
212     fourth_byte = glyph2 & 0xff;
213 
214     if ((first_byte >= 0x81) && (first_byte <= 0xfe)) {
215         if ((second_byte >= 0x30) && (second_byte <= 0x39)) {
216             if ((third_byte >= 0x81) && (third_byte <= 0xfe)) {
217                 if ((fourth_byte >= 0x30) && (fourth_byte <= 0x39)) {
218                     valid = 1;
219                 }
220             }
221         }
222     }
223 
224     return valid;
225 }
226 
227 /* Calculate mode switching */
hx_define_mode(char mode[],int source[],const size_t length)228 static void hx_define_mode(char mode[], int source[], const size_t length) {
229     size_t i;
230     char lastmode = 't';
231     int done;
232 
233     i = 0;
234     do {
235         done = 0;
236 
237         if (isRegion1(source[i])) {
238             mode[i] = '1';
239             done = 1;
240             i++;
241         }
242 
243         if ((done == 0) && (isRegion2(source[i]))) {
244             mode[i] = '2';
245             done = 1;
246             i++;
247         }
248 
249         if ((done == 0) && (isDoubleByte(source[i]))) {
250             mode[i] = 'd';
251             done = 1;
252             i++;
253         }
254 
255         if ((done == 0) && (i < length - 1)) {
256             if (isFourByte(source[i], source[i + 1])) {
257                 mode[i] = 'f';
258                 mode[i + 1] = 'f';
259                 done = 1;
260                 i += 2;
261             }
262         }
263 
264         if (done == 0) {
265             if ((source[i] >= '0') && (source[i] <= '9')) {
266                 mode[i] = 'n';
267                 if (lastmode != 'n') {
268                     lastmode = 'n';
269                 }
270             } else {
271                 if ((source[i] <= 127) && ((source[i] <= 27) || (source[i] >= 32))) {
272                     mode[i] = 't';
273                     if (lastmode != 't') {
274                         lastmode = 't';
275                     }
276                 } else {
277                     mode[i] = 'b';
278                     if (lastmode != 'b') {
279                         lastmode = 'b';
280                     }
281                 }
282             }
283             i++;
284         }
285     } while (i < length);
286     mode[length] = '\0';
287 }
288 
289 /* Convert Text 1 sub-mode character to encoding value, as given in table 3 */
lookup_text1(char input)290 int lookup_text1(char input) {
291     int encoding_value = 0;
292 
293     if ((input >= '0') && (input <= '9')) {
294         encoding_value = input - '0';
295     }
296 
297     if ((input >= 'A') && (input <= 'Z')) {
298         encoding_value = input - 'A' + 10;
299     }
300 
301     if ((input >= 'a') && (input <= 'z')) {
302         encoding_value = input - 'a' + 36;
303     }
304 
305     return encoding_value;
306 }
307 
308 /* Convert Text 2 sub-mode character to encoding value, as given in table 4 */
lookup_text2(char input)309 int lookup_text2(char input) {
310     int encoding_value = 0;
311 
312     if ((input >= 0) && (input <= 27)) {
313         encoding_value = input;
314     }
315 
316     if ((input >= ' ') && (input <= '/')) {
317         encoding_value = input - ' ' + 28;
318     }
319 
320     if ((input >= '[') && (input <= 96)) {
321         encoding_value = input - '[' + 51;
322     }
323 
324     if ((input >= '{') && (input <= 127)) {
325         encoding_value = input - '{' + 57;
326     }
327 
328     return encoding_value;
329 }
330 
331 /* Convert input data to binary stream */
calculate_binary(char binary[],char mode[],int source[],const size_t length,const int eci,int debug)332 static void calculate_binary(char binary[], char mode[], int source[], const size_t length, const int eci, int debug) {
333     int block_length;
334     int position = 0;
335     int i, count, encoding_value;
336     int first_byte, second_byte;
337     int third_byte, fourth_byte;
338     int glyph;
339     int submode;
340 
341     if (eci != 3) {
342         /* Encoding ECI assignment number, according to Table 5 */
343         bin_append(8, 4, binary); // ECI
344         if (eci <= 127) {
345             bin_append(eci, 8, binary);
346         }
347         if ((eci >= 128) && (eci <= 16383)) {
348             strcat(binary, "10");
349             bin_append(eci, 14, binary);
350         }
351         if (eci >= 16384) {
352             strcat(binary, "110");
353             bin_append(eci, 21, binary);
354         }
355     }
356 
357     do {
358         block_length = 0;
359         do {
360             block_length++;
361         } while (mode[position + block_length] == mode[position]);
362 
363         switch (mode[position]) {
364             case 'n':
365                 /* Numeric mode */
366                 /* Mode indicator */
367                 bin_append(1, 4, binary);
368 
369                 if (debug) {
370                     printf("Numeric\n");
371                 }
372 
373                 i = 0;
374 
375                 while (i < block_length) {
376                     int first = 0, second = 0, third = 0;
377 
378                     first = posn(NEON, (char) source[position + i]);
379                     count = 1;
380                     encoding_value = first;
381 
382                     if (i + 1 < block_length && mode[position + i + 1] == 'n') {
383                         second = posn(NEON, (char) source[position + i + 1]);
384                         count = 2;
385                         encoding_value = (encoding_value * 10) + second;
386 
387                         if (i + 2 < block_length && mode[position + i + 2] == 'n') {
388                             third = posn(NEON, (char) source[position + i + 2]);
389                             count = 3;
390                             encoding_value = (encoding_value * 10) + third;
391                         }
392                     }
393 
394                     bin_append(encoding_value, 10, binary);
395 
396                     if (debug) {
397                         printf("0x%4x (%d)", encoding_value, encoding_value);
398                     }
399 
400                     i += count;
401                 }
402 
403                 /* Mode terminator depends on number of characters in last group (Table 2) */
404                 switch (count) {
405                     case 1:
406                         bin_append(1021, 10, binary);
407                         break;
408                     case 2:
409                         bin_append(1022, 10, binary);
410                         break;
411                     case 3:
412                         bin_append(1023, 10, binary);
413                         break;
414                 }
415 
416                 if (debug) {
417                     printf(" (TERM %d)\n", count);
418                 }
419 
420                 break;
421             case 't':
422                 /* Text mode */
423                 if (position != 0) {
424                     /* Mode indicator */
425                     bin_append(2, 4, binary);
426 
427                     if (debug) {
428                         printf("Text\n");
429                     }
430                 }
431 
432                 submode = 1;
433 
434                 i = 0;
435 
436                 while (i < block_length) {
437 
438                     if (getsubmode((char) source[i + position]) != submode) {
439                         /* Change submode */
440                         bin_append(62, 6, binary);
441                         submode = getsubmode((char) source[i + position]);
442                         if (debug) {
443                             printf("SWITCH ");
444                         }
445                     }
446 
447                     if (submode == 1) {
448                         encoding_value = lookup_text1((char) source[i + position]);
449                     } else {
450                         encoding_value = lookup_text2((char) source[i + position]);
451                     }
452 
453                     bin_append(encoding_value, 6, binary);
454 
455                     if (debug) {
456                         printf("%c (%d) ", (char) source[i], encoding_value);
457                     }
458                     i++;
459                 }
460 
461                 /* Terminator */
462                 bin_append(63, 6, binary);
463 
464                 if (debug) {
465                     printf("\n");
466                 }
467                 break;
468             case 'b':
469                 /* Binary Mode */
470                 /* Mode indicator */
471                 bin_append(3, 4, binary);
472 
473                 /* Count indicator */
474                 bin_append(block_length, 13, binary);
475 
476                 if (debug) {
477                     printf("Binary (length %d)\n", block_length);
478                 }
479 
480                 i = 0;
481 
482                 while (i < block_length) {
483 
484                     /* 8-bit bytes with no conversion */
485                     bin_append(source[i + position], 8, binary);
486 
487                     if (debug) {
488                         printf("%d ", source[i + position]);
489                     }
490 
491                     i++;
492                 }
493 
494                 if (debug) {
495                     printf("\n");
496                 }
497                 break;
498             case '1':
499                 /* Region 1 encoding */
500                 /* Mode indicator */
501                 bin_append(4, 4, binary);
502 
503                 if (debug) {
504                     printf("Region 1\n");
505                 }
506 
507                 i = 0;
508 
509                 while (i < block_length) {
510                     first_byte = (source[i + position] & 0xff00) >> 8;
511                     second_byte = source[i + position] & 0xff;
512 
513                     /* Subset 1 */
514                     glyph = (0x5e * (first_byte - 0xb0)) + (second_byte - 0xa1);
515 
516                     /* Subset 2 */
517                     if ((first_byte >= 0xa1) && (first_byte <= 0xa3)) {
518                         if ((second_byte >= 0xa1) && (second_byte <= 0xfe)) {
519                             glyph = (0x5e * first_byte - 0xa1) + (second_byte - 0xa1) + 0xeb0;
520                         }
521                     }
522 
523                     /* Subset 3 */
524                     if ((source[i + position] >= 0xa8a1) && (source[i + position] <= 0xa8c0)) {
525                         glyph = (second_byte - 0xa1) + 0xfca;
526                     }
527 
528                     if (debug) {
529                         printf("%d ", glyph);
530                     }
531 
532                     bin_append(glyph, 12, binary);
533                     i++;
534                 }
535 
536                 /* Terminator */
537                 bin_append(4095, 12, binary);
538 
539                 if (debug) {
540                     printf("\n");
541                 }
542 
543                 break;
544             case '2':
545                 /* Region 2 encoding */
546                 /* Mode indicator */
547                 bin_append(5, 4, binary);
548 
549                 if (debug) {
550                     printf("Region 2\n");
551                 }
552 
553                 i = 0;
554 
555                 while (i < block_length) {
556                     first_byte = (source[i + position] & 0xff00) >> 8;
557                     second_byte = source[i + position] & 0xff;
558 
559                     glyph = (0x5e * (first_byte - 0xd8)) + (second_byte - 0xa1);
560 
561                     if (debug) {
562                         printf("%d ", glyph);
563                     }
564 
565                     bin_append(glyph, 12, binary);
566                     i++;
567                 }
568 
569                 /* Terminator */
570                 bin_append(4095, 12, binary);
571 
572                 if (debug) {
573                     printf("\n");
574                 }
575                 break;
576             case 'd':
577                 /* Double byte encoding */
578                 /* Mode indicator */
579                 bin_append(6, 4, binary);
580 
581                 if (debug) {
582                     printf("Double byte\n");
583                 }
584 
585                 i = 0;
586 
587                 while (i < block_length) {
588                     first_byte = (source[i + position] & 0xff00) >> 8;
589                     second_byte = source[i + position] & 0xff;
590 
591                     if (second_byte <= 0x7e) {
592                         glyph = (0xbe * (first_byte - 0x81)) + (second_byte - 0x40);
593                     } else {
594                         glyph = (0xbe * (first_byte - 0x81)) + (second_byte - 0x41);
595                     }
596 
597                     if (debug) {
598                         printf("%d ", glyph);
599                     }
600 
601                     bin_append(glyph, 15, binary);
602                     i++;
603                 }
604 
605                 /* Terminator */
606                 bin_append(32767, 15, binary);
607                 /* Terminator sequence of length 12 is a mistake
608                    - confirmed by Wang Yi */
609 
610                 if (debug) {
611                     printf("\n");
612                 }
613                 break;
614             case 'f':
615                 /* Four-byte encoding */
616                 if (debug) {
617                     printf("Four byte\n");
618                 }
619 
620                 i = 0;
621 
622                 while (i < block_length) {
623 
624                     /* Mode indicator */
625                     bin_append(7, 4, binary);
626 
627                     first_byte = (source[i + position] & 0xff00) >> 8;
628                     second_byte = source[i + position] & 0xff;
629                     third_byte = (source[i + position + 1] & 0xff00) >> 8;
630                     fourth_byte = source[i + position + 1] & 0xff;
631 
632                     glyph = (0x3138 * (first_byte - 0x81)) + (0x04ec * (second_byte - 0x30)) +
633                             (0x0a * (third_byte - 0x81)) + (fourth_byte - 0x30);
634 
635                     if (debug) {
636                         printf("%d ", glyph);
637                     }
638 
639                     bin_append(glyph, 15, binary);
640                     i += 2;
641                 }
642 
643                 /* No terminator */
644 
645                 if (debug) {
646                     printf("\n");
647                 }
648                 break;
649 
650         }
651 
652         position += block_length;
653 
654     } while (position < length);
655 }
656 
657 /* Finder pattern for top left of symbol */
hx_place_finder_top_left(unsigned char * grid,int size)658 void hx_place_finder_top_left(unsigned char* grid, int size) {
659     int xp, yp;
660     int x = 0, y = 0;
661     char finder[] = {0x7F, 0x40, 0x5F, 0x50, 0x57, 0x57, 0x57};
662 
663     for (xp = 0; xp < 7; xp++) {
664         for (yp = 0; yp < 7; yp++) {
665             if (finder[yp] & 0x40 >> xp) {
666                 grid[((yp + y) * size) + (xp + x)] = 0x11;
667             } else {
668                 grid[((yp + y) * size) + (xp + x)] = 0x10;
669             }
670         }
671     }
672 }
673 
674 /* Finder pattern for top right and bottom left of symbol */
hx_place_finder(unsigned char * grid,int size,int x,int y)675 void hx_place_finder(unsigned char* grid, int size, int x, int y) {
676     int xp, yp;
677     char finder[] = {0x7F, 0x01, 0x7D, 0x05, 0x75, 0x75, 0x75};
678 
679     for (xp = 0; xp < 7; xp++) {
680         for (yp = 0; yp < 7; yp++) {
681             if (finder[yp] & 0x40 >> xp) {
682                 grid[((yp + y) * size) + (xp + x)] = 0x11;
683             } else {
684                 grid[((yp + y) * size) + (xp + x)] = 0x10;
685             }
686         }
687     }
688 }
689 
690 /* Finder pattern for bottom right of symbol */
hx_place_finder_bottom_right(unsigned char * grid,int size)691 void hx_place_finder_bottom_right(unsigned char* grid, int size) {
692     int xp, yp;
693     int x = size - 7, y = size - 7;
694     char finder[] = {0x75, 0x75, 0x75, 0x05, 0x7D, 0x01, 0x7F};
695 
696     for (xp = 0; xp < 7; xp++) {
697         for (yp = 0; yp < 7; yp++) {
698             if (finder[yp] & 0x40 >> xp) {
699                 grid[((yp + y) * size) + (xp + x)] = 0x11;
700             } else {
701                 grid[((yp + y) * size) + (xp + x)] = 0x10;
702             }
703         }
704     }
705 }
706 
707 /* Avoid plotting outside symbol or over finder patterns */
hx_safe_plot(unsigned char * grid,int size,int x,int y,int value)708 void hx_safe_plot(unsigned char *grid, int size, int x, int y, int value) {
709     if ((x >= 0) && (x < size)) {
710         if ((y >= 0) && (y < size)) {
711             if (grid[(y * size) + x] == 0) {
712                 grid[(y * size) + x] = value;
713             }
714         }
715     }
716 }
717 
718 /* Plot an alignment pattern around top and right of a module */
hx_plot_alignment(unsigned char * grid,int size,int x,int y,int w,int h)719 void hx_plot_alignment(unsigned char *grid, int size, int x, int y, int w, int h) {
720     int i;
721     hx_safe_plot(grid, size, x, y, 0x11);
722     hx_safe_plot(grid, size, x - 1, y + 1, 0x10);
723 
724     for (i = 1; i <= w; i++) {
725         /* Top */
726         hx_safe_plot(grid, size, x - i, y, 0x11);
727         hx_safe_plot(grid, size, x - i - 1, y + 1, 0x10);
728     }
729 
730     for (i = 1; i < h; i++) {
731         /* Right */
732         hx_safe_plot(grid, size, x, y + i, 0x11);
733         hx_safe_plot(grid, size, x - 1, y + i + 1, 0x10);
734     }
735 }
736 
737 /* Plot assistant alignment patterns */
hx_plot_assistant(unsigned char * grid,int size,int x,int y)738 void hx_plot_assistant(unsigned char *grid, int size, int x, int y) {
739     hx_safe_plot(grid, size, x - 1, y - 1, 0x10);
740     hx_safe_plot(grid, size, x, y - 1, 0x10);
741     hx_safe_plot(grid, size, x + 1, y - 1, 0x10);
742     hx_safe_plot(grid, size, x - 1, y, 0x10);
743     hx_safe_plot(grid, size, x, y, 0x11);
744     hx_safe_plot(grid, size, x + 1, y, 0x10);
745     hx_safe_plot(grid, size, x - 1, y + 1, 0x10);
746     hx_safe_plot(grid, size, x, y + 1, 0x10);
747     hx_safe_plot(grid, size, x + 1, y + 1, 0x10);
748 }
749 
750 /* Put static elements in the grid */
hx_setup_grid(unsigned char * grid,int size,int version)751 void hx_setup_grid(unsigned char* grid, int size, int version) {
752     int i, j;
753 
754     for (i = 0; i < size; i++) {
755         for (j = 0; j < size; j++) {
756             grid[(i * size) + j] = 0;
757         }
758     }
759 
760     /* Add finder patterns */
761     hx_place_finder_top_left(grid, size);
762     hx_place_finder(grid, size, 0, size - 7);
763     hx_place_finder(grid, size, size - 7, 0);
764     hx_place_finder_bottom_right(grid, size);
765 
766     /* Add finder pattern separator region */
767     for (i = 0; i < 8; i++) {
768         /* Top left */
769         grid[(7 * size) + i] = 0x10;
770         grid[(i * size) + 7] = 0x10;
771 
772         /* Top right */
773         grid[(7 * size) + (size - i - 1)] = 0x10;
774         grid[((size - i - 1) * size) + 7] = 0x10;
775 
776         /* Bottom left */
777         grid[(i * size) + (size - 8)] = 0x10;
778         grid[((size - 8) * size) + i] = 0x10;
779 
780         /* Bottom right */
781         grid[((size - 8) * size) + (size - i - 1)] = 0x10;
782         grid[((size - i - 1) * size) + (size - 8)] = 0x10;
783     }
784 
785     /* Reserve function information region */
786     for (i = 0; i < 9; i++) {
787         /* Top left */
788         grid[(8 * size) + i] = 0x10;
789         grid[(i * size) + 8] = 0x10;
790 
791         /* Top right */
792         grid[(8 * size) + (size - i - 1)] = 0x10;
793         grid[((size - i - 1) * size) + 8] = 0x10;
794 
795         /* Bottom left */
796         grid[(i * size) + (size - 9)] = 0x10;
797         grid[((size - 9) * size) + i] = 0x10;
798 
799         /* Bottom right */
800         grid[((size - 9) * size) + (size - i - 1)] = 0x10;
801         grid[((size - i - 1) * size) + (size - 9)] = 0x10;
802     }
803 
804     if (version > 3) {
805         int k = hx_module_k[version - 1];
806         int r = hx_module_r[version - 1];
807         int m = hx_module_m[version - 1];
808         int x, y, row_switch, column_switch;
809         int module_height, module_width;
810         int mod_x, mod_y;
811 
812         /* Add assistant alignment patterns to left and right */
813         y = 0;
814         mod_y = 0;
815         do {
816             if (mod_y < m) {
817                 module_height = k;
818             } else {
819                 module_height = r - 1;
820             }
821 
822             if ((mod_y % 2) == 0) {
823                 if ((m % 2) == 1) {
824                     hx_plot_assistant(grid, size, 0, y);
825                 }
826             } else {
827                 if ((m % 2) == 0) {
828                     hx_plot_assistant(grid, size, 0, y);
829                 }
830                 hx_plot_assistant(grid, size, size - 1, y);
831             }
832 
833             mod_y++;
834             y += module_height;
835         } while (y < size);
836 
837         /* Add assistant alignment patterns to top and bottom */
838         x = (size - 1);
839         mod_x = 0;
840         do {
841             if (mod_x < m) {
842                 module_width = k;
843             } else {
844                 module_width = r - 1;
845             }
846 
847             if ((mod_x % 2) == 0) {
848                 if ((m % 2) == 1) {
849                     hx_plot_assistant(grid, size, x, (size - 1));
850                 }
851             } else {
852                 if ((m % 2) == 0) {
853                     hx_plot_assistant(grid, size, x, (size - 1));
854                 }
855                 hx_plot_assistant(grid, size, x, 0);
856             }
857 
858             mod_x++;
859             x -= module_width;
860         } while (x >= 0);
861 
862         /* Add alignment pattern */
863         column_switch = 1;
864         y = 0;
865         mod_y = 0;
866         do {
867             if (mod_y < m) {
868                 module_height = k;
869             } else {
870                 module_height = r - 1;
871             }
872 
873             if (column_switch == 1) {
874                 row_switch = 1;
875                 column_switch = 0;
876             } else {
877                 row_switch = 0;
878                 column_switch = 1;
879             }
880 
881             x = (size - 1);
882             mod_x = 0;
883             do {
884                 if (mod_x < m) {
885                     module_width = k;
886                 } else {
887                     module_width = r - 1;
888                 }
889 
890                 if (row_switch == 1) {
891                     if (!(y == 0 && x == (size - 1))) {
892                         hx_plot_alignment(grid, size, x, y, module_width, module_height);
893                     }
894                     row_switch = 0;
895                 } else {
896                     row_switch = 1;
897                 }
898                 mod_x++;
899                 x -= module_width;
900             } while (x >= 0);
901 
902             mod_y++;
903             y += module_height;
904         } while (y < size);
905     }
906 }
907 
908 /* Calculate error correction codes */
hx_add_ecc(unsigned char fullstream[],unsigned char datastream[],int version,int ecc_level)909 void hx_add_ecc(unsigned char fullstream[], unsigned char datastream[], int version, int ecc_level) {
910     unsigned char data_block[180];
911     unsigned char ecc_block[36];
912     int i, j, block;
913     int batch_size, data_length, ecc_length;
914     int input_position = -1;
915     int output_position = -1;
916     int table_d1_pos = ((version - 1) * 36) + ((ecc_level - 1) * 9);
917 
918     for (i = 0; i < 3; i++) {
919         batch_size = hx_table_d1[table_d1_pos + (3 * i)];
920         data_length = hx_table_d1[table_d1_pos + (3 * i) + 1];
921         ecc_length = hx_table_d1[table_d1_pos + (3 * i) + 2];
922 
923         for (block = 0; block < batch_size; block++) {
924             for (j = 0; j < data_length; j++) {
925                 input_position++;
926                 output_position++;
927                 data_block[j] = datastream[input_position];
928                 fullstream[output_position] = datastream[input_position];
929             }
930 
931             rs_init_gf(0x163); // x^8 + x^6 + x^5 + x + 1 = 0
932             rs_init_code(ecc_length, 1);
933             rs_encode(data_length, data_block, ecc_block);
934             rs_free();
935 
936             for (j = 0; j < ecc_length; j++) {
937                 output_position++;
938                 fullstream[output_position] = ecc_block[ecc_length - j - 1];
939             }
940         }
941     }
942 }
943 
944 /* Rearrange data in batches of 13 codewords (section 5.8.2) */
make_picket_fence(unsigned char fullstream[],unsigned char picket_fence[],int streamsize)945 void make_picket_fence(unsigned char fullstream[], unsigned char picket_fence[], int streamsize) {
946     int i, start;
947     int output_position = 0;
948 
949     for (start = 0; start < 13; start++) {
950         for (i = start; i < streamsize; i += 13) {
951             if (i < streamsize) {
952                 picket_fence[output_position] = fullstream[i];
953                 output_position++;
954             }
955         }
956     }
957 }
958 
959 /* Evaluate a bitmask according to table 9 */
hx_evaluate(unsigned char * eval,int size,int pattern)960 int hx_evaluate(unsigned char *eval, int size, int pattern) {
961     int x, y, block, weight;
962     int result = 0;
963     char state;
964     int p;
965     int a, b, afterCount, beforeCount;
966 #ifndef _MSC_VER
967     char local[size * size];
968 #else
969     char* local = (char *) _alloca((size * size) * sizeof (char));
970 #endif
971 
972     /* all four bitmask variants have been encoded in the 4 bits of the bytes
973      * that make up the grid array. select them for evaluation according to the
974      * desired pattern.*/
975     for (x = 0; x < size; x++) {
976         for (y = 0; y < size; y++) {
977             if ((eval[(y * size) + x] & (0x01 << pattern)) != 0) {
978                 local[(y * size) + x] = '1';
979             } else {
980                 local[(y * size) + x] = '0';
981             }
982         }
983     }
984 
985     /* Test 1: 1:1:1:1:3  or 3:1:1:1:1 ratio pattern in row/column */
986     /* Vertical */
987     for (x = 0; x < size; x++) {
988         for (y = 0; y < (size - 7); y++) {
989             p = 0;
990             for (weight = 0; weight < 7; weight++) {
991                 if (local[((y + weight) * size) + x] == '1') {
992                     p += (0x40 >> weight);
993                 }
994             }
995             if ((p == 0x57) || (p == 0x75)) {
996                 /* Pattern found, check before and after */
997                 beforeCount = 0;
998                 for (b = (y - 3); b < y; b++) {
999                     if (b < 0) {
1000                         beforeCount++;
1001                     } else {
1002                         if (local[(b * size) + x] == '0') {
1003                             beforeCount++;
1004                         } else {
1005                             beforeCount = 0;
1006                         }
1007                     }
1008                 }
1009 
1010                 afterCount = 0;
1011                 for (a = (y + 7); a <= (y + 9); a++) {
1012                     if (a >= size) {
1013                         afterCount++;
1014                     } else {
1015                         if (local[(a * size) + x] == '0') {
1016                             afterCount++;
1017                         } else {
1018                             afterCount = 0;
1019                         }
1020                     }
1021                 }
1022 
1023                 if ((beforeCount == 3) || (afterCount == 3)) {
1024                     /* Pattern is preceeded or followed by light area
1025                        3 modules wide */
1026                     result += 50;
1027                 }
1028             }
1029         }
1030     }
1031 
1032     /* Horizontal */
1033     for (y = 0; y < size; y++) {
1034         for (x = 0; x < (size - 7); x++) {
1035             p = 0;
1036             for (weight = 0; weight < 7; weight++) {
1037                 if (local[(y * size) + x + weight] == '1') {
1038                     p += (0x40 >> weight);
1039                 }
1040             }
1041             if ((p == 0x57) || (p == 0x75)) {
1042                 /* Pattern found, check before and after */
1043                 beforeCount = 0;
1044                 for (b = (x - 3); b < x; b++) {
1045                     if (b < 0) {
1046                         beforeCount++;
1047                     } else {
1048                         if (local[(y * size) + b] == '0') {
1049                             beforeCount++;
1050                         } else {
1051                             beforeCount = 0;
1052                         }
1053                     }
1054                 }
1055 
1056                 afterCount = 0;
1057                 for (a = (x + 7); a <= (x + 9); a++) {
1058                     if (a >= size) {
1059                         afterCount++;
1060                     } else {
1061                         if (local[(y * size) + a] == '0') {
1062                             afterCount++;
1063                         } else {
1064                             afterCount = 0;
1065                         }
1066                     }
1067                 }
1068 
1069                 if ((beforeCount == 3) || (afterCount == 3)) {
1070                     /* Pattern is preceeded or followed by light area
1071                        3 modules wide */
1072                     result += 50;
1073                 }
1074             }
1075         }
1076     }
1077 
1078     /* Test 2: Adjacent modules in row/column in same colour */
1079     /* In AIMD-15 section 5.8.3.2 it is stated... “In Table 9 below, i refers to the row
1080      * position of the module.” - however i being the length of the run of the
1081      * same colour (i.e. "block" below) in the same fashion as ISO/IEC 18004
1082      * makes more sense. -- Confirmed by Wang Yi */
1083 
1084     /* Vertical */
1085     for (x = 0; x < size; x++) {
1086         state = local[x];
1087         block = 0;
1088         for (y = 0; y < size; y++) {
1089             if (local[(y * size) + x] == state) {
1090                 block++;
1091             } else {
1092                 if (block > 3) {
1093                     result += (3 + block) * 4;
1094                 }
1095                 block = 0;
1096                 state = local[(y * size) + x];
1097             }
1098         }
1099         if (block > 3) {
1100             result += (3 + block) * 4;
1101         }
1102     }
1103 
1104     /* Horizontal */
1105     for (y = 0; y < size; y++) {
1106         state = local[y * size];
1107         block = 0;
1108         for (x = 0; x < size; x++) {
1109             if (local[(y * size) + x] == state) {
1110                 block++;
1111             } else {
1112                 if (block > 3) {
1113                     result += (3 + block) * 4;
1114                 }
1115                 block = 0;
1116                 state = local[(y * size) + x];
1117             }
1118         }
1119         if (block > 3) {
1120             result += (3 + block) * 4;
1121         }
1122     }
1123 
1124     return result;
1125 }
1126 
1127 /* Apply the four possible bitmasks for evaluation */
hx_apply_bitmask(unsigned char * grid,int size)1128 int hx_apply_bitmask(unsigned char *grid, int size) {
1129     int x, y;
1130     int i, j;
1131     int pattern, penalty[4];
1132     int best_pattern, best_val;
1133     int bit;
1134     unsigned char p;
1135 
1136 #ifndef _MSC_VER
1137     unsigned char mask[size * size];
1138     unsigned char eval[size * size];
1139 #else
1140     unsigned char* mask = (unsigned char *) _alloca((size * size) * sizeof (unsigned char));
1141     unsigned char* eval = (unsigned char *) _alloca((size * size) * sizeof (unsigned char));
1142 #endif
1143 
1144     /* Perform data masking */
1145     for (x = 0; x < size; x++) {
1146         for (y = 0; y < size; y++) {
1147             mask[(y * size) + x] = 0x00;
1148             j = x + 1;
1149             i = y + 1;
1150 
1151             if (!(grid[(y * size) + x] & 0xf0)) {
1152                 if ((i + j) % 2 == 0) {
1153                     mask[(y * size) + x] += 0x02;
1154                 }
1155                 if ((((i + j) % 3) + (j % 3)) % 2 == 0) {
1156                     mask[(y * size) + x] += 0x04;
1157                 }
1158                 if (((i % j) + (j % i) + (i % 3) + (j % 3)) % 2 == 0) {
1159                     mask[(y * size) + x] += 0x08;
1160                 }
1161             }
1162         }
1163     }
1164 
1165     // apply data masks to grid, result in eval
1166     for (x = 0; x < size; x++) {
1167         for (y = 0; y < size; y++) {
1168             if (grid[(y * size) + x] & 0x01) {
1169                 p = 0xff;
1170             } else {
1171                 p = 0x00;
1172             }
1173 
1174             eval[(y * size) + x] = mask[(y * size) + x] ^ p;
1175         }
1176     }
1177 
1178     /* Evaluate result */
1179     for (pattern = 0; pattern < 4; pattern++) {
1180         penalty[pattern] = hx_evaluate(eval, size, pattern);
1181     }
1182 
1183     best_pattern = 0;
1184     best_val = penalty[0];
1185     for (pattern = 1; pattern < 4; pattern++) {
1186         if (penalty[pattern] < best_val) {
1187             best_pattern = pattern;
1188             best_val = penalty[pattern];
1189         }
1190     }
1191 
1192     /* Apply mask */
1193     for (x = 0; x < size; x++) {
1194         for (y = 0; y < size; y++) {
1195             bit = 0;
1196             switch (best_pattern) {
1197                 case 0: if (mask[(y * size) + x] & 0x01) {
1198                         bit = 1;
1199                     }
1200                     break;
1201                 case 1: if (mask[(y * size) + x] & 0x02) {
1202                         bit = 1;
1203                     }
1204                     break;
1205                 case 2: if (mask[(y * size) + x] & 0x04) {
1206                         bit = 1;
1207                     }
1208                     break;
1209                 case 3: if (mask[(y * size) + x] & 0x08) {
1210                         bit = 1;
1211                     }
1212                     break;
1213             }
1214             if (bit == 1) {
1215                 if (grid[(y * size) + x] & 0x01) {
1216                     grid[(y * size) + x] = 0x00;
1217                 } else {
1218                     grid[(y * size) + x] = 0x01;
1219                 }
1220             }
1221         }
1222     }
1223 
1224     return best_pattern;
1225 }
1226 
1227 /* Han Xin Code - main */
han_xin(struct zint_symbol * symbol,const unsigned char source[],size_t length)1228 int han_xin(struct zint_symbol *symbol, const unsigned char source[], size_t length) {
1229     int est_binlen;
1230     int ecc_level = symbol->option_1;
1231     int i, j, version, posn = 0;
1232     int data_codewords = 0, size;
1233     int codewords;
1234     int bitmask;
1235     int error_number;
1236     int bin_len;
1237     int done;
1238     char function_information[36];
1239     unsigned char fi_cw[3] = {0, 0, 0};
1240     unsigned char fi_ecc[4];
1241 
1242 #ifndef _MSC_VER
1243     int utfdata[length + 1];
1244     int gbdata[(length + 1) * 2];
1245     char mode[length + 1];
1246 #else
1247     int* utfdata = (int *) _alloca((length + 1) * sizeof (int));
1248     int* gbdata = (int *) _alloca(((length + 1) * 2) * sizeof (int));
1249     char* mode = (char *) _alloca((length + 1) * sizeof (char));
1250     char* binary;
1251     unsigned char *datastream;
1252     unsigned char *fullstream;
1253     unsigned char *picket_fence;
1254     unsigned char *grid;
1255 #endif
1256 
1257     if ((symbol->input_mode == DATA_MODE) || (symbol->eci != 3)) {
1258         for (i = 0; i < length; i++) {
1259             gbdata[i] = (int) source[i];
1260         }
1261     } else {
1262         /* Convert Unicode input to GB-18030 */
1263         error_number = utf8toutf16(symbol, source, utfdata, &length);
1264         if (error_number != 0) {
1265             return error_number;
1266         }
1267 
1268         posn = 0;
1269         for (i = 0; i < length; i++) {
1270             done = 0;
1271             gbdata[posn] = 0;
1272 
1273             /* Single byte characters in range U+0000 -> U+007F */
1274             if (utfdata[i] <= 0x7f) {
1275                 gbdata[posn] = utfdata[i];
1276                 posn++;
1277                 done = 1;
1278             }
1279 
1280             /* Two bytes characters in GB-2312 */
1281             if (done == 0) {
1282                 j = 0;
1283                 do {
1284                     if (gb2312_lookup[j * 2] == utfdata[i]) {
1285                         gbdata[posn] = gb2312_lookup[(j * 2) + 1];
1286                         posn++;
1287                         done = 1;
1288                     }
1289                     j++;
1290                 } while ((j < 7445) && (done == 0));
1291             }
1292 
1293             /* Two byte characters in GB-18030 */
1294             if (done == 0) {
1295                 j = 0;
1296                 do {
1297                     if (gb18030_twobyte_lookup[j * 2] == utfdata[i]) {
1298                         gbdata[posn] = gb18030_twobyte_lookup[(j * 2) + 1];
1299                         posn++;
1300                         done = 1;
1301                     }
1302                     j++;
1303                 } while ((j < 16495) && (done == 0));
1304             }
1305 
1306             /* Four byte characters in range U+0080 -> U+FFFF */
1307             if (done == 0) {
1308                 j = 0;
1309                 do {
1310                     if (gb18030_fourbyte_lookup[j * 3] == utfdata[i]) {
1311                         gbdata[posn] = gb18030_fourbyte_lookup[(j * 3) + 1];
1312                         gbdata[posn + 1] = gb18030_fourbyte_lookup[(j * 3) + 2];
1313                         posn += 2;
1314                         done = 1;
1315                     }
1316                     j++;
1317                 } while ((j < 6793) && (done == 0));
1318             }
1319 
1320             /* Supplementary planes U+10000 -> U+1FFFF */
1321             if (done == 0) {
1322                 if (utfdata[i] >= 0x10000 && utfdata[i] < 0x110000) {
1323                     /* algorithm from libiconv-1.15\lib\gb18030.h */
1324                     int j, r3, r2, r1, r0;
1325 
1326                     j = utfdata[i] - 0x10000;
1327                     r3 = (j % 10) + 0x30; j = j / 10;
1328                     r2 = (j % 126) + 0x81; j = j / 126;
1329                     r1 = (j % 10) + 0x30; j = j / 10;
1330                     r0 = j + 0x90;
1331                     gbdata[posn] = (r0 << 8) + r1;
1332                     gbdata[posn + 1] = (r2 << 8) + r3;
1333                     posn += 2;
1334                     done = 1;
1335                 }
1336             }
1337 
1338             /* Character not found */
1339             if (done == 0) {
1340                 strcpy(symbol->errtxt, "540: Unknown character in input data");
1341                 return ZINT_ERROR_INVALID_DATA;
1342             }
1343         }
1344         length = posn;
1345     }
1346 
1347     hx_define_mode(mode, gbdata, length);
1348 
1349     est_binlen = calculate_binlength(mode, gbdata, length, symbol->eci);
1350 
1351 #ifndef _MSC_VER
1352     char binary[est_binlen + 10];
1353 #else
1354     binary = (char *) _alloca((est_binlen + 10) * sizeof (char));
1355 #endif
1356     memset(binary, 0, (est_binlen + 1) * sizeof (char));
1357 
1358     if ((ecc_level <= 0) || (ecc_level >= 5)) {
1359         ecc_level = 1;
1360     }
1361 
1362     calculate_binary(binary, mode, gbdata, length, symbol->eci, symbol->debug);
1363     bin_len = strlen(binary);
1364     codewords = bin_len / 8;
1365     if (bin_len % 8 != 0) {
1366         codewords++;
1367     }
1368 
1369     version = 85;
1370     for (i = 84; i > 0; i--) {
1371         switch (ecc_level) {
1372             case 1:
1373                 if (hx_data_codewords_L1[i - 1] > codewords) {
1374                     version = i;
1375                     data_codewords = hx_data_codewords_L1[i - 1];
1376                 }
1377                 break;
1378             case 2:
1379                 if (hx_data_codewords_L2[i - 1] > codewords) {
1380                     version = i;
1381                     data_codewords = hx_data_codewords_L2[i - 1];
1382                 }
1383                 break;
1384             case 3:
1385                 if (hx_data_codewords_L3[i - 1] > codewords) {
1386                     version = i;
1387                     data_codewords = hx_data_codewords_L3[i - 1];
1388                 }
1389                 break;
1390             case 4:
1391                 if (hx_data_codewords_L4[i - 1] > codewords) {
1392                     version = i;
1393                     data_codewords = hx_data_codewords_L4[i - 1];
1394                 }
1395                 break;
1396             default:
1397                 assert(0);
1398                 break;
1399         }
1400     }
1401 
1402     if (version == 85) {
1403         strcpy(symbol->errtxt, "541: Input too long for selected error correction level");
1404         return ZINT_ERROR_TOO_LONG;
1405     }
1406 
1407     if ((symbol->option_2 < 0) || (symbol->option_2 > 84)) {
1408         symbol->option_2 = 0;
1409     }
1410 
1411     if (symbol->option_2 > version) {
1412         version = symbol->option_2;
1413     }
1414 
1415     if ((symbol->option_2 != 0) && (symbol->option_2 < version)) {
1416         strcpy(symbol->errtxt, "542: Input too long for selected symbol size");
1417         return ZINT_ERROR_TOO_LONG;
1418     }
1419 
1420     /* If there is spare capacity, increase the level of ECC */
1421 
1422     if ((ecc_level == 1) && (codewords < hx_data_codewords_L2[version - 1])) {
1423         ecc_level = 2;
1424         data_codewords = hx_data_codewords_L2[version - 1];
1425     }
1426 
1427     if ((ecc_level == 2) && (codewords < hx_data_codewords_L3[version - 1])) {
1428         ecc_level = 3;
1429         data_codewords = hx_data_codewords_L3[version - 1];
1430     }
1431 
1432     if ((ecc_level == 3) && (codewords < hx_data_codewords_L4[version - 1])) {
1433         ecc_level = 4;
1434         data_codewords = hx_data_codewords_L4[version - 1];
1435     }
1436 
1437     //printf("Version %d, ECC %d\n", version, ecc_level);
1438 
1439     size = (version * 2) + 21;
1440 
1441 #ifndef _MSC_VER
1442     unsigned char datastream[data_codewords];
1443     unsigned char fullstream[hx_total_codewords[version - 1]];
1444     unsigned char picket_fence[hx_total_codewords[version - 1]];
1445     unsigned char grid[size * size];
1446 #else
1447     datastream = (unsigned char *) _alloca((data_codewords) * sizeof (unsigned char));
1448     fullstream = (unsigned char *) _alloca((hx_total_codewords[version - 1]) * sizeof (unsigned char));
1449     picket_fence = (unsigned char *) _alloca((hx_total_codewords[version - 1]) * sizeof (unsigned char));
1450     grid = (unsigned char *) _alloca((size * size) * sizeof (unsigned char));
1451 #endif
1452 
1453     for (i = 0; i < data_codewords; i++) {
1454         datastream[i] = 0;
1455     }
1456 
1457     for (i = 0; i < bin_len; i++) {
1458         if (binary[i] == '1') {
1459             datastream[i / 8] += 0x80 >> (i % 8);
1460         }
1461     }
1462 
1463     hx_setup_grid(grid, size, version);
1464 
1465     hx_add_ecc(fullstream, datastream, version, ecc_level);
1466 
1467     make_picket_fence(fullstream, picket_fence, hx_total_codewords[version - 1]);
1468 
1469     /* Populate grid */
1470     j = 0;
1471     for (i = 0; i < (size * size); i++) {
1472         if (grid[i] == 0x00) {
1473             if (j < (hx_total_codewords[version - 1] * 8)) {
1474                 if (picket_fence[(j / 8)] & (0x80 >> (j % 8))) {
1475                     grid[i] = 0x01;
1476                 }
1477                 j++;
1478             }
1479         }
1480     }
1481 
1482     bitmask = hx_apply_bitmask(grid, size);
1483 
1484     /* Form function information string */
1485     for (i = 0; i < 34; i++) {
1486         if (i % 2) {
1487             function_information[i] = '1';
1488         } else {
1489             function_information[i] = '0';
1490         }
1491     }
1492     function_information[34] = '\0';
1493 
1494     for (i = 0; i < 8; i++) {
1495         if ((version + 20) & (0x80 >> i)) {
1496             function_information[i] = '1';
1497         } else {
1498             function_information[i] = '0';
1499         }
1500     }
1501 
1502     for (i = 0; i < 2; i++) {
1503         if ((ecc_level - 1) & (0x02 >> i)) {
1504             function_information[i + 8] = '1';
1505         } else {
1506             function_information[i + 8] = '0';
1507         }
1508     }
1509 
1510     for (i = 0; i < 2; i++) {
1511         if (bitmask & (0x02 >> i)) {
1512             function_information[i + 10] = '1';
1513         } else {
1514             function_information[i + 10] = '0';
1515         }
1516     }
1517 
1518 
1519 
1520     for (i = 0; i < 3; i++) {
1521         for (j = 0; j < 4; j++) {
1522             if (function_information[(i * 4) + j] == '1') {
1523                 fi_cw[i] += (0x08 >> j);
1524             }
1525         }
1526     }
1527 
1528     rs_init_gf(0x13);
1529     rs_init_code(4, 1);
1530     rs_encode(3, fi_cw, fi_ecc);
1531     rs_free();
1532 
1533     for (i = 0; i < 4; i++) {
1534         for (j = 0; j < 4; j++) {
1535             if (fi_ecc[3 - i] & (0x08 >> j)) {
1536                 function_information[(i * 4) + j + 12] = '1';
1537             } else {
1538                 function_information[(i * 4) + j + 12] = '0';
1539             }
1540         }
1541     }
1542 
1543     /* Add function information to symbol */
1544     for (i = 0; i < 9; i++) {
1545         if (function_information[i] == '1') {
1546             grid[(8 * size) + i] = 0x01;
1547             grid[((size - 8 - 1) * size) + (size - i - 1)] = 0x01;
1548         }
1549         if (function_information[i + 8] == '1') {
1550             grid[((8 - i) * size) + 8] = 0x01;
1551             grid[((size - 8 - 1 + i) * size) + (size - 8 - 1)] = 0x01;
1552         }
1553         if (function_information[i + 17] == '1') {
1554             grid[(i * size) + (size - 1 - 8)] = 0x01;
1555             grid[((size - 1 - i) * size) + 8] = 0x01;
1556         }
1557         if (function_information[i + 25] == '1') {
1558             grid[(8 * size) + (size - 1 - 8 + i)] = 0x01;
1559             grid[((size - 1 - 8) * size) + (8 - i)] = 0x01;
1560         }
1561     }
1562 
1563     symbol->width = size;
1564     symbol->rows = size;
1565 
1566     for (i = 0; i < size; i++) {
1567         for (j = 0; j < size; j++) {
1568             if (grid[(i * size) + j] & 0x01) {
1569                 set_module(symbol, i, j);
1570             }
1571         }
1572         symbol->row_height[i] = 1;
1573     }
1574 
1575     return 0;
1576 }
1577