Check-in [6ad4565b78]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:update zint to version 2.5.2
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6ad4565b780354828ad9fad6f877e78104d1f2c0
User & Date: chw 2016-11-11 07:09:37
Context
2016-11-11
07:11
minor cleanup in [undroidwish] build scripts regarding zint and snack check-in: db7ebb5b8c user: chw tags: trunk
07:09
update zint to version 2.5.2 check-in: 6ad4565b78 user: chw tags: trunk
2016-11-10
23:13
add missing file to SDL2 directory check-in: 8d6f20d9b4 user: chw tags: trunk
Changes

Added assets/zint2.5.2/demo.tcl.









































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package require Tk
package require zint
wm title . "ZINT Demo"
wm minsize . 480 320
if {[info command sdltk] eq "sdltk"} {
    wm attributes . -fullscreen 1
    set padx 30
    set pady 20
} else {
    wm geometry . 480x320
    set padx 5
    set pady 5
}
image create photo ::zintimg
pack [::ttk::combobox .c -values [lsort [zint symbologies]] -state readonly] \
    -side top -fill x -padx $padx -pady $pady
.c set Datamatrix
pack [::ttk::entry .e] -side top -fill x -padx $padx -pady $pady
.e insert end 12345
bind .e <Return> Generate
pack [::ttk::button .b -text Generate -command Generate] -fill x -side top \
    -padx $padx -pady $pady
proc Generate {} {
    ::zintimg blank
    ::zintimg configure -width 1 -height 1
    ::zintimg blank
    ::zintimg configure -width 0 -height 0
    if {[catch {zint encode [.e get] ::zintimg -barcode [.c get]} e]} {
        tk_messageBox -message $e -title "Zint error"
    } else {
	set w [image width ::zintimg]
	set h [image height ::zintimg]
	set lw [winfo width .l]
	set lh [winfo height .l]
	set sx [expr {int(1.0 * $lw / $w)}]
	set sy [expr {int(1.0 * $lh / $h)}]
	if {$sy < $sx} {
	    set sx $sy
	}
	if {$sx <= 0} {
	    set sx [expr {1.1 * $lw / $w}]
	    set sy [expr {1.1 * $lh / $h}]
	    if {$sy < $sx} {
		set sx $sy
	    }
	}
	::zintimg blank
	::zintimg configure -width 1 -height 1
	::zintimg blank
	::zintimg configure -width 0 -height 0
	catch {
	    zint encode [.e get] ::zintimg -barcode [.c get] -scale $sx
	}
    }
}
pack [label .l -image ::zintimg -bg white] -side top -fill both -expand 1 \
    -padx $padx -pady $pady
bind .e <Configure> {
    after cancel Generate
    after idle Generate
}
bind .c <<ComboboxSelected>> {
    after cancel Generate
    after idle Generate
}
bind all <Break> exit
bind all <Control-q> exit
bind all <Alt-q> exit

Added assets/zint2.5.2/pkgIndex.tcl.





>
>
1
2
package ifneeded zint 2.5.2 \
    [list load libzint[info sharedlibextension] Zint]

Changes to jni/zint/Android.mk.

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36


37
38
39
40
41
42
43
44
45



46
47

48
49
50
51
52

53
54
55
56
57
58

59
60
61
62
63
64
65

LOCAL_ADDITIONAL_DEPENDENCIES += $(tk_path)/tk-config.mk

LOCAL_C_INCLUDES := $(tcl_includes) $(tk_includes) \
	$(LOCAL_PATH)/../libpng $(LOCAL_PATH)/backend

LOCAL_CFLAGS := $(tcl_cflags) $(tk_cflags) \
	-DZINT_VERSION="\"2.5.0\"" \
	-Dmain=zint \
	-O2

LOCAL_SRC_FILES := \
	backend/2of5.c \
	backend/auspost.c \
	backend/aztec.c \


	backend/code128.c \
	backend/code16k.c \
	backend/code1.c \
	backend/code49.c \
	backend/code.c \
	backend/common.c \
	backend/composite.c \
	backend/dllversion.c \
	backend/dmatrix.c \



	backend/gridmtx.c \
	backend/gs1.c \

	backend/imail.c \
	backend/large.c \
	backend/library.c \
	backend/maxicode.c \
	backend/medical.c \

	backend/pdf417.c \
	backend/plessey.c \
	backend/png.c \
	backend/postal.c \
	backend/ps.c \
	backend/qr.c \

	backend/reedsol.c \
	backend/render.c \
	backend/rss.c \
	backend/svg.c \
	backend/telepen.c \
	backend/upcean.c \
	backend_tcl/zint.c \







|







>
>









>
>
>


>





>






>







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

LOCAL_ADDITIONAL_DEPENDENCIES += $(tk_path)/tk-config.mk

LOCAL_C_INCLUDES := $(tcl_includes) $(tk_includes) \
	$(LOCAL_PATH)/../libpng $(LOCAL_PATH)/backend

LOCAL_CFLAGS := $(tcl_cflags) $(tk_cflags) \
	-DZINT_VERSION="\"2.5.2\"" \
	-Dmain=zint \
	-O2

LOCAL_SRC_FILES := \
	backend/2of5.c \
	backend/auspost.c \
	backend/aztec.c \
	backend/bmp.c \
	backend/codablock.c \
	backend/code128.c \
	backend/code16k.c \
	backend/code1.c \
	backend/code49.c \
	backend/code.c \
	backend/common.c \
	backend/composite.c \
	backend/dllversion.c \
	backend/dmatrix.c \
	backend/dotcode.c \
	backend/eci.c \
	backend/gif.c \
	backend/gridmtx.c \
	backend/gs1.c \
	backend/hanxin.c \
	backend/imail.c \
	backend/large.c \
	backend/library.c \
	backend/maxicode.c \
	backend/medical.c \
	backend/pcx.c \
	backend/pdf417.c \
	backend/plessey.c \
	backend/png.c \
	backend/postal.c \
	backend/ps.c \
	backend/qr.c \
	backend/raster.c \
	backend/reedsol.c \
	backend/render.c \
	backend/rss.c \
	backend/svg.c \
	backend/telepen.c \
	backend/upcean.c \
	backend_tcl/zint.c \

Changes to jni/zint/README.

13
14
15
16
17
18
19
20

21

22
23
24












25
26
27
28
29
30
31
Extended Code 39, Code 93, PZN, Code 23, LOGMARS, Codabar, Pharmacode, Code
128, EAN-128, NVE-18, Code 16k, PDF417, MicroPDF417, Two-Track Pharmacode,
PostNet, PLANET, Australia Post 4-State Symbols, RM4SCC, USPS OneCode, GS1
DataBar, DataBar-14, DataBar Limited, DataBar Extended, DataBar Stacked,
Composite Symbology, Data Matrix, QR Code, Maxicode, Aztec Code, EAN-13,
Micro QR, Korea Post Barcode, HIBC Code 128, HIBC Code 39, HIBC Data Matrix,
HIBC PDF417, HIBC MicroPDF417, HIBC QR Code, HIBC Aztec Code, Japanese Postal
Code, Code 49, Channel Code, Code One, Grid Matrix, FIM and Flattermarken.




PROJECT STATUS
--------------












Version 2.3.0:
This release features a complete rebuild of QR Code and Micro QR Code
functionality which now:

* Automatically detects and adjusts to Japanese characters
* Supports GS1 encoding
* Does not require the qrencode library.







|
>

>



>
>
>
>
>
>
>
>
>
>
>
>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Extended Code 39, Code 93, PZN, Code 23, LOGMARS, Codabar, Pharmacode, Code
128, EAN-128, NVE-18, Code 16k, PDF417, MicroPDF417, Two-Track Pharmacode,
PostNet, PLANET, Australia Post 4-State Symbols, RM4SCC, USPS OneCode, GS1
DataBar, DataBar-14, DataBar Limited, DataBar Extended, DataBar Stacked,
Composite Symbology, Data Matrix, QR Code, Maxicode, Aztec Code, EAN-13,
Micro QR, Korea Post Barcode, HIBC Code 128, HIBC Code 39, HIBC Data Matrix,
HIBC PDF417, HIBC MicroPDF417, HIBC QR Code, HIBC Aztec Code, Japanese Postal
Code, Code 49, Channel Code, Code One, Grid Matrix, FIM and Flattermarken,
Codablock-F, DotCode, Han Xin Code.

Output can be saved as BMP, EPS, GIF, PCX, PNG or SVG. 

PROJECT STATUS
--------------
Version 2.5.0:
After a long period of inaction, many new features and bugfixes, including:

* Reintroduction of Codablock-F
* Introduction of symbologies DotCode and Han Xin Code
* New output formats: GIF, BMP and PCX
* ECI handling
* Redesigned handling of batch files at the command line
* Integrate DMRE handling in Data Matrix
* New licensing model


Version 2.3.0:
This release features a complete rebuild of QR Code and Micro QR Code
functionality which now:

* Automatically detects and adjusts to Japanese characters
* Supports GS1 encoding
* Does not require the qrencode library.

Changes to jni/zint/backend/2of5.c.

55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
...
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
};

static inline char check_digit(unsigned int count) {
    return itoc((10 - (count % 10)) % 10);
}

/* Code 2 of 5 Standard (Code 2 of 5 Matrix) */
int matrix_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length) { 

    int i, error_number;
    char dest[512]; /* 6 + 80 * 6 + 6 + 1 ~ 512*/

    error_number = 0;

    if (length > 80) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }

    /* start character */
    strcpy(dest, "411111");

    for (i = 0; i < length; i++) {
        lookup(NEON, C25MatrixTable, source[i], dest);
    }

    /* Stop character */
	strcat(dest, "41111");

    expand(symbol, dest);
    ustrcpy(symbol->text, source);
    return error_number;
}

/* Code 2 of 5 Industrial */
int industrial_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length) { 

    int i, error_number;
    char dest[512]; /* 6 + 40 * 10 + 6 + 1 */

    error_number = 0;

    if (length > 45) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid character in data");
        return error_number;
    }

    /* start character */
    strcpy(dest, "313111");

    for (i = 0; i < length; i++) {
        lookup(NEON, C25IndustTable, source[i], dest);
    }

    /* Stop character */
	strcat(dest, "31113");

    expand(symbol, dest);
    ustrcpy(symbol->text, source);
    return error_number;
}

/* Code 2 of 5 IATA */
int iata_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length) { 
    int i, error_number;
    char dest[512]; /* 4 + 45 * 10 + 3 + 1 */

    error_number = 0;

    if (length > 45) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }

    /* start */
    strcpy(dest, "1111");

    for (i = 0; i < length; i++) {
        lookup(NEON, C25IndustTable, source[i], dest);
    }

    /* stop */
	strcat(dest, "311");

    expand(symbol, dest);
    ustrcpy(symbol->text, source);
    return error_number;
}

/* Code 2 of 5 Data Logic */
int logic_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length) { 

    int i, error_number;
    char dest[512]; /* 4 + 80 * 6 + 3 + 1 */

    error_number = 0;

    if (length > 80) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }

    /* start character */
    strcpy(dest, "1111");

    for (i = 0; i < length; i++) {
        lookup(NEON, C25MatrixTable, source[i], dest);
    }

    /* Stop character */
	strcat(dest, "311");

    expand(symbol, dest);
    ustrcpy(symbol->text, source);
    return error_number;
}

/* Code 2 of 5 Interleaved */
int interleaved_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length) { 

    int i, j, k, error_number;
    char bars[7], spaces[7], mixed[14], dest[1000];
#ifndef _MSC_VER
    unsigned char temp[length + 2];
#else
    unsigned char* temp = (unsigned char *) _alloca((length + 2) * sizeof (unsigned char));
#endif

    error_number = 0;

    if (length > 89) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }

    ustrcpy(temp, (unsigned char *) "");
    /* Input must be an even number of characters for Interlaced 2 of 5 to work:
       if an odd number of characters has been entered then add a leading zero */
    if (length & 1) {
        ustrcpy(temp, (unsigned char *) "0");
        length++;
    }
    strcat((char*)temp, (char*)source);

    /* start character */
    strcpy(dest, "1111");

    for (i = 0; i < length; i += 2) {
        /* look up the bars and the spaces and put them in two strings */
        strcpy(bars, "");
................................................................................
        for (j = 0; j <= 4; j++) {
            mixed[k] = bars[j];
            k++;
            mixed[k] = spaces[j];
            k++;
        }
        mixed[k] = '\0';
		strcat(dest, mixed);
    }

    /* Stop character */
	strcat(dest, "311");

    expand(symbol, dest);
    ustrcpy(symbol->text, temp);
    return error_number;

}

/* Interleaved 2-of-5 (ITF) */
int itf14(struct zint_symbol *symbol, unsigned char source[], int length) {
    int i, error_number, zeroes;
    unsigned int count;
    char localstr[16];

    error_number = 0;

    count = 0;

    if (length > 13) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid character in data");
        return error_number;
    }

    /* Add leading zeros as required */
    zeroes = 13 - length;
    for (i = 0; i < zeroes; i++) {
        localstr[i] = '0';
................................................................................
    localstr[14] = '\0';
    error_number = interleaved_two_of_five(symbol, (unsigned char *) localstr, strlen(localstr));
    ustrcpy(symbol->text, (unsigned char*) localstr);
    return error_number;
}

/* Deutshe Post Leitcode */
int dpleit(struct zint_symbol *symbol, unsigned char source[], int length) { 
    int i, error_number;
    unsigned int count;
    char localstr[16];
    int zeroes;

    error_number = 0;
    count = 0;
    if (length > 13) {
        strcpy(symbol->errtxt, "Input wrong length");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }

    zeroes = 13 - length;
    for (i = 0; i < zeroes; i++)
        localstr[i] = '0';
    strcpy(localstr + zeroes, (char *) source);
................................................................................
    localstr[14] = '\0';
    error_number = interleaved_two_of_five(symbol, (unsigned char *) localstr, strlen(localstr));
    ustrcpy(symbol->text, (unsigned char*) localstr);
    return error_number;
}

/* Deutsche Post Identcode */
int dpident(struct zint_symbol *symbol, unsigned char source[], int length) { 
    int i, error_number, zeroes;
    unsigned int count;
    char localstr[16];

    count = 0;
    if (length > 11) {
        strcpy(symbol->errtxt, "Input wrong length");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }

    zeroes = 11 - length;
    for (i = 0; i < zeroes; i++)
        localstr[i] = '0';
    strcpy(localstr + zeroes, (char *) source);







|




<
<

|




|











|







|




<
<

|




|











|







|



<
<

|




|











|







|




<
<

|




|











|







|









<
<

|




|










|







 







|



|













<
<



|





|







 







|





<


|




|







 







|






|




|







55
56
57
58
59
60
61
62
63
64
65
66


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97


98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127


128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158


159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194


195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250


251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
...
280
281
282
283
284
285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
...
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
};

static inline char check_digit(unsigned int count) {
    return itoc((10 - (count % 10)) % 10);
}

/* Code 2 of 5 Standard (Code 2 of 5 Matrix) */
int matrix_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length) {

    int i, error_number;
    char dest[512]; /* 6 + 80 * 6 + 6 + 1 ~ 512*/



    if (length > 80) {
        strcpy(symbol->errtxt, "Input too long (C01)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C02)");
        return error_number;
    }

    /* start character */
    strcpy(dest, "411111");

    for (i = 0; i < length; i++) {
        lookup(NEON, C25MatrixTable, source[i], dest);
    }

    /* Stop character */
    strcat(dest, "41111");

    expand(symbol, dest);
    ustrcpy(symbol->text, source);
    return error_number;
}

/* Code 2 of 5 Industrial */
int industrial_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length) {

    int i, error_number;
    char dest[512]; /* 6 + 40 * 10 + 6 + 1 */



    if (length > 45) {
        strcpy(symbol->errtxt, "Input too long (C03)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid character in data (C04)");
        return error_number;
    }

    /* start character */
    strcpy(dest, "313111");

    for (i = 0; i < length; i++) {
        lookup(NEON, C25IndustTable, source[i], dest);
    }

    /* Stop character */
    strcat(dest, "31113");

    expand(symbol, dest);
    ustrcpy(symbol->text, source);
    return error_number;
}

/* Code 2 of 5 IATA */
int iata_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length) {
    int i, error_number;
    char dest[512]; /* 4 + 45 * 10 + 3 + 1 */



    if (length > 45) {
        strcpy(symbol->errtxt, "Input too long (C05)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C06)");
        return error_number;
    }

    /* start */
    strcpy(dest, "1111");

    for (i = 0; i < length; i++) {
        lookup(NEON, C25IndustTable, source[i], dest);
    }

    /* stop */
    strcat(dest, "311");

    expand(symbol, dest);
    ustrcpy(symbol->text, source);
    return error_number;
}

/* Code 2 of 5 Data Logic */
int logic_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length) {

    int i, error_number;
    char dest[512]; /* 4 + 80 * 6 + 3 + 1 */



    if (length > 80) {
        strcpy(symbol->errtxt, "Input too long (C07)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C08)");
        return error_number;
    }

    /* start character */
    strcpy(dest, "1111");

    for (i = 0; i < length; i++) {
        lookup(NEON, C25MatrixTable, source[i], dest);
    }

    /* Stop character */
    strcat(dest, "311");

    expand(symbol, dest);
    ustrcpy(symbol->text, source);
    return error_number;
}

/* Code 2 of 5 Interleaved */
int interleaved_two_of_five(struct zint_symbol *symbol, const unsigned char source[], size_t length) {

    int i, j, k, error_number;
    char bars[7], spaces[7], mixed[14], dest[1000];
#ifndef _MSC_VER
    unsigned char temp[length + 2];
#else
    unsigned char* temp = (unsigned char *) _alloca((length + 2) * sizeof (unsigned char));
#endif



    if (length > 89) {
        strcpy(symbol->errtxt, "Input too long (C09)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C0A)");
        return error_number;
    }

    ustrcpy(temp, (unsigned char *) "");
    /* Input must be an even number of characters for Interlaced 2 of 5 to work:
       if an odd number of characters has been entered then add a leading zero */
    if (length & 1) {
        ustrcpy(temp, (unsigned char *) "0");
        length++;
    }
    strcat((char*) temp, (char*) source);

    /* start character */
    strcpy(dest, "1111");

    for (i = 0; i < length; i += 2) {
        /* look up the bars and the spaces and put them in two strings */
        strcpy(bars, "");
................................................................................
        for (j = 0; j <= 4; j++) {
            mixed[k] = bars[j];
            k++;
            mixed[k] = spaces[j];
            k++;
        }
        mixed[k] = '\0';
        strcat(dest, mixed);
    }

    /* Stop character */
    strcat(dest, "311");

    expand(symbol, dest);
    ustrcpy(symbol->text, temp);
    return error_number;

}

/* Interleaved 2-of-5 (ITF) */
int itf14(struct zint_symbol *symbol, unsigned char source[], int length) {
    int i, error_number, zeroes;
    unsigned int count;
    char localstr[16];



    count = 0;

    if (length > 13) {
        strcpy(symbol->errtxt, "Input too long (C0B)");
        return ZINT_ERROR_TOO_LONG;
    }

    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid character in data (C0D)");
        return error_number;
    }

    /* Add leading zeros as required */
    zeroes = 13 - length;
    for (i = 0; i < zeroes; i++) {
        localstr[i] = '0';
................................................................................
    localstr[14] = '\0';
    error_number = interleaved_two_of_five(symbol, (unsigned char *) localstr, strlen(localstr));
    ustrcpy(symbol->text, (unsigned char*) localstr);
    return error_number;
}

/* Deutshe Post Leitcode */
int dpleit(struct zint_symbol *symbol, unsigned char source[], int length) {
    int i, error_number;
    unsigned int count;
    char localstr[16];
    int zeroes;


    count = 0;
    if (length > 13) {
        strcpy(symbol->errtxt, "Input wrong length (C0E)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C0D)");
        return error_number;
    }

    zeroes = 13 - length;
    for (i = 0; i < zeroes; i++)
        localstr[i] = '0';
    strcpy(localstr + zeroes, (char *) source);
................................................................................
    localstr[14] = '\0';
    error_number = interleaved_two_of_five(symbol, (unsigned char *) localstr, strlen(localstr));
    ustrcpy(symbol->text, (unsigned char*) localstr);
    return error_number;
}

/* Deutsche Post Identcode */
int dpident(struct zint_symbol *symbol, unsigned char source[], int length) {
    int i, error_number, zeroes;
    unsigned int count;
    char localstr[16];

    count = 0;
    if (length > 11) {
        strcpy(symbol->errtxt, "Input wrong length (C0E)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C0F)");
        return error_number;
    }

    zeroes = 11 - length;
    for (i = 0; i < zeroes; i++)
        localstr[i] = '0';
    strcpy(localstr + zeroes, (char *) source);

Changes to jni/zint/backend/CMakeLists.txt.

1
2
3
4
5
6
7
8
9
10

11
12
13
14
15
16
17
18
19
20
21
22
23

24

25
26
27
28
# (c) 2008 by BogDan Vatra < bogdan@licentia.eu >

project(zint)

find_package(PNG)

set(zint_COMMON_SRCS common.c library.c render.c ps.c large.c reedsol.c gs1.c svg.c png.c)
set(zint_ONEDIM_SRCS code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c)
set(zint_POSTAL_SRCS postal.c auspost.c imail.c)
set(zint_TWODIM_SRCS code16k.c dmatrix.c pdf417.c qr.c maxicode.c composite.c aztec.c code49.c code1.c gridmtx.c)

set(zint_SRCS ${zint_COMMON_SRCS} ${zint_ONEDIM_SRCS} ${zint_POSTAL_SRCS} ${zint_TWODIM_SRCS} )

if(PNG_FOUND)
    include_directories( ${PNG_INCLUDES} )
else(PNG_FOUND)
    add_definitions (-DNO_PNG)
endif(PNG_FOUND)

add_library(zint SHARED ${zint_SRCS})

set_target_properties(zint PROPERTIES 	SOVERSION "${ZINT_VERSION_MAJOR}.${ZINT_VERSION_MINOR}"
					VERSION ${ZINT_VERSION})


target_link_libraries(zint ${PNG_LIBRARIES} )

target_link_libraries(zint -lm)

install(TARGETS zint  ${INSTALL_TARGETS_DEFAULT_ARGS} )
install(FILES zint.h DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel)






|


|
>
|












>
|
>




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# (c) 2008 by BogDan Vatra < bogdan@licentia.eu >

project(zint)

find_package(PNG)

set(zint_COMMON_SRCS common.c library.c render.c large.c reedsol.c gs1.c eci.c)
set(zint_ONEDIM_SRCS code.c code128.c 2of5.c upcean.c telepen.c medical.c plessey.c rss.c)
set(zint_POSTAL_SRCS postal.c auspost.c imail.c)
set(zint_TWODIM_SRCS code16k.c codablock.c dmatrix.c pdf417.c qr.c maxicode.c composite.c aztec.c code49.c code1.c gridmtx.c hanxin.c dotcode.c)
set(zint_OUTPUT_SRCS render.c ps.c svg.c bmp.c pcx.c gif.c png.c raster.c)
set(zint_SRCS ${zint_OUTPUT_SRCS} ${zint_COMMON_SRCS} ${zint_ONEDIM_SRCS} ${zint_POSTAL_SRCS} ${zint_TWODIM_SRCS})

if(PNG_FOUND)
    include_directories( ${PNG_INCLUDES} )
else(PNG_FOUND)
    add_definitions (-DNO_PNG)
endif(PNG_FOUND)

add_library(zint SHARED ${zint_SRCS})

set_target_properties(zint PROPERTIES 	SOVERSION "${ZINT_VERSION_MAJOR}.${ZINT_VERSION_MINOR}"
					VERSION ${ZINT_VERSION})

if(PNG_FOUND)
    target_link_libraries(zint ${PNG_LIBRARIES} )
endif(PNG_FOUND)
target_link_libraries(zint -lm)

install(TARGETS zint  ${INSTALL_TARGETS_DEFAULT_ARGS} )
install(FILES zint.h DESTINATION ${INCLUDE_INSTALL_DIR} COMPONENT Devel)

Changes to jni/zint/backend/auspost.c.

102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
...
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
...
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
    /* The contents of data_pattern conform to the following standard:
       0 = Tracker, Ascender and Descender
       1 = Tracker and Ascender
       2 = Tracker and Descender
       3 = Tracker only */
    int error_number, zeroes;
    int writer;
    unsigned int loopey, reader, h;


    char data_pattern[200];
    char fcc[3] = {0, 0, 0}, dpid[10];
    char localstr[30];

    error_number = 0;
    strcpy(localstr, "");
................................................................................
                strcpy(fcc, "62");
                break;
            case 23:
                strcpy(fcc, "62");
                error_number = is_sane(NEON, source, length);
                break;
            default:
                strcpy(symbol->errtxt, "Auspost input is wrong length");
                return ZINT_ERROR_TOO_LONG;
        }
        if (error_number == ZINT_ERROR_INVALID_DATA) {
            strcpy(symbol->errtxt, "Invalid characters in data");
            return error_number;
        }
    } else {
        if (length > 8) {
            strcpy(symbol->errtxt, "Auspost input is too long");
            return ZINT_ERROR_TOO_LONG;
        }
        switch (symbol->symbology) {
            case BARCODE_AUSREPLY: strcpy(fcc, "45");
                break;
            case BARCODE_AUSROUTE: strcpy(fcc, "87");
                break;
................................................................................
        localstr[8] = '\0';
    }

    strcat(localstr, (char*) source);
    h = strlen(localstr);
    error_number = is_sane(GDSET, (unsigned char *) localstr, h);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }

    /* Verifiy that the first 8 characters are numbers */
    memcpy(dpid, localstr, 8);
    dpid[8] = '\0';
    error_number = is_sane(NEON, (unsigned char *) dpid, strlen(dpid));
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in DPID");
        return error_number;
    }

    /* Start character */
    strcpy(data_pattern, "13");

    /* Encode the FCC */







|
>







 







|



|




|







 







|








|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
    /* The contents of data_pattern conform to the following standard:
       0 = Tracker, Ascender and Descender
       1 = Tracker and Ascender
       2 = Tracker and Descender
       3 = Tracker only */
    int error_number, zeroes;
    int writer;
    unsigned int loopey, reader;
    size_t h;

    char data_pattern[200];
    char fcc[3] = {0, 0, 0}, dpid[10];
    char localstr[30];

    error_number = 0;
    strcpy(localstr, "");
................................................................................
                strcpy(fcc, "62");
                break;
            case 23:
                strcpy(fcc, "62");
                error_number = is_sane(NEON, source, length);
                break;
            default:
                strcpy(symbol->errtxt, "Auspost input is wrong length (D01)");
                return ZINT_ERROR_TOO_LONG;
        }
        if (error_number == ZINT_ERROR_INVALID_DATA) {
            strcpy(symbol->errtxt, "Invalid characters in data (D02)");
            return error_number;
        }
    } else {
        if (length > 8) {
            strcpy(symbol->errtxt, "Auspost input is too long (D03)");
            return ZINT_ERROR_TOO_LONG;
        }
        switch (symbol->symbology) {
            case BARCODE_AUSREPLY: strcpy(fcc, "45");
                break;
            case BARCODE_AUSROUTE: strcpy(fcc, "87");
                break;
................................................................................
        localstr[8] = '\0';
    }

    strcat(localstr, (char*) source);
    h = strlen(localstr);
    error_number = is_sane(GDSET, (unsigned char *) localstr, h);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (D04)");
        return error_number;
    }

    /* Verifiy that the first 8 characters are numbers */
    memcpy(dpid, localstr, 8);
    dpid[8] = '\0';
    error_number = is_sane(NEON, (unsigned char *) dpid, strlen(dpid));
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in DPID (D05)");
        return error_number;
    }

    /* Start character */
    strcpy(data_pattern, "13");

    /* Encode the FCC */

Changes to jni/zint/backend/aztec.c.

36
37
38
39
40
41
42


43
44
45
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70
71
72
73
74
..
77
78
79
80
81
82
83
84
85
86
87
88
89
90
















91




92
93
94
95
96
97
98
...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
...
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
...
660
661
662
663
664
665
666
667
668
669



670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
...
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
...
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
...
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
...
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
...
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
....
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
....
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
....
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
....
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
....
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384

1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
....
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
....
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
#ifdef _MSC_VER
#include <malloc.h> 
#endif
#include "common.h"
#include "aztec.h"
#include "reedsol.h"



/**
 * Shorten the string by one character
 */
void mapshorten(int *charmap, int *typemap, int start, int length) {
    memmove(charmap + start + 1, charmap + start + 2, (length - 1) * sizeof (int));
    memmove(typemap + start + 1, typemap + start + 2, (length - 1) * sizeof (int));
}

/**
 * Insert a character into the middle of a string at position posn
 */

void insert(char binary_string[], int posn, char newbit) {
    size_t i, end;

    end = strlen(binary_string);
    for (i = end; i > posn; i--) {
        binary_string[i] = binary_string[i - 1];
    }
    binary_string[posn] = newbit;
}


/**
 * Encode input data into a binary string
 */
int aztec_text_process(unsigned char source[], const unsigned int src_len, char binary_string[], int gs1) {
    int i, j, k, p, bytes;
    int curtable, newtable, lasttable, chartype, maplength, blocks, debug;
#ifndef _MSC_VER
    int charmap[src_len * 2], typemap[src_len * 2];
    int blockmap[2][src_len];
#else
    int* charmap = (int*) _alloca(src_len * 2 * sizeof (int));
................................................................................
    blockmap[0] = (int*) _alloca(src_len * sizeof (int));
    blockmap[1] = (int*) _alloca(src_len * sizeof (int));
#endif
    /* Lookup input string in encoding table */
    maplength = 0;
    debug = 0;

    for (i = 0; i < (int) src_len; i++) {
        if (gs1 && (i == 0)) {
            /* Add FNC1 to beginning of GS1 messages */
            charmap[maplength] = 0;
            typemap[maplength++] = PUNC;
            charmap[maplength] = 400;
            typemap[maplength++] = PUNC;
















        }




        if ((gs1) && (source[i] == '[')) {
            /* FNC1 represented by FLG(0) */
            charmap[maplength] = 0;
            typemap[maplength++] = PUNC;
            charmap[maplength] = 400;
            typemap[maplength++] = PUNC;
        } else {
................................................................................
            blockmap[0][blocks - 1] = 4;
        }
        if (blockmap[0][blocks - 1] & 8) {
            blockmap[0][blocks - 1] = 8;
        }

        /* look for adjacent blocks which can use the same table (right to left search) */
        for (i = blocks - 1; i > 0; i--) {
            if (blockmap[0][i] & blockmap[0][i + 1]) {
                blockmap[0][i] = (blockmap[0][i] & blockmap[0][i + 1]);
            }
        }

        /* determine the encoding table for characters which do not fit with adjacent blocks */
        for (i = 1; i < blocks; i++) {
................................................................................
        }

        /* Combine blocks of the same type */
        i = 0;
        do {
            if (blockmap[0][i] == blockmap[0][i + 1]) {
                blockmap[1][i] += blockmap[1][i + 1];
                for (j = i + 1; j < blocks; j++) {
                    blockmap[0][j] = blockmap[0][j + 1];
                    blockmap[1][j] = blockmap[1][j + 1];
                }
                blocks--;
            } else {
                i++;
            }
        } while (i < blocks);
    }

    /* Put the adjusted block data back into typemap */
    j = 0;
    for (i = 0; i < blocks; i++) {
        if ((blockmap[1][i] < 3) && (blockmap[0][i] != 32)) {
            /* Shift character(s) needed */
................................................................................
            }
            if (typemap[i] > 64) {
                /* Shift character */
                switch (typemap[i]) {
                    case (64 + UPPER): /* To UPPER */
                        switch (curtable) {
                            case LOWER: /* US */
                                strcat(binary_string, hexbit[28]);
                                if (debug) printf("US ");
                                break;
                            case MIXED: /* UL */
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("UL ");
                                newtable = UPPER;
                                break;
                            case PUNC: /* UL */
                                strcat(binary_string, hexbit[31]);
                                if (debug) printf("UL ");
                                newtable = UPPER;
                                break;
                            case DIGIT: /* US */
                                strcat(binary_string, pentbit[15]);
                                if (debug) printf("US ");
                                break;
                        }
                        break;
                    case (64 + LOWER): /* To LOWER */
                        switch (curtable) {
                            case UPPER: /* LL */
                                strcat(binary_string, hexbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                            case MIXED: /* LL */
                                strcat(binary_string, hexbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                            case PUNC: /* UL LL */
                                strcat(binary_string, hexbit[31]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                            case DIGIT: /* UL LL */
                                strcat(binary_string, pentbit[14]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                        }
                        break;
                    case (64 + MIXED): /* To MIXED */
                        switch (curtable) {
                            case UPPER: /* ML */
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                            case LOWER: /* ML */
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                            case PUNC: /* UL ML */
                                strcat(binary_string, hexbit[31]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                            case DIGIT: /* UL ML */
                                strcat(binary_string, pentbit[14]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                        }
                        break;
                    case (64 + PUNC): /* To PUNC */
                        switch (curtable) {
                            case UPPER: /* PS */
                                strcat(binary_string, hexbit[0]);
                                if (debug) printf("PS ");
                                break;
                            case LOWER: /* PS */
                                strcat(binary_string, hexbit[0]);
                                if (debug) printf("PS ");
                                break;
                            case MIXED: /* PS */
                                strcat(binary_string, hexbit[0]);
                                if (debug) printf("PS ");
                                break;
                            case DIGIT: /* PS */
                                strcat(binary_string, pentbit[0]);
                                if (debug) printf("PS ");
                                break;
                        }
                        break;
                    case (64 + DIGIT): /* To DIGIT */
                        switch (curtable) {
                            case UPPER: /* DL */
                                strcat(binary_string, hexbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                            case LOWER: /* DL */
                                strcat(binary_string, hexbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                            case MIXED: /* UL DL */
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                            case PUNC: /* UL DL */
                                strcat(binary_string, hexbit[31]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                        }
                        break;
                }
            } else {
                /* Latch character */
                switch (typemap[i]) {
                    case UPPER: /* To UPPER */
                        switch (curtable) {
                            case LOWER: /* ML UL */
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("ML ");
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("UL ");
                                newtable = UPPER;
                                break;
                            case MIXED: /* UL */
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("UL ");
                                newtable = UPPER;
                                break;
                            case PUNC: /* UL */
                                strcat(binary_string, hexbit[31]);
                                if (debug) printf("UL ");
                                newtable = UPPER;
                                break;
                            case DIGIT: /* UL */
                                strcat(binary_string, pentbit[14]);
                                if (debug) printf("UL ");
                                newtable = UPPER;
                                break;
                        }
                        break;
                    case LOWER: /* To LOWER */
                        switch (curtable) {
                            case UPPER: /* LL */
                                strcat(binary_string, hexbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                            case MIXED: /* LL */
                                strcat(binary_string, hexbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                            case PUNC: /* UL LL */
                                strcat(binary_string, hexbit[31]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                            case DIGIT: /* UL LL */
                                strcat(binary_string, pentbit[14]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                        }
                        break;
                    case MIXED: /* To MIXED */
                        switch (curtable) {
                            case UPPER: /* ML */
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                            case LOWER: /* ML */
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                            case PUNC: /* UL ML */
                                strcat(binary_string, hexbit[31]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                            case DIGIT: /* UL ML */
                                strcat(binary_string, pentbit[14]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                        }
                        break;
                    case PUNC: /* To PUNC */
                        switch (curtable) {
                            case UPPER: /* ML PL */
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("ML ");
                                strcat(binary_string, hexbit[30]);
                                if (debug) printf("PL ");
                                newtable = PUNC;
                                break;
                            case LOWER: /* ML PL */
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("ML ");
                                strcat(binary_string, hexbit[30]);
                                if (debug) printf("PL ");
                                newtable = PUNC;
                                break;
                            case MIXED: /* PL */
                                strcat(binary_string, hexbit[30]);
                                if (debug) printf("PL ");
                                newtable = PUNC;
                                break;
                            case DIGIT: /* UL ML PL */
                                strcat(binary_string, pentbit[14]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("ML ");
                                strcat(binary_string, hexbit[30]);
                                if (debug) printf("PL ");
                                newtable = PUNC;
                                break;
                        }
                        break;
                    case DIGIT: /* To DIGIT */
                        switch (curtable) {
                            case UPPER: /* DL */
                                strcat(binary_string, hexbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                            case LOWER: /* DL */
                                strcat(binary_string, hexbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                            case MIXED: /* UL DL */
                                strcat(binary_string, hexbit[29]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                            case PUNC: /* UL DL */
                                strcat(binary_string, hexbit[31]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                        }
                        break;
                    case BINARY: /* To BINARY */
                        lasttable = curtable;
                        switch (curtable) {
                            case UPPER: /* BS */
                                strcat(binary_string, hexbit[31]);
                                if (debug) printf("BS ");
                                newtable = BINARY;
                                break;
                            case LOWER: /* BS */
                                strcat(binary_string, hexbit[31]);
                                if (debug) printf("BS ");
                                newtable = BINARY;
                                break;
                            case MIXED: /* BS */
                                strcat(binary_string, hexbit[31]);
                                if (debug) printf("BS ");
                                newtable = BINARY;
                                break;
                            case PUNC: /* UL BS */
                                strcat(binary_string, hexbit[31]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[31]);
                                if (debug) printf("BS ");
                                lasttable = UPPER;
                                newtable = BINARY;
                                break;
                            case DIGIT: /* UL BS */
                                strcat(binary_string, pentbit[14]);
                                if (debug) printf("UL ");
                                strcat(binary_string, hexbit[31]);
                                if (debug) printf("BS ");
                                lasttable = UPPER;
                                newtable = BINARY;
                                break;
                        }

                        bytes = 0;
................................................................................
            chartype -= 64;
        }
        switch (chartype) {
            case UPPER:
            case LOWER:
            case MIXED:
            case PUNC:
                if (charmap[i] >= 400) {
                    strcat(binary_string, tribit[charmap[i] - 400]);
                    if (debug) printf("FLG(%d) ", charmap[i] - 400);



                } else {
                    strcat(binary_string, hexbit[charmap[i]]);
                    if (!((chartype == PUNC) && (charmap[i] == 0)))
                        if (debug) printf("%d ", charmap[i]);
                }
                break;
            case DIGIT:
                strcat(binary_string, pentbit[charmap[i]]);
                if (debug) printf("%d ", charmap[i]);
                break;
            case BINARY:
                for (p = 0; p < 8; p++) {
                    if (charmap[i] & (0x80 >> p)) {
                        strcat(binary_string, "1");
                    } else {
................................................................................
        return ZINT_ERROR_TOO_LONG;
    }

    return 0;
}

/* Prevent data from obscuring reference grid */
int avoidReferenceGrid(int input) {
    int output;

    output = input;
    if (output > 10) {
        output++;
    }
    if (output > 26) {
        output++;
    }
    if (output > 42) {
................................................................................
        output++;
    }

    return output;
}

/* Calculate the position of the bits in the grid */
void popilate_map() {
    int layer, start, length, n, i;
    int x, y;

    for (x = 0; x < 151; x++) {
        for (y = 0; y < 151; y++) {
            AztecMap[(x * 151) + y] = 0;
        }
................................................................................
    char adjusted_string[20000];
    unsigned char desc_data[4], desc_ecc[6];
    int err_code, ecc_level, compact, data_length, data_maxsize, codeword_size, adjusted_length;
    int remainder, padbits, count, gs1, adjustment_size;
    int debug = 0, reader = 0;
    int comp_loop = 4;

#ifndef _MSC_VER
    unsigned char local_source[length + 1];
#else
    unsigned char* local_source = (unsigned char*) _alloca(length + 1);
    unsigned int* data_part;
    unsigned int* ecc_part;
#endif

    memset(binary_string, 0, 20000);
    memset(adjusted_string, 0, 20000);

................................................................................
    } else {
        gs1 = 0;
    }
    if (symbol->output_options & READER_INIT) {
        reader = 1;
        comp_loop = 1;
    }
    if ((gs1 == 1) && (reader == 1)) {
        strcpy(symbol->errtxt, "Cannot encode in GS1 and Reader Initialisation mode at the same time");
        return ZINT_ERROR_INVALID_OPTION;
    }

    switch (symbol->input_mode) {
        case DATA_MODE:
        case GS1_MODE:
            memcpy(local_source, source, length);
            local_source[length] = '\0';
            break;
        case UNICODE_MODE:
            err_code = latin1_process(symbol, source, local_source, &length);
            if (err_code != 0) {
                return err_code;
            }
            break;
    }

    err_code = aztec_text_process(local_source, length, binary_string, gs1);


    if (err_code != 0) {
        strcpy(symbol->errtxt, "Input too long or too many extended ASCII characters");
        return err_code;
    }

    if (!((symbol->option_1 >= -1) && (symbol->option_1 <= 4))) {
        strcpy(symbol->errtxt, "Invalid error correction level - using default instead");
        err_code = ZINT_WARN_INVALID_OPTION;
        symbol->option_1 = -1;
    }

    ecc_level = symbol->option_1;

    if ((ecc_level == -1) || (ecc_level == 0)) {
        ecc_level = 2;
    }

    data_length = strlen(binary_string);

    layers = 0; /* Keep compiler happy! */
    data_maxsize = 0; /* Keep compiler happy! */
    adjustment_size = 0;
    if (symbol->option_2 == 0) { /* The size of the symbol can be determined by Zint */
        do {
            /* Decide what size symbol to use - the smallest that fits the data */
................................................................................
                            data_maxsize = AztecCompact50DataSizes[i - 1];
                        }
                    }
                    break;
            }

            if (layers == 0) { /* Couldn't find a symbol which fits the data */
                strcpy(symbol->errtxt, "Input too long (too many bits for selected ECC)");
                return ZINT_ERROR_TOO_LONG;
            }

            /* Determine codeword bitlength - Table 3 */
            codeword_size = 6; /* if (layers <= 2) */
            if ((layers >= 3) && (layers <= 8)) {
                codeword_size = 8;
................................................................................
                    }
                }
                adjusted_string[j] = binary_string[i];
                j++;
                i++;
            } while (i <= (data_length + 1));
            adjusted_string[j] = '\0';
            adjusted_length = strlen(adjusted_string);
            adjustment_size = adjusted_length - data_length;

            /* Add padding */
            remainder = adjusted_length % codeword_size;

            padbits = codeword_size - remainder;
            if (padbits == codeword_size) {
                padbits = 0;
            }

            for (i = 0; i < padbits; i++) {
                strcat(adjusted_string, "1");
            }
            adjusted_length = strlen(adjusted_string);

            count = 0;
            for (i = (adjusted_length - codeword_size); i < adjusted_length; i++) {
                if (adjusted_string[i] == '1') {
                    count++;
                }
            }
................................................................................
                }
            }
            adjusted_string[j] = binary_string[i];
            j++;
            i++;
        } while (i <= (data_length + 1));
        adjusted_string[j] = '\0';
        adjusted_length = strlen(adjusted_string);

        remainder = adjusted_length % codeword_size;

        padbits = codeword_size - remainder;
        if (padbits == codeword_size) {
            padbits = 0;
        }

        for (i = 0; i < padbits; i++) {
            strcat(adjusted_string, "1");
        }
        adjusted_length = strlen(adjusted_string);

        count = 0;
        for (i = (adjusted_length - codeword_size); i < adjusted_length; i++) {
            if (adjusted_string[i] == '1') {
                count++;
            }
        }
................................................................................
        if (compact) {
            data_maxsize = codeword_size * (AztecCompactSizes[layers - 1] - 3);
        } else {
            data_maxsize = codeword_size * (AztecSizes[layers - 1] - 3);
        }

        if (adjusted_length > data_maxsize) {
            strcpy(symbol->errtxt, "Data too long for specified Aztec Code symbol size");
            return ZINT_ERROR_TOO_LONG;
        }

        if (debug) {
            printf("Codewords:\n");
            for (i = 0; i < (adjusted_length / codeword_size); i++) {
                for (j = 0; j < codeword_size; j++) {
................................................................................
                printf("\n");
            }
        }

    }

    if (reader && (layers > 22)) {
        strcpy(symbol->errtxt, "Data too long for reader initialisation symbol");
        return ZINT_ERROR_TOO_LONG;
    }

    data_blocks = adjusted_length / codeword_size;

    if (compact) {
        ecc_blocks = AztecCompactSizes[layers - 1] - data_blocks;
................................................................................
        } else {
            if ((data_blocks - 1) & 0x20) {
                descriptor[2] = '1';
            } else {
                descriptor[2] = '0';
            }
        }
        if ((data_blocks - 1) & 0x10) {
            descriptor[3] = '1';
        } else {
            descriptor[3] = '0';
        }

        if ((data_blocks - 1) & 0x08) {
            descriptor[4] = '1';
        } else {
            descriptor[4] = '0';
        }
        if ((data_blocks - 1) & 0x04) {
            descriptor[5] = '1';
        } else {
            descriptor[5] = '0';
        }
        if ((data_blocks - 1) & 0x02) {
            descriptor[6] = '1';
        } else {
            descriptor[6] = '0';
        }
        if ((data_blocks - 1) & 0x01) {
            descriptor[7] = '1';
        } else {
            descriptor[7] = '0';
        }
        descriptor[8] = '\0';
        if (debug) printf("Mode Message = %s\n", descriptor);
    } else {
        /* The first 5 bits represent the number of layers minus 1 */
        if ((layers - 1) & 0x10) {
            descriptor[0] = '1';
        } else {
            descriptor[0] = '0';
        }
        if ((layers - 1) & 0x08) {
            descriptor[1] = '1';
        } else {
            descriptor[1] = '0';
        }
        if ((layers - 1) & 0x04) {
            descriptor[2] = '1';
        } else {
            descriptor[2] = '0';
        }
        if ((layers - 1) & 0x02) {
            descriptor[3] = '1';
        } else {
            descriptor[3] = '0';
        }
        if ((layers - 1) & 0x01) {
            descriptor[4] = '1';
        } else {
            descriptor[4] = '0';
        }
        /* The next 11 bits represent the number of data blocks minus 1 */
        if (reader) {
            descriptor[5] = '1';
        } else {
            if ((data_blocks - 1) & 0x400) {
                descriptor[5] = '1';
            } else {
                descriptor[5] = '0';
            }
        }
        if ((data_blocks - 1) & 0x200) {
            descriptor[6] = '1';
        } else {
            descriptor[6] = '0';
        }
        if ((data_blocks - 1) & 0x100) {
            descriptor[7] = '1';
        } else {
            descriptor[7] = '0';
        }
        if ((data_blocks - 1) & 0x80) {
            descriptor[8] = '1';
        } else {
            descriptor[8] = '0';
        }
        if ((data_blocks - 1) & 0x40) {
            descriptor[9] = '1';
        } else {
            descriptor[9] = '0';
        }
        if ((data_blocks - 1) & 0x20) {
            descriptor[10] = '1';
        } else {
            descriptor[10] = '0';
        }
        if ((data_blocks - 1) & 0x10) {
            descriptor[11] = '1';
        } else {
            descriptor[11] = '0';
        }
        if ((data_blocks - 1) & 0x08) {
            descriptor[12] = '1';
        } else {
            descriptor[12] = '0';
        }
        if ((data_blocks - 1) & 0x04) {
            descriptor[13] = '1';
        } else {
            descriptor[13] = '0';
        }
        if ((data_blocks - 1) & 0x02) {
            descriptor[14] = '1';
        } else {
            descriptor[14] = '0';
        }
        if ((data_blocks - 1) & 0x01) {
            descriptor[15] = '1';
        } else {
            descriptor[15] = '0';
        }
        descriptor[16] = '\0';
        if (debug) printf("Mode Message = %s\n", descriptor);
    }

    /* Split into 4-bit codewords */
    for (i = 0; i < 4; i++) {
................................................................................
    int input_value, error_number, i, p, y, x;
    char binary_string[28];
    unsigned char data_codewords[3], ecc_codewords[6];

    error_number = 0;
    input_value = 0;
    if (length > 3) {
        strcpy(symbol->errtxt, "Input too large");
        return ZINT_ERROR_INVALID_DATA;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number != 0) {
        strcpy(symbol->errtxt, "Invalid characters in input");
        return ZINT_ERROR_INVALID_DATA;
    }
    switch (length) {
        case 3: input_value = 100 * ctoi(source[0]);
            input_value += 10 * ctoi(source[1]);
            input_value += ctoi(source[2]);
            break;
................................................................................
            input_value += ctoi(source[1]);
            break;
        case 1: input_value = ctoi(source[0]);
            break;
    }

    if (input_value > 255) {
        strcpy(symbol->errtxt, "Input too large");
        return ZINT_ERROR_INVALID_DATA;
    }

    strcpy(binary_string, "");
    for (p = 0; p < 8; p++) {
        if (input_value & (0x80 >> p)) {
            strcat(binary_string, "1");







>
>



|







>
|








>




|







 







<
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

>
>
>
>







 







|







 







|







|







 







|



|




|




|







|




|




|

|




|

|








|




|




|

|




|

|








|



|



|



|







|




|




|

|




|

|












|

|




|




|




|








|




|




|

|




|

|








|




|




|

|




|

|








|

|




|

|




|




|

|

|








|




|




|

|




|

|









|




|




|




|

|





|

|







 







|


>
>
>

|





|







 







|
<

<







 







|







 







|
<
<
<







 







|
|



|
<
<
<
<
<
<
<
<
<
|
<
<
<
|

<

|




|










|







 







|







 







|













|







 







|











|







 







|







 







|







 







<
<
<
<
|
>
|
|
|
|
|
<
<
<
<

<
<
<
<
|
<
<
<
<
<




|
<
<
<
<
|
|
|
|
|
<
<
<
<

<
<
<
<
|
<
<
<
<
<










|
<
<
<
<
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|




|







 







|







36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
..
81
82
83
84
85
86
87

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
...
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
...
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
...
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
...
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
...
723
724
725
726
727
728
729
730

731

732
733
734
735
736
737
738
...
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
...
885
886
887
888
889
890
891
892



893
894
895
896
897
898
899
...
902
903
904
905
906
907
908
909
910
911
912
913
914









915



916
917

918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
....
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
....
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
....
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
....
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
....
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
....
1381
1382
1383
1384
1385
1386
1387




1388
1389
1390
1391
1392
1393
1394




1395




1396





1397
1398
1399
1400
1401




1402
1403
1404
1405
1406




1407




1408





1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419




1420
1421
1422
1423
1424







































1425
1426
1427
1428
1429
1430
1431
....
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
....
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
#ifdef _MSC_VER
#include <malloc.h> 
#endif
#include "common.h"
#include "aztec.h"
#include "reedsol.h"

static int AztecMap[22801];

/**
 * Shorten the string by one character
 */
static void mapshorten(int *charmap, int *typemap, const int start, const int length) {
    memmove(charmap + start + 1, charmap + start + 2, (length - 1) * sizeof (int));
    memmove(typemap + start + 1, typemap + start + 2, (length - 1) * sizeof (int));
}

/**
 * Insert a character into the middle of a string at position posn
 */
/*
static void insert(char binary_string[], const size_t posn, const char newbit) {
    size_t i, end;

    end = strlen(binary_string);
    for (i = end; i > posn; i--) {
        binary_string[i] = binary_string[i - 1];
    }
    binary_string[posn] = newbit;
}
*/

/**
 * Encode input data into a binary string
 */
static int aztec_text_process(const unsigned char source[], const unsigned int src_len, char binary_string[], const int gs1, const int eci) {
    int i, j, k, p, bytes;
    int curtable, newtable, lasttable, chartype, maplength, blocks, debug;
#ifndef _MSC_VER
    int charmap[src_len * 2], typemap[src_len * 2];
    int blockmap[2][src_len];
#else
    int* charmap = (int*) _alloca(src_len * 2 * sizeof (int));
................................................................................
    blockmap[0] = (int*) _alloca(src_len * sizeof (int));
    blockmap[1] = (int*) _alloca(src_len * sizeof (int));
#endif
    /* Lookup input string in encoding table */
    maplength = 0;
    debug = 0;


    if (gs1) {
        /* Add FNC1 to beginning of GS1 messages */
        charmap[maplength] = 0;
        typemap[maplength++] = PUNC;
        charmap[maplength] = 400;
        typemap[maplength++] = PUNC;
    } else if (eci != 3) {
        /* Set ECI mode */
        charmap[maplength] = 0;
        typemap[maplength++] = PUNC;
        if (eci < 10) {
            charmap[maplength] = 401; // FLG(1)
            typemap[maplength++] = PUNC;
            charmap[maplength] = 502 + eci;
            typemap[maplength++] = PUNC;
        } else {
            charmap[maplength] = 402; // FLG(2)
            typemap[maplength++] = PUNC;
            charmap[maplength] = 502 + (eci / 10);
            typemap[maplength++] = PUNC;
            charmap[maplength] = 502 + (eci % 10);
            typemap[maplength++] = PUNC;
        }

    }

    for (i = 0; i < (int) src_len; i++) {
        if ((gs1) && (source[i] == '[')) {
            /* FNC1 represented by FLG(0) */
            charmap[maplength] = 0;
            typemap[maplength++] = PUNC;
            charmap[maplength] = 400;
            typemap[maplength++] = PUNC;
        } else {
................................................................................
            blockmap[0][blocks - 1] = 4;
        }
        if (blockmap[0][blocks - 1] & 8) {
            blockmap[0][blocks - 1] = 8;
        }

        /* look for adjacent blocks which can use the same table (right to left search) */
        for (i = blocks - 1 - 1; i >= 0; i--) {
            if (blockmap[0][i] & blockmap[0][i + 1]) {
                blockmap[0][i] = (blockmap[0][i] & blockmap[0][i + 1]);
            }
        }

        /* determine the encoding table for characters which do not fit with adjacent blocks */
        for (i = 1; i < blocks; i++) {
................................................................................
        }

        /* Combine blocks of the same type */
        i = 0;
        do {
            if (blockmap[0][i] == blockmap[0][i + 1]) {
                blockmap[1][i] += blockmap[1][i + 1];
                for (j = i + 1; j < blocks - 1; j++) {
                    blockmap[0][j] = blockmap[0][j + 1];
                    blockmap[1][j] = blockmap[1][j + 1];
                }
                blocks--;
            } else {
                i++;
            }
        } while (i < blocks - 1);
    }

    /* Put the adjusted block data back into typemap */
    j = 0;
    for (i = 0; i < blocks; i++) {
        if ((blockmap[1][i] < 3) && (blockmap[0][i] != 32)) {
            /* Shift character(s) needed */
................................................................................
            }
            if (typemap[i] > 64) {
                /* Shift character */
                switch (typemap[i]) {
                    case (64 + UPPER): /* To UPPER */
                        switch (curtable) {
                            case LOWER: /* US */
                                strcat(binary_string, pentbit[28]);
                                if (debug) printf("US ");
                                break;
                            case MIXED: /* UL */
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("UL ");
                                newtable = UPPER;
                                break;
                            case PUNC: /* UL */
                                strcat(binary_string, pentbit[31]);
                                if (debug) printf("UL ");
                                newtable = UPPER;
                                break;
                            case DIGIT: /* US */
                                strcat(binary_string, quadbit[15]);
                                if (debug) printf("US ");
                                break;
                        }
                        break;
                    case (64 + LOWER): /* To LOWER */
                        switch (curtable) {
                            case UPPER: /* LL */
                                strcat(binary_string, pentbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                            case MIXED: /* LL */
                                strcat(binary_string, pentbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                            case PUNC: /* UL LL */
                                strcat(binary_string, pentbit[31]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                            case DIGIT: /* UL LL */
                                strcat(binary_string, quadbit[14]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                        }
                        break;
                    case (64 + MIXED): /* To MIXED */
                        switch (curtable) {
                            case UPPER: /* ML */
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                            case LOWER: /* ML */
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                            case PUNC: /* UL ML */
                                strcat(binary_string, pentbit[31]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                            case DIGIT: /* UL ML */
                                strcat(binary_string, quadbit[14]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                        }
                        break;
                    case (64 + PUNC): /* To PUNC */
                        switch (curtable) {
                            case UPPER: /* PS */
                                strcat(binary_string, pentbit[0]);
                                if (debug) printf("PS ");
                                break;
                            case LOWER: /* PS */
                                strcat(binary_string, pentbit[0]);
                                if (debug) printf("PS ");
                                break;
                            case MIXED: /* PS */
                                strcat(binary_string, pentbit[0]);
                                if (debug) printf("PS ");
                                break;
                            case DIGIT: /* PS */
                                strcat(binary_string, quadbit[0]);
                                if (debug) printf("PS ");
                                break;
                        }
                        break;
                    case (64 + DIGIT): /* To DIGIT */
                        switch (curtable) {
                            case UPPER: /* DL */
                                strcat(binary_string, pentbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                            case LOWER: /* DL */
                                strcat(binary_string, pentbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                            case MIXED: /* UL DL */
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                            case PUNC: /* UL DL */
                                strcat(binary_string, pentbit[31]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                        }
                        break;
                }
            } else {
                /* Latch character */
                switch (typemap[i]) {
                    case UPPER: /* To UPPER */
                        switch (curtable) {
                            case LOWER: /* ML UL */
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("ML ");
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("UL ");
                                newtable = UPPER;
                                break;
                            case MIXED: /* UL */
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("UL ");
                                newtable = UPPER;
                                break;
                            case PUNC: /* UL */
                                strcat(binary_string, pentbit[31]);
                                if (debug) printf("UL ");
                                newtable = UPPER;
                                break;
                            case DIGIT: /* UL */
                                strcat(binary_string, quadbit[14]);
                                if (debug) printf("UL ");
                                newtable = UPPER;
                                break;
                        }
                        break;
                    case LOWER: /* To LOWER */
                        switch (curtable) {
                            case UPPER: /* LL */
                                strcat(binary_string, pentbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                            case MIXED: /* LL */
                                strcat(binary_string, pentbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                            case PUNC: /* UL LL */
                                strcat(binary_string, pentbit[31]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                            case DIGIT: /* UL LL */
                                strcat(binary_string, quadbit[14]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[28]);
                                if (debug) printf("LL ");
                                newtable = LOWER;
                                break;
                        }
                        break;
                    case MIXED: /* To MIXED */
                        switch (curtable) {
                            case UPPER: /* ML */
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                            case LOWER: /* ML */
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                            case PUNC: /* UL ML */
                                strcat(binary_string, pentbit[31]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                            case DIGIT: /* UL ML */
                                strcat(binary_string, quadbit[14]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("ML ");
                                newtable = MIXED;
                                break;
                        }
                        break;
                    case PUNC: /* To PUNC */
                        switch (curtable) {
                            case UPPER: /* ML PL */
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("ML ");
                                strcat(binary_string, pentbit[30]);
                                if (debug) printf("PL ");
                                newtable = PUNC;
                                break;
                            case LOWER: /* ML PL */
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("ML ");
                                strcat(binary_string, pentbit[30]);
                                if (debug) printf("PL ");
                                newtable = PUNC;
                                break;
                            case MIXED: /* PL */
                                strcat(binary_string, pentbit[30]);
                                if (debug) printf("PL ");
                                newtable = PUNC;
                                break;
                            case DIGIT: /* UL ML PL */
                                strcat(binary_string, quadbit[14]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("ML ");
                                strcat(binary_string, pentbit[30]);
                                if (debug) printf("PL ");
                                newtable = PUNC;
                                break;
                        }
                        break;
                    case DIGIT: /* To DIGIT */
                        switch (curtable) {
                            case UPPER: /* DL */
                                strcat(binary_string, pentbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                            case LOWER: /* DL */
                                strcat(binary_string, pentbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                            case MIXED: /* UL DL */
                                strcat(binary_string, pentbit[29]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                            case PUNC: /* UL DL */
                                strcat(binary_string, pentbit[31]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[30]);
                                if (debug) printf("DL ");
                                newtable = DIGIT;
                                break;
                        }
                        break;
                    case BINARY: /* To BINARY */
                        lasttable = curtable;
                        switch (curtable) {
                            case UPPER: /* BS */
                                strcat(binary_string, pentbit[31]);
                                if (debug) printf("BS ");
                                newtable = BINARY;
                                break;
                            case LOWER: /* BS */
                                strcat(binary_string, pentbit[31]);
                                if (debug) printf("BS ");
                                newtable = BINARY;
                                break;
                            case MIXED: /* BS */
                                strcat(binary_string, pentbit[31]);
                                if (debug) printf("BS ");
                                newtable = BINARY;
                                break;
                            case PUNC: /* UL BS */
                                strcat(binary_string, pentbit[31]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[31]);
                                if (debug) printf("BS ");
                                lasttable = UPPER;
                                newtable = BINARY;
                                break;
                            case DIGIT: /* UL BS */
                                strcat(binary_string, quadbit[14]);
                                if (debug) printf("UL ");
                                strcat(binary_string, pentbit[31]);
                                if (debug) printf("BS ");
                                lasttable = UPPER;
                                newtable = BINARY;
                                break;
                        }

                        bytes = 0;
................................................................................
            chartype -= 64;
        }
        switch (chartype) {
            case UPPER:
            case LOWER:
            case MIXED:
            case PUNC:
                if ((charmap[i] >= 400) && (charmap[i] < 500)) {
                    strcat(binary_string, tribit[charmap[i] - 400]);
                    if (debug) printf("FLG(%d) ", charmap[i] - 400);
                } else if (charmap[i] >= 500) {
                    strcat(binary_string, quadbit[charmap[i] - 500]);
                    if (debug) printf("[%d] ", charmap[i] - 500);
                } else {
                    strcat(binary_string, pentbit[charmap[i]]);
                    if (!((chartype == PUNC) && (charmap[i] == 0)))
                        if (debug) printf("%d ", charmap[i]);
                }
                break;
            case DIGIT:
                strcat(binary_string, quadbit[charmap[i]]);
                if (debug) printf("%d ", charmap[i]);
                break;
            case BINARY:
                for (p = 0; p < 8; p++) {
                    if (charmap[i] & (0x80 >> p)) {
                        strcat(binary_string, "1");
                    } else {
................................................................................
        return ZINT_ERROR_TOO_LONG;
    }

    return 0;
}

/* Prevent data from obscuring reference grid */
static int avoidReferenceGrid(int output) {



    if (output > 10) {
        output++;
    }
    if (output > 26) {
        output++;
    }
    if (output > 42) {
................................................................................
        output++;
    }

    return output;
}

/* Calculate the position of the bits in the grid */
static void populate_map() {
    int layer, start, length, n, i;
    int x, y;

    for (x = 0; x < 151; x++) {
        for (y = 0; y < 151; y++) {
            AztecMap[(x * 151) + y] = 0;
        }
................................................................................
    char adjusted_string[20000];
    unsigned char desc_data[4], desc_ecc[6];
    int err_code, ecc_level, compact, data_length, data_maxsize, codeword_size, adjusted_length;
    int remainder, padbits, count, gs1, adjustment_size;
    int debug = 0, reader = 0;
    int comp_loop = 4;

#ifdef _MSC_VER



    unsigned int* data_part;
    unsigned int* ecc_part;
#endif

    memset(binary_string, 0, 20000);
    memset(adjusted_string, 0, 20000);

................................................................................
    } else {
        gs1 = 0;
    }
    if (symbol->output_options & READER_INIT) {
        reader = 1;
        comp_loop = 1;
    }
    if (gs1 && reader) {
        strcpy(symbol->errtxt, "Cannot encode in GS1 and Reader Initialisation mode at the same time (E01)");
        return ZINT_ERROR_INVALID_OPTION;
    }

    populate_map();













    err_code = aztec_text_process(source, length, binary_string, gs1, symbol->eci);


    if (err_code != 0) {
        strcpy(symbol->errtxt, "Input too long or too many extended ASCII characters (E02)");
        return err_code;
    }

    if (!((symbol->option_1 >= -1) && (symbol->option_1 <= 4))) {
        strcpy(symbol->errtxt, "Invalid error correction level - using default instead (E03)");
        err_code = ZINT_WARN_INVALID_OPTION;
        symbol->option_1 = -1;
    }

    ecc_level = symbol->option_1;

    if ((ecc_level == -1) || (ecc_level == 0)) {
        ecc_level = 2;
    }

    data_length = (int) strlen(binary_string);

    layers = 0; /* Keep compiler happy! */
    data_maxsize = 0; /* Keep compiler happy! */
    adjustment_size = 0;
    if (symbol->option_2 == 0) { /* The size of the symbol can be determined by Zint */
        do {
            /* Decide what size symbol to use - the smallest that fits the data */
................................................................................
                            data_maxsize = AztecCompact50DataSizes[i - 1];
                        }
                    }
                    break;
            }

            if (layers == 0) { /* Couldn't find a symbol which fits the data */
                strcpy(symbol->errtxt, "Input too long (too many bits for selected ECC) (E04)");
                return ZINT_ERROR_TOO_LONG;
            }

            /* Determine codeword bitlength - Table 3 */
            codeword_size = 6; /* if (layers <= 2) */
            if ((layers >= 3) && (layers <= 8)) {
                codeword_size = 8;
................................................................................
                    }
                }
                adjusted_string[j] = binary_string[i];
                j++;
                i++;
            } while (i <= (data_length + 1));
            adjusted_string[j] = '\0';
            adjusted_length = (int) strlen(adjusted_string);
            adjustment_size = adjusted_length - data_length;

            /* Add padding */
            remainder = adjusted_length % codeword_size;

            padbits = codeword_size - remainder;
            if (padbits == codeword_size) {
                padbits = 0;
            }

            for (i = 0; i < padbits; i++) {
                strcat(adjusted_string, "1");
            }
            adjusted_length = (int) strlen(adjusted_string);

            count = 0;
            for (i = (adjusted_length - codeword_size); i < adjusted_length; i++) {
                if (adjusted_string[i] == '1') {
                    count++;
                }
            }
................................................................................
                }
            }
            adjusted_string[j] = binary_string[i];
            j++;
            i++;
        } while (i <= (data_length + 1));
        adjusted_string[j] = '\0';
        adjusted_length = (int) strlen(adjusted_string);

        remainder = adjusted_length % codeword_size;

        padbits = codeword_size - remainder;
        if (padbits == codeword_size) {
            padbits = 0;
        }

        for (i = 0; i < padbits; i++) {
            strcat(adjusted_string, "1");
        }
        adjusted_length = (int) strlen(adjusted_string);

        count = 0;
        for (i = (adjusted_length - codeword_size); i < adjusted_length; i++) {
            if (adjusted_string[i] == '1') {
                count++;
            }
        }
................................................................................
        if (compact) {
            data_maxsize = codeword_size * (AztecCompactSizes[layers - 1] - 3);
        } else {
            data_maxsize = codeword_size * (AztecSizes[layers - 1] - 3);
        }

        if (adjusted_length > data_maxsize) {
            strcpy(symbol->errtxt, "Data too long for specified Aztec Code symbol size (E05)");
            return ZINT_ERROR_TOO_LONG;
        }

        if (debug) {
            printf("Codewords:\n");
            for (i = 0; i < (adjusted_length / codeword_size); i++) {
                for (j = 0; j < codeword_size; j++) {
................................................................................
                printf("\n");
            }
        }

    }

    if (reader && (layers > 22)) {
        strcpy(symbol->errtxt, "Data too long for reader initialisation symbol (E06)");
        return ZINT_ERROR_TOO_LONG;
    }

    data_blocks = adjusted_length / codeword_size;

    if (compact) {
        ecc_blocks = AztecCompactSizes[layers - 1] - data_blocks;
................................................................................
        } else {
            if ((data_blocks - 1) & 0x20) {
                descriptor[2] = '1';
            } else {
                descriptor[2] = '0';
            }
        }





        for (i = 3; i < 8; i++) {
            if ((data_blocks - 1) & (0x10 >> (i - 3))) {
                descriptor[i] = '1';
            } else {
                descriptor[i] = '0';
            }




        }










        descriptor[8] = '\0';
        if (debug) printf("Mode Message = %s\n", descriptor);
    } else {
        /* The first 5 bits represent the number of layers minus 1 */
        for (i = 0; i < 5; i++) {




            if ((layers - 1) & (0x10 >> i)) {
                descriptor[i] = '1';
            } else {
                descriptor[i] = '0';
            }




        }










        /* The next 11 bits represent the number of data blocks minus 1 */
        if (reader) {
            descriptor[5] = '1';
        } else {
            if ((data_blocks - 1) & 0x400) {
                descriptor[5] = '1';
            } else {
                descriptor[5] = '0';
            }
        }
        for (i = 6; i < 16; i++) {




            if ((data_blocks - 1) & (0x200 >> (i - 6))) {
                descriptor[i] = '1';
            } else {
                descriptor[i] = '0';
            }







































        }
        descriptor[16] = '\0';
        if (debug) printf("Mode Message = %s\n", descriptor);
    }

    /* Split into 4-bit codewords */
    for (i = 0; i < 4; i++) {
................................................................................
    int input_value, error_number, i, p, y, x;
    char binary_string[28];
    unsigned char data_codewords[3], ecc_codewords[6];

    error_number = 0;
    input_value = 0;
    if (length > 3) {
        strcpy(symbol->errtxt, "Input too large (E07)");
        return ZINT_ERROR_INVALID_DATA;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number != 0) {
        strcpy(symbol->errtxt, "Invalid characters in input (E08)");
        return ZINT_ERROR_INVALID_DATA;
    }
    switch (length) {
        case 3: input_value = 100 * ctoi(source[0]);
            input_value += 10 * ctoi(source[1]);
            input_value += ctoi(source[2]);
            break;
................................................................................
            input_value += ctoi(source[1]);
            break;
        case 1: input_value = ctoi(source[0]);
            break;
    }

    if (input_value > 255) {
        strcpy(symbol->errtxt, "Input too large (E09)");
        return ZINT_ERROR_INVALID_DATA;
    }

    strcpy(binary_string, "");
    for (p = 0; p < 8; p++) {
        if (input_value & (0x80 >> p)) {
            strcat(binary_string, "1");

Changes to jni/zint/backend/aztec.h.

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
..
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#define UPPER	1
#define LOWER	2
#define MIXED	4
#define PUNC	8
#define DIGIT	16
#define BINARY	32

static int AztecMap[22801];

static const int CompactAztecMap[] = {
    /* 27 x 27 data grid */
    609, 608, 411, 413, 415, 417, 419, 421, 423, 425, 427, 429, 431, 433, 435, 437, 439, 441, 443, 445, 447, 449, 451, 453, 455, 457, 459,
    607, 606, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458,
    605, 604, 409, 408, 243, 245, 247, 249, 251, 253, 255, 257, 259, 261, 263, 265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 460, 461,
    603, 602, 407, 406, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 462, 463,
    601, 600, 405, 404, 241, 240, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 284, 285, 464, 465,
................................................................................

/* Problem characters are:
        300: Carriage Return (ASCII 13)
        301: Comma (ASCII 44)
        302: Full Stop (ASCII 46)
 */

static const char *hexbit[32] = {
    "00000", "00001", "00010", "00011", "00100", "00101", "00110", "00111", "01000", "01001",
    "01010", "01011", "01100", "01101", "01110", "01111", "10000", "10001", "10010", "10011", "10100", "10101",
    "10110", "10111", "11000", "11001", "11010", "11011", "11100", "11101", "11110", "11111"
};

static const char *pentbit[16] = {
    "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001",
    "1010", "1011", "1100", "1101", "1110", "1111"
};

static const char *tribit[8] = {
    "000", "001", "010", "011", "100", "101", "110", "111"
};







<
<







 







|





|







33
34
35
36
37
38
39


40
41
42
43
44
45
46
..
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#define UPPER	1
#define LOWER	2
#define MIXED	4
#define PUNC	8
#define DIGIT	16
#define BINARY	32



static const int CompactAztecMap[] = {
    /* 27 x 27 data grid */
    609, 608, 411, 413, 415, 417, 419, 421, 423, 425, 427, 429, 431, 433, 435, 437, 439, 441, 443, 445, 447, 449, 451, 453, 455, 457, 459,
    607, 606, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458,
    605, 604, 409, 408, 243, 245, 247, 249, 251, 253, 255, 257, 259, 261, 263, 265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 460, 461,
    603, 602, 407, 406, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 462, 463,
    601, 600, 405, 404, 241, 240, 107, 109, 111, 113, 115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 284, 285, 464, 465,
................................................................................

/* Problem characters are:
        300: Carriage Return (ASCII 13)
        301: Comma (ASCII 44)
        302: Full Stop (ASCII 46)
 */

static const char *pentbit[32] = {
    "00000", "00001", "00010", "00011", "00100", "00101", "00110", "00111", "01000", "01001",
    "01010", "01011", "01100", "01101", "01110", "01111", "10000", "10001", "10010", "10011", "10100", "10101",
    "10110", "10111", "11000", "11001", "11010", "11011", "11100", "11101", "11110", "11111"
};

static const char *quadbit[16] = {
    "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001",
    "1010", "1011", "1100", "1101", "1110", "1111"
};

static const char *tribit[8] = {
    "000", "001", "010", "011", "100", "101", "110", "111"
};

Added jni/zint/backend/bmp.c.































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* bmp.c - Handles output to Windows Bitmap file */

/*
    libzint - the open source barcode library
    Copyright (C) 2009-2016 Robin Stuart <rstuart114@gmail.com>

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

    1. Redistributions of source code must retain the above copyright 
       notice, this list of conditions and the following disclaimer.  
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.  
    3. Neither the name of the project nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission. 

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
    SUCH DAMAGE.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "bmp.h"        /* Bitmap header structure */
#include <math.h>
#ifdef _MSC_VER
#include <io.h>
#include <fcntl.h>
#endif

#define SSET	"0123456789ABCDEF"

int bmp_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) {
    int i, row, column;
    int fgred, fggrn, fgblu, bgred, bggrn, bgblu;
    int row_size;
    unsigned int data_size;
    unsigned char *bitmap_file_start, *bmp_posn;
    char *bitmap;
    FILE *bmp_file;
    bitmap_file_header_t file_header;
    bitmap_info_header_t info_header;

    if (symbol->bitmap != NULL)
        free(symbol->bitmap);

    row_size = 4 * floor((24.0 * symbol->bitmap_width + 31) / 32);
    bitmap = (char *) malloc(row_size * symbol->bitmap_height);

    fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
    fggrn = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]);
    fgblu = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]);
    bgred = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]);
    bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]);
    bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]);

    /* Pixel Plotting */
    i = 0;
    for (row = 0; row < symbol->bitmap_height; row++) {
        for (column = 0; column < symbol->bitmap_width; column++) {
            i = (3 * column) + (row * row_size);
            switch (*(pixelbuf + (symbol->bitmap_width * (symbol->bitmap_height - row - 1)) + column)) {
                case '1':
                    bitmap[i] = fgblu;
                    bitmap[i + 1] = fggrn;
                    bitmap[i + 2] = fgred;
                    break;
                default:
                    bitmap[i] = bgblu;
                    bitmap[i + 1] = bggrn;
                    bitmap[i + 2] = bgred;
                    break;

            }
        }
    }

    data_size = symbol->bitmap_height * row_size;
    symbol->bitmap_byte_length = data_size;

    file_header.header_field = 0x4d42; // "BM"
    file_header.file_size = sizeof (bitmap_file_header_t) + sizeof (bitmap_info_header_t) + data_size;
    file_header.reserved = 0;
    file_header.data_offset = sizeof (bitmap_file_header_t) + sizeof (bitmap_info_header_t);

    info_header.header_size = sizeof (bitmap_info_header_t);
    info_header.width = symbol->bitmap_width;
    info_header.height = symbol->bitmap_height;
    info_header.colour_planes = 1;
    info_header.bits_per_pixel = 24;
    info_header.compression_method = 0; // BI_RGB
    info_header.image_size = 0;
    info_header.horiz_res = 0;
    info_header.vert_res = 0;
    info_header.colours = 0;
    info_header.important_colours = 0;

    bitmap_file_start = (unsigned char*) malloc(file_header.file_size);
    memset(bitmap_file_start, 0xff, file_header.file_size);

    bmp_posn = bitmap_file_start;
    memcpy(bitmap_file_start, &file_header, sizeof (bitmap_file_header_t));
    bmp_posn += sizeof (bitmap_file_header_t);
    memcpy(bmp_posn, &info_header, sizeof (bitmap_info_header_t));
    bmp_posn += sizeof (bitmap_info_header_t);
    memcpy(bmp_posn, bitmap, data_size);

    /* Open output file in binary mode */
    if ((symbol->output_options & BARCODE_STDOUT) != 0) {
#ifdef _MSC_VER
        if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
            strcpy(symbol->errtxt, "Can't open output file");
            return ZINT_ERROR_FILE_ACCESS;
        }
#endif
        bmp_file = stdout;
    } else {
        if (!(bmp_file = fopen(symbol->outfile, "wb"))) {
            strcpy(symbol->errtxt, "Can't open output file (F00)");
            return ZINT_ERROR_FILE_ACCESS;
        }
    }

    fwrite(bitmap_file_start, file_header.file_size, 1, bmp_file);
    fclose(bmp_file);

    free(bitmap_file_start);
    free(bitmap);
    return 0;
}

Added jni/zint/backend/bmp.h.

























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*  bmp.h - header structure for Windows bitmap files

    libzint - the open source barcode library
    Copyright (C) 2009-2016 Robin Stuart <rstuart114@gmail.com>

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

    1. Redistributions of source code must retain the above copyright 
       notice, this list of conditions and the following disclaimer.  
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.  
    3. Neither the name of the project nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission. 

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
    SUCH DAMAGE.
 */

#ifndef BMP_H
#define BMP_H

#ifdef __cplusplus
extern "C" {
#endif

#ifdef _MSC_VER
#include <windows.h>
#include "stdint_msvc.h"
#else
#include <stdint.h>
#endif

#pragma pack (1)
    
    typedef struct bitmap_file_header {
        uint16_t header_field;
        uint32_t file_size;
        uint32_t reserved;
        uint32_t data_offset;
    } bitmap_file_header_t;

    typedef struct bitmap_info_header {
        uint32_t header_size;
        int32_t width;
        int32_t height;
        uint16_t colour_planes;
        uint16_t bits_per_pixel;
        uint32_t compression_method;
        uint32_t image_size;
        int32_t horiz_res;
        int32_t vert_res;
        uint32_t colours;
        uint32_t important_colours;
    } bitmap_info_header_t;
    
#pragma pack ()
    
#ifdef __cplusplus
}
#endif

#endif /* BMP_H */

Added jni/zint/backend/codablock.c.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
/* codablock.c - Handles Codablock-F and Codablock-E */

/*
    libzint - the open source barcode library
    Copyright (C) 2016 Harald Oehlmann

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

    1. Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
    3. Neither the name of the project nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    SUCH DAMAGE.
 */

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#ifdef _MSC_VER
#include <malloc.h>
#endif
#include "common.h"
#include "gs1.h"

#define uchar unsigned char

/* FTab C128 flags - may be added */
#define CodeA 1
#define CodeB 2
#define CodeC 4
#define CEnd 8
#define CShift 16
#define CFill 32
#define CodeFNC1 64
#define ZTNum (CodeA+CodeB+CodeC)
#define ZTFNC1 (CodeA+CodeB+CodeC+CodeFNC1)

/* ASCII-Extension for Codablock-F */
#define aFNC1 (uchar)(128)
#define aFNC2 (uchar)(129)
#define aFNC3 (uchar)(130)
#define aFNC4 (uchar)(131)
#define aCodeA (uchar)(132)
#define aCodeB (uchar)(133)
#define aCodeC (uchar)(134)
#define aShift (uchar)(135)

static const char *C128Table[107] = {
    /* Code 128 character encodation - Table 1 */
    "212222", "222122", "222221", "121223", "121322", "131222", "122213",
    "122312", "132212", "221213", "221312", "231212", "112232", "122132", "122231", "113222",
    "123122", "123221", "223211", "221132", "221231", "213212", "223112", "312131", "311222",
    "321122", "321221", "312212", "322112", "322211", "212123", "212321", "232121", "111323",
    "131123", "131321", "112313", "132113", "132311", "211313", "231113", "231311", "112133",
    "112331", "132131", "113123", "113321", "133121", "313121", "211331", "231131", "213113",
    "213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111", "314111",
    "221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214",
    "112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112",
    "134111", "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112",
    "421211", "212141", "214121", "412121", "111143", "111341", "131141", "114113", "114311",
    "411113", "411311", "113141", "114131", "311141", "411131", "211412", "211214", "211232",
    "2331112"
};

/* Code F Analysing-Chart */
typedef struct sCharacterSetTable
{
    int CharacterSet;       /* Still possible character sets for actual*/
    int AFollowing;     /* Still following Characters in Charset A */
    int BFollowing;     /* Still following Characters in Charset B */
    int CFollowing;     /* Still following Characters in Charset C */
} CharacterSetTable;

/* Find the possible Code-128 Character sets for a character
 * The result is an or of CodeA,CodeB,CodeC,CodeFNC1 in dependency of the
 * possible Code 128 character sets.
 */
int GetPossibleCharacterSet(unsigned char C)
{
    if (C<='\x19')      /* Dec:31 */
        return CodeA;
    if (C>='0' && C<='9')
        return ZTNum;   /* ZTNum=CodeA+CodeB+CodeC */
    if (C==aFNC1)
        return ZTFNC1;  /* ZTFNC1=CodeA+CodeB+CodeC+CodeFNC1 */
    if (C>='\x60' && C<='\x7f')      /* 60 to 127 */
        return CodeB;
    return CodeA+CodeB;
}

/* Create a Table with the following information for each Data character:
 *  int CharacterSet    is an or of CodeA,CodeB,CodeC,CodeFNC1, in
 *          dependency which character set is applicable.
 *          (Result of GetPossibleCharacterSet)
 *  int AFollowing,BFollowing   The number of source characters you still may encode
 *          in this character set.
 *  int CFollowing  The number of characters encodable in CodeC if we
 *          start here.
 */
void CreateCharacterSetTable(CharacterSetTable T[], unsigned char *data, int dataLength)
{
    int charCur;
    int runChar;

    /* Treat the Data backwards */
    charCur=dataLength-1;
    T[charCur].CharacterSet=GetPossibleCharacterSet(data[charCur]);
    T[charCur].AFollowing=((T[charCur].CharacterSet & CodeA)==0)?0:1;
    T[charCur].BFollowing=((T[charCur].CharacterSet & CodeB)==0)?0:1;
    T[charCur].CFollowing=0;

    for (charCur--;charCur>=0;charCur--)
    {
        T[charCur].CharacterSet=GetPossibleCharacterSet(data[charCur]);
        T[charCur].AFollowing=
            ((T[charCur].CharacterSet & CodeA)==0)?0:T[charCur+1].AFollowing+1;
        T[charCur].BFollowing=
            ((T[charCur].CharacterSet & CodeB)==0)?0:T[charCur+1].BFollowing+1;
        T[charCur].CFollowing=0;

    }
    /* Find the CodeC-chains */
    for (charCur=0;charCur<dataLength;charCur++)
    {
        T[charCur].CFollowing=0;
        if ((T[charCur].CharacterSet & CodeC)!=0)
        {
            /* CodeC possible */
            runChar=charCur;
            do{
                /* Wether this is FNC1 wether next is */
                /* numeric */
                if (T[runChar].CharacterSet==ZTFNC1)
                    /* FNC1 */
                    ++(T[charCur].CFollowing);
                else
                {
                    ++runChar;
                    if (runChar>=dataLength)
                        break;
                    /* Only a Number may follow */
                    if (T[runChar].CharacterSet==ZTNum)
                        T[charCur].CFollowing+=2;
                    else
                        break;
                }
                ++runChar;
            } while (runChar<dataLength);
        }
    }
}

/* Find the amount of numerical characters in pairs which will fit in
 * one bundle into the line (up to here). This is calculated online because
 * it depends on the space in the line.
 */
int RemainingDigits(CharacterSetTable *T, int charCur,int emptyColumns)
{
    int digitCount;     /* Numerical digits fitting in the line */
    int runChar;
    runChar=charCur;
    digitCount=0;
    while(emptyColumns>0 && runChar<charCur+T[charCur].CFollowing)
    {
        if (T[runChar].CharacterSet!=ZTFNC1)
        {
            /* NOT FNC1 */
            digitCount+=2;
            runChar++;
        }
        runChar++;
        emptyColumns--;
    }
    return digitCount;
}

/* Find the Character distribution at a given column count.
 * If to many rows (>44) are requested the columns is extended.
 * A oneLigner may be choosen if shorter.
 * Parameters :
 *  T       Pointer on the Characters which fit in the row
 *          If a different count is calculated it is corrected
 *          in the callers workspace.
 *  pFillings   Output of filling characters
 *  pSet        Output of the character sets used, allocated by me.
 *  Data        The Data string to encode, exceptionnally not an out
 *  Return value    Resulting row count
 */

int Columns2Rows(CharacterSetTable *T, unsigned char *data, int dataLength,
        int * pRows, int * pUseColumns, int * pSet, int * pFillings)
{
    int useColumns;     /* Usable Characters per line */
    int fillings;       /* Number of filling characters */
    int rowsCur;
    int charCur;
    int runChar;
    int emptyColumns;   /* Number of codes still empty in line. */
    int emptyColumns2;  /* Alternative emptyColumns to compare */
    int fOneLiner;      /* Flag if One Liner */
    int CPaires;        /* Number of digit pairs which may fit in the line */
    int characterSetCur;        /* Current Character Set */

    useColumns=*pUseColumns;
    if (useColumns<3)
        useColumns=3;

    /* >>> Loop until rowsCur<44 */
    do {
        memset(pSet,0,dataLength*sizeof(int));
        charCur=0;
        rowsCur=0;
        fOneLiner=1;        /* First try one-Liner */

        /* >>> Line and OneLiner-try Loop */
        do{
            /* >> Start Character */
            emptyColumns=useColumns;    /* Remained place in Line */
            if (fOneLiner)
                emptyColumns+=2;

            /* >>Choose in Set A or B */
            /* (C is changed as an option later on) */

            pSet[charCur]=characterSetCur=
                (T[charCur].AFollowing > T[charCur].BFollowing)
                ? CodeA : CodeB;

            /* >> Test on Numeric Mode C */
            CPaires=RemainingDigits(T,charCur, emptyColumns);
            if (CPaires>=4)
            {
                /* 4 Digits in Numeric compression ->OK */
                /* > May an odd start find more ? */
                /* Skip leading <FNC1>'s */
                /* Typical structure : <FNC1><FNC1>12... */
                /* Test if numeric after one isn't better.*/
                runChar=charCur;
                emptyColumns2=emptyColumns;
                while (T[runChar].CharacterSet==ZTFNC1)
                {
                    ++runChar;
                    --emptyColumns2;
                }
                if (CPaires>=RemainingDigits(T,runChar+1,emptyColumns2-1))
                {
                    /* Start odd is not better */
                    /* We start in C */
                    pSet[charCur]=characterSetCur=CodeC;
                    /* Inkrement charCur */
                    if (T[charCur].CharacterSet!=ZTFNC1)
                        ++charCur;      /* 2 Num.Digits */
                }
            }
            ++charCur;
            --emptyColumns;

            /* >> Following characters */
            while(emptyColumns>0 && charCur<dataLength)
            {
                switch(characterSetCur){
                case CodeA:
                case CodeB:
                    /* >> Check switching to CodeC */
                    /* Switch if :
                     *  - Character not FNC1
                     *  - 4 real Digits will fit in line
                     *  - an odd Start will not be better
                     */
                    if (T[charCur].CharacterSet==ZTNum
                        && (CPaires=RemainingDigits(T,charCur, emptyColumns-1))>=4
                        && CPaires > RemainingDigits(T,charCur+1,emptyColumns-2))
                    {
                        /* > Change to C */
                        pSet[charCur]=characterSetCur=CodeC;
                        charCur+=2; /* 2 Digit */
                        emptyColumns-=2; /* <SwitchC>12 */
                    } else if (characterSetCur==CodeA)
                    {
                        if(T[charCur].AFollowing==0)
                        {
                            /* Must change to B */
                            if (emptyColumns==1)
                            {
                                /* Can't switch: */
                                pSet[charCur-1]|=CEnd+CFill;
                                emptyColumns=0;
                            }else{
                                /* <Shift> or <switchB>? */
                                pSet[charCur]|=(T[charCur].BFollowing==1)?CShift:CodeB;
                                emptyColumns-=2;
                                ++charCur;
                            }
                        }else{
                            --emptyColumns;
                            ++charCur;
                        }
                    } else { /* Last possibility : CodeB */
                        if(T[charCur].BFollowing==0)
                        {
                            /* Must change to A */
                            if (emptyColumns==1)
                            {
                                /* Can't switch: */
                                pSet[charCur-1]|=CEnd+CFill;
                                emptyColumns=0;
                            } else {
                                /* <Shift> or <switchA>? */
                                pSet[charCur]|=(T[charCur].AFollowing==1)?CShift:CodeA;
                                emptyColumns-=2;
                                ++charCur;
                            }
                        }else{
                            --emptyColumns;
                            ++charCur;
                        }
                    }
                    break;
                case CodeC:
                    if(T[charCur].CFollowing>0)
                    {
                        charCur+=(T[charCur].CharacterSet==ZTFNC1)?1:2;
                        emptyColumns--;
                    }else{
                        /* Must change to A or B */
                        if (emptyColumns==1)
                        {
                            /* Can't switch: */
                            pSet[charCur-1]|=CEnd+CFill;
                            emptyColumns=0;
                        }else{
                            /*<SwitchA> or <switchA>?*/
                            characterSetCur=pSet[charCur]=
                                (T[charCur].AFollowing > T[charCur].BFollowing)
                                ?CodeA:CodeB;
                            emptyColumns-=2;
                            ++charCur;
                        }
                    }
                    break;
                } /* switch */
            } /* while */

            /* > End of Codeline */
            pSet[charCur-1]|=CEnd;
            ++rowsCur;
            if ( fOneLiner)
            {
                if (charCur<dataLength)
                {
                    /* One line not sufficiant */
                    fOneLiner=0;
                    /* Reset and Start again */
                    charCur=0;
                    rowsCur=0;
                    memset(pSet,0,dataLength*sizeof(int));
                }else{
                    /* Calculate real Length of OneLiner */
                    /* This is -2 BASED !!! */
                    useColumns-=emptyColumns;
                }
            }
        } while (charCur<dataLength); /* <= Data.Len-1 */

        /* Place check characters C1,C2 */
        if (fOneLiner)
            fillings=0;
        else{
            switch (emptyColumns) {
            case 1:
                pSet[charCur-1]|=CFill;
                /* Glide in following block without break */
            case 0:
                ++rowsCur;
                fillings=useColumns-2+emptyColumns;
                break;
            case 2:
                fillings=0;
                break;
            default:
                pSet[charCur-1]|=CFill;
                fillings=emptyColumns-2;
            }
        }

        if (rowsCur>44) {
            ++useColumns;
            if (useColumns > 62) {
                return ZINT_ERROR_TOO_LONG;
            }
        }
    } while(rowsCur>44);
    #ifdef _DEBUG
        printf("  -> out: rowsCur <%i>, useColumns <%i>, fillings <%i>\n",rowsCur,useColumns,fillings);
    #endif
    *pUseColumns=useColumns;
    *pRows=rowsCur;
    *pFillings=fillings;
    return 0;
}
/* Find columns if row count is given.
 */
int Rows2Columns(CharacterSetTable *T, unsigned char *data, int dataLength,
        int * pRows, int * pUseColumns, int * pSet, int * pFillings)
{
    int errorCur;
    int rowsCur;
    int rowsRequested;  /* Number of requested rows */
    int backupRows = 0;
    int fillings;
    int backupFillings = 0;
    int useColumns;
    int testColumns;    /* To enter into Width2Rows */
    int backupColumns = 0;
    int fBackupOk = 0;      /* The memorysed set is o.k. */
    int testListSize = 0;
    int pTestList[62];
#ifndef _MSC_VER
    int *pBackupSet[dataLength];
#else
    int *pBackupSet = (int *)_alloca(dataLength*sizeof(int));
#endif

    rowsRequested=*pRows;

    #ifdef _DEBUG
        fprintf(stderr,"Optimizer : Searching <%i> rows\n",rowsRequested);
    #endif

    if (rowsRequested==1)
        /* OneLiners are self-calibrating */
        testColumns=32767;
    else {
        /* First guess */
        testColumns=dataLength/rowsRequested;
        if (testColumns > 62)
            testColumns = 62;
        else if (testColumns < 1)
            testColumns = 1;
    }

    for (;;) {
        pTestList[testListSize] = testColumns;
        testListSize++;
        useColumns=testColumns; /* Make a copy because it may be modified */
        errorCur = Columns2Rows(T, data, dataLength, &rowsCur, &useColumns, pSet, &fillings);
        if (errorCur != 0)
            return errorCur;
        if (rowsCur<=rowsRequested) {
            /* Less or exactly line number found */
            /* check if column count below already tested or Count = 1*/
            int fInTestList = (rowsCur == 1 || testColumns == 1);
            int posCur;
            for (posCur = 0; posCur < testListSize && ! fInTestList; posCur++) {
                if ( pTestList[posCur] == testColumns-1 )
                    fInTestList = 1;
            }
            if (fInTestList) {
                /* >> Smaller Width already tested
                 * if rowsCur=rowsRequested->Exit
                 * if rowsCur<rowsRequested and fillings>0
                 * -> New search for rowsRequested:=rowsCur
                 */
                if ( rowsCur == rowsRequested || fillings == 0 || testColumns == 1 ) {
                    /* Exit with actual */
                    *pFillings=fillings;
                    *pRows=rowsCur;
                    *pUseColumns = useColumns;
                    return 0;
                }
                /* Search again for smaller Line number */
                rowsRequested=rowsCur;
                pTestList[0] = testColumns;
                testListSize = 1;
            }
            /* > Test more rows (shorter CDB) */
            fBackupOk=(rowsCur==rowsRequested);
            memcpy(pBackupSet,pSet,dataLength*sizeof(int));
            backupFillings=fillings;
            backupColumns=useColumns;
            backupRows=rowsCur;
            --testColumns;
        } else {
            /* > To many rows */
            int fInTestList = fBackupOk;
            int posCur;
            for (posCur = 0; posCur < testListSize && ! fInTestList; posCur++) {
                if ( pTestList[posCur] == testColumns+1 )
                    fInTestList = 1;
            }
            if (fInTestList) {
                /* The next less-rows (larger) code was
                 * already tested. So give the larger
                 * back.
                 */
                memcpy(pSet,pBackupSet,dataLength*sizeof(int));
                *pFillings=backupFillings;
                *pRows=backupRows;
                *pUseColumns=backupColumns;
                return 0;
            }
            /* > Test less rows (longer code) */
            backupRows=rowsCur;
            memcpy(pBackupSet,pSet,dataLength*sizeof(int));
            backupFillings=fillings;
            backupColumns=useColumns;
            fBackupOk=0;
            ++testColumns;
        }
    }
}

/* Print a character in character set A
 */
void A2C128_A(uchar **ppOutPos,uchar c)
{
    uchar * pOutPos = *ppOutPos;
    switch(c){
    case aCodeB: *pOutPos=100; break;
    case aFNC4: *pOutPos=101; break;
    case aFNC1: *pOutPos=102; break;
    case aFNC2: *pOutPos=97; break;
    case aFNC3: *pOutPos=96; break;
    case aCodeC: *pOutPos=99; break;
    case aShift: *pOutPos=98; break;
    default:
        /* +++ HaO 13.11.98 c>' ' && c < '\x1F' corrected */
        if(c>=' ' && c<='_')
            *pOutPos=(uchar)(c-' ');
        else
            *pOutPos=(uchar)(c+64);
        break;
    }
    (*ppOutPos)++;
}
/* Output c in Set B
 */
void A2C128_B(uchar **ppOutPos,uchar c)
{
    uchar * pOutPos = *ppOutPos;
    switch(c){
    case aFNC1: *pOutPos=102; break;
    case aFNC2: *pOutPos=97; break;
    case aFNC3: *pOutPos=96; break;
    case aFNC4: *pOutPos=100; break;
    case aCodeA: *pOutPos=101; break;
    case aCodeC: *pOutPos=99; break;
    case aShift: *pOutPos=98; break;
    default: *pOutPos=(uchar)(c-' '); break;
    }
    ++(*ppOutPos);
}
/* Output c1, c2 in Set C
 */
void A2C128_C(uchar **ppOutPos,uchar c1,uchar c2)
{
    uchar * pOutPos = *ppOutPos;
    switch(c1){
    case aFNC1: *pOutPos=102; break;
    case aCodeB: *pOutPos=100; break;
    case aCodeA: *pOutPos=101; break;
    default: *pOutPos=(char)(10 * (c1- '0') + (c2 - '0'));break;
    }
    (*ppOutPos)++;
}
/* Output a character in Characterset
 */
void ASCIIZ128(uchar **ppOutPos, int CharacterSet,uchar c1, uchar c2)
{
    if (CharacterSet==CodeA)
        A2C128_A(ppOutPos,c1);
    else if(CharacterSet==CodeB)
        A2C128_B(ppOutPos,c1);
    else
        A2C128_C(ppOutPos,c1,c2);
}
/* XLate Table A of Codablock-F Specification and call output
 */
void SumASCII(uchar **ppOutPos, int Sum, int CharacterSet)
{
    switch (CharacterSet){
    case CodeA:
        A2C128_A(ppOutPos, (uchar)Sum);
        break;
    case CodeB:
        if (Sum<=31)
            A2C128_B(ppOutPos, (uchar)(Sum+96));
        else if(Sum<=47)
            A2C128_B(ppOutPos, (uchar)Sum);
        else
            A2C128_B(ppOutPos, (uchar)(Sum+10));
        break;
    case CodeC:
        A2C128_C(ppOutPos
            ,(char)(Sum/10+'0') ,(uchar)(Sum%10+'0'));
        break;
    }
}

/* Main function called by zint framework
 */
int codablock(struct zint_symbol *symbol, unsigned char source[], int length) {
    int charCur;
    int dataLength;
    int Error;
    int rows, columns, useColumns;
    int fillings;
    int Sum1,Sum2;
    uchar * pOutPos;
    int rowCur;
    int characterSetCur;
    int emptyColumns;
        char dest[1000];
        int r, c;
#ifdef _MSC_VER
    CharacterSetTable *T;
    unsigned char *data;
    int *pSet;
    uchar * pOutput;
#endif

    /* Parameter check */
    /* option1: rows 0: automatic, 1..44 */
    rows = symbol->option_1;
    if (rows > 44) {
        strcpy(symbol->errtxt, "Row parameter not in 0..44 (D10)");
        return ZINT_ERROR_INVALID_OPTION;
    }
    /* option_2: (usable data) columns: 0: automatic, 6..66 */
    columns = symbol->option_2;
    if ( ! (columns <= 0 || (columns >= 6 && columns <=66)) ) {
        strcpy(symbol->errtxt, "Columns parameter not in 0,6..66 (D11)");
        return ZINT_ERROR_INVALID_OPTION;
    }
    /* GS1 not implemented */
    if  (symbol->input_mode == GS1_MODE) {
        strcpy(symbol->errtxt, "GS1 mode not supported (D12)");
        return ZINT_ERROR_INVALID_OPTION;
    }
#ifndef _MSC_VER
    unsigned char data[length*2+1];
#else
    data = (unsigned char *) _alloca(length * 2+1);
#endif

    dataLength = 0;
    if (symbol->output_options & READER_INIT) {
        data[dataLength] = aFNC3;
        dataLength++;
    }
    /* Replace all Codes>127 with <fnc4>Code-128 */
    for (charCur=0;charCur<length;charCur++) {
        if (source[charCur]>127)
        {
            data[dataLength] = aFNC4;
            dataLength++;
            data[dataLength] = (unsigned char)(source[charCur]&127);
        } else
            data[dataLength] = source[charCur];
        dataLength++;
    }

    /* Build character set table */
#ifndef _MSC_VER
    CharacterSetTable T[dataLength];
    int pSet[dataLength];
#else
    T=(CharacterSetTable *)_alloca(dataLength*sizeof(CharacterSetTable));
    pSet = (int *)_alloca(dataLength*sizeof(int));
#endif
    CreateCharacterSetTable(T,data,dataLength);

    /* Find final row and column count */
    /* nor row nor column count given */
    if ( rows <= 0 && columns <= 5 ) {
        /* Use Code128 until reasonable size */
        if (dataLength < 9) {
            rows = 1;
        } else {
            /* use 1/1 aspect/ratio Codablock */
            columns = ((int)floor(sqrt(1.0*dataLength))+5);
            if (columns > 64)
                columns = 64;
                #ifdef _DEBUG
                printf("Auto column count for %d characters:%d\n",dataLength,columns);
                #endif
        }
    }
    /* There are 5 Codewords for Organisation Start(2),row(1),CheckSum,Stop */
    useColumns = columns - 5;
    if ( rows > 0 ) {
        /* row count given */
        Error=Rows2Columns(T,data,dataLength,&rows,&useColumns,pSet,&fillings);
    } else {
        /* column count given */
        Error=Columns2Rows(T,data,dataLength,&rows,&useColumns,pSet,&fillings);
    }
    if (Error != 0) {
        strcpy(symbol->errtxt, "data string to long (D13)");
        return Error;
    }
    /* Checksum */
    Sum1=Sum2=0;
    if (rows>1)
    {
        int charCur;
        for (charCur=0 ; charCur<dataLength ; charCur++) {
            Sum1=(Sum1 + (charCur%86+1)*data[charCur])%86;
            Sum2=(Sum2 + (charCur%86)*data[charCur])%86;
        }
    }

    #ifdef _DEBUG
    {   /* start a new level of local variables */
        int DPos;
        printf("\nData:");
        for (DPos=0 ; DPos< dataLength ; DPos++)
            fputc(data[DPos],stdout);

        printf("\n Set:");
        for (DPos=0 ; DPos< dataLength ; DPos++) {
            switch (pSet[DPos]&(CodeA+CodeB+CodeC)) {
            case CodeA: fputc('A',stdout); break;
            case CodeB: fputc('B',stdout); break;
            case CodeC: fputc('C',stdout); break;
            default: fputc('.',stdout); break;
            }
        }
        printf("\nFNC1:");
        for (DPos=0 ; DPos< dataLength ; DPos++)
            fputc((pSet[DPos]&CodeFNC1)==0?'.':'X',stdout);
        printf("\n END:");
        for (DPos=0 ; DPos< dataLength ; DPos++)
            fputc((pSet[DPos]&CEnd)==0?'.':'X',stdout);
        printf("\nShif:");
        for (DPos=0 ; DPos< dataLength ; DPos++)
            fputc((pSet[DPos]&CShift)==0?'.':'X',stdout);
        printf("\nFILL:");
        for (DPos=0 ; DPos< dataLength ; DPos++)
            fputc((pSet[DPos]&CFill)==0?'.':'X',stdout);
        fputc('\n',stdout);
    }
    #endif

    columns = useColumns + 5;

    /* >>> Build C128 code numbers */
    /* The C128 column count contains Start (2CW), Row ID, Checksum, Stop */
#ifndef _MSC_VER
    uchar pOutput[columns * rows];
#else
    pOutput = (unsigned char *)_alloca(columns * rows * sizeof(char));
#endif
    pOutPos = pOutput;
    charCur=0;
    /* >> Loop over rows */
    for (rowCur=0 ; rowCur<rows ; rowCur++) {
        if (charCur>=dataLength)
        {
            /* >> Empty line with StartCCodeBCodeC */
            characterSetCur=CodeC;
            /* CDB Start C*/
            *pOutPos='\x67';
            pOutPos++;
            *pOutPos='\x63';
            pOutPos++;
            SumASCII(&pOutPos,rowCur+42,CodeC);
            emptyColumns=useColumns-2;
            while (emptyColumns>0)
            {
                if(characterSetCur==CodeC)
                {
                    A2C128_C(&pOutPos,aCodeB,'\0');
                    characterSetCur=CodeB;
                }else{
                    A2C128_B(&pOutPos,aCodeC);
                    characterSetCur=CodeC;
                }
                --emptyColumns;
            }
        }else{
            /* >> Normal Line */
            /* > Startcode */
            switch (pSet[charCur] & (CodeA+CodeB+CodeC)){
            case CodeA:
                *pOutPos = '\x67';
                pOutPos++;
                if (rows>1) {
                    *pOutPos = '\x62';
                    pOutPos++;
                }
                characterSetCur=CodeA;
                break;
            case CodeB:
                if (rows==1) {
                    *pOutPos = '\x68';
                    pOutPos++;
                } else {
                    *pOutPos = '\x67';
                    pOutPos++;
                    *pOutPos = '\x64';
                    pOutPos++;
                }
                characterSetCur=CodeB;
                break;
            case CodeC:
            default:
                if (rows==1) {
                    *pOutPos = '\x69';
                    pOutPos++;
                } else {
                    *pOutPos = '\x67';
                    pOutPos++;
                    *pOutPos = '\x63';
                    pOutPos++;
                }
                characterSetCur=CodeC;
                break;
            }
            if (rows>1)
            {
                /* > Set F1 */
                /* In first line : # of rows */
                /* In Case of CodeA we shifted to CodeB */
                SumASCII(&pOutPos
                    ,(rowCur==0)?rows-2:rowCur+42
                    ,(characterSetCur==CodeA)?CodeB:characterSetCur
                );
            }
            /* >>> Data */
            emptyColumns=useColumns;
            /* +++ One liner don't have start/stop code */
            if (rows == 1)
                emptyColumns +=2;
            /* >> Character loop */
            while (emptyColumns>0)
            {
                /* ? Change character set */
                /* not at first possition (It was then the start set) */
                /* +++ special case for one-ligner */
                if (emptyColumns<useColumns || (rows == 1 && charCur!=0) )
                {
                    if ((pSet[charCur]&CodeA)!=0)
                    {
                        /* Change to A */
                        ASCIIZ128(&pOutPos,characterSetCur,aCodeA,'\0');
                        --emptyColumns;
                        characterSetCur=CodeA;
                    } else if ((pSet[charCur]&CodeB)!=0)
                    {
                        /* Change to B */
                        ASCIIZ128(&pOutPos,characterSetCur,aCodeB,'\0');
                        --emptyColumns;
                        characterSetCur=CodeB;
                    } else if ((pSet[charCur]&CodeC)!=0)
                    {
                        /* Change to C */
                        ASCIIZ128(&pOutPos,characterSetCur,aCodeC,'\0');
                        --emptyColumns;
                        characterSetCur=CodeC;
                    }
                }
                if ((pSet[charCur]&CodeA)!=0)
                {
                    /* >> Shift it and put out the shifted character */
                    ASCIIZ128(&pOutPos,characterSetCur,aShift,'\0');
                    emptyColumns-=2;
                    characterSetCur=(characterSetCur==CodeB)?CodeA:CodeB;
                    ASCIIZ128(&pOutPos,characterSetCur,data[charCur],'\0');
                    characterSetCur=(characterSetCur==CodeB)?CodeA:CodeB;
                }else{
                    /* Normal Character */
                    if (characterSetCur==CodeC)
                    {
                        if (data[charCur]==aFNC1)
                            A2C128_C(&pOutPos,aFNC1,'\0');
                        else
                        {
                            A2C128_C(&pOutPos,data[charCur],data[charCur+1]);
                            ++charCur;
                            /* We need this here to get the good index */
                            /* for the termination flags in Set. */
                        }
                    }else
                        ASCIIZ128(&pOutPos,characterSetCur,data[charCur],'\0');
                    --emptyColumns;
                }
                /* >> End Criteria */
                if ((pSet[charCur] & CFill)!=0)
                {
                    /* Fill Line but leave space for checks in last line */
                    if(rowCur==rows-1 && emptyColumns>=2)
                        emptyColumns-=2;
                    while(emptyColumns>0)
                    {
                        switch(characterSetCur){
                        case CodeC:
                            A2C128_C(&pOutPos,aCodeB,'\0');
                            characterSetCur=CodeB;
                            break;
                        case CodeB:
                            A2C128_B(&pOutPos,aCodeC);
                            characterSetCur=CodeC;
                            break;
                        case CodeA:
                            A2C128_A(&pOutPos,aCodeC);
                            characterSetCur=CodeC;
                            break;
                        }
                        --emptyColumns;
                    }
                }
                if ((pSet[charCur] & CEnd)!=0)
                    emptyColumns=0;
                ++charCur;
            } /* Loop over characters */
        } /* if filling-Line / normal */

        /* Add checksum in last line */
        if(rows>1 && rowCur==rows-1)
        {
            SumASCII(&pOutPos,Sum1,characterSetCur);
            SumASCII(&pOutPos,Sum2,characterSetCur);
        }
        /* Add Code 128 checksum */
        {
            int Sum=0;
            int Pos=0;
            for ( ; Pos < useColumns+3 ; Pos++)
            {
                Sum = (Sum +
                    ((Pos==0?1:Pos) * pOutput[columns*rowCur+Pos]) % 103
                    ) % 103;
            }
            *pOutPos=(uchar)Sum;
            pOutPos++;
        }
        /* Add end character */
        *pOutPos=106;
        pOutPos++;
    } /* End Lineloop */

    #ifdef _DEBUG
        /* Dump the output to the screen
         */
        printf("\nCode 128 Code Numbers:\n");
        {   /* start a new level of local variables */
            int DPos, DPos2;
            for (DPos=0 ; DPos< rows ; DPos++)
            {
                for (DPos2=0 ; DPos2 < columns ; DPos2++)
                {
                    printf("%3d ",(int)(pOutput[DPos*columns+DPos2]));
                }
                printf("\n");
            }
        }
        printf("rows=%i columns=%i fillings=%i\n", rows, columns, fillings);
    #endif

    /* Paint the C128 patterns */
    for (r = 0; r < rows; r++) {
        strcpy(dest, "");
        for(c = 0; c < columns; c++) {
            strcat(dest, C128Table[pOutput[r * columns + c]]);
        }
        expand(symbol, dest);
        symbol->row_height[r] = 10;
    }
    
    if (!(symbol->output_options & BARCODE_BIND)) {
        symbol->output_options += BARCODE_BIND;
    }
        
    if (symbol->border_width < 2) {
        symbol->border_width = 2;
    }
    return 0;
}

Changes to jni/zint/backend/code.c.

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
...
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
...
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
...
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
...
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
...
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
...
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
...
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
...
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584

    unsigned int i;
    int h, c_digit, c_weight, c_count, k_digit, k_weight, k_count;
    int weight[128], error_number;
    char dest[1024]; /* 6 +  121 * 6 + 2 * 6 + 5 + 1 ~ 1024*/
    char checkstr[3];

    error_number = 0;

    if (length > 121) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(SODIUM, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }
    c_weight = 1;
    c_count = 0;
    k_weight = 1;
    k_count = 0;

................................................................................

    ustrcpy(symbol->text, source);
    strcat((char*) symbol->text, checkstr);
    return error_number;
}

/* Code 39 */
int c39(struct zint_symbol *symbol, unsigned char source[], int length) {
    unsigned int i;
    unsigned int counter;
    char check_digit;
    int error_number;
    char dest[775];
    char localstr[2] = {0};

    error_number = 0;
    counter = 0;

    if ((symbol->option_2 < 0) || (symbol->option_2 > 1)) {
        symbol->option_2 = 0;
    }

    if ((symbol->symbology == BARCODE_LOGMARS) && (length > 59)) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    } else if (length > 74) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    to_upper(source);
    error_number = is_sane(SILVER, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }

    /* Start character */
    strcpy(dest, "1211212111");

    for (i = 0; i < (unsigned int) length; i++) {
................................................................................
    }

    /* Stop character */
    strcat(dest, "121121211");

    if ((symbol->symbology == BARCODE_LOGMARS) || (symbol->symbology == BARCODE_HIBC_39)) {
        /* LOGMARS uses wider 'wide' bars than normal Code 39 */
        counter = strlen(dest);
        for (i = 0; i < counter; i++) {
            if (dest[i] == '2') {
                dest[i] = '3';
            }
        }
    }

................................................................................
/* Pharmazentral Nummer (PZN) */
int pharmazentral(struct zint_symbol *symbol, unsigned char source[], int length) {

    int i, error_number, zeroes;
    unsigned int count, check_digit;
    char localstr[10];

    error_number = 0;

    count = 0;
    if (length > 6) {
        strcpy(symbol->errtxt, "Input wrong length");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }

    localstr[0] = '-';
    zeroes = 6 - length + 1;
    for (i = 1; i < zeroes; i++)
        localstr[i] = '0';
................................................................................
    check_digit = count % 11;
    if (check_digit == 11) {
        check_digit = 0;
    }
    localstr[7] = itoc(check_digit);
    localstr[8] = '\0';
    if (localstr[7] == 'A') {
        strcpy(symbol->errtxt, "Invalid PZN Data");
        return ZINT_ERROR_INVALID_DATA;
    }
    error_number = c39(symbol, (unsigned char *) localstr, strlen(localstr));
    ustrcpy(symbol->text, (unsigned char *) "PZN");
    strcat((char*) symbol->text, localstr);
    return error_number;
}
................................................................................
/* Extended Code 39 - ISO/IEC 16388:2007 Annex A */
int ec39(struct zint_symbol *symbol, unsigned char source[], int length) {

    unsigned char buffer[150] = {0};
    unsigned int i;
    int error_number;

    error_number = 0;

    if (length > 74) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    /* Creates a buffer string and places control characters into it */
    for (i = 0; i < (unsigned int) length; i++) {
        if (source[i] > 127) {
            /* Cannot encode extended ASCII */
            strcpy(symbol->errtxt, "Invalid characters in input data");
            return ZINT_ERROR_INVALID_DATA;
        }
        strcat((char*) buffer, EC39Ctrl[source[i]]);
    }

    /* Then sends the buffer to the C39 function */
    error_number = c39(symbol, buffer, ustrlen(buffer));
................................................................................
    char dest[670];
    char set_copy[] = SILVER;

    error_number = 0;
    strcpy(buffer, "");

    if (length > 107) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    /* Message Content */
    for (i = 0; i < length; i++) {
        if (source[i] > 127) {
            /* Cannot encode extended ASCII */
            strcpy(symbol->errtxt, "Invalid characters in input data");
            return ZINT_ERROR_INVALID_DATA;
        }
        strcat(buffer, C93Ctrl[source[i]]);
        symbol->text[i] = source[i] ? source[i] : ' ';
    }

    /* Now we can check the true length of the barcode */
    h = strlen(buffer);
    if (h > 107) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    for (i = 0; i < h; i++) {
        values[i] = posn(SILVER, buffer[i]);
    }

................................................................................
    int channels, i;
    int error_number = 0, range = 0, zeroes;
    char hrt[9];

    target_value = 0;

    if (length > 7) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }

    if ((symbol->option_2 < 3) || (symbol->option_2 > 8)) {
        channels = 0;
    } else {
        channels = symbol->option_2;
................................................................................
            break;
        case 8: if (target_value > 7742862) {
                range = 1;
            }
            break;
    }
    if (range) {
        strcpy(symbol->errtxt, "Value out of range");
        return ZINT_ERROR_INVALID_DATA;
    }

    for (i = 0; i < 11; i++) {
        B[i] = 0;
        S[i] = 0;
    }







<
<

|




|







 







|







<







|


|





|







 







|







 







<
<


|




|







 







|







 







<
<

|







|







 







|







|







|

|







 







|




|







 







|







108
109
110
111
112
113
114


115
116
117
118
119
120
121
122
123
124
125
126
127
128
...
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
...
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
...
291
292
293
294
295
296
297


298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
...
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
...
335
336
337
338
339
340
341


342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
...
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
...
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
...
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577

    unsigned int i;
    int h, c_digit, c_weight, c_count, k_digit, k_weight, k_count;
    int weight[128], error_number;
    char dest[1024]; /* 6 +  121 * 6 + 2 * 6 + 5 + 1 ~ 1024*/
    char checkstr[3];



    if (length > 121) {
        strcpy(symbol->errtxt, "Input too long (C20)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(SODIUM, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C21)");
        return error_number;
    }
    c_weight = 1;
    c_count = 0;
    k_weight = 1;
    k_count = 0;

................................................................................

    ustrcpy(symbol->text, source);
    strcat((char*) symbol->text, checkstr);
    return error_number;
}

/* Code 39 */
int c39(struct zint_symbol *symbol, unsigned char source[], const size_t length) {
    unsigned int i;
    unsigned int counter;
    char check_digit;
    int error_number;
    char dest[775];
    char localstr[2] = {0};


    counter = 0;

    if ((symbol->option_2 < 0) || (symbol->option_2 > 1)) {
        symbol->option_2 = 0;
    }

    if ((symbol->symbology == BARCODE_LOGMARS) && (length > 59)) {
        strcpy(symbol->errtxt, "Input too long (C22)");
        return ZINT_ERROR_TOO_LONG;
    } else if (length > 74) {
        strcpy(symbol->errtxt, "Input too long (C23)");
        return ZINT_ERROR_TOO_LONG;
    }
    to_upper(source);
    error_number = is_sane(SILVER, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C24)");
        return error_number;
    }

    /* Start character */
    strcpy(dest, "1211212111");

    for (i = 0; i < (unsigned int) length; i++) {
................................................................................
    }

    /* Stop character */
    strcat(dest, "121121211");

    if ((symbol->symbology == BARCODE_LOGMARS) || (symbol->symbology == BARCODE_HIBC_39)) {
        /* LOGMARS uses wider 'wide' bars than normal Code 39 */
        counter = (unsigned int) strlen(dest);
        for (i = 0; i < counter; i++) {
            if (dest[i] == '2') {
                dest[i] = '3';
            }
        }
    }

................................................................................
/* Pharmazentral Nummer (PZN) */
int pharmazentral(struct zint_symbol *symbol, unsigned char source[], int length) {

    int i, error_number, zeroes;
    unsigned int count, check_digit;
    char localstr[10];



    count = 0;
    if (length > 6) {
        strcpy(symbol->errtxt, "Input wrong length (C25)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C26)");
        return error_number;
    }

    localstr[0] = '-';
    zeroes = 6 - length + 1;
    for (i = 1; i < zeroes; i++)
        localstr[i] = '0';
................................................................................
    check_digit = count % 11;
    if (check_digit == 11) {
        check_digit = 0;
    }
    localstr[7] = itoc(check_digit);
    localstr[8] = '\0';
    if (localstr[7] == 'A') {
        strcpy(symbol->errtxt, "Invalid PZN Data (C27)");
        return ZINT_ERROR_INVALID_DATA;
    }
    error_number = c39(symbol, (unsigned char *) localstr, strlen(localstr));
    ustrcpy(symbol->text, (unsigned char *) "PZN");
    strcat((char*) symbol->text, localstr);
    return error_number;
}
................................................................................
/* Extended Code 39 - ISO/IEC 16388:2007 Annex A */
int ec39(struct zint_symbol *symbol, unsigned char source[], int length) {

    unsigned char buffer[150] = {0};
    unsigned int i;
    int error_number;



    if (length > 74) {
        strcpy(symbol->errtxt, "Input too long (C28)");
        return ZINT_ERROR_TOO_LONG;
    }

    /* Creates a buffer string and places control characters into it */
    for (i = 0; i < (unsigned int) length; i++) {
        if (source[i] > 127) {
            /* Cannot encode extended ASCII */
            strcpy(symbol->errtxt, "Invalid characters in input data (C29)");
            return ZINT_ERROR_INVALID_DATA;
        }
        strcat((char*) buffer, EC39Ctrl[source[i]]);
    }

    /* Then sends the buffer to the C39 function */
    error_number = c39(symbol, buffer, ustrlen(buffer));
................................................................................
    char dest[670];
    char set_copy[] = SILVER;

    error_number = 0;
    strcpy(buffer, "");

    if (length > 107) {
        strcpy(symbol->errtxt, "Input too long (C2A)");
        return ZINT_ERROR_TOO_LONG;
    }

    /* Message Content */
    for (i = 0; i < length; i++) {
        if (source[i] > 127) {
            /* Cannot encode extended ASCII */
            strcpy(symbol->errtxt, "Invalid characters in input data (C2B)");
            return ZINT_ERROR_INVALID_DATA;
        }
        strcat(buffer, C93Ctrl[source[i]]);
        symbol->text[i] = source[i] ? source[i] : ' ';
    }

    /* Now we can check the true length of the barcode */
    h = (int) strlen(buffer);
    if (h > 107) {
        strcpy(symbol->errtxt, "Input too long (C2C)");
        return ZINT_ERROR_TOO_LONG;
    }

    for (i = 0; i < h; i++) {
        values[i] = posn(SILVER, buffer[i]);
    }

................................................................................
    int channels, i;
    int error_number = 0, range = 0, zeroes;
    char hrt[9];

    target_value = 0;

    if (length > 7) {
        strcpy(symbol->errtxt, "Input too long (C2D)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C2E)");
        return error_number;
    }

    if ((symbol->option_2 < 3) || (symbol->option_2 > 8)) {
        channels = 0;
    } else {
        channels = symbol->option_2;
................................................................................
            break;
        case 8: if (target_value > 7742862) {
                range = 1;
            }
            break;
    }
    if (range) {
        strcpy(symbol->errtxt, "Value out of range (C2F)");
        return ZINT_ERROR_INVALID_DATA;
    }

    for (i = 0; i < 11; i++) {
        B[i] = 0;
        S[i] = 0;
    }

Changes to jni/zint/backend/code1.c.

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
...
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
...
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930

931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959

960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988

989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
....
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
....
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
....
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193

1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222

1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251

1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
....
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
....
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
....
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
#include "common.h"
#include "code1.h"
#include "reedsol.h"
#include "large.h"
#include <stdio.h>
#include <string.h>
#include <math.h>
#ifdef __APPLE__
#include <sys/malloc.h>
#else
#include <malloc.h>
#endif

void horiz(struct zint_symbol *symbol, int row_no, int full) {
    int i;

    if (full) {
        for (i = 0; i < symbol->width; i++) {
            set_module(symbol, row_no, i);
................................................................................
    if (source[position + i - 1] == '>') {
        return 1;
    }

    return 0;
}

int c1_look_ahead_test(unsigned char source[], int sourcelen, int position, int current_mode, int gs1) {
    float ascii_count, c40_count, text_count, edi_count, byte_count;
    char reduced_char;
    int done, best_scheme, best_count, sp;

    /* Step J */
    if (current_mode == C1_ASCII) {
        ascii_count = 0.0;
................................................................................
            if (data_left >= 3) {
                if ((decimal_count == 2) && ((source[sp + 2] >= '0') && (source[sp + 2] <= '9'))) {
                    decimal_count = 3;
                }
            }

            if (decimal_count != 3) {
                int bits_left_in_byte, target_count;
                int sub_target;
                /* Finish Decimal mode and go back to ASCII */

                strcat(decimal_binary, "111111"); /* Unlatch */

                target_count = 3;
                if (strlen(decimal_binary) <= 16) {
................................................................................
                    strcat(decimal_binary, "01");
                }

                if ((bits_left_in_byte == 4) || (bits_left_in_byte == 6)) {
                    if (decimal_count >= 1) {
                        int sub_value = ctoi(source[sp]) + 1;

                        if (sub_value & 0x08) {
                            strcat(decimal_binary, "1");
                        } else {
                            strcat(decimal_binary, "0");
                        }
                        if (sub_value & 0x04) {
                            strcat(decimal_binary, "1");
                        } else {
                            strcat(decimal_binary, "0");
                        }
                        if (sub_value & 0x02) {
                            strcat(decimal_binary, "1");
                        } else {
                            strcat(decimal_binary, "0");
                        }
                        if (sub_value & 0x01) {
                            strcat(decimal_binary, "1");
                        } else {
                            strcat(decimal_binary, "0");
                        }
                        sp++;
                    } else {
                        strcat(decimal_binary, "1111");
                    }
                }

                if (bits_left_in_byte == 6) {
                    strcat(decimal_binary, "01");
                }

                /* Binary buffer is full - transfer to target */
                if (target_count >= 1) {
                    sub_target = 0;
                    if (decimal_binary[0] == '1') {
                        sub_target += 128;
                    }

                    if (decimal_binary[1] == '1') {
                        sub_target += 64;
                    }
                    if (decimal_binary[2] == '1') {
                        sub_target += 32;
                    }
                    if (decimal_binary[3] == '1') {
                        sub_target += 16;
                    }
                    if (decimal_binary[4] == '1') {
                        sub_target += 8;
                    }
                    if (decimal_binary[5] == '1') {
                        sub_target += 4;
                    }
                    if (decimal_binary[6] == '1') {
                        sub_target += 2;
                    }
                    if (decimal_binary[7] == '1') {
                        sub_target += 1;
                    }
                    target[tp] = sub_target;
                    tp++;
                }
                if (target_count >= 2) {
                    sub_target = 0;
                    if (decimal_binary[8] == '1') {
                        sub_target += 128;
                    }

                    if (decimal_binary[9] == '1') {
                        sub_target += 64;
                    }
                    if (decimal_binary[10] == '1') {
                        sub_target += 32;
                    }
                    if (decimal_binary[11] == '1') {
                        sub_target += 16;
                    }
                    if (decimal_binary[12] == '1') {
                        sub_target += 8;
                    }
                    if (decimal_binary[13] == '1') {
                        sub_target += 4;
                    }
                    if (decimal_binary[14] == '1') {
                        sub_target += 2;
                    }
                    if (decimal_binary[15] == '1') {
                        sub_target += 1;
                    }
                    target[tp] = sub_target;
                    tp++;
                }
                if (target_count == 3) {
                    sub_target = 0;
                    if (decimal_binary[16] == '1') {
                        sub_target += 128;
                    }

                    if (decimal_binary[17] == '1') {
                        sub_target += 64;
                    }
                    if (decimal_binary[18] == '1') {
                        sub_target += 32;
                    }
                    if (decimal_binary[19] == '1') {
                        sub_target += 16;
                    }
                    if (decimal_binary[20] == '1') {
                        sub_target += 8;
                    }
                    if (decimal_binary[21] == '1') {
                        sub_target += 4;
                    }
                    if (decimal_binary[22] == '1') {
                        sub_target += 2;
                    }
                    if (decimal_binary[23] == '1') {
                        sub_target += 1;
                    }
                    target[tp] = sub_target;
                    tp++;
                }

                next_mode = C1_ASCII;
            } else {
................................................................................
                tp++;
                sp++;
            }
        }

        if (tp > 1480) {
            /* Data is too large for symbol */
            strcpy(symbol->errtxt, "Input data too long");
            return 0;
        }
    } while (sp < length);

    /* Empty buffers */
    if (c40_p == 2) {
        int iv;
................................................................................
        target[tp] = iv % 256;
        tp++;
        target[tp] = 255;
        tp++; /* Unlatch */
    }

    if (current_mode == C1_DECIMAL) {
        int bits_left_in_byte, target_count;
        int sub_target;
        /* Finish Decimal mode and go back to ASCII */

        strcat(decimal_binary, "111111"); /* Unlatch */

        target_count = 3;
        if (strlen(decimal_binary) <= 16) {
................................................................................
        if (bits_left_in_byte == 6) {
            strcat(decimal_binary, "01");
        }

        /* Binary buffer is full - transfer to target */
        if (target_count >= 1) {
            sub_target = 0;
            if (decimal_binary[0] == '1') {
                sub_target += 128;
            }

            if (decimal_binary[1] == '1') {
                sub_target += 64;
            }
            if (decimal_binary[2] == '1') {
                sub_target += 32;
            }
            if (decimal_binary[3] == '1') {
                sub_target += 16;
            }
            if (decimal_binary[4] == '1') {
                sub_target += 8;
            }
            if (decimal_binary[5] == '1') {
                sub_target += 4;
            }
            if (decimal_binary[6] == '1') {
                sub_target += 2;
            }
            if (decimal_binary[7] == '1') {
                sub_target += 1;
            }
            target[tp] = sub_target;
            tp++;
        }
        if (target_count >= 2) {
            sub_target = 0;
            if (decimal_binary[8] == '1') {
                sub_target += 128;
            }

            if (decimal_binary[9] == '1') {
                sub_target += 64;
            }
            if (decimal_binary[10] == '1') {
                sub_target += 32;
            }
            if (decimal_binary[11] == '1') {
                sub_target += 16;
            }
            if (decimal_binary[12] == '1') {
                sub_target += 8;
            }
            if (decimal_binary[13] == '1') {
                sub_target += 4;
            }
            if (decimal_binary[14] == '1') {
                sub_target += 2;
            }
            if (decimal_binary[15] == '1') {
                sub_target += 1;
            }
            target[tp] = sub_target;
            tp++;
        }
        if (target_count == 3) {
            sub_target = 0;
            if (decimal_binary[16] == '1') {
                sub_target += 128;
            }

            if (decimal_binary[17] == '1') {
                sub_target += 64;
            }
            if (decimal_binary[18] == '1') {
                sub_target += 32;
            }
            if (decimal_binary[19] == '1') {
                sub_target += 16;
            }
            if (decimal_binary[20] == '1') {
                sub_target += 8;
            }
            if (decimal_binary[21] == '1') {
                sub_target += 4;
            }
            if (decimal_binary[22] == '1') {
                sub_target += 2;
            }
            if (decimal_binary[23] == '1') {
                sub_target += 1;
            }
            target[tp] = sub_target;
            tp++;
        }
    }

    if (current_mode == C1_BYTE) {
................................................................................
            tp += 2;
        }
    }

    /* Re-check length of data */
    if (tp > 1480) {
        /* Data is too large for symbol */
        strcpy(symbol->errtxt, "Input data too long");
        return 0;
    }
    /* 
    printf("targets:\n");
    for(i = 0; i < tp; i++) {
            printf("[%d]", target[i]);
    }
................................................................................
    int size = 1, i, j, data_blocks;

    char datagrid[136][120];
    int row, col;
    int sub_version = 0;

    if ((symbol->option_2 < 0) || (symbol->option_2 > 10)) {
        strcpy(symbol->errtxt, "Invalid symbol size");
        return ZINT_ERROR_INVALID_OPTION;
    }

    if (symbol->option_2 == 9) {
        /* Version S */
        int codewords;
        short int elreg[112];
        unsigned int data[15], ecc[15];
        int stream[30];
        int block_width;

        if (length > 18) {
            strcpy(symbol->errtxt, "Input data too long");
            return ZINT_ERROR_TOO_LONG;
        }
        if (is_sane(NEON, source, length) == ZINT_ERROR_INVALID_DATA) {
            strcpy(symbol->errtxt, "Invalid input data (Version S encodes numeric input only)");
            return ZINT_ERROR_INVALID_DATA;
        }

        sub_version = 3;
        codewords = 12;
        block_width = 6; /* Version S-30 */
        if (length <= 12) {
................................................................................
        data_length = c1_encode(symbol, source, data, length);

        if (data_length == 0) {
            return ZINT_ERROR_TOO_LONG;
        }

        if (data_length > 38) {
            strcpy(symbol->errtxt, "Input data too long");
            return ZINT_ERROR_TOO_LONG;
        }

        size = 10;
        sub_version = 3;
        data_cw = 38;
        ecc_cw = 22;







<
<
<
<
<







 







|







 







|







 







|
<
<
<
<
|
|
|
|
|
<
<
<
<

<
<
<
<
|













<
<
|
>
|
<
<
<
<
<
<
|
|
<
<

<
<
<
<
<
<
<
<
<





<
<
|
>
|
<
<
<
<
<
<
|
|
<
<

<
<
<
<
<
<
<
<
<





<
<
|
>
|
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<







 







|







 







|







 







<
<
|
>
|
<
<
<
<
<
<
|
|
<
<

<
<
<
<
<
<
<
<
<





<
<
|
>
|
<
<
<
<
<
<
|
|
<
<

<
<
<
<
<
<
<
<
<





<
<
|
>
|
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<







 







|







 







|












|



|







 







|







33
34
35
36
37
38
39





40
41
42
43
44
45
46
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
...
883
884
885
886
887
888
889
890




891
892
893
894
895




896




897
898
899
900
901
902
903
904
905
906
907
908
909
910


911
912
913






914
915


916









917
918
919
920
921


922
923
924






925
926


927









928
929
930
931
932


933
934
935






936
937











938
939
940
941
942
943
944
....
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
....
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
....
1113
1114
1115
1116
1117
1118
1119


1120
1121
1122






1123
1124


1125









1126
1127
1128
1129
1130


1131
1132
1133






1134
1135


1136









1137
1138
1139
1140
1141


1142
1143
1144






1145
1146











1147
1148
1149
1150
1151
1152
1153
....
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
....
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
....
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
#include "common.h"
#include "code1.h"
#include "reedsol.h"
#include "large.h"
#include <stdio.h>
#include <string.h>
#include <math.h>






void horiz(struct zint_symbol *symbol, int row_no, int full) {
    int i;

    if (full) {
        for (i = 0; i < symbol->width; i++) {
            set_module(symbol, row_no, i);
................................................................................
    if (source[position + i - 1] == '>') {
        return 1;
    }

    return 0;
}

static int c1_look_ahead_test(unsigned char source[], int sourcelen, int position, int current_mode, int gs1) {
    float ascii_count, c40_count, text_count, edi_count, byte_count;
    char reduced_char;
    int done, best_scheme, best_count, sp;

    /* Step J */
    if (current_mode == C1_ASCII) {
        ascii_count = 0.0;
................................................................................
            if (data_left >= 3) {
                if ((decimal_count == 2) && ((source[sp + 2] >= '0') && (source[sp + 2] <= '9'))) {
                    decimal_count = 3;
                }
            }

            if (decimal_count != 3) {
                size_t bits_left_in_byte, target_count;
                int sub_target;
                /* Finish Decimal mode and go back to ASCII */

                strcat(decimal_binary, "111111"); /* Unlatch */

                target_count = 3;
                if (strlen(decimal_binary) <= 16) {
................................................................................
                    strcat(decimal_binary, "01");
                }

                if ((bits_left_in_byte == 4) || (bits_left_in_byte == 6)) {
                    if (decimal_count >= 1) {
                        int sub_value = ctoi(source[sp]) + 1;

                        for (i = 0x08; i > 0; i = i >> 1) {




                            if (sub_value & i) {
                                strcat(decimal_binary, "1");
                            } else {
                                strcat(decimal_binary, "0");
                            }




                        }




                        
                        sp++;
                    } else {
                        strcat(decimal_binary, "1111");
                    }
                }

                if (bits_left_in_byte == 6) {
                    strcat(decimal_binary, "01");
                }

                /* Binary buffer is full - transfer to target */
                if (target_count >= 1) {
                    sub_target = 0;


                    
                    for (i = 0; i < 8; i++) {
                        if (decimal_binary[i] == '1') {






                            sub_target += 128 >> i;
                        }


                    }









                    target[tp] = sub_target;
                    tp++;
                }
                if (target_count >= 2) {
                    sub_target = 0;


                    
                    for (i = 0; i < 8; i++) {
                        if (decimal_binary[i + 8] == '1') {






                            sub_target += 128 >> i;
                        }


                    }









                    target[tp] = sub_target;
                    tp++;
                }
                if (target_count == 3) {
                    sub_target = 0;


                    
                    for (i = 0; i < 8; i++) {
                        if (decimal_binary[i + 16] == '1') {






                            sub_target += 128 >> i;
                        }











                    }
                    target[tp] = sub_target;
                    tp++;
                }

                next_mode = C1_ASCII;
            } else {
................................................................................
                tp++;
                sp++;
            }
        }

        if (tp > 1480) {
            /* Data is too large for symbol */
            strcpy(symbol->errtxt, "Input data too long (E10)");
            return 0;
        }
    } while (sp < length);

    /* Empty buffers */
    if (c40_p == 2) {
        int iv;
................................................................................
        target[tp] = iv % 256;
        tp++;
        target[tp] = 255;
        tp++; /* Unlatch */
    }

    if (current_mode == C1_DECIMAL) {
        size_t bits_left_in_byte, target_count;
        int sub_target;
        /* Finish Decimal mode and go back to ASCII */

        strcat(decimal_binary, "111111"); /* Unlatch */

        target_count = 3;
        if (strlen(decimal_binary) <= 16) {
................................................................................
        if (bits_left_in_byte == 6) {
            strcat(decimal_binary, "01");
        }

        /* Binary buffer is full - transfer to target */
        if (target_count >= 1) {
            sub_target = 0;


            
            for (i = 0; i < 8; i++) {
                if (decimal_binary[i] == '1') {






                    sub_target += 128 >> i;
                }


            }









            target[tp] = sub_target;
            tp++;
        }
        if (target_count >= 2) {
            sub_target = 0;


            
            for (i = 0; i < 8; i++) {
                if (decimal_binary[i + 8] == '1') {






                    sub_target += 128 >> i;
                }


            }









            target[tp] = sub_target;
            tp++;
        }
        if (target_count == 3) {
            sub_target = 0;


            
            for (i = 0; i < 8; i++) {
                if (decimal_binary[i + 16] == '1') {






                    sub_target += 128 >> i;
                }











            }
            target[tp] = sub_target;
            tp++;
        }
    }

    if (current_mode == C1_BYTE) {
................................................................................
            tp += 2;
        }
    }

    /* Re-check length of data */
    if (tp > 1480) {
        /* Data is too large for symbol */
        strcpy(symbol->errtxt, "Input data too long (E11)");
        return 0;
    }
    /* 
    printf("targets:\n");
    for(i = 0; i < tp; i++) {
            printf("[%d]", target[i]);
    }
................................................................................
    int size = 1, i, j, data_blocks;

    char datagrid[136][120];
    int row, col;
    int sub_version = 0;

    if ((symbol->option_2 < 0) || (symbol->option_2 > 10)) {
        strcpy(symbol->errtxt, "Invalid symbol size (E12)");
        return ZINT_ERROR_INVALID_OPTION;
    }

    if (symbol->option_2 == 9) {
        /* Version S */
        int codewords;
        short int elreg[112];
        unsigned int data[15], ecc[15];
        int stream[30];
        int block_width;

        if (length > 18) {
            strcpy(symbol->errtxt, "Input data too long (E13)");
            return ZINT_ERROR_TOO_LONG;
        }
        if (is_sane(NEON, source, length) == ZINT_ERROR_INVALID_DATA) {
            strcpy(symbol->errtxt, "Invalid input data (Version S encodes numeric input only) (E14)");
            return ZINT_ERROR_INVALID_DATA;
        }

        sub_version = 3;
        codewords = 12;
        block_width = 6; /* Version S-30 */
        if (length <= 12) {
................................................................................
        data_length = c1_encode(symbol, source, data, length);

        if (data_length == 0) {
            return ZINT_ERROR_TOO_LONG;
        }

        if (data_length > 38) {
            strcpy(symbol->errtxt, "Input data too long (E15)");
            return ZINT_ERROR_TOO_LONG;
        }

        size = 10;
        sub_version = 3;
        data_cw = 38;
        ecc_cw = 22;

Changes to jni/zint/backend/code128.c.

306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
...
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
...
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
...
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
...
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
....
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
....
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
    j = 0;
    bar_characters = 0;
    f_state = 0;

    if (sourcelen > 160) {
        /* This only blocks rediculously long input - the actual length of the
           resulting barcode depends on the type of data, so this is trapped later */
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    /* Detect extended ASCII characters */
    for (i = 0; i < sourcelen; i++) {
        if (source[i] >= 128)
            fset[i] = 'f';
................................................................................

        if (set[i] == 'C') {
            glyph_count = glyph_count + 0.5;
        } else {
            glyph_count = glyph_count + 1.0;
        }
    }
    if (glyph_count > 80.0) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    /* So now we know what start character to use - we can get on with it! */
    if (symbol->output_options & READER_INIT) {
        /* Reader Initialisation mode */
        switch (set[0]) {
................................................................................
    /* Stop character */
    strcat(dest, C128Table[106]);
    expand(symbol, dest);
    return error_number;
}

/* Handle EAN-128 (Now known as GS1-128) */
int ean_128(struct zint_symbol *symbol, unsigned char source[], int length) {
    int i, j, values[170], bar_characters, read, total_sum;
    int error_number, indexchaine, indexliste;
    char set[170], mode, last_set;
    float glyph_count;
    char dest[1000];
    int separator_row, linkage_flag, c_count;
#ifndef _MSC_VER
................................................................................

    memset(values, 0, sizeof (values));
    memset(set, ' ', sizeof (set));

    if (length > 160) {
        /* This only blocks rediculously long input - the actual length of the
        resulting barcode depends on the type of data, so this is trapped later */
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    for (i = 0; i < length; i++) {
        if (source[i] == '\0') {
            /* Null characters not allowed! */
            strcpy(symbol->errtxt, "NULL character in input data");
            return ZINT_ERROR_INVALID_DATA;
        }
    }

    /* if part of a composite symbol make room for the separator pattern */
    if (symbol->symbology == BARCODE_EAN128_CC) {
        separator_row = symbol->rows;
................................................................................

        if ((set[i] == 'C') && (reduced[i] != '[')) {
            glyph_count = glyph_count + 0.5;
        } else {
            glyph_count = glyph_count + 1.0;
        }
    }
    if (glyph_count > 80.0) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    /* So now we know what start character to use - we can get on with it! */
    switch (set[0]) {
        case 'A': /* Start A */
            strcat(dest, C128Table[103]);
................................................................................
    int error_number, zeroes, i, nve_check, total_sum, sourcelen;
    unsigned char ean128_equiv[25];

    memset(ean128_equiv, 0, 25);
    sourcelen = length;

    if (sourcelen > 17) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }
    zeroes = 17 - sourcelen;
    strcpy((char *) ean128_equiv, "[00]");
    memset(ean128_equiv + 4, '0', zeroes);
    strcpy((char*) ean128_equiv + 4 + zeroes, (char*) source);

................................................................................
/* EAN-14 - A version of EAN-128 */
int ean_14(struct zint_symbol *symbol, unsigned char source[], int length) {
    int i, count, check_digit;
    int error_number, zeroes;
    unsigned char ean128_equiv[20];

    if (length > 13) {
        strcpy(symbol->errtxt, "Input wrong length");
        return ZINT_ERROR_TOO_LONG;
    }

    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid character in data");
        return error_number;
    }

    zeroes = 13 - length;
    strcpy((char*) ean128_equiv, "[01]");
    memset(ean128_equiv + 4, '0', zeroes);
    ustrcpy(ean128_equiv + 4 + zeroes, source);







|







 







|
|







 







|







 







|





|







 







|
|







 







|





|







 







|





|







306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
...
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
...
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
...
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
...
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
....
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
....
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
    j = 0;
    bar_characters = 0;
    f_state = 0;

    if (sourcelen > 160) {
        /* This only blocks rediculously long input - the actual length of the
           resulting barcode depends on the type of data, so this is trapped later */
        strcpy(symbol->errtxt, "Input too long (C40)");
        return ZINT_ERROR_TOO_LONG;
    }

    /* Detect extended ASCII characters */
    for (i = 0; i < sourcelen; i++) {
        if (source[i] >= 128)
            fset[i] = 'f';
................................................................................

        if (set[i] == 'C') {
            glyph_count = glyph_count + 0.5;
        } else {
            glyph_count = glyph_count + 1.0;
        }
    }
    if (glyph_count > 60.0) {
        strcpy(symbol->errtxt, "Input too long (C41)");
        return ZINT_ERROR_TOO_LONG;
    }

    /* So now we know what start character to use - we can get on with it! */
    if (symbol->output_options & READER_INIT) {
        /* Reader Initialisation mode */
        switch (set[0]) {
................................................................................
    /* Stop character */
    strcat(dest, C128Table[106]);
    expand(symbol, dest);
    return error_number;
}

/* Handle EAN-128 (Now known as GS1-128) */
int ean_128(struct zint_symbol *symbol, unsigned char source[], const size_t length) {
    int i, j, values[170], bar_characters, read, total_sum;
    int error_number, indexchaine, indexliste;
    char set[170], mode, last_set;
    float glyph_count;
    char dest[1000];
    int separator_row, linkage_flag, c_count;
#ifndef _MSC_VER
................................................................................

    memset(values, 0, sizeof (values));
    memset(set, ' ', sizeof (set));

    if (length > 160) {
        /* This only blocks rediculously long input - the actual length of the
        resulting barcode depends on the type of data, so this is trapped later */
        strcpy(symbol->errtxt, "Input too long (C42)");
        return ZINT_ERROR_TOO_LONG;
    }
    for (i = 0; i < length; i++) {
        if (source[i] == '\0') {
            /* Null characters not allowed! */
            strcpy(symbol->errtxt, "NULL character in input data (C43)");
            return ZINT_ERROR_INVALID_DATA;
        }
    }

    /* if part of a composite symbol make room for the separator pattern */
    if (symbol->symbology == BARCODE_EAN128_CC) {
        separator_row = symbol->rows;
................................................................................

        if ((set[i] == 'C') && (reduced[i] != '[')) {
            glyph_count = glyph_count + 0.5;
        } else {
            glyph_count = glyph_count + 1.0;
        }
    }
    if (glyph_count > 60.0) {
        strcpy(symbol->errtxt, "Input too long (C44)");
        return ZINT_ERROR_TOO_LONG;
    }

    /* So now we know what start character to use - we can get on with it! */
    switch (set[0]) {
        case 'A': /* Start A */
            strcat(dest, C128Table[103]);
................................................................................
    int error_number, zeroes, i, nve_check, total_sum, sourcelen;
    unsigned char ean128_equiv[25];

    memset(ean128_equiv, 0, 25);
    sourcelen = length;

    if (sourcelen > 17) {
        strcpy(symbol->errtxt, "Input too long (C45)");
        return ZINT_ERROR_TOO_LONG;
    }

    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C46)");
        return error_number;
    }
    zeroes = 17 - sourcelen;
    strcpy((char *) ean128_equiv, "[00]");
    memset(ean128_equiv + 4, '0', zeroes);
    strcpy((char*) ean128_equiv + 4 + zeroes, (char*) source);

................................................................................
/* EAN-14 - A version of EAN-128 */
int ean_14(struct zint_symbol *symbol, unsigned char source[], int length) {
    int i, count, check_digit;
    int error_number, zeroes;
    unsigned char ean128_equiv[20];

    if (length > 13) {
        strcpy(symbol->errtxt, "Input wrong length (C47)");
        return ZINT_ERROR_TOO_LONG;
    }

    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid character in data (C48)");
        return error_number;
    }

    zeroes = 13 - length;
    strcpy((char*) ean128_equiv, "[01]");
    memset(ean128_equiv + 4, '0', zeroes);
    ustrcpy(ean128_equiv + 4 + zeroes, source);

Changes to jni/zint/backend/code16k.c.

274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
...
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
...
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
    if (symbol->input_mode == GS1_MODE) {
        gs1 = 1;
    } else {
        gs1 = 0;
    }

    if (input_length > 157) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    bar_characters = 0;

    /* Detect extended ASCII characters */
    for (i = 0; i < (unsigned int) input_length; i++) {
................................................................................

    if ((gs1) && (set[0] != 'A')) {
        /* FNC1 can be integrated with mode character */
        glyph_count--;
    }

    if (glyph_count > 77.0) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    /* Calculate how tall the symbol will be */
    glyph_count = glyph_count + 2.0;
    i = glyph_count;
    rows_needed = (i / 5);
................................................................................
    }

    if (symbol->output_options & READER_INIT) {
        if (m == 2) {
            m = 5;
        }
        if (gs1) {
            strcpy(symbol->errtxt, "Cannot use both GS1 mode and Reader Initialisation");
            return ZINT_ERROR_INVALID_OPTION;
        } else {
            if ((set[0] == 'B') && (set[1] == 'C')) {
                m = 6;
            }
        }
        values[bar_characters] = (7 * (rows_needed - 2)) + m; /* see 4.3.4.2 */







|







 







|







 







|







274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
...
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
...
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
    if (symbol->input_mode == GS1_MODE) {
        gs1 = 1;
    } else {
        gs1 = 0;
    }

    if (input_length > 157) {
        strcpy(symbol->errtxt, "Input too long (D20)");
        return ZINT_ERROR_TOO_LONG;
    }

    bar_characters = 0;

    /* Detect extended ASCII characters */
    for (i = 0; i < (unsigned int) input_length; i++) {
................................................................................

    if ((gs1) && (set[0] != 'A')) {
        /* FNC1 can be integrated with mode character */
        glyph_count--;
    }

    if (glyph_count > 77.0) {
        strcpy(symbol->errtxt, "Input too long (D21)");
        return ZINT_ERROR_TOO_LONG;
    }

    /* Calculate how tall the symbol will be */
    glyph_count = glyph_count + 2.0;
    i = glyph_count;
    rows_needed = (i / 5);
................................................................................
    }

    if (symbol->output_options & READER_INIT) {
        if (m == 2) {
            m = 5;
        }
        if (gs1) {
            strcpy(symbol->errtxt, "Cannot use both GS1 mode and Reader Initialisation (D22)");
            return ZINT_ERROR_INVALID_OPTION;
        } else {
            if ((set[0] == 'B') && (set[1] == 'C')) {
                m = 6;
            }
        }
        values[bar_characters] = (7 * (rows_needed - 2)) + m; /* see 4.3.4.2 */

Changes to jni/zint/backend/code49.c.

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
...
204
205
206
207
208
209
210

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
...
325
326
327
328
329
330
331

332

333
334
335
336
    int w_grid[8][4]; /* Refets to table 2 */
    int pad_count = 0;
    char pattern[40];
    int gs1;
    size_t h;

    if (length > 81) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    if (symbol->input_mode == GS1_MODE) {
        gs1 = 1;
        strcpy(intermediate, "*"); /* FNC1 */
    } else {
        gs1 = 0;
    }

    for (i = 0; i < length; i++) {
        if (source[i] > 127) {
            strcpy(symbol->errtxt, "Invalid characters in input data");
            return ZINT_ERROR_INVALID_DATA;
        }
        if (gs1 && (source[i] == '['))
            strcat(intermediate, "*"); /* FNC1 */
        else
            strcat(intermediate, c49_table7[source[i]]);
    }
................................................................................
        case 44: M = 5;
            break;
        default: M = 0;
            break;
    }

    if (M != 0) {

        for (i = 0; i < codeword_count; i++) {
            codewords[i] = codewords[i + 1];
        }
        codeword_count--;
    }

    if (codeword_count > 49) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    /* Place codewords in code character array (c grid) */
    rows = 0;
    do {
        for (i = 0; i < 7; i++) {
................................................................................

        /* Expand into symbol */
        symbol->row_height[i] = 10;
        expand(symbol, pattern);
    }

    symbol->whitespace_width = 10;

    symbol->output_options = BARCODE_BIND;

    symbol->border_width = 2;

    return 0;
}







|











|







 







>



<



|







 







>
|
>




48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
...
204
205
206
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225
...
325
326
327
328
329
330
331
332
333
334
335
336
337
338
    int w_grid[8][4]; /* Refets to table 2 */
    int pad_count = 0;
    char pattern[40];
    int gs1;
    size_t h;

    if (length > 81) {
        strcpy(symbol->errtxt, "Input too long (D30)");
        return ZINT_ERROR_TOO_LONG;
    }
    if (symbol->input_mode == GS1_MODE) {
        gs1 = 1;
        strcpy(intermediate, "*"); /* FNC1 */
    } else {
        gs1 = 0;
    }

    for (i = 0; i < length; i++) {
        if (source[i] > 127) {
            strcpy(symbol->errtxt, "Invalid characters in input data (D31)");
            return ZINT_ERROR_INVALID_DATA;
        }
        if (gs1 && (source[i] == '['))
            strcat(intermediate, "*"); /* FNC1 */
        else
            strcat(intermediate, c49_table7[source[i]]);
    }
................................................................................
        case 44: M = 5;
            break;
        default: M = 0;
            break;
    }

    if (M != 0) {
        codeword_count--;
        for (i = 0; i < codeword_count; i++) {
            codewords[i] = codewords[i + 1];
        }

    }

    if (codeword_count > 49) {
        strcpy(symbol->errtxt, "Input too long (D32)");
        return ZINT_ERROR_TOO_LONG;
    }

    /* Place codewords in code character array (c grid) */
    rows = 0;
    do {
        for (i = 0; i < 7; i++) {
................................................................................

        /* Expand into symbol */
        symbol->row_height[i] = 10;
        expand(symbol, pattern);
    }

    symbol->whitespace_width = 10;
    if (!(symbol->output_options & BARCODE_BIND)) {
        symbol->output_options += BARCODE_BIND;
    }
    symbol->border_width = 2;

    return 0;
}

Changes to jni/zint/backend/common.c.

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
..
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
..
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
...
163
164
165
166
167
168
169


170
171

172
173
174
175


176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198


199
200
201
202
203
204
205
206
207
208
...
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
...
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
...
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
























 */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "common.h"

/* Local replacement for strlen() with unsigned char strings */
int ustrlen(const unsigned char data[]) {
    return strlen((const char*) data);
}

/* Local replacement for strcpy() with unsigned char strings */

void ustrcpy(unsigned char target[], const unsigned char source[]) {
    strcpy((char *) target, (const char*) source);
}

/* Converts a character 0-9 to its equivalent integer value */
int ctoi(const char source) {
    if ((source >= '0') && (source <= '9'))
        return (source - '0');
    return (source - 'A' + 10);
}

................................................................................
    } else {
        return ('A' + (source - 10));
    }
}

/* Converts lower case characters to upper case in a string source[] */
void to_upper(unsigned char source[]) {
    unsigned int i, src_len = ustrlen(source);

    for (i = 0; i < src_len; i++) {
        if ((source[i] >= 'a') && (source[i] <= 'z')) {
            source [i] = (source[i] - 'a') + 'A';
        }
    }
}

/* Verifies that a string only uses valid characters */
int is_sane(char test_string[], const unsigned char source[], const int length) {
    unsigned int i, j, latch;
    unsigned int lt = strlen(test_string);

    for (i = 0; i < length; i++) {
        latch = FALSE;
        for (j = 0; j < lt; j++) {
            if (source[i] == test_string[j]) {
                latch = TRUE;
                break;
................................................................................
        }
    }

    return 0;
}

/* Returns the position of data in set_string */
int posn(char set_string[], const char data) {
    unsigned int i, n = strlen(set_string);

    for (i = 0; i < n; i++) {
        if (data == set_string[i]) {
            return i;
        }
    }
    return 0;
}

/* Replaces huge switch statements for looking up in tables */
void lookup(char set_string[], const char *table[], const char data, char dest[]) {
    unsigned int i, n = strlen(set_string);

    for (i = 0; i < n; i++) {
        if (data == set_string[i]) {
            strcat(dest, table[i]);
        }
    }
}

/* Return true (1) if a module is dark/black, orherwise false (0) */
int module_is_set(const struct zint_symbol *symbol, const int y_coord, const int x_coord) {
    return (symbol->encoded_data[y_coord][x_coord / 7] >> (x_coord % 7)) & 1;
}

/* Set a module to dark/black */
void set_module(struct zint_symbol *symbol, const int y_coord, const int x_coord) {
    symbol->encoded_data[y_coord][x_coord / 7] |= 1 << (x_coord % 7);
................................................................................

/* Set (or unset) a module to white */
void unset_module(struct zint_symbol *symbol, const int y_coord, const int x_coord) {
    symbol->encoded_data[y_coord][x_coord / 7] &= ~(1 << (x_coord % 7));
}

/* Expands from a width pattern to a bit pattern */
void expand(struct zint_symbol *symbol, char data[]) {

    unsigned int reader, n = strlen(data);
    int writer, i;
    char latch;

    writer = 0;
    latch = '1';

    for (reader = 0; reader < n; reader++) {
................................................................................
        }
    }
    symbol->rows = symbol->rows + 1;
}

/* Indicates which symbologies can have row binding */
int is_stackable(const int symbology) {


    if (symbology < BARCODE_PDF417) {
        return 1;

    }
    if (symbology == BARCODE_CODE128B) {
        return 1;
    }


    if (symbology == BARCODE_ISBNX) {
        return 1;
    }
    if (symbology == BARCODE_EAN14) {
        return 1;
    }
    if (symbology == BARCODE_NVE18) {
        return 1;
    }
    if (symbology == BARCODE_KOREAPOST) {
        return 1;
    }
    if (symbology == BARCODE_PLESSEY) {
        return 1;
    }
    if (symbology == BARCODE_TELEPEN_NUM) {
        return 1;
    }
    if (symbology == BARCODE_ITF14) {
        return 1;
    }
    if (symbology == BARCODE_CODE32) {
        return 1;


    }

    return 0;
}

/* Indicates which symbols can have addon (EAN-2 and EAN-5) */
int is_extendable(const int symbology) {
    if (symbology == BARCODE_EANX) {
        return 1;
    }
................................................................................
            return 1;
        }
    }

    return 0;
}

/* Convert Unicode to Latin-1 for those symbologies which only support Latin-1 */
int latin1_process(struct zint_symbol *symbol, const unsigned char source[], unsigned char preprocessed[], int *length) {
    int j, i, next;

    j = 0;
    i = 0;
    do {
        next = -1;
        if (source[i] < 128) {
            preprocessed[j] = source[i];
            j++;
            next = i + 1;
        } else {
            if (source[i] == 0xC2) {
                preprocessed[j] = source[i + 1];
                j++;
                next = i + 2;
            }
            if (source[i] == 0xC3) {
                preprocessed[j] = source[i + 1] + 64;
                j++;
                next = i + 2;
            }
        }
        if (next == -1) {
            strcpy(symbol->errtxt, "error: Invalid character in input string (only Latin-1 characters supported)");
            return ZINT_ERROR_INVALID_DATA;
        }
        i = next;
    } while (i < *length);
    preprocessed[j] = '\0';
    *length = j;

    return 0;
}

int utf8toutf16(struct zint_symbol *symbol, const unsigned char source[], int vals[], int *length) {
    int bpos, jpos, error_number;
    int next;

    bpos = 0;
    jpos = 0;
    error_number = 0;
................................................................................
        if (source[bpos] <= 0x7f) {
            /* 1 byte mode (7-bit ASCII) */
            vals[jpos] = source[bpos];
            next = bpos + 1;
            jpos++;
        } else {
            if ((source[bpos] >= 0x80) && (source[bpos] <= 0xbf)) {
                strcpy(symbol->errtxt, "Corrupt Unicode data");
                return ZINT_ERROR_INVALID_DATA;
            }
            if ((source[bpos] >= 0xc0) && (source[bpos] <= 0xc1)) {
                strcpy(symbol->errtxt, "Overlong encoding not supported");
                return ZINT_ERROR_INVALID_DATA;
            }

            if ((source[bpos] >= 0xc2) && (source[bpos] <= 0xdf)) {
                /* 2 byte mode */
                vals[jpos] = ((source[bpos] & 0x1f) << 6) + (source[bpos + 1] & 0x3f);
                next = bpos + 2;
................................................................................
                if ((source[bpos] >= 0xe0) && (source[bpos] <= 0xef)) {
                /* 3 byte mode */
                vals[jpos] = ((source[bpos] & 0x0f) << 12) + ((source[bpos + 1] & 0x3f) << 6) + (source[bpos + 2] & 0x3f);
                next = bpos + 3;
                jpos++;
            } else
                if (source[bpos] >= 0xf0) {
                strcpy(symbol->errtxt, "Unicode sequences of more than 3 bytes not supported");
                return ZINT_ERROR_INVALID_DATA;
            }
        }

        bpos = next;

    } while (bpos < *length);
    *length = jpos;

    return error_number;
}
































|



<
<
<
<
<
<







 







|









|
|
|







 







|
|










|
|








|







 







|

|







 







>
>

<
>

<
<
|
>
>
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
<
|
<
>
>


|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|



|







 







|












>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
31
32
33
34
35
36
37
38
39
40
41






42
43
44
45
46
47
48
..
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
..
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
...
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
...
157
158
159
160
161
162
163
164
165
166

167
168


169
170
171
172


173


174


175


176


177


178


179

180
181
182
183
184
185
186
187
188
189
190
191
...
217
218
219
220
221
222
223




































224
225
226
227
228
229
230
...
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
 */
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "common.h"

/* Local replacement for strlen() with unsigned char strings */
size_t ustrlen(const unsigned char data[]) {
    return strlen((const char*) data);
}







/* Converts a character 0-9 to its equivalent integer value */
int ctoi(const char source) {
    if ((source >= '0') && (source <= '9'))
        return (source - '0');
    return (source - 'A' + 10);
}

................................................................................
    } else {
        return ('A' + (source - 10));
    }
}

/* Converts lower case characters to upper case in a string source[] */
void to_upper(unsigned char source[]) {
    size_t i, src_len = ustrlen(source);

    for (i = 0; i < src_len; i++) {
        if ((source[i] >= 'a') && (source[i] <= 'z')) {
            source [i] = (source[i] - 'a') + 'A';
        }
    }
}

/* Verifies that a string only uses valid characters */
int is_sane(const char test_string[], const unsigned char source[], const size_t length) {
    unsigned int j, latch;
    size_t i, lt = strlen(test_string);

    for (i = 0; i < length; i++) {
        latch = FALSE;
        for (j = 0; j < lt; j++) {
            if (source[i] == test_string[j]) {
                latch = TRUE;
                break;
................................................................................
        }
    }

    return 0;
}

/* Returns the position of data in set_string */
int posn(const char set_string[], const char data) {
    size_t i, n = strlen(set_string);

    for (i = 0; i < n; i++) {
        if (data == set_string[i]) {
            return i;
        }
    }
    return 0;
}

/* Replaces huge switch statements for looking up in tables */
void lookup(const char set_string[], const char *table[], const char data, char dest[]) {
    size_t i, n = strlen(set_string);

    for (i = 0; i < n; i++) {
        if (data == set_string[i]) {
            strcat(dest, table[i]);
        }
    }
}

/* Return true (1) if a module is dark/black, otherwise false (0) */
int module_is_set(const struct zint_symbol *symbol, const int y_coord, const int x_coord) {
    return (symbol->encoded_data[y_coord][x_coord / 7] >> (x_coord % 7)) & 1;
}

/* Set a module to dark/black */
void set_module(struct zint_symbol *symbol, const int y_coord, const int x_coord) {
    symbol->encoded_data[y_coord][x_coord / 7] |= 1 << (x_coord % 7);
................................................................................

/* Set (or unset) a module to white */
void unset_module(struct zint_symbol *symbol, const int y_coord, const int x_coord) {
    symbol->encoded_data[y_coord][x_coord / 7] &= ~(1 << (x_coord % 7));
}

/* Expands from a width pattern to a bit pattern */
void expand(struct zint_symbol *symbol, const char data[]) {

    size_t reader, n = strlen(data);
    int writer, i;
    char latch;

    writer = 0;
    latch = '1';

    for (reader = 0; reader < n; reader++) {
................................................................................
        }
    }
    symbol->rows = symbol->rows + 1;
}

/* Indicates which symbologies can have row binding */
int is_stackable(const int symbology) {
    int retval = 0;

    if (symbology < BARCODE_PDF417) {

        retval = 1;
    }



    switch (symbology) {
        case BARCODE_CODE128B:
        case BARCODE_ISBNX:


        case BARCODE_EAN14:


        case BARCODE_NVE18:


        case BARCODE_KOREAPOST:


        case BARCODE_PLESSEY:


        case BARCODE_TELEPEN_NUM:


        case BARCODE_ITF14:


        case BARCODE_CODE32:

        case BARCODE_CODABLOCKF:
            retval = 1;
    }

    return retval;
}

/* Indicates which symbols can have addon (EAN-2 and EAN-5) */
int is_extendable(const int symbology) {
    if (symbology == BARCODE_EANX) {
        return 1;
    }
................................................................................
            return 1;
        }
    }

    return 0;
}





































int utf8toutf16(struct zint_symbol *symbol, const unsigned char source[], int vals[], int *length) {
    int bpos, jpos, error_number;
    int next;

    bpos = 0;
    jpos = 0;
    error_number = 0;
................................................................................
        if (source[bpos] <= 0x7f) {
            /* 1 byte mode (7-bit ASCII) */
            vals[jpos] = source[bpos];
            next = bpos + 1;
            jpos++;
        } else {
            if ((source[bpos] >= 0x80) && (source[bpos] <= 0xbf)) {
                strcpy(symbol->errtxt, "Corrupt Unicode data (B40)");
                return ZINT_ERROR_INVALID_DATA;
            }
            if ((source[bpos] >= 0xc0) && (source[bpos] <= 0xc1)) {
                strcpy(symbol->errtxt, "Overlong encoding not supported (B41)");
                return ZINT_ERROR_INVALID_DATA;
            }

            if ((source[bpos] >= 0xc2) && (source[bpos] <= 0xdf)) {
                /* 2 byte mode */
                vals[jpos] = ((source[bpos] & 0x1f) << 6) + (source[bpos + 1] & 0x3f);
                next = bpos + 2;
................................................................................
                if ((source[bpos] >= 0xe0) && (source[bpos] <= 0xef)) {
                /* 3 byte mode */
                vals[jpos] = ((source[bpos] & 0x0f) << 12) + ((source[bpos + 1] & 0x3f) << 6) + (source[bpos + 2] & 0x3f);
                next = bpos + 3;
                jpos++;
            } else
                if (source[bpos] >= 0xf0) {
                strcpy(symbol->errtxt, "Unicode sequences of more than 3 bytes not supported (B42)");
                return ZINT_ERROR_INVALID_DATA;
            }
        }

        bpos = next;

    } while (bpos < *length);
    *length = jpos;

    return error_number;
}

void set_minimum_height(struct zint_symbol *symbol, int min_height) {
    /* Enforce minimum permissable height of rows */
    int fixed_height = 0;
    int zero_count = 0;
    int i;
    
    for (i = 0; i < symbol->rows; i++) {
        fixed_height += symbol->row_height[i];
        
        if (symbol->row_height[i] == 0) {
            zero_count++;
        }
    }
    
    if (zero_count > 0) {
        if (((symbol->height - fixed_height) / zero_count) < min_height) {
            for (i = 0; i < symbol->rows; i++) {
                if (symbol->row_height[i] == 0) {
                    symbol->row_height[i] = min_height;
                }
            }
        }
    }
}

Changes to jni/zint/backend/common.h.

42
43
44
45
46
47
48



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

74
75
76
77
78
#define TRUE		1
#endif

/* The most commonly used set */
#define NEON	"0123456789"

#include "zint.h"




#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

    extern int ustrlen(const unsigned char source[]);
    extern void ustrcpy(unsigned char target[], const unsigned char source[]);
    extern int ctoi(const char source);
    extern char itoc(const int source);
    extern void to_upper(unsigned char source[]);
    extern int is_sane(char test_string[], const unsigned char source[], const int length);
    extern void lookup(char set_string[], const char *table[], const char data, char dest[]);
    extern int posn(char set_string[], const char data);
    extern void expand(struct zint_symbol *symbol, char data[]);
    extern int is_stackable(const int symbology);
    extern int is_extendable(const int symbology);
    extern int roundup(const float input);
    extern int module_is_set(const struct zint_symbol *symbol, const int y_coord, const int x_coord);
    extern void set_module(struct zint_symbol *symbol, const int y_coord, const int x_coord);
    extern void unset_module(struct zint_symbol *symbol, const int y_coord, const int x_coord);
    extern int istwodigits(const unsigned char source[], const int position);
    extern double froundup(const double input);
    extern int parunmodd(const unsigned char llyth);
    extern int latin1_process(struct zint_symbol *symbol, const unsigned char source[], unsigned char preprocessed[], int *length);
    extern int utf8toutf16(struct zint_symbol *symbol, const unsigned char source[], int vals[], int *length);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __COMMON_H */







>
>
>





|
<



|
|
|
|









<

>





42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

74
75
76
77
78
79
80
#define TRUE		1
#endif

/* The most commonly used set */
#define NEON	"0123456789"

#include "zint.h"
#include <stdlib.h>

#define ustrcpy(target,source) strcpy((char*)target,(const char*)source)

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

    extern size_t ustrlen(const unsigned char source[]);

    extern int ctoi(const char source);
    extern char itoc(const int source);
    extern void to_upper(unsigned char source[]);
    extern int is_sane(const char test_string[], const unsigned char source[], const size_t length);
    extern void lookup(const char set_string[], const char *table[], const char data, char dest[]);
    extern int posn(const char set_string[], const char data);
    extern void expand(struct zint_symbol *symbol, const char data[]);
    extern int is_stackable(const int symbology);
    extern int is_extendable(const int symbology);
    extern int roundup(const float input);
    extern int module_is_set(const struct zint_symbol *symbol, const int y_coord, const int x_coord);
    extern void set_module(struct zint_symbol *symbol, const int y_coord, const int x_coord);
    extern void unset_module(struct zint_symbol *symbol, const int y_coord, const int x_coord);
    extern int istwodigits(const unsigned char source[], const int position);
    extern double froundup(const double input);
    extern int parunmodd(const unsigned char llyth);

    extern int utf8toutf16(struct zint_symbol *symbol, const unsigned char source[], int vals[], int *length);
    extern void set_minimum_height(struct zint_symbol *symbol, int min_height);
#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __COMMON_H */

Changes to jni/zint/backend/composite.c.

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
...
789
790
791
792
793
794
795








































































































































































































































796
797
798
799
800
801
802
...
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
....
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
....
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708

1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
....
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996

1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
....
2087
2088
2089
2090
2091
2092
2093



















2094
2095
2096
2097
2098
2099
2100
....
2103
2104
2105
2106
2107
2108
2109

2110

2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138



2139
2140
2141
2142
2143
2144
2145
2146
2147
2148

2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168



2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
....
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
....
2252
2253
2254
2255
2256
2257
2258











































2259
2260
2261
2262
2263
2264
2265
#include "pdf417.h"
#include "gs1.h"

#define UINT unsigned short

extern int general_rules(char field[], char type[]);
extern int eanx(struct zint_symbol *symbol, unsigned char source[], int length);
extern int ean_128(struct zint_symbol *symbol, unsigned char source[], int length);
extern int rss14(struct zint_symbol *symbol, unsigned char source[], int length);
extern int rsslimited(struct zint_symbol *symbol, unsigned char source[], int length);
extern int rssexpanded(struct zint_symbol *symbol, unsigned char source[], int length);

static UINT pwr928[69][7];

int _min(int first, int second) {
................................................................................
        symbol->row_height[i] = 3;
    }
    symbol->rows = (mclength / cc_width);
    symbol->width = strlen(pattern);

    return 0;
}









































































































































































































































int cc_binary_string(struct zint_symbol *symbol, const char source[], char binary_string[], int cc_mode, int *cc_width, int *ecc, int lin_width) { /* Handles all data encodation from section 5 of ISO/IEC 24723 */
    int encoding_method, read_posn, d1, d2, value, alpha_pad;
    int i, j, mask, ai_crop, fnc1_latch;
    long int group_val;
    int ai90_mode, latch, remainder, binary_length;
    char date_str[4];
................................................................................
                case '/': alphanum += 1;
                    break;
            }

            if (!(((ninety[i] >= '0') && (ninety[i] <= '9')) || ((ninety[i] >= 'A') && (ninety[i] <= 'Z')))) {
                if ((ninety[i] != '*') && (ninety[i] != ',') && (ninety[i] != '-') && (ninety[i] != '.') && (ninety[i] != '/')) {
                    /* An Invalid AI 90 character */
                    strcpy(symbol->errtxt, "Invalid AI 90 data");
                    return ZINT_ERROR_INVALID_DATA;
                }
            }
        }

        /* must start with 0, 1, 2 or 3 digits followed by an uppercase character */
        test1 = -1;
................................................................................

    }

    general_field_type[strlen(general_field)] = '\0';

    if (latch == 1) {
        /* Invalid characters in input data */
        strcpy(symbol->errtxt, "Invalid characters in input data");
        return ZINT_ERROR_INVALID_DATA;
    }

    for (i = 0; i < (int) strlen(general_field); i++) {
        if ((general_field_type[i] == ISOIEC) && (general_field[i + 1] == '[')) {
            general_field_type[i + 1] = ISOIEC;
        }
................................................................................
                if (general_field[i] == '_') strcat(binary_string, "11111011"); /* underline or low line */
                if (general_field[i] == ' ') strcat(binary_string, "11111100"); /* space */

                i++;
                break;
        }
    } while (i + latch < (int) strlen(general_field));

    binary_length = strlen(binary_string);
    if (cc_mode == 1) {
        /* CC-A 2D component - calculate remaining space */
        switch (*(cc_width)) {
            case 2:
                if (binary_length > 167) {
                    return ZINT_ERROR_TOO_LONG;
                }
                if (binary_length <= 167) {
                    target_bitsize = 167;
                }
                if (binary_length <= 138) {
                    target_bitsize = 138;
                }
                if (binary_length <= 118) {
                    target_bitsize = 118;
                }
                if (binary_length <= 108) {
                    target_bitsize = 108;
                }
                if (binary_length <= 88) {
                    target_bitsize = 88;
                }
                if (binary_length <= 78) {
                    target_bitsize = 78;
                }
                if (binary_length <= 59) {
                    target_bitsize = 59;
                }
                break;
            case 3:
                if (binary_length > 167) {
                    return ZINT_ERROR_TOO_LONG;
                }
                if (binary_length <= 167) {
                    target_bitsize = 167;
                }
                if (binary_length <= 138) {
                    target_bitsize = 138;
                }
                if (binary_length <= 118) {
                    target_bitsize = 118;
                }
                if (binary_length <= 98) {
                    target_bitsize = 98;
                }
                if (binary_length <= 78) {
                    target_bitsize = 78;
                }
                break;
            case 4:
                if (binary_length > 197) {
                    return ZINT_ERROR_TOO_LONG;
                }
                if (binary_length <= 197) {
                    target_bitsize = 197;
                }
                if (binary_length <= 167) {
                    target_bitsize = 167;
                }
                if (binary_length <= 138) {
                    target_bitsize = 138;
                }
                if (binary_length <= 108) {
                    target_bitsize = 108;
                }
                if (binary_length <= 78) {
                    target_bitsize = 78;
                }
                break;
        }
    }

    if (cc_mode == 2) {
        /* CC-B 2D component - calculated from ISO/IEC 24728 Table 1  */
        switch (*(cc_width)) {
            case 2:
                if (binary_length > 336) {
                    return ZINT_ERROR_TOO_LONG;
                }
                if (binary_length <= 336) {
                    target_bitsize = 336;
                }
                if (binary_length <= 296) {
                    target_bitsize = 296;
                }
                if (binary_length <= 256) {
                    target_bitsize = 256;
                }
                if (binary_length <= 208) {
                    target_bitsize = 208;
                }
                if (binary_length <= 160) {
                    target_bitsize = 160;
                }
                if (binary_length <= 104) {
                    target_bitsize = 104;
                }
                if (binary_length <= 56) {
                    target_bitsize = 56;
                }
                break;
            case 3:
                if (binary_length > 768) {
                    return ZINT_ERROR_TOO_LONG;
                }
                if (binary_length <= 768) {
                    target_bitsize = 768;
                }
                if (binary_length <= 648) {
                    target_bitsize = 648;
                }
                if (binary_length <= 536) {
                    target_bitsize = 536;
                }
                if (binary_length <= 416) {
                    target_bitsize = 416;
                }
                if (binary_length <= 304) {
                    target_bitsize = 304;
                }
                if (binary_length <= 208) {
                    target_bitsize = 208;
                }
                if (binary_length <= 152) {
                    target_bitsize = 152;
                }
                if (binary_length <= 112) {
                    target_bitsize = 112;
                }
                if (binary_length <= 72) {
                    target_bitsize = 72;
                }
                if (binary_length <= 32) {
                    target_bitsize = 32;
                }
                break;
            case 4:
                if (binary_length > 1184) {
                    return ZINT_ERROR_TOO_LONG;
                }
                if (binary_length <= 1184) {
                    target_bitsize = 1184;
                }
                if (binary_length <= 1016) {
                    target_bitsize = 1016;
                }
                if (binary_length <= 840) {
                    target_bitsize = 840;
                }
                if (binary_length <= 672) {
                    target_bitsize = 672;
                }
                if (binary_length <= 496) {
                    target_bitsize = 496;
                }
                if (binary_length <= 352) {
                    target_bitsize = 352;
                }
                if (binary_length <= 264) {
                    target_bitsize = 264;
                }
                if (binary_length <= 208) {
                    target_bitsize = 208;
                }
                if (binary_length <= 152) {
                    target_bitsize = 152;
                }
                if (binary_length <= 96) {
                    target_bitsize = 96;
                }
                if (binary_length <= 56) {
                    target_bitsize = 56;
                }
                break;
        }
    }

    if (cc_mode == 3) {
        /* CC-C 2D Component is a bit more complex! */
        int byte_length, codewords_used, ecc_level, ecc_codewords, rows;
        int codewords_total, target_codewords, target_bytesize;

        byte_length = binary_length / 8;
        if (binary_length % 8 != 0) {
            byte_length++;
        }

        codewords_used = (byte_length / 6) * 5;
        codewords_used += byte_length % 6;

        ecc_level = 7;
        if (codewords_used <= 1280) {
            ecc_level = 6;
        }
        if (codewords_used <= 640) {
            ecc_level = 5;
        }
        if (codewords_used <= 320) {
            ecc_level = 4;
        }
        if (codewords_used <= 160) {
            ecc_level = 3;
        }
        if (codewords_used <= 40) {
            ecc_level = 2;
        }
        *(ecc) = ecc_level;
        ecc_codewords = 1;
        for (i = 1; i <= (ecc_level + 1); i++) {
            ecc_codewords *= 2;
        }

        codewords_used += ecc_codewords;
        codewords_used += 3;

        if (codewords_used > symbol->option_3) {

            return ZINT_ERROR_TOO_LONG;
        }

        *(cc_width) = (lin_width - 62) / 17;
        if ((codewords_used / *(cc_width)) > 90) {
            /* stop the symbol from becoming too high */
            *(cc_width) = *(cc_width) + 1;
        }

        rows = codewords_used / *(cc_width);
        if (codewords_used % *(cc_width) != 0) {
            rows++;
        }

        codewords_total = *(cc_width) * rows;

        target_codewords = codewords_total - ecc_codewords;
        target_codewords -= 3;

        target_bytesize = 6 * (target_codewords / 5);
        target_bytesize += target_codewords % 5;

        target_bitsize = 8 * target_bytesize;
    }

    remainder = binary_length - target_bitsize;

    if (latch == 1) {
        i = 0;
        /* There is still one more numeric digit to encode */

        if ((remainder >= 4) && (remainder <= 6)) {
            d1 = ctoi(general_field[i]);
................................................................................
                mask = mask >> 1;
            }
            /* This may push the symbol up to the next size */
        }
    }

    if (strlen(binary_string) > 11805) { /* (2361 * 5) */
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    /* all the code below is repeated from above - it needs to be calculated again because the
       size of the symbol may have changed when adding data in the above sequence */

    binary_length = strlen(binary_string);
    if (cc_mode == 1) {
        /* CC-A 2D component - calculate padding required */
        switch (*(cc_width)) {
            case 2:
                if (binary_length > 167) {
                    return ZINT_ERROR_TOO_LONG;
                }
                if (binary_length <= 167) {
                    target_bitsize = 167;
                }
                if (binary_length <= 138) {
                    target_bitsize = 138;
                }
                if (binary_length <= 118) {
                    target_bitsize = 118;
                }
                if (binary_length <= 108) {
                    target_bitsize = 108;
                }
                if (binary_length <= 88) {
                    target_bitsize = 88;
                }
                if (binary_length <= 78) {
                    target_bitsize = 78;
                }
                if (binary_length <= 59) {
                    target_bitsize = 59;
                }
                break;
            case 3:
                if (binary_length > 167) {
                    return ZINT_ERROR_TOO_LONG;
                }
                if (binary_length <= 167) {
                    target_bitsize = 167;
                }
                if (binary_length <= 138) {
                    target_bitsize = 138;
                }
                if (binary_length <= 118) {
                    target_bitsize = 118;
                }
                if (binary_length <= 98) {
                    target_bitsize = 98;
                }
                if (binary_length <= 78) {
                    target_bitsize = 78;
                }
                break;
            case 4:
                if (binary_length > 197) {
                    return ZINT_ERROR_TOO_LONG;
                }
                if (binary_length <= 197) {
                    target_bitsize = 197;
                }
                if (binary_length <= 167) {
                    target_bitsize = 167;
                }
                if (binary_length <= 138) {
                    target_bitsize = 138;
                }
                if (binary_length <= 108) {
                    target_bitsize = 108;
                }
                if (binary_length <= 78) {
                    target_bitsize = 78;
                }
                break;
        }
    }

    if (cc_mode == 2) {
        /* CC-B 2D component */
        switch (*(cc_width)) {
            case 2:
                if (binary_length > 336) {
                    return ZINT_ERROR_TOO_LONG;
                }
                if (binary_length <= 336) {
                    target_bitsize = 336;
                }
                if (binary_length <= 296) {
                    target_bitsize = 296;
                }
                if (binary_length <= 256) {
                    target_bitsize = 256;
                }
                if (binary_length <= 208) {
                    target_bitsize = 208;
                }
                if (binary_length <= 160) {
                    target_bitsize = 160;
                }
                if (binary_length <= 104) {
                    target_bitsize = 104;
                }
                if (binary_length <= 56) {
                    target_bitsize = 56;
                }
                break;
            case 3:
                if (binary_length > 768) {
                    return ZINT_ERROR_TOO_LONG;
                }
                if (binary_length <= 768) {
                    target_bitsize = 768;
                }
                if (binary_length <= 648) {
                    target_bitsize = 648;
                }
                if (binary_length <= 536) {
                    target_bitsize = 536;
                }
                if (binary_length <= 416) {
                    target_bitsize = 416;
                }
                if (binary_length <= 304) {
                    target_bitsize = 304;
                }
                if (binary_length <= 208) {
                    target_bitsize = 208;
                }
                if (binary_length <= 152) {
                    target_bitsize = 152;
                }
                if (binary_length <= 112) {
                    target_bitsize = 112;
                }
                if (binary_length <= 72) {
                    target_bitsize = 72;
                }
                if (binary_length <= 32) {
                    target_bitsize = 32;
                }
                break;
            case 4:
                if (binary_length > 1184) {
                    return ZINT_ERROR_TOO_LONG;
                }
                if (binary_length <= 1184) {
                    target_bitsize = 1184;
                }
                if (binary_length <= 1016) {
                    target_bitsize = 1016;
                }
                if (binary_length <= 840) {
                    target_bitsize = 840;
                }
                if (binary_length <= 672) {
                    target_bitsize = 672;
                }
                if (binary_length <= 496) {
                    target_bitsize = 496;
                }
                if (binary_length <= 352) {
                    target_bitsize = 352;
                }
                if (binary_length <= 264) {
                    target_bitsize = 264;
                }
                if (binary_length <= 208) {
                    target_bitsize = 208;
                }
                if (binary_length <= 152) {
                    target_bitsize = 152;
                }
                if (binary_length <= 96) {
                    target_bitsize = 96;
                }
                if (binary_length <= 56) {
                    target_bitsize = 56;
                }
                break;
        }
    }

    if (cc_mode == 3) {
        /* CC-C 2D Component is a bit more complex! */
        int byte_length, codewords_used, ecc_level, ecc_codewords, rows;
        int codewords_total, target_codewords, target_bytesize;

        byte_length = binary_length / 8;
        if (binary_length % 8 != 0) {
            byte_length++;
        }

        codewords_used = (byte_length / 6) * 5;
        codewords_used += byte_length % 6;

        ecc_level = 7;
        if (codewords_used <= 1280) {
            ecc_level = 6;
        }
        if (codewords_used <= 640) {
            ecc_level = 5;
        }
        if (codewords_used <= 320) {
            ecc_level = 4;
        }
        if (codewords_used <= 160) {
            ecc_level = 3;
        }
        if (codewords_used <= 40) {
            ecc_level = 2;
        }
        *(ecc) = ecc_level;
        ecc_codewords = 1;
        for (i = 1; i <= (ecc_level + 1); i++) {
            ecc_codewords *= 2;
        }

        codewords_used += ecc_codewords;
        codewords_used += 3;

        if (codewords_used > symbol->option_3) {

            return ZINT_ERROR_TOO_LONG;
        }

        *(cc_width) = (lin_width - 62) / 17;
        if ((codewords_used / *(cc_width)) > 90) {
            /* stop the symbol from becoming too high */
            *(cc_width) = *(cc_width) + 1;
        }

        rows = codewords_used / *(cc_width);
        if (codewords_used % *(cc_width) != 0) {
            rows++;
        }

        codewords_total = *(cc_width) * rows;

        target_codewords = codewords_total - ecc_codewords;
        target_codewords -= 3;

        target_bytesize = 6 * (target_codewords / 5);
        target_bytesize += target_codewords % 5;

        target_bitsize = 8 * target_bytesize;
    }

    if (binary_length < target_bitsize) {
        /* Now add padding to binary string */
        if (alpha_pad == 1) {
            strcat(binary_string, "11111");
            alpha_pad = 0;
................................................................................
    if (zsecond_len) {
        memmove(symbol->primary + n + zsecond_len, symbol->primary + n, second_len);
        memset(symbol->primary + n, '0', zsecond_len);
        n += zsecond_len + second_len;
    }
    symbol->primary[n] = '\0';
}




















int composite(struct zint_symbol *symbol, unsigned char source[], int length) {
    int error_number, cc_mode, cc_width, ecc_level;
    int j, i, k;
    unsigned int rs = length + 1;
    unsigned int bs = 20 * rs;
    unsigned int pri_len;
................................................................................
    char binary_string[bs];
#else
    char* reduced = (char*) _alloca(rs);
    char* binary_string = (char*) _alloca(bs);
#endif
    struct zint_symbol *linear;
    int top_shift, bottom_shift;



    error_number = 0;
    pri_len = strlen(symbol->primary);
    if (pri_len == 0) {
        strcpy(symbol->errtxt, "No primary (linear) message in 2D composite");
        return ZINT_ERROR_INVALID_OPTION;
    }

    if (length > 2990) {
        strcpy(symbol->errtxt, "2D component input data too long");
        return ZINT_ERROR_TOO_LONG;
    }

    linear = ZBarcode_Create(); /* Symbol contains the 2D component and Linear contains the rest */

    error_number = gs1_verify(symbol, source, length, reduced);
    if (error_number != 0) {
        return error_number;
    }

    cc_mode = symbol->option_1;

    if ((cc_mode == 3) && (symbol->symbology != BARCODE_EAN128_CC)) {
        /* CC-C can only be used with a GS1-128 linear part */
        strcpy(symbol->errtxt, "Invalid mode (CC-C only valid with GS1-128 linear component)");
        return ZINT_ERROR_INVALID_OPTION;
    }

    linear->symbology = symbol->symbology;




    if (linear->symbology != BARCODE_EAN128_CC) {
        /* Set the "component linkage" flag in the linear component */
        linear->option_1 = 2;
    } else {
        /* GS1-128 needs to know which type of 2D component is used */
        linear->option_1 = cc_mode;
    }

    switch (symbol->symbology) {

        case BARCODE_EANX_CC: error_number = eanx(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_EAN128_CC: error_number = ean_128(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_RSS14_CC: error_number = rss14(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_RSS_LTD_CC: error_number = rsslimited(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_RSS_EXP_CC: error_number = rssexpanded(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_UPCA_CC: error_number = eanx(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_UPCE_CC: error_number = eanx(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_RSS14STACK_CC: error_number = rss14(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_RSS14_OMNI_CC: error_number = rss14(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_RSS_EXPSTACK_CC: error_number = rssexpanded(linear, (unsigned char *) symbol->primary, pri_len);
            break;



    }

    if (error_number != 0) {
        strcpy(symbol->errtxt, linear->errtxt);
        strcat(symbol->errtxt, " in linear component");
        return error_number;
    }

    switch (symbol->symbology) {
            /* Determine width of 2D component according to ISO/IEC 24723 Table 1 */
        case BARCODE_EANX_CC:
            switch (pri_len) {
                case 7: /* EAN-8 */
................................................................................
        case BARCODE_RSS14STACK_CC: cc_width = 2;
            break;
        case BARCODE_RSS14_OMNI_CC: cc_width = 2;
            break;
        case BARCODE_RSS_EXPSTACK_CC: cc_width = 4;
            break;
    }

    memset(binary_string, 0, bs);

    if (cc_mode < 1 || cc_mode > 3) {
        cc_mode = 1;
    }

    if (cc_mode == 1) {
        i = cc_binary_string(symbol, reduced, binary_string, cc_mode, &cc_width, &ecc_level, linear->width);
        if (i == ZINT_ERROR_TOO_LONG) {
            cc_mode = 2;
        }
    }

    if (cc_mode == 2) {
        /* If the data didn't fit into CC-A it is recalculated for CC-B */
        i = cc_binary_string(symbol, reduced, binary_string, cc_mode, &cc_width, &ecc_level, linear->width);
        if (i == ZINT_ERROR_TOO_LONG) {
            if (symbol->symbology != BARCODE_EAN128_CC) {
                return ZINT_ERROR_TOO_LONG;
            } else {
                cc_mode = 3;
            }
        }
    }

    if (cc_mode == 3) {
        /* If the data didn't fit in CC-B (and linear part is GS1-128) it is recalculated for CC-C */
        i = cc_binary_string(symbol, reduced, binary_string, cc_mode, &cc_width, &ecc_level, linear->width);
        if (i == ZINT_ERROR_TOO_LONG) {
            return ZINT_ERROR_TOO_LONG;
        }
    }

    switch (cc_mode) {
            /* Note that ecc_level is only relevant to CC-C */
................................................................................
        case 3: error_number = cc_c(symbol, binary_string, cc_width, ecc_level);
            break;
    }

    if (error_number != 0) {
        return ZINT_ERROR_ENCODING_PROBLEM;
    }












































    /* Merge the linear component with the 2D component */

    top_shift = 0;
    bottom_shift = 0;

    switch (symbol->symbology) {







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







 







|







 







|

|
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
|
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
|
|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<







 







|



<
<


|
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
|
<
<
<
|
<
<
|
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
|
>



|




|


|
<
<
<
<
<
<
<

<


|



<
>
>
>
|
<
<
<
<
<
<
|
<
|
>
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
>
>
>
|
<
<
<
<
<







 







|







|







|











|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
...
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
....
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
....
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
....
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725


1726




1727



















1728














































1729




1730



















1731
1732




























1733




1734



1735


1736




1737




































































1738
1739
1740
1741



















1742



1743
1744
1745
1746
1747
1748
1749
....
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784


1785
1786
1787


1788




1789



















1790














































1791




1792



















1793
1794




























1795




1796



1797


1798




1799




































































1800
1801






















1802
1803
1804
1805
1806
1807
1808
....
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
....
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925







1926

1927
1928
1929
1930
1931
1932

1933
1934
1935
1936






1937

1938
1939
1940



















1941
1942
1943
1944





1945
1946
1947
1948
1949
1950
1951
....
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
....
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
#include "pdf417.h"
#include "gs1.h"

#define UINT unsigned short

extern int general_rules(char field[], char type[]);
extern int eanx(struct zint_symbol *symbol, unsigned char source[], int length);
extern int ean_128(struct zint_symbol *symbol, unsigned char source[], const size_t length);
extern int rss14(struct zint_symbol *symbol, unsigned char source[], int length);
extern int rsslimited(struct zint_symbol *symbol, unsigned char source[], int length);
extern int rssexpanded(struct zint_symbol *symbol, unsigned char source[], int length);

static UINT pwr928[69][7];

int _min(int first, int second) {
................................................................................
        symbol->row_height[i] = 3;
    }
    symbol->rows = (mclength / cc_width);
    symbol->width = strlen(pattern);

    return 0;
}

int calc_padding_cca(int binary_length, int cc_width) {
    int target_bitsize = 0;
    
    switch (cc_width) {
        case 2:
            if (binary_length <= 167) {
                target_bitsize = 167;
            }
            if (binary_length <= 138) {
                target_bitsize = 138;
            }
            if (binary_length <= 118) {
                target_bitsize = 118;
            }
            if (binary_length <= 108) {
                target_bitsize = 108;
            }
            if (binary_length <= 88) {
                target_bitsize = 88;
            }
            if (binary_length <= 78) {
                target_bitsize = 78;
            }
            if (binary_length <= 59) {
                target_bitsize = 59;
            }
            break;
        case 3:
            if (binary_length <= 167) {
                target_bitsize = 167;
            }
            if (binary_length <= 138) {
                target_bitsize = 138;
            }
            if (binary_length <= 118) {
                target_bitsize = 118;
            }
            if (binary_length <= 98) {
                target_bitsize = 98;
            }
            if (binary_length <= 78) {
                target_bitsize = 78;
            }
            break;
        case 4:
            if (binary_length <= 197) {
                target_bitsize = 197;
            }
            if (binary_length <= 167) {
                target_bitsize = 167;
            }
            if (binary_length <= 138) {
                target_bitsize = 138;
            }
            if (binary_length <= 108) {
                target_bitsize = 108;
            }
            if (binary_length <= 78) {
                target_bitsize = 78;
            }
            break;
        }
    
        return target_bitsize;
}

int calc_padding_ccb(int binary_length, int cc_width) {
    int target_bitsize = 0;
    
    switch (cc_width) {
        case 2:
            if (binary_length <= 336) {
                target_bitsize = 336;
            }
            if (binary_length <= 296) {
                target_bitsize = 296;
            }
            if (binary_length <= 256) {
                target_bitsize = 256;
            }
            if (binary_length <= 208) {
                target_bitsize = 208;
            }
            if (binary_length <= 160) {
                target_bitsize = 160;
            }
            if (binary_length <= 104) {
                target_bitsize = 104;
            }
            if (binary_length <= 56) {
                target_bitsize = 56;
            }
            break;
        case 3:
            if (binary_length <= 768) {
                target_bitsize = 768;
            }
            if (binary_length <= 648) {
                target_bitsize = 648;
            }
            if (binary_length <= 536) {
                target_bitsize = 536;
            }
            if (binary_length <= 416) {
                target_bitsize = 416;
            }
            if (binary_length <= 304) {
                target_bitsize = 304;
            }
            if (binary_length <= 208) {
                target_bitsize = 208;
            }
            if (binary_length <= 152) {
                target_bitsize = 152;
            }
            if (binary_length <= 112) {
                target_bitsize = 112;
            }
            if (binary_length <= 72) {
                target_bitsize = 72;
            }
            if (binary_length <= 32) {
                target_bitsize = 32;
            }
            break;
        case 4:
            if (binary_length <= 1184) {
                target_bitsize = 1184;
            }
            if (binary_length <= 1016) {
                target_bitsize = 1016;
            }
            if (binary_length <= 840) {
                target_bitsize = 840;
            }
            if (binary_length <= 672) {
                target_bitsize = 672;
            }
            if (binary_length <= 496) {
                target_bitsize = 496;
            }
            if (binary_length <= 352) {
                target_bitsize = 352;
            }
            if (binary_length <= 264) {
                target_bitsize = 264;
            }
            if (binary_length <= 208) {
                target_bitsize = 208;
            }
            if (binary_length <= 152) {
                target_bitsize = 152;
            }
            if (binary_length <= 96) {
                target_bitsize = 96;
            }
            if (binary_length <= 56) {
                target_bitsize = 56;
            }
            break;
    }
    
    return target_bitsize;
}

int calc_padding_ccc(int binary_length, int *cc_width, int lin_width, int *ecc) {
    int target_bitsize = 0;
    int byte_length, codewords_used, ecc_level, ecc_codewords, rows;
    int codewords_total, target_codewords, target_bytesize;
    int i;

    byte_length = binary_length / 8;
    if (binary_length % 8 != 0) {
        byte_length++;
    }

    codewords_used = (byte_length / 6) * 5;
    codewords_used += byte_length % 6;

    ecc_level = 7;
    if (codewords_used <= 1280) {
        ecc_level = 6;
    }
    if (codewords_used <= 640) {
        ecc_level = 5;
    }
    if (codewords_used <= 320) {
        ecc_level = 4;
    }
    if (codewords_used <= 160) {
        ecc_level = 3;
    }
    if (codewords_used <= 40) {
        ecc_level = 2;
    }
    *(ecc) = ecc_level;
    ecc_codewords = 1;
    for (i = 1; i <= (ecc_level + 1); i++) {
        ecc_codewords *= 2;
    }

    codewords_used += ecc_codewords;
    codewords_used += 3;

    *(cc_width) = (lin_width - 62) / 17;
    /* stop the symbol from becoming too high */
    do {
        *(cc_width) = *(cc_width) + 1;
        rows = codewords_used / *(cc_width);
    } while (rows > 90);

    if (codewords_used % *(cc_width) != 0) {
        rows++;
    }

    codewords_total = *(cc_width) * rows;
    
    if (codewords_total > 928) { // PDF_MAX
        return 0;
    }

    target_codewords = codewords_total - ecc_codewords;
    target_codewords -= 3;

    target_bytesize = 6 * (target_codewords / 5);
    target_bytesize += target_codewords % 5;

    target_bitsize = 8 * target_bytesize;
    
    return target_bitsize;
}

int cc_binary_string(struct zint_symbol *symbol, const char source[], char binary_string[], int cc_mode, int *cc_width, int *ecc, int lin_width) { /* Handles all data encodation from section 5 of ISO/IEC 24723 */
    int encoding_method, read_posn, d1, d2, value, alpha_pad;
    int i, j, mask, ai_crop, fnc1_latch;
    long int group_val;
    int ai90_mode, latch, remainder, binary_length;
    char date_str[4];
................................................................................
                case '/': alphanum += 1;
                    break;
            }

            if (!(((ninety[i] >= '0') && (ninety[i] <= '9')) || ((ninety[i] >= 'A') && (ninety[i] <= 'Z')))) {
                if ((ninety[i] != '*') && (ninety[i] != ',') && (ninety[i] != '-') && (ninety[i] != '.') && (ninety[i] != '/')) {
                    /* An Invalid AI 90 character */
                    strcpy(symbol->errtxt, "Invalid AI 90 data (D40)");
                    return ZINT_ERROR_INVALID_DATA;
                }
            }
        }

        /* must start with 0, 1, 2 or 3 digits followed by an uppercase character */
        test1 = -1;
................................................................................

    }

    general_field_type[strlen(general_field)] = '\0';

    if (latch == 1) {
        /* Invalid characters in input data */
        strcpy(symbol->errtxt, "Invalid characters in input data (D41)");
        return ZINT_ERROR_INVALID_DATA;
    }

    for (i = 0; i < (int) strlen(general_field); i++) {
        if ((general_field_type[i] == ISOIEC) && (general_field[i + 1] == '[')) {
            general_field_type[i + 1] = ISOIEC;
        }
................................................................................
                if (general_field[i] == '_') strcat(binary_string, "11111011"); /* underline or low line */
                if (general_field[i] == ' ') strcat(binary_string, "11111100"); /* space */

                i++;
                break;
        }
    } while (i + latch < (int) strlen(general_field));
    
    binary_length = strlen(binary_string);
    switch (cc_mode) {


        case 1:




            target_bitsize = calc_padding_cca(binary_length, *(cc_width));



















            break;














































        case 2:




            target_bitsize = calc_padding_ccb(binary_length, *(cc_width));



















            break;
        case 3:




























            target_bitsize = calc_padding_ccc(binary_length, cc_width, lin_width, ecc);




            break;



    }


    




    if (target_bitsize == 0) {




































































        strcpy(symbol->errtxt, "Input too long for selected 2d component (D42)");
        return ZINT_ERROR_TOO_LONG;
    }




















    remainder = target_bitsize - binary_length;




    if (latch == 1) {
        i = 0;
        /* There is still one more numeric digit to encode */

        if ((remainder >= 4) && (remainder <= 6)) {
            d1 = ctoi(general_field[i]);
................................................................................
                mask = mask >> 1;
            }
            /* This may push the symbol up to the next size */
        }
    }

    if (strlen(binary_string) > 11805) { /* (2361 * 5) */
        strcpy(symbol->errtxt, "Input too long (D43)");
        return ZINT_ERROR_TOO_LONG;
    }




    binary_length = strlen(binary_string);
    switch (cc_mode) {


        case 1:




            target_bitsize = calc_padding_cca(binary_length, *(cc_width));



















            break;














































        case 2:




            target_bitsize = calc_padding_ccb(binary_length, *(cc_width));



















            break;
        case 3:




























            target_bitsize = calc_padding_ccc(binary_length, cc_width, lin_width, ecc);




            break;



    }


    




    if (target_bitsize == 0) {




































































        strcpy(symbol->errtxt, "Input too long for selected 2d component (D44)");
        return ZINT_ERROR_TOO_LONG;






















    }

    if (binary_length < target_bitsize) {
        /* Now add padding to binary string */
        if (alpha_pad == 1) {
            strcat(binary_string, "11111");
            alpha_pad = 0;
................................................................................
    if (zsecond_len) {
        memmove(symbol->primary + n + zsecond_len, symbol->primary + n, second_len);
        memset(symbol->primary + n, '0', zsecond_len);
        n += zsecond_len + second_len;
    }
    symbol->primary[n] = '\0';
}

int linear_dummy_run(unsigned char *source, int length) {
    struct zint_symbol *dummy;
    int error_number;
    int linear_width;
    
    dummy = ZBarcode_Create();
    dummy->symbology = BARCODE_EAN128_CC;
    dummy->option_1 = 3;
    error_number = ean_128(dummy, source, length);
    linear_width = dummy->width;
    ZBarcode_Delete(dummy);
    
    if (error_number == 0) {
        return linear_width;
    } else {
        return 0;
    }
}

int composite(struct zint_symbol *symbol, unsigned char source[], int length) {
    int error_number, cc_mode, cc_width, ecc_level;
    int j, i, k;
    unsigned int rs = length + 1;
    unsigned int bs = 20 * rs;
    unsigned int pri_len;
................................................................................
    char binary_string[bs];
#else
    char* reduced = (char*) _alloca(rs);
    char* binary_string = (char*) _alloca(bs);
#endif
    struct zint_symbol *linear;
    int top_shift, bottom_shift;
    int linear_width = 0;
    
    /* Perform sanity checks on input options first */
    error_number = 0;
    pri_len = strlen(symbol->primary);
    if (pri_len == 0) {
        strcpy(symbol->errtxt, "No primary (linear) message in 2D composite (D45)");
        return ZINT_ERROR_INVALID_OPTION;
    }

    if (length > 2990) {
        strcpy(symbol->errtxt, "2D component input data too long (D46)");
        return ZINT_ERROR_TOO_LONG;
    }
    







    cc_mode = symbol->option_1;

    if ((cc_mode == 3) && (symbol->symbology != BARCODE_EAN128_CC)) {
        /* CC-C can only be used with a GS1-128 linear part */
        strcpy(symbol->errtxt, "Invalid mode (CC-C only valid with GS1-128 linear component) (D47)");
        return ZINT_ERROR_INVALID_OPTION;
    }


    error_number = gs1_verify(symbol, source, length, reduced);
    if (error_number != 0) {
        return error_number;
    }






    

    if (symbol->symbology == BARCODE_EAN128_CC) {
        /* Do a test run of encoding the linear component to establish its width */
        linear_width = linear_dummy_run((unsigned char *) symbol->primary, pri_len);



















        if (linear_width == 0) {
            strcpy(symbol->errtxt, "Invalid data (D48)");
            return ZINT_ERROR_INVALID_DATA;
        }





    }

    switch (symbol->symbology) {
            /* Determine width of 2D component according to ISO/IEC 24723 Table 1 */
        case BARCODE_EANX_CC:
            switch (pri_len) {
                case 7: /* EAN-8 */
................................................................................
        case BARCODE_RSS14STACK_CC: cc_width = 2;
            break;
        case BARCODE_RSS14_OMNI_CC: cc_width = 2;
            break;
        case BARCODE_RSS_EXPSTACK_CC: cc_width = 4;
            break;
    }
    
    memset(binary_string, 0, bs);

    if (cc_mode < 1 || cc_mode > 3) {
        cc_mode = 1;
    }

    if (cc_mode == 1) {
        i = cc_binary_string(symbol, reduced, binary_string, cc_mode, &cc_width, &ecc_level, linear_width);
        if (i == ZINT_ERROR_TOO_LONG) {
            cc_mode = 2;
        }
    }

    if (cc_mode == 2) {
        /* If the data didn't fit into CC-A it is recalculated for CC-B */
        i = cc_binary_string(symbol, reduced, binary_string, cc_mode, &cc_width, &ecc_level, linear_width);
        if (i == ZINT_ERROR_TOO_LONG) {
            if (symbol->symbology != BARCODE_EAN128_CC) {
                return ZINT_ERROR_TOO_LONG;
            } else {
                cc_mode = 3;
            }
        }
    }

    if (cc_mode == 3) {
        /* If the data didn't fit in CC-B (and linear part is GS1-128) it is recalculated for CC-C */
        i = cc_binary_string(symbol, reduced, binary_string, cc_mode, &cc_width, &ecc_level, linear_width);
        if (i == ZINT_ERROR_TOO_LONG) {
            return ZINT_ERROR_TOO_LONG;
        }
    }

    switch (cc_mode) {
            /* Note that ecc_level is only relevant to CC-C */
................................................................................
        case 3: error_number = cc_c(symbol, binary_string, cc_width, ecc_level);
            break;
    }

    if (error_number != 0) {
        return ZINT_ERROR_ENCODING_PROBLEM;
    }
    
    /* 2D component done, now calculate linear component */
    linear = ZBarcode_Create(); /* Symbol contains the 2D component and Linear contains the rest */
    
    linear->symbology = symbol->symbology;

    if (linear->symbology != BARCODE_EAN128_CC) {
        /* Set the "component linkage" flag in the linear component */
        linear->option_1 = 2;
    } else {
        /* GS1-128 needs to know which type of 2D component is used */
        linear->option_1 = cc_mode;
    }

    switch (symbol->symbology) {
        case BARCODE_EANX_CC: error_number = eanx(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_EAN128_CC: error_number = ean_128(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_RSS14_CC: error_number = rss14(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_RSS_LTD_CC: error_number = rsslimited(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_RSS_EXP_CC: error_number = rssexpanded(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_UPCA_CC: error_number = eanx(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_UPCE_CC: error_number = eanx(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_RSS14STACK_CC: error_number = rss14(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_RSS14_OMNI_CC: error_number = rss14(linear, (unsigned char *) symbol->primary, pri_len);
            break;
        case BARCODE_RSS_EXPSTACK_CC: error_number = rssexpanded(linear, (unsigned char *) symbol->primary, pri_len);
            break;
    }

    if (error_number != 0) {
        strcpy(symbol->errtxt, linear->errtxt);
        strcat(symbol->errtxt, " in linear component ");
        ZBarcode_Delete(linear);
        return error_number;
    }

    /* Merge the linear component with the 2D component */

    top_shift = 0;
    bottom_shift = 0;

    switch (symbol->symbology) {

Changes to jni/zint/backend/dmatrix.c.

42
43
44
45
46
47
48




49
50
51
52
53
54
55
...
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
...
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
...
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
...
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570








571
572
573
574
575
576
577
...
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
...
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
...
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
...
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
...
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
....
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062


1063
1064








1065










1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
....
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
....
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
....
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#ifdef _MSC_VER
#include <malloc.h>




#endif
#include "reedsol.h"
#include "common.h"
#include "dmatrix.h"

/* Annex M placement alorithm low level */
static void ecc200placementbit(int *array, const int NR, const int NC, int r, int c, const int p, const char b) {
................................................................................
    int i;
    int nonX12Position = 0;
    int specialX12Position = 0;
    int retval = 0;

    for (i = position; i < sourcelen; i++) {
        if (nonX12Position == 0) {
            if (isX12(i) == 1) {
                nonX12Position = i;
            }
        }

        if (specialX12Position == 0) {
            if ((inputData[i] == (char) 13) ||
                    (inputData[i] == '*') ||
................................................................................
    float ascii_count, c40_count, text_count, x12_count, edf_count, b256_count, best_count;
    int sp, best_scheme;

    best_scheme = DM_NULL;

    /* step (j) */
    if (current_mode == DM_ASCII) {
        ascii_count = 0.0;
        c40_count = 1.0;
        text_count = 1.0;
        x12_count = 1.0;
        edf_count = 1.0;
        b256_count = 1.25;
    } else {
        ascii_count = 1.0;
        c40_count = 2.0;
        text_count = 2.0;
        x12_count = 2.0;
        edf_count = 2.0;
        b256_count = 2.25;
    }

    switch (current_mode) {
        case DM_C40: c40_count = 0.0;
            break;
        case DM_TEXT: text_count = 0.0;
            break;
        case DM_X12: x12_count = 0.0;
            break;
        case DM_EDIFACT: edf_count = 0.0;
            break;
        case DM_BASE256: b256_count = 0.0;
            break;
    }

    sp = position;

    do {
        if (sp == (sourcelen - 1)) {
            /* At the end of data ... step (k) */
            ascii_count = ceil(ascii_count);
            b256_count = ceil(b256_count);
            edf_count = ceil(edf_count);
            text_count = ceil(text_count);
            x12_count = ceil(x12_count);
            c40_count = ceil(c40_count);

            best_count = c40_count;
            best_scheme = DM_C40; // (k)(7)

            if (x12_count < best_count) {
                best_count = x12_count;
                best_scheme = DM_X12; // (k)(6)
................................................................................
        } else {

            /* ascii ... step (l) */
            if ((inputData[sp] >= '0') && (inputData[sp] <= '9')) {
                ascii_count += 0.5F; // (l)(1)
            } else {
                if (inputData[sp] > 127) {
                    ascii_count = ceil(ascii_count) + 2.0F; // (l)(2)
                } else {
                    ascii_count = ceil(ascii_count) + 1.0F; // (l)(3)
                }
            }

            /* c40 ... step (m) */
            if ((inputData[sp] == ' ') ||
                    (((inputData[sp] >= '0') && (inputData[sp] <= '9')) ||
                    ((inputData[sp] >= 'A') && (inputData[sp] <= 'Z')))) {
................................................................................
        tp++;
        strcat(binary, " ");
        if (debug) printf("FN1 ");
    } /* FNC1 */

    if (symbol->output_options & READER_INIT) {
        if (gs1) {
            strcpy(symbol->errtxt, "Cannot encode in GS1 mode and Reader Initialisation at the same time");
            return ZINT_ERROR_INVALID_OPTION;
        } else {
            target[tp] = 234;
            tp++; /* Reader Programming */
            strcat(binary, " ");
            if (debug) printf("RP ");
        }
    }









    /* Check for Macro05/Macro06 */
    /* "[)>[RS]05[GS]...[RS][EOT]" -> CW 236 */
    /* "[)>[RS]06[GS]...[RS][EOT]" -> CW 237 */
    if (tp == 0 && sp == 0 && inputlen >= 9
            && source[0] == '[' && source[1] == ')' && source[2] == '>'
            && source[3] == '\x1e' && source[4] == '0'
................................................................................
                process_buffer[*process_p] = value;
                (*process_p)++;

                if (*process_p >= 3) {
                    int iv;

                    iv = (1600 * process_buffer[0]) + (40 * process_buffer[1]) + (process_buffer[2]) + 1;
                    target[tp] = iv / 256;
                    tp++;
                    target[tp] = iv % 256;
                    tp++;
                    strcat(binary, "  ");
                    if (debug) printf("[%d %d %d] ", process_buffer[0], process_buffer[1], process_buffer[2]);

                    process_buffer[0] = process_buffer[3];
................................................................................
                process_buffer[*process_p] = value;
                (*process_p)++;

                if (*process_p >= 3) {
                    int iv;

                    iv = (1600 * process_buffer[0]) + (40 * process_buffer[1]) + (process_buffer[2]) + 1;
                    target[tp] = iv / 256;
                    tp++;
                    target[tp] = iv % 256;
                    tp++;
                    strcat(binary, "  ");
                    if (debug) printf("[%d %d %d] ", process_buffer[0], process_buffer[1], process_buffer[2]);

                    process_buffer[0] = process_buffer[3];
................................................................................
                process_buffer[*process_p] = value;
                (*process_p)++;

                if (*process_p >= 3) {
                    int iv;

                    iv = (1600 * process_buffer[0]) + (40 * process_buffer[1]) + (process_buffer[2]) + 1;
                    target[tp] = iv / 256;
                    tp++;
                    target[tp] = iv % 256;
                    tp++;
                    strcat(binary, "  ");
                    if (debug) printf("[%d %d %d] ", process_buffer[0], process_buffer[1], process_buffer[2]);

                    process_buffer[0] = process_buffer[3];
................................................................................

                process_buffer[*process_p] = value;
                (*process_p)++;
                sp++;
            }

            if (*process_p >= 4) {
                target[tp] = (process_buffer[0] << 2) + ((process_buffer[1] & 0x30) >> 4);
                tp++;
                target[tp] = ((process_buffer[1] & 0x0f) << 4) + ((process_buffer[2] & 0x3c) >> 2);
                tp++;
                target[tp] = ((process_buffer[2] & 0x03) << 6) + process_buffer[3];
                tp++;
                strcat(binary, "   ");
                if (debug) printf("[%d %d %d %d] ", process_buffer[0], process_buffer[1], process_buffer[2], process_buffer[3]);

                process_buffer[0] = process_buffer[4];
                process_buffer[1] = process_buffer[5];
                process_buffer[2] = process_buffer[6];
................................................................................
    for (i = 0; i < tp; i++) {
        if (binary[i] == 'b') {
            int prn, temp;

            prn = ((149 * (i + 1)) % 255) + 1;
            temp = target[i] + prn;
            if (temp <= 255) {
                target[i] = temp;
            } else {
                target[i] = temp - 256;
            }
        }
    }

    *(last_mode) = current_mode;
    return tp;
}
................................................................................
                    target[target_length] = source[inputlen - 1] + 1;
                    target_length++;
                }
            }
            break;

        case DM_EDIFACT:
            if (symbols_left == process_p) // Unlatch not required!
            {
                if (process_p == 1) {
                    target[target_length] = source[inputlen - 1] + 1;
                    target_length++;
                }

                if (process_p == 2) {
                    target[target_length] = source[inputlen - 2] + 1;
                    target_length++;
                    target[target_length] = source[inputlen - 1] + 1;
                    target_length++;
                }



                if (process_p == 3) // Append edifact unlatch value (31) and encode as triple.








                {










                    target[target_length] = (unsigned char) ((process_buffer[0] << 2) + ((process_buffer[1] & 0x30) >> 4));
                    target_length++;
                    target[target_length] = (unsigned char) (((process_buffer[1] & 0x0f) << 4) + ((process_buffer[2] & 0x3c) >> 2));
                    target_length++;
                    target[target_length] = (unsigned char) (((process_buffer[2] & 0x03) << 6) + 31);
                    target_length++;
                }
            }

            if (symbols_left > process_p) // Unlatch and encode remaining data in ascii.
            {
                // Edifact unlatch.
                if (symbols_left < 3) {
                    target[target_length] = 31;
                    target_length++;
                } else
                    target[target_length] = (31 << 2);
                target_length++;

                if (process_p == 1) {
                    target[target_length] = source[inputlen - 1] + 1;
                    target_length++;
                }

                if (process_p == 2) {
                    target[target_length] = source[inputlen - 2] + 1;
                    target_length++;
                    target[target_length] = source[inputlen - 1] + 1;
                    target_length++;
                }

                if (process_p == 3) {
                    target[target_length] = source[inputlen - 3] + 1;
                    target_length++;
                    target[target_length] = source[inputlen - 2] + 1;
                    target_length++;
                    target[target_length] = source[inputlen - 1] + 1;
                    target_length++;
                }
            }
            break;
    }

    if (debug) {
        int i;
        printf("\n\n");
................................................................................
        if (i == tail_length) {
            target[tp] = 129;
            tp++; /* Pad */
        } else {
            prn = ((149 * (tp + 1)) % 253) + 1;
            temp = 129 + prn;
            if (temp <= 254) {
                target[tp] = temp;
                tp++;
            } else {
                target[tp] = temp - 254;
                tp++;
            }
        }
    }
}

int data_matrix_200(struct zint_symbol *symbol, unsigned char source[], const int length) {
    int inputlen, i, skew = 0;
    unsigned char binary[2200];
    int binlen;
    int process_buffer[8]; /* holds remaining data to finalised */
    int process_p; /* number of characters left to finalise */
    int symbolsize, optionsize, calcsize;
    int taillength, error_number = 0;
    int H, W, FH, FW, datablock, bytes, rsblock;
    int last_mode;
    unsigned char *grid = 0;
    int symbols_left;
    inputlen = length;

    /* inputlen may be decremented by 2 if macro character is used */
    binlen = dm200encode(symbol, source, binary, &last_mode, &inputlen, process_buffer, &process_p);

    if (binlen == 0) {
        strcpy(symbol->errtxt, "Data too long to fit in symbol");
        return ZINT_ERROR_TOO_LONG;
    }

    if ((symbol->option_2 >= 1) && (symbol->option_2 <= DMSIZESCOUNT)) {
        optionsize = intsymbol[symbol->option_2 - 1];
    } else {
        optionsize = -1;
................................................................................

    symbolsize = optionsize;
    if (calcsize > optionsize) {
        symbolsize = calcsize;
        if (optionsize != -1) {
            /* flag an error */
            error_number = ZINT_WARN_INVALID_OPTION;
            strcpy(symbol->errtxt, "Data does not fit in selected symbol size");
        }
    }

    // Now we know the symbol size we can handle the remaining data in the process buffer.
    symbols_left = matrixbytes[symbolsize] - binlen;
    binlen = dm200encode_remainder(binary, binlen, source, inputlen, last_mode, process_buffer, process_p, symbols_left);

................................................................................

    symbol->rows = H;
    symbol->width = W;

    return error_number;
}

int dmatrix(struct zint_symbol *symbol, unsigned char source[], const int length) {
    int error_number;

    if (symbol->option_1 <= 1) {
        /* ECC 200 */
        error_number = data_matrix_200(symbol, source, length);
    } else {
        /* ECC 000 - 140 */
        strcpy(symbol->errtxt, "Older Data Matrix standards are no longer supported");
        error_number = ZINT_ERROR_INVALID_OPTION;
    }

    return error_number;
}







>
>
>
>







 







|







 







|
|
|
|
|
|

|
|
|
|
|
|



|

|

|

|

|








|
|
|
|
|
|







 







|

|







 







|








>
>
>
>
>
>
>
>







 







|







 







|







 







|







 







|



|







 







|

|







 







|












>
>

<
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>







|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|


|






|
|







|


<





|







 







|







 







|




|


|





42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
...
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
...
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
...
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
...
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
...
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
...
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
...
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
....
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077

1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104































1105
1106
1107
1108
1109
1110
1111
....
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154

1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
....
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
....
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#ifdef _MSC_VER
#include <malloc.h>
/* ceilf (C99) not before MSVC++2013 (C++ 12.0) */
#if _MSC_VER < 1800
#define ceilf ceil
#endif
#endif
#include "reedsol.h"
#include "common.h"
#include "dmatrix.h"

/* Annex M placement alorithm low level */
static void ecc200placementbit(int *array, const int NR, const int NC, int r, int c, const int p, const char b) {
................................................................................
    int i;
    int nonX12Position = 0;
    int specialX12Position = 0;
    int retval = 0;

    for (i = position; i < sourcelen; i++) {
        if (nonX12Position == 0) {
            if (isX12(inputData[i]) != 1) {
                nonX12Position = i;
            }
        }

        if (specialX12Position == 0) {
            if ((inputData[i] == (char) 13) ||
                    (inputData[i] == '*') ||
................................................................................
    float ascii_count, c40_count, text_count, x12_count, edf_count, b256_count, best_count;
    int sp, best_scheme;

    best_scheme = DM_NULL;

    /* step (j) */
    if (current_mode == DM_ASCII) {
        ascii_count = 0.0F;
        c40_count = 1.0F;
        text_count = 1.0F;
        x12_count = 1.0F;
        edf_count = 1.0F;
        b256_count = 1.25F;
    } else {
        ascii_count = 1.0F;
        c40_count = 2.0F;
        text_count = 2.0F;
        x12_count = 2.0F;
        edf_count = 2.0F;
        b256_count = 2.25F;
    }

    switch (current_mode) {
        case DM_C40: c40_count = 0.0F;
            break;
        case DM_TEXT: text_count = 0.0F;
            break;
        case DM_X12: x12_count = 0.0F;
            break;
        case DM_EDIFACT: edf_count = 0.0F;
            break;
        case DM_BASE256: b256_count = 0.0F;
            break;
    }

    sp = position;

    do {
        if (sp == (sourcelen - 1)) {
            /* At the end of data ... step (k) */
            ascii_count = ceilf(ascii_count);
            b256_count = ceilf(b256_count);
            edf_count = ceilf(edf_count);
            text_count = ceilf(text_count);
            x12_count = ceilf(x12_count);
            c40_count = ceilf(c40_count);

            best_count = c40_count;
            best_scheme = DM_C40; // (k)(7)

            if (x12_count < best_count) {
                best_count = x12_count;
                best_scheme = DM_X12; // (k)(6)
................................................................................
        } else {

            /* ascii ... step (l) */
            if ((inputData[sp] >= '0') && (inputData[sp] <= '9')) {
                ascii_count += 0.5F; // (l)(1)
            } else {
                if (inputData[sp] > 127) {
                    ascii_count = ceilf(ascii_count) + 2.0F; // (l)(2)
                } else {
                    ascii_count = ceilf(ascii_count) + 1.0F; // (l)(3)
                }
            }

            /* c40 ... step (m) */
            if ((inputData[sp] == ' ') ||
                    (((inputData[sp] >= '0') && (inputData[sp] <= '9')) ||
                    ((inputData[sp] >= 'A') && (inputData[sp] <= 'Z')))) {
................................................................................
        tp++;
        strcat(binary, " ");
        if (debug) printf("FN1 ");
    } /* FNC1 */

    if (symbol->output_options & READER_INIT) {
        if (gs1) {
            strcpy(symbol->errtxt, "Cannot encode in GS1 mode and Reader Initialisation at the same time (E10)");
            return ZINT_ERROR_INVALID_OPTION;
        } else {
            target[tp] = 234;
            tp++; /* Reader Programming */
            strcat(binary, " ");
            if (debug) printf("RP ");
        }
    }

    if (symbol->eci > 3) {
        target[tp] = 241; /* ECI Character */
        tp++;
        target[tp] = (unsigned char) (symbol->eci + 1);
        tp++;
        if (debug) printf("ECI %d ", symbol->eci + 1);
    }

    /* Check for Macro05/Macro06 */
    /* "[)>[RS]05[GS]...[RS][EOT]" -> CW 236 */
    /* "[)>[RS]06[GS]...[RS][EOT]" -> CW 237 */
    if (tp == 0 && sp == 0 && inputlen >= 9
            && source[0] == '[' && source[1] == ')' && source[2] == '>'
            && source[3] == '\x1e' && source[4] == '0'
................................................................................
                process_buffer[*process_p] = value;
                (*process_p)++;

                if (*process_p >= 3) {
                    int iv;

                    iv = (1600 * process_buffer[0]) + (40 * process_buffer[1]) + (process_buffer[2]) + 1;
                    target[tp] = (unsigned char) (iv / 256);
                    tp++;
                    target[tp] = iv % 256;
                    tp++;
                    strcat(binary, "  ");
                    if (debug) printf("[%d %d %d] ", process_buffer[0], process_buffer[1], process_buffer[2]);

                    process_buffer[0] = process_buffer[3];
................................................................................
                process_buffer[*process_p] = value;
                (*process_p)++;

                if (*process_p >= 3) {
                    int iv;

                    iv = (1600 * process_buffer[0]) + (40 * process_buffer[1]) + (process_buffer[2]) + 1;
                    target[tp] = (unsigned char) (iv / 256);
                    tp++;
                    target[tp] = iv % 256;
                    tp++;
                    strcat(binary, "  ");
                    if (debug) printf("[%d %d %d] ", process_buffer[0], process_buffer[1], process_buffer[2]);

                    process_buffer[0] = process_buffer[3];
................................................................................
                process_buffer[*process_p] = value;
                (*process_p)++;

                if (*process_p >= 3) {
                    int iv;

                    iv = (1600 * process_buffer[0]) + (40 * process_buffer[1]) + (process_buffer[2]) + 1;
                    target[tp] = (unsigned char) (iv / 256);
                    tp++;
                    target[tp] = iv % 256;
                    tp++;
                    strcat(binary, "  ");
                    if (debug) printf("[%d %d %d] ", process_buffer[0], process_buffer[1], process_buffer[2]);

                    process_buffer[0] = process_buffer[3];
................................................................................

                process_buffer[*process_p] = value;
                (*process_p)++;
                sp++;
            }

            if (*process_p >= 4) {
                target[tp] = (unsigned char) ((process_buffer[0] << 2) + ((process_buffer[1] & 0x30) >> 4));
                tp++;
                target[tp] = ((process_buffer[1] & 0x0f) << 4) + ((process_buffer[2] & 0x3c) >> 2);
                tp++;
                target[tp] = (unsigned char) (((process_buffer[2] & 0x03) << 6) + process_buffer[3]);
                tp++;
                strcat(binary, "   ");
                if (debug) printf("[%d %d %d %d] ", process_buffer[0], process_buffer[1], process_buffer[2], process_buffer[3]);

                process_buffer[0] = process_buffer[4];
                process_buffer[1] = process_buffer[5];
                process_buffer[2] = process_buffer[6];
................................................................................
    for (i = 0; i < tp; i++) {
        if (binary[i] == 'b') {
            int prn, temp;

            prn = ((149 * (i + 1)) % 255) + 1;
            temp = target[i] + prn;
            if (temp <= 255) {
                target[i] = (unsigned char) (temp);
            } else {
                target[i] = (unsigned char) (temp - 256);
            }
        }
    }

    *(last_mode) = current_mode;
    return tp;
}
................................................................................
                    target[target_length] = source[inputlen - 1] + 1;
                    target_length++;
                }
            }
            break;

        case DM_EDIFACT:
            if (symbols_left <= 2) // Unlatch not required!
            {
                if (process_p == 1) {
                    target[target_length] = source[inputlen - 1] + 1;
                    target_length++;
                }

                if (process_p == 2) {
                    target[target_length] = source[inputlen - 2] + 1;
                    target_length++;
                    target[target_length] = source[inputlen - 1] + 1;
                    target_length++;
                }
            } else {
                // Append edifact unlatch value (31) and encode as triple.


                if (process_p == 1) {
                    target[target_length] = (unsigned char) ((process_buffer[0] << 2) + ((31 & 0x30) >> 4));
                    target_length++;
                    target[target_length] = (unsigned char) ((31 & 0x0f) << 4);
                    target_length++;
                    target[target_length] = (unsigned char) 0;
                    target_length++;
                }

                if (process_p == 2) {
                    target[target_length] = (unsigned char) ((process_buffer[0] << 2) + ((process_buffer[1] & 0x30) >> 4));
                    target_length++;
                    target[target_length] = (unsigned char) (((process_buffer[1] & 0x0f) << 4) + ((31 & 0x3c) >> 2));
                    target_length++;
                    target[target_length] = (unsigned char) (((31 & 0x03) << 6));
                    target_length++;
                }

                if (process_p == 3) {
                    target[target_length] = (unsigned char) ((process_buffer[0] << 2) + ((process_buffer[1] & 0x30) >> 4));
                    target_length++;
                    target[target_length] = (unsigned char) (((process_buffer[1] & 0x0f) << 4) + ((process_buffer[2] & 0x3c) >> 2));
                    target_length++;
                    target[target_length] = (unsigned char) (((process_buffer[2] & 0x03) << 6) + 31);
                    target_length++;
                }
































            }
            break;
    }

    if (debug) {
        int i;
        printf("\n\n");
................................................................................
        if (i == tail_length) {
            target[tp] = 129;
            tp++; /* Pad */
        } else {
            prn = ((149 * (tp + 1)) % 253) + 1;
            temp = 129 + prn;
            if (temp <= 254) {
                target[tp] = (unsigned char) (temp);
                tp++;
            } else {
                target[tp] = (unsigned char) (temp - 254);
                tp++;
            }
        }
    }
}

int data_matrix_200(struct zint_symbol *symbol, const unsigned char source[], const int in_length) {
    int i, inputlen = in_length, skew = 0;
    unsigned char binary[2200];
    int binlen;
    int process_buffer[8]; /* holds remaining data to finalised */
    int process_p; /* number of characters left to finalise */
    int symbolsize, optionsize, calcsize;
    int taillength, error_number = 0;
    int H, W, FH, FW, datablock, bytes, rsblock;
    int last_mode = DM_ASCII;
    unsigned char *grid = 0;
    int symbols_left;


    /* inputlen may be decremented by 2 if macro character is used */
    binlen = dm200encode(symbol, source, binary, &last_mode, &inputlen, process_buffer, &process_p);

    if (binlen == 0) {
        strcpy(symbol->errtxt, "Data too long to fit in symbol (E11)");
        return ZINT_ERROR_TOO_LONG;
    }

    if ((symbol->option_2 >= 1) && (symbol->option_2 <= DMSIZESCOUNT)) {
        optionsize = intsymbol[symbol->option_2 - 1];
    } else {
        optionsize = -1;
................................................................................

    symbolsize = optionsize;
    if (calcsize > optionsize) {
        symbolsize = calcsize;
        if (optionsize != -1) {
            /* flag an error */
            error_number = ZINT_WARN_INVALID_OPTION;
            strcpy(symbol->errtxt, "Data does not fit in selected symbol size (E12)");
        }
    }

    // Now we know the symbol size we can handle the remaining data in the process buffer.
    symbols_left = matrixbytes[symbolsize] - binlen;
    binlen = dm200encode_remainder(binary, binlen, source, inputlen, last_mode, process_buffer, process_p, symbols_left);

................................................................................

    symbol->rows = H;
    symbol->width = W;

    return error_number;
}

int dmatrix(struct zint_symbol *symbol, const unsigned char source[], const int in_length) {
    int error_number;

    if (symbol->option_1 <= 1) {
        /* ECC 200 */
        error_number = data_matrix_200(symbol, source, in_length);
    } else {
        /* ECC 000 - 140 */
        strcpy(symbol->errtxt, "Older Data Matrix standards are no longer supported (E13)");
        error_number = ZINT_ERROR_INVALID_OPTION;
    }

    return error_number;
}

Changes to jni/zint/backend/dmatrix.h.

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

#ifndef __IEC16022ECC200_H
#define __IEC16022ECC200_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

    extern int data_matrix_200(struct zint_symbol *symbol, unsigned char source[], const int length);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#define MAXBARCODE 3116








|







40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

#ifndef __IEC16022ECC200_H
#define __IEC16022ECC200_H
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

    extern int data_matrix_200(struct zint_symbol *symbol, const unsigned char source[], const int length);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#define MAXBARCODE 3116

Added jni/zint/backend/dotcode.c.



























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
/* dotcode.c - Handles DotCode */

/*
    libzint - the open source barcode library
    Copyright (C) 2016 Robin Stuart <rstuart114@gmail.com>

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

    1. Redistributions of source code must retain the above copyright 
       notice, this list of conditions and the following disclaimer.  
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.  
    3. Neither the name of the project nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission. 

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
    SUCH DAMAGE.    
 */

/* 
 * Attempts to encode DotCode according to AIMD013 Rev 1.34a, dated Feb 19, 2009
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#ifndef _MSC_VER
#include <stdint.h>
#else
#include "ms_stdint.h"
#include <malloc.h>
#endif
#include "common.h"
#include "gs1.h"

#define GF 113
#define PM 3

/* DotCode symbol character dot patterns, from Annex C */
static const int dot_patterns[113] = {
    0x155, 0x0ab, 0x0ad, 0x0b5, 0x0d5, 0x156, 0x15a, 0x16a, 0x1aa, 0x0ae,
    0x0b6, 0x0ba, 0x0d6, 0x0da, 0x0ea, 0x12b, 0x12d, 0x135, 0x14b, 0x14d,
    0x153, 0x159, 0x165, 0x169, 0x195, 0x1a5, 0x1a9, 0x057, 0x05b, 0x05d,
    0x06b, 0x06d, 0x075, 0x097, 0x09b, 0x09d, 0x0a7, 0x0b3, 0x0b9, 0x0cb,
    0x0cd, 0x0d3, 0x0d9, 0x0e5, 0x0e9, 0x12e, 0x136, 0x13a, 0x14e, 0x15c,
    0x166, 0x16c, 0x172, 0x174, 0x196, 0x19a, 0x1a6, 0x1ac, 0x1b2, 0x1b4,
    0x1ca, 0x1d2, 0x1d4, 0x05e, 0x06e, 0x076, 0x07a, 0x09e, 0x0bc, 0x0ce,
    0x0dc, 0x0e6, 0x0ec, 0x0f2, 0x0f4, 0x117, 0x11b, 0x11d, 0x127, 0x133,
    0x139, 0x147, 0x163, 0x171, 0x18b, 0x18d, 0x193, 0x199, 0x1a3, 0x1b1,
    0x1c5, 0x1c9, 0x1d1, 0x02f, 0x037, 0x03b, 0x03d, 0x04f, 0x067, 0x073,
    0x079, 0x08f, 0x0c7, 0x0e3, 0x0f1, 0x11e, 0x13c, 0x178, 0x18e, 0x19c,
    0x1b8, 0x1c6, 0x1cc
};

int get_dot(char Dots[], int Hgt, int Wid, int x, int y) {
    int retval = 0;

    if ((x >= 0) && (x < Wid) && (y >= 0) && (y < Hgt)) {
        if (Dots[(y * Wid) + x] == '1') {
            retval = 1;
        }
    }

    return retval;
}

/* Dot pattern scoring routine from Annex A */
int score_array(char Dots[], int Hgt, int Wid) {
    int x, y, worstedge, first, last, sum;

    sum = 0;
    first = -1;
    last = -1;

    // across the top edge, count printed dots and measure their extent
    for (x = 0; x < Wid; x += 2)
        if (get_dot(Dots, Hgt, Wid, x, 0)) {
            if (first < 0) {
                first = x;
            }
            last = x;
            sum++;
        }
    worstedge = sum + last - first;
    worstedge *= Hgt;

    sum = 0;
    first = -1;

    //across the bottom edge, ditto
    for (x = Wid & 1; x < Wid; x += 2)
        if (get_dot(Dots, Hgt, Wid, x, Hgt - 1)) {
            if (first < 0) {
                first = x;
            }
            last = x;
            sum++;
        }
    sum += last - first;
    sum *= Hgt;
    if (sum < worstedge) {
        worstedge = sum;
    }

    sum = 0;
    first = -1;

    //down the left edge, ditto
    for (y = 0; y < Hgt; y += 2)
        if (get_dot(Dots, Hgt, Wid, 0, y)) {
            if (first < 0) {
                first = y;
            }
            last = y;
            sum++;
        }
    sum += last - first;
    sum *= Wid;
    if (sum < worstedge) {
        worstedge = sum;
    }

    sum = 0;
    first = -1;

    //down the right edge, ditto
    for (y = Hgt & 1; y < Hgt; y += 2)
        if (get_dot(Dots, Hgt, Wid, Wid - 1, y)) {
            if (first < 0) {
                first = y;
            }
            last = y;
            sum++;
        }
    sum += last - first;
    sum *= Wid;
    if (sum < worstedge) {
        worstedge = sum;
    }

    // throughout the array, count the # of unprinted 5-somes (cross patterns)
    // plus the # of printed dots surrounded by 8 unprinted neighbors
    sum = 0;
    for (y = 0; y < Hgt; y++) {
        for (x = y & 1; x < Wid; x += 2) {
            if ((!get_dot(Dots, Hgt, Wid, x - 1, y - 1))
                    && (!get_dot(Dots, Hgt, Wid, x + 1, y - 1))
                    && (!get_dot(Dots, Hgt, Wid, x - 1, y + 1))
                    && (!get_dot(Dots, Hgt, Wid, x + 1, y + 1))
                    && ((!get_dot(Dots, Hgt, Wid, x, y))
                    || ((!get_dot(Dots, Hgt, Wid, x - 2, y))
                    && (!get_dot(Dots, Hgt, Wid, x, y - 2))
                    && (!get_dot(Dots, Hgt, Wid, x + 2, y))
                    && (!get_dot(Dots, Hgt, Wid, x, y + 2))))) {
                sum++;
            }
        }
    }

    return (worstedge - sum * sum);
}

//-------------------------------------------------------------------------
// "rsencode(nd,nc)" adds "nc" R-S check words to "nd" data words in wd[]
// employing Galois Field GF, where GF is prime, with a prime modulus of PM
//-------------------------------------------------------------------------

void rsencode(int nd, int nc, unsigned char *wd) {
    int i, j, k, nw, start, step, root[GF], c[GF];

    // Start by generating "nc" roots (antilogs):
    root[0] = 1;
    for (i = 1; i <= nc; i++)
        root[i] = (PM * root[i - 1]) % GF;

    // Here we compute how many interleaved R-S blocks will be needed
    nw = nd + nc;
    step = (nw + GF - 2) / (GF - 1);

    // ...& then for each such block:
    for (start = 0; start < step; start++) {
        int ND = (nd - start + step - 1) / step, NW = (nw - start + step - 1) / step, NC = NW - ND;

        // first compute the generator polynomial "c" of order "NC":
        for (i = 1; i <= NC; i++)
            c[i] = 0;
        c[0] = 1;

        for (i = 1; i <= NC; i++) {
            for (j = NC; j >= 1; j--) {
                c[j] = (GF + c[j] - (root[i] * c[j - 1]) % GF) % GF;
            }
        }

        // & then compute the corresponding checkword values into wd[]
        // ... (a) starting at wd[start] & (b) stepping by step
        for (i = ND; i < NW; i++)
            wd[start + i * step] = 0;
        for (i = 0; i < ND; i++) {
            k = (wd[start + i * step] + wd[start + ND * step]) % GF;
            for (j = 0; j < NC - 1; j++) {
                wd[start + (ND + j) * step] = (GF - ((c[j + 1] * k) % GF) + wd[start + (ND + j + 1) * step]) % GF;
            }
            wd[start + (ND + NC - 1) * step] = (GF - ((c[NC] * k) % GF)) % GF;
        }
        for (i = ND; i < NW; i++)
            wd[start + i * step] = (GF - wd[start + i * step]) % GF;
    }
}

/* Check if the next character is directly encodable in code set A (Annex F.II.D) */
int datum_a(const unsigned char source[], int position, int length) {
    int retval = 0;

    if (position < length) {
        if (source[position] <= 95) {
            retval = 1;
        }
    }

    return retval;
}

/* Check if the next character is directly encodable in code set B (Annex F.II.D) */
int datum_b(const unsigned char source[], int position, int length) {
    int retval = 0;

    if (position < length) {
        if (source[position] >= 32) {
            retval = 1;
        }

        switch (source[position]) {
            case 9: // HT
            case 28: // FS
            case 29: // GS
            case 30: // RS
                retval = 1;
        }

        if (position != length - 2) {
            if ((source[position] == 13) && (source[position + 1] == 10)) { // CRLF
                retval = 1;
            }
        }
    }

    return retval;
}

/* Check if the next characters are directly encodable in code set C (Annex F.II.D) */
int datum_c(const unsigned char source[], int position, int length) {
    int retval = 0;

    if (position < length - 2) {
        if (((source[position] >= '0') && (source[position] <= '9'))
                && ((source[position + 1] >= '0') && (source[position + 1] <= '9')))
            retval = 1;
    }

    return retval;
}

/* Returns how many consecutive digits lie immediately ahead (Annex F.II.A) */
int n_digits(const unsigned char source[], int position, int length) {
    int i;

    for (i = position; ((source[i] >= '0') && (source[i] <= '9')) && (i < length); i++);

    return i - position;
}

/* checks ahead for 10 or more digits starting "17xxxxxx10..." (Annex F.II.B) */
int seventeen_ten(const unsigned char source[], int position, int length) {
    int found = 0;

    if (n_digits(source, position, length) >= 10) {
        if (((source[position] == '1') && (source[position + 1] == '7'))
                && ((source[position + 8] == '1') && (source[position + 9] == '0'))) {
            found = 1;
        }
    }

    return found;
}

/*  checks how many characters ahead can be reached while datum_c is true,
 *  returning the resulting number of codewords (Annex F.II.E)
 */
int ahead_c(const unsigned char source[], int position, int length) {
    int count = 0;
    int i;

    for (i = position; (i < length) && datum_c(source, i, length); i += 2) {
        count++;
    }

    return count;
}

/* Annex F.II.F */
int try_c(const unsigned char source[], int position, int length) {
    int retval = 0;

    if (n_digits(source, position, length) > 0) {
        if (ahead_c(source, position, length) > ahead_c(source, position + 1, length)) {
            retval = ahead_c(source, position, length);
        }
    }

    return retval;
}

/* Annex F.II.G */
int ahead_a(const unsigned char source[], int position, int length) {
    int count = 0;
    int i;

    for (i = position; ((i < length) && datum_a(source, i, length))
            && (try_c(source, i, length) < 2); i++) {
        count++;
    }

    return count;
}

/* Annex F.II.H */
int ahead_b(const unsigned char source[], int position, int length) {
    int count = 0;
    int i;

    for (i = position; ((i < length) && datum_b(source, i, length))
            && (try_c(source, i, length) < 2); i++) {
        count++;
    }

    return count;
}

/* checks if the next character is in the range 128 to 255  (Annex F.II.I) */
int binary(const unsigned char source[], int position, int length) {
    int retval = 0;

    if (source[position] >= 128) {
        retval = 1;
    }

    return retval;
}

/* Analyse input data stream and encode using algorithm from Annex F */
int dotcode_encode_message(struct zint_symbol *symbol, const unsigned char source[], int length, unsigned char *codeword_array) {
    int input_position, array_length, i;
    char encoding_mode;
    int inside_macro, done;
    int debug = 0;
    int binary_buffer_size = 0;
    int lawrencium[6]; // Reversed radix 103 values

#if defined(_MSC_VER) && _MSC_VER == 1200
    uint64_t binary_buffer = 0;
#else
    uint64_t binary_buffer = 0ULL;
#endif

    input_position = 0;
    array_length = 0;
    encoding_mode = 'C';
    inside_macro = 0;

    if (symbol->output_options & READER_INIT) {
        codeword_array[array_length] = 109; // FNC3
        array_length++;
    }

    if (symbol->input_mode != GS1_MODE) {
        codeword_array[array_length] = 107; // FNC1
        array_length++;
    }

    if (symbol->eci > 3) {
        codeword_array[array_length] = 108; // FNC2
        array_length++;
        codeword_array[array_length] = symbol->eci;
        array_length++;
    }

    do {
        done = 0;

        /* Step A */
        if ((input_position == length - 2) && (inside_macro != 0) && (inside_macro != 100)) {
            // inside_macro only gets set to 97, 98 or 99 if the last two characters are RS/EOT
            input_position += 2;
            done = 1;
            if (debug) {
                printf("A ");
            }
        }

        if ((input_position == length - 1) && (inside_macro == 100)) {
            // inside_macro only gets set to 100 if the last character is EOT
            input_position++;
            done = 1;
            if (debug) {
                printf("A ");
            }
        }

        /* Step B1 */
        if ((!done) && (encoding_mode == 'C')) {
            if ((array_length == 0) && (length > 9)) {
                if ((source[input_position] == '[')
                        && (source[input_position + 1] == ')')
                        && (source[input_position + 2] == '>')
                        && (source[input_position + 3] == 30) // RS
                        && (source[length - 1] == 04)) { // EOT

                    codeword_array[array_length] = 106; // Latch B
                    array_length++;
                    encoding_mode = 'B';

                    if ((source[input_position + 6] == 29) && (source[length - 2] == 30)) { // GS/RS
                        if ((source[input_position + 4] == '0') && (source[input_position + 5] == '5')) {
                            codeword_array[array_length] = 97; // Macro
                            array_length++;
                            input_position += 7;
                            inside_macro = 97;
                            done = 1;
                            if (debug) {
                                printf("B1/1 ");
                            }
                        }

                        if ((source[input_position + 4] == '0') && (source[input_position + 5] == '6')) {
                            codeword_array[array_length] = 98; // Macro
                            array_length++;
                            input_position += 7;
                            inside_macro = 98;
                            done = 1;
                            if (debug) {
                                printf("B1/2 ");
                            }
                        }

                        if ((source[input_position + 4] == '1') && (source[input_position + 5] == '2')) {
                            codeword_array[array_length] = 99; // Macro
                            array_length++;
                            input_position += 7;
                            inside_macro = 99;
                            done = 1;
                            if (debug) {
                                printf("B1/3 ");
                            }
                        }
                    }

                    if (!done) {
                        codeword_array[array_length] = 100; // Macro
                        array_length++;
                        input_position += 4;
                        inside_macro = 100;
                        done = 1;
                        if (debug) {
                            printf("B1/4 ");
                        }
                    }
                }
            }
        }

        /* Step B2 */
        if ((!done) && (encoding_mode == 'C')) {
            if (seventeen_ten(source, input_position, length)) {
                codeword_array[array_length] = 100; // (17)...(10)
                array_length++;
                codeword_array[array_length] = ((source[input_position + 2] - '0') * 10) + (source[input_position + 3] - '0');
                array_length++;
                codeword_array[array_length] = ((source[input_position + 4] - '0') * 10) + (source[input_position + 5] - '0');
                array_length++;
                codeword_array[array_length] = ((source[input_position + 6] - '0') * 10) + (source[input_position + 7] - '0');
                array_length++;
                input_position += 10;
                done = 1;
                if (debug) {
                    printf("B2/1 ");
                }
            }
        }

        if ((!done) && (encoding_mode == 'C')) {
            if (datum_c(source, input_position, length) || ((source[input_position] == '[') && (symbol->input_mode == GS1_MODE))) {
                if (source[input_position] == '[') {
                    codeword_array[array_length] = 107; // FNC1
                    input_position++;
                } else {
                    codeword_array[array_length] = ((source[input_position] - '0') * 10) + (source[input_position + 1] - '0');
                    input_position += 2;
                }
                array_length++;
                done = 1;
                if (debug) {
                    printf("B2/2 ");
                }
            }
        }

        /* Setp B3 */
        if ((!done) && (encoding_mode == 'C')) {
            if (binary(source, input_position, length)) {
                if (n_digits(source, input_position + 1, length) > 0) {
                    if ((source[input_position] - 128) < 32) {
                        codeword_array[array_length] = 110; // Bin Shift A
                        array_length++;
                        codeword_array[array_length] = source[input_position] - 128 + 64;
                        array_length++;
                    } else {
                        codeword_array[array_length] = 111; // Bin Shift B
                        array_length++;
                        codeword_array[array_length] = source[input_position] - 128 - 32;
                        array_length++;
                    }
                    input_position++;
                } else {
                    codeword_array[array_length] = 112; // Bin Latch
                    array_length++;
                    encoding_mode = 'X';
                }
                done = 1;
                if (debug) {
                    printf("B3 ");
                }
            }
        }

        /* Step B4 */
        if ((!done) && (encoding_mode == 'C')) {
            int m = ahead_a(source, input_position, length);
            int n = ahead_b(source, input_position, length);
            if (m > n) {
                codeword_array[array_length] = 101; // Latch A
                array_length++;
                encoding_mode = 'A';
            } else {
                if (n <= 4) {
                    codeword_array[array_length] = 101 + n; // nx Shift B
                    array_length++;

                    for (i = 0; i < n; i++) {
                        codeword_array[array_length] = source[input_position] - 32;
                        array_length++;
                        input_position++;
                    }
                } else {
                    codeword_array[array_length] = 106; // Latch B
                    array_length++;
                    encoding_mode = 'B';
                }
            }
            done = 1;
            if (debug) {
                printf("B4 ");
            }
        }

        /* Step C1 */
        if ((!done) && (encoding_mode == 'B')) {
            int n = try_c(source, input_position, length);

            if (n >= 2) {
                if (n <= 4) {
                    codeword_array[array_length] = 103 + (n - 2); // nx Shift C
                    array_length++;
                    for (i = 0; i < n; i++) {
                        codeword_array[array_length] = ((source[input_position] - '0') * 10) + (source[input_position + 1] - '0');
                        array_length++;
                        input_position += 2;
                    }
                } else {
                    codeword_array[array_length] = 106; // Latch C
                    array_length++;
                    encoding_mode = 'C';
                }
                done = 1;
                if (debug) {
                    printf("C1 ");
                }
            }
        }

        /* Step C2 */
        if ((!done) && (encoding_mode == 'B')) {
            if ((source[input_position] == '[') && (symbol->input_mode == GS1_MODE)) {
                codeword_array[array_length] = 107; // FNC1
                array_length++;
                input_position++;
                done = 1;
                if (debug) {
                    printf("C2/1 ");
                }
            } else {
                if (datum_b(source, input_position, length)) {
                    codeword_array[array_length] = source[input_position] - 32;
                    array_length++;
                    input_position++;
                    done = 1;
                    if (debug) {
                        printf("C2/2 ");
                    }
                }
            }
        }

        /* Step C3 */
        if ((!done) && (encoding_mode == 'B')) {
            if (binary(source, input_position, length)) {
                if (datum_b(source, input_position + 1, length)) {
                    if ((source[input_position] - 128) < 32) {
                        codeword_array[array_length] = 110; // Bin Shift A
                        array_length++;
                        codeword_array[array_length] = source[input_position] - 128 + 64;
                        array_length++;
                    } else {
                        codeword_array[array_length] = 111; // Bin Shift B
                        array_length++;
                        codeword_array[array_length] = source[input_position] - 128 - 32;
                        array_length++;
                    }
                    input_position++;
                } else {
                    codeword_array[array_length] = 112; // Bin Latch
                    array_length++;
                    encoding_mode = 'X';
                }
                done = 1;
                if (debug) {
                    printf("C3 ");
                }
            }
        }

        /* Step C4 */
        if ((!done) && (encoding_mode == 'B')) {
            if (ahead_a(source, input_position, length) == 1) {
                codeword_array[array_length] = 101; // Shift A
                array_length++;
                if (source[input_position] < 32) {
                    codeword_array[array_length] = source[input_position] + 64;
                } else {
                    codeword_array[array_length] = source[input_position] - 32;
                }
                array_length++;
                input_position++;
            } else {
                codeword_array[array_length] = 102; // Latch A
                array_length++;
                encoding_mode = 'A';
            }
            done = 1;
            if (debug) {
                printf("C4 ");
            }
        }

        /* Step D1 */
        if ((!done) && (encoding_mode == 'A')) {
            int n = try_c(source, input_position, length);
            if (n >= 2) {
                if (n <= 4) {
                    codeword_array[array_length] = 103 + (n - 2); // nx Shift C
                    array_length++;
                    for (i = 0; i < n; i++) {
                        codeword_array[array_length] = ((source[input_position] - '0') * 10) + (source[input_position + 1] - '0');
                        array_length++;
                        input_position += 2;
                    }
                } else {
                    codeword_array[array_length] = 106; // Latch C
                    array_length++;
                    encoding_mode = 'C';
                }
                done = 1;
                if (debug) {
                    printf("D1 ");
                }
            }
        }

        /* Step D2 */
        if ((!done) && (encoding_mode == 'A')) {
            if ((source[input_position] == '[') && (symbol->input_mode == GS1_MODE)) {
                codeword_array[array_length] = 107; // FNC1
                array_length++;
                input_position++;
                done = 1;
                if (debug) {
                    printf("D2/1 ");
                }
            } else {
                if (datum_a(source, input_position, length)) {
                    if (source[input_position] < 32) {
                        codeword_array[array_length] = source[input_position] + 64;
                    } else {
                        codeword_array[array_length] = source[input_position] - 32;
                    }
                    array_length++;
                    input_position++;
                    done = 1;
                    if (debug) {
                        printf("D2/2 ");
                    }
                }
            }
        }

        /* Step D3 */
        if ((!done) && (encoding_mode == 'A')) {
            if (binary(source, input_position, length)) {
                if (datum_a(source, input_position + 1, length)) {
                    if ((source[input_position] - 128) < 32) {
                        codeword_array[array_length] = 110; // Bin Shift A
                        array_length++;
                        codeword_array[array_length] = source[input_position] - 128 + 64;
                        array_length++;
                    } else {
                        codeword_array[array_length] = 111; // Bin Shift B
                        array_length++;
                        codeword_array[array_length] = source[input_position] - 128 - 32;
                        array_length++;
                    }
                    input_position++;
                } else {
                    codeword_array[array_length] = 112; // Bin Latch
                    array_length++;
                    encoding_mode = 'X';
                }
                done = 1;
                if (debug) {
                    printf("D3 ");
                }
            }
        }

        /* Step D4 */
        if ((!done) && (encoding_mode == 'A')) {
            int n = ahead_b(source, input_position, length);

            if (n <= 6) {
                codeword_array[array_length] = 95 + n; // nx Shift B
                array_length++;
                for (i = 0; i < n; i++) {
                    codeword_array[array_length] = source[input_position] - 32;
                    array_length++;
                    input_position++;
                }
            } else {
                codeword_array[array_length] = 102; // Latch B
                array_length++;
                encoding_mode = 'B';
            }
            done = 1;
            if (debug) {
                printf("D4 ");
            }
        }

        /* Step E1 */
        if ((!done) && (encoding_mode == 'X')) {
            int n = try_c(source, input_position, length);

            if (n >= 2) {
                /* Empty binary buffer */
                for (i = 0; i < (binary_buffer_size + 1); i++) {
                    lawrencium[i] = binary_buffer % 103;
                    binary_buffer /= 103;
                }

                for (i = 0; i < (binary_buffer_size + 1); i++) {
                    codeword_array[array_length] = lawrencium[binary_buffer_size - i];
                    array_length++;
                }
                binary_buffer = 0;
                binary_buffer_size = 0;

                if (n <= 7) {
                    codeword_array[array_length] = 101 + n; // Interrupt for nx Shift C
                    array_length++;
                    for (i = 0; i < n; i++) {
                        codeword_array[array_length] = ((source[input_position] - '0') * 10) + (source[input_position + 1] - '0');
                        array_length++;
                        input_position += 2;
                    }
                } else {
                    codeword_array[array_length] = 111; // Terminate with Latch to C
                    array_length++;
                    encoding_mode = 'C';
                }
                done = 1;
                if (debug) {
                    printf("E1 ");
                }
            }
        }

        /* Step E2 */
        /* Section 5.2.1.1 para D.2.i states:
         * "Groups of six codewords, each valued between 0 and 102, are radix converted from
         * base 103 into five base 259 values..."
         */
        if ((!done) && (encoding_mode == 'X')) {
            if (binary(source, input_position, length)
                    || binary(source, input_position + 1, length)
                    || binary(source, input_position + 2, length)
                    || binary(source, input_position + 3, length)) {
                binary_buffer *= 259;
                binary_buffer += source[input_position];
                binary_buffer_size++;

                if (binary_buffer_size == 5) {
                    for (i = 0; i < 6; i++) {
                        lawrencium[i] = binary_buffer % 103;
                        binary_buffer /= 103;
                    }

                    for (i = 0; i < 6; i++) {
                        codeword_array[array_length] = lawrencium[5 - i];
                        array_length++;
                    }
                    binary_buffer = 0;
                    binary_buffer_size = 0;
                }
                input_position++;
                done = 1;
                if (debug) {
                    printf("E2 ");
                }
            }
        }

        /* Step E3 */
        if ((!done) && (encoding_mode == 'X')) {
            /* Empty binary buffer */
            for (i = 0; i < (binary_buffer_size + 1); i++) {
                lawrencium[i] = binary_buffer % 103;
                binary_buffer /= 103;
            }

            for (i = 0; i < (binary_buffer_size + 1); i++) {
                codeword_array[array_length] = lawrencium[binary_buffer_size - i];
                array_length++;
            }
            binary_buffer = 0;
            binary_buffer_size = 0;

            if (ahead_a(source, input_position, length) > ahead_b(source, input_position, length)) {
                codeword_array[array_length] = 109; // Terminate with Latch to A
                encoding_mode = 'A';
            } else {
                codeword_array[array_length] = 110; // Terminate with Latch to B
                encoding_mode = 'B';
            }
            array_length++;
            done = 1;
            if (debug) {
                printf("E3 ");
            }
        }
    } while (input_position < length);

    if (debug) {
        printf("\n\n");
    }

    return array_length;
}

/* Convert codewords to binary data stream */
static size_t make_dotstream(unsigned char masked_array[], int array_length, char dot_stream[]) {
    int i, j;
    int mask = 0x100;

    dot_stream[0] = '\0';

    /* Mask value is encoded as two dots */
    switch (masked_array[0]) {
        case 0:
            strcat(dot_stream, "00");
            break;
        case 1:
            strcat(dot_stream, "01");
            break;
        case 2:
            strcat(dot_stream, "10");
            break;
        case 3:
            strcat(dot_stream, "11");
            break;
    }

    /* The rest of the data uses 9-bit dot patterns from Annex C */
    for (i = 1; i < array_length; i++) {
        for (j = 0; j < 9; j++) {
            if (dot_patterns[masked_array[i]] & (mask >> j)) {
                strcat(dot_stream, "1");
            } else {
                strcat(dot_stream, "0");
            }
        }
    }

    return strlen(dot_stream);
}

/* Determines if a given dot is a reserved corner dot 
 * to be used by one of the last six bits 
 */
int is_corner(int column, int row, int width, int height) {
    int corner = 0;

    /* Top Left */
    if ((column == 0) && (row == 0)) {
        corner = 1;
    }

    /* Top Right */
    if (height % 2) {
        if (((column == width - 2) && (row == 0))
                || ((column == width - 1) && (row == 1))) {
            corner = 1;
        }
    } else {
        if ((column == width - 1) && (row == 0)) {
            corner = 1;
        }
    }

    /* Bottom Left */
    if (height % 2) {
        if ((column == 0) && (row == height - 1)) {
            corner = 1;
        }
    } else {
        if (((column == 0) && (row == height - 2))
                || ((column == 1) && (row == height - 1))) {
            corner = 1;
        }
    }

    /* Bottom Right */
    if (((column == width - 2) && (row == height - 1))
            || ((column == width - 1) && (row == height - 2))) {
        corner = 1;
    }

    return corner;
}

/* Place the dots in the symbol*/
void fold_dotstream(char dot_stream[], int width, int height, char dot_array[]) {
    int column, row;
    int input_position = 0;

    if (height % 2) {
        /* Horizontal folding */
        for (row = 0; row < height; row++) {
            for (column = 0; column < width; column++) {
                if (!((column + row) % 2)) {
                    if (is_corner(column, row, width, height)) {
                        dot_array[(row * width) + column] = 'C';
                    } else {
                        dot_array[((height - row - 1) * width) + column] = dot_stream[input_position];
                        input_position++;
                    }
                } else {
                    dot_array[((height - row - 1) * width) + column] = ' '; // Non-data position
                }
            }
        }

        /* Corners */
        dot_array[width - 2] = dot_stream[input_position];
        input_position++;
        dot_array[(height * width) - 2] = dot_stream[input_position];
        input_position++;
        dot_array[(width * 2) - 1] = dot_stream[input_position];
        input_position++;
        dot_array[((height - 1) * width) - 1] = dot_stream[input_position];
        input_position++;
        dot_array[0] = dot_stream[input_position];
        input_position++;
        dot_array[(height - 1) * width] = dot_stream[input_position];
    } else {
        /* Vertical folding */
        for (column = 0; column < width; column++) {
            for (row = 0; row < height; row++) {
                if (!((column + row) % 2)) {
                    if (is_corner(column, row, width, height)) {
                        dot_array[(row * width) + column] = 'C';
                    } else {
                        dot_array[(row * width) + column] = dot_stream[input_position];
                        input_position++;
                    }
                } else {
                    dot_array[(row * width) + column] = ' '; // Non-data position
                }
            }
        }

        /* Corners */
        dot_array[((height - 1) * width) - 1] = dot_stream[input_position];
        input_position++;
        dot_array[(height - 2) * width] = dot_stream[input_position];
        input_position++;
        dot_array[(height * width) - 2] = dot_stream[input_position];
        input_position++;
        dot_array[((height - 1) * width) + 1] = dot_stream[input_position];
        input_position++;
        dot_array[width - 1] = dot_stream[input_position];
        input_position++;
        dot_array[0] = dot_stream[input_position];
    }
}

int dotcode(struct zint_symbol *symbol, const unsigned char source[], int length) {
    int i, j, k;
    size_t jc;
    int data_length, ecc_length;
    int min_dots, n_dots;
    int height, width, pad_chars;
    int mask_score[4];
    int weight;
    size_t dot_stream_length;
    int high_score, best_mask;
    int debug = 0;

#ifndef _MSC_VER
    unsigned char codeword_array[length * 3];
    unsigned char masked_codeword_array[length * 3];
#else
    char* dot_stream;
    char* dot_array;
    unsigned char* codeword_array = (unsigned char *) _alloca(length * 3 * sizeof (unsigned char));
    unsigned char* masked_codeword_array = (unsigned char *) _alloca(length * 3 * sizeof (unsigned char));
#endif /* _MSC_VER */

    data_length = dotcode_encode_message(symbol, source, length, codeword_array);

    ecc_length = 3 + (data_length / 2);

    if (debug) {
        printf("Codeword length = %d, ECC length = %d\n", data_length, ecc_length);
    }

    min_dots = 9 * (data_length + 3 + (data_length / 2)) + 2;

    if (symbol->option_2 == 0) {

        height = (int) sqrt(2.0 * min_dots);
        if (height % 2) {
            height++;
        }

        width = (2 * min_dots) / height;
        if (!(width % 2)) {
            width++;
        }

    } else {
        width = symbol->option_2;

        height = (2 * min_dots) / width;

        if (!((width + height) % 2)) {
            height++;
        }
    }

    if ((height > 200) || (width > 200)) {
        strcpy(symbol->errtxt, "Specified symbol size is too large (E20)");
        return ZINT_ERROR_INVALID_OPTION;
    }

    n_dots = (height * width) / 2;

#ifndef _MSC_VER
    char dot_stream[height * width * 3];
    char dot_array[width * height * sizeof (char) ];
#else
    dot_stream = (char *) _alloca(height * width * 3);
    if (!dot_stream) return ZINT_ERROR_MEMORY;

    dot_array = (char *) _alloca(width * height * sizeof (char));
    if (!dot_array) return ZINT_ERROR_MEMORY;
#endif

    /* Add pad characters */
    for (pad_chars = 0; 9 * ((data_length + pad_chars + 3 + ((data_length + pad_chars) / 2)) + 2) < n_dots; pad_chars++);

    if (pad_chars > 0) {
        codeword_array[data_length] = 109; // Latch to Code Set A
        data_length++;
        pad_chars--;
    }

    for (i = 0; i < pad_chars; i++) {
        codeword_array[data_length] = 106; // Pad
        data_length++;
    }

    if (data_length > 450) {
        // Larger data sets than this cause rsencode() to throw SIGSEGV
        // This should probably be fixed by somebody who understands what rsencode() does...
        strcpy(symbol->errtxt, "Input too long (E21)");
        return ZINT_ERROR_TOO_LONG;
    }

    ecc_length = 3 + (data_length / 2);

    /* Evaluate data mask options */
    for (i = 0; i < 4; i++) {
        switch (i) {
            case 0:
                masked_codeword_array[0] = 0;
                for (j = 0; j < data_length; j++) {
                    masked_codeword_array[j + 1] = codeword_array[j];
                }
                break;
            case 1:
                weight = 0;
                masked_codeword_array[0] = 1;
                for (j = 0; j < data_length; j++) {
                    masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
                    weight += 3;
                }
                break;
            case 2:
                weight = 0;
                masked_codeword_array[0] = 2;
                for (j = 0; j < data_length; j++) {
                    masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
                    weight += 7;
                }
                break;
            case 3:
                weight = 0;
                masked_codeword_array[0] = 3;
                for (j = 0; j < data_length; j++) {
                    masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
                    weight += 17;
                }
                break;
        }

        rsencode(data_length + 1, ecc_length, masked_codeword_array);

        dot_stream_length = make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream);

        /* Add pad bits */
        for (jc = dot_stream_length; jc < n_dots; jc++) {
            strcat(dot_stream, "1");
        }

        fold_dotstream(dot_stream, width, height, dot_array);

        mask_score[i] = score_array(dot_array, height, width);

        if (debug) {
            printf("Mask %d score is %d\n", i, mask_score[i]);
        }
    }

    high_score = mask_score[0];
    best_mask = 0;

    for (i = 1; i < 4; i++) {
        if (mask_score[i] > high_score) {
            high_score = mask_score[i];
            best_mask = i;
        }
    }

    if (best_mask != 3) {
        /* Reprocess to get symbol with best mask */
        switch (best_mask) {
            case 0:
                masked_codeword_array[0] = 0;
                for (j = 0; j < data_length; j++) {
                    masked_codeword_array[j + 1] = codeword_array[j];
                }
                break;
            case 1:
                weight = 0;
                masked_codeword_array[0] = 1;
                for (j = 0; j < data_length; j++) {
                    masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
                    weight += 3;
                }
                break;
            case 2:
                weight = 0;
                masked_codeword_array[0] = 2;
                for (j = 0; j < data_length; j++) {
                    masked_codeword_array[j + 1] = (weight + codeword_array[j]) % 113;
                    weight += 7;
                }
                break;
        }

        rsencode(data_length + 1, ecc_length, masked_codeword_array);
        dot_stream_length = make_dotstream(masked_codeword_array, (data_length + ecc_length + 1), dot_stream);

        /* Add pad bits */
        for (jc = dot_stream_length; jc < n_dots; jc++) {
            strcat(dot_stream, "1");
        }

        fold_dotstream(dot_stream, width, height, dot_array);
    } /* else { the version with the best mask is already in memory } */

    if (debug) {
        for (k = 0; k < height; k++) {
            for (j = 0; j < width; j++) {
                printf("%c", dot_array[(k * width) + j]);
            }
            printf("\n");
        }
    }

    /* Copy values to symbol */
    symbol->width = width;
    symbol->rows = height;

    for (k = 0; k < height; k++) {
        for (j = 0; j < width; j++) {
            if (dot_array[(k * width) + j] == '1') {
                set_module(symbol, k, j);
            }
        }
        symbol->row_height[k] = 1;
    }

    if (!(symbol->output_options & BARCODE_DOTTY_MODE)) {
        symbol->output_options += BARCODE_DOTTY_MODE;
    }

    return 0;
}

Added jni/zint/backend/eci.c.











































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/*  eci.c - Extended Channel Interpretations

    libzint - the open source barcode library
    Copyright (C) 2009-2016 Robin Stuart <rstuart114@gmail.com>

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

    1. Redistributions of source code must retain the above copyright 
       notice, this list of conditions and the following disclaimer.  
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.  
    3. Neither the name of the project nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission. 

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
    SUCH DAMAGE.
 */

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "eci.h"
#include "zint.h"
#ifdef _MSC_VER
#include <malloc.h>
#endif

/* Convert Unicode to other character encodings */
int utf_to_eci(int eci, const unsigned char source[], unsigned char dest[], int *length) {
    int glyph;
    int bytelen;
    int in_posn;
    int out_posn;
    int ext;
    int done;

    if (eci == 26) {
        /* Unicode mode, do not process - just copy data across */
        for (in_posn = 0; in_posn < *length; in_posn++) {
            dest[in_posn] = source[in_posn];
        }
        dest[*length] = '\0';
        return 0;
    }

    in_posn = 0;
    out_posn = 0;
    do {
        /* Single byte (ASCII) character */
        bytelen = 1;
        glyph = (int) source[in_posn];

        if ((source[in_posn] >= 0x80) && (source[in_posn] < 0xc0)) {
            /* Something has gone wrong, abort */
            return ZINT_ERROR_INVALID_DATA;
        }

        if ((source[in_posn] >= 0xc0) && (source[in_posn] < 0xe0)) {
            /* Two-byte character */
            bytelen = 2;
            glyph = (source[in_posn] & 0x1f) << 6;

            if (*length < (in_posn + 2)) {
                return ZINT_ERROR_INVALID_DATA;
            }

            if (source[in_posn + 1] > 0xc0) {
                return ZINT_ERROR_INVALID_DATA;
            }

            glyph += (source[in_posn + 1] & 0x3f);
        }

        if ((source[in_posn] >= 0xe0) && (source[in_posn] < 0xf0)) {
            /* Three-byte character */
            bytelen = 3;
            glyph = (source[in_posn] & 0x0f) << 12;

            if (*length < (in_posn + 2)) {
                return ZINT_ERROR_INVALID_DATA;
            }

            if (*length < (in_posn + 3)) {
                return ZINT_ERROR_INVALID_DATA;
            }

            if (source[in_posn + 1] > 0xc0) {
                return ZINT_ERROR_INVALID_DATA;
            }

            if (source[in_posn + 2] > 0xc0) {
                return ZINT_ERROR_INVALID_DATA;
            }

            glyph += (source[in_posn + 1] & 0x3f) << 6;
            glyph += (source[in_posn + 2] & 0x3f);
        }

        if ((source[in_posn] >= 0xf0) && (source[in_posn] < 0xf7)) {
            /* Four-byte character */
            bytelen = 4;
            glyph = (source[in_posn] & 0x07) << 18;

            if (*length < (in_posn + 2)) {
                return ZINT_ERROR_INVALID_DATA;
            }

            if (*length < (in_posn + 3)) {
                return ZINT_ERROR_INVALID_DATA;
            }

            if (*length < (in_posn + 4)) {
                return ZINT_ERROR_INVALID_DATA;
            }

            if (source[in_posn + 1] > 0xc0) {
                return ZINT_ERROR_INVALID_DATA;
            }

            if (source[in_posn + 2] > 0xc0) {
                return ZINT_ERROR_INVALID_DATA;
            }

            if (source[in_posn + 3] > 0xc0) {
                return ZINT_ERROR_INVALID_DATA;
            }

            glyph += (source[in_posn + 1] & 0x3f) << 12;
            glyph += (source[in_posn + 2] & 0x3f) << 6;
            glyph += (source[in_posn + 3] & 0x3f);
        }

        if (source[in_posn] >= 0xf7) {
            /* More than 4 bytes not supported */
            return ZINT_ERROR_INVALID_DATA;
        }

        if (glyph < 128) {
            dest[out_posn] = glyph;
        } else {
            done = 0;
            for (ext = 0; ext < 128; ext++) {
                switch (eci) {
                    case 3: // Latin-1
                        if (glyph == iso_8859_1[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 4: // Latin-2
                        if (glyph == iso_8859_2[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 5: // Latin-3
                        if (glyph == iso_8859_3[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 6: // Latin-4
                        if (glyph == iso_8859_4[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 7: // Latin/Cyrillic
                        if (glyph == iso_8859_5[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 8: // Latin/Arabic
                        if (glyph == iso_8859_6[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 9: // Latin/Greek
                        if (glyph == iso_8859_7[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 10: // Latin/Hebrew
                        if (glyph == iso_8859_8[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 11: // Latin-5
                        if (glyph == iso_8859_9[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 12: // Latin-6
                        if (glyph == iso_8859_10[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 13: // Latin/Thai
                        if (glyph == iso_8859_11[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 15: // Latin-7
                        if (glyph == iso_8859_13[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 16: // Latin-8
                        if (glyph == iso_8859_14[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 17: // Latin-9
                        if (glyph == iso_8859_15[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 18: // Latin-10
                        if (glyph == iso_8859_16[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 21: // Windows-1250
                        if (glyph == windows_1250[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 22: // Windows-1251
                        if (glyph == windows_1251[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 23: // Windows-1252
                        if (glyph == windows_1252[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    case 24: // Windows-1256
                        if (glyph == windows_1256[ext]) {
                            dest[out_posn] = ext + 128;
                            done = 1;
                        }
                        break;
                    default:
                        break;
                }
            }

            if (!(done)) {
                return ZINT_ERROR_INVALID_DATA;
            }
        }

        in_posn += bytelen;
        out_posn++;
    } while (in_posn < *length);
    dest[out_posn] = '\0';
    *length = out_posn;

    return 0;
}

/* Find the lowest ECI mode which will encode a given set of Unicode text */
int get_best_eci(unsigned char source[], int length) {
    int eci = 3;

#ifndef _MSC_VER
    unsigned char local_source[length + 1];
#else
    unsigned char *local_source = (unsigned char*) _alloca(length + 1);
#endif

    do {
        if (utf_to_eci(eci, source, local_source, &length) == 0) {
            return eci;
        }
        eci++;
    } while (eci < 25);

    return 26; // If all of these fail, use Unicode!
}

Added jni/zint/backend/eci.h.

























































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*  eci.c - Extended Channel Interpretations to Unicode tables

    libzint - the open source barcode library
    Copyright (C) 2009-2016 Robin Stuart <rstuart114@gmail.com>

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

    1. Redistributions of source code must retain the above copyright 
       notice, this list of conditions and the following disclaimer.  
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.  
    3. Neither the name of the project nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission. 

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
    SUCH DAMAGE.
 */

#ifndef ECI_H
#define ECI_H

#ifdef __cplusplus
extern "C" {
#endif

    static const int iso_8859_1[] = {// Latin alphabet No. 1
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
        0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
        0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
        0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
        0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
        0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
    };

    static const int iso_8859_2[] = {// Latin alphabet No. 2
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b,
        0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c,
        0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
        0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
        0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
        0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9
    };

    static const int iso_8859_3[] = {// Latin alphabet No. 3
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x0126, 0x02d8, 0x00a3, 0x00a4, 0x0000, 0x0124, 0x00a7, 0x00a8, 0x0130, 0x015e, 0x011e, 0x0134, 0x00ad, 0x0000, 0x017b,
        0x00b0, 0x0127, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x0125, 0x00b7, 0x00b8, 0x0131, 0x015f, 0x011f, 0x0135, 0x00bd, 0x0000, 0x017c,
        0x00c0, 0x00c1, 0x00c2, 0x0000, 0x00c4, 0x010a, 0x0108, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
        0x0000, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x0120, 0x00d6, 0x00d7, 0x011c, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x016c, 0x015c, 0x00df,
        0x00e0, 0x00e1, 0x00e2, 0x0000, 0x00e4, 0x010b, 0x0109, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
        0x0000, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x0121, 0x00f6, 0x00f7, 0x011d, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x016d, 0x015d, 0x02d9
    };

    static const int iso_8859_4[] = {// Latin alphabet No. 4
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x012b, 0x013b, 0x00a7, 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af,
        0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7, 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b,
        0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a,
        0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df,
        0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b,
        0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9
    };

    static const int iso_8859_5[] = {// Latin/Cyrillic alphabet
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x00ad, 0x040e, 0x040f,
        0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
        0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
        0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
        0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f,
        0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x00a7, 0x045e, 0x045f
    };

    static const int iso_8859_6[] = {// Latin/Arabic alphabet
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x0000, 0x0000, 0x0000, 0x00a4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x060c, 0x00ad, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x061b, 0x0000, 0x0000, 0x0000, 0x061f,
        0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f,
        0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f,
        0x0650, 0x0651, 0x0652, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
    };

    static const int iso_8859_7[] = {// Latin/Greek alphabet
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x2018, 0x2019, 0x00a3, 0x20ac, 0x20af, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x037a, 0x00ab, 0x00ac, 0x00ad, 0x0000, 0x2015,
        0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x0384, 0x0385, 0x0386, 0x00b7, 0x0388, 0x0389, 0x038a, 0x00bb, 0x038c, 0x00bd, 0x038e, 0x038f,
        0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
        0x03a0, 0x03a1, 0x0000, 0x03a3, 0x03a4, 0x03a5, 0x03a6, 0x03a7, 0x03a8, 0x03a9, 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af,
        0x03b0, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
        0x03c0, 0x03c1, 0x03c2, 0x03c3, 0x03c4, 0x03c5, 0x03c6, 0x03c7, 0x03c8, 0x03c9, 0x03ca, 0x03cb, 0x03cc, 0x03cd, 0x03ce, 0x0000
    };

    static const int iso_8859_8[] = {// Latin/Hebrew alphabet
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x0000, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00d7, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
        0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00f7, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2017,
        0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df,
        0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, 0x05e8, 0x05e9, 0x05ea, 0x0000, 0x0000, 0x200e, 0x200f, 0x0000
    };

    static const int iso_8859_9[] = {// Latin alphabet No. 5
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
        0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
        0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
        0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df,
        0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
        0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff
    };

    static const int iso_8859_10[] = {// Latin alphabet No. 6
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x0104, 0x0112, 0x0122, 0x012a, 0x012b, 0x0136, 0x00a7, 0x013b, 0x0110, 0x0160, 0x0166, 0x017d, 0x00ad, 0x016a, 0x014a,
        0x00b0, 0x0105, 0x0113, 0x0123, 0x012b, 0x0129, 0x0137, 0x00b7, 0x013c, 0x0111, 0x0161, 0x0167, 0x017e, 0x2015, 0x016b, 0x014b,
        0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x00cf,
        0x00d0, 0x0145, 0x014c, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x0168, 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
        0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x00ef,
        0x00f0, 0x0146, 0x014d, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x0169, 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x0138
    };

    static const int iso_8859_11[] = {// Latin/Thai alphabet
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f,
        0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f,
        0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f,
        0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e36, 0x0e36, 0x0e37, 0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0e3f,
        0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0e4e, 0x0e4f,
        0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, 0x0e58, 0x0e59, 0x0e5a, 0x0e5b, 0x0000, 0x0000, 0x0000, 0x0000
    };

    static const int iso_8859_13[] = {// Latin alphabet No. 7
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x201d, 0x00a2, 0x00a3, 0x00a4, 0x201e, 0x00a6, 0x00a7, 0x00d8, 0x00a9, 0x0156, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00c6,
        0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x201c, 0x00b5, 0x00b6, 0x00b7, 0x00f8, 0x00b9, 0x0157, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00e6,
        0x0104, 0x012e, 0x0100, 0x0106, 0x00c4, 0x00c5, 0x0118, 0x0112, 0x010c, 0x00c9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012a, 0x013b,
        0x0160, 0x0143, 0x0145, 0x00d3, 0x014c, 0x00d5, 0x00d6, 0x00d7, 0x0172, 0x0141, 0x015a, 0x016a, 0x00dc, 0x017b, 0x017d, 0x00df,
        0x0105, 0x012f, 0x0101, 0x0107, 0x00e4, 0x00e5, 0x0119, 0x0113, 0x010d, 0x00e9, 0x017a, 0x0117, 0x0123, 0x0137, 0x012b, 0x013c,
        0x0161, 0x0144, 0x0146, 0x00f3, 0x014d, 0x00f5, 0x00f6, 0x00f7, 0x0173, 0x0142, 0x015b, 0x016b, 0x00fc, 0x017c, 0x017e, 0x2019
    };

    static const int iso_8859_14[] = {// Latin alphabet No. 8 (Celtic)
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x1e02, 0x1e03, 0x00a3, 0x010a, 0x010b, 0x1e0a, 0x00a7, 0x1e80, 0x00a9, 0x1e82, 0x1e0b, 0x1ef2, 0x00ad, 0x00ae, 0x0178,
        0x1e1e, 0x1e1f, 0x0120, 0x0121, 0x1e40, 0x1e41, 0x00b6, 0x1e56, 0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61,
        0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
        0x0174, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x1e6a, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x0176, 0x00df,
        0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
        0x0175, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x1e6b, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x0177, 0x00ff
    };

    static const int iso_8859_15[] = {// Latin alphabet No. 9
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x20ac, 0x00a5, 0x0160, 0x00a7, 0x0161, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
        0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x017d, 0x00b5, 0x00b6, 0x00b7, 0x017e, 0x00b9, 0x00ba, 0x00bb, 0x0152, 0x0153, 0x0178, 0x00bf,
        0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
        0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
        0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
        0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
    };

    static const int iso_8859_16[] = {// Latin alphabet No. 10
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x00a0, 0x0104, 0x0105, 0x0141, 0x20ac, 0x201e, 0x0160, 0x00a7, 0x0161, 0x00a9, 0x0218, 0x00ab, 0x0179, 0x00ad, 0x017a, 0x017b,
        0x00b0, 0x00b1, 0x010c, 0x0142, 0x017d, 0x201d, 0x00b6, 0x00b7, 0x017e, 0x010d, 0x0219, 0x00bb, 0x0152, 0x0153, 0x0178, 0x017c,
        0x00c0, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0106, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
        0x00e0, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x0107, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
        0x0111, 0x0144, 0x00f2, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x015b, 0x0171, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0119, 0x021b, 0x00ff
    };

    static const int windows_1250[] = {
        0x20ac, 0x0000, 0x201a, 0x0000, 0x201e, 0x2026, 0x2020, 0x2021, 0x0000, 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179,
        0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a,
        0x00a0, 0x02c7, 0x02db, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b,
        0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c,
        0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
        0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
        0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
        0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9
    };

    static const int windows_1251[] = {
        0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f,
        0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x0000, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f,
        0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407,
        0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457,
        0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, 0x041f,
        0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e, 0x042f,
        0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, 0x043f,
        0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e, 0x044f
    };

    static const int windows_1252[] = {
        0x20ac, 0x0000, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017d, 0x0000,
        0x0000, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x0000, 0x017e, 0x0178,
        0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
        0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
        0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
        0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
        0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
        0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
    };

    static const int windows_1256[] = {
        0x20ac, 0x067e, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, 0x02c6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
        0x06af, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, 0x06a9, 0x2122, 0x0691, 0x203a, 0x0153, 0x200c, 0x200d, 0x06ba,
        0x00a0, 0x060c, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, 0x00a8, 0x00a9, 0x06be, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
        0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, 0x00b8, 0x00b9, 0x061b, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x061f,
        0x06c1, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f,
        0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x00d7, 0x0637, 0x0638, 0x0639, 0x063a, 0x0640, 0x0641, 0x0642, 0x0643,
        0x00e0, 0x0644, 0x00e2, 0x0645, 0x0646, 0x0647, 0x0648, 0x00e7, 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x0649, 0x064a, 0x00ee, 0x00ef,
        0x064b, 0x064c, 0x064d, 0x064e, 0x00f4, 0x064f, 0x0650, 0x00f7, 0x0651, 0x00f9, 0x0652, 0x00fb, 0x00fc, 0x200e, 0x200f, 0x06d2
    };

#ifdef __cplusplus
}
#endif

#endif /* ECI_H */

Added jni/zint/backend/gb18030.h.

more than 10,000 changes

Added jni/zint/backend/gif.c.





































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
/* gif.c - Handles output to gif file */

/*
    libzint - the open source barcode library
    Copyright (C) 2009-2016 Robin Stuart <rstuart114@gmail.com>

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

    1. Redistributions of source code must retain the above copyright 
       notice, this list of conditions and the following disclaimer.  
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.  
    3. Neither the name of the project nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission. 

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
    SUCH DAMAGE.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include <math.h>
#ifdef _MSC_VER
#include <io.h>
#include <fcntl.h>
#include <malloc.h>
#endif

#define SSET	"0123456789ABCDEF"

/* Index of transparent color, -1 for no transparent color
 * This might be set into a variable if transparency is activated as an option
 */
#define TRANSPARENT_INDEX (-1)

/* Used bit depth, may be changed for bigger pallet in future */
#define DESTINATION_IMAGE_BITS 1
#include <stdlib.h>

typedef struct s_statestruct {
    unsigned char * pOut;
    unsigned char *pIn;
    unsigned int InLen;
    unsigned int OutLength;
    unsigned int OutPosCur;
    unsigned int OutByteCountPos;
    unsigned short ClearCode;
    unsigned short FreeCode;
    char fByteCountByteSet;
    unsigned char OutBitsFree;
    unsigned short NodeAxon[4096];
    unsigned short NodeNext[4096];
    unsigned char NodePix[4096];
} statestruct;

static char BufferNextByte(statestruct *pState) {
    (pState->OutPosCur)++;
    /* Check if this position is a byte count position
     * fg_f_bytecountbyte_set indicates, if byte count position bytes should be
     * inserted in general.
     * If this is true, and the distance to the last byte count position is 256
     * (e.g. 255 bytes in between), a byte count byte is inserted, and the value
     * of the last one is set to 255.
     * */
    if (pState->fByteCountByteSet && (pState->OutByteCountPos + 256 == pState->OutPosCur)) {
        (pState->pOut)[pState->OutByteCountPos] = 255;
        pState->OutByteCountPos = pState->OutPosCur;
        (pState->OutPosCur)++;
    }
    if (pState->OutPosCur >= pState->OutLength)
        return 1;
    (pState->pOut)[pState->OutPosCur] = 0x00;
    return 0;
}

static char AddCodeToBuffer(statestruct *pState, unsigned short CodeIn, unsigned char CodeBits) {
    /* Check, if we may fill up the current byte completely */
    if (CodeBits >= pState->OutBitsFree) {
        (pState->pOut)[pState->OutPosCur] |= (unsigned char)
                (CodeIn << (8 - pState->OutBitsFree));
        if (BufferNextByte(pState))
            return -1;
        CodeIn = (unsigned short) (CodeIn >> pState->OutBitsFree);
        CodeBits -= pState->OutBitsFree;
        pState->OutBitsFree = 8;
        /* Write a full byte if there are at least 8 code bits left */
        if (CodeBits >= pState->OutBitsFree) {
            (pState->pOut)[pState->OutPosCur] = (unsigned char) CodeIn;
            if (BufferNextByte(pState))
                return -1;
            CodeIn = (unsigned short) (CodeIn >> 8);
            CodeBits -= 8;
        }
    }
    /* The remaining bits of CodeIn fit in the current byte. */
    if (CodeBits > 0) {
        (pState->pOut)[pState->OutPosCur] |= (unsigned char)
                (CodeIn << (8 - pState->OutBitsFree));
        pState->OutBitsFree -= CodeBits;
    }
    return 0;
}

static void FlushStringTable(statestruct *pState) {
    unsigned short Pos;
    for (Pos = 0; Pos < pState->ClearCode; Pos++) {
        (pState->NodeAxon)[Pos] = 0;
    }
}

unsigned short FindPixelOutlet(statestruct *pState, unsigned short HeadNode, unsigned char Byte) {
    unsigned short Outlet;

    Outlet = (pState->NodeAxon)[HeadNode];
    while (Outlet) {
        if ((pState->NodePix)[Outlet] == Byte)
            return Outlet;
        Outlet = (pState->NodeNext)[Outlet];
    }
    return 0;
}

static char NextCode(statestruct *pState, unsigned char * pPixelValueCur, unsigned char CodeBits) {
    unsigned short UpNode;
    unsigned short DownNode;
    /* start with the root node for last pixel chain */
    UpNode = *pPixelValueCur;
    if ((pState->InLen) == 0)
        return AddCodeToBuffer(pState, UpNode, CodeBits);

    *pPixelValueCur = (*(pState->pIn)) - '0';
    (pState->pIn)++;
    (pState->InLen)--;
    /* Follow the string table and the data stream to the end of the longest string that has a code */
    while (0 != (DownNode = FindPixelOutlet(pState, UpNode, *pPixelValueCur))) {
        UpNode = DownNode;
        if ((pState->InLen) == 0)
            return AddCodeToBuffer(pState, UpNode, CodeBits);

        *pPixelValueCur = (*(pState->pIn)) - '0';
        (pState->pIn)++;
        (pState->InLen)--;
    }
    /* Submit 'UpNode' which is the code of the longest string */
    if (AddCodeToBuffer(pState, UpNode, CodeBits))
        return -1;
    /* ... and extend the string by appending 'PixelValueCur' */
    /* Create a successor node for 'PixelValueCur' whose code is 'freecode' */
    (pState->NodePix)[pState->FreeCode] = *pPixelValueCur;
    (pState->NodeAxon)[pState->FreeCode] = (pState->NodeNext)[pState->FreeCode] = 0;
    /* ...and link it to the end of the chain emanating from fg_axon[UpNode]. */
    DownNode = (pState->NodeAxon)[UpNode];
    if (!DownNode) {
        (pState->NodeAxon)[UpNode] = pState->FreeCode;
    } else {
        while ((pState->NodeNext)[DownNode]) {
            DownNode = (pState->NodeNext)[DownNode];
        }
        (pState->NodeNext)[DownNode] = pState->FreeCode;
    }
    return 1;
}

int gif_lzw(unsigned char *pOut, int OutLength, unsigned char *pIn, int InLen) {
    unsigned char PixelValueCur;
    unsigned char CodeBits;
    unsigned short Pos;
    statestruct State;

    State.pIn = pIn;
    State.InLen = InLen;
    State.pOut = pOut;
    State.OutLength = OutLength;
    // > Get first data byte
    if (State.InLen == 0)
        return 0;

    PixelValueCur = (unsigned char) ((*(State.pIn)) - '0');
    (State.pIn)++;
    (State.InLen)--;
    CodeBits = 3;
    State.ClearCode = 4;
    State.FreeCode = 6;
    State.OutBitsFree = 8;
    State.OutPosCur = -1;
    State.fByteCountByteSet = 0;

    if (BufferNextByte(&State))
        return 0;

    for (Pos = 0; Pos < State.ClearCode; Pos++)
        State.NodePix[Pos] = (unsigned char) Pos;

    FlushStringTable(&State);

    /* Write what the GIF specification calls the "code size". */
    (State.pOut)[State.OutPosCur] = 2;
    /* Reserve first bytecount byte */
    if (BufferNextByte(&State))
        return 0;
    State.OutByteCountPos = State.OutPosCur;
    if (BufferNextByte(&State))
        return 0;
    State.fByteCountByteSet = 1;
    /* Submit one 'ClearCode' as the first code */
    if (AddCodeToBuffer(&State, State.ClearCode, CodeBits))
        return 0;

    for (;;) {
        char Res;
        /* generate and save the next code, which may consist of multiple input pixels. */
        Res = NextCode(&State, &PixelValueCur, CodeBits);
        if (Res < 0)
            return 0;
        //* Check for end of data stream */
        if (!Res) {
            /* submit 'eoi' as the last item of the code stream */
            if (AddCodeToBuffer(&State, (unsigned short) (State.ClearCode + 1), CodeBits))
                return 0;
            State.fByteCountByteSet = 0;
            if (State.OutBitsFree < 8) {
                if (BufferNextByte(&State))
                    return 0;
            }
            // > Update last bytecount byte;
            if (State.OutByteCountPos < State.OutPosCur) {
                (State.pOut)[State.OutByteCountPos] = (unsigned char) (State.OutPosCur - State.OutByteCountPos - 1);
            }
            State.OutPosCur++;
            return State.OutPosCur;
        }
        /* Check for currently last code */
        if (State.FreeCode == (1U << CodeBits))
            CodeBits++;
        State.FreeCode++;
        /* Check for full stringtable */
        if (State.FreeCode == 0xfff) {
            FlushStringTable(&State);
            if (AddCodeToBuffer(&State, State.ClearCode, CodeBits))
                return 0;

            CodeBits = (unsigned char) (1 + 2);
            State.FreeCode = (unsigned short) (State.ClearCode + 2);
        }
    }
}

int gif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) {
    char outbuf[10];
    FILE *gif_file;
    unsigned short usTemp;
    int byte_out;
#ifdef _MSC_VER
    char * lzwoutbuf;
#endif

#ifndef _MSC_VER
    char lzwoutbuf[symbol->bitmap_height * symbol->bitmap_width];
#else
    lzwoutbuf = (char *) _alloca((symbol->bitmap_height * symbol->bitmap_width) * sizeof (char));
#endif /* _MSC_VER */

    /* Open output file in binary mode */
    if ((symbol->output_options & BARCODE_STDOUT) != 0) {
#ifdef _MSC_VER
        if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
            strcpy(symbol->errtxt, "Can't open output file");
            return ZINT_ERROR_FILE_ACCESS;
        }
#endif
        gif_file = stdout;
    } else {
        if (!(gif_file = fopen(symbol->outfile, "wb"))) {
            strcpy(symbol->errtxt, "Can't open output file (F10)");
            return ZINT_ERROR_FILE_ACCESS;
        }
    }
    /*ImageWidth = 2;
    ImageHeight = 2;
    rotated_bitmap[0] = 1;
    rotated_bitmap[1] = 1;
    rotated_bitmap[2] = 0;
    rotated_bitmap[3] = 0;
     */

    /* GIF signature (6) */
    memcpy(outbuf, "GIF87a", 6);
    if (TRANSPARENT_INDEX != -1)
        outbuf[4] = '9';
    fwrite(outbuf, 6, 1, gif_file);
    /* Screen Descriptor (7) */
    /* Screen Width */
    usTemp = (unsigned short) symbol->bitmap_width;
    outbuf[0] = (unsigned char) (0xff & usTemp);
    outbuf[1] = (unsigned char) ((0xff00 & usTemp) / 0x100);
    /* Screen Height */
    usTemp = (unsigned short) symbol->bitmap_height;
    outbuf[2] = (unsigned char) (0xff & usTemp);
    outbuf[3] = (unsigned char) ((0xff00 & usTemp) / 0x100);
    /* write ImageBits-1 to the three least significant bits of byte 5  of
     * the Screen Descriptor
     */
    outbuf[4] = (unsigned char) (0xf0 | (0x7 & (DESTINATION_IMAGE_BITS - 1)));
    /*  Background color = colortable index 0 */
    outbuf[5] = 0x00;
    /* Byte 7 must be 0x00  */
    outbuf[6] = 0x00;
    fwrite(outbuf, 7, 1, gif_file);
    /* Global Color Table (6) */
    /* RGB 0 color */
    outbuf[0] = (unsigned char) (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]);
    outbuf[1] = (unsigned char) (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]);
    outbuf[2] = (unsigned char) (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]);
    /* RGB 1 color */
    outbuf[3] = (unsigned char) (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
    outbuf[4] = (unsigned char) (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]);
    outbuf[5] = (unsigned char) (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]);
    fwrite(outbuf, 6, 1, gif_file);

    /* Graphic control extension (8) */
    /* A graphic control extension block is used for overlay gifs.
     * This is necessary to define a transparent color.
     */
    if (TRANSPARENT_INDEX != -1) {
        /* Extension Introducer = '!' */
        outbuf[0] = '\x21';
        /* Graphic Control Label */
        outbuf[1] = '\xf9';
        /* Block Size */
        outbuf[2] = 4;
        /* Packet fields:
         * 3 Reserved
         * 3 Disposal Method: 0 No Action, 1 No Dispose, 2: Background, 3: Prev.
         * 1 User Input Flag: 0: no user input, 1: user input
         * 1 Transparent Color Flag: 0: No Transparency, 1: Transparency index
         */
        outbuf[3] = 1;
        /* Delay Time */
        outbuf[4] = 0;
        outbuf[5] = 0;
        /* Transparent Color Index */
        outbuf[6] = (unsigned char) TRANSPARENT_INDEX;
        /* Block Terminator */
        outbuf[7] = 0;
        fwrite(outbuf, 8, 1, gif_file);
    }
    /* Image Descriptor */
    /* Image separator character = ',' */
    outbuf[0] = 0x2c;
    /* "Image Left" */
    outbuf[1] = 0x00;
    outbuf[2] = 0x00;
    /* "Image Top" */
    outbuf[3] = 0x00;
    outbuf[4] = 0x00;
    /* Image Width (low byte first) */
    outbuf[5] = (unsigned char) (0xff & symbol->bitmap_width);
    outbuf[6] = (unsigned char) ((0xff00 & symbol->bitmap_width) / 0x100);
    /* Image Height */
    outbuf[7] = (unsigned char) (0xff & symbol->bitmap_height);
    outbuf[8] = (unsigned char) ((0xff00 & symbol->bitmap_height) / 0x100);

    /* Byte 10 contains the interlaced flag and
     * information on the local color table.
     * There is no local color table if its most significant bit is reset.
     */
    outbuf[9] = (unsigned char) (0 | (0x7 & (DESTINATION_IMAGE_BITS - 1)));
    fwrite(outbuf, 10, 1, gif_file);

    /* call lzw encoding */
    byte_out = gif_lzw(
            (unsigned char *) lzwoutbuf,
            symbol->bitmap_height * symbol->bitmap_width,
            (unsigned char *) pixelbuf,
            symbol->bitmap_height * symbol->bitmap_width);
    if (byte_out <= 0) {
        fclose(gif_file);
        return ZINT_ERROR_MEMORY;
    }
    fwrite(lzwoutbuf, byte_out, 1, gif_file);

    /* GIF terminator */
    fputc('\x3b', gif_file);
    fclose(gif_file);

    return 0;
}

Changes to jni/zint/backend/gridmtx.c.

344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
...
366
367
368
369
370
371
372











373
374
375
376
377
378
379
....
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062

1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
....
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
            strcat(binary, "1");
        } else {
            strcat(binary, "0");
        }
    }
}

int gm_encode(int gbdata[], int length, char binary[], int reader) {
    /* Create a binary stream representation of the input data.
       7 sets are defined - Chinese characters, Numerals, Lower case letters, Upper case letters,
       Mixed numerals and latters, Control characters and 8-bit binary data */
    int sp, current_mode, next_mode, last_mode, glyph = 0, q;
    int c1, c2, done;
    int p = 0, ppos;
    int numbuf[3], punt = 0;
................................................................................
    current_mode = 0;
    last_mode = 0;
    number_pad_posn = 0;

    if (reader) {
        strcat(binary, "1010"); /* FNC3 - Reader Initialisation */
    }












    do {
        next_mode = seek_forward(gbdata, length, sp, current_mode);

        if (next_mode != current_mode) {
            switch (current_mode) {
                case 0:
................................................................................
    int* gbdata = (int *) _alloca((length + 1) * sizeof (int));
#endif

    for (i = 0; i < 1460; i++) {
        word[i] = 0;
    }

    switch (symbol->input_mode) {
        case DATA_MODE:
            for (i = 0; i < length; i++) {
                gbdata[i] = (int) source[i];
            }
            break;
        default:

            /* Convert Unicode input to GB-2312 */
            error_number = utf8toutf16(symbol, source, utfdata, &length);
            if (error_number != 0) {
                return error_number;
            }

            for (i = 0; i < length; i++) {
                if (utfdata[i] <= 0xff) {
                    gbdata[i] = utfdata[i];
                } else {
                    j = 0;
                    glyph = 0;
                    do {
                        if (gb2312_lookup[j * 2] == utfdata[i]) {
                            glyph = gb2312_lookup[(j * 2) + 1];
                        }
                        j++;
                    } while ((j < 7445) && (glyph == 0));
                    if (glyph == 0) {
                        strcpy(symbol->errtxt, "Invalid character in input data");
                        return ZINT_ERROR_INVALID_DATA;
                    }
                    gbdata[i] = glyph;
                }
            }
            break;
    }

    if (symbol->output_options & READER_INIT) reader = 1;

    error_number = gm_encode(gbdata, length, binary, reader);
    if (error_number != 0) {
        strcpy(symbol->errtxt, "Input data too long");
        return error_number;
    }

    /* Determine the size of the symbol */
    data_cw = strlen(binary) / 7;

    auto_layers = 13;
................................................................................
        case 4: data_max = 875;
            break;
        case 5: data_max = 729;
            break;
    }

    if (data_cw > data_max) {
        strcpy(symbol->errtxt, "Input data too long");
        return ZINT_ERROR_TOO_LONG;
    }

    gm_add_ecc(binary, data_cw, layers, ecc_level, word);
    size = 6 + (layers * 12);
    modules = 1 + (layers * 2);








|







 







>
>
>
>
>
>
>
>
>
>
>







 







|
<
|
|
|
<
<
>
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<




|

|







 







|







344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
...
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
....
1060
1061
1062
1063
1064
1065
1066
1067

1068
1069
1070


1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096

1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
....
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
            strcat(binary, "1");
        } else {
            strcat(binary, "0");
        }
    }
}

int gm_encode(int gbdata[], int length, char binary[], int reader, int eci) {
    /* Create a binary stream representation of the input data.
       7 sets are defined - Chinese characters, Numerals, Lower case letters, Upper case letters,
       Mixed numerals and latters, Control characters and 8-bit binary data */
    int sp, current_mode, next_mode, last_mode, glyph = 0, q;
    int c1, c2, done;
    int p = 0, ppos;
    int numbuf[3], punt = 0;
................................................................................
    current_mode = 0;
    last_mode = 0;
    number_pad_posn = 0;

    if (reader) {
        strcat(binary, "1010"); /* FNC3 - Reader Initialisation */
    }
    
    if (eci != 3) {
        strcat(binary, "11000"); /* ECI */
        for (q = 0; q < 10; q++) {
            if (eci & (0x100 >> q)) {
                strcat(binary, "1");
            } else {
                strcat(binary, "0");
            }
        }
    }

    do {
        next_mode = seek_forward(gbdata, length, sp, current_mode);

        if (next_mode != current_mode) {
            switch (current_mode) {
                case 0:
................................................................................
    int* gbdata = (int *) _alloca((length + 1) * sizeof (int));
#endif

    for (i = 0; i < 1460; i++) {
        word[i] = 0;
    }

    if ((symbol->input_mode == DATA_MODE) || (symbol->eci != 3)) {

        for (i = 0; i < length; i++) {
            gbdata[i] = (int) source[i];
        }


    } else {
        /* Convert Unicode input to GB-2312 */
        error_number = utf8toutf16(symbol, source, utfdata, &length);
        if (error_number != 0) {
            return error_number;
        }

        for (i = 0; i < length; i++) {
            if (utfdata[i] <= 0xff) {
                gbdata[i] = utfdata[i];
            } else {
                j = 0;
                glyph = 0;
                do {
                    if (gb2312_lookup[j * 2] == utfdata[i]) {
                        glyph = gb2312_lookup[(j * 2) + 1];
                    }
                    j++;
                } while ((j < 7445) && (glyph == 0));
                if (glyph == 0) {
                    strcpy(symbol->errtxt, "Invalid character in input data (E30)");
                    return ZINT_ERROR_INVALID_DATA;
                }
                gbdata[i] = glyph;
            }
        }

    }

    if (symbol->output_options & READER_INIT) reader = 1;

    error_number = gm_encode(gbdata, length, binary, reader, symbol->eci);
    if (error_number != 0) {
        strcpy(symbol->errtxt, "Input data too long (E31)");
        return error_number;
    }

    /* Determine the size of the symbol */
    data_cw = strlen(binary) / 7;

    auto_layers = 13;
................................................................................
        case 4: data_max = 875;
            break;
        case 5: data_max = 729;
            break;
    }

    if (data_cw > data_max) {
        strcpy(symbol->errtxt, "Input data too long (E32)");
        return ZINT_ERROR_TOO_LONG;
    }

    gm_add_ecc(binary, data_cw, layers, ecc_level, word);
    size = 6 + (layers * 12);
    modules = 1 + (layers * 2);

Changes to jni/zint/backend/gridmtx.h.

79
80
81
82
83
84
85

86
87
88
89
90
91
92
...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
    1, 1, 1, 2, 2, 2, 2, 3, 2, 7, 5, 10, 6
};

static const int gm_b2[] = {
    0, 0, 0, 0, 0, 1, 2, 2, 4, 0, 4, 0, 6
};


static const int gm_ebeb[] = {
    /* E1 B3 E2 B4 */
    0, 0, 0, 0, // version 1
    3, 1, 0, 0,
    5, 1, 0, 0,
    7, 1, 0, 0,
    9, 1, 0, 0,
................................................................................
    29, 1, 0, 0,
    39, 1, 0, 0,
    49, 1, 0, 0,
    8, 2, 0, 0, // version 4
    16, 2, 0, 0,
    24, 2, 0, 0,
    32, 2, 0, 0,
    41, 1, 10, 1,
    12, 2, 0, 0, // version 5
    24, 2, 0, 0,
    36, 2, 0, 0,
    48, 2, 0, 0,
    61, 1, 60, 1,
    11, 3, 0, 0, // version 6
    23, 1, 22, 2,







>







 







|







79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
    1, 1, 1, 2, 2, 2, 2, 3, 2, 7, 5, 10, 6
};

static const int gm_b2[] = {
    0, 0, 0, 0, 0, 1, 2, 2, 4, 0, 4, 0, 6
};

/* Values from table A.1 */
static const int gm_ebeb[] = {
    /* E1 B3 E2 B4 */
    0, 0, 0, 0, // version 1
    3, 1, 0, 0,
    5, 1, 0, 0,
    7, 1, 0, 0,
    9, 1, 0, 0,
................................................................................
    29, 1, 0, 0,
    39, 1, 0, 0,
    49, 1, 0, 0,
    8, 2, 0, 0, // version 4
    16, 2, 0, 0,
    24, 2, 0, 0,
    32, 2, 0, 0,
    41, 1, 40, 1,
    12, 2, 0, 0, // version 5
    24, 2, 0, 0,
    36, 2, 0, 0,
    48, 2, 0, 0,
    61, 1, 60, 1,
    11, 3, 0, 0, // version 6
    23, 1, 22, 2,

Changes to jni/zint/backend/gs1.c.

65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
...
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
...
349
350
351
352
353
354
355
356
357
358
    temp[0] = itoc(ten);
    strcat(ai_string, temp);
    temp[0] = itoc(unit);
    strcat(ai_string, temp);
    strcat(ai_string, ")");
}

int gs1_verify(struct zint_symbol *symbol, const unsigned char source[], const unsigned int src_len, char reduced[]) {
    int i, j, last_ai, ai_latch;
    char ai_string[6];
    int bracket_level, max_bracket_level, ai_length, max_ai_length, min_ai_length;
    int ai_value[100], ai_location[100], ai_count, data_location[100], data_length[100];
    int error_latch;

    /* Detect extended ASCII characters */
    for (i = 0; i < src_len; i++) {
        if (source[i] >= 128) {
            strcpy(symbol->errtxt, "Extended ASCII characters are not supported by GS1");
            return ZINT_ERROR_INVALID_DATA;
        }
        if (source[i] < 32) {
            strcpy(symbol->errtxt, "Control characters are not supported by GS1");
            return ZINT_ERROR_INVALID_DATA;
        }
    }

    if (source[0] != '[') {
        strcpy(symbol->errtxt, "Data does not start with an AI");
        return ZINT_ERROR_INVALID_DATA;
    }

    /* Check the position of the brackets */
    bracket_level = 0;
    max_bracket_level = 0;
    ai_length = 0;
................................................................................
            max_ai_length = ai_length;
        }
    }
    min_ai_length--;

    if (bracket_level != 0) {
        /* Not all brackets are closed */
        strcpy(symbol->errtxt, "Malformed AI in input data (brackets don\'t match)");
        return ZINT_ERROR_INVALID_DATA;
    }

    if (max_bracket_level > 1) {
        /* Nested brackets */
        strcpy(symbol->errtxt, "Found nested brackets in input data");
        return ZINT_ERROR_INVALID_DATA;
    }

    if (max_ai_length > 4) {
        /* AI is too long */
        strcpy(symbol->errtxt, "Invalid AI in input data (AI too long)");
        return ZINT_ERROR_INVALID_DATA;
    }

    if (min_ai_length <= 1) {
        /* AI is too short */
        strcpy(symbol->errtxt, "Invalid AI in input data (AI too short)");
        return ZINT_ERROR_INVALID_DATA;
    }

    if (ai_latch == 1) {
        /* Non-numeric data in AI */
        strcpy(symbol->errtxt, "Invalid AI in input data (non-numeric characters in AI)");
        return ZINT_ERROR_INVALID_DATA;
    }

    ai_count = 0;
    for (i = 1; i < src_len; i++) {
        if (source[i - 1] == '[') {
            ai_location[ai_count] = i;
................................................................................
        } while ((source[data_location[i] + data_length[i] - 1] != '[') && (data_location[i] + data_length[i] <= src_len));
        data_length[i]--;
    }

    for (i = 0; i < ai_count; i++) {
        if (data_length[i] == 0) {
            /* No data for given AI */
            strcpy(symbol->errtxt, "Empty data field in input data");
            return ZINT_ERROR_INVALID_DATA;
        }
    }

    error_latch = 0;
    strcpy(ai_string, "");
    for (i = 0; i < ai_count; i++) {
................................................................................
            /* error has just been detected: capture AI */
            itostr(ai_string, ai_value[i]);
            error_latch += 4;
        }
    }

    if (error_latch == 5) {
        strcpy(symbol->errtxt, "Invalid data length for AI ");
        strcat(symbol->errtxt, ai_string);
        return ZINT_ERROR_INVALID_DATA;
    }

    if (error_latch == 6) {
        strcpy(symbol->errtxt, "Invalid AI value ");
        strcat(symbol->errtxt, ai_string);
        return ZINT_ERROR_INVALID_DATA;
    }

    /* Resolve AI data - put resulting string in 'reduced' */
    j = 0;
    last_ai = 0;
................................................................................
        return error_number;
    }

    if (strlen(temp) < src_len + 5) {
        ustrcpy(reduced, (unsigned char*) temp);
        return 0;
    }
    strcpy(symbol->errtxt, "ugs1_verify overflow");
    return ZINT_ERROR_INVALID_DATA;
}







|









|



|





|







 







|





|





|





|





|







 







|







 







|





|







 







|


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
...
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
...
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
...
349
350
351
352
353
354
355
356
357
358
    temp[0] = itoc(ten);
    strcat(ai_string, temp);
    temp[0] = itoc(unit);
    strcat(ai_string, temp);
    strcat(ai_string, ")");
}

int gs1_verify(struct zint_symbol *symbol, const unsigned char source[], const size_t src_len, char reduced[]) {
    int i, j, last_ai, ai_latch;
    char ai_string[6];
    int bracket_level, max_bracket_level, ai_length, max_ai_length, min_ai_length;
    int ai_value[100], ai_location[100], ai_count, data_location[100], data_length[100];
    int error_latch;

    /* Detect extended ASCII characters */
    for (i = 0; i < src_len; i++) {
        if (source[i] >= 128) {
            strcpy(symbol->errtxt, "Extended ASCII characters are not supported by GS1 (B50)");
            return ZINT_ERROR_INVALID_DATA;
        }
        if (source[i] < 32) {
            strcpy(symbol->errtxt, "Control characters are not supported by GS1 (B51)");
            return ZINT_ERROR_INVALID_DATA;
        }
    }

    if (source[0] != '[') {
        strcpy(symbol->errtxt, "Data does not start with an AI (B52)");
        return ZINT_ERROR_INVALID_DATA;
    }

    /* Check the position of the brackets */
    bracket_level = 0;
    max_bracket_level = 0;
    ai_length = 0;
................................................................................
            max_ai_length = ai_length;
        }
    }
    min_ai_length--;

    if (bracket_level != 0) {
        /* Not all brackets are closed */
        strcpy(symbol->errtxt, "Malformed AI in input data (brackets don\'t match) (B53)");
        return ZINT_ERROR_INVALID_DATA;
    }

    if (max_bracket_level > 1) {
        /* Nested brackets */
        strcpy(symbol->errtxt, "Found nested brackets in input data (B54)");
        return ZINT_ERROR_INVALID_DATA;
    }

    if (max_ai_length > 4) {
        /* AI is too long */
        strcpy(symbol->errtxt, "Invalid AI in input data (AI too long) (B55)");
        return ZINT_ERROR_INVALID_DATA;
    }

    if (min_ai_length <= 1) {
        /* AI is too short */
        strcpy(symbol->errtxt, "Invalid AI in input data (AI too short) (B56)");
        return ZINT_ERROR_INVALID_DATA;
    }

    if (ai_latch == 1) {
        /* Non-numeric data in AI */
        strcpy(symbol->errtxt, "Invalid AI in input data (non-numeric characters in AI) (B57)");
        return ZINT_ERROR_INVALID_DATA;
    }

    ai_count = 0;
    for (i = 1; i < src_len; i++) {
        if (source[i - 1] == '[') {
            ai_location[ai_count] = i;
................................................................................
        } while ((source[data_location[i] + data_length[i] - 1] != '[') && (data_location[i] + data_length[i] <= src_len));
        data_length[i]--;
    }

    for (i = 0; i < ai_count; i++) {
        if (data_length[i] == 0) {
            /* No data for given AI */
            strcpy(symbol->errtxt, "Empty data field in input data (B58)");
            return ZINT_ERROR_INVALID_DATA;
        }
    }

    error_latch = 0;
    strcpy(ai_string, "");
    for (i = 0; i < ai_count; i++) {
................................................................................
            /* error has just been detected: capture AI */
            itostr(ai_string, ai_value[i]);
            error_latch += 4;
        }
    }

    if (error_latch == 5) {
        strcpy(symbol->errtxt, "Invalid data length for AI (B59)");
        strcat(symbol->errtxt, ai_string);
        return ZINT_ERROR_INVALID_DATA;
    }

    if (error_latch == 6) {
        strcpy(symbol->errtxt, "Invalid AI value (B60)");
        strcat(symbol->errtxt, ai_string);
        return ZINT_ERROR_INVALID_DATA;
    }

    /* Resolve AI data - put resulting string in 'reduced' */
    j = 0;
    last_ai = 0;
................................................................................
        return error_number;
    }

    if (strlen(temp) < src_len + 5) {
        ustrcpy(reduced, (unsigned char*) temp);
        return 0;
    }
    strcpy(symbol->errtxt, "ugs1_verify overflow (B61)");
    return ZINT_ERROR_INVALID_DATA;
}

Changes to jni/zint/backend/gs1.h.

32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#ifndef __GS1_H
#define __GS1_H

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

    extern int gs1_verify(struct zint_symbol *symbol, const unsigned char source[], const unsigned int src_len, char reduced[]);
    extern int ugs1_verify(struct zint_symbol *symbol, const unsigned char source[], const unsigned int src_len, unsigned char reduced[]);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __GS1_H */







|







32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#ifndef __GS1_H
#define __GS1_H

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

    extern int gs1_verify(struct zint_symbol *symbol, const unsigned char source[], const size_t src_len, char reduced[]);
    extern int ugs1_verify(struct zint_symbol *symbol, const unsigned char source[], const unsigned int src_len, unsigned char reduced[]);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* __GS1_H */

Added jni/zint/backend/hanxin.c.











































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
/*  hanxin.c - Han Xin Code

    libzint - the open source barcode library
    Copyright (C) 2009-2016 Robin Stuart <rstuart114@gmail.com>

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

    1. Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.
    3. Neither the name of the project nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
    SUCH DAMAGE.
 */

/* This code attempts to implement Han Xin Code according to AIMD-015:2010 (Rev 0.8) */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifdef _MSC_VER
#include <malloc.h>
#endif
#include "common.h"
#include "reedsol.h"
#include "hanxin.h"
#include "gb18030.h"
#include "assert.h"

/* Find which submode to use for a text character */
int getsubmode(char input) {
    int submode = 2;

    if ((input >= '0') && (input <= '9')) {
        submode = 1;
    }

    if ((input >= 'A') && (input <= 'Z')) {
        submode = 1;
    }

    if ((input >= 'a') && (input <= 'z')) {
        submode = 1;
    }

    return submode;
}

/* Calculate the approximate length of the binary string */
int calculate_binlength(char mode[], int source[], int length, int eci) {
    int i;
    char lastmode = 't';
    int est_binlen = 0;
    int submode = 1;

    if (eci != 3) {
        est_binlen += 12;
    }

    i = 0;
    do {
        switch (mode[i]) {
            case 'n':
                if (lastmode != 'n') {
                    est_binlen += 14;
                    lastmode = 'n';
                }
                est_binlen += 4;
                break;
            case 't':
                if (lastmode != 't') {
                    est_binlen += 10;
                    lastmode = 't';
                    submode = 1;
                }
                if (getsubmode((char) source[i]) != submode) {
                    est_binlen += 6;
                    submode = getsubmode((char) source[i]);
                }
                est_binlen += 6;
                break;
            case 'b':
                if (lastmode != 'b') {
                    est_binlen += 17;
                    lastmode = 'b';
                }
                est_binlen += 8;
                break;
            case '1':
                if (lastmode != '1') {
                    est_binlen += 16;
                    lastmode = '1';
                }
                est_binlen += 12;
                break;
            case '2':
                if (lastmode != '2') {
                    est_binlen += 16;
                    lastmode = '2';
                }
                est_binlen += 12;
                break;
            case 'd':
                if (lastmode != 'd') {
                    est_binlen += 16;
                    lastmode = 'd';
                }
                est_binlen += 15;
                break;
            case 'f':
                if (lastmode != 'f') {
                    est_binlen += 4;
                    lastmode = 'f';
                }
                est_binlen += 21;
                i++;
                break;
        }
        i++;
    } while (i < length);

    return est_binlen;
}

int isRegion1(int glyph) {
    int first_byte, second_byte;
    int valid = 0;

    first_byte = (glyph & 0xff00) >> 8;
    second_byte = glyph & 0xff;

    if ((first_byte >= 0xb0) && (first_byte <= 0xd7)) {
        if ((second_byte >= 0xa1) && (second_byte <= 0xfe)) {
            valid = 1;
        }
    }

    if ((first_byte >= 0xa1) && (first_byte <= 0xa3)) {
        if ((second_byte >= 0xa1) && (second_byte <= 0xfe)) {
            valid = 1;
        }
    }

    if ((glyph >= 0xa8a1) && (glyph <= 0xa8c0)) {
        valid = 1;
    }

    return valid;
}

int isRegion2(int glyph) {
    int first_byte, second_byte;
    int valid = 0;

    first_byte = (glyph & 0xff00) >> 8;
    second_byte = glyph & 0xff;

    if ((first_byte >= 0xd8) && (first_byte <= 0xf7)) {
        if ((second_byte >= 0xa1) && (second_byte <= 0xfe)) {
            valid = 1;
        }
    }

    return valid;
}

int isDoubleByte(int glyph) {
    int first_byte, second_byte;
    int valid = 0;

    first_byte = (glyph & 0xff00) >> 8;
    second_byte = glyph & 0xff;

    if ((first_byte >= 0x81) && (first_byte <= 0xfe)) {
        if ((second_byte >= 0x40) && (second_byte <= 0x7e)) {
            valid = 1;
        }

        if ((second_byte >= 0x80) && (second_byte <= 0xfe)) {
            valid = 1;
        }
    }

    return valid;
}

int isFourByte(int glyph, int glyph2) {
    int first_byte, second_byte;
    int third_byte, fourth_byte;
    int valid = 0;

    first_byte = (glyph & 0xff00) >> 8;
    second_byte = glyph & 0xff;
    third_byte = (glyph2 & 0xff00) >> 8;
    fourth_byte = glyph2 & 0xff;

    if ((first_byte >= 0x81) && (first_byte <= 0xfe)) {
        if ((second_byte >= 0x30) && (second_byte <= 0x39)) {
            if ((third_byte >= 0x81) && (third_byte <= 0xfe)) {
                if ((fourth_byte >= 0x30) && (fourth_byte <= 0x39)) {
                    valid = 1;
                }
            }
        }
    }

    return valid;
}

/* Calculate mode switching */
void hx_define_mode(char mode[], int source[], int length) {
    int i;
    char lastmode = 't';
    int done;

    i = 0;
    do {
        done = 0;

        if (isRegion1(source[i])) {
            mode[i] = '1';
            done = 1;
            i++;
        }

        if ((done == 0) && (isRegion2(source[i]))) {
            mode[i] = '2';
            done = 1;
            i++;
        }

        if ((done == 0) && (isDoubleByte(source[i]))) {
            mode[i] = 'd';
            done = 1;
            i++;
        }

        if ((done == 0) && (i < length - 1)) {
            if (isFourByte(source[i], source[i + 1])) {
                mode[i] = 'f';
                mode[i + 1] = 'f';
                done = 1;
                i += 2;
            }
        }

        if (done == 0) {
            if ((source[i] >= '0') && (source[i] <= '9')) {
                mode[i] = 'n';
                if (lastmode != 'n') {
                    lastmode = 'n';
                }
            } else {
                if ((source[i] <= 127) && ((source[i] <= 27) || (source[i] >= 32))) {
                    mode[i] = 't';
                    if (lastmode != 't') {
                        lastmode = 't';
                    }
                } else {
                    mode[i] = 'b';
                    if (lastmode != 'b') {
                        lastmode = 'b';
                    }
                }
            }
            i++;
        }
    } while (i < length);
    mode[length] = '\0';
}

/* Convert Text 1 sub-mode character to encoding value, as given in table 3 */
int lookup_text1(char input) {
    int encoding_value = 0;

    if ((input >= '0') && (input <= '9')) {
        encoding_value = input - '0';
    }

    if ((input >= 'A') && (input <= 'Z')) {
        encoding_value = input - 'A' + 10;
    }

    if ((input >= 'a') && (input <= 'z')) {
        encoding_value = input - 'a' + 36;
    }

    return encoding_value;
}

/* Convert Text 2 sub-mode character to encoding value, as given in table 4 */
int lookup_text2(char input) {
    int encoding_value = 0;

    if ((input >= 0) && (input <= 27)) {
        encoding_value = input;
    }

    if ((input >= ' ') && (input <= '/')) {
        encoding_value = input - ' ' + 28;
    }

    if ((input >= '[') && (input <= 96)) {
        encoding_value = input - '[' + 51;
    }

    if ((input >= '{') && (input <= 127)) {
        encoding_value = input - '{' + 57;
    }

    return encoding_value;
}

/* Convert input data to binary stream */
void calculate_binary(char binary[], char mode[], int source[], int length, int eci) {
    int block_length;
    int position = 0;
    int i, p, count, encoding_value;
    int debug = 0;
    int first_byte, second_byte;
    int third_byte, fourth_byte;
    int glyph;
    int submode;

    if (eci != 3) {
        strcat(binary, "1000"); // ECI
        for (p = 0; p < 8; p++) {
            if (eci & (0x80 >> p)) {
                strcat(binary, "1");
            } else {
                strcat(binary, "0");
            }
        }
    }

    do {
        block_length = 0;
        do {
            block_length++;
        } while (mode[position + block_length] == mode[position]);

        switch (mode[position]) {
            case 'n':
                /* Numeric mode */
                /* Mode indicator */
                strcat(binary, "0001");

                if (debug) {
                    printf("Numeric\n");
                }

                i = 0;

                while (i < block_length) {
                    int first = 0, second = 0, third = 0;

                    first = posn(NEON, (char) source[position + i]);
                    count = 1;
                    encoding_value = first;

                    if (i + 1 < block_length && mode[position + i + 1] == 'n') {
                        second = posn(NEON, (char) source[position + i + 1]);
                        count = 2;
                        encoding_value = (encoding_value * 10) + second;

                        if (i + 2 < block_length && mode[position + i + 2] == 'n') {
                            third = posn(NEON, (char) source[position + i + 2]);
                            count = 3;
                            encoding_value = (encoding_value * 10) + third;
                        }
                    }

                    for (p = 0; p < 10; p++) {
                        if (encoding_value & (0x200 >> p)) {
                            strcat(binary, "1");
                        } else {
                            strcat(binary, "0");
                        }
                    }

                    if (debug) {
                        printf("0x%4x (%d)", encoding_value, encoding_value);
                    }

                    i += count;
                }

                /* Mode terminator depends on number of characters in last group (Table 2) */
                switch (count) {
                    case 1:
                        strcat(binary, "1111111101");
                        break;
                    case 2:
                        strcat(binary, "1111111110");
                        break;
                    case 3:
                        strcat(binary, "1111111111");
                        break;
                }

                if (debug) {
                    printf(" (TERM %d)\n", count);
                }

                break;
            case 't':
                /* Text mode */
                if (position != 0) {
                    /* Mode indicator */
                    strcat(binary, "0010");

                    if (debug) {
                        printf("Text\n");
                    }
                }

                submode = 1;

                i = 0;

                while (i < block_length) {

                    if (getsubmode((char) source[i + position]) != submode) {
                        /* Change submode */
                        strcat(binary, "111110");
                        submode = getsubmode((char) source[i + position]);
                        if (debug) {
                            printf("SWITCH ");
                        }
                    }

                    if (submode == 1) {
                        encoding_value = lookup_text1((char) source[i + position]);
                    } else {
                        encoding_value = lookup_text2((char) source[i + position]);
                    }

                    for (p = 0; p < 6; p++) {
                        if (encoding_value & (0x20 >> p)) {
                            strcat(binary, "1");
                        } else {
                            strcat(binary, "0");
                        }
                    }

                    if (debug) {
                        printf("%c (%d) ", (char) source[i], encoding_value);
                    }
                    i++;
                }

                /* Terminator */
                strcat(binary, "111111");

                if (debug) {
                    printf("\n");
                }
                break;
            case 'b':
                /* Binary Mode */
                /* Mode indicator */
                strcat(binary, "0011");

                /* Count indicator */
                for (p = 0; p < 13; p++) {
                    if (block_length & (0x1000 >> p)) {
                        strcat(binary, "1");
                    } else {
                        strcat(binary, "0");
                    }
                }

                if (debug) {
                    printf("Binary (length %d)\n", block_length);
                }

                i = 0;

                while (i < block_length) {

                    /* 8-bit bytes with no conversion */
                    for (p = 0; p < 8; p++) {
                        if (source[i + position] & (0x80 >> p)) {
                            strcat(binary, "1");
                        } else {
                            strcat(binary, "0");
                        }
                    }

                    if (debug) {
                        printf("%d ", source[i + position]);
                    }

                    i++;
                }

                if (debug) {
                    printf("\n");
                }
                break;
            case '1':
                /* Region 1 encoding */
                /* Mode indicator */
                strcat(binary, "0100");

                if (debug) {
                    printf("Region 1\n");
                }

                i = 0;

                while (i < block_length) {
                    first_byte = (source[i + position] & 0xff00) >> 8;
                    second_byte = source[i + position] & 0xff;

                    /* Subset 1 */
                    glyph = (0x5e * (first_byte - 0xb0)) + (second_byte - 0xa1);

                    /* Subset 2 */
                    if ((first_byte >= 0xa1) && (first_byte <= 0xa3)) {
                        if ((second_byte >= 0xa1) && (second_byte <= 0xfe)) {
                            glyph = (0x5e * first_byte - 0xa1) + (second_byte - 0xa1) + 0xeb0;
                        }
                    }

                    /* Subset 3 */
                    if ((source[i + position] >= 0xa8a1) && (source[i + position] <= 0xa8c0)) {
                        glyph = (second_byte - 0xa1) + 0xfca;
                    }

                    if (debug) {
                        printf("%d ", glyph);
                    }

                    for (p = 0; p < 12; p++) {
                        if (glyph & (0x800 >> p)) {
                            strcat(binary, "1");
                        } else {
                            strcat(binary, "0");
                        }
                    }

                    i++;
                }

                /* Terminator */
                strcat(binary, "111111111111");

                if (debug) {
                    printf("\n");
                }

                break;
            case '2':
                /* Region 2 encoding */
                /* Mode indicator */
                strcat(binary, "0101");

                if (debug) {
                    printf("Region 2\n");
                }

                i = 0;

                while (i < block_length) {
                    first_byte = (source[i + position] & 0xff00) >> 8;
                    second_byte = source[i + position] & 0xff;

                    glyph = (0x5e * (first_byte - 0xd8)) + (second_byte - 0xa1);

                    if (debug) {
                        printf("%d ", glyph);
                    }

                    for (p = 0; p < 12; p++) {
                        if (glyph & (0x800 >> p)) {
                            strcat(binary, "1");
                        } else {
                            strcat(binary, "0");
                        }
                    }

                    i++;
                }

                /* Terminator */
                strcat(binary, "111111111111");

                if (debug) {
                    printf("\n");
                }
                break;
            case 'd':
                /* Double byte encoding */
                /* Mode indicator */
                strcat(binary, "0110");

                if (debug) {
                    printf("Double byte\n");
                }

                i = 0;

                while (i < block_length) {
                    first_byte = (source[i + position] & 0xff00) >> 8;
                    second_byte = source[i + position] & 0xff;

                    if (second_byte <= 0x7e) {
                        glyph = (0xbe * (first_byte - 0x81)) + (second_byte - 0x40);
                    } else {
                        glyph = (0xbe * (first_byte - 0x81)) + (second_byte - 0x41);
                    }

                    if (debug) {
                        printf("%d ", glyph);
                    }

                    for (p = 0; p < 15; p++) {
                        if (glyph & (0x4000 >> p)) {
                            strcat(binary, "1");
                        } else {
                            strcat(binary, "0");
                        }
                    }

                    i++;
                }

                /* Terminator */
                strcat(binary, "111111111111111");
                /* Terminator sequence of length 12 is a mistake
                   - confirmed by Wang Yi */

                if (debug) {
                    printf("\n");
                }
                break;
            case 'f':
                /* Four-byte encoding */
                if (debug) {
                    printf("Four byte\n");
                }

                i = 0;

                while (i < block_length) {

                    /* Mode indicator */
                    strcat(binary, "0111");

                    first_byte = (source[i + position] & 0xff00) >> 8;
                    second_byte = source[i + position] & 0xff;
                    third_byte = (source[i + position + 1] & 0xff00) >> 8;
                    fourth_byte = source[i + position + 1] & 0xff;

                    glyph = (0x3138 * (first_byte - 0x81)) + (0x04ec * (second_byte - 0x30)) +
                            (0x0a * (third_byte - 0x81)) + (fourth_byte - 0x30);

                    if (debug) {
                        printf("%d ", glyph);
                    }

                    for (p = 0; p < 15; p++) {
                        if (glyph & (0x4000 >> p)) {
                            strcat(binary, "1");
                        } else {
                            strcat(binary, "0");
                        }
                    }

                    i += 2;
                }

                /* No terminator */

                if (debug) {
                    printf("\n");
                }
                break;

        }

        position += block_length;

    } while (position < length);
}

/* Finder pattern for top left of symbol */
void hx_place_finder_top_left(unsigned char* grid, int size) {
    int xp, yp;
    int x = 0, y = 0;

    int finder[] = {
        1, 1, 1, 1, 1, 1, 1,
        1, 0, 0, 0, 0, 0, 0,
        1, 0, 1, 1, 1, 1, 1,
        1, 0, 1, 0, 0, 0, 0,
        1, 0, 1, 0, 1, 1, 1,
        1, 0, 1, 0, 1, 1, 1,
        1, 0, 1, 0, 1, 1, 1
    };

    for (xp = 0; xp < 7; xp++) {
        for (yp = 0; yp < 7; yp++) {
            if (finder[xp + (7 * yp)] == 1) {
                grid[((yp + y) * size) + (xp + x)] = 0x11;
            } else {
                grid[((yp + y) * size) + (xp + x)] = 0x10;
            }
        }
    }
}

/* Finder pattern for top right and bottom left of symbol */
void hx_place_finder(unsigned char* grid, int size, int x, int y) {
    int xp, yp;

    int finder[] = {
        1, 1, 1, 1, 1, 1, 1,
        0, 0, 0, 0, 0, 0, 1,
        1, 1, 1, 1, 1, 0, 1,
        0, 0, 0, 0, 1, 0, 1,
        1, 1, 1, 0, 1, 0, 1,
        1, 1, 1, 0, 1, 0, 1,
        1, 1, 1, 0, 1, 0, 1
    };

    for (xp = 0; xp < 7; xp++) {
        for (yp = 0; yp < 7; yp++) {
            if (finder[xp + (7 * yp)] == 1) {
                grid[((yp + y) * size) + (xp + x)] = 0x11;
            } else {
                grid[((yp + y) * size) + (xp + x)] = 0x10;
            }
        }
    }
}

/* Finder pattern for bottom right of symbol */
void hx_place_finder_bottom_right(unsigned char* grid, int size) {
    int xp, yp;
    int x = size - 7, y = size - 7;

    int finder[] = {
        1, 1, 1, 0, 1, 0, 1,
        1, 1, 1, 0, 1, 0, 1,
        1, 1, 1, 0, 1, 0, 1,
        0, 0, 0, 0, 1, 0, 1,
        1, 1, 1, 1, 1, 0, 1,
        0, 0, 0, 0, 0, 0, 1,
        1, 1, 1, 1, 1, 1, 1
    };

    for (xp = 0; xp < 7; xp++) {
        for (yp = 0; yp < 7; yp++) {
            if (finder[xp + (7 * yp)] == 1) {
                grid[((yp + y) * size) + (xp + x)] = 0x11;
            } else {
                grid[((yp + y) * size) + (xp + x)] = 0x10;
            }
        }
    }
}

/* Avoid plotting outside symbol or over finder patterns */
void hx_safe_plot(unsigned char *grid, int size, int x, int y, int value) {
    if ((x >= 0) && (x < size)) {
        if ((y >= 0) && (y < size)) {
            if (grid[(y * size) + x] == 0) {
                grid[(y * size) + x] = value;
            }
        }
    }
}

/* Plot an alignment pattern around top and right of a module */
void hx_plot_alignment(unsigned char *grid, int size, int x, int y, int w, int h) {
    int i;
    hx_safe_plot(grid, size, x, y, 0x11);
    hx_safe_plot(grid, size, x - 1, y + 1, 0x10);

    for (i = 1; i <= w; i++) {
        /* Top */
        hx_safe_plot(grid, size, x - i, y, 0x11);
        hx_safe_plot(grid, size, x - i - 1, y + 1, 0x10);
    }

    for (i = 1; i < h; i++) {
        /* Right */
        hx_safe_plot(grid, size, x, y + i, 0x11);
        hx_safe_plot(grid, size, x - 1, y + i + 1, 0x10);
    }
}

/* Plot assistant alignment patterns */
void hx_plot_assistant(unsigned char *grid, int size, int x, int y) {
    hx_safe_plot(grid, size, x - 1, y - 1, 0x10);
    hx_safe_plot(grid, size, x, y - 1, 0x10);
    hx_safe_plot(grid, size, x + 1, y - 1, 0x10);
    hx_safe_plot(grid, size, x - 1, y, 0x10);
    hx_safe_plot(grid, size, x, y, 0x11);
    hx_safe_plot(grid, size, x + 1, y, 0x10);
    hx_safe_plot(grid, size, x - 1, y + 1, 0x10);
    hx_safe_plot(grid, size, x, y + 1, 0x10);
    hx_safe_plot(grid, size, x + 1, y + 1, 0x10);
}

/* Put static elements in the grid */
void hx_setup_grid(unsigned char* grid, int size, int version) {
    int i, j;

    for (i = 0; i < size; i++) {
        for (j = 0; j < size; j++) {
            grid[(i * size) + j] = 0;
        }
    }

    /* Add finder patterns */
    hx_place_finder_top_left(grid, size);
    hx_place_finder(grid, size, 0, size - 7);
    hx_place_finder(grid, size, size - 7, 0);
    hx_place_finder_bottom_right(grid, size);

    /* Add finder pattern separator region */
    for (i = 0; i < 8; i++) {
        /* Top left */
        grid[(7 * size) + i] = 0x10;
        grid[(i * size) + 7] = 0x10;

        /* Top right */
        grid[(7 * size) + (size - i - 1)] = 0x10;
        grid[((size - i - 1) * size) + 7] = 0x10;

        /* Bottom left */
        grid[(i * size) + (size - 8)] = 0x10;
        grid[((size - 8) * size) + i] = 0x10;

        /* Bottom right */
        grid[((size - 8) * size) + (size - i - 1)] = 0x10;
        grid[((size - i - 1) * size) + (size - 8)] = 0x10;
    }

    /* Reserve function information region */
    for (i = 0; i < 9; i++) {
        /* Top left */
        grid[(8 * size) + i] = 0x10;
        grid[(i * size) + 8] = 0x10;

        /* Top right */
        grid[(8 * size) + (size - i - 1)] = 0x10;
        grid[((size - i - 1) * size) + 8] = 0x10;

        /* Bottom left */
        grid[(i * size) + (size - 9)] = 0x10;
        grid[((size - 9) * size) + i] = 0x10;

        /* Bottom right */
        grid[((size - 9) * size) + (size - i - 1)] = 0x10;
        grid[((size - i - 1) * size) + (size - 9)] = 0x10;
    }

    if (version > 3) {
        int k = hx_module_k[version - 1];
        int r = hx_module_r[version - 1];
        int m = hx_module_m[version - 1];
        int x, y, row_switch, column_switch;
        int module_height, module_width;
        int mod_x, mod_y;

        /* Add assistant alignment patterns to left and right */
        y = 0;
        mod_y = 0;
        do {
            if (mod_y < m) {
                module_height = k;
            } else {
                module_height = r - 1;
            }

            if ((mod_y % 2) == 0) {
                if ((m % 2) == 1) {
                    hx_plot_assistant(grid, size, 0, y);
                }
            } else {
                if ((m % 2) == 0) {
                    hx_plot_assistant(grid, size, 0, y);
                }
                hx_plot_assistant(grid, size, size - 1, y);
            }

            mod_y++;
            y += module_height;
        } while (y < size);

        /* Add assistant alignment patterns to top and bottom */
        x = (size - 1);
        mod_x = 0;
        do {
            if (mod_x < m) {
                module_width = k;
            } else {
                module_width = r - 1;
            }

            if ((mod_x % 2) == 0) {
                if ((m % 2) == 1) {
                    hx_plot_assistant(grid, size, x, (size - 1));
                }
            } else {
                if ((m % 2) == 0) {
                    hx_plot_assistant(grid, size, x, (size - 1));
                }
                hx_plot_assistant(grid, size, x, 0);
            }

            mod_x++;
            x -= module_width;
        } while (x >= 0);

        /* Add alignment pattern */
        column_switch = 1;
        y = 0;
        mod_y = 0;
        do {
            if (mod_y < m) {
                module_height = k;
            } else {
                module_height = r - 1;
            }

            if (column_switch == 1) {
                row_switch = 1;
                column_switch = 0;
            } else {
                row_switch = 0;
                column_switch = 1;
            }

            x = (size - 1);
            mod_x = 0;
            do {
                if (mod_x < m) {
                    module_width = k;
                } else {
                    module_width = r - 1;
                }

                if (row_switch == 1) {
                    if (!(y == 0 && x == (size - 1))) {
                        hx_plot_alignment(grid, size, x, y, module_width, module_height);
                    }
                    row_switch = 0;
                } else {
                    row_switch = 1;
                }
                mod_x++;
                x -= module_width;
            } while (x >= 0);

            mod_y++;
            y += module_height;
        } while (y < size);
    }
}

/* Calculate error correction codes */
void hx_add_ecc(unsigned char fullstream[], unsigned char datastream[], int version, int ecc_level) {
    unsigned char data_block[180];
    unsigned char ecc_block[36];
    int i, j, block;
    int batch_size, data_length, ecc_length;
    int input_position = -1;
    int output_position = -1;

    for (i = 0; i < 3; i++) {
        batch_size = hx_table_d1[(((version - 1) + (ecc_level - 1)) * 9) + (3 * i)];
        data_length = hx_table_d1[(((version - 1) + (ecc_level - 1)) * 9) + (3 * i) + 1];
        ecc_length = hx_table_d1[(((version - 1) + (ecc_level - 1)) * 9) + (3 * i) + 2];

        for (block = 0; block < batch_size; block++) {
            for (j = 0; j < data_length; j++) {
                input_position++;
                output_position++;
                data_block[j] = datastream[input_position];
                fullstream[output_position] = datastream[input_position];
            }

            rs_init_gf(0x163); // x^8 + x^6 + x^5 + x + 1 = 0
            rs_init_code(ecc_length, 1);
            rs_encode(data_length, data_block, ecc_block);
            rs_free();

            for (j = 0; j < ecc_length; j++) {
                output_position++;
                fullstream[output_position] = ecc_block[ecc_length - j - 1];
            }
        }
    }
}

/* Rearrange data in batches of 13 codewords (section 5.8.2) */
void make_picket_fence(unsigned char fullstream[], unsigned char picket_fence[], int streamsize) {
    int i, start;
    int output_position = 0;

    for (start = 0; start < 13; start++) {
        for (i = start; i < streamsize; i += 13) {
            if (i < streamsize) {
                picket_fence[output_position] = fullstream[i];
                output_position++;
            }
        }
    }
}

/* Evaluate a bitmask according to table 9 */
int hx_evaluate(unsigned char *eval, int size, int pattern) {
    int x, y, block, weight;
    int result = 0;
    char state;
    int p;
    int a, b, afterCount, beforeCount;
#ifndef _MSC_VER
    char local[size * size];
#else
    char* local = (char *) _alloca((size * size) * sizeof (char));
#endif

    /* all four bitmask variants have been encoded in the 4 bits of the bytes
     * that make up the grid array. select them for evaluation according to the
     * desired pattern.*/
    for (x = 0; x < size; x++) {
        for (y = 0; y < size; y++) {
            if ((eval[(y * size) + x] & (0x01 << pattern)) != 0) {
                local[(y * size) + x] = '1';
            } else {
                local[(y * size) + x] = '0';
            }
        }
    }

    /* Test 1: 1:1:1:1:3  or 3:1:1:1:1 ratio pattern in row/column */
    /* Vertical */
    for (x = 0; x < size; x++) {
        for (y = 0; y < (size - 7); y++) {
            p = 0;
            for (weight = 0; weight < 7; weight++) {
                if (local[((y + weight) * size) + x] == '1') {
                    p += (0x40 >> weight);
                }
            }
            if ((p == 0x57) || (p = 0x75)) {
                /* Pattern found, check before and after */
                beforeCount = 0;
                for (b = (y - 3); b < y; b++) {
                    if (b < 0) {
                        beforeCount++;
                    } else {
                        if (local[(b * size) + x] == '0') {
                            beforeCount++;
                        } else {
                            beforeCount = 0;
                        }
                    }
                }

                afterCount = 0;
                for (a = (y + 7); a <= (y + 9); a++) {
                    if (a >= size) {
                        afterCount++;
                    } else {
                        if (local[(a * size) + x] == '0') {
                            afterCount++;
                        } else {
                            afterCount = 0;
                        }
                    }
                }

                if ((beforeCount == 3) || (afterCount == 3)) {
                    /* Pattern is preceeded or followed by light area
                       3 modules wide */
                    result += 50;
                }
            }
        }
    }

    /* Horizontal */
    for (y = 0; y < size; y++) {
        for (x = 0; x < (size - 7); x++) {
            p = 0;
            for (weight = 0; weight < 7; weight++) {
                if (local[(y * size) + x + weight] == '1') {
                    p += (0x40 >> weight);
                }
            }
            if ((p == 0x57) || (p = 0x75)) {
                /* Pattern found, check before and after */
                beforeCount = 0;
                for (b = (x - 3); b < x; b++) {
                    if (b < 0) {
                        beforeCount++;
                    } else {
                        if (local[(y * size) + b] == '0') {
                            beforeCount++;
                        } else {
                            beforeCount = 0;
                        }
                    }
                }

                afterCount = 0;
                for (a = (x + 7); a <= (x + 9); a++) {
                    if (a >= size) {
                        afterCount++;
                    } else {
                        if (local[(y * size) + a] == '0') {
                            afterCount++;
                        } else {
                            afterCount = 0;
                        }
                    }
                }

                if ((beforeCount == 3) || (afterCount == 3)) {
                    /* Pattern is preceeded or followed by light area
                       3 modules wide */
                    result += 50;
                }
            }
        }
    }

    /* Test 2: Adjacent modules in row/column in same colour */
    /* In AIMD-15 section 5.8.3.2 it is stated... “In Table 9 below, i refers to the row
     * position of the module.” - however i being the length of the run of the
     * same colour (i.e. "block" below) in the same fashion as ISO/IEC 18004
     * makes more sense. -- Confirmed by Wang Yi */

    /* Vertical */
    for (x = 0; x < size; x++) {
        state = local[x];
        block = 0;
        for (y = 0; y < size; y++) {
            if (local[(y * size) + x] == state) {
                block++;
            } else {
                if (block > 3) {
                    result += (3 + block) * 4;
                }
                block = 0;
                state = local[(y * size) + x];
            }
        }
        if (block > 3) {
            result += (3 + block) * 4;
        }
    }

    /* Horizontal */
    for (y = 0; y < size; y++) {
        state = local[y * size];
        block = 0;
        for (x = 0; x < size; x++) {
            if (local[(y * size) + x] == state) {
                block++;
            } else {
                if (block > 3) {
                    result += (3 + block) * 4;
                }
                block = 0;
                state = local[(y * size) + x];
            }
        }
        if (block > 3) {
            result += (3 + block) * 4;
        }
    }

    return result;
}

/* Apply the four possible bitmasks for evaluation */
int hx_apply_bitmask(unsigned char *grid, int size) {
    int x, y;
    int i, j;
    int pattern, penalty[4];
    int best_pattern, best_val;
    int bit;
    unsigned char p;

#ifndef _MSC_VER
    unsigned char mask[size * size];
    unsigned char eval[size * size];
#else
    unsigned char* mask = (unsigned char *) _alloca((size * size) * sizeof (unsigned char));
    unsigned char* eval = (unsigned char *) _alloca((size * size) * sizeof (unsigned char));
#endif

    /* Perform data masking */
    for (x = 0; x < size; x++) {
        for (y = 0; y < size; y++) {
            mask[(y * size) + x] = 0x00;
            j = x + 1;
            i = y + 1;

            if (!(grid[(y * size) + x] & 0xf0)) {
                if ((i + j) % 2 == 0) {
                    mask[(y * size) + x] += 0x02;
                }
                if ((((i + j) % 3) + (j % 3)) % 2 == 0) {
                    mask[(y * size) + x] += 0x04;
                }
                if (((i % j) + (j % i) + (i % 3) + (j % 3)) % 2 == 0) {
                    mask[(y * size) + x] += 0x08;
                }
            }
        }
    }

    // apply data masks to grid, result in eval
    for (x = 0; x < size; x++) {
        for (y = 0; y < size; y++) {
            if (grid[(y * size) + x] & 0x01) {
                p = 0xff;
            } else {
                p = 0x00;
            }

            eval[(y * size) + x] = mask[(y * size) + x] ^ p;
        }
    }

    /* Evaluate result */
    for (pattern = 0; pattern < 4; pattern++) {
        penalty[pattern] = hx_evaluate(eval, size, pattern);
    }

    best_pattern = 0;
    best_val = penalty[0];
    for (pattern = 1; pattern < 4; pattern++) {
        if (penalty[pattern] < best_val) {
            best_pattern = pattern;
            best_val = penalty[pattern];
        }
    }

    /* Apply mask */
    for (x = 0; x < size; x++) {
        for (y = 0; y < size; y++) {
            bit = 0;
            switch (best_pattern) {
                case 0: if (mask[(y * size) + x] & 0x01) {
                        bit = 1;
                    }
                    break;
                case 1: if (mask[(y * size) + x] & 0x02) {
                        bit = 1;
                    }
                    break;
                case 2: if (mask[(y * size) + x] & 0x04) {
                        bit = 1;
                    }
                    break;
                case 3: if (mask[(y * size) + x] & 0x08) {
                        bit = 1;
                    }
                    break;
            }
            if (bit == 1) {
                if (grid[(y * size) + x] & 0x01) {
                    grid[(y * size) + x] = 0x00;
                } else {
                    grid[(y * size) + x] = 0x01;
                }
            }
        }
    }

    return best_pattern;
}

/* Han Xin Code - main */
int han_xin(struct zint_symbol *symbol, const unsigned char source[], int length) {
    int est_binlen;
    int ecc_level = symbol->option_1;
    int i, j, version, posn = 0, glyph, glyph2;
    int data_codewords = 0, size;
    int est_codewords;
    int bitmask;
    int error_number;
    char function_information[36];
    unsigned char fi_cw[3] = {0, 0, 0};
    unsigned char fi_ecc[4];

#ifndef _MSC_VER
    int utfdata[length + 1];
    int gbdata[(length + 1) * 2];
    char mode[length + 1];
#else
    int* utfdata = (int *) _alloca((length + 1) * sizeof (int));
    int* gbdata = (int *) _alloca(((length + 1) * 2) * sizeof (int));
    char* mode = (char *) _alloca((length + 1) * sizeof (char));
    char* binary;
    unsigned char *datastream;
    unsigned char *fullstream;
    unsigned char *picket_fence;
    unsigned char *grid;
#endif

    if ((symbol->input_mode == DATA_MODE) || (symbol->eci != 3)) {
        for (i = 0; i < length; i++) {
            gbdata[i] = (int) source[i];
        }
    } else {
        /* Convert Unicode input to GB-18030 */
        error_number = utf8toutf16(symbol, source, utfdata, &length);
        if (error_number != 0) {
            return error_number;
        }

        posn = 0;
        for (i = 0; i < length; i++) {
            if (utfdata[i] <= 0x7f) {
                gbdata[posn] = utfdata[i];
                posn++;
            } else {
                j = 0;
                glyph = 0;
                do {
                    if (gb18030_twobyte_lookup[j * 2] == utfdata[i]) {
                        glyph = gb18030_twobyte_lookup[(j * 2) + 1];
                    }
                    j++;
                } while ((j < 23940) && (glyph == 0));

                if (glyph == 0) {
                    j = 0;
                    glyph = 0;
                    glyph2 = 0;
                    do {
                        if (gb18030_fourbyte_lookup[j * 3] == utfdata[i]) {
                            glyph = gb18030_fourbyte_lookup[(j * 3) + 1];
                            glyph2 = gb18030_fourbyte_lookup[(j * 3) + 2];
                        }
                        j++;
                    } while ((j < 6793) && (glyph == 0));
                    if (glyph == 0) {
                        strcpy(symbol->errtxt, "Unknown character in input data (E40)");
                        return ZINT_ERROR_INVALID_DATA;
                    } else {
                        gbdata[posn] = glyph;
                        gbdata[posn + 1] = glyph2;
                        posn += 2;
                    }
                } else {
                    gbdata[posn] = glyph;
                    posn++;
                }
            }
        }
        length = posn;
    }

    hx_define_mode(mode, gbdata, length);

    est_binlen = calculate_binlength(mode, gbdata, length, symbol->eci);
    est_codewords = est_binlen / 8;
    if (est_binlen % 8 != 0) {
        est_codewords++;
    }

#ifndef _MSC_VER
    char binary[est_binlen + 1];
#else
    binary = (char *) _alloca((est_binlen + 10) * sizeof (char));
#endif
    memset(binary, 0, (est_binlen + 1) * sizeof (char));

    if ((ecc_level <= 0) || (ecc_level >= 5)) {
        ecc_level = 1;
    }

    calculate_binary(binary, mode, gbdata, length, symbol->eci);

    version = 85;
    for (i = 84; i > 0; i--) {
        switch (ecc_level) {
            case 1:
                if (hx_data_codewords_L1[i - 1] > est_codewords) {
                    version = i;
                    data_codewords = hx_data_codewords_L1[i - 1];
                }
                break;
            case 2:
                if (hx_data_codewords_L2[i - 1] > est_codewords) {
                    version = i;
                    data_codewords = hx_data_codewords_L2[i - 1];
                }
                break;
            case 3:
                if (hx_data_codewords_L3[i - 1] > est_codewords) {
                    version = i;
                    data_codewords = hx_data_codewords_L3[i - 1];
                }
                break;
            case 4:
                if (hx_data_codewords_L4[i - 1] > est_codewords) {
                    version = i;
                    data_codewords = hx_data_codewords_L4[i - 1];
                }
                break;
            default:
                assert(0);
                break;
        }
    }

    if (version == 85) {
        strcpy(symbol->errtxt, "Input too long for selected error correction level (E41)");
        return ZINT_ERROR_TOO_LONG;
    }

    if ((symbol->option_2 < 0) || (symbol->option_2 > 84)) {
        symbol->option_2 = 0;
    }

    if (symbol->option_2 > version) {
        version = symbol->option_2;
    }

    /* If there is spare capacity, increase the level of ECC */

    if ((ecc_level == 1) && (est_codewords < hx_data_codewords_L2[version - 1])) {
        ecc_level = 2;
        data_codewords = hx_data_codewords_L2[version - 1];
    }

    if ((ecc_level == 2) && (est_codewords < hx_data_codewords_L3[version - 1])) {
        ecc_level = 3;
        data_codewords = hx_data_codewords_L3[version - 1];
    }

    if ((ecc_level == 3) && (est_codewords < hx_data_codewords_L4[version - 1])) {
        ecc_level = 4;
        data_codewords = hx_data_codewords_L4[version - 1];
    }

    //printf("Version %d, ECC %d\n", version, ecc_level);

    size = (version * 2) + 21;

#ifndef _MSC_VER
    unsigned char datastream[data_codewords];
    unsigned char fullstream[hx_total_codewords[version - 1]];
    unsigned char picket_fence[hx_total_codewords[version - 1]];
    unsigned char grid[size * size];
#else
    datastream = (unsigned char *) _alloca((data_codewords) * sizeof (unsigned char));
    fullstream = (unsigned char *) _alloca((hx_total_codewords[version - 1]) * sizeof (unsigned char));
    picket_fence = (unsigned char *) _alloca((hx_total_codewords[version - 1]) * sizeof (unsigned char));
    grid = (unsigned char *) _alloca((size * size) * sizeof (unsigned char));
#endif

    for (i = 0; i < data_codewords; i++) {
        datastream[i] = 0;
    }

    for (i = 0; i < est_binlen; i++) {
        if (binary[i] == '1') {
            datastream[i / 8] += 0x80 >> (i % 8);
        }
    }

    hx_setup_grid(grid, size, version);

    hx_add_ecc(fullstream, datastream, version, ecc_level);

    make_picket_fence(fullstream, picket_fence, hx_total_codewords[version - 1]);

    /* Populate grid */
    j = 0;
    for (i = 0; i < (size * size); i++) {
        if (grid[i] == 0x00) {
            if (j < (hx_total_codewords[version - 1] * 8)) {
                if (picket_fence[(j / 8)] & (0x80 >> (j % 8))) {
                    grid[i] = 0x01;
                }
                j++;
            }
        }
    }

    bitmask = hx_apply_bitmask(grid, size);

    /* Form function information string */
    for (i = 0; i < 34; i++) {
        if (i % 2) {
            function_information[i] = '1';
        } else {
            function_information[i] = '0';
        }
    }
    function_information[34] = '\0';

    for (i = 0; i < 8; i++) {
        if ((version + 20) & (0x80 >> i)) {
            function_information[i] = '1';
        } else {
            function_information[i] = '0';
        }
    }

    for (i = 0; i < 2; i++) {
        if (ecc_level & (0x02 >> i)) {
            function_information[i + 8] = '1';
        } else {
            function_information[i + 8] = '0';
        }
    }

    for (i = 0; i < 2; i++) {
        if (bitmask & (0x02 >> i)) {
            function_information[i + 10] = '1';
        } else {
            function_information[i + 10] = '0';
        }
    }



    for (i = 0; i < 3; i++) {
        for (j = 0; j < 4; j++) {
            if (function_information[(i * 4) + j] == '1') {
                fi_cw[i] += (0x08 >> j);
            }
        }
    }

    rs_init_gf(0x13);
    rs_init_code(4, 1);
    rs_encode(3, fi_cw, fi_ecc);
    rs_free();

    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            if (fi_ecc[3 - i] & (0x08 >> j)) {
                function_information[(i * 4) + j + 12] = '1';
            } else {
                function_information[(i * 4) + j + 12] = '0';
            }
        }
    }

    /* Add function information to symbol */
    for (i = 0; i < 9; i++) {
        if (function_information[i] == '1') {
            grid[(8 * size) + i] = 0x01;
            grid[((size - 8 - 1) * size) + (size - i - 1)] = 0x01;
        }
        if (function_information[i + 8] == '1') {
            grid[((8 - i) * size) + 8] = 0x01;
            grid[((size - 8 - 1 + i) * size) + (size - 8 - 1)] = 0x01;
        }
        if (function_information[i + 17] == '1') {
            grid[(i * size) + (size - 1 - 8)] = 0x01;
            grid[((size - 1 - i) * size) + 8] = 0x01;
        }
        if (function_information[i + 25] == '1') {
            grid[(8 * size) + (size - 1 - 8 + i)] = 0x01;
            grid[((size - 1 - 8) * size) + (8 - i)] = 0x01;
        }
    }

    symbol->width = size;
    symbol->rows = size;

    for (i = 0; i < size; i++) {
        for (j = 0; j < size; j++) {
            if (grid[(i * size) + j] & 0x01) {
                set_module(symbol, i, j);
            }
        }
        symbol->row_height[i] = 1;
    }

    return 0;
}

Added jni/zint/backend/hanxin.h.

























































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
/*  hanxin.h - definitions for Han Xin code

    libzint - the open source barcode library
    Copyright (C) 2009-2016 Robin Stuart <rstuart114@gmail.com>
    Copyright (C) 2016 Zoe Stuart

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

    1. Redistributions of source code must retain the above copyright 
       notice, this list of conditions and the following disclaimer.  
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.  
    3. Neither the name of the project nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission. 

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
    SUCH DAMAGE.
 */

/* Data from table B1: Data capacity of Han Xin Code */
static const int hx_total_codewords[] = {
    25, 37, 50, 54, 69, 84, 100, 117, 136, 155, 161, 181, 203, 225, 249,
    273, 299, 325, 353, 381, 411, 422, 453, 485, 518, 552, 587, 623, 660,
    698, 737, 754, 794, 836, 878, 922, 966, 1011, 1058, 1105, 1126, 1175,
    1224, 1275, 1327, 1380, 1434, 1489, 1513, 1569, 1628, 1686, 1745, 1805,
    1867, 1929, 1992, 2021, 2086, 2151, 2218, 2286, 2355, 2425, 2496, 2528,
    2600, 2673, 2749, 2824, 2900, 2977, 3056, 3135, 3171, 3252, 3334, 3416,
    3500, 3585, 3671, 3758, 3798, 3886
};

static const int hx_data_codewords_L1[] = {
    21, 31, 42, 46, 57, 70, 84, 99, 114, 131, 135, 153, 171, 189, 209, 229,
    251, 273, 297, 321, 345, 354, 381, 407, 436, 464, 493, 523, 554, 586, 619,
    634, 666, 702, 738, 774, 812, 849, 888, 929, 946, 987, 1028, 1071, 1115,
    1160, 1204, 1251, 1271, 1317, 1368, 1416, 1465, 1517, 1569, 1621, 1674,
    1697, 1752, 1807, 1864, 1920, 1979, 2037, 2096, 2124, 2184, 2245, 2309,
    2372, 2436, 2501, 2568, 2633, 2663, 2732, 2800, 2870, 2940, 3011,
    3083, 3156, 3190, 3264
};

static const int hx_data_codewords_L2[] = {
    17, 25, 34, 38, 49, 58, 70, 81, 96, 109, 113, 127, 143, 157, 175, 191, 209,
    227, 247, 267, 287, 296, 317, 339, 362, 386, 411, 437, 462, 488, 515, 528,
    556, 586, 614, 646, 676, 707, 740, 773, 788, 823, 856, 893, 929, 966, 1004,
    1043, 1059, 1099, 1140, 1180, 1221, 1263, 1307, 1351, 1394, 1415, 1460,
    1505, 1552, 1600, 1649, 1697, 1748, 1770, 1820, 1871, 1925, 1976, 2030,
    2083, 2140, 2195, 2219, 2276, 2334, 2392, 2450, 2509, 2569, 2630, 2658,
    2720
};

static const int hx_data_codewords_L3[] = {
    13, 19, 26, 30, 37, 46, 54, 63, 74, 83, 87, 97, 109, 121, 135, 147, 161,
    175, 191, 205, 221, 228, 245, 261, 280, 298, 317, 337, 358, 376, 397, 408,
    428, 452, 474, 498, 522, 545, 572, 597, 608, 635, 660, 689, 717, 746, 774,
    805, 817, 847, 880, 910, 943, 975, 1009, 1041, 1076, 1091, 1126, 1161, 1198,
    1234, 1271, 1309, 1348, 1366, 1404, 1443, 1485, 1524, 1566, 1607, 1650, 1693,
    1713, 1756, 1800, 1844, 1890, 1935, 1983, 2030, 2050, 2098
};

static const int hx_data_codewords_L4[] = {
    9, 15, 20, 22, 27, 34, 40, 47, 54, 61, 65, 73, 81, 89, 99, 109, 119, 129,
    141, 153, 165, 168, 181, 195, 208, 220, 235, 251, 264, 280, 295, 302, 318,
    334, 352, 368, 386, 405, 424, 441, 450, 469, 490, 509, 531, 552, 574, 595, 605,
    627, 652, 674, 697, 721, 747, 771, 796, 809, 834, 861, 892, 914, 941, 969, 998,
    1012, 1040, 1069, 1099, 1130, 1160, 1191, 1222, 1253, 1269, 1300, 1334,
    1366, 1400, 1433, 1469, 1504, 1520, 1554
};

/* Value 'k' from Annex A */
static const int hx_module_k[] = {
    0, 0, 0, 14, 16, 16, 17, 18, 19, 20,
    14, 15, 16, 16, 17, 17, 18, 19, 20, 20,
    21, 16, 17, 17, 18, 18, 19, 19, 20, 20,
    21, 17, 17, 18, 18, 19, 19, 19, 20, 20,
    17, 17, 18, 18, 18, 19, 19, 19, 17, 17,
    18, 18, 18, 18, 19, 19, 19, 17, 17, 18,
    18, 18, 18, 19, 19, 17, 17, 17, 18, 18,
    18, 18, 19, 19, 17, 17, 17, 18, 18, 18,
    18, 18, 17, 17
};

/* Value 'r' from Annex A */
static const int hx_module_r[] = {
    0, 0, 0, 15, 15, 17, 18, 19, 20, 21,
    15, 15, 15, 17, 17, 19, 19, 19, 19, 21,
    21, 17, 16, 18, 17, 19, 18, 20, 19, 21,
    20, 17, 19, 17, 19, 17, 19, 21, 19, 21,
    18, 20, 17, 19, 21, 18, 20, 22, 17, 19,
    15, 17, 19, 21, 17, 19, 21, 18, 20, 15,
    17, 19, 21, 16, 18, 17, 19, 21, 15, 17,
    19, 21, 15, 17, 18, 20, 22, 15, 17, 19,
    21, 23, 17, 19
};

/* Value of 'm' from Annex A */
static const int hx_module_m[] = {
    0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 3, 3, 3, 3, 3, 3, 3, 3, 3,
    3, 4, 4, 4, 4, 4, 4, 4, 4, 4,
    5, 5, 5, 5, 5, 5, 5, 5, 6, 6,
    6, 6, 6, 6, 6, 6, 6, 7, 7, 7,
    7, 7, 7, 7, 7, 8, 8, 8, 8, 8,
    8, 8, 8, 8, 9, 9, 9, 9, 9, 9,
    9, 9, 10, 10
};

/* Error correction block sizes from Table D1 */
static const int hx_table_d1[] = {
    /* #blocks, k, 2t, #blocks, k, 2t, #blocks, k, 2t */
    1, 21, 4, 0, 0, 0, 0, 0, 0, // version 1
    1, 17, 8, 0, 0, 0, 0, 0, 0,
    1, 13, 12, 0, 0, 0, 0, 0, 0,
    1, 9, 16, 0, 0, 0, 0, 0, 0,
    1, 31, 6, 0, 0, 0, 0, 0, 0, // version 2
    1, 25, 12, 0, 0, 0, 0, 0, 0,
    1, 19, 18, 0, 0, 0, 0, 0, 0,
    1, 15, 22, 0, 0, 0, 0, 0, 0,
    1, 42, 8, 0, 0, 0, 0, 0, 0, // version 3
    1, 34, 16, 0, 0, 0, 0, 0, 0,
    1, 26, 24, 0, 0, 0, 0, 0, 0,
    1, 20, 30, 0, 0, 0, 0, 0, 0,
    1, 46, 8, 0, 0, 0, 0, 0, 0, // version 4
    1, 38, 16, 0, 0, 0, 0, 0, 0,
    1, 30, 24, 0, 0, 0, 0, 0, 0,
    1, 22, 32, 0, 0, 0, 0, 0, 0,
    1, 57, 12, 0, 0, 0, 0, 0, 0, // version 5
    1, 49, 20, 0, 0, 0, 0, 0, 0,
    1, 37, 32, 0, 0, 0, 0, 0, 0,
    1, 14, 20, 1, 13, 22, 0, 0, 0,
    1, 70, 14, 0, 0, 0, 0, 0, 0, // version 6
    1, 58, 26, 0, 0, 0, 0, 0, 0,
    1, 24, 20, 1, 22, 18, 0, 0, 0,
    1, 16, 24, 1, 18, 26, 0, 0, 0,
    1, 84, 16, 0, 0, 0, 0, 0, 0, // version 7
    1, 70, 30, 0, 0, 0, 0, 0, 0,
    1, 26, 22, 1, 28, 24, 0, 0, 0,
    2, 14, 20, 1, 12, 20, 0, 0, 0,
    1, 99, 18, 0, 0, 0, 0, 0, 0, // version 8
    1, 40, 18, 1, 41, 18, 0, 0, 0,
    1, 31, 26, 1, 32, 28, 0, 0, 0,
    2, 16, 24, 1, 15, 22, 0, 0, 0,
    1, 114, 22, 0, 0, 0, 0, 0, 0, // version 9
    2, 48, 20, 0, 0, 0, 0, 0, 0,
    2, 24, 20, 1, 26, 22, 0, 0, 0,
    2, 18, 28, 1, 18, 26, 0, 0, 0,
    1, 131, 24, 0, 0, 0, 0, 0, 0, // version 10
    1, 52, 22, 1, 57, 24, 0, 0, 0,
    2, 27, 24, 1, 29, 24, 0, 0, 0,
    2, 21, 32, 1, 19, 30, 0, 0, 0,
    1, 135, 26, 0, 0, 0, 0, 0, 0, // version 11
    1, 56, 24, 1, 57, 24, 0, 0, 0,
    2, 28, 24, 1, 31, 26, 0, 0, 0,
    2, 22, 32, 1, 21, 32, 0, 0, 0,
    1, 153, 28, 0, 0, 0, 0, 0, 0, // version 12
    1, 62, 26, 1, 65, 28, 0, 0, 0,
    2, 32, 28, 1, 33, 28, 0, 0, 0,
    3, 17, 26, 1, 22, 30, 0, 0, 0,
    1, 86, 16, 1, 85, 16, 0, 0, 0, // version 13
    1, 71, 30, 1, 72, 30, 0, 0, 0,
    2, 37, 32, 1, 35, 30, 0, 0, 0,
    3, 20, 30, 1, 21, 32, 0, 0, 0,
    1, 94, 18, 1, 95, 18, 0, 0, 0, // version 14
    2, 51, 22, 1, 55, 24, 0, 0, 0,
    3, 30, 26, 1, 31, 26, 0, 0, 0,
    4, 18, 28, 1, 17, 24, 0, 0, 0,
    1, 104, 20, 1, 105, 20, 0, 0, 0, // version 15
    2, 57, 24, 1, 61, 26, 0, 0, 0,
    3, 33, 28, 1, 36, 30, 0, 0, 0,
    4, 20, 30, 1, 19, 30, 0, 0, 0,
    1, 115, 22, 1, 114, 22, 0, 0, 0, // version 16
    2, 65, 28, 1, 61, 26, 0, 0, 0,
    3, 38, 32, 1, 33, 30, 0, 0, 0,
    5, 19, 28, 1, 14, 24, 0, 0, 0,
    1, 126, 24, 1, 125, 24, 0, 0, 0, // version 17
    2, 70, 30, 1, 69, 30, 0, 0, 0,
    4, 33, 28, 1, 29, 26, 0, 0, 0,
    5, 20, 30, 1, 19, 30, 0, 0, 0,
    1, 136, 26, 1, 137, 26, 0, 0, 0, //version 18
    3, 56, 24, 1, 59, 26, 0, 0, 0,
    5, 35, 30, 0, 0, 0, 0, 0, 0,
    6, 18, 28, 1, 21, 28, 0, 0, 0,
    1, 148, 28, 1, 149, 28, 0, 0, 0, // version 19
    3, 61, 26, 1, 64, 28, 0, 0, 0,
    7, 24, 20, 1, 23, 22, 0, 0, 0,
    6, 20, 30, 1, 21, 32, 0, 0, 0,
    3, 107, 20, 0, 0, 0, 0, 0, 0, // version 20
    3, 65, 28, 1, 72, 30, 0, 0, 0,
    7, 26, 22, 1, 23, 22, 0, 0, 0,
    7, 19, 28, 1, 20, 32, 0, 0, 0,
    3, 115, 22, 0, 0, 0, 0, 0, 0, // version 21
    4, 56, 24, 1, 63, 28, 0, 0, 0,
    7, 28, 24, 1, 25, 22, 0, 0, 0,
    8, 18, 28, 1, 21, 22, 0, 0, 0,
    2, 116, 22, 1, 122, 24, 0, 0, 0, // version 22
    4, 56, 24, 1, 72, 30, 0, 0, 0,
    7, 28, 24, 1, 32, 26, 0, 0, 0,
    8, 18, 28, 1, 24, 30, 0, 0, 0,
    3, 127, 24, 0, 0, 0, 0, 0, 0, // version 23
    5, 51, 22, 1, 62, 26, 0, 0, 0,
    7, 30, 26, 1, 35, 26, 0, 0, 0,
    8, 20, 30, 1, 21, 32, 0, 0, 0,
    2, 135, 26, 1, 137, 26, 0, 0, 0, // version 24
    5, 56, 24, 1, 59, 26, 0, 0, 0,
    7, 33, 28, 1, 30, 28, 0, 0, 0,
    11, 16, 24, 1, 19, 26, 0, 0, 0,
    3, 105, 20, 1, 121, 22, 0, 0, 0, // version 25
    5, 61, 26, 1, 57, 26, 0, 0, 0,
    9, 28, 24, 1, 28, 22, 0, 0, 0,
    10, 19, 28, 1, 18, 30, 0, 0, 0,
    2, 157, 30, 1, 150, 28, 0, 0, 0, // version 26
    5, 65, 28, 1, 61, 26, 0, 0, 0,
    8, 33, 28, 1, 34, 30, 0, 0, 0,
    10, 19, 28, 2, 15, 26, 0, 0, 0,
    3, 126, 24, 1, 115, 22, 0, 0, 0, // version 27
    7, 51, 22, 1, 54, 22, 0, 0, 0,
    8, 35, 30, 1, 37, 30, 0, 0, 0,
    15, 15, 22, 1, 10, 22, 0, 0, 0,
    4, 105, 20, 1, 103, 20, 0, 0, 0, // version 28
    7, 56, 24, 1, 45, 18, 0, 0, 0,
    10, 31, 26, 1, 27, 26, 0, 0, 0,
    10, 17, 26, 3, 20, 28, 1, 21, 28,
    3, 139, 26, 1, 137, 28, 0, 0, 0, // version 29
    6, 66, 28, 1, 66, 30, 0, 0, 0,
    9, 36, 30, 1, 34, 32, 0, 0, 0,
    13, 19, 28, 1, 17, 32, 0, 0, 0,
    6, 84, 16, 1, 82, 16, 0, 0, 0, // version 30
    6, 70, 30, 1, 68, 30, 0, 0, 0,
    7, 35, 30, 3, 33, 28, 1, 32, 28,
    13, 20, 30, 1, 20, 28, 0, 0, 0,
    5, 105, 20, 1, 94, 18, 0, 0, 0, // version 31
    6, 74, 32, 1, 71, 30, 0, 0, 0,
    11, 33, 28, 1, 34, 32, 0, 0, 0,
    13, 19, 28, 3, 16, 26, 0, 0, 0,
    4, 127, 24, 1, 126, 24, 0, 0, 0, // version 32
    7, 66, 28, 1, 66, 30, 0, 0, 0,
    12, 30, 24, 1, 24, 28, 1, 24, 30,
    15, 19, 28, 1, 17, 32, 0, 0, 0,
    7, 84, 16, 1, 78, 16, 0, 0, 0, // version 33
    7, 70, 30, 1, 66, 28, 0, 0, 0,
    12, 33, 28, 1, 32, 30, 0, 0, 0,
    14, 21, 32, 1, 24, 28, 0, 0, 0,
    5, 117, 22, 1, 117, 24, 0, 0, 0, // version 34
    8, 66, 28, 1, 58, 26, 0, 0, 0,
    11, 38, 32, 1, 34, 32, 0, 0, 0,
    15, 20, 30, 2, 17, 26, 0, 0, 0,
    4, 148, 28, 1, 146, 28, 0, 0, 0, // version 35
    8, 68, 30, 1, 70, 24, 0, 0, 0,
    10, 36, 32, 3, 38, 28, 0, 0, 0,
    16, 19, 28, 3, 16, 26, 0, 0, 0,
    4, 126, 24, 2, 135, 26, 0, 0, 0, // version 36
    8, 70, 28, 2, 43, 26, 0, 0, 0,
    13, 32, 28, 2, 41, 30, 0, 0, 0,
    17, 19, 28, 3, 15, 26, 0, 0, 0,
    5, 136, 26, 1, 132, 24, 0, 0, 0, // version 37
    5, 67, 30, 4, 68, 28, 1, 69, 28,
    14, 35, 30, 1, 32, 24, 0, 0, 0,
    18, 18, 26, 3, 16, 28, 1, 14, 28,
    3, 142, 26, 3, 141, 28, 0, 0, 0, // version 38
    8, 70, 30, 1, 73, 32, 1, 74, 32,
    12, 34, 30, 3, 34, 26, 1, 35, 28,
    18, 21, 32, 1, 27, 30, 0, 0, 0,
    5, 116, 22, 2, 103, 20, 1, 102, 20, // version 39
    9, 74, 32, 1, 74, 30, 0, 0, 0,
    14, 34, 28, 2, 32, 32, 1, 32, 30,
    19, 21, 32, 1, 25, 26, 0, 0, 0,
    7, 116, 22, 1, 117, 22, 0, 0, 0, // version 40
    11, 65, 28, 1, 58, 24, 0, 0, 0,
    15, 38, 32, 1, 27, 28, 0, 0, 0,
    20, 20, 30, 1, 20, 32, 1, 21, 32,
    6, 136, 26, 1, 130, 24, 0, 0, 0, // version 41
    11, 66, 28, 1, 62, 30, 0, 0, 0,
    14, 34, 28, 3, 34, 32, 1, 30, 30,
    18, 20, 30, 3, 20, 28, 2, 15, 26,
    5, 105, 20, 2, 115, 22, 2, 116, 22, // version 42
    10, 75, 32, 1, 73, 32, 0, 0, 0,
    16, 38, 32, 1, 27, 28, 0, 0, 0,
    22, 19, 28, 2, 16, 30, 1, 19, 30,
    6, 147, 28, 1, 146, 28, 0, 0, 0, // version 43
    11, 66, 28, 2, 65, 30, 0, 0, 0,
    18, 33, 28, 2, 33, 30, 0, 0, 0,
    22, 21, 32, 1, 28, 30, 0, 0, 0,
    6, 116, 22, 3, 125, 24, 0, 0, 0, // version 44
    11, 75, 32, 1, 68, 30, 0, 0, 0,
    13, 35, 28, 6, 34, 32, 1, 30, 30,
    23, 21, 32, 1, 26, 30, 0, 0, 0,
    7, 105, 20, 4, 95, 18, 0, 0, 0, // version 45
    12, 67, 28, 1, 63, 30, 1, 62, 32,
    21, 31, 26, 2, 33, 32, 0, 0, 0,
    23, 21, 32, 2, 24, 30, 0, 0, 0,
    10, 116, 22, 0, 0, 0, 0, 0, 0, // version 46
    12, 74, 32, 1, 78, 30, 0, 0, 0,
    18, 37, 32, 1, 39, 30, 1, 41, 28,
    25, 21, 32, 1, 27, 28, 0, 0, 0,
    5, 126, 24, 4, 115, 22, 1, 114, 22, // version 47
    12, 67, 28, 2, 66, 32, 1, 68, 30,
    21, 35, 30, 1, 39, 30, 0, 0, 0,
    26, 21, 32, 1, 28, 28, 0, 0, 0,
    9, 126, 24, 1, 117, 22, 0, 0, 0, // version 48
    13, 75, 32, 1, 68, 30, 0, 0, 0,
    20, 35, 30, 3, 35, 28, 0, 0, 0,
    27, 21, 32, 1, 28, 30, 0, 0, 0,
    9, 126, 24, 1, 137, 26, 0, 0, 0, // version 49
    13, 71, 30, 2, 68, 32, 0, 0, 0,
    20, 37, 32, 1, 39, 28, 1, 38, 28,
    24, 20, 32, 5, 25, 28, 0, 0, 0,
    8, 147, 28, 1, 141, 28, 0, 0, 0, // version 50
    10, 73, 32, 4, 74, 30, 1, 73, 30,
    16, 36, 32, 6, 39, 30, 1, 37, 30,
    27, 21, 32, 3, 20, 26, 0, 0, 0,
    9, 137, 26, 1, 135, 26, 0, 0, 0, // version 51
    12, 70, 30, 4, 75, 32, 0, 0, 0,
    24, 35, 30, 1, 40, 28, 0, 0, 0,
    23, 20, 32, 8, 24, 30, 0, 0, 0,
    14, 95, 18, 1, 86, 18, 0, 0, 0, // version 52
    13, 73, 32, 3, 77, 30, 0, 0, 0,
    24, 35, 30, 2, 35, 28, 0, 0, 0,
    26, 21, 32, 5, 21, 30, 1, 23, 30,
    9, 147, 28, 1, 142, 28, 0, 0, 0, // version 53
    10, 73, 30, 6, 70, 32, 1, 71, 32,
    25, 35, 30, 2, 34, 26, 0, 0, 0,
    29, 21, 32, 4, 22, 30, 0, 0, 0,
    11, 126, 24, 1, 131, 24, 0, 0, 0, // version 54
    16, 74, 32, 1, 79, 30, 0, 0, 0,
    25, 38, 32, 1, 25, 30, 0, 0, 0,
    33, 21, 32, 1, 28, 28, 0, 0, 0,
    14, 105, 20, 1, 99, 18, 0, 0, 0, // version 55
    19, 65, 28, 1, 72, 28, 0, 0, 0,
    24, 37, 32, 2, 40, 30, 1, 41, 30,
    31, 21, 32, 4, 24, 32, 0, 0, 0,
    10, 147, 28, 1, 151, 28, 0, 0, 0, // version 56
    15, 71, 30, 3, 71, 32, 1, 73, 32,
    24, 37, 32, 3, 38, 30, 1, 39, 30,
    36, 19, 30, 3, 29, 26, 0, 0, 0,
    15, 105, 20, 1, 99, 18, 0, 0, 0, // version 57
    19, 70, 30, 1, 64, 28, 0, 0, 0,
    27, 38, 32, 2, 25, 26, 0, 0, 0,
    38, 20, 30, 2, 18, 28, 0, 0, 0,
    14, 105, 20, 1, 113, 22, 1, 114, 22, // version 58
    17, 67, 30, 3, 92, 32, 0, 0, 0,
    30, 35, 30, 1, 41, 30, 0, 0, 0,
    36, 21, 32, 1, 26, 30, 1, 27, 30,
    11, 146, 28, 1, 146, 26, 0, 0, 0, // version 59
    20, 70, 30, 1, 60, 26, 0, 0, 0,
    29, 38, 32, 1, 24, 32, 0, 0, 0,
    40, 20, 30, 2, 17, 26, 0, 0, 0,
    3, 137, 26, 1, 136, 26, 10, 126, 24, // version 60
    22, 65, 28, 1, 75, 30, 0, 0, 0,
    30, 37, 32, 1, 51, 30, 0, 0, 0,
    42, 20, 30, 1, 21, 30, 0, 0, 0,
    12, 126, 24, 2, 118, 22, 1, 116, 22, // version 61
    19, 74, 32, 1, 74, 30, 1, 72, 28,
    30, 38, 32, 2, 29, 30, 0, 0, 0,
    39, 20, 32, 2, 37, 26, 1, 38, 26,
    12, 126, 24, 3, 136, 26, 0, 0, 0, // version 62
    21, 70, 30, 2, 65, 28, 0, 0, 0,
    34, 35, 30, 1, 44, 32, 0, 0, 0,
    42, 20, 30, 2, 19, 28, 2, 18, 28,
    12, 126, 24, 3, 117, 22, 1, 116, 22, // version 63
    25, 61, 26, 2, 62, 28, 0, 0, 0,
    34, 35, 30, 1, 40, 32, 1, 41, 32,
    45, 20, 30, 1, 20, 32, 1, 21, 32,
    15, 105, 20, 2, 115, 22, 2, 116, 22, // version 64
    25, 65, 28, 1, 72, 28, 0, 0, 0,
    18, 35, 30, 17, 37, 32, 1, 50, 32,
    42, 20, 30, 6, 19, 28, 1, 15, 28,
    19, 105, 20, 1, 101, 20, 0, 0, 0, // version 65
    33, 51, 22, 1, 65, 22, 0, 0, 0,
    40, 33, 28, 1, 28, 28, 0, 0, 0,
    49, 20, 30, 1, 18, 28, 0, 0, 0,
    18, 105, 20, 2, 117, 22, 0, 0, 0, // version 66
    26, 65, 28, 1, 80, 30, 0, 0, 0,
    35, 35, 30, 3, 35, 28, 1, 36, 28,
    52, 18, 28, 2, 38, 30, 0, 0, 0,
    26, 84, 16, 0, 0, 0, 0, 0, 0, // version 67
    26, 70, 30, 0, 0, 0, 0, 0, 0,
    45, 31, 26, 1, 9, 26, 0, 0, 0,
    52, 20, 30, 0, 0, 0, 0, 0, 0,
    16, 126, 24, 1, 114, 22, 1, 115, 22, // version 68
    23, 70, 30, 3, 65, 28, 1, 66, 28,
    40, 35, 30, 1, 43, 30, 0, 0, 0,
    46, 20, 30, 7, 19, 28, 1, 16, 28,
    19, 116, 22, 1, 105, 22, 0, 0, 0, // version 69
    20, 70, 30, 7, 66, 28, 1, 63, 28,
    40, 35, 30, 1, 42, 32, 1, 43, 32,
    54, 20, 30, 1, 19, 30, 0, 0, 0,
    17, 126, 24, 2, 115, 22, 0, 0, 0, // version 70
    24, 70, 30, 4, 74, 32, 0, 0, 0,
    48, 31, 26, 2, 18, 26, 0, 0, 0,
    54, 19, 28, 6, 15, 26, 1, 14, 26,
    29, 84, 16, 0, 0, 0, 0, 0, 0, // version 71
    29, 70, 30, 0, 0, 0, 0, 0, 0,
    6, 34, 30, 3, 36, 30, 38, 33, 28,
    58, 20, 30, 0, 0, 0, 0, 0, 0,
    16, 147, 28, 1, 149, 28, 0, 0, 0, // version 72
    31, 66, 28, 1, 37, 26, 0, 0, 0,
    48, 33, 28, 1, 23, 26, 0, 0, 0,
    53, 20, 30, 6, 19, 28, 1, 17, 28,
    20, 115, 22, 2, 134, 24, 0, 0, 0, // verdion 73
    29, 66, 28, 2, 56, 26, 2, 57, 26,
    45, 36, 30, 2, 15, 28, 0, 0, 0,
    59, 20, 30, 2, 21, 32, 0, 0, 0,
    17, 147, 28, 1, 134, 26, 0, 0, 0, // version 74
    26, 70, 30, 5, 75, 32, 0, 0, 0,
    47, 35, 30, 1, 48, 32, 0, 0, 0,
    64, 18, 28, 2, 33, 30, 1, 35, 30,
    22, 115, 22, 1, 133, 24, 0, 0, 0, // version 75
    33, 65, 28, 1, 74, 28, 0, 0, 0,
    43, 36, 30, 5, 27, 28, 1, 30, 28,
    57, 20, 30, 5, 21, 32, 1, 24, 32,
    18, 136, 26, 2, 142, 26, 0, 0, 0, // version 76
    33, 66, 28, 2, 49, 26, 0, 0, 0,
    48, 35, 30, 2, 38, 28, 0, 0, 0,
    64, 20, 30, 1, 20, 32, 0, 0, 0,
    19, 126, 24, 2, 135, 26, 1, 136, 26, // version 77
    32, 66, 28, 2, 55, 26, 2, 56, 26,
    49, 36, 30, 2, 18, 32, 0, 0, 0,
    65, 18, 28, 5, 27, 30, 1, 29, 30,
    20, 137, 26, 1, 130, 26, 0, 0, 0, // version 78
    30, 75, 32, 2, 71, 32, 0, 0, 0,
    46, 35, 30, 6, 39, 32, 0, 0, 0,
    3, 12, 30, 70, 19, 28, 0, 0, 0,
    20, 147, 28, 0, 0, 0, 0, 0, 0, // version 79
    35, 70, 30, 0, 0, 0, 0, 0, 0,
    49, 35, 30, 5, 35, 28, 0, 0, 0,
    70, 20, 30, 0, 0, 0, 0, 0, 0,
    21, 136, 26, 1, 155, 28, 0, 0, 0, // version 80
    34, 70, 30, 1, 64, 28, 1, 65, 28,
    54, 35, 30, 1, 45, 30, 0, 0, 0,
    68, 20, 30, 3, 18, 28, 1, 19, 28,
    19, 126, 24, 5, 115, 22, 1, 114, 22, // version 81
    33, 70, 30, 3, 65, 28, 1, 64, 28,
    52, 35, 30, 3, 41, 32, 1, 40, 32,
    67, 20, 30, 5, 21, 32, 1, 24, 32,
    2, 150, 28, 21, 136, 26, 0, 0, 0, // version 82
    32, 70, 30, 6, 65, 28, 0, 0, 0,
    52, 38, 32, 2, 27, 32, 0, 0, 0,
    73, 20, 30, 2, 22, 32, 0, 0, 0,
    21, 126, 24, 4, 136, 26, 0, 0, 0, // version 83
    30, 74, 32, 6, 73, 30, 0, 0, 0,
    54, 35, 30, 4, 40, 32, 0, 0, 0,
    75, 20, 30, 1, 20, 28, 0, 0, 0,
    30, 105, 20, 1, 114, 22, 0, 0, 0, // version 84
    3, 45, 22, 55, 47, 20, 0, 0, 0,
    2, 26, 26, 62, 33, 28, 0, 0, 0,
    79, 18, 28, 4, 33, 30, 0, 0, 0
};

Changes to jni/zint/backend/imail.c.

252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
...
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
...
621
622
623
624
625
626
627
628
629
630
631
632

633
634
635
636
637
638
639
640
641

642



643
644
645
646
647
648
649
            FrameCheckSequence &= 0x7FF;
            Data <<= 1;
        }
    }
    return FrameCheckSequence;
}

void breakup(short int fcs_bit[], unsigned short usps_crc) {
    int i;

    for (i = 0; i < 13; i++) {
        fcs_bit[i] = 0;
    }

    if (usps_crc >= 4096) {
        fcs_bit[12] = 1;
        usps_crc -= 4096;
    }
    if (usps_crc >= 2048) {
        fcs_bit[11] = 1;
        usps_crc -= 2048;
    }
    if (usps_crc >= 1024) {
        fcs_bit[10] = 1;
        usps_crc -= 1024;
    }
    if (usps_crc >= 512) {
        fcs_bit[9] = 1;
        usps_crc -= 512;
    }
    if (usps_crc >= 256) {
        fcs_bit[8] = 1;
        usps_crc -= 256;
    }
    if (usps_crc >= 128) {
        fcs_bit[7] = 1;
        usps_crc -= 128;
    }
    if (usps_crc >= 64) {
        fcs_bit[6] = 1;
        usps_crc -= 64;
    }
    if (usps_crc >= 32) {
        fcs_bit[5] = 1;
        usps_crc -= 32;
    }
    if (usps_crc >= 16) {
        fcs_bit[4] = 1;
        usps_crc -= 16;
    }
    if (usps_crc >= 8) {
        fcs_bit[3] = 1;
        usps_crc -= 8;
    }
    if (usps_crc >= 4) {
        fcs_bit[2] = 1;
        usps_crc -= 4;
    }
    if (usps_crc >= 2) {
        fcs_bit[1] = 1;
        usps_crc -= 2;
    }
    if (usps_crc == 1) {
        fcs_bit[0] = 1;
    }
}

int imail(struct zint_symbol *symbol, unsigned char source[], int length) {
    char data_pattern[200];
    int error_number;
    int i, j, read;
    char zip[35], tracker[35], zip_adder[11], temp[2];
    short int accum[112], x_reg[112], y_reg[112];
    unsigned char byte_array[13];
    unsigned short usps_crc;
    int codeword[10];
    unsigned short characters[10];
    short int bit_pattern[13], bar_map[130];

    error_number = 0;

    if (length > 32) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(SODIUM, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }

    strcpy(zip, "");
    strcpy(tracker, "");

    /* separate the tracking code from the routing code */
................................................................................
    if (j == 0) {
        tracker[read] = '\0';
    } else {
        zip[read] = '\0';
    }

    if (strlen(tracker) != 20) {
        strcpy(symbol->errtxt, "Invalid length tracking code");
        return ZINT_ERROR_INVALID_DATA;
    }
    if (strlen(zip) > 11) {
        strcpy(symbol->errtxt, "Invalid ZIP code");
        return ZINT_ERROR_INVALID_DATA;
    }

    /* *** Step 1 - Conversion of Data Fields into Binary Data *** */

    /* Routing code first */

................................................................................
    for (i = 0; i < 10; i++) {
        if (codeword[i] < 1287) {
            characters[i] = AppxD_I[codeword[i]];
        } else {
            characters[i] = AppxD_II[codeword[i] - 1287];
        }
    }

    breakup(bit_pattern, usps_crc);

    for (i = 0; i < 10; i++) {
        if (bit_pattern[i] == 1) {

            characters[i] = 0x1FFF - characters[i];
        }
    }

    /* *** Step 6 - Conversion from Characters to the Intelligent Mail Barcode *** */

    for (i = 0; i < 10; i++) {
        breakup(bit_pattern, characters[i]);
        for (j = 0; j < 13; j++) {

            bar_map[AppxD_IV[(13 * i) + j] - 1] = bit_pattern[j];



        }
    }

    strcpy(data_pattern, "");
    temp[1] = '\0';
    for (i = 0; i < 65; i++) {
        j = 0;







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










|




|




|







 







|



|







 







|
<
<

<
>





<

<

>
|
>
>
>







252
253
254
255
256
257
258




























































259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
...
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
...
561
562
563
564
565
566
567
568


569

570
571
572
573
574
575

576

577
578
579
580
581
582
583
584
585
586
587
588
589
            FrameCheckSequence &= 0x7FF;
            Data <<= 1;
        }
    }
    return FrameCheckSequence;
}





























































int imail(struct zint_symbol *symbol, unsigned char source[], int length) {
    char data_pattern[200];
    int error_number;
    int i, j, read;
    char zip[35], tracker[35], zip_adder[11], temp[2];
    short int accum[112], x_reg[112], y_reg[112];
    unsigned char byte_array[13];
    unsigned short usps_crc;
    int codeword[10];
    unsigned short characters[10];
    short int bar_map[130];

    error_number = 0;

    if (length > 32) {
        strcpy(symbol->errtxt, "Input too long (D50)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(SODIUM, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (D51)");
        return error_number;
    }

    strcpy(zip, "");
    strcpy(tracker, "");

    /* separate the tracking code from the routing code */
................................................................................
    if (j == 0) {
        tracker[read] = '\0';
    } else {
        zip[read] = '\0';
    }

    if (strlen(tracker) != 20) {
        strcpy(symbol->errtxt, "Invalid length tracking code (D52)");
        return ZINT_ERROR_INVALID_DATA;
    }
    if (strlen(zip) > 11) {
        strcpy(symbol->errtxt, "Invalid ZIP code (D53)");
        return ZINT_ERROR_INVALID_DATA;
    }

    /* *** Step 1 - Conversion of Data Fields into Binary Data *** */

    /* Routing code first */

................................................................................
    for (i = 0; i < 10; i++) {
        if (codeword[i] < 1287) {
            characters[i] = AppxD_I[codeword[i]];
        } else {
            characters[i] = AppxD_II[codeword[i] - 1287];
        }
    }
    


    for (i = 0; i < 10; i++) {

        if (usps_crc & (1 << i)) {
            characters[i] = 0x1FFF - characters[i];
        }
    }

    /* *** Step 6 - Conversion from Characters to the Intelligent Mail Barcode *** */

    for (i = 0; i < 10; i++) {

        for (j = 0; j < 13; j++) {
            if (characters[i] & (1 << j)) {
                bar_map[AppxD_IV[(13 * i) + j] - 1] = 1;
            } else {
                bar_map[AppxD_IV[(13 * i) + j] - 1] = 0;
            }
        }
    }

    strcpy(data_pattern, "");
    temp[1] = '\0';
    for (i = 0; i < 65; i++) {
        j = 0;

Changes to jni/zint/backend/library.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
..
63
64
65
66
67
68
69
70
71
72
73
74
75


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
...
100
101
102
103
104
105
106


107
108
109
110
111
112
113
...
116
117
118
119
120
121
122
















123
124
125
126
127
128
129



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
...
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
...
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
...
259
260
261
262
263
264
265
266
267
268
269

270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
...
344
345
346
347
348
349
350



351
352
353
354































355
356
357
358
359
360
361
...
374
375
376
377
378
379
380

















































381
382
383
384
385
386
387
...
396
397
398
399
400
401
402

403
404
405
406
407
408
409
...
410
411
412
413
414
415
416

417

418
419
420
421
422
423
424
...
454
455
456
457
458
459
460

461
462
463
464
465
466
467
...
469
470
471
472
473
474
475



476
477
478
479
480
481
482
...
487
488
489
490
491
492
493


494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511

512
513
514

515
516
517

518

519
520
521
522
523
524
525
526
527
528
529

530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553



554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571

572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605

606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645

646
647
648
649
650
651
652
653

654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671


672
673
674
675
676
677
678
679
680
681
682
683
684
685

686
687
688
689
690
691
692




693
694
695
696
697
698
699
...
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715



716

717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789

790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
...
825
826
827
828
829
830
831








832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853










854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879





880
881
882
883
884

885
886
887
888
889
890
























891
892
893
894
895
896
897
898
899
900
901
902

903
904
905





906
907
908
909
910
911
912
...
913
914
915
916
917
918
919
920
921







922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938

















939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956





957
958
959
960
961
962
963
...
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
....
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
....
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
....
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
#include "common.h"
#include "gs1.h"

#define TECHNETIUM	"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"

struct zint_symbol *ZBarcode_Create() {
    struct zint_symbol *symbol;
    int i;

    symbol = (struct zint_symbol*) malloc(sizeof (*symbol));
    if (!symbol) return NULL;

    memset(symbol, 0, sizeof (*symbol));
    symbol->symbology = BARCODE_CODE128;
    symbol->height = 0;
    symbol->whitespace_width = 0;
    symbol->border_width = 0;
    symbol->output_options = 0;
    symbol->rows = 0;
    symbol->width = 0;
    strcpy(symbol->fgcolour, "000000");
    strcpy(symbol->bgcolour, "ffffff");
................................................................................
    symbol->option_1 = -1;
    symbol->option_2 = 0;
    symbol->option_3 = 928; // PDF_MAX
    symbol->show_hrt = 1; // Show human readable text
    symbol->input_mode = DATA_MODE;
    strcpy(symbol->primary, "");
    memset(&(symbol->encoded_data[0][0]), 0, sizeof (symbol->encoded_data));
    for (i = 0; i < 178; i++) {
        symbol->row_height[i] = 0;
    }
    symbol->bitmap = NULL;
    symbol->bitmap_width = 0;
    symbol->bitmap_height = 0;


    return symbol;
}

void ZBarcode_Clear(struct zint_symbol *symbol) {
    int i, j;

    for (i = 0; i < symbol->rows; i++) {
        for (j = 0; j < symbol->width; j++) {
            unset_module(symbol, i, j);
        }
    }
    symbol->rows = 0;
    symbol->width = 0;
    memset(symbol->text, 0, 128);
    symbol->errtxt[0] = '\0';
    if (symbol->bitmap != NULL) {
        free(symbol->bitmap);
        symbol->bitmap = NULL;
    }
    symbol->bitmap_width = 0;
    symbol->bitmap_height = 0;
................................................................................
    if (symbol->bitmap != NULL)
        free(symbol->bitmap);

    // If there is a rendered version, ensure its memory is released
    if (symbol->rendered != NULL) {
        struct zint_render_line *line, *l;
        struct zint_render_string *string, *s;



        // Free lines
        line = symbol->rendered->lines;
        while (line) {
            l = line;
            line = line->next;
            free(l);
................................................................................
        string = symbol->rendered->strings;
        while (string) {
            s = string;
            string = string->next;
            free(s->text);
            free(s);
        }

















        // Free Render
        free(symbol->rendered);
    }
    free(symbol);
}




extern int eanx(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN system barcodes */
extern int c39(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 3 from 9 (or Code 39) */
extern int pharmazentral(struct zint_symbol *symbol, unsigned char source[], int length); /* Pharmazentral Nummer (PZN) */
extern int ec39(struct zint_symbol *symbol, unsigned char source[], int length); /* Extended Code 3 from 9 (or Code 39+) */
extern int codabar(struct zint_symbol *symbol, unsigned char source[], int length); /* Codabar - a simple substitution cipher */
extern int matrix_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Standard (& Matrix) */
extern int industrial_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Industrial */
extern int iata_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 IATA */
extern int interleaved_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Interleaved */
extern int logic_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Data Logic */
extern int itf14(struct zint_symbol *symbol, unsigned char source[], int length); /* ITF-14 */
extern int dpleit(struct zint_symbol *symbol, unsigned char source[], int length); /* Deutsche Post Leitcode */
extern int dpident(struct zint_symbol *symbol, unsigned char source[], int length); /* Deutsche Post Identcode */
extern int c93(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 93 - a re-working of Code 39+, generates 2 check digits */
extern int code_128(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 128 and NVE-18 */
extern int ean_128(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN-128 (GS1-128) */
extern int code_11(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 11 */
extern int msi_handle(struct zint_symbol *symbol, unsigned char source[], int length); /* MSI Plessey */
extern int telepen(struct zint_symbol *symbol, unsigned char source[], int length); /* Telepen ASCII */
extern int telepen_num(struct zint_symbol *symbol, unsigned char source[], int length); /* Telepen Numeric */
extern int plessey(struct zint_symbol *symbol, unsigned char source[], int length); /* Plessey Code */
extern int pharma_one(struct zint_symbol *symbol, unsigned char source[], int length); /* Pharmacode One Track */
extern int flattermarken(struct zint_symbol *symbol, unsigned char source[], int length); /* Flattermarken */
................................................................................
extern int post_plot(struct zint_symbol *symbol, unsigned char source[], int length); /* Postnet */
extern int planet_plot(struct zint_symbol *symbol, unsigned char source[], int length); /* PLANET */
extern int imail(struct zint_symbol *symbol, unsigned char source[], int length); /* Intelligent Mail (aka USPS OneCode) */
extern int royal_plot(struct zint_symbol *symbol, unsigned char source[], int length); /* RM4SCC */
extern int australia_post(struct zint_symbol *symbol, unsigned char source[], int length); /* Australia Post 4-state */
extern int code16k(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 16k */
extern int pdf417enc(struct zint_symbol *symbol, unsigned char source[], int length); /* PDF417 */
extern int dmatrix(struct zint_symbol *symbol, unsigned char source[], int length); /* Data Matrix (IEC16022) */
extern int qr_code(struct zint_symbol *symbol, const unsigned char source[], int length); /* QR Code */
extern int micro_pdf417(struct zint_symbol *symbol, unsigned char chaine[], int length); /* Micro PDF417 */
extern int maxicode(struct zint_symbol *symbol, unsigned char source[], int length); /* Maxicode */
extern int rss14(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS-14 */
extern int rsslimited(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS Limited */
extern int rssexpanded(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS Expanded */
extern int composite(struct zint_symbol *symbol, unsigned char source[], int length); /* Composite Symbology */
................................................................................
extern int aztec_runes(struct zint_symbol *symbol, unsigned char source[], int length); /* Aztec Runes */
extern int korea_post(struct zint_symbol *symbol, unsigned char source[], int length); /* Korea Post */
extern int japan_post(struct zint_symbol *symbol, unsigned char source[], int length); /* Japanese Post */
extern int code_49(struct zint_symbol *symbol, unsigned char source[], const int length); /* Code 49 */
extern int channel_code(struct zint_symbol *symbol, unsigned char source[], int length); /* Channel Code */
extern int code_one(struct zint_symbol *symbol, unsigned char source[], int length); /* Code One */
extern int grid_matrix(struct zint_symbol *symbol, const unsigned char source[], int length); /* Grid Matrix */

#ifndef NO_PNG
extern int png_handle(struct zint_symbol *symbol, int rotate_angle);
#endif

extern int render_plot(struct zint_symbol *symbol, float width, float height);

extern int bmp_handle(struct zint_symbol *symbol, int rotate_angle);
extern int ps_plot(struct zint_symbol *symbol);
extern int svg_plot(struct zint_symbol *symbol);

void error_tag(char error_string[], int error_number) {
    char error_buffer[100];

    if (error_number != 0) {
        strcpy(error_buffer, error_string);

................................................................................
    int space = 0;

    if (symbol->output_options & BARCODE_STDOUT) {
        f = stdout;
    } else {
        f = fopen(symbol->outfile, "w");
        if (!f) {
            strcpy(symbol->errtxt, "Could not open output file");
            return ZINT_ERROR_FILE_ACCESS;
        }
    }

    for (r = 0; r < symbol->rows; r++) {
        byt = 0;
        for (i = 0; i < symbol->width; i++) {
................................................................................
        fclose(f);
    }

    return 0;
}

/* Process health industry bar code data */
int hibc(struct zint_symbol *symbol, unsigned char source[], int length) {
    int counter, error_number, i;
    char to_process[40], temp[2], check_digit;


    if (length > 36) {
        strcpy(symbol->errtxt, "Data too long for HIBC LIC");
        return ZINT_ERROR_TOO_LONG;
    }
    to_upper(source);
    error_number = is_sane(TECHNETIUM, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }

    strcpy(to_process, "+");
    counter = 41;
    for (i = 0; i < length; i++) {
        counter += posn(TECHNETIUM, source[i]);
................................................................................
            break;
        case BARCODE_HIBC_MICPDF:
            error_number = micro_pdf417(symbol, (unsigned char *) to_process, length);
            break;
        case BARCODE_HIBC_AZTEC:
            error_number = aztec(symbol, (unsigned char *) to_process, length);
            break;



    }

    return error_number;
}
































static int gs1_compliant(const int symbology) {
    /* Returns 1 if symbology supports GS1 data */

    int result = 0;

    switch (symbology) {
................................................................................
        case BARCODE_RSS_EXPSTACK_CC:
        case BARCODE_CODE16K:
        case BARCODE_AZTEC:
        case BARCODE_DATAMATRIX:
        case BARCODE_CODEONE:
        case BARCODE_CODE49:
        case BARCODE_QRCODE:

















































            result = 1;
            break;
    }

    return result;
}

................................................................................
        case BARCODE_C25INTER:
        case BARCODE_C25IATA:
        case BARCODE_C25LOGIC:
        case BARCODE_C25IND:
        case BARCODE_CODE39:
        case BARCODE_EXCODE39:
        case BARCODE_EANX:

        case BARCODE_EAN128:
        case BARCODE_CODABAR:
        case BARCODE_CODE128:
        case BARCODE_DPLEIT:
        case BARCODE_DPIDENT:
        case BARCODE_CODE16K:
        case BARCODE_CODE49:
................................................................................
        case BARCODE_CODE93:
        case BARCODE_FLAT:
        case BARCODE_RSS14:
        case BARCODE_RSS_LTD:
        case BARCODE_RSS_EXP:
        case BARCODE_TELEPEN:
        case BARCODE_UPCA:

        case BARCODE_UPCE:

        case BARCODE_POSTNET:
        case BARCODE_MSI_PLESSEY:
        case BARCODE_FIM:
        case BARCODE_LOGMARS:
        case BARCODE_PHARMA:
        case BARCODE_PZN:
        case BARCODE_PHARMA_TWO:
................................................................................
        case BARCODE_HIBC_128:
        case BARCODE_HIBC_39:
        case BARCODE_HIBC_DM:
        case BARCODE_HIBC_QR:
        case BARCODE_HIBC_PDF:
        case BARCODE_HIBC_MICPDF:
        case BARCODE_HIBC_AZTEC:

        case BARCODE_AZRUNE:
        case BARCODE_CODE32:
        case BARCODE_EANX_CC:
        case BARCODE_EAN128_CC:
        case BARCODE_RSS14_CC:
        case BARCODE_RSS_LTD_CC:
        case BARCODE_RSS_EXP_CC:
................................................................................
        case BARCODE_UPCE_CC:
        case BARCODE_RSS14STACK_CC:
        case BARCODE_RSS14_OMNI_CC:
        case BARCODE_RSS_EXPSTACK_CC:
        case BARCODE_CHANNEL:
        case BARCODE_CODEONE:
        case BARCODE_GRIDMATRIX:



            result = 1;
            break;
    }

    return result;
}

................................................................................
    switch (symbol->symbology) {
        case BARCODE_QRCODE: error_number = qr_code(symbol, source, length);
            break;
        case BARCODE_MICROQR: error_number = microqr(symbol, source, length);
            break;
        case BARCODE_GRIDMATRIX: error_number = grid_matrix(symbol, source, length);
            break;


    }

    return error_number;
}

static int reduced_charset(struct zint_symbol *symbol, const unsigned char *source, int length) {
    /* These are the "norm" standards which only support Latin-1 at most */
    int error_number = 0;

#ifndef _MSC_VER
    unsigned char preprocessed[length + 1];
#else
    unsigned char* preprocessed = (unsigned char*) _alloca(length + 1);
#endif

    if (symbol->symbology == BARCODE_CODE16K) {
        symbol->whitespace_width = 16;
        symbol->border_width = 2;

        symbol->output_options = BARCODE_BIND;
    }


    if (symbol->symbology == BARCODE_ITF14) {
        symbol->whitespace_width = 20;
        symbol->border_width = 8;

        symbol->output_options = BARCODE_BOX;

    }

    switch (symbol->input_mode) {
        case DATA_MODE:
        case GS1_MODE:
            memcpy(preprocessed, source, length);
            preprocessed[length] = '\0';
            break;
        case UNICODE_MODE:
            error_number = latin1_process(symbol, source, preprocessed, &length);
            if (error_number != 0) {

                return error_number;
            }
            break;
    }

    switch (symbol->symbology) {
        case BARCODE_C25MATRIX: error_number = matrix_two_of_five(symbol, preprocessed, length);
            break;
        case BARCODE_C25IND: error_number = industrial_two_of_five(symbol, preprocessed, length);
            break;
        case BARCODE_C25INTER: error_number = interleaved_two_of_five(symbol, preprocessed, length);
            break;
        case BARCODE_C25IATA: error_number = iata_two_of_five(symbol, preprocessed, length);
            break;
        case BARCODE_C25LOGIC: error_number = logic_two_of_five(symbol, preprocessed, length);
            break;
        case BARCODE_DPLEIT: error_number = dpleit(symbol, preprocessed, length);
            break;
        case BARCODE_DPIDENT: error_number = dpident(symbol, preprocessed, length);
            break;
        case BARCODE_UPCA: error_number = eanx(symbol, preprocessed, length);
            break;
        case BARCODE_UPCE: error_number = eanx(symbol, preprocessed, length);
            break;



        case BARCODE_EANX: error_number = eanx(symbol, preprocessed, length);
            break;
        case BARCODE_EAN128: error_number = ean_128(symbol, preprocessed, length);
            break;
        case BARCODE_CODE39: error_number = c39(symbol, preprocessed, length);
            break;
        case BARCODE_PZN: error_number = pharmazentral(symbol, preprocessed, length);
            break;
        case BARCODE_EXCODE39: error_number = ec39(symbol, preprocessed, length);
            break;
        case BARCODE_CODABAR: error_number = codabar(symbol, preprocessed, length);
            break;
        case BARCODE_CODE93: error_number = c93(symbol, preprocessed, length);
            break;
        case BARCODE_LOGMARS: error_number = c39(symbol, preprocessed, length);
            break;
        case BARCODE_CODE128: error_number = code_128(symbol, preprocessed, length);
            break;

        case BARCODE_CODE128B: error_number = code_128(symbol, preprocessed, length);
            break;
        case BARCODE_NVE18: error_number = nve_18(symbol, preprocessed, length);
            break;
        case BARCODE_CODE11: error_number = code_11(symbol, preprocessed, length);
            break;
        case BARCODE_MSI_PLESSEY: error_number = msi_handle(symbol, preprocessed, length);
            break;
        case BARCODE_TELEPEN: error_number = telepen(symbol, preprocessed, length);
            break;
        case BARCODE_TELEPEN_NUM: error_number = telepen_num(symbol, preprocessed, length);
            break;
        case BARCODE_PHARMA: error_number = pharma_one(symbol, preprocessed, length);
            break;
        case BARCODE_PLESSEY: error_number = plessey(symbol, preprocessed, length);
            break;
        case BARCODE_ITF14: error_number = itf14(symbol, preprocessed, length);
            break;
        case BARCODE_FLAT: error_number = flattermarken(symbol, preprocessed, length);
            break;
        case BARCODE_FIM: error_number = fim(symbol, preprocessed, length);
            break;
        case BARCODE_POSTNET: error_number = post_plot(symbol, preprocessed, length);
            break;
        case BARCODE_PLANET: error_number = planet_plot(symbol, preprocessed, length);
            break;
        case BARCODE_RM4SCC: error_number = royal_plot(symbol, preprocessed, length);
            break;
        case BARCODE_AUSPOST: error_number = australia_post(symbol, preprocessed, length);
            break;
        case BARCODE_AUSREPLY: error_number = australia_post(symbol, preprocessed, length);
            break;
        case BARCODE_AUSROUTE: error_number = australia_post(symbol, preprocessed, length);
            break;

        case BARCODE_AUSREDIRECT: error_number = australia_post(symbol, preprocessed, length);
            break;
        case BARCODE_CODE16K: error_number = code16k(symbol, preprocessed, length);
            break;
        case BARCODE_PHARMA_TWO: error_number = pharma_two(symbol, preprocessed, length);
            break;
        case BARCODE_ONECODE: error_number = imail(symbol, preprocessed, length);
            break;
        case BARCODE_ISBNX: error_number = eanx(symbol, preprocessed, length);
            break;
        case BARCODE_RSS14: error_number = rss14(symbol, preprocessed, length);
            break;
        case BARCODE_RSS14STACK: error_number = rss14(symbol, preprocessed, length);
            break;
        case BARCODE_RSS14STACK_OMNI: error_number = rss14(symbol, preprocessed, length);
            break;
        case BARCODE_RSS_LTD: error_number = rsslimited(symbol, preprocessed, length);
            break;
        case BARCODE_RSS_EXP: error_number = rssexpanded(symbol, preprocessed, length);
            break;
        case BARCODE_RSS_EXPSTACK: error_number = rssexpanded(symbol, preprocessed, length);
            break;
        case BARCODE_EANX_CC: error_number = composite(symbol, preprocessed, length);
            break;
        case BARCODE_EAN128_CC: error_number = composite(symbol, preprocessed, length);
            break;
        case BARCODE_RSS14_CC: error_number = composite(symbol, preprocessed, length);
            break;
        case BARCODE_RSS_LTD_CC: error_number = composite(symbol, preprocessed, length);
            break;
        case BARCODE_RSS_EXP_CC: error_number = composite(symbol, preprocessed, length);
            break;
        case BARCODE_UPCA_CC: error_number = composite(symbol, preprocessed, length);
            break;
        case BARCODE_UPCE_CC: error_number = composite(symbol, preprocessed, length);
            break;
        case BARCODE_RSS14STACK_CC: error_number = composite(symbol, preprocessed, length);
            break;
        case BARCODE_RSS14_OMNI_CC: error_number = composite(symbol, preprocessed, length);
            break;

        case BARCODE_RSS_EXPSTACK_CC: error_number = composite(symbol, preprocessed, length);
            break;
        case BARCODE_KIX: error_number = kix_code(symbol, preprocessed, length);
            break;
        case BARCODE_CODE32: error_number = code32(symbol, preprocessed, length);
            break;
        case BARCODE_DAFT: error_number = daft_code(symbol, preprocessed, length);
            break;

        case BARCODE_EAN14: error_number = ean_14(symbol, preprocessed, length);
            break;
        case BARCODE_AZRUNE: error_number = aztec_runes(symbol, preprocessed, length);
            break;
        case BARCODE_KOREAPOST: error_number = korea_post(symbol, preprocessed, length);
            break;
        case BARCODE_HIBC_128: error_number = hibc(symbol, preprocessed, length);
            break;
        case BARCODE_HIBC_39: error_number = hibc(symbol, preprocessed, length);
            break;
        case BARCODE_HIBC_DM: error_number = hibc(symbol, preprocessed, length);
            break;
        case BARCODE_HIBC_QR: error_number = hibc(symbol, preprocessed, length);
            break;
        case BARCODE_HIBC_PDF: error_number = hibc(symbol, preprocessed, length);
            break;
        case BARCODE_HIBC_MICPDF: error_number = hibc(symbol, preprocessed, length);
            break;


        case BARCODE_HIBC_AZTEC: error_number = hibc(symbol, preprocessed, length);
            break;
        case BARCODE_JAPANPOST: error_number = japan_post(symbol, preprocessed, length);
            break;
        case BARCODE_CODE49: error_number = code_49(symbol, preprocessed, length);
            break;
        case BARCODE_CHANNEL: error_number = channel_code(symbol, preprocessed, length);
            break;
        case BARCODE_CODEONE: error_number = code_one(symbol, preprocessed, length);
            break;
        case BARCODE_DATAMATRIX: error_number = dmatrix(symbol, preprocessed, length);
            break;
        case BARCODE_PDF417: error_number = pdf417enc(symbol, preprocessed, length);
            break;

        case BARCODE_PDF417TRUNC: error_number = pdf417enc(symbol, preprocessed, length);
            break;
        case BARCODE_MICROPDF417: error_number = micro_pdf417(symbol, preprocessed, length);
            break;
        case BARCODE_MAXICODE: error_number = maxicode(symbol, preprocessed, length);
            break;
        case BARCODE_AZTEC: error_number = aztec(symbol, preprocessed, length);




            break;
    }

    return error_number;
}

int ZBarcode_Encode(struct zint_symbol *symbol, unsigned char *source, int length) {
................................................................................
    int error_number, error_buffer, i;
#ifdef _MSC_VER
    unsigned char* local_source;
#endif
    error_number = 0;

    if (length == 0) {
        length = ustrlen(source);
    }
    if (length == 0) {
        strcpy(symbol->errtxt, "No input data");
        error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
        return ZINT_ERROR_INVALID_DATA;
    }

    if (strcmp(symbol->outfile, "") == 0) {



        strcpy(symbol->outfile, "out.png");

    }
#ifndef _MSC_VER
    unsigned char local_source[length + 1];
#else
    local_source = (unsigned char*) _alloca(length + 1);
#endif

    /* First check the symbology field */
    if (symbol->symbology < 1) {
        strcpy(symbol->errtxt, "Symbology out of range, using Code 128");
        symbol->symbology = BARCODE_CODE128;
        error_number = ZINT_WARN_INVALID_OPTION;
    }

    /* symbol->symbologys 1 to 86 are defined by tbarcode */
    if (symbol->symbology == 5) {
        symbol->symbology = BARCODE_C25MATRIX;
    }
    if ((symbol->symbology >= 10) && (symbol->symbology <= 12)) {
        symbol->symbology = BARCODE_EANX;
    }
    if ((symbol->symbology == 14) || (symbol->symbology == 15)) {
        symbol->symbology = BARCODE_EANX;
    }
    if (symbol->symbology == 17) {
        symbol->symbology = BARCODE_UPCA;
    }
    if (symbol->symbology == 19) {
        strcpy(symbol->errtxt, "Codabar 18 not supported, using Codabar");
        symbol->symbology = BARCODE_CODABAR;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    if (symbol->symbology == 26) {
        symbol->symbology = BARCODE_UPCA;
    }
    if (symbol->symbology == 27) {
        strcpy(symbol->errtxt, "UPCD1 not supported");
        error_number = ZINT_ERROR_INVALID_OPTION;
    }
    if (symbol->symbology == 33) {
        symbol->symbology = BARCODE_EAN128;
    }
    if ((symbol->symbology == 35) || (symbol->symbology == 36)) {
        symbol->symbology = BARCODE_UPCA;
    }
    if ((symbol->symbology == 38) || (symbol->symbology == 39)) {
        symbol->symbology = BARCODE_UPCE;
    }
    if ((symbol->symbology >= 41) && (symbol->symbology <= 45)) {
        symbol->symbology = BARCODE_POSTNET;
    }
    if (symbol->symbology == 46) {
        symbol->symbology = BARCODE_PLESSEY;
    }
    if (symbol->symbology == 48) {
        symbol->symbology = BARCODE_NVE18;
    }
    if (symbol->symbology == 54) {
        strcpy(symbol->errtxt, "General Parcel Code not supported, using Code 128");
        symbol->symbology = BARCODE_CODE128;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    if ((symbol->symbology == 59) || (symbol->symbology == 61)) {
        symbol->symbology = BARCODE_CODE128;
    }
    if (symbol->symbology == 62) {
        symbol->symbology = BARCODE_CODE93;
    }
    if ((symbol->symbology == 64) || (symbol->symbology == 65)) {
        symbol->symbology = BARCODE_AUSPOST;
    }
    if (symbol->symbology == 73) {
        strcpy(symbol->errtxt, "Codablock E not supported");

        error_number = ZINT_ERROR_INVALID_OPTION;
    }
    if (symbol->symbology == 78) {
        symbol->symbology = BARCODE_RSS14;
    }
    if (symbol->symbology == 83) {
        symbol->symbology = BARCODE_PLANET;
    }
    if (symbol->symbology == 88) {
        symbol->symbology = BARCODE_EAN128;
    }
    if (symbol->symbology == 91) {
        strcpy(symbol->errtxt, "Symbology out of range, using Code 128");
        symbol->symbology = BARCODE_CODE128;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    if ((symbol->symbology >= 94) && (symbol->symbology <= 96)) {
        strcpy(symbol->errtxt, "Symbology out of range, using Code 128");
        symbol->symbology = BARCODE_CODE128;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    if (symbol->symbology == 100) {
        symbol->symbology = BARCODE_HIBC_128;
    }
    if (symbol->symbology == 101) {
................................................................................
    }
    if (symbol->symbology == 109) {
        symbol->symbology = BARCODE_HIBC_MICPDF;
    }
    if (symbol->symbology == 111) {
        symbol->symbology = BARCODE_HIBC_BLOCKF;
    }








    if ((symbol->symbology >= 113) && (symbol->symbology <= 127)) {
        strcpy(symbol->errtxt, "Symbology out of range, using Code 128");
        symbol->symbology = BARCODE_CODE128;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    /* Everything from 128 up is Zint-specific */
    if (symbol->symbology >= 143) {
        strcpy(symbol->errtxt, "Symbology out of range, using Code 128");
        symbol->symbology = BARCODE_CODE128;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    if ((symbol->symbology == BARCODE_CODABLOCKF) || (symbol->symbology == BARCODE_HIBC_BLOCKF)) {
        strcpy(symbol->errtxt, "Codablock F not supported");
        error_number = ZINT_ERROR_INVALID_OPTION;
    }

    if (error_number > 4) {
        error_tag(symbol->errtxt, error_number);
        return error_number;
    } else {
        error_buffer = error_number;
    }











    if ((symbol->input_mode < 0) || (symbol->input_mode > 2)) {
        symbol->input_mode = DATA_MODE;
    }

    if (symbol->input_mode == GS1_MODE) {
        for (i = 0; i < length; i++) {
            if (source[i] == '\0') {
                strcpy(symbol->errtxt, "NULL characters not permitted in GS1 mode");
                return ZINT_ERROR_INVALID_DATA;
            }
        }
        if (gs1_compliant(symbol->symbology) == 1) {
            error_number = ugs1_verify(symbol, source, length, local_source);
            if (error_number != 0) {
                return error_number;
            }
            length = ustrlen(local_source);
        } else {
            strcpy(symbol->errtxt, "Selected symbology does not support GS1 mode");
            return ZINT_ERROR_INVALID_OPTION;
        }
    } else {
        memcpy(local_source, source, length);
        local_source[length] = '\0';
    }






    switch (symbol->symbology) {
        case BARCODE_QRCODE:
        case BARCODE_MICROQR:
        case BARCODE_GRIDMATRIX:

            error_number = extended_charset(symbol, local_source, length);
            break;
        default:
            error_number = reduced_charset(symbol, local_source, length);
            break;
    }

























    if ((symbol->symbology == BARCODE_CODE128) || (symbol->symbology == BARCODE_CODE128B)) {
        for (i = 0; i < length; i++) {
            if (local_source[i] == '\0') {
                symbol->text[i] = ' ';
            } else {
                symbol->text[i] = local_source[i];
            }
        }
    }

    if (error_number == 0) {

        error_number = error_buffer;
    }
    error_tag(symbol->errtxt, error_number);





    return error_number;
}

int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) {
    int error_number;
    char output[4];

................................................................................
    switch (rotate_angle) {
        case 0:
        case 90:
        case 180:
        case 270:
            break;
        default:
            strcpy(symbol->errtxt, "Invalid rotation angle");
            return ZINT_ERROR_INVALID_OPTION;







    }

    if (strlen(symbol->outfile) > 3) {
        output[0] = symbol->outfile[strlen(symbol->outfile) - 3];
        output[1] = symbol->outfile[strlen(symbol->outfile) - 2];
        output[2] = symbol->outfile[strlen(symbol->outfile) - 1];
        output[3] = '\0';
        to_upper((unsigned char*) output);

#ifndef NO_PNG
        if (!(strcmp(output, "PNG"))) {
            if (symbol->scale < 1.0) {
                symbol->text[0] = '\0';
            }
            error_number = png_handle(symbol, rotate_angle);
        } else
#endif

















            if (!(strcmp(output, "TXT"))) {
            error_number = dump_plot(symbol);
        } else
            if (!(strcmp(output, "EPS"))) {
            error_number = ps_plot(symbol);
        } else
            if (!(strcmp(output, "SVG"))) {
            error_number = svg_plot(symbol);
        } else {
            strcpy(symbol->errtxt, "Unknown output format");
            error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
            return ZINT_ERROR_INVALID_OPTION;
        }
    } else {
        strcpy(symbol->errtxt, "Unknown output format");
        error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
        return ZINT_ERROR_INVALID_OPTION;
    }






    error_tag(symbol->errtxt, error_number);
    return error_number;
}

int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle) {
    int error_number;
................................................................................
    switch (rotate_angle) {
        case 0:
        case 90:
        case 180:
        case 270:
            break;
        default:
            strcpy(symbol->errtxt, "Invalid rotation angle");
            return ZINT_ERROR_INVALID_OPTION;
    }

    error_number = bmp_handle(symbol, rotate_angle);
    error_tag(symbol->errtxt, error_number);
    return error_number;
}

int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle) {
    int error_number;

    error_number = 0;

    error_number = ZBarcode_Encode(symbol, input, length);
    if (error_number != 0) {
        return error_number;
    }

    error_number = ZBarcode_Print(symbol, rotate_angle);
    return error_number;
}

int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle) {
    int error_number;

    error_number = 0;

    error_number = ZBarcode_Encode(symbol, input, length);
    if (error_number != 0) {
        return error_number;
    }

    error_number = ZBarcode_Buffer(symbol, rotate_angle);
    return error_number;
................................................................................

    if (!strcmp(filename, "-")) {
        file = stdin;
        fileLen = 7100;
    } else {
        file = fopen(filename, "rb");
        if (!file) {
            strcpy(symbol->errtxt, "Unable to read input file");
            return ZINT_ERROR_INVALID_DATA;
        }

        /* Get file length */
        fseek(file, 0, SEEK_END);
        fileLen = ftell(file);
        fseek(file, 0, SEEK_SET);

        if (fileLen > 7100) {
            /* The largest amount of data that can be encoded is 7089 numeric digits in QR Code */
            strcpy(symbol->errtxt, "Input file too long");
            fclose(file);
            return ZINT_ERROR_INVALID_DATA;
        }
    }

    /* Allocate memory */
    buffer = (unsigned char *) malloc(fileLen * sizeof (unsigned char));
    if (!buffer) {
        strcpy(symbol->errtxt, "Internal memory error");
        if (strcmp(filename, "-"))
            fclose(file);
        return ZINT_ERROR_MEMORY;
    }

    /* Read file contents into buffer */

    do {
        n = fread(buffer + nRead, 1, fileLen - nRead, file);
        if (ferror(file)) {
            strcpy(symbol->errtxt, strerror(errno));
            nRead = 0;
            return ZINT_ERROR_INVALID_DATA;
        }
        nRead += n;
    } while (!feof(file) && (0 < n) && (nRead < fileLen));

    fclose(file);
    ret = ZBarcode_Encode(symbol, buffer, nRead);
................................................................................
    free(buffer);
    return ret;
}

int ZBarcode_Encode_File_and_Print(struct zint_symbol *symbol, char *filename, int rotate_angle) {
    int error_number;

    error_number = 0;

    error_number = ZBarcode_Encode_File(symbol, filename);
    if (error_number != 0) {
        return error_number;
    }

    return ZBarcode_Print(symbol, rotate_angle);
}

int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol, char *filename, int rotate_angle) {
    int error_number;

    error_number = 0;

    error_number = ZBarcode_Encode_File(symbol, filename);
    if (error_number != 0) {
        return error_number;
    }

    return ZBarcode_Buffer(symbol, rotate_angle);
}
................................................................................
 * Converts encoded data into an intermediate format to be interpreted
 * in other applications using this library.
 *
 * If the width and height are not set to zero, the barcode will be resized to those
 * dimensions. The symbol->scale and symbol->height values are totally ignored in this case.
 *
 */
int ZBarcode_Render(struct zint_symbol *symbol, float width, float height) {
    // Send the request to the render_plot method
    return render_plot(symbol, width, height);
}







<






|







 







<
|
<



>
>













|







 







>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







>
>
>

|






|






|







 







|







 







|
|
|
|
|
|
|
|
<
<







 







|







 







|

|

>
|
|





|







 







>
>
>




>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







>

>







 







>







 







>
>
>







 







>
>





|




|

|





>
|
|
|
>
|


>
|
>





|
|


|

>






|

|

|

|

|

|

|

|
<
|
|
>
>
>
|

|

|

|

|

|

|

|

|
<
>
|

|

|

|

|

|

|

|

|

|

|

|

|

|

|
<
|
<
|
<
>
|

|

|

|

|

|
<
|
|
|

|

|
|
|

|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
<
|
<
>
|

|

|

|

>
|

|

|

|
<
|
<
|
<
|
<
|
<
|
<
>
>
|

|

|

|

|

|

|
<
>
|

|

|

|
>
>
>
>







 







|


|





>
>
>

>









|











|






|







|





|


|












|













|
>
|











|




|







 







>
>
>
>
>
>
>
>
|
|





|



<
<
<
<







>
>
>
>
>
>
>
>
>
>








|










|






>
>
>
>
>





>






>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












>



>
>
>
>
>







 







|

>
>
>
>
>
>
>









<




|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>









|




|



>
>
>
>
>







 







|



|







<
<












<
<







 







|










|








|











<







 







<
<











<
<







 







|



39
40
41
42
43
44
45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
..
62
63
64
65
66
67
68

69

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
..
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211


212
213
214
215
216
217
218
...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
...
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
...
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
...
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
...
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
...
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
...
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
...
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
...
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666

667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688

689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718

719

720

721
722
723
724
725
726
727
728
729
730
731
732

733
734
735
736
737
738
739
740
741
742
743

744

745

746

747

748

749

750

751

752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768

769

770

771

772

773

774
775
776
777
778
779
780
781
782
783
784
785
786
787
788

789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
...
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
...
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963




964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
....
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100

1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
....
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174


1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186


1187
1188
1189
1190
1191
1192
1193
....
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240

1241
1242
1243
1244
1245
1246
1247
....
1248
1249
1250
1251
1252
1253
1254


1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265


1266
1267
1268
1269
1270
1271
1272
....
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
#include "common.h"
#include "gs1.h"

#define TECHNETIUM	"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%"

struct zint_symbol *ZBarcode_Create() {
    struct zint_symbol *symbol;


    symbol = (struct zint_symbol*) malloc(sizeof (*symbol));
    if (!symbol) return NULL;

    memset(symbol, 0, sizeof (*symbol));
    symbol->symbology = BARCODE_CODE128;
    symbol->height = 50;
    symbol->whitespace_width = 0;
    symbol->border_width = 0;
    symbol->output_options = 0;
    symbol->rows = 0;
    symbol->width = 0;
    strcpy(symbol->fgcolour, "000000");
    strcpy(symbol->bgcolour, "ffffff");
................................................................................
    symbol->option_1 = -1;
    symbol->option_2 = 0;
    symbol->option_3 = 928; // PDF_MAX
    symbol->show_hrt = 1; // Show human readable text
    symbol->input_mode = DATA_MODE;
    strcpy(symbol->primary, "");
    memset(&(symbol->encoded_data[0][0]), 0, sizeof (symbol->encoded_data));

    memset(&(symbol->row_height[0]), 0, sizeof (symbol->row_height));

    symbol->bitmap = NULL;
    symbol->bitmap_width = 0;
    symbol->bitmap_height = 0;
    symbol->eci = 3;
    symbol->dot_size = 4.0 / 5.0;
    return symbol;
}

void ZBarcode_Clear(struct zint_symbol *symbol) {
    int i, j;

    for (i = 0; i < symbol->rows; i++) {
        for (j = 0; j < symbol->width; j++) {
            unset_module(symbol, i, j);
        }
    }
    symbol->rows = 0;
    symbol->width = 0;
    memset(symbol->text, 0, sizeof(symbol->text));
    symbol->errtxt[0] = '\0';
    if (symbol->bitmap != NULL) {
        free(symbol->bitmap);
        symbol->bitmap = NULL;
    }
    symbol->bitmap_width = 0;
    symbol->bitmap_height = 0;
................................................................................
    if (symbol->bitmap != NULL)
        free(symbol->bitmap);

    // If there is a rendered version, ensure its memory is released
    if (symbol->rendered != NULL) {
        struct zint_render_line *line, *l;
        struct zint_render_string *string, *s;
        struct zint_render_ring *ring, *r;
        struct zint_render_hexagon *hexagon, *h;

        // Free lines
        line = symbol->rendered->lines;
        while (line) {
            l = line;
            line = line->next;
            free(l);
................................................................................
        string = symbol->rendered->strings;
        while (string) {
            s = string;
            string = string->next;
            free(s->text);
            free(s);
        }

        // Free Rings
        ring = symbol->rendered->rings;
        while (ring) {
            r = ring;
            ring = ring->next;
            free(r);
        }

        // Free Hexagons
        hexagon = symbol->rendered->hexagons;
        while (hexagon) {
            h = hexagon;
            hexagon = hexagon->next;
            free(h);
        }

        // Free Render
        free(symbol->rendered);
    }
    free(symbol);
}

extern int get_best_eci(unsigned char source[], int length); /* Calculate suitable ECI mode */
extern int utf_to_eci(int eci, const unsigned char source[], unsigned char dest[], int *length); /* Convert Unicode to other encodings */

extern int eanx(struct zint_symbol *symbol, unsigned char source[], int length); /* EAN system barcodes */
extern int c39(struct zint_symbol *symbol, unsigned char source[], const size_t length); /* Code 3 from 9 (or Code 39) */
extern int pharmazentral(struct zint_symbol *symbol, unsigned char source[], int length); /* Pharmazentral Nummer (PZN) */
extern int ec39(struct zint_symbol *symbol, unsigned char source[], int length); /* Extended Code 3 from 9 (or Code 39+) */
extern int codabar(struct zint_symbol *symbol, unsigned char source[], int length); /* Codabar - a simple substitution cipher */
extern int matrix_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Standard (& Matrix) */
extern int industrial_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Industrial */
extern int iata_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 IATA */
extern int interleaved_two_of_five(struct zint_symbol *symbol, const unsigned char source[], size_t length); /* Code 2 of 5 Interleaved */
extern int logic_two_of_five(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 2 of 5 Data Logic */
extern int itf14(struct zint_symbol *symbol, unsigned char source[], int length); /* ITF-14 */
extern int dpleit(struct zint_symbol *symbol, unsigned char source[], int length); /* Deutsche Post Leitcode */
extern int dpident(struct zint_symbol *symbol, unsigned char source[], int length); /* Deutsche Post Identcode */
extern int c93(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 93 - a re-working of Code 39+, generates 2 check digits */
extern int code_128(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 128 and NVE-18 */
extern int ean_128(struct zint_symbol *symbol, unsigned char source[], const size_t length); /* EAN-128 (GS1-128) */
extern int code_11(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 11 */
extern int msi_handle(struct zint_symbol *symbol, unsigned char source[], int length); /* MSI Plessey */
extern int telepen(struct zint_symbol *symbol, unsigned char source[], int length); /* Telepen ASCII */
extern int telepen_num(struct zint_symbol *symbol, unsigned char source[], int length); /* Telepen Numeric */
extern int plessey(struct zint_symbol *symbol, unsigned char source[], int length); /* Plessey Code */
extern int pharma_one(struct zint_symbol *symbol, unsigned char source[], int length); /* Pharmacode One Track */
extern int flattermarken(struct zint_symbol *symbol, unsigned char source[], int length); /* Flattermarken */
................................................................................
extern int post_plot(struct zint_symbol *symbol, unsigned char source[], int length); /* Postnet */
extern int planet_plot(struct zint_symbol *symbol, unsigned char source[], int length); /* PLANET */
extern int imail(struct zint_symbol *symbol, unsigned char source[], int length); /* Intelligent Mail (aka USPS OneCode) */
extern int royal_plot(struct zint_symbol *symbol, unsigned char source[], int length); /* RM4SCC */
extern int australia_post(struct zint_symbol *symbol, unsigned char source[], int length); /* Australia Post 4-state */
extern int code16k(struct zint_symbol *symbol, unsigned char source[], int length); /* Code 16k */
extern int pdf417enc(struct zint_symbol *symbol, unsigned char source[], int length); /* PDF417 */
extern int dmatrix(struct zint_symbol *symbol, const unsigned char source[], int length); /* Data Matrix (IEC16022) */
extern int qr_code(struct zint_symbol *symbol, const unsigned char source[], int length); /* QR Code */
extern int micro_pdf417(struct zint_symbol *symbol, unsigned char chaine[], int length); /* Micro PDF417 */
extern int maxicode(struct zint_symbol *symbol, unsigned char source[], int length); /* Maxicode */
extern int rss14(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS-14 */
extern int rsslimited(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS Limited */
extern int rssexpanded(struct zint_symbol *symbol, unsigned char source[], int length); /* RSS Expanded */
extern int composite(struct zint_symbol *symbol, unsigned char source[], int length); /* Composite Symbology */
................................................................................
extern int aztec_runes(struct zint_symbol *symbol, unsigned char source[], int length); /* Aztec Runes */
extern int korea_post(struct zint_symbol *symbol, unsigned char source[], int length); /* Korea Post */
extern int japan_post(struct zint_symbol *symbol, unsigned char source[], int length); /* Japanese Post */
extern int code_49(struct zint_symbol *symbol, unsigned char source[], const int length); /* Code 49 */
extern int channel_code(struct zint_symbol *symbol, unsigned char source[], int length); /* Channel Code */
extern int code_one(struct zint_symbol *symbol, unsigned char source[], int length); /* Code One */
extern int grid_matrix(struct zint_symbol *symbol, const unsigned char source[], int length); /* Grid Matrix */
extern int han_xin(struct zint_symbol * symbol, const unsigned char source[], int length); /* Han Xin */
extern int dotcode(struct zint_symbol * symbol, const unsigned char source[], int length); /* DotCode */
extern int codablock(struct zint_symbol * symbol, unsigned char source[], int length); /* Codablock */

extern int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to PNG/BMP/PCX */
extern int render_plot(struct zint_symbol *symbol, float width, float height); /* Plot to gLabels */
extern int ps_plot(struct zint_symbol *symbol); /* Plot to EPS */
extern int svg_plot(struct zint_symbol *symbol); /* Plot to SVG */



void error_tag(char error_string[], int error_number) {
    char error_buffer[100];

    if (error_number != 0) {
        strcpy(error_buffer, error_string);

................................................................................
    int space = 0;

    if (symbol->output_options & BARCODE_STDOUT) {
        f = stdout;
    } else {
        f = fopen(symbol->outfile, "w");
        if (!f) {
            strcpy(symbol->errtxt, "Could not open output file (B01)");
            return ZINT_ERROR_FILE_ACCESS;
        }
    }

    for (r = 0; r < symbol->rows; r++) {
        byt = 0;
        for (i = 0; i < symbol->width; i++) {
................................................................................
        fclose(f);
    }

    return 0;
}

/* Process health industry bar code data */
static int hibc(struct zint_symbol *symbol, unsigned char source[], size_t length) {
    int counter, error_number, i;
    char to_process[113], temp[2], check_digit;

    /* without "+" and check: max 110 characters in HIBC 2.6 */
    if (length > 110) {
        strcpy(symbol->errtxt, "Data too long for HIBC LIC (B02)");
        return ZINT_ERROR_TOO_LONG;
    }
    to_upper(source);
    error_number = is_sane(TECHNETIUM, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (B03)");
        return error_number;
    }

    strcpy(to_process, "+");
    counter = 41;
    for (i = 0; i < length; i++) {
        counter += posn(TECHNETIUM, source[i]);
................................................................................
            break;
        case BARCODE_HIBC_MICPDF:
            error_number = micro_pdf417(symbol, (unsigned char *) to_process, length);
            break;
        case BARCODE_HIBC_AZTEC:
            error_number = aztec(symbol, (unsigned char *) to_process, length);
            break;
        case BARCODE_HIBC_BLOCKF:
            error_number = codablock(symbol, (unsigned char *) to_process, length);
            break;
    }

    return error_number;
}

static void check_row_heights(struct zint_symbol *symbol) {
    /* Check that rows with undefined heights are never less than 5x  */
    int large_bar_count = 0;
    int i;
    int preset_height = 0;
    int large_bar_height = 0;
   
    for (i = 0; i < symbol->rows; i++) {
        preset_height += symbol->row_height[i];
        if (symbol->row_height[i] == 0) {
            large_bar_count++;
        }
    }
    
    if (large_bar_count == 0) {
        symbol->height = preset_height;
    } else {
        large_bar_height = (symbol->height - preset_height) / large_bar_count;
    }
    
    if (large_bar_height < 5) {
        for (i = 0; i < symbol->rows; i++) {
            if (symbol->row_height[i] == 0) {
                symbol->row_height[i] = 5;
                preset_height += 5;
            }
        }
        symbol->height = preset_height;
    }
}

static int gs1_compliant(const int symbology) {
    /* Returns 1 if symbology supports GS1 data */

    int result = 0;

    switch (symbology) {
................................................................................
        case BARCODE_RSS_EXPSTACK_CC:
        case BARCODE_CODE16K:
        case BARCODE_AZTEC:
        case BARCODE_DATAMATRIX:
        case BARCODE_CODEONE:
        case BARCODE_CODE49:
        case BARCODE_QRCODE:
        case BARCODE_DOTCODE:
            result = 1;
            break;
    }

    return result;
}

static int is_matrix(const int symbology) {
    /* Returns 1 if symbology is a matrix design */

    int result = 0;

    switch (symbology) {
        case BARCODE_QRCODE:
        case BARCODE_DATAMATRIX:
        case BARCODE_MICROQR:
        case BARCODE_HIBC_DM:
        case BARCODE_AZTEC:
        case BARCODE_HIBC_QR:
        case BARCODE_HIBC_AZTEC:
        case BARCODE_AZRUNE:
        case BARCODE_CODEONE:
        case BARCODE_GRIDMATRIX:
        case BARCODE_HANXIN:
        case BARCODE_DOTCODE:
            result = 1;
            break;
    }

    return result;
}

static int supports_eci(const int symbology) {
    /* Returns 1 if symbology can encode the ECI character */

    int result = 0;

    switch (symbology) {
        case BARCODE_AZTEC:
        case BARCODE_DATAMATRIX:
        case BARCODE_MAXICODE:
        case BARCODE_MICROPDF417:
        case BARCODE_PDF417:
        case BARCODE_PDF417TRUNC:
        case BARCODE_QRCODE:
        case BARCODE_DOTCODE:
        case BARCODE_GRIDMATRIX:
        case BARCODE_HANXIN:
            result = 1;
            break;
    }

    return result;
}

................................................................................
        case BARCODE_C25INTER:
        case BARCODE_C25IATA:
        case BARCODE_C25LOGIC:
        case BARCODE_C25IND:
        case BARCODE_CODE39:
        case BARCODE_EXCODE39:
        case BARCODE_EANX:
        case BARCODE_EANX_CHK:
        case BARCODE_EAN128:
        case BARCODE_CODABAR:
        case BARCODE_CODE128:
        case BARCODE_DPLEIT:
        case BARCODE_DPIDENT:
        case BARCODE_CODE16K:
        case BARCODE_CODE49:
................................................................................
        case BARCODE_CODE93:
        case BARCODE_FLAT:
        case BARCODE_RSS14:
        case BARCODE_RSS_LTD:
        case BARCODE_RSS_EXP:
        case BARCODE_TELEPEN:
        case BARCODE_UPCA:
        case BARCODE_UPCA_CHK:
        case BARCODE_UPCE:
        case BARCODE_UPCE_CHK:
        case BARCODE_POSTNET:
        case BARCODE_MSI_PLESSEY:
        case BARCODE_FIM:
        case BARCODE_LOGMARS:
        case BARCODE_PHARMA:
        case BARCODE_PZN:
        case BARCODE_PHARMA_TWO:
................................................................................
        case BARCODE_HIBC_128:
        case BARCODE_HIBC_39:
        case BARCODE_HIBC_DM:
        case BARCODE_HIBC_QR:
        case BARCODE_HIBC_PDF:
        case BARCODE_HIBC_MICPDF:
        case BARCODE_HIBC_AZTEC:
        case BARCODE_HIBC_BLOCKF:
        case BARCODE_AZRUNE:
        case BARCODE_CODE32:
        case BARCODE_EANX_CC:
        case BARCODE_EAN128_CC:
        case BARCODE_RSS14_CC:
        case BARCODE_RSS_LTD_CC:
        case BARCODE_RSS_EXP_CC:
................................................................................
        case BARCODE_UPCE_CC:
        case BARCODE_RSS14STACK_CC:
        case BARCODE_RSS14_OMNI_CC:
        case BARCODE_RSS_EXPSTACK_CC:
        case BARCODE_CHANNEL:
        case BARCODE_CODEONE:
        case BARCODE_GRIDMATRIX:
        case BARCODE_HANXIN:
        case BARCODE_DOTCODE:
        case BARCODE_CODABLOCKF:
            result = 1;
            break;
    }

    return result;
}

................................................................................
    switch (symbol->symbology) {
        case BARCODE_QRCODE: error_number = qr_code(symbol, source, length);
            break;
        case BARCODE_MICROQR: error_number = microqr(symbol, source, length);
            break;
        case BARCODE_GRIDMATRIX: error_number = grid_matrix(symbol, source, length);
            break;
        case BARCODE_HANXIN: error_number = han_xin(symbol, source, length);
            break;
    }

    return error_number;
}

static int reduced_charset(struct zint_symbol *symbol, const unsigned char *source, int in_length) {
    /* These are the "norm" standards which only support Latin-1 at most */
    int error_number = 0;

#ifndef _MSC_VER
    unsigned char preprocessed[in_length + 1];
#else
    unsigned char* preprocessed = (unsigned char*) _alloca(in_length + 1);
#endif

    if (symbol->symbology == BARCODE_CODE16K) {
        symbol->whitespace_width = 16;
        symbol->border_width = 2;
        if (!(symbol->output_options & BARCODE_BIND)) {
            symbol->output_options += BARCODE_BIND;
        }
    }
    else
        if (symbol->symbology == BARCODE_ITF14) {
        symbol->whitespace_width = 20;
        symbol->border_width = 8;
        if (!(symbol->output_options & BARCODE_BOX)) {
            symbol->output_options += BARCODE_BOX;
        }
    }

    switch (symbol->input_mode) {
        case DATA_MODE:
        case GS1_MODE:
            memcpy(preprocessed, source, in_length);
            preprocessed[in_length] = '\0';
            break;
        case UNICODE_MODE:
            error_number = utf_to_eci(symbol->eci, source, preprocessed, &in_length);
            if (error_number != 0) {
                strcpy(symbol->errtxt, "Invalid characters in input data (B04)");
                return error_number;
            }
            break;
    }

    switch (symbol->symbology) {
        case BARCODE_C25MATRIX: error_number = matrix_two_of_five(symbol, preprocessed, in_length);
            break;
        case BARCODE_C25IND: error_number = industrial_two_of_five(symbol, preprocessed, in_length);
            break;
        case BARCODE_C25INTER: error_number = interleaved_two_of_five(symbol, preprocessed, in_length);
            break;
        case BARCODE_C25IATA: error_number = iata_two_of_five(symbol, preprocessed, in_length);
            break;
        case BARCODE_C25LOGIC: error_number = logic_two_of_five(symbol, preprocessed, in_length);
            break;
        case BARCODE_DPLEIT: error_number = dpleit(symbol, preprocessed, in_length);
            break;
        case BARCODE_DPIDENT: error_number = dpident(symbol, preprocessed, in_length);
            break;
        case BARCODE_UPCA: 

        case BARCODE_UPCA_CHK:
        case BARCODE_UPCE: 
        case BARCODE_UPCE_CHK:
        case BARCODE_EANX: 
        case BARCODE_EANX_CHK:
            error_number = eanx(symbol, preprocessed, in_length);
            break;
        case BARCODE_EAN128: error_number = ean_128(symbol, preprocessed, in_length);
            break;
        case BARCODE_CODE39: error_number = c39(symbol, preprocessed, in_length);
            break;
        case BARCODE_PZN: error_number = pharmazentral(symbol, preprocessed, in_length);
            break;
        case BARCODE_EXCODE39: error_number = ec39(symbol, preprocessed, in_length);
            break;
        case BARCODE_CODABAR: error_number = codabar(symbol, preprocessed, in_length);
            break;
        case BARCODE_CODE93: error_number = c93(symbol, preprocessed, in_length);
            break;
        case BARCODE_LOGMARS: error_number = c39(symbol, preprocessed, in_length);
            break;
        case BARCODE_CODE128:

        case BARCODE_CODE128B: 
            error_number = code_128(symbol, preprocessed, in_length);
            break;
        case BARCODE_NVE18: error_number = nve_18(symbol, preprocessed, in_length);
            break;
        case BARCODE_CODE11: error_number = code_11(symbol, preprocessed, in_length);
            break;
        case BARCODE_MSI_PLESSEY: error_number = msi_handle(symbol, preprocessed, in_length);
            break;
        case BARCODE_TELEPEN: error_number = telepen(symbol, preprocessed, in_length);
            break;
        case BARCODE_TELEPEN_NUM: error_number = telepen_num(symbol, preprocessed, in_length);
            break;
        case BARCODE_PHARMA: error_number = pharma_one(symbol, preprocessed, in_length);
            break;
        case BARCODE_PLESSEY: error_number = plessey(symbol, preprocessed, in_length);
            break;
        case BARCODE_ITF14: error_number = itf14(symbol, preprocessed, in_length);
            break;
        case BARCODE_FLAT: error_number = flattermarken(symbol, preprocessed, in_length);
            break;
        case BARCODE_FIM: error_number = fim(symbol, preprocessed, in_length);
            break;
        case BARCODE_POSTNET: error_number = post_plot(symbol, preprocessed, in_length);
            break;
        case BARCODE_PLANET: error_number = planet_plot(symbol, preprocessed, in_length);
            break;
        case BARCODE_RM4SCC: error_number = royal_plot(symbol, preprocessed, in_length);
            break;
        case BARCODE_AUSPOST:

        case BARCODE_AUSREPLY: 

        case BARCODE_AUSROUTE:

        case BARCODE_AUSREDIRECT:
            error_number = australia_post(symbol, preprocessed, in_length);
            break;
        case BARCODE_CODE16K: error_number = code16k(symbol, preprocessed, in_length);
            break;
        case BARCODE_PHARMA_TWO: error_number = pharma_two(symbol, preprocessed, in_length);
            break;
        case BARCODE_ONECODE: error_number = imail(symbol, preprocessed, in_length);
            break;
        case BARCODE_ISBNX: error_number = eanx(symbol, preprocessed, in_length);
            break;
        case BARCODE_RSS14:

        case BARCODE_RSS14STACK: 
        case BARCODE_RSS14STACK_OMNI: 
            error_number = rss14(symbol, preprocessed, in_length);
            break;
        case BARCODE_RSS_LTD: error_number = rsslimited(symbol, preprocessed, in_length);
            break;
        case BARCODE_RSS_EXP: 
        case BARCODE_RSS_EXPSTACK: 
            error_number = rssexpanded(symbol, preprocessed, in_length);
            break;
        case BARCODE_EANX_CC: 

        case BARCODE_EAN128_CC: 

        case BARCODE_RSS14_CC: 

        case BARCODE_RSS_LTD_CC: 

        case BARCODE_RSS_EXP_CC: 

        case BARCODE_UPCA_CC: 

        case BARCODE_UPCE_CC: 

        case BARCODE_RSS14STACK_CC: 

        case BARCODE_RSS14_OMNI_CC: 

        case BARCODE_RSS_EXPSTACK_CC: 
            error_number = composite(symbol, preprocessed, in_length);
            break;
        case BARCODE_KIX: error_number = kix_code(symbol, preprocessed, in_length);
            break;
        case BARCODE_CODE32: error_number = code32(symbol, preprocessed, in_length);
            break;
        case BARCODE_DAFT: error_number = daft_code(symbol, preprocessed, in_length);
            break;
        case BARCODE_EAN14:
            error_number = ean_14(symbol, preprocessed, in_length);
            break;
        case BARCODE_AZRUNE: error_number = aztec_runes(symbol, preprocessed, in_length);
            break;
        case BARCODE_KOREAPOST: error_number = korea_post(symbol, preprocessed, in_length);
            break;
        case BARCODE_HIBC_128: 

        case BARCODE_HIBC_39: 

        case BARCODE_HIBC_DM: 

        case BARCODE_HIBC_QR: 

        case BARCODE_HIBC_PDF: 

        case BARCODE_HIBC_MICPDF: 

        case BARCODE_HIBC_AZTEC: 
        case BARCODE_HIBC_BLOCKF: 
            error_number = hibc(symbol, preprocessed, in_length);
            break;
        case BARCODE_JAPANPOST: error_number = japan_post(symbol, preprocessed, in_length);
            break;
        case BARCODE_CODE49: error_number = code_49(symbol, preprocessed, in_length);
            break;
        case BARCODE_CHANNEL: error_number = channel_code(symbol, preprocessed, in_length);
            break;
        case BARCODE_CODEONE: error_number = code_one(symbol, preprocessed, in_length);
            break;
        case BARCODE_DATAMATRIX: error_number = dmatrix(symbol, preprocessed, in_length);
            break;
        case BARCODE_PDF417: 

        case BARCODE_PDF417TRUNC: 
            error_number = pdf417enc(symbol, preprocessed, in_length);
            break;
        case BARCODE_MICROPDF417: error_number = micro_pdf417(symbol, preprocessed, in_length);
            break;
        case BARCODE_MAXICODE: error_number = maxicode(symbol, preprocessed, in_length);
            break;
        case BARCODE_AZTEC: error_number = aztec(symbol, preprocessed, in_length);
            break;
        case BARCODE_DOTCODE: error_number = dotcode(symbol, preprocessed, in_length);
            break;
        case BARCODE_CODABLOCKF: error_number = codablock(symbol, preprocessed, in_length);
            break;
    }

    return error_number;
}

int ZBarcode_Encode(struct zint_symbol *symbol, unsigned char *source, int length) {
................................................................................
    int error_number, error_buffer, i;
#ifdef _MSC_VER
    unsigned char* local_source;
#endif
    error_number = 0;

    if (length == 0) {
        length = (int) ustrlen(source);
    }
    if (length == 0) {
        strcpy(symbol->errtxt, "No input data (B05)");
        error_tag(symbol->errtxt, ZINT_ERROR_INVALID_DATA);
        return ZINT_ERROR_INVALID_DATA;
    }

    if (strcmp(symbol->outfile, "") == 0) {
#ifdef NO_PNG
        strcpy(symbol->outfile, "out.gif");
#else    
        strcpy(symbol->outfile, "out.png");
#endif
    }
#ifndef _MSC_VER
    unsigned char local_source[length + 1];
#else
    local_source = (unsigned char*) _alloca(length + 1);
#endif

    /* First check the symbology field */
    if (symbol->symbology < 1) {
        strcpy(symbol->errtxt, "Symbology out of range, using Code 128 (B06)");
        symbol->symbology = BARCODE_CODE128;
        error_number = ZINT_WARN_INVALID_OPTION;
    }

    /* symbol->symbologys 1 to 86 are defined by tbarcode */
    if (symbol->symbology == 5) {
        symbol->symbology = BARCODE_C25MATRIX;
    }
    if ((symbol->symbology >= 10) && (symbol->symbology <= 12)) {
        symbol->symbology = BARCODE_EANX;
    }
    if (symbol->symbology == 15) {
        symbol->symbology = BARCODE_EANX;
    }
    if (symbol->symbology == 17) {
        symbol->symbology = BARCODE_UPCA;
    }
    if (symbol->symbology == 19) {
        strcpy(symbol->errtxt, "Codabar 18 not supported, using Codabar (B07)");
        symbol->symbology = BARCODE_CODABAR;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    if (symbol->symbology == 26) {
        symbol->symbology = BARCODE_UPCA;
    }
    if (symbol->symbology == 27) {
        strcpy(symbol->errtxt, "UPCD1 not supported (B08)");
        error_number = ZINT_ERROR_INVALID_OPTION;
    }
    if (symbol->symbology == 33) {
        symbol->symbology = BARCODE_EAN128;
    }
    if (symbol->symbology == 36) {
        symbol->symbology = BARCODE_UPCA;
    }
    if (symbol->symbology == 38) {
        symbol->symbology = BARCODE_UPCE;
    }
    if ((symbol->symbology >= 41) && (symbol->symbology <= 45)) {
        symbol->symbology = BARCODE_POSTNET;
    }
    if (symbol->symbology == 46) {
        symbol->symbology = BARCODE_PLESSEY;
    }
    if (symbol->symbology == 48) {
        symbol->symbology = BARCODE_NVE18;
    }
    if (symbol->symbology == 54) {
        strcpy(symbol->errtxt, "General Parcel Code not supported, using Code 128 (B10)");
        symbol->symbology = BARCODE_CODE128;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    if ((symbol->symbology == 59) || (symbol->symbology == 61)) {
        symbol->symbology = BARCODE_CODE128;
    }
    if (symbol->symbology == 62) {
        symbol->symbology = BARCODE_CODE93;
    }
    if ((symbol->symbology == 64) || (symbol->symbology == 65)) {
        symbol->symbology = BARCODE_AUSPOST;
    }
    if (symbol->symbology == 73) {
        strcpy(symbol->errtxt, "Symbology out of range, using Code 128 (B11)");
        symbol->symbology = BARCODE_CODE128;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    if (symbol->symbology == 78) {
        symbol->symbology = BARCODE_RSS14;
    }
    if (symbol->symbology == 83) {
        symbol->symbology = BARCODE_PLANET;
    }
    if (symbol->symbology == 88) {
        symbol->symbology = BARCODE_EAN128;
    }
    if (symbol->symbology == 91) {
        strcpy(symbol->errtxt, "Symbology out of range, using Code 128 (B12)");
        symbol->symbology = BARCODE_CODE128;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    if ((symbol->symbology >= 94) && (symbol->symbology <= 96)) {
        strcpy(symbol->errtxt, "Symbology out of range, using Code 128 (B13)");
        symbol->symbology = BARCODE_CODE128;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    if (symbol->symbology == 100) {
        symbol->symbology = BARCODE_HIBC_128;
    }
    if (symbol->symbology == 101) {
................................................................................
    }
    if (symbol->symbology == 109) {
        symbol->symbology = BARCODE_HIBC_MICPDF;
    }
    if (symbol->symbology == 111) {
        symbol->symbology = BARCODE_HIBC_BLOCKF;
    }
    if ((symbol->symbology == 113) || (symbol->symbology == 114)) {
        strcpy(symbol->errtxt, "Symbology out of range, using Code 128 (B14)");
        symbol->symbology = BARCODE_CODE128;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    if (symbol->symbology == 115) {
        symbol->symbology = BARCODE_DOTCODE;
    }
    if ((symbol->symbology >= 117) && (symbol->symbology <= 127)) {
        strcpy(symbol->errtxt, "Symbology out of range, using Code 128 (B15)");
        symbol->symbology = BARCODE_CODE128;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    /* Everything from 128 up is Zint-specific */
    if (symbol->symbology >= 143) {
        strcpy(symbol->errtxt, "Symbology out of range, using Code 128 (B16)");
        symbol->symbology = BARCODE_CODE128;
        error_number = ZINT_WARN_INVALID_OPTION;
    }





    if (error_number > 4) {
        error_tag(symbol->errtxt, error_number);
        return error_number;
    } else {
        error_buffer = error_number;
    }

    if ((!(supports_eci(symbol->symbology))) && (symbol->eci != 3)) {
        strcpy(symbol->errtxt, "Symbology does not support ECI switching (B17)");
        error_number = ZINT_ERROR_INVALID_OPTION;
    }

    if ((symbol->eci < 3) || (symbol->eci > 26) || (symbol->eci == 14) || (symbol->eci == 19) || (symbol->eci == 25)) {
        strcpy(symbol->errtxt, "Invalid or unsupported ECI mode (B18)");
        error_number = ZINT_ERROR_INVALID_OPTION;
    }

    if ((symbol->input_mode < 0) || (symbol->input_mode > 2)) {
        symbol->input_mode = DATA_MODE;
    }

    if (symbol->input_mode == GS1_MODE) {
        for (i = 0; i < length; i++) {
            if (source[i] == '\0') {
                strcpy(symbol->errtxt, "NULL characters not permitted in GS1 mode (B19)");
                return ZINT_ERROR_INVALID_DATA;
            }
        }
        if (gs1_compliant(symbol->symbology) == 1) {
            error_number = ugs1_verify(symbol, source, length, local_source);
            if (error_number != 0) {
                return error_number;
            }
            length = ustrlen(local_source);
        } else {
            strcpy(symbol->errtxt, "Selected symbology does not support GS1 mode (B20)");
            return ZINT_ERROR_INVALID_OPTION;
        }
    } else {
        memcpy(local_source, source, length);
        local_source[length] = '\0';
    }
    
    if ((symbol->dot_size < 0.01) || (symbol->dot_size > 20.0)) {
        strcpy(symbol->errtxt, "Invalid dot size (B21)");
        return ZINT_ERROR_INVALID_OPTION;
    }

    switch (symbol->symbology) {
        case BARCODE_QRCODE:
        case BARCODE_MICROQR:
        case BARCODE_GRIDMATRIX:
        case BARCODE_HANXIN:
            error_number = extended_charset(symbol, local_source, length);
            break;
        default:
            error_number = reduced_charset(symbol, local_source, length);
            break;
    }

    if ((error_number == ZINT_ERROR_INVALID_DATA) && (supports_eci(symbol->symbology)
            && (symbol->input_mode == UNICODE_MODE))) {
        /* Try another ECI mode */
        symbol->eci = get_best_eci(local_source, length);
            
        error_number = ZINT_WARN_USES_ECI;
        strcpy(symbol->errtxt, "Encoded data includes ECI codes (B22)");
        //printf("Data will encode with ECI %d\n", symbol->eci);

        switch (symbol->symbology) {
            case BARCODE_QRCODE:
            case BARCODE_MICROQR:
            case BARCODE_GRIDMATRIX:
            case BARCODE_HANXIN:
                error_number = utf_to_eci(symbol->eci, source, local_source, &length);
                error_number = extended_charset(symbol, local_source, length);
                break;
            default:
                error_number = reduced_charset(symbol, local_source, length);
                break;
        }
        
    }

    if ((symbol->symbology == BARCODE_CODE128) || (symbol->symbology == BARCODE_CODE128B)) {
        for (i = 0; i < length; i++) {
            if (local_source[i] == '\0') {
                symbol->text[i] = ' ';
            } else {
                symbol->text[i] = local_source[i];
            }
        }
    }

    if (error_number == 0) {
        
        error_number = error_buffer;
    }
    error_tag(symbol->errtxt, error_number);
    
    if (error_number <= 5) {
        check_row_heights(symbol);
    }
    
    return error_number;
}

int ZBarcode_Print(struct zint_symbol *symbol, int rotate_angle) {
    int error_number;
    char output[4];

................................................................................
    switch (rotate_angle) {
        case 0:
        case 90:
        case 180:
        case 270:
            break;
        default:
            strcpy(symbol->errtxt, "Invalid rotation angle (B23)");
            return ZINT_ERROR_INVALID_OPTION;
    }

    if (symbol->output_options & BARCODE_DOTTY_MODE) {
        if (!(is_matrix(symbol->symbology))) {
            strcpy(symbol->errtxt, "Selected symbology cannot be rendered as dots (B24)");
            return ZINT_ERROR_INVALID_OPTION;
        }
    }

    if (strlen(symbol->outfile) > 3) {
        output[0] = symbol->outfile[strlen(symbol->outfile) - 3];
        output[1] = symbol->outfile[strlen(symbol->outfile) - 2];
        output[2] = symbol->outfile[strlen(symbol->outfile) - 1];
        output[3] = '\0';
        to_upper((unsigned char*) output);


        if (!(strcmp(output, "PNG"))) {
            if (symbol->scale < 1.0) {
                symbol->text[0] = '\0';
            }
            error_number = plot_raster(symbol, rotate_angle, OUT_PNG_FILE);
        } else
            if (!(strcmp(output, "BMP"))) {
            if (symbol->scale < 1.0) {
                symbol->text[0] = '\0';
            }
            error_number = plot_raster(symbol, rotate_angle, OUT_BMP_FILE);
        } else
            if (!(strcmp(output, "PCX"))) {
            if (symbol->scale < 1.0) {
                symbol->text[0] = '\0';
            }
            error_number = plot_raster(symbol, rotate_angle, OUT_PCX_FILE);
        } else
            if (!(strcmp(output, "GIF"))) {
            if (symbol->scale < 1.0) {
                symbol->text[0] = '\0';
            }
            error_number = plot_raster(symbol, rotate_angle, OUT_GIF_FILE);
        } else
            if (!(strcmp(output, "TXT"))) {
            error_number = dump_plot(symbol);
        } else
            if (!(strcmp(output, "EPS"))) {
            error_number = ps_plot(symbol);
        } else
            if (!(strcmp(output, "SVG"))) {
            error_number = svg_plot(symbol);
        } else {
            strcpy(symbol->errtxt, "Unknown output format (B25)");
            error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
            return ZINT_ERROR_INVALID_OPTION;
        }
    } else {
        strcpy(symbol->errtxt, "Unknown output format (B26)");
        error_tag(symbol->errtxt, ZINT_ERROR_INVALID_OPTION);
        return ZINT_ERROR_INVALID_OPTION;
    }

    if (error_number == ZINT_ERROR_INVALID_OPTION) {
        /* If libpng is not installed */
        strcpy(symbol->errtxt, "Unknown output format (B27)");
    }

    error_tag(symbol->errtxt, error_number);
    return error_number;
}

int ZBarcode_Buffer(struct zint_symbol *symbol, int rotate_angle) {
    int error_number;
................................................................................
    switch (rotate_angle) {
        case 0:
        case 90:
        case 180:
        case 270:
            break;
        default:
            strcpy(symbol->errtxt, "Invalid rotation angle (B28)");
            return ZINT_ERROR_INVALID_OPTION;
    }

    error_number = plot_raster(symbol, rotate_angle, OUT_BUFFER);
    error_tag(symbol->errtxt, error_number);
    return error_number;
}

int ZBarcode_Encode_and_Print(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle) {
    int error_number;



    error_number = ZBarcode_Encode(symbol, input, length);
    if (error_number != 0) {
        return error_number;
    }

    error_number = ZBarcode_Print(symbol, rotate_angle);
    return error_number;
}

int ZBarcode_Encode_and_Buffer(struct zint_symbol *symbol, unsigned char *input, int length, int rotate_angle) {
    int error_number;



    error_number = ZBarcode_Encode(symbol, input, length);
    if (error_number != 0) {
        return error_number;
    }

    error_number = ZBarcode_Buffer(symbol, rotate_angle);
    return error_number;
................................................................................

    if (!strcmp(filename, "-")) {
        file = stdin;
        fileLen = 7100;
    } else {
        file = fopen(filename, "rb");
        if (!file) {
            strcpy(symbol->errtxt, "Unable to read input file (B29)");
            return ZINT_ERROR_INVALID_DATA;
        }

        /* Get file length */
        fseek(file, 0, SEEK_END);
        fileLen = ftell(file);
        fseek(file, 0, SEEK_SET);

        if (fileLen > 7100) {
            /* The largest amount of data that can be encoded is 7089 numeric digits in QR Code */
            strcpy(symbol->errtxt, "Input file too long (B30)");
            fclose(file);
            return ZINT_ERROR_INVALID_DATA;
        }
    }

    /* Allocate memory */
    buffer = (unsigned char *) malloc(fileLen * sizeof (unsigned char));
    if (!buffer) {
        strcpy(symbol->errtxt, "Internal memory error (B31)");
        if (strcmp(filename, "-"))
            fclose(file);
        return ZINT_ERROR_MEMORY;
    }

    /* Read file contents into buffer */

    do {
        n = fread(buffer + nRead, 1, fileLen - nRead, file);
        if (ferror(file)) {
            strcpy(symbol->errtxt, strerror(errno));

            return ZINT_ERROR_INVALID_DATA;
        }
        nRead += n;
    } while (!feof(file) && (0 < n) && (nRead < fileLen));

    fclose(file);
    ret = ZBarcode_Encode(symbol, buffer, nRead);
................................................................................
    free(buffer);
    return ret;
}

int ZBarcode_Encode_File_and_Print(struct zint_symbol *symbol, char *filename, int rotate_angle) {
    int error_number;



    error_number = ZBarcode_Encode_File(symbol, filename);
    if (error_number != 0) {
        return error_number;
    }

    return ZBarcode_Print(symbol, rotate_angle);
}

int ZBarcode_Encode_File_and_Buffer(struct zint_symbol *symbol, char *filename, int rotate_angle) {
    int error_number;



    error_number = ZBarcode_Encode_File(symbol, filename);
    if (error_number != 0) {
        return error_number;
    }

    return ZBarcode_Buffer(symbol, rotate_angle);
}
................................................................................
 * Converts encoded data into an intermediate format to be interpreted
 * in other applications using this library.
 *
 * If the width and height are not set to zero, the barcode will be resized to those
 * dimensions. The symbol->scale and symbol->height values are totally ignored in this case.
 *
 */
int ZBarcode_Render(struct zint_symbol *symbol, const float width, const float height) {
    // Send the request to the render_plot method
    return render_plot(symbol, width, height);
}

Changes to jni/zint/backend/maxicode.c.

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
...
452
453
454
455
456
457
458









459
460
461
462
463
464
465
...
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
...
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
...
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
/* Includes corrections thanks to Monica Swanson @ Source Technologies */

#include "common.h"
#include "maxicode.h"
#include "reedsol.h"
#include <string.h>
#include <stdlib.h>
#ifdef __APPLE__
#include <sys/malloc.h>
#else
#include <malloc.h>
#endif

int maxi_codeword[144];

/* Handles error correction of primary message */
void maxi_do_primary_check() {
    unsigned char data[15];
    unsigned char results[15];
................................................................................
    for (i = 143; i > bump_posn; i--) {
        set[i] = set[i - 1];
        character[i] = character[i - 1];
    }
}

/* Format text according to Appendix A */
int maxi_text_process(int mode, unsigned char source[], int length) {
    /* This code doesn't make use of [Lock in C], [Lock in D]
    and [Lock in E] and so is not always the most efficient at
    compressing data, but should suffice for most applications */

    int set[144], character[144], i, j, done, count, current_set;

    if (length > 138) {
................................................................................
            }
            length -= 3;
        } else {
            i++;
        }
    } while (i <= 143);










    if (((mode == 2) || (mode == 3)) && (length > 84)) {
        return ZINT_ERROR_TOO_LONG;
    }

    if (((mode == 4) || (mode == 6)) && (length > 93)) {
        return ZINT_ERROR_TOO_LONG;
    }
................................................................................
    maxi_codeword[5] = ((postcode[0] & 0x03) << 4) | ((postcode[1] & 0x3c) >> 2);
    maxi_codeword[6] = ((postcode[0] & 0x3c) >> 2) | ((country & 0x3) << 4);
    maxi_codeword[7] = (country & 0xfc) >> 2;
    maxi_codeword[8] = ((country & 0x300) >> 8) | ((service & 0xf) << 2);
    maxi_codeword[9] = ((service & 0x3f0) >> 4);
}

int maxicode(struct zint_symbol *symbol, unsigned char source[], int length) {
    int i, j, block, bit, mode, countrycode = 0, service = 0, lp = 0;
    int bit_pattern[7], internal_error = 0, eclen, error_number;
    char postcode[12], countrystr[4], servicestr[4];

#ifndef _MSC_VER
    unsigned char local_source[length + 1];
#else
    unsigned char* local_source = (unsigned char*) _alloca(length + 1);
#endif

    mode = symbol->option_1;
    strcpy(postcode, "");
    strcpy(countrystr, "");
    strcpy(servicestr, "");

    /* The following to be replaced by ECI handling */
    switch (symbol->input_mode) {
        case DATA_MODE:
        case GS1_MODE:
            memcpy(local_source, source, length);
            local_source[length] = '\0';
            break;
        case UNICODE_MODE:
            error_number = latin1_process(symbol, source, local_source, &length);
            if (error_number != 0) {
                return error_number;
            }
            break;
    }
    memset(maxi_codeword, 0, sizeof (maxi_codeword));

    if (mode == -1) { /* If mode is unspecified */
        lp = strlen(symbol->primary);
        if (lp == 0) {
            mode = 4;
        } else {
................................................................................
                    break;
                }
            }
        }
    }

    if ((mode < 2) || (mode > 6)) { /* Only codes 2 to 6 supported */
        strcpy(symbol->errtxt, "Invalid Maxicode Mode");
        return ZINT_ERROR_INVALID_OPTION;
    }

    if ((mode == 2) || (mode == 3)) { /* Modes 2 and 3 need data in symbol->primary */
        if (lp == 0) { /* Mode set manually means lp doesn't get set */
            lp = strlen(symbol->primary);
        }
        if (lp != 15) {
            strcpy(symbol->errtxt, "Invalid Primary String");
            return ZINT_ERROR_INVALID_DATA;
        }

        for (i = 9; i < 15; i++) { /* check that country code and service are numeric */
            if ((symbol->primary[i] < '0') || (symbol->primary[i] > '9')) {
                strcpy(symbol->errtxt, "Invalid Primary String");
                return ZINT_ERROR_INVALID_DATA;
            }
        }

        memcpy(postcode, symbol->primary, 9);
        postcode[9] = '\0';

................................................................................
        if (mode == 3) {
            maxi_do_primary_3(postcode, countrycode, service);
        }
    } else {
        maxi_codeword[0] = mode;
    }

    i = maxi_text_process(mode, local_source, length);
    if (i == ZINT_ERROR_TOO_LONG) {
        strcpy(symbol->errtxt, "Input data too long");
        return i;
    }

    /* All the data is sorted - now do error correction */
    maxi_do_primary_check(); /* always EEC */

    if (mode == 5)







<
<
<
<
<







 







|







 







>
>
>
>
>
>
>
>
>







 







|

|


<
<
<
<
<
<





<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|








|





|







 







|

|







33
34
35
36
37
38
39





40
41
42
43
44
45
46
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
...
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
...
553
554
555
556
557
558
559
560
561
562
563
564






565
566
567
568
569














570
571
572
573
574
575
576
...
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
...
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
/* Includes corrections thanks to Monica Swanson @ Source Technologies */

#include "common.h"
#include "maxicode.h"
#include "reedsol.h"
#include <string.h>
#include <stdlib.h>






int maxi_codeword[144];

/* Handles error correction of primary message */
void maxi_do_primary_check() {
    unsigned char data[15];
    unsigned char results[15];
................................................................................
    for (i = 143; i > bump_posn; i--) {
        set[i] = set[i - 1];
        character[i] = character[i - 1];
    }
}

/* Format text according to Appendix A */
int maxi_text_process(int mode, unsigned char source[], int length, int eci) {
    /* This code doesn't make use of [Lock in C], [Lock in D]
    and [Lock in E] and so is not always the most efficient at
    compressing data, but should suffice for most applications */

    int set[144], character[144], i, j, done, count, current_set;

    if (length > 138) {
................................................................................
            }
            length -= 3;
        } else {
            i++;
        }
    } while (i <= 143);

    /* Insert ECI at the beginning of message if needed */
    if (eci != 3) {
        maxi_bump(set, character, 0);
        character[0] = 27; // ECI
        maxi_bump(set, character, 1);
        character[1] = eci;
        length += 2;
    }
    
    if (((mode == 2) || (mode == 3)) && (length > 84)) {
        return ZINT_ERROR_TOO_LONG;
    }

    if (((mode == 4) || (mode == 6)) && (length > 93)) {
        return ZINT_ERROR_TOO_LONG;
    }
................................................................................
    maxi_codeword[5] = ((postcode[0] & 0x03) << 4) | ((postcode[1] & 0x3c) >> 2);
    maxi_codeword[6] = ((postcode[0] & 0x3c) >> 2) | ((country & 0x3) << 4);
    maxi_codeword[7] = (country & 0xfc) >> 2;
    maxi_codeword[8] = ((country & 0x300) >> 8) | ((service & 0xf) << 2);
    maxi_codeword[9] = ((service & 0x3f0) >> 4);
}

int maxicode(struct zint_symbol *symbol, unsigned char local_source[], int length) {
    int i, j, block, bit, mode, countrycode = 0, service = 0, lp = 0;
    int bit_pattern[7], internal_error = 0, eclen;
    char postcode[12], countrystr[4], servicestr[4];







    mode = symbol->option_1;
    strcpy(postcode, "");
    strcpy(countrystr, "");
    strcpy(servicestr, "");















    memset(maxi_codeword, 0, sizeof (maxi_codeword));

    if (mode == -1) { /* If mode is unspecified */
        lp = strlen(symbol->primary);
        if (lp == 0) {
            mode = 4;
        } else {
................................................................................
                    break;
                }
            }
        }
    }

    if ((mode < 2) || (mode > 6)) { /* Only codes 2 to 6 supported */
        strcpy(symbol->errtxt, "Invalid Maxicode Mode (E50)");
        return ZINT_ERROR_INVALID_OPTION;
    }

    if ((mode == 2) || (mode == 3)) { /* Modes 2 and 3 need data in symbol->primary */
        if (lp == 0) { /* Mode set manually means lp doesn't get set */
            lp = strlen(symbol->primary);
        }
        if (lp != 15) {
            strcpy(symbol->errtxt, "Invalid Primary String (E51)");
            return ZINT_ERROR_INVALID_DATA;
        }

        for (i = 9; i < 15; i++) { /* check that country code and service are numeric */
            if ((symbol->primary[i] < '0') || (symbol->primary[i] > '9')) {
                strcpy(symbol->errtxt, "Invalid Primary String (E52)");
                return ZINT_ERROR_INVALID_DATA;
            }
        }

        memcpy(postcode, symbol->primary, 9);
        postcode[9] = '\0';

................................................................................
        if (mode == 3) {
            maxi_do_primary_3(postcode, countrycode, service);
        }
    } else {
        maxi_codeword[0] = mode;
    }

    i = maxi_text_process(mode, local_source, length, symbol->eci);
    if (i == ZINT_ERROR_TOO_LONG) {
        strcpy(symbol->errtxt, "Input data too long (E53)");
        return i;
    }

    /* All the data is sorted - now do error correction */
    maxi_do_primary_check(); /* always EEC */

    if (mode == 5)

Deleted jni/zint/backend/maxipng.h.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/* maxipng.h - Shapes for Maxicode output to PNG file */

/*
    libzint - the open source barcode library
    Copyright (C) 2008-2016 Robin Stuart <rstuart114@gmail.com>

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

    1. Redistributions of source code must retain the above copyright 
       notice, this list of conditions and the following disclaimer.  
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.  
    3. Neither the name of the project nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission. 

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
    SUCH DAMAGE.
 */

/* This file contains the pixel-by-pixel representation of maxicode glyphs
   at a resolution of 12 pixels per millimeter. hexagon[] is taken directly
   from ISO 16023 Annex J. bullseye[] was calculated by the Gimp */

#define SSET	"0123456789ABCDEF"

static const int hexagon[120] = {
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
    0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
    0, 0, 1, 1, 1, 1, 1, 1, 1, 0,
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    0, 0, 1, 1, 1, 1, 1, 1, 1, 0,
    0, 0, 0, 1, 1, 1, 1, 1, 0, 0,
    0, 0, 0, 0, 1, 1, 1, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

static const unsigned int bullseye_compressed[] = {
    0, 0, 0, 0, 0, 255, 248, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 31, 255, 255, 192, 0, 0, 0, 0,
    0, 0, 0, 1, 255, 255, 255, 252, 0, 0, 0, 0,
    0, 0, 0, 7, 255, 255, 255, 255, 0, 0, 0, 0,
    0, 0, 0, 31, 255, 255, 255, 255, 192, 0, 0, 0,
    0, 0, 0, 127, 255, 255, 255, 255, 240, 0, 0, 0,
    0, 0, 1, 255, 255, 255, 255, 255, 252, 0, 0, 0,
    0, 0, 7, 255, 255, 255, 255, 255, 255, 0, 0, 0,
    0, 0, 15, 255, 255, 0, 7, 255, 255, 128, 0, 0,
    0, 0, 63, 255, 240, 0, 0, 127, 255, 224, 0, 0,
    0, 0, 127, 255, 128, 0, 0, 15, 255, 240, 0, 0,
    0, 0, 255, 252, 0, 0, 0, 1, 255, 248, 0, 0,
    0, 1, 255, 240, 0, 0, 0, 0, 127, 252, 0, 0,
    0, 3, 255, 224, 0, 0, 0, 0, 63, 254, 0, 0,
    0, 7, 255, 128, 0, 0, 0, 0, 15, 255, 0, 0,
    0, 15, 255, 0, 0, 0, 0, 0, 7, 255, 128, 0,
    0, 31, 252, 0, 0, 127, 240, 0, 1, 255, 192, 0,
    0, 63, 248, 0, 7, 255, 255, 0, 0, 255, 224, 0,
    0, 127, 240, 0, 63, 255, 255, 224, 0, 127, 240, 0,
    0, 127, 224, 0, 255, 255, 255, 248, 0, 63, 240, 0,
    0, 255, 192, 1, 255, 255, 255, 252, 0, 31, 248, 0,
    1, 255, 128, 7, 255, 255, 255, 255, 0, 15, 252, 0,
    1, 255, 0, 15, 255, 255, 255, 255, 128, 7, 252, 0,
    3, 255, 0, 63, 255, 255, 255, 255, 224, 7, 254, 0,
    3, 254, 0, 127, 255, 192, 31, 255, 240, 3, 254, 0,
    7, 252, 0, 255, 252, 0, 1, 255, 248, 1, 255, 0,
    7, 252, 1, 255, 240, 0, 0, 127, 252, 1, 255, 0,
    15, 248, 1, 255, 192, 0, 0, 31, 252, 0, 255, 128,
    15, 240, 3, 255, 128, 0, 0, 15, 254, 0, 127, 128,
    31, 240, 7, 255, 0, 0, 0, 7, 255, 0, 127, 192,
    31, 224, 7, 254, 0, 0, 0, 3, 255, 0, 63, 192,
    63, 224, 15, 252, 0, 0, 0, 1, 255, 128, 63, 224,
    63, 224, 31, 248, 0, 63, 192, 0, 255, 192, 63, 224,
    63, 192, 31, 240, 0, 255, 240, 0, 127, 192, 31, 224,
    63, 192, 63, 224, 3, 255, 252, 0, 63, 224, 31, 224,
    127, 192, 63, 224, 7, 255, 254, 0, 63, 224, 31, 240,
    127, 128, 63, 192, 15, 255, 255, 0, 31, 224, 15, 240,
    127, 128, 127, 192, 31, 255, 255, 128, 31, 240, 15, 240,
    127, 128, 127, 128, 63, 255, 255, 192, 15, 240, 15, 240,
    127, 128, 127, 128, 63, 255, 255, 192, 15, 240, 15, 240,
    255, 0, 127, 128, 127, 240, 255, 224, 15, 240, 7, 240,
    255, 0, 255, 128, 127, 192, 63, 224, 15, 248, 7, 240,
    255, 0, 255, 0, 255, 128, 31, 240, 7, 248, 7, 240,
    255, 0, 255, 0, 255, 128, 31, 240, 7, 248, 7, 240,
    255, 0, 255, 0, 255, 0, 15, 240, 7, 248, 7, 240,
    255, 0, 255, 0, 255, 0, 15, 240, 7, 248, 7, 240,
    255, 0, 255, 0, 255, 0, 15, 240, 7, 248, 7, 240,
    255, 0, 255, 0, 255, 0, 15, 240, 7, 248, 7, 240,
    255, 0, 255, 0, 255, 128, 31, 240, 7, 248, 7, 240,
    255, 0, 255, 0, 255, 128, 31, 240, 7, 248, 7, 240,
    255, 0, 255, 0, 127, 192, 63, 224, 7, 248, 7, 240,
    255, 0, 255, 128, 127, 240, 255, 224, 15, 248, 7, 240,
    255, 0, 127, 128, 63, 255, 255, 192, 15, 240, 7, 240,
    127, 128, 127, 128, 63, 255, 255, 192, 15, 240, 15, 240,
    127, 128, 127, 128, 31, 255, 255, 128, 15, 240, 15, 240,
    127, 128, 127, 192, 15, 255, 255, 0, 31, 240, 15, 240,
    127, 128, 63, 192, 7, 255, 254, 0, 31, 224, 15, 240,
    127, 192, 63, 224, 3, 255, 252, 0, 63, 224, 31, 240,
    63, 192, 63, 224, 0, 255, 240, 0, 63, 224, 31, 224,
    63, 192, 31, 240, 0, 63, 192, 0, 127, 192, 31, 224,
    63, 224, 31, 248, 0, 0, 0, 0, 255, 192, 63, 224,
    63, 224, 15, 252, 0, 0, 0, 1, 255, 128, 63, 224,
    31, 224, 7, 254, 0, 0, 0, 3, 255, 0, 63, 192,
    31, 240, 7, 255, 0, 0, 0, 7, 255, 0, 127, 192,
    15, 240, 3, 255, 128, 0, 0, 15, 254, 0, 127, 128,
    15, 248, 1, 255, 192, 0, 0, 31, 252, 0, 255, 128,
    7, 252, 1, 255, 240, 0, 0, 127, 252, 1, 255, 0,
    7, 252, 0, 255, 252, 0, 1, 255, 248, 1, 255, 0,
    3, 254, 0, 127, 255, 192, 31, 255, 240, 3, 254, 0,
    3, 255, 0, 63, 255, 255, 255, 255, 224, 7, 254, 0,
    1, 255, 0, 15, 255, 255, 255, 255, 128, 7, 252, 0,
    1, 255, 128, 7, 255, 255, 255, 255, 0, 15, 252, 0,
    0, 255, 192, 1, 255, 255, 255, 252, 0, 31, 248, 0,
    0, 127, 224, 0, 255, 255, 255, 248, 0, 63, 240, 0,
    0, 127, 240, 0, 63, 255, 255, 224, 0, 127, 240, 0,
    0, 63, 248, 0, 7, 255, 255, 0, 0, 255, 224, 0,
    0, 31, 252, 0, 0, 127, 240, 0, 1, 255, 192, 0,
    0, 15, 255, 0, 0, 0, 0, 0, 7, 255, 128, 0,
    0, 7, 255, 128, 0, 0, 0, 0, 15, 255, 0, 0,
    0, 3, 255, 224, 0, 0, 0, 0, 63, 254, 0, 0,
    0, 1, 255, 240, 0, 0, 0, 0, 127, 252, 0, 0,
    0, 0, 255, 252, 0, 0, 0, 1, 255, 248, 0, 0,
    0, 0, 127, 255, 128, 0, 0, 15, 255, 240, 0, 0,
    0, 0, 63, 255, 240, 0, 0, 127, 255, 224, 0, 0,
    0, 0, 15, 255, 255, 0, 7, 255, 255, 128, 0, 0,
    0, 0, 7, 255, 255, 255, 255, 255, 255, 0, 0, 0,
    0, 0, 1, 255, 255, 255, 255, 255, 252, 0, 0, 0,
    0, 0, 0, 127, 255, 255, 255, 255, 240, 0, 0, 0,
    0, 0, 0, 31, 255, 255, 255, 255, 192, 0, 0, 0,
    0, 0, 0, 7, 255, 255, 255, 255, 0, 0, 0, 0,
    0, 0, 0, 1, 255, 255, 255, 252, 0, 0, 0, 0,
    0, 0, 0, 0, 31, 255, 255, 192, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 255, 248, 0, 0, 0, 0, 0
};

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










































































































































































































































































































Changes to jni/zint/backend/medical.c.

31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
..
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
...
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
...
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "common.h"

extern int c39(struct zint_symbol *symbol, unsigned char source[], int length);
/* Codabar table checked against EN 798:1995 */

#define CALCIUM	"0123456789-$:/.+ABCD"

static const char *CodaTable[20] = {
    "11111221", "11112211", "11121121", "22111111", "11211211", "21111211",
    "12111121", "12112111", "12211111", "21121111", "11122111", "11221111", "21112121", "21211121",
................................................................................
       the specification at http://www.laetus.com/laetus.php?request=file&id=69 */

    unsigned long int tester;
    int counter, error_number, h;
    char inter[18] = {0}; /* 131070 -> 17 bits */
    char dest[64]; /* 17 * 2 + 1 */

    error_number = 0;

    if (length > 6) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }

    tester = atoi((char*) source);

    if ((tester < 3) || (tester > 131070)) {
        strcpy(symbol->errtxt, "Data out of range");
        return ZINT_ERROR_INVALID_DATA;
    }

    do {
        if (!(tester & 1)) {
            strcat(inter, "W");
            tester = (tester - 2) / 2;
................................................................................
    int counter, h;
    char inter[17];
    int error_number;

    tester = atoi((char*) source);

    if ((tester < 4) || (tester > 64570080)) {
        strcpy(symbol->errtxt, "Data out of range");
        return ZINT_ERROR_INVALID_DATA;
    }
    error_number = 0;
    strcpy(inter, "");
    do {
        switch (tester % 3) {
            case 0:
................................................................................
    char height_pattern[200];
    unsigned int loopey, h;
    int writer;
    int error_number = 0;
    strcpy(height_pattern, "");

    if (length > 8) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }
    error_number = pharma_two_calc(symbol, source, height_pattern);
    if (error_number != 0) {
        return error_number;
    }

................................................................................

/* The Codabar system consisting of simple substitution */
int codabar(struct zint_symbol *symbol, unsigned char source[], int length) {

    int i, error_number;
    char dest[512];

    error_number = 0;
    strcpy(dest, "");

    if (length > 60) { /* No stack smashing please */
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    to_upper(source);
    error_number = is_sane(CALCIUM, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }
    /* Codabar must begin and end with the characters A, B, C or D */
    if ((source[0] != 'A') && (source[0] != 'B') && (source[0] != 'C')
            && (source[0] != 'D')) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return ZINT_ERROR_INVALID_DATA;
    }

    if ((source[length - 1] != 'A') && (source[length - 1] != 'B') &&
            (source[length - 1] != 'C') && (source[length - 1] != 'D')) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return ZINT_ERROR_INVALID_DATA;
    }

    for (i = 0; i < length; i++) {
        lookup(CALCIUM, CodaTable, source[i], dest);
    }

................................................................................
    char localstr[10], risultante[7];
    long int pharmacode, remainder, devisor;
    int codeword[6];
    char tabella[34];

    /* Validate the input */
    if (length > 8) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }

    /* Add leading zeros as required */
    zeroes = 8 - length;
    memset(localstr, '0', zeroes);
    strcpy(localstr + zeroes, (char*) source);







|







 







<
<

|




|






|







 







|







 







|




|







 







<



|





|





|





|







 







|




|







31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
..
60
61
62
63
64
65
66


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
...
193
194
195
196
197
198
199

200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "common.h"

extern int c39(struct zint_symbol *symbol, unsigned char source[], const size_t length);
/* Codabar table checked against EN 798:1995 */

#define CALCIUM	"0123456789-$:/.+ABCD"

static const char *CodaTable[20] = {
    "11111221", "11112211", "11121121", "22111111", "11211211", "21111211",
    "12111121", "12112111", "12211111", "21121111", "11122111", "11221111", "21112121", "21211121",
................................................................................
       the specification at http://www.laetus.com/laetus.php?request=file&id=69 */

    unsigned long int tester;
    int counter, error_number, h;
    char inter[18] = {0}; /* 131070 -> 17 bits */
    char dest[64]; /* 17 * 2 + 1 */



    if (length > 6) {
        strcpy(symbol->errtxt, "Input too long (C50)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C51)");
        return error_number;
    }

    tester = atoi((char*) source);

    if ((tester < 3) || (tester > 131070)) {
        strcpy(symbol->errtxt, "Data out of range (C52)");
        return ZINT_ERROR_INVALID_DATA;
    }

    do {
        if (!(tester & 1)) {
            strcat(inter, "W");
            tester = (tester - 2) / 2;
................................................................................
    int counter, h;
    char inter[17];
    int error_number;

    tester = atoi((char*) source);

    if ((tester < 4) || (tester > 64570080)) {
        strcpy(symbol->errtxt, "Data out of range (C53)");
        return ZINT_ERROR_INVALID_DATA;
    }
    error_number = 0;
    strcpy(inter, "");
    do {
        switch (tester % 3) {
            case 0:
................................................................................
    char height_pattern[200];
    unsigned int loopey, h;
    int writer;
    int error_number = 0;
    strcpy(height_pattern, "");

    if (length > 8) {
        strcpy(symbol->errtxt, "Input too long (C54)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C55)");
        return error_number;
    }
    error_number = pharma_two_calc(symbol, source, height_pattern);
    if (error_number != 0) {
        return error_number;
    }

................................................................................

/* The Codabar system consisting of simple substitution */
int codabar(struct zint_symbol *symbol, unsigned char source[], int length) {

    int i, error_number;
    char dest[512];


    strcpy(dest, "");

    if (length > 60) { /* No stack smashing please */
        strcpy(symbol->errtxt, "Input too long (C56)");
        return ZINT_ERROR_TOO_LONG;
    }
    to_upper(source);
    error_number = is_sane(CALCIUM, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C57)");
        return error_number;
    }
    /* Codabar must begin and end with the characters A, B, C or D */
    if ((source[0] != 'A') && (source[0] != 'B') && (source[0] != 'C')
            && (source[0] != 'D')) {
        strcpy(symbol->errtxt, "Invalid characters in data (C58)");
        return ZINT_ERROR_INVALID_DATA;
    }

    if ((source[length - 1] != 'A') && (source[length - 1] != 'B') &&
            (source[length - 1] != 'C') && (source[length - 1] != 'D')) {
        strcpy(symbol->errtxt, "Invalid characters in data (C59)");
        return ZINT_ERROR_INVALID_DATA;
    }

    for (i = 0; i < length; i++) {
        lookup(CALCIUM, CodaTable, source[i], dest);
    }

................................................................................
    char localstr[10], risultante[7];
    long int pharmacode, remainder, devisor;
    int codeword[6];
    char tabella[34];

    /* Validate the input */
    if (length > 8) {
        strcpy(symbol->errtxt, "Input too long (C5A)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(NEON, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C5B)");
        return error_number;
    }

    /* Add leading zeros as required */
    zeroes = 8 - length;
    memset(localstr, '0', zeroes);
    strcpy(localstr + zeroes, (char*) source);

Added jni/zint/backend/pcx.c.

























































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/* pcx.c - Handles output to ZSoft PCX file */

/*
    libzint - the open source barcode library
    Copyright (C) 2009-2016 Robin Stuart <rstuart114@gmail.com>

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

    1. Redistributions of source code must retain the above copyright 
       notice, this list of conditions and the following disclaimer.  
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.  
    3. Neither the name of the project nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission. 

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
    SUCH DAMAGE.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
#include "pcx.h"        /* PCX header structure */
#include <math.h>
#ifdef _MSC_VER
#include <io.h>
#include <fcntl.h>
#include <malloc.h>
#endif

#define SSET	"0123456789ABCDEF"

int pcx_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) {
    int fgred, fggrn, fgblu, bgred, bggrn, bgblu;
    int row, column, i, colour;
    int run_count;
    FILE *pcx_file;
    pcx_header_t header;
#ifdef _MSC_VER
    unsigned char* rle_row;
#endif

#ifndef _MSC_VER
    unsigned char rle_row[symbol->bitmap_width];
#else
    rle_row = (unsigned char *) _alloca((symbol->bitmap_width * 6) * sizeof (unsigned char));
#endif /* _MSC_VER */

    fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
    fggrn = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]);
    fgblu = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]);
    bgred = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]);
    bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]);
    bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]);


    header.manufacturer = 10; // ZSoft
    header.version = 5; // Version 3.0
    header.encoding = 1; // Run length encoding
    header.bits_per_pixel = 8;
    header.window_xmin = 0;
    header.window_ymin = 0;
    header.window_xmax = symbol->bitmap_width - 1;
    header.window_ymax = symbol->bitmap_height - 1;
    header.horiz_dpi = 300;
    header.vert_dpi = 300;

    for (i = 0; i < 48; i++) {
        header.colourmap[i] = 0x00;
    }

    header.reserved = 0;
    header.number_of_planes = 3;

    if (symbol->bitmap_width % 2) {
        header.bytes_per_line = symbol->bitmap_width + 1;
    } else {
        header.bytes_per_line = symbol->bitmap_width;
    }

    header.palette_info = 1; // Colour
    header.horiz_screen_size = 0;
    header.vert_screen_size = 0;

    for (i = 0; i < 54; i++) {
        header.filler[i] = 0x00;
    }

    /* Open output file in binary mode */
    if (symbol->output_options & BARCODE_STDOUT) {
#ifdef _MSC_VER
        if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
            strcpy(symbol->errtxt, "Can't open output file");
            return ZINT_ERROR_FILE_ACCESS;
        }
#endif
        pcx_file = stdout;
    } else {
        if (!(pcx_file = fopen(symbol->outfile, "wb"))) {
            strcpy(symbol->errtxt, "Can't open output file (F20)");
            return ZINT_ERROR_FILE_ACCESS;
        }
    }

    fwrite(&header, sizeof (pcx_header_t), 1, pcx_file);

    for (row = 0; row < symbol->bitmap_height; row++) {
        for (colour = 0; colour < 3; colour++) {
            for (column = 0; column < symbol->bitmap_width; column++) {
                switch (colour) {
                    case 0:
                        if (pixelbuf[(row * symbol->bitmap_width) + column] == '1') {
                            rle_row[column] = fgred;
                        } else {
                            rle_row[column] = bgred;
                        }
                        break;
                    case 1:
                        if (pixelbuf[(row * symbol->bitmap_width) + column] == '1') {
                            rle_row[column] = fggrn;
                        } else {
                            rle_row[column] = bggrn;
                        }
                        break;
                    case 2:
                        if (pixelbuf[(row * symbol->bitmap_width) + column] == '1') {
                            rle_row[column] = fgblu;
                        } else {
                            rle_row[column] = bgblu;
                        }
                        break;
                }
            }

            run_count = 1;
            for (column = 1; column < symbol->bitmap_width; column++) {
                if ((rle_row[column - 1] == rle_row[column]) && (run_count < 63)) {
                    run_count++;
                } else {
                    run_count += 0xc0;
                    fputc(run_count, pcx_file);
                    fputc(rle_row[column - 1], pcx_file);
                    run_count = 1;
                }
            }

            if (run_count > 1) {
                run_count += 0xc0;
                fputc(run_count, pcx_file);
                fputc(rle_row[column - 1], pcx_file);
            }
        }
    }

    fclose(pcx_file);

    return 0;
}

Added jni/zint/backend/pcx.h.

























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/*  pcx.h - header structure for ZSoft PCX files

    libzint - the open source barcode library
    Copyright (C) 2016 Robin Stuart <rstuart114@gmail.com>

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions
    are met:

    1. Redistributions of source code must retain the above copyright 
       notice, this list of conditions and the following disclaimer.  
    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.  
    3. Neither the name of the project nor the names of its contributors
       may be used to endorse or promote products derived from this software
       without specific prior written permission. 

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
    OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
    LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
    OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
    SUCH DAMAGE.
 */

#ifndef PCX_H
#define PCX_H

#ifdef __cplusplus
extern "C" {
#endif

#ifdef _MSC_VER
#include <windows.h>
#include "stdint_msvc.h"
#else
#include <stdint.h>
#endif

#pragma pack (1)
    
    typedef struct pcx_header {
        uint8_t manufacturer;
        uint8_t version;
        uint8_t encoding;
        uint8_t bits_per_pixel;
        uint16_t window_xmin;
        uint16_t window_ymin;
        uint16_t window_xmax;
        uint16_t window_ymax;
        uint16_t horiz_dpi;
        uint16_t vert_dpi;
        uint8_t colourmap[48];
        uint8_t reserved;
        uint8_t number_of_planes;
        uint16_t bytes_per_line;
        uint16_t palette_info;
        uint16_t horiz_screen_size;
        uint16_t vert_screen_size;
        uint8_t filler[54];
    } pcx_header_t;

#pragma pack ()
    
#ifdef __cplusplus
}
#endif

#endif /* PCX_H */

Changes to jni/zint/backend/pdf417.c.

605
606
607
608
609
610
611

612
613
614
615








616
617
618
619
620
621
622
...
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
...
919
920
921
922
923
924
925

926
927
928
929








930
931
932
933
934
935
936
...
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
...
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
            }
        }
    }

    /* 541 - now compress the data */
    indexchaine = 0;
    mclength = 0;

    if (symbol->output_options & READER_INIT) {
        chainemc[mclength] = 921; /* Reader Initialisation */
        mclength++;
    }








    for (i = 0; i < indexliste; i++) {
        switch (liste[1][i]) {
            case TEX: /* 547 - text mode */
                textprocess(chainemc, &mclength, (char*) chaine, indexchaine, liste[0][i], i);
                break;
            case BYT: /* 670 - octet stream mode */
                byteprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i], i);
................................................................................
/* 345 */
int pdf417enc(struct zint_symbol *symbol, unsigned char source[], int length) {
    int codeerr, error_number;

    error_number = 0;

    if ((symbol->option_1 < -1) || (symbol->option_1 > 8)) {
        strcpy(symbol->errtxt, "Security value out of range");
        symbol->option_1 = -1;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    if ((symbol->option_2 < 0) || (symbol->option_2 > 30)) {
        strcpy(symbol->errtxt, "Number of columns out of range");
        symbol->option_2 = 0;
        error_number = ZINT_WARN_INVALID_OPTION;
    }

    /* 349 */
    codeerr = pdf417(symbol, source, length);

    /* 352 */
    if (codeerr != 0) {
        switch (codeerr) {
            case 1:
                strcpy(symbol->errtxt, "No such file or file unreadable");
                error_number = ZINT_ERROR_INVALID_OPTION;
                break;
            case 2:
                strcpy(symbol->errtxt, "Input string too long");
                error_number = ZINT_ERROR_TOO_LONG;
                break;
            case 3:
                strcpy(symbol->errtxt, "Number of codewords per row too small");
                error_number = ZINT_WARN_INVALID_OPTION;
                break;
            case 4:
                strcpy(symbol->errtxt, "Data too long for specified number of columns");
                error_number = ZINT_ERROR_TOO_LONG;
                break;
            default:
                strcpy(symbol->errtxt, "Something strange happened");
                error_number = ZINT_ERROR_ENCODING_PROBLEM;
                break;
        }
    }

    /* 364 */
    return error_number;
................................................................................
            }
        }
    }

    /* 541 - now compress the data */
    indexchaine = 0;
    mclength = 0;

    if (symbol->output_options & READER_INIT) {
        chainemc[mclength] = 921; /* Reader Initialisation */
        mclength++;
    }








    for (i = 0; i < indexliste; i++) {
        switch (liste[1][i]) {
            case TEX: /* 547 - text mode */
                textprocess(chainemc, &mclength, (char*) chaine, indexchaine, liste[0][i], i);
                break;
            case BYT: /* 670 - octet stream mode */
                byteprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i], i);
................................................................................
        }
        indexchaine = indexchaine + liste[0][i];
    }

    /* This is where it all changes! */

    if (mclength > 126) {
        strcpy(symbol->errtxt, "Input data too long");
        return ZINT_ERROR_TOO_LONG;
    }
    if (symbol->option_2 > 4) {
        strcpy(symbol->errtxt, "Specified width out of range");
        symbol->option_2 = 0;
        codeerr = ZINT_WARN_INVALID_OPTION;
    }

    if (debug) {
        printf("\nEncoded Data Stream:\n");
        for (i = 0; i < mclength; i++) {
................................................................................
    /* Now figure out which variant of the symbol to use and load values accordingly */

    variant = 0;

    if ((symbol->option_2 == 1) && (mclength > 20)) {
        /* the user specified 1 column but the data doesn't fit - go to automatic */
        symbol->option_2 = 0;
        strcpy(symbol->errtxt, "Specified symbol size too small for data");
        codeerr = ZINT_WARN_INVALID_OPTION;
    }

    if ((symbol->option_2 == 2) && (mclength > 37)) {
        /* the user specified 2 columns but the data doesn't fit - go to automatic */
        symbol->option_2 = 0;
        strcpy(symbol->errtxt, "Specified symbol size too small for data");
        codeerr = ZINT_WARN_INVALID_OPTION;
    }

    if ((symbol->option_2 == 3) && (mclength > 82)) {
        /* the user specified 3 columns but the data doesn't fit - go to automatic */
        symbol->option_2 = 0;
        strcpy(symbol->errtxt, "Specified symbol size too small for data");
        codeerr = ZINT_WARN_INVALID_OPTION;
    }

    if (symbol->option_2 == 1) {
        /* the user specified 1 column and the data does fit */
        variant = 6;
        if (mclength <= 16) {







>




>
>
>
>
>
>
>
>







 







|




|











|



|



|



|



|







 







>




>
>
>
>
>
>
>
>







 







|



|







 







|






|






|







605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
...
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
...
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
...
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
...
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
            }
        }
    }

    /* 541 - now compress the data */
    indexchaine = 0;
    mclength = 0;
    
    if (symbol->output_options & READER_INIT) {
        chainemc[mclength] = 921; /* Reader Initialisation */
        mclength++;
    }
    
    if (symbol->eci != 3) {
        chainemc[mclength] = 927; /* ECI */
        mclength++;
        chainemc[mclength] = symbol->eci;
        mclength++;
    }
    
    for (i = 0; i < indexliste; i++) {
        switch (liste[1][i]) {
            case TEX: /* 547 - text mode */
                textprocess(chainemc, &mclength, (char*) chaine, indexchaine, liste[0][i], i);
                break;
            case BYT: /* 670 - octet stream mode */
                byteprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i], i);
................................................................................
/* 345 */
int pdf417enc(struct zint_symbol *symbol, unsigned char source[], int length) {
    int codeerr, error_number;

    error_number = 0;

    if ((symbol->option_1 < -1) || (symbol->option_1 > 8)) {
        strcpy(symbol->errtxt, "Security value out of range (D60)");
        symbol->option_1 = -1;
        error_number = ZINT_WARN_INVALID_OPTION;
    }
    if ((symbol->option_2 < 0) || (symbol->option_2 > 30)) {
        strcpy(symbol->errtxt, "Number of columns out of range (D61)");
        symbol->option_2 = 0;
        error_number = ZINT_WARN_INVALID_OPTION;
    }

    /* 349 */
    codeerr = pdf417(symbol, source, length);

    /* 352 */
    if (codeerr != 0) {
        switch (codeerr) {
            case 1:
                strcpy(symbol->errtxt, "No such file or file unreadable (D62)");
                error_number = ZINT_ERROR_INVALID_OPTION;
                break;
            case 2:
                strcpy(symbol->errtxt, "Input string too long (D63)");
                error_number = ZINT_ERROR_TOO_LONG;
                break;
            case 3:
                strcpy(symbol->errtxt, "Number of codewords per row too small (D64)");
                error_number = ZINT_WARN_INVALID_OPTION;
                break;
            case 4:
                strcpy(symbol->errtxt, "Data too long for specified number of columns (D65)");
                error_number = ZINT_ERROR_TOO_LONG;
                break;
            default:
                strcpy(symbol->errtxt, "Something strange happened (D66)");
                error_number = ZINT_ERROR_ENCODING_PROBLEM;
                break;
        }
    }

    /* 364 */
    return error_number;
................................................................................
            }
        }
    }

    /* 541 - now compress the data */
    indexchaine = 0;
    mclength = 0;
    
    if (symbol->output_options & READER_INIT) {
        chainemc[mclength] = 921; /* Reader Initialisation */
        mclength++;
    }
    
    if (symbol->eci != 3) {
        chainemc[mclength] = 927; /* ECI */
        mclength++;
        chainemc[mclength] = symbol->eci;
        mclength++;
    }
    
    for (i = 0; i < indexliste; i++) {
        switch (liste[1][i]) {
            case TEX: /* 547 - text mode */
                textprocess(chainemc, &mclength, (char*) chaine, indexchaine, liste[0][i], i);
                break;
            case BYT: /* 670 - octet stream mode */
                byteprocess(chainemc, &mclength, chaine, indexchaine, liste[0][i], i);
................................................................................
        }
        indexchaine = indexchaine + liste[0][i];
    }

    /* This is where it all changes! */

    if (mclength > 126) {
        strcpy(symbol->errtxt, "Input data too long (D67)");
        return ZINT_ERROR_TOO_LONG;
    }
    if (symbol->option_2 > 4) {
        strcpy(symbol->errtxt, "Specified width out of range (D68)");
        symbol->option_2 = 0;
        codeerr = ZINT_WARN_INVALID_OPTION;
    }

    if (debug) {
        printf("\nEncoded Data Stream:\n");
        for (i = 0; i < mclength; i++) {
................................................................................
    /* Now figure out which variant of the symbol to use and load values accordingly */

    variant = 0;

    if ((symbol->option_2 == 1) && (mclength > 20)) {
        /* the user specified 1 column but the data doesn't fit - go to automatic */
        symbol->option_2 = 0;
        strcpy(symbol->errtxt, "Specified symbol size too small for data (D69)");
        codeerr = ZINT_WARN_INVALID_OPTION;
    }

    if ((symbol->option_2 == 2) && (mclength > 37)) {
        /* the user specified 2 columns but the data doesn't fit - go to automatic */
        symbol->option_2 = 0;
        strcpy(symbol->errtxt, "Specified symbol size too small for data (D6A)");
        codeerr = ZINT_WARN_INVALID_OPTION;
    }

    if ((symbol->option_2 == 3) && (mclength > 82)) {
        /* the user specified 3 columns but the data doesn't fit - go to automatic */
        symbol->option_2 = 0;
        strcpy(symbol->errtxt, "Specified symbol size too small for data (D6B)");
        codeerr = ZINT_WARN_INVALID_OPTION;
    }

    if (symbol->option_2 == 1) {
        /* the user specified 1 column and the data does fit */
        variant = 6;
        if (mclength <= 16) {

Changes to jni/zint/backend/plessey.c.

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
...
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
...
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
...
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
...
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

    unsigned int i, check;
    unsigned char *checkptr;
    static const char grid[9] = {1, 1, 1, 1, 0, 1, 0, 0, 1};
    char dest[1024]; /* 8 + 65 * 8 + 8 * 2 + 9 + 1 ~ 1024 */
    int error_number;

    error_number = 0;

    if (length > 65) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(SSET, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data");
        return error_number;
    }
    checkptr = (unsigned char *) calloc(1, length * 4 + 8);

    /* Start character */
    strcpy(dest, "31311331");

................................................................................
/* Plain MSI Plessey - does not calculate any check character */
int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int length) {

    unsigned int i;
    char dest[512]; /* 2 + 55 * 8 + 3 + 1 ~ 512 */

    if (length > 55) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    /* start character */
    strcpy(dest, "21");

    for (i = 0; i < length; i++) {
................................................................................
    char un[200], tri[32];
    int error_number, h;
    char dest[1000];

    error_number = 0;

    if (length > 18) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    /* start character */
    strcpy(dest, "21");

    /* draw data section */
................................................................................
    int error_number, h;
    char dest[1000];

    error_number = 0;

    if (src_len > 18) {
        /* No Entry Stack Smashers! limit because of str->number conversion*/
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    /* start character */
    strcpy(dest, "21");

    /* draw data section */
................................................................................
    int i, weight, x, check;
    int error_number;
    char dest[1000];

    error_number = 0;

    if (src_len > 55) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    /* start character */
    strcpy(dest, "21");

    /* draw data section */
................................................................................
    char dest[1000];
    unsigned char temp[32];
    unsigned int temp_len;

    error_number = 0;

    if (src_len > 18) {
        strcpy(symbol->errtxt, "Input too long");
        return ZINT_ERROR_TOO_LONG;
    }

    /* start character */
    strcpy(dest, "21");

    /* draw data section */
................................................................................
}

int msi_handle(struct zint_symbol *symbol, unsigned char source[], int length) {
    int error_number;

    error_number = is_sane(NEON, source, length);
    if (error_number != 0) {
        strcpy(symbol->errtxt, "Invalid characters in input data");
        return ZINT_ERROR_INVALID_DATA;
    }


    if ((symbol->option_2 < 0) || (symbol->option_2 > 4)) {
        symbol->option_2 = 0;
    }







<
<

|




|







 







|







 







|







 







|







 







|







 







|







 







|







53
54
55
56
57
58
59


60
61
62
63
64
65
66
67
68
69
70
71
72
73
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
...
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
...
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
...
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

    unsigned int i, check;
    unsigned char *checkptr;
    static const char grid[9] = {1, 1, 1, 1, 0, 1, 0, 0, 1};
    char dest[1024]; /* 8 + 65 * 8 + 8 * 2 + 9 + 1 ~ 1024 */
    int error_number;



    if (length > 65) {
        strcpy(symbol->errtxt, "Input too long (C70)");
        return ZINT_ERROR_TOO_LONG;
    }
    error_number = is_sane(SSET, source, length);
    if (error_number == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Invalid characters in data (C71)");
        return error_number;
    }
    checkptr = (unsigned char *) calloc(1, length * 4 + 8);

    /* Start character */
    strcpy(dest, "31311331");

................................................................................
/* Plain MSI Plessey - does not calculate any check character */
int msi_plessey(struct zint_symbol *symbol, unsigned char source[], int length) {

    unsigned int i;
    char dest[512]; /* 2 + 55 * 8 + 3 + 1 ~ 512 */

    if (length > 55) {
        strcpy(symbol->errtxt, "Input too long (C72)");
        return ZINT_ERROR_TOO_LONG;
    }

    /* start character */
    strcpy(dest, "21");

    for (i = 0; i < length; i++) {
................................................................................
    char un[200], tri[32];
    int error_number, h;
    char dest[1000];

    error_number = 0;

    if (length > 18) {
        strcpy(symbol->errtxt, "Input too long (C73)");
        return ZINT_ERROR_TOO_LONG;
    }

    /* start character */
    strcpy(dest, "21");

    /* draw data section */
................................................................................
    int error_number, h;
    char dest[1000];

    error_number = 0;

    if (src_len > 18) {
        /* No Entry Stack Smashers! limit because of str->number conversion*/
        strcpy(symbol->errtxt, "Input too long (C74)");
        return ZINT_ERROR_TOO_LONG;
    }

    /* start character */
    strcpy(dest, "21");

    /* draw data section */
................................................................................
    int i, weight, x, check;
    int error_number;
    char dest[1000];

    error_number = 0;

    if (src_len > 55) {
        strcpy(symbol->errtxt, "Input too long (C75)");
        return ZINT_ERROR_TOO_LONG;
    }

    /* start character */
    strcpy(dest, "21");

    /* draw data section */
................................................................................
    char dest[1000];
    unsigned char temp[32];
    unsigned int temp_len;

    error_number = 0;

    if (src_len > 18) {
        strcpy(symbol->errtxt, "Input too long (C76)");
        return ZINT_ERROR_TOO_LONG;
    }

    /* start character */
    strcpy(dest, "21");

    /* draw data section */
................................................................................
}

int msi_handle(struct zint_symbol *symbol, unsigned char source[], int length) {
    int error_number;

    error_number = is_sane(NEON, source, length);
    if (error_number != 0) {
        strcpy(symbol->errtxt, "Invalid characters in input data (C77)");
        return ZINT_ERROR_INVALID_DATA;
    }


    if ((symbol->option_2 < 0) || (symbol->option_2 > 4)) {
        symbol->option_2 = 0;
    }

Changes to jni/zint/backend/png.c.

30
31
32
33
34
35
36

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
...
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
...
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
    SUCH DAMAGE.
 */

#include <stdio.h>
#ifdef _MSC_VER
#include <fcntl.h>
#include <io.h>

#endif
#include <stdlib.h>
#include <string.h>
#include "common.h"

#ifdef _MSC_VER
#include <malloc.h> 
#endif /* _MSC_VER */

#ifndef NO_PNG
#include <png.h>
#include <zlib.h>
#include <setjmp.h>
#endif /* NO_PNG */
#include "maxipng.h"	/* Maxicode shapes */

#include "font.h"	/* Font for human readable text */

#define SSET	"0123456789ABCDEF"

#define	PNG_DATA	100
#define	BMP_DATA	200

#ifndef NO_PNG

struct mainprog_info_type {
    long width;
    long height;
    FILE *outfile;
    jmp_buf jmpbuf;
};

static void writepng_error_handler(png_structp png_ptr, png_const_charp msg) {
    struct mainprog_info_type *graphic;

    fprintf(stderr, "writepng libpng error: %s\n", msg);
    fflush(stderr);

    graphic = (struct mainprog_info_type*) png_get_error_ptr(png_ptr);
    if (graphic == NULL) {
        /* we are completely hosed now */
        fprintf(stderr,
                "writepng severe error:  jmpbuf not recoverable; terminating.\n");
        fflush(stderr);
        return;
    }
    longjmp(graphic->jmpbuf, 1);
}

int png_pixel_plot(struct zint_symbol *symbol, int image_height, int image_width, char *pixelbuf, int rotate_angle) {
    struct mainprog_info_type wpng_info;
    struct mainprog_info_type *graphic;
    png_structp png_ptr;
    png_infop info_ptr;
    unsigned char *image_data;
    int i, row, column, errno;
    int fgred, fggrn, fgblu, bgred, bggrn, bgblu;

#ifndef _MSC_VER
    unsigned char outdata[image_width * 3];
#else
    unsigned char* outdata = (unsigned char*) _alloca(image_width * 3);
#endif

    graphic = &wpng_info;

    switch (rotate_angle) {
        case 0:
        case 180:
            graphic->width = image_width;
            graphic->height = image_height;
            break;
        case 90:
        case 270:
            graphic->width = image_height;
            graphic->height = image_width;
            break;
    }

    /* sort out colour options */
    to_upper((unsigned char*) symbol->fgcolour);
    to_upper((unsigned char*) symbol->bgcolour);

    if (strlen(symbol->fgcolour) != 6) {
        strcpy(symbol->errtxt, "Malformed foreground colour target");
        return ZINT_ERROR_INVALID_OPTION;
    }
    if (strlen(symbol->bgcolour) != 6) {
        strcpy(symbol->errtxt, "Malformed background colour target");
        return ZINT_ERROR_INVALID_OPTION;
    }
    errno = is_sane(SSET, (unsigned char*) symbol->fgcolour, strlen(symbol->fgcolour));
    if (errno == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Malformed foreground colour target");
        return ZINT_ERROR_INVALID_OPTION;
    }
    errno = is_sane(SSET, (unsigned char*) symbol->bgcolour, strlen(symbol->bgcolour));
    if (errno == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Malformed background colour target");
        return ZINT_ERROR_INVALID_OPTION;
    }

    fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
    fggrn = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]);
    fgblu = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]);
    bgred = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]);
    bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]);
    bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]);

    /* Open output file in binary mode */
    if ((symbol->output_options & BARCODE_STDOUT) != 0) {
#ifdef _MSC_VER
        if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
            strcpy(symbol->errtxt, "Can't open output file");
            return ZINT_ERROR_FILE_ACCESS;
        }
#endif
        graphic->outfile = stdout;
    } else {
        if (!(graphic->outfile = fopen(symbol->outfile, "wb"))) {
            strcpy(symbol->errtxt, "Can't open output file");
            return ZINT_ERROR_FILE_ACCESS;
        }
    }

    /* Set up error handling routine as proc() above */
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, graphic, writepng_error_handler, NULL);
    if (!png_ptr) {
        strcpy(symbol->errtxt, "Out of memory");
        return ZINT_ERROR_MEMORY;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        png_destroy_write_struct(&png_ptr, NULL);
        strcpy(symbol->errtxt, "Out of memory");
        return ZINT_ERROR_MEMORY;
    }

    /* catch jumping here */
    if (setjmp(graphic->jmpbuf)) {
        png_destroy_write_struct(&png_ptr, &info_ptr);
        strcpy(symbol->errtxt, "libpng error occurred");
        return ZINT_ERROR_MEMORY;
    }

    /* open output file with libpng */
    png_init_io(png_ptr, graphic->outfile);

    /* set compression */
................................................................................
    png_write_info(png_ptr, info_ptr);

    /* set up the transformations:  for now, just pack low-bit-depth pixels
    into bytes (one, two or four pixels per byte) */
    png_set_packing(png_ptr);

    /* Pixel Plotting */

    switch (rotate_angle) {
        case 0: /* Plot the right way up */
            for (row = 0; row < image_height; row++) {
                for (column = 0; column < image_width; column++) {
                    i = column * 3;
                    switch (*(pixelbuf + (image_width * row) + column)) {
                        case '1':
                            outdata[i] = fgred;
                            outdata[i + 1] = fggrn;
                            outdata[i + 2] = fgblu;
                            break;
                        default:
                            outdata[i] = bgred;
                            outdata[i + 1] = bggrn;
                            outdata[i + 2] = bgblu;
                            break;

                    }
                }
                /* write row contents to file */
                image_data = outdata;
                png_write_row(png_ptr, image_data);
            }
            break;
        case 90: /* Plot 90 degrees clockwise */
            for (row = 0; row < image_width; row++) {
                for (column = 0; column < image_height; column++) {
                    i = column * 3;
                    switch (*(pixelbuf + (image_width * (image_height - column - 1)) + row)) {
                        case '1':
                            outdata[i] = fgred;
                            outdata[i + 1] = fggrn;
                            outdata[i + 2] = fgblu;
                            break;
                        default:
                            outdata[i] = bgred;
                            outdata[i + 1] = bggrn;
                            outdata[i + 2] = bgblu;
                            break;

                    }
                }

                /* write row contents to file */
                image_data = outdata;
                png_write_row(png_ptr, image_data);
            }
            break;
        case 180: /* Plot upside down */
            for (row = 0; row < image_height; row++) {
                for (column = 0; column < image_width; column++) {
                    i = column * 3;
                    switch (*(pixelbuf + (image_width * (image_height - row - 1)) + (image_width - column - 1))) {
                        case '1':
                            outdata[i] = fgred;
                            outdata[i + 1] = fggrn;
                            outdata[i + 2] = fgblu;
                            break;
                        default:
                            outdata[i] = bgred;
                            outdata[i + 1] = bggrn;
                            outdata[i + 2] = bgblu;
                            break;

                    }
                }

                /* write row contents to file */
                image_data = outdata;
                png_write_row(png_ptr, image_data);
            }
            break;
        case 270: /* Plot 90 degrees anti-clockwise */
            for (row = 0; row < image_width; row++) {
                for (column = 0; column < image_height; column++) {
                    i = column * 3;
                    switch (*(pixelbuf + (image_width * column) + (image_width - row - 1))) {
                        case '1':
                            outdata[i] = fgred;
                            outdata[i + 1] = fggrn;
                            outdata[i + 2] = fgblu;
                            break;
                        default:
                            outdata[i] = bgred;
                            outdata[i + 1] = bggrn;
                            outdata[i + 2] = bgblu;
                            break;

                    }
                }

                /* write row contents to file */
                image_data = outdata;
                png_write_row(png_ptr, image_data);
            }
            break;
    }

    /* End the file */
    png_write_end(png_ptr, NULL);

    /* make sure we have disengaged */
    if (png_ptr && info_ptr) png_destroy_write_struct(&png_ptr, &info_ptr);
................................................................................
        fflush(wpng_info.outfile);
    } else {
        fclose(wpng_info.outfile);
    }
    return 0;
}
#endif /* NO_PNG */

int bmp_pixel_plot(struct zint_symbol *symbol, int image_height, int image_width, char *pixelbuf, int rotate_angle) {
    int i, row, column, errno;
    int fgred, fggrn, fgblu, bgred, bggrn, bgblu;

    switch (rotate_angle) {
        case 0:
        case 180:
            symbol->bitmap_width = image_width;
            symbol->bitmap_height = image_height;
            break;
        case 90:
        case 270:
            symbol->bitmap_width = image_height;
            symbol->bitmap_height = image_width;
            break;
    }

    if (symbol->bitmap != NULL)
        free(symbol->bitmap);

    symbol->bitmap = (char *) malloc(image_width * image_height * 3);


    /* sort out colour options */
    to_upper((unsigned char*) symbol->fgcolour);
    to_upper((unsigned char*) symbol->bgcolour);

    if (strlen(symbol->fgcolour) != 6) {
        strcpy(symbol->errtxt, "Malformed foreground colour target");
        return ZINT_ERROR_INVALID_OPTION;
    }
    if (strlen(symbol->bgcolour) != 6) {
        strcpy(symbol->errtxt, "Malformed background colour target");
        return ZINT_ERROR_INVALID_OPTION;
    }
    errno = is_sane(SSET, (unsigned char*) symbol->fgcolour, strlen(symbol->fgcolour));
    if (errno == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Malformed foreground colour target");
        return ZINT_ERROR_INVALID_OPTION;
    }
    errno = is_sane(SSET, (unsigned char*) symbol->bgcolour, strlen(symbol->fgcolour));
    if (errno == ZINT_ERROR_INVALID_DATA) {
        strcpy(symbol->errtxt, "Malformed background colour target");
        return ZINT_ERROR_INVALID_OPTION;
    }

    fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
    fggrn = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]);
    fgblu = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]);
    bgred = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]);
    bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]);
    bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]);

    /* Pixel Plotting */
    i = 0;
    switch (rotate_angle) {
        case 0: /* Plot the right way up */
            for (row = 0; row < image_height; row++) {
                for (column = 0; column < image_width; column++) {
                    switch (*(pixelbuf + (image_width * row) + column)) {
                        case '1':
                            symbol->bitmap[i++] = fgred;
                            symbol->bitmap[i++] = fggrn;
                            symbol->bitmap[i++] = fgblu;
                            break;
                        default:
                            symbol->bitmap[i++] = bgred;
                            symbol->bitmap[i++] = bggrn;
                            symbol->bitmap[i++] = bgblu;
                            break;

                    }
                }
            }
            break;
        case 90: /* Plot 90 degrees clockwise */
            for (row = 0; row < image_width; row++) {
                for (column = 0; column < image_height; column++) {
                    switch (*(pixelbuf + (image_width * (image_height - column - 1)) + row)) {
                        case '1':
                            symbol->bitmap[i++] = fgred;
                            symbol->bitmap[i++] = fggrn;
                            symbol->bitmap[i++] = fgblu;
                            break;
                        default:
                            symbol->bitmap[i++] = bgred;
                            symbol->bitmap[i++] = bggrn;
                            symbol->bitmap[i++] = bgblu;
                            break;

                    }
                }
            }
            break;
        case 180: /* Plot upside down */
            for (row = 0; row < image_height; row++) {
                for (column = 0; column < image_width; column++) {
                    switch (*(pixelbuf + (image_width * (image_height - row - 1)) + (image_width - column - 1))) {
                        case '1':
                            symbol->bitmap[i++] = fgred;
                            symbol->bitmap[i++] = fggrn;
                            symbol->bitmap[i++] = fgblu;
                            break;
                        default:
                            symbol->bitmap[i++] = bgred;
                            symbol->bitmap[i++] = bggrn;
                            symbol->bitmap[i++] = bgblu;
                            break;

                    }
                }
            }
            break;
        case 270: /* Plot 90 degrees anti-clockwise */
            for (row = 0; row < image_width; row++) {
                for (column = 0; column < image_height; column++) {
                    switch (*(pixelbuf + (image_width * column) + (image_width - row - 1))) {
                        case '1':
                            symbol->bitmap[i++] = fgred;
                            symbol->bitmap[i++] = fggrn;
                            symbol->bitmap[i++] = fgblu;
                            break;
                        default:
                            symbol->bitmap[i++] = bgred;
                            symbol->bitmap[i++] = bggrn;
                            symbol->bitmap[i++] = bgblu;
                            break;

                    }
                }
            }
            break;
    }

    return 0;
}

int png_to_file(struct zint_symbol *symbol, int image_height, int image_width, char *pixelbuf, int rotate_angle, int image_type) {
    int error_number;
    float scaler = symbol->scale;
    char *scaled_pixelbuf;
    int horiz, vert, i;
    int scale_width, scale_height;

    if (scaler == 0) {
        scaler = 0.5;
    }
    scale_width = image_width * scaler;
    scale_height = image_height * scaler;

    /* Apply scale options by creating another pixel buffer */
    if (!(scaled_pixelbuf = (char *) malloc(scale_width * scale_height))) {
        printf("Insufficient memory for pixel buffer");
        return ZINT_ERROR_ENCODING_PROBLEM;
    } else {
        for (i = 0; i < (scale_width * scale_height); i++) {
            *(scaled_pixelbuf + i) = '0';
        }
    }

    for (vert = 0; vert < scale_height; vert++) {
        for (horiz = 0; horiz < scale_width; horiz++) {
            *(scaled_pixelbuf + (vert * scale_width) + horiz) = *(pixelbuf + ((int) (vert / scaler) * image_width) + (int) (horiz / scaler));
        }
    }

    if (image_type == PNG_DATA) {
#ifndef NO_PNG
        error_number = png_pixel_plot(symbol, scale_height, scale_width, scaled_pixelbuf, rotate_angle);
#else
        return ZINT_ERROR_INVALID_OPTION;
#endif
    } else {
        error_number = bmp_pixel_plot(symbol, scale_height, scale_width, scaled_pixelbuf, rotate_angle);
    }

    free(scaled_pixelbuf);

    return error_number;
}

void draw_bar(char *pixelbuf, int xpos, int xlen, int ypos, int ylen, int image_width, int image_height) {
    /* Draw a rectangle */
    int i, j, png_ypos;

    png_ypos = image_height - ypos - ylen;
    /* This fudge is needed because EPS measures height from the bottom up but
    PNG measures y position from the top down */

    for (i = (xpos); i < (xpos + xlen); i++) {
        for (j = (png_ypos); j < (png_ypos + ylen); j++) {
            *(pixelbuf + (image_width * j) + i) = '1';
        }
    }
}

int bullseye_pixel(int row, int col) {
    int block_val, block_pos, return_val;

    block_val = bullseye_compressed[(row * 12) + (col / 8)];
    return_val = 0;
    block_pos = col % 8;

    if (block_val & (0x80 >> block_pos)) {
        return_val = 1;
    }

    return return_val;
}

void draw_bullseye(char *pixelbuf, int image_width, int xoffset, int yoffset) {
    /* Central bullseye in Maxicode symbols */
    int i, j;

    for (j = 103; j < 196; j++) {
        for (i = 0; i < 93; i++) {
            if (bullseye_pixel(j - 103, i)) {
                /* if(bullseye[(((j - 103) * 93) + i)] == 1) { */
                *(pixelbuf + (image_width * j) + (image_width * yoffset) + i + 99 + xoffset) = '1';
            }
        }
    }
}

void draw_hexagon(char *pixelbuf, int image_width, int xposn, int yposn) {
    /* Put a hexagon into the pixel buffer */
    int i, j;

    for (i = 0; i < 12; i++) {
        for (j = 0; j < 10; j++) {
            if (hexagon[(i * 10) + j] == 1) {
                *(pixelbuf + (image_width * i) + (image_width * yposn) + xposn + j) = '1';
            }
        }
    }
}

void draw_letter(char *pixelbuf, unsigned char letter, int xposn, int yposn, int smalltext, int image_width, int image_height) {
    /* Put a letter into a position */
    int skip, x, y, glyph_no;

    skip = 0;

    if (letter < 33) {
        skip = 1;
    }
    if ((letter > 127) && (letter < 161)) {
        skip = 1;
    }

    if (skip == 0) {
        if (letter > 128) {
            glyph_no = letter - 66;
        } else {
            glyph_no = letter - 33;
        }
        
        
        if (smalltext) {
            for (y = 0; y < 9; y++) {
                for (x = 0; x < 5; x++) {
                    if (small_font[(glyph_no * 8) + y] & (0x10 >> x)) {
                        *(pixelbuf + (y * image_width) + (yposn * image_width) + xposn + x) = '1';
                    }
                }
            }
        } else {
            for (y = 0; y < 14; y++) {
                for (x = 0; x < 7; x++) {
                    if (ascii_font[(glyph_no * 14) + y] & (0x40 >> x)) {
                        *(pixelbuf + (y * image_width) + (yposn * image_width) + xposn + x) = '1';
                    }
                }
            }
        }
    }
}

/* Plot a string into the pixel buffer */
void draw_string(char *pixbuf, char input_string[], int xposn, int yposn, int smalltext, int image_width, int image_height) {
    int i, string_length, string_left_hand;

    string_length = strlen(input_string);
    string_left_hand = xposn - ((7 * string_length) / 2);

    for (i = 0; i < string_length; i++) {
        draw_letter(pixbuf, input_string[i], string_left_hand + (i * 7), yposn, smalltext, image_width, image_height);
    }

}

int maxi_png_plot(struct zint_symbol *symbol, int rotate_angle, int data_type) {
    int i, row, column, xposn, yposn;
    int image_height, image_width;
    char *pixelbuf;
    int error_number;
    int xoffset, yoffset;

    xoffset = symbol->border_width + symbol->whitespace_width;
    yoffset = symbol->border_width;
    image_width = 300 + (2 * xoffset * 2);
    image_height = 300 + (2 * yoffset * 2);

    if (!(pixelbuf = (char *) malloc(image_width * image_height))) {
        printf("Insifficient memory for pixel buffer");
        return ZINT_ERROR_ENCODING_PROBLEM;
    } else {
        for (i = 0; i < (image_width * image_height); i++) {
            *(pixelbuf + i) = '0';
        }
    }

    draw_bullseye(pixelbuf, image_width, (2 * xoffset), (2 * yoffset));

    for (row = 0; row < symbol->rows; row++) {
        yposn = row * 9;
        for (column = 0; column < symbol->width; column++) {
            xposn = column * 10;
            if (module_is_set(symbol, row, column)) {
                if (row & 1) {
                    /* Odd (reduced) row */
                    xposn += 5;
                    draw_hexagon(pixelbuf, image_width, xposn + (2 * xoffset), yposn + (2 * yoffset));
                } else {
                    /* Even (full) row */
                    draw_hexagon(pixelbuf, image_width, xposn + (2 * xoffset), yposn + (2 * yoffset));
                }
            }
        }
    }

    if (((symbol->output_options & BARCODE_BOX) != 0) || ((symbol->output_options & BARCODE_BIND) != 0)) {
        /* boundary bars */
        draw_bar(pixelbuf, 0, image_width, 0, symbol->border_width * 2, image_width, image_height);
        draw_bar(pixelbuf, 0, image_width, 300 + (symbol->border_width * 2), symbol->border_width * 2, image_width, image_height);
    }

    if ((symbol->output_options & BARCODE_BOX) != 0) {
        /* side bars */
        draw_bar(pixelbuf, 0, symbol->border_width * 2, 0, image_height, image_width, image_height);
        draw_bar(pixelbuf, 300 + ((symbol->border_width + symbol->whitespace_width + symbol->whitespace_width) * 2), symbol->border_width * 2, 0, image_height, image_width, image_height);
    }

    error_number = png_to_file(symbol, image_height, image_width, pixelbuf, rotate_angle, data_type);
    free(pixelbuf);
    return error_number;
}

/* Convert UTF-8 to Latin1 Codepage for the interpretation line */
void to_latin1(unsigned char source[], unsigned char preprocessed[]) {
    int j, i, input_length;

    input_length = ustrlen(source);

    j = 0;
    i = 0;
    while (i < input_length) {
        switch (source[i]) {
            case 0xC2:
                /* UTF-8 C2xxh */
                /* Character range: C280h (latin: 80h) to C2BFh (latin: BFh) */
                i++;
                preprocessed[j] = source[i];
                j++;
                break;
            case 0xC3:
                /* UTF-8 C3xx */
                /* Character range: C380h (latin: C0h) to C3BFh (latin: FFh) */
                i++;
                preprocessed[j] = source[i] + 64;
                j++;
                break;
            default:
                /* Process ASCII (< 80h), all other unicode points are ignored */
                if (source[i] < 128) {
                    preprocessed[j] = source[i];
                    j++;
                }
                break;
        }
        i++;
    }
    preprocessed[j] = '\0';

    return;
}

int png_plot(struct zint_symbol *symbol, int rotate_angle, int data_type) {
    int textdone, main_width, comp_offset, large_bar_count;
    char textpart[10], addon[6];
    float addon_text_posn, preset_height, large_bar_height;
    int i, r, textoffset, yoffset, xoffset, latch, image_width, image_height;
    char *pixelbuf;
    int addon_latch = 0, smalltext = 0;
    int this_row, block_width, plot_height, plot_yposn, textpos;
    float row_height, row_posn;
    int error_number;
    int default_text_posn;
    int next_yposn;
#ifndef _MSC_VER
    unsigned char local_text[ustrlen(symbol->text) + 1];
#else
    unsigned char* local_text = (unsigned char*) _alloca(ustrlen(symbol->text) + 1);
#endif

    if (symbol->show_hrt != 0) {
        to_latin1(symbol->text, local_text);
    } else {
        local_text[0] = '\0';
    }

    textdone = 0;
    main_width = symbol->width;
    strcpy(addon, "");
    comp_offset = 0;
    addon_text_posn = 0.0;
    row_height = 0;
    if (symbol->output_options & SMALL_TEXT) {
        smalltext = 1;
    }

    if (symbol->height == 0) {
        symbol->height = 50;
    }

    large_bar_count = 0;
    preset_height = 0.0;
    for (i = 0; i < symbol->rows; i++) {
        preset_height += symbol->row_height[i];
        if (symbol->row_height[i] == 0) {
            large_bar_count++;
        }
    }

    if (large_bar_count == 0) {
        symbol->height = preset_height;
        large_bar_height = 10;
    } else {
        large_bar_height = (symbol->height - preset_height) / large_bar_count;
    }

    while (!(module_is_set(symbol, symbol->rows - 1, comp_offset))) {
        comp_offset++;
    }

    /* Certain symbols need whitespace otherwise characters get chopped off the sides */
    if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC))
            || (symbol->symbology == BARCODE_ISBNX)) {
        switch (ustrlen(local_text)) {
            case 13: /* EAN 13 */
            case 16:
            case 19:
                if (symbol->whitespace_width == 0) {
                    symbol->whitespace_width = 10;
                }
                main_width = 96 + comp_offset;
                break;
            default:
                main_width = 68 + comp_offset;
        }
    }

    if (((symbol->symbology == BARCODE_UPCA) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCA_CC)) {
        if (symbol->whitespace_width == 0) {
            symbol->whitespace_width = 10;
            main_width = 96 + comp_offset;
        }
    }

    if (((symbol->symbology == BARCODE_UPCE) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_UPCE_CC)) {
        if (symbol->whitespace_width == 0) {
            symbol->whitespace_width = 10;
            main_width = 51 + comp_offset;
        }
    }

    latch = 0;
    r = 0;
    /* Isolate add-on text */
    if (is_extendable(symbol->symbology)) {
        for (i = 0; i < ustrlen(local_text); i++) {
            if (latch == 1) {
                addon[r] = local_text[i];
                r++;
            }
            if (symbol->text[i] == '+') {
                latch = 1;
            }
        }
    }
    addon[r] = '\0';

    if (ustrlen(local_text) != 0) {
        textoffset = 9;
    } else {
        textoffset = 0;
    }
    xoffset = symbol->border_width + symbol->whitespace_width;
    yoffset = symbol->border_width;
    image_width = 2 * (symbol->width + xoffset + xoffset);
    image_height = 2 * (symbol->height + textoffset + yoffset + yoffset);

    if (!(pixelbuf = (char *) malloc(image_width * image_height))) {
        printf("Insufficient memory for pixel buffer");
        return ZINT_ERROR_ENCODING_PROBLEM;
    } else {
        for (i = 0; i < (image_width * image_height); i++) {
            *(pixelbuf + i) = '0';
        }
    }

    if (((symbol->output_options & BARCODE_BOX) != 0) || ((symbol->output_options & BARCODE_BIND) != 0)) {
        default_text_posn = image_height - 17;
    } else {
        default_text_posn = image_height - 17 - symbol->border_width - symbol->border_width;
    }

    row_posn = textoffset + yoffset;
    next_yposn = textoffset + yoffset;
    row_height = 0;

    /* Plot the body of the symbol to the pixel buffer */
    for (r = 0; r < symbol->rows; r++) {
        this_row = symbol->rows - r - 1; /* invert r otherwise plots upside down */
        row_posn += row_height;
        plot_yposn = next_yposn;
        if (symbol->row_height[this_row] == 0) {
            row_height = large_bar_height;
        } else {
            row_height = symbol->row_height[this_row];
        }
        next_yposn = (int) (row_posn + row_height);
        plot_height = next_yposn - plot_yposn;

        i = 0;
        if (module_is_set(symbol, this_row, 0)) {
            latch = 1;
        } else {
            latch = 0;
        }

        do {
            block_width = 0;
            do {
                block_width++;
            } while (module_is_set(symbol, this_row, i + block_width) == module_is_set(symbol, this_row, i));
            if ((addon_latch == 0) && (r == 0) && (i > main_width)) {
                plot_height = (int) (row_height - 5.0);
                plot_yposn = (int) (row_posn - 5.0);
                addon_text_posn = row_posn + row_height - 8.0;
                addon_latch = 1;
            }
            if (latch == 1) {
                /* a bar */
                draw_bar(pixelbuf, (i + xoffset) * 2, block_width * 2, plot_yposn * 2, plot_height * 2, image_width, image_height);
                latch = 0;
            } else {
                /* a space */
                latch = 1;
            }
            i += block_width;

        } while (i < symbol->width);
    }

    xoffset += comp_offset;

    if ((((symbol->symbology == BARCODE_EANX) && (symbol->rows == 1)) || (symbol->symbology == BARCODE_EANX_CC)) || (symbol->symbology == BARCODE_ISBNX)) {
        /* guard bar extensions and text formatting for EAN8 and EAN13 */
        switch (ustrlen(local_text)) {
            case 8: /* EAN-8 */
            case 11:
            case 14:
                draw_bar(pixelbuf, (0 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height);
                draw_bar(pixelbuf, (2 + xoffset) * 2, 1 * 2, (4 + (int) yoffset) * 2, 5 * 2, image_width, image_height);