pdf417 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,27 @@
1
+ // strfunctions from Nokogiri
2
+ #define PDF417_STR_NEW2(str) \
3
+ rb_str_new2((const char *)(str))
4
+
5
+ #define PDF417_STR_NEW(str, len) \
6
+ rb_str_new((const char *)(str), (long)(len))
7
+
8
+ #define RBSTR_OR_QNIL(_str) \
9
+ (_str ? PDF417_STR_NEW2(_str) : Qnil)
10
+
11
+ VALUE rb_cPdf417;
12
+ static VALUE rb_pdf417_encode_text(VALUE self, VALUE text);
13
+ static VALUE rb_pdf417_codewords(VALUE self);
14
+ static VALUE rb_pdf417_to_blob(VALUE self);
15
+ static VALUE rb_pdf417_new(VALUE class, VALUE text);
16
+ static void rb_pdf417_cleanup(void *p);
17
+ static VALUE rb_pdf417_init(VALUE self, VALUE text);
18
+ static VALUE rb_pdf417_bitColumns(VALUE self);
19
+ static VALUE rb_pdf417_lenBits(VALUE self);
20
+ static VALUE rb_pdf417_codeRows(VALUE self);
21
+ static VALUE rb_pdf417_codeColumns(VALUE self);
22
+ static VALUE rb_pdf417_lenCodewords(VALUE self);
23
+ static VALUE rb_pdf417_errorLevel(VALUE self);
24
+ static VALUE rb_pdf417_options(VALUE self);
25
+ static VALUE rb_pdf417_aspectRatio(VALUE self);
26
+ static VALUE rb_pdf417_yHeight(VALUE self);
27
+ static VALUE rb_pdf417_error(VALUE self);
@@ -0,0 +1,860 @@
1
+ /*
2
+ * Copyright 2003-2005 by Paulo Soares.
3
+ *
4
+ * The contents of this file are subject to the Mozilla Public License Version 1.1
5
+ * (the "License"); you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at http://www.mozilla.org/MPL/
7
+ *
8
+ * Software distributed under the License is distributed on an "AS IS" basis,
9
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
10
+ * for the specific language governing rights and limitations under the License.
11
+ *
12
+ * The Original Code is 'pdf417lib, a library to generate the bidimensional barcode PDF417'.
13
+ *
14
+ * The Initial Developer of the Original Code is Paulo Soares. Portions created by
15
+ * the Initial Developer are Copyright (C) 2003 by Paulo Soares.
16
+ * All Rights Reserved.
17
+ *
18
+ * Contributor(s): all the names of the contributors are added in the source code
19
+ * where applicable.
20
+ *
21
+ * Alternatively, the contents of this file may be used under the terms of the
22
+ * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
23
+ * provisions of LGPL are applicable instead of those above. If you wish to
24
+ * allow use of your version of this file only under the terms of the LGPL
25
+ * License and not to allow others to use your version of this file under
26
+ * the MPL, indicate your decision by deleting the provisions above and
27
+ * replace them with the notice and other provisions required by the LGPL.
28
+ * If you do not delete the provisions above, a recipient may use your version
29
+ * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
30
+ *
31
+ * This library is free software; you can redistribute it and/or modify it
32
+ * under the terms of the MPL as stated above or under the terms of the GNU
33
+ * Library General Public License as published by the Free Software Foundation;
34
+ * either version 2 of the License, or any later version.
35
+ *
36
+ * This library is distributed in the hope that it will be useful, but WITHOUT
37
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
38
+ * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
39
+ * details.
40
+ *
41
+ * If you didn't download this code from the following link, you should check if
42
+ * you aren't using an obsolete version:
43
+ * http://sourceforge.net/projects/pdf417lib
44
+ */
45
+
46
+
47
+ // #ifndef __APPLE__
48
+ // #include <malloc.h>
49
+ // #endif
50
+
51
+ #include <string.h>
52
+ #include <stdio.h>
53
+ #include <stdlib.h>
54
+ #include <math.h>
55
+ #include <ruby.h>
56
+
57
+
58
+ #ifdef __cplusplus
59
+ extern "C" {
60
+ #endif
61
+
62
+ #define __INCLUDE_PDF417LIBIMP_H__
63
+ #include "pdf417libimp.h"
64
+ #undef __INCLUDE_PDF417LIBIMP_H__
65
+ #include "pdf417lib.h"
66
+
67
+ #ifndef NULL
68
+ #ifdef __cplusplus
69
+ #define NULL 0
70
+ #else
71
+ #define NULL ((void *)0)
72
+ #endif
73
+ #endif
74
+
75
+
76
+
77
+ char* MIXED_SET = "0123456789&\r\t,:#-.$/+%*=^";
78
+ char* PUNCTUATION_SET = ";<>@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'";
79
+
80
+ typedef struct _listElement {
81
+ char type;
82
+ int start;
83
+ int end;
84
+ } listElement, *pListElement;
85
+
86
+ typedef struct _arrayList {
87
+ pListElement array;
88
+ int size;
89
+ int capacity;
90
+ } arrayList, *pArrayList;
91
+
92
+ typedef struct _pdf417class {
93
+ int bitPtr;
94
+ int cwPtr;
95
+ pdf417param *param;
96
+ } pdf417class, *pPdf417class;
97
+
98
+
99
+ static void listInit(pArrayList list) {
100
+ list->capacity = 20;
101
+ list->size = 0;
102
+ list->array = ALLOC_N(listElement, (list->capacity * sizeof(listElement))); //(pListElement)malloc(list->capacity * sizeof(listElement));
103
+ }
104
+
105
+ static void listFree(pArrayList list) {
106
+ free(list->array);
107
+ list->array = NULL;
108
+ }
109
+
110
+ static void listAdd(pArrayList list, char type, int start, int end) {
111
+ if (list->size == list->capacity) {
112
+ pListElement temp;
113
+ list->capacity *= 2;
114
+ temp = ALLOC_N(listElement, (list->capacity * sizeof(listElement))); //(pListElement)malloc(list->capacity * sizeof(listElement));
115
+ memcpy(temp, list->array, list->size * sizeof(listElement));
116
+ free(list->array);
117
+ list->array = temp;
118
+ }
119
+ list->array[list->size].type = type;
120
+ list->array[list->size].start = start;
121
+ list->array[list->size].end = end;
122
+ ++list->size;
123
+ }
124
+
125
+ static pListElement listGet(pArrayList list, int idx) {
126
+ if (idx >= list->size || idx < 0)
127
+ return NULL;
128
+ return list->array + idx;
129
+ }
130
+
131
+ static void listRemove(pArrayList list, int idx) {
132
+ if (idx >= list->size || idx < 0)
133
+ return;
134
+ --list->size;
135
+ memmove(list->array + idx, list->array + (idx + 1), (list->size - idx) * sizeof(listElement));
136
+ }
137
+
138
+ static int checkElementType(pListElement p, char type) {
139
+ if (!p)
140
+ return 0;
141
+ return (p->type == type);
142
+ }
143
+
144
+ static int getElementLength(pListElement p) {
145
+ if (!p)
146
+ return 0;
147
+ return p->end - p->start;
148
+ }
149
+
150
+ void pdf417init(pPdf417param param) {
151
+ param->options = 0;
152
+ param->outBits = NULL;
153
+ param->lenBits = 0;
154
+ param->error = 0;
155
+ param->lenText = -1;
156
+ param->text = "";
157
+ param->yHeight = 3;
158
+ param->aspectRatio = 0.5;
159
+ }
160
+
161
+ void pdf417free(pPdf417param param) {
162
+ if (param->outBits != NULL) {
163
+ free(param->outBits);
164
+ param->outBits = NULL;
165
+ }
166
+ }
167
+
168
+ static void outCodeword17(pPdf417class p, int codeword) {
169
+ int bytePtr = p->bitPtr / 8;
170
+ int bit = p->bitPtr - bytePtr * 8;
171
+ p->param->outBits[bytePtr++] |= codeword >> (9 + bit);
172
+ p->param->outBits[bytePtr++] |= codeword >> (1 + bit);
173
+ codeword <<= 8;
174
+ p->param->outBits[bytePtr] |= codeword >> (1 + bit);
175
+ p->bitPtr += 17;
176
+ }
177
+
178
+ static void outCodeword18(pPdf417class p, int codeword) {
179
+ int bytePtr = p->bitPtr / 8;
180
+ int bit = p->bitPtr - bytePtr * 8;
181
+ p->param->outBits[bytePtr++] |= codeword >> (10 + bit);
182
+ p->param->outBits[bytePtr++] |= codeword >> (2 + bit);
183
+ codeword <<= 8;
184
+ p->param->outBits[bytePtr] |= codeword >> (2 + bit);
185
+ if (bit == 7)
186
+ p->param->outBits[++bytePtr] |= 0x80;
187
+ p->bitPtr += 18;
188
+ }
189
+
190
+ static void outCodeword(pPdf417class p, int codeword) {
191
+ outCodeword17(p, codeword);
192
+ }
193
+
194
+ static void outStopPattern(pPdf417class p) {
195
+ outCodeword18(p, STOP_PATTERN);
196
+ }
197
+
198
+ static void outStartPattern(pPdf417class p) {
199
+ outCodeword17(p, START_PATTERN);
200
+ }
201
+
202
+ static void outPaintCode(pPdf417class p) {
203
+ int codePtr = 0;
204
+ int row;
205
+ int rowMod;
206
+ int *cluster;
207
+ int edge;
208
+ int column;
209
+ p->param->bitColumns = START_CODE_SIZE * (p->param->codeColumns + 3) + STOP_SIZE;
210
+ p->param->lenBits = ((p->param->bitColumns - 1) / 8 + 1) * p->param->codeRows;
211
+ p->param->outBits = ALLOC_N(char, p->param->lenBits); //(char*)malloc(p->param->lenBits);
212
+ memset(p->param->outBits, 0, p->param->lenBits);
213
+ for (row = 0; row < p->param->codeRows; ++row) {
214
+ p->bitPtr = ((p->param->bitColumns - 1) / 8 + 1) * 8 * row;
215
+ rowMod = row % 3;
216
+ cluster = CLUSTERS[rowMod];
217
+ outStartPattern(p);
218
+ edge = 0;
219
+ switch (rowMod) {
220
+ case 0:
221
+ edge = 30 * (row / 3) + ((p->param->codeRows - 1) / 3);
222
+ break;
223
+ case 1:
224
+ edge = 30 * (row / 3) + p->param->errorLevel * 3 + ((p->param->codeRows - 1) % 3);
225
+ break;
226
+ default:
227
+ edge = 30 * (row / 3) + p->param->codeColumns - 1;
228
+ break;
229
+ }
230
+ outCodeword(p, cluster[edge]);
231
+
232
+ for (column = 0; column < p->param->codeColumns; ++column) {
233
+ outCodeword(p, cluster[p->param->codewords[codePtr++]]);
234
+ }
235
+
236
+ switch (rowMod) {
237
+ case 0:
238
+ edge = 30 * (row / 3) + p->param->codeColumns - 1;
239
+ break;
240
+ case 1:
241
+ edge = 30 * (row / 3) + ((p->param->codeRows - 1) / 3);
242
+ break;
243
+ default:
244
+ edge = 30 * (row / 3) + p->param->errorLevel * 3 + ((p->param->codeRows - 1) % 3);
245
+ break;
246
+ }
247
+ outCodeword(p, cluster[edge]);
248
+ outStopPattern(p);
249
+ }
250
+ if (p->param->options & PDF417_INVERT_BITMAP) {
251
+ char* pm = p->param->outBits;
252
+ char* end = pm + p->param->lenBits;
253
+ while (pm < end)
254
+ *(pm++) ^= 0xff;
255
+ }
256
+ }
257
+
258
+ static void calculateErrorCorrection(pPdf417class p, int dest) {
259
+ int t1 = 0;
260
+ int t2 = 0;
261
+ int t3 = 0;
262
+ int *A;
263
+ int Alength;
264
+ int *E;
265
+ int lastE;
266
+ int k, e, j;
267
+ if (p->param->errorLevel < 0 || p->param->errorLevel > 8)
268
+ p->param->errorLevel = 0;
269
+ A = ERROR_LEVEL[p->param->errorLevel];
270
+ Alength = 2 << p->param->errorLevel;
271
+ E = p->param->codewords + dest;
272
+ memset(E, 0, Alength * sizeof(int));
273
+ lastE = Alength - 1;
274
+ for (k = 0; k < p->param->lenCodewords; ++k) {
275
+ t1 = p->param->codewords[k] + E[0];
276
+ for (e = 0; e <= lastE; ++e) {
277
+ t2 = (t1 * A[lastE - e]) % MOD;
278
+ t3 = MOD - t2;
279
+ E[e] = ((e == lastE ? 0 : E[e + 1]) + t3) % MOD;
280
+ }
281
+ }
282
+ for (j = 0; j < Alength; ++j)
283
+ E[j] = (MOD - E[j]) % MOD;
284
+ }
285
+
286
+ static int getTextTypeAndValue(char* text, int size, int idx) {
287
+ int c;
288
+ char *ms, *ps;
289
+ if (idx >= size)
290
+ return 0;
291
+ c = text[idx];
292
+ if (c >= 'A' && c <= 'Z')
293
+ return (ALPHA + c - 'A');
294
+ if (c >= 'a' && c <= 'z')
295
+ return (LOWER + c - 'a');
296
+ if (c == ' ')
297
+ return (ALPHA + LOWER + MIXED + SPACE);
298
+ ms = strchr(MIXED_SET, c);
299
+ ps = strchr(PUNCTUATION_SET, c);
300
+ if (!ms && !ps)
301
+ return (ISBYTE + (c & 0xff));
302
+ if (ms - MIXED_SET == ps - PUNCTUATION_SET)
303
+ return (MIXED + PUNCTUATION + (ms - MIXED_SET));
304
+ if (ms != NULL)
305
+ return (MIXED + (ms - MIXED_SET));
306
+ return (PUNCTUATION + (ps - PUNCTUATION_SET));
307
+ }
308
+
309
+ static void textCompaction(pPdf417class p, int start, int length) {
310
+ int dest[ABSOLUTE_MAX_TEXT_SIZE * 2];
311
+ char* text = p->param->text;
312
+ int mode = ALPHA;
313
+ int ptr = 0;
314
+ int fullBytes = 0;
315
+ int v = 0;
316
+ int k;
317
+ int size;
318
+ memset(dest, 0, sizeof(dest));
319
+ length += start;
320
+ for (k = start; k < length; ++k) {
321
+ v = getTextTypeAndValue(text, length, k);
322
+ if ((v & mode) != 0) {
323
+ dest[ptr++] = v & 0xff;
324
+ continue;
325
+ }
326
+ if ((v & ISBYTE) != 0) {
327
+ if ((ptr & 1) != 0) {
328
+ dest[ptr++] = (mode & PUNCTUATION) != 0 ? PAL : PS;
329
+ mode = (mode & PUNCTUATION) != 0 ? ALPHA : mode;
330
+ }
331
+ dest[ptr++] = BYTESHIFT;
332
+ dest[ptr++] = v & 0xff;
333
+ fullBytes += 2;
334
+ continue;
335
+ }
336
+ switch (mode) {
337
+ case ALPHA:
338
+ if ((v & LOWER) != 0) {
339
+ dest[ptr++] = LL;
340
+ dest[ptr++] = v & 0xff;
341
+ mode = LOWER;
342
+ }
343
+ else if ((v & MIXED) != 0) {
344
+ dest[ptr++] = ML;
345
+ dest[ptr++] = v & 0xff;
346
+ mode = MIXED;
347
+ }
348
+ else if ((getTextTypeAndValue(text, length, k + 1) & getTextTypeAndValue(text, length, k + 2) & PUNCTUATION) != 0) {
349
+ dest[ptr++] = ML;
350
+ dest[ptr++] = PL;
351
+ dest[ptr++] = v & 0xff;
352
+ mode = PUNCTUATION;
353
+ }
354
+ else {
355
+ dest[ptr++] = PS;
356
+ dest[ptr++] = v & 0xff;
357
+ }
358
+ break;
359
+ case LOWER:
360
+ if ((v & ALPHA) != 0) {
361
+ if ((getTextTypeAndValue(text, length, k + 1) & getTextTypeAndValue(text, length, k + 2) & ALPHA) != 0) {
362
+ dest[ptr++] = ML;
363
+ dest[ptr++] = AL;
364
+ mode = ALPHA;
365
+ }
366
+ else {
367
+ dest[ptr++] = AS;
368
+ }
369
+ dest[ptr++] = v & 0xff;
370
+ }
371
+ else if ((v & MIXED) != 0) {
372
+ dest[ptr++] = ML;
373
+ dest[ptr++] = v & 0xff;
374
+ mode = MIXED;
375
+ }
376
+ else if ((getTextTypeAndValue(text, length, k + 1) & getTextTypeAndValue(text, length, k + 2) & PUNCTUATION) != 0) {
377
+ dest[ptr++] = ML;
378
+ dest[ptr++] = PL;
379
+ dest[ptr++] = v & 0xff;
380
+ mode = PUNCTUATION;
381
+ }
382
+ else {
383
+ dest[ptr++] = PS;
384
+ dest[ptr++] = v & 0xff;
385
+ }
386
+ break;
387
+ case MIXED:
388
+ if ((v & LOWER) != 0) {
389
+ dest[ptr++] = LL;
390
+ dest[ptr++] = v & 0xff;
391
+ mode = LOWER;
392
+ }
393
+ else if ((v & ALPHA) != 0) {
394
+ dest[ptr++] = AL;
395
+ dest[ptr++] = v & 0xff;
396
+ mode = ALPHA;
397
+ }
398
+ else if ((getTextTypeAndValue(text, length, k + 1) & getTextTypeAndValue(text, length, k + 2) & PUNCTUATION) != 0) {
399
+ dest[ptr++] = PL;
400
+ dest[ptr++] = v & 0xff;
401
+ mode = PUNCTUATION;
402
+ }
403
+ else {
404
+ dest[ptr++] = PS;
405
+ dest[ptr++] = v & 0xff;
406
+ }
407
+ break;
408
+ case PUNCTUATION:
409
+ dest[ptr++] = PAL;
410
+ mode = ALPHA;
411
+ --k;
412
+ break;
413
+ }
414
+ }
415
+ if ((ptr & 1) != 0)
416
+ dest[ptr++] = PS;
417
+ size = (ptr + fullBytes) / 2;
418
+ if (size + p->cwPtr > MAX_DATA_CODEWORDS) {
419
+ p->param->error = PDF417_ERROR_TEXT_TOO_BIG;
420
+ return;
421
+ }
422
+ length = ptr;
423
+ ptr = 0;
424
+ while (ptr < length) {
425
+ v = dest[ptr++];
426
+ if (v >= 30) {
427
+ p->param->codewords[p->cwPtr++] = v;
428
+ p->param->codewords[p->cwPtr++] = dest[ptr++];
429
+ }
430
+ else
431
+ p->param->codewords[p->cwPtr++] = v * 30 + dest[ptr++];
432
+ }
433
+ }
434
+
435
+ static void basicNumberCompaction(pPdf417class p, int start, int length) {
436
+ char* text = p->param->text;
437
+ int* ret = p->param->codewords + p->cwPtr;
438
+ int retLast = length / 3;
439
+ int ni, k;
440
+ p->cwPtr += retLast + 1;
441
+ memset(ret, 0, (retLast + 1) * sizeof(int));
442
+ ret[retLast] = 1;
443
+ length += start;
444
+ for (ni = start; ni < length; ++ni) {
445
+ // multiply by 10
446
+ for (k = retLast; k >= 0; --k)
447
+ ret[k] *= 10;
448
+ // add the digit
449
+ ret[retLast] += text[ni] - '0';
450
+ // propagate carry
451
+ for (k = retLast; k > 0; --k) {
452
+ ret[k - 1] += ret[k] / 900;
453
+ ret[k] %= 900;
454
+ }
455
+ }
456
+ }
457
+
458
+ static void numberCompaction(pPdf417class p, int start, int length) {
459
+ int full = (length / 44) * 15;
460
+ int size = length % 44;
461
+ int k;
462
+ if (size == 0)
463
+ size = full;
464
+ else
465
+ size = full + size / 3 + 1;
466
+ if (size + p->cwPtr > MAX_DATA_CODEWORDS) {
467
+ p->param->error = PDF417_ERROR_TEXT_TOO_BIG;
468
+ return;
469
+ }
470
+ length += start;
471
+ for (k = start; k < length; k += 44) {
472
+ size = length - k < 44 ? length - k : 44;
473
+ basicNumberCompaction(p, k, size);
474
+ }
475
+ }
476
+
477
+ static void byteCompaction6(pPdf417class p, int start) {
478
+ int length = 6;
479
+ char* text = p->param->text;
480
+ int* ret = p->param->codewords + p->cwPtr;
481
+ int retLast = 4;
482
+ int ni, k;
483
+ p->cwPtr += retLast + 1;
484
+ memset(ret, 0, (retLast + 1) * sizeof(int));
485
+ length += start;
486
+ for (ni = start; ni < length; ++ni) {
487
+ // multiply by 256
488
+ for (k = retLast; k >= 0; --k)
489
+ ret[k] *= 256;
490
+ // add the digit
491
+ ret[retLast] += (int)text[ni] & 0xff;
492
+ // propagate carry
493
+ for (k = retLast; k > 0; --k) {
494
+ ret[k - 1] += ret[k] / 900;
495
+ ret[k] %= 900;
496
+ }
497
+ }
498
+ }
499
+
500
+ static void byteCompaction(pPdf417class p, int start, int length) {
501
+ int k, j;
502
+ int size = (length / 6) * 5 + (length % 6);
503
+ if (size + p->cwPtr > MAX_DATA_CODEWORDS) {
504
+ p->param->error = PDF417_ERROR_TEXT_TOO_BIG;
505
+ return;
506
+ }
507
+ length += start;
508
+ for (k = start; k < length; k += 6) {
509
+ size = length - k < 44 ? length - k : 6;
510
+ if (size < 6) {
511
+ for (j = 0; j < size; ++j)
512
+ p->param->codewords[p->cwPtr++] = (int)p->param->text[k + j] & 0xff;
513
+ }
514
+ else {
515
+ byteCompaction6(p, k);
516
+ }
517
+ }
518
+ }
519
+
520
+ static void breakString(pPdf417class p, pArrayList list) {
521
+ char* text = p->param->text;
522
+ int textLength = p->param->lenText;
523
+ int lastP = 0;
524
+ int startN = 0;
525
+ int nd = 0;
526
+ char c = 0;
527
+ int k, ptrS, lastTxt, j, txt;
528
+ pListElement v;
529
+ pListElement vp;
530
+ pListElement vn;
531
+ list->size = 0;
532
+ for (k = 0; k < textLength; ++k) {
533
+ c = text[k];
534
+ if (c >= '0' && c <= '9') {
535
+ if (nd == 0)
536
+ startN = k;
537
+ ++nd;
538
+ continue;
539
+ }
540
+ if (nd >= 13) {
541
+ if (lastP != startN) {
542
+ c = text[lastP];
543
+ ptrS = lastP;
544
+ lastTxt = (c >= ' ' && c < 127) || c == '\r' || c == '\n' || c == '\t';
545
+ for (j = lastP; j < startN; ++j) {
546
+ c = text[j];
547
+ txt = (c >= ' ' && c < 127) || c == '\r' || c == '\n' || c == '\t';
548
+ if (txt != lastTxt) {
549
+ listAdd(list, (char)(lastTxt ? 'T' : 'B'), lastP, j);
550
+ lastP = j;
551
+ lastTxt = txt;
552
+ }
553
+ }
554
+ listAdd(list, (char)(lastTxt ? 'T' : 'B'), lastP, startN);
555
+ }
556
+ listAdd(list, 'N', startN, k);
557
+ lastP = k;
558
+ }
559
+ nd = 0;
560
+ }
561
+ if (nd < 13)
562
+ startN = textLength;
563
+ if (lastP != startN) {
564
+ c = text[lastP];
565
+ ptrS = lastP;
566
+ lastTxt = (c >= ' ' && c < 127) || c == '\r' || c == '\n' || c == '\t';
567
+ for (j = lastP; j < startN; ++j) {
568
+ c = text[j];
569
+ txt = (c >= ' ' && c < 127) || c == '\r' || c == '\n' || c == '\t';
570
+ if (txt != lastTxt) {
571
+ listAdd(list, (char)(lastTxt ? 'T' : 'B'), lastP, j);
572
+ lastP = j;
573
+ lastTxt = txt;
574
+ }
575
+ }
576
+ listAdd(list, (char)(lastTxt ? 'T' : 'B'), lastP, startN);
577
+ }
578
+ if (nd >= 13)
579
+ listAdd(list, 'N', startN, textLength);
580
+ //optimize
581
+ //merge short binary
582
+ for (k = 0; k < list->size; ++k) {
583
+ v = listGet(list, k);
584
+ vp = listGet(list, k - 1);
585
+ vn = listGet(list, k + 1);;
586
+ if (checkElementType(v, 'B') && getElementLength(v) == 1) {
587
+ if (checkElementType(vp, 'T') && checkElementType(vn, 'T')
588
+ && getElementLength(vp) + getElementLength(vn) >= 3) {
589
+ vp->end = vn->end;
590
+ listRemove(list, k);
591
+ listRemove(list, k);
592
+ k = -1;
593
+ continue;
594
+ }
595
+ }
596
+ }
597
+ //merge text sections
598
+ for (k = 0; k < list->size; ++k) {
599
+ v = listGet(list, k);
600
+ vp = listGet(list, k - 1);
601
+ vn = listGet(list, k + 1);;
602
+ if (checkElementType(v, 'T') && getElementLength(v) >= 5) {
603
+ int redo = 0;
604
+ if ((checkElementType(vp, 'B') && getElementLength(vp) == 1) || checkElementType(vp, 'T')) {
605
+ redo = 1;
606
+ v->start = vp->start;
607
+ listRemove(list, k - 1);
608
+ --k;
609
+ }
610
+ if ((checkElementType(vn, 'B') && getElementLength(vn) == 1) || checkElementType(vn, 'T')) {
611
+ redo = 1;
612
+ v->end = vn->end;
613
+ listRemove(list, k + 1);
614
+ }
615
+ if (redo) {
616
+ k = -1;
617
+ continue;
618
+ }
619
+ }
620
+ }
621
+ //merge binary sections
622
+ for (k = 0; k < list->size; ++k) {
623
+ v = listGet(list, k);
624
+ vp = listGet(list, k - 1);
625
+ vn = listGet(list, k + 1);;
626
+ if (checkElementType(v, 'B')) {
627
+ int redo = 0;
628
+ if ((checkElementType(vp, 'T') && getElementLength(vp) < 5) || checkElementType(vp, 'B')) {
629
+ redo = 1;
630
+ v->start = vp->start;
631
+ listRemove(list, k - 1);
632
+ --k;
633
+ }
634
+ if ((checkElementType(vn, 'T') && getElementLength(vn) < 5) || checkElementType(vn, 'B')) {
635
+ redo = 1;
636
+ v->end = vn->end;
637
+ listRemove(list, k + 1);
638
+ }
639
+ if (redo) {
640
+ k = -1;
641
+ continue;
642
+ }
643
+ }
644
+ }
645
+ // check if all numbers
646
+ if (list->size == 1 && (v = listGet(list, 0))->type == 'T' && getElementLength(v) >= 8) {
647
+ for (k = v->start; k < v->end; ++k) {
648
+ c = text[k];
649
+ if (c < '0' || c > '9')
650
+ break;
651
+ }
652
+ if (k == v->end)
653
+ v->type = 'N';
654
+ }
655
+ }
656
+
657
+ static void assemble(pPdf417class p, pArrayList list) {
658
+ int k;
659
+ if (list->size == 0)
660
+ return;
661
+ p->cwPtr = 1;
662
+ for (k = 0; k < list->size; ++k) {
663
+ pListElement v = listGet(list, k);
664
+ switch (v->type) {
665
+ case 'T':
666
+ if (k != 0)
667
+ p->param->codewords[p->cwPtr++] = TEXT_MODE;
668
+ textCompaction(p, v->start, v->end - v->start);
669
+ break;
670
+ case 'N':
671
+ p->param->codewords[p->cwPtr++] = NUMERIC_MODE;
672
+ numberCompaction(p, v->start, v->end - v->start);
673
+ break;
674
+ case 'B':
675
+ p->param->codewords[p->cwPtr++] = (v->end - v->start) % 6 ? BYTE_MODE : BYTE_MODE_6;
676
+ byteCompaction(p, v->start, v->end - v->start);
677
+ break;
678
+ }
679
+ if (p->param->error)
680
+ return;
681
+ }
682
+ }
683
+
684
+ static int maxPossibleErrorLevel(int remain) {
685
+ int level = 8;
686
+ int size = 512;
687
+ while (level > 0) {
688
+ if (remain >= size)
689
+ return level;
690
+ --level;
691
+ size >>= 1;
692
+ }
693
+ return 0;
694
+ }
695
+
696
+ static void dumpList(pPdf417class p, pArrayList list) {
697
+ int k;
698
+ if (list->size == 0)
699
+ return;
700
+ for (k = 0; k < list->size; ++k) {
701
+ pListElement v = listGet(list, k);
702
+ printf("%c%.*s\n", v->type, v->end - v->start, p->param->text + v->start);
703
+ }
704
+ }
705
+
706
+ static int getMaxSquare(pPdf417param p) {
707
+ if (p->codeColumns > 21) {
708
+ p->codeColumns = 29;
709
+ p->codeRows = 32;
710
+ }
711
+ else {
712
+ p->codeColumns = 16;
713
+ p->codeRows = 58;
714
+ }
715
+ return MAX_DATA_CODEWORDS + 2;
716
+ }
717
+
718
+ void fetchCodewords(pPdf417param p) {
719
+ pdf417class pp;
720
+ arrayList list;
721
+ pp.param = p;
722
+ p->error = 0;
723
+ if (p->lenText < 0)
724
+ p->lenText = strlen(p->text);
725
+ if (p->lenText > ABSOLUTE_MAX_TEXT_SIZE) {
726
+ p->error = PDF417_ERROR_TEXT_TOO_BIG;
727
+ return;
728
+ }
729
+ listInit(&list);
730
+ breakString(&pp, &list);
731
+ //dumpList(&pp, &list);
732
+ assemble(&pp, &list);
733
+ listFree(&list);
734
+ if (p->error)
735
+ return;
736
+ p->codewords[0] = p->lenCodewords = pp.cwPtr;
737
+
738
+ }
739
+
740
+ void paintCode(pPdf417param p) {
741
+ pdf417class pp;
742
+ arrayList list;
743
+ int maxErr, fixedColumn, lenErr, tot, skipRowColAdjust, pad;
744
+ pp.param = p;
745
+ p->error = 0;
746
+ if (p->options & PDF417_USE_RAW_CODEWORDS) {
747
+ if (p->lenCodewords > MAX_DATA_CODEWORDS || p->lenCodewords < 1 || p->lenCodewords != p->codewords[0]) {
748
+ p->error = PDF417_ERROR_INVALID_PARAMS;
749
+ return;
750
+ }
751
+ }
752
+ else {
753
+ if (p->lenText < 0)
754
+ p->lenText = strlen(p->text);
755
+ if (p->lenText > ABSOLUTE_MAX_TEXT_SIZE) {
756
+ p->error = PDF417_ERROR_TEXT_TOO_BIG;
757
+ return;
758
+ }
759
+ listInit(&list);
760
+ breakString(&pp, &list);
761
+ // dumpList(&pp, &list);
762
+ assemble(&pp, &list);
763
+ listFree(&list);
764
+ if (p->error)
765
+ return;
766
+ p->codewords[0] = p->lenCodewords = pp.cwPtr;
767
+ }
768
+ maxErr = maxPossibleErrorLevel(MAX_DATA_CODEWORDS + 2 - p->lenCodewords);
769
+ if (!(p->options & PDF417_USE_ERROR_LEVEL)) {
770
+ if (p->lenCodewords < 41)
771
+ p->errorLevel = 2;
772
+ else if (p->lenCodewords < 161)
773
+ p->errorLevel = 3;
774
+ else if (p->lenCodewords < 321)
775
+ p->errorLevel = 4;
776
+ else
777
+ p->errorLevel = 5;
778
+ }
779
+ if (p->errorLevel < 0)
780
+ p->errorLevel = 0;
781
+ else if (p->errorLevel > maxErr)
782
+ p->errorLevel = maxErr;
783
+ if (p->codeColumns < 1)
784
+ p->codeColumns = 1;
785
+ else if (p->codeColumns > 30)
786
+ p->codeColumns = 30;
787
+ if (p->codeRows < 3)
788
+ p->codeRows = 3;
789
+ else if (p->codeRows > 90)
790
+ p->codeRows = 90;
791
+ lenErr = 2 << p->errorLevel;
792
+ fixedColumn = !(p->options & PDF417_FIXED_ROWS);
793
+ skipRowColAdjust = 0;
794
+ tot = p->lenCodewords + lenErr;
795
+ if (p->options & PDF417_FIXED_RECTANGLE) {
796
+ tot = p->codeColumns * p->codeRows;
797
+ if (tot > MAX_DATA_CODEWORDS + 2) {
798
+ tot = getMaxSquare(p);
799
+ }
800
+ if (tot < p->lenCodewords + lenErr)
801
+ tot = p->lenCodewords + lenErr;
802
+ else
803
+ skipRowColAdjust = 1;
804
+ }
805
+ else if (!(p->options & (PDF417_FIXED_COLUMNS | PDF417_FIXED_ROWS))) {
806
+ double c, b;
807
+ fixedColumn = 1;
808
+ if (p->aspectRatio < 0.001)
809
+ p->aspectRatio = 0.001f;
810
+ else if (p->aspectRatio > 1000)
811
+ p->aspectRatio = 1000;
812
+ b = 73 * p->aspectRatio - 4;
813
+ c = (-b + sqrt(b * b + 4 * 17 * p->aspectRatio * (p->lenCodewords + lenErr) * p->yHeight)) / (2 * 17 * p->aspectRatio);
814
+ p->codeColumns = (int)(c + 0.5);
815
+ if (p->codeColumns < 1)
816
+ p->codeColumns = 1;
817
+ else if (p->codeColumns > 30)
818
+ p->codeColumns = 30;
819
+ }
820
+ if (!skipRowColAdjust) {
821
+ if (fixedColumn) {
822
+ p->codeRows = (tot - 1) / p->codeColumns + 1;
823
+ if (p->codeRows < 3)
824
+ p->codeRows = 3;
825
+ else if (p->codeRows > 90) {
826
+ p->codeRows = 90;
827
+ p->codeColumns = (tot - 1) / 90 + 1;
828
+ }
829
+ }
830
+ else {
831
+ p->codeColumns = (tot - 1) / p->codeRows + 1;
832
+ if (p->codeColumns > 30) {
833
+ p->codeColumns = 30;
834
+ p->codeRows = (tot - 1) / 30 + 1;
835
+ }
836
+ }
837
+ tot = p->codeRows * p->codeColumns;
838
+ }
839
+ if (tot > MAX_DATA_CODEWORDS + 2) {
840
+ tot = getMaxSquare(p);
841
+ }
842
+ p->errorLevel = maxPossibleErrorLevel(tot - p->lenCodewords);
843
+ lenErr = 2 << p->errorLevel;
844
+ pad = tot - lenErr - p->lenCodewords;
845
+ pp.cwPtr = p->lenCodewords;
846
+ while (pad--)
847
+ p->codewords[pp.cwPtr++] = TEXT_MODE;
848
+ p->codewords[0] = p->lenCodewords = pp.cwPtr;
849
+ calculateErrorCorrection(&pp, pp.param->lenCodewords);
850
+ pp.param->lenCodewords = tot;
851
+ outPaintCode(&pp);
852
+ }
853
+
854
+ #ifdef __cplusplus
855
+ }
856
+ #endif
857
+
858
+
859
+
860
+