001/*
002 * $Id: BarcodePDF417.java 4784 2011-03-15 08:33:00Z blowagie $
003 *
004 * This file is part of the iText (R) project.
005 * Copyright (c) 1998-2011 1T3XT BVBA
006 * Authors: Bruno Lowagie, Paulo Soares, et al.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU Affero General Public License version 3
010 * as published by the Free Software Foundation with the addition of the
011 * following permission added to Section 15 as permitted in Section 7(a):
012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT,
013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
014 *
015 * This program is distributed in the hope that it will be useful, but
016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
017 * or FITNESS FOR A PARTICULAR PURPOSE.
018 * See the GNU Affero General Public License for more details.
019 * You should have received a copy of the GNU Affero General Public License
020 * along with this program; if not, see http://www.gnu.org/licenses or write to
021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
022 * Boston, MA, 02110-1301 USA, or download the license from the following URL:
023 * http://itextpdf.com/terms-of-use/
024 *
025 * The interactive user interfaces in modified source and object code versions
026 * of this program must display Appropriate Legal Notices, as required under
027 * Section 5 of the GNU Affero General Public License.
028 *
029 * In accordance with Section 7(b) of the GNU Affero General Public License,
030 * a covered work must retain the producer line in every PDF that is created
031 * or manipulated using iText.
032 *
033 * You can be released from the requirements of the license by purchasing
034 * a commercial license. Buying such a license is mandatory as soon as you
035 * develop commercial activities involving the iText software without
036 * disclosing the source code of your own applications.
037 * These activities include: offering paid services to customers as an ASP,
038 * serving PDFs on the fly in a web application, shipping iText with a closed
039 * source product.
040 *
041 * For more information, please contact iText Software Corp. at this
042 * address: sales@itextpdf.com
043 */
044package com.itextpdf.text.pdf;
045
046import java.awt.Canvas;
047import java.awt.image.MemoryImageSource;
048import java.util.ArrayList;
049
050import com.itextpdf.text.BadElementException;
051import com.itextpdf.text.Image;
052import com.itextpdf.text.error_messages.MessageLocalization;
053import com.itextpdf.text.pdf.codec.CCITTG4Encoder;
054
055/** Generates the 2D barcode PDF417. Supports dimensioning auto-sizing, fixed
056 * and variable sizes, automatic and manual error levels, raw codeword input,
057 * codeword size optimization and bitmap inversion. The output can
058 * be a CCITT G4 <CODE>Image</CODE> or a raw bitmap.
059 * @author Paulo Soares
060 */
061public class BarcodePDF417 {
062
063    /** Auto-size is made based on <CODE>aspectRatio</CODE> and <CODE>yHeight</CODE>. */
064    public static final int PDF417_USE_ASPECT_RATIO = 0;
065    /** The size of the barcode will be at least <CODE>codeColumns*codeRows</CODE>. */
066    public static final int PDF417_FIXED_RECTANGLE = 1;
067    /** The size will be at least <CODE>codeColumns</CODE>
068     * with a variable number of <CODE>codeRows</CODE>.
069     */
070    public static final int PDF417_FIXED_COLUMNS = 2;
071    /** The size will be at least <CODE>codeRows</CODE>
072     * with a variable number of <CODE>codeColumns</CODE>.
073     */
074    public static final int PDF417_FIXED_ROWS = 4;
075    /** The error level correction is set automatically according
076     * to ISO 15438 recommendations.
077     */
078    public static final int PDF417_AUTO_ERROR_LEVEL = 0;
079    /** The error level correction is set by the user. It can be 0 to 8. */
080    public static final int PDF417_USE_ERROR_LEVEL = 16;
081    /**
082     * One single binary segment is used
083     */
084    public static final int PDF417_FORCE_BINARY = 32;
085    /** No <CODE>text</CODE> interpretation is done and the content of <CODE>codewords</CODE>
086     * is used directly.
087     */
088    public static final int PDF417_USE_RAW_CODEWORDS = 64;
089    /** Inverts the output bits of the raw bitmap that is normally
090     * bit one for black. It has only effect for the raw bitmap.
091     */
092    public static final int PDF417_INVERT_BITMAP = 128;
093    /** Use Macro PDF417 Encoding
094     * @see #setMacroFileId(String)
095     * @see #setMacroSegmentId(int)
096     * @see #setMacroSegmentCount(int)
097     */
098    public static final int PDF417_USE_MACRO = 256;
099
100
101    private int macroSegmentCount=0;
102    private int macroSegmentId=-1;
103    private String macroFileId;
104    private int macroIndex;
105    protected int bitPtr;
106    protected int cwPtr;
107    protected SegmentList segmentList;
108
109
110    /** Creates a new <CODE>BarcodePDF417</CODE> with the default settings. */
111    public BarcodePDF417() {
112        setDefaultParameters();
113    }
114
115    /**
116     * Sets the segment id for macro PDF417 encoding
117     * @param id the id (starting at 0)
118     * @see #setMacroSegmentCount(int)
119     */
120    public void setMacroSegmentId(int id) {
121        this.macroSegmentId = id;
122    }
123
124    /**
125     * Sets the segment count for macro PDF417 encoding
126     * @param cnt the number of macro segments
127     * @see #setMacroSegmentId(int)
128     */
129    public void setMacroSegmentCount(int cnt) {
130        this.macroSegmentCount = cnt;
131    }
132
133    /**
134     * Sets the File ID for macro PDF417 encoding
135     * @param id the file id
136     */
137    public void setMacroFileId(String id) {
138        this.macroFileId = id;
139    }
140
141    protected boolean checkSegmentType(Segment segment, char type) {
142        if (segment == null)
143            return false;
144        return segment.type == type;
145    }
146
147    protected int getSegmentLength(Segment segment) {
148        if (segment == null)
149            return 0;
150        return segment.end - segment.start;
151    }
152
153    /** Set the default settings that correspond to <CODE>PDF417_USE_ASPECT_RATIO</CODE>
154     * and <CODE>PDF417_AUTO_ERROR_LEVEL</CODE>.
155     */
156    public void setDefaultParameters() {
157        options = 0;
158        outBits = null;
159        text = new byte[0];
160        yHeight = 3;
161        aspectRatio = 0.5f;
162    }
163
164    protected void outCodeword17(int codeword) {
165        int bytePtr = bitPtr / 8;
166        int bit = bitPtr - bytePtr * 8;
167        outBits[bytePtr++] |= codeword >> 9 + bit;
168        outBits[bytePtr++] |= codeword >> 1 + bit;
169        codeword <<= 8;
170        outBits[bytePtr] |= codeword >> 1 + bit;
171        bitPtr += 17;
172    }
173
174    protected void outCodeword18(int codeword) {
175        int bytePtr = bitPtr / 8;
176        int bit = bitPtr - bytePtr * 8;
177        outBits[bytePtr++] |= codeword >> 10 + bit;
178        outBits[bytePtr++] |= codeword >> 2 + bit;
179        codeword <<= 8;
180        outBits[bytePtr] |= codeword >> 2 + bit;
181        if (bit == 7)
182            outBits[++bytePtr] |= 0x80;
183        bitPtr += 18;
184    }
185
186    protected void outCodeword(int codeword) {
187        outCodeword17(codeword);
188    }
189
190    protected void outStopPattern() {
191        outCodeword18(STOP_PATTERN);
192    }
193
194    protected void outStartPattern() {
195        outCodeword17(START_PATTERN);
196    }
197
198    protected void outPaintCode() {
199        int codePtr = 0;
200        bitColumns = START_CODE_SIZE * (codeColumns + 3) + STOP_SIZE;
201        int lenBits = ((bitColumns - 1) / 8 + 1) * codeRows;
202        outBits = new byte[lenBits];
203        for (int row = 0; row < codeRows; ++row) {
204            bitPtr = ((bitColumns - 1) / 8 + 1) * 8 * row;
205            int rowMod = row % 3;
206            int cluster[] = CLUSTERS[rowMod];
207            outStartPattern();
208            int edge = 0;
209            switch (rowMod) {
210            case 0:
211                edge = 30 * (row / 3) + (codeRows - 1) / 3;
212                break;
213            case 1:
214                edge = 30 * (row / 3) + errorLevel * 3 + (codeRows - 1) % 3;
215                break;
216            default:
217                edge = 30 * (row / 3) + codeColumns - 1;
218                break;
219            }
220            outCodeword(cluster[edge]);
221
222            for (int column = 0; column < codeColumns; ++column) {
223                outCodeword(cluster[codewords[codePtr++]]);
224            }
225
226            switch (rowMod) {
227            case 0:
228                edge = 30 * (row / 3) + codeColumns - 1;
229                break;
230            case 1:
231                edge = 30 * (row / 3) + (codeRows - 1) / 3;
232                break;
233            default:
234                edge = 30 * (row / 3) + errorLevel * 3 + (codeRows - 1) % 3;
235                break;
236            }
237            outCodeword(cluster[edge]);
238            outStopPattern();
239        }
240        if ((options & PDF417_INVERT_BITMAP) != 0) {
241            for (int k = 0; k < outBits.length; ++k)
242                outBits[k] ^= 0xff;
243        }
244    }
245
246    protected void calculateErrorCorrection(int dest) {
247        if (errorLevel < 0 || errorLevel > 8)
248            errorLevel = 0;
249        int A[] = ERROR_LEVEL[errorLevel];
250        int Alength = 2 << errorLevel;
251        for (int k = 0; k < Alength; ++k)
252            codewords[dest + k] = 0;
253        int lastE = Alength - 1;
254        for (int k = 0; k < lenCodewords; ++k) {
255            int t1 = codewords[k] + codewords[dest];
256            for (int e = 0; e <= lastE; ++e) {
257                int t2 = t1 * A[lastE - e] % MOD;
258                int t3 = MOD - t2;
259                codewords[dest + e] = ((e == lastE ? 0 : codewords[dest + e + 1]) + t3) % MOD;
260            }
261        }
262        for (int k = 0; k < Alength; ++k)
263            codewords[dest + k] = (MOD - codewords[dest + k]) % MOD;
264    }
265
266    private static int getTextTypeAndValue(byte[] input, int maxLength, int idx) {
267        if (idx >= maxLength)
268            return 0;
269        char c = (char)(input[idx] & 0xff);
270        if (c >= 'A' && c <= 'Z')
271            return ALPHA + c - 'A';
272        if (c >= 'a' && c <= 'z')
273            return LOWER + c - 'a';
274        if (c == ' ')
275            return ALPHA + LOWER + MIXED + SPACE;
276        int ms = MIXED_SET.indexOf(c);
277        int ps = PUNCTUATION_SET.indexOf(c);
278        if (ms < 0 && ps < 0)
279            return ISBYTE + c;
280        if (ms == ps)
281            return MIXED + PUNCTUATION + ms;
282        if (ms >= 0)
283            return MIXED + ms;
284        return PUNCTUATION + ps;
285    }
286
287    protected int getTextTypeAndValue(int maxLength, int idx) {
288        return getTextTypeAndValue(text, maxLength,idx);
289    }
290
291    private void textCompaction(byte[] input, int start, int length) {
292        int dest[] = new int[ABSOLUTE_MAX_TEXT_SIZE * 2];
293        int mode = ALPHA;
294        int ptr = 0;
295        int fullBytes = 0;
296        int v = 0;
297        int k;
298        int size;
299        length += start;
300        for (k = start; k < length; ++k) {
301            v = getTextTypeAndValue(input, length, k);
302            if ((v & mode) != 0) {
303                dest[ptr++] = v & 0xff;
304                continue;
305            }
306            if ((v & ISBYTE) != 0) {
307                if ((ptr & 1) != 0) {
308                    //add a padding word
309                    dest[ptr++] = PAL;
310                    mode = (mode & PUNCTUATION) != 0 ? ALPHA : mode;
311                }
312                dest[ptr++] = BYTESHIFT;
313                dest[ptr++] = v & 0xff;
314                fullBytes += 2;
315                continue;
316            }
317            switch (mode) {
318            case ALPHA:
319                if ((v & LOWER) != 0) {
320                    dest[ptr++] = LL;
321                    dest[ptr++] = v & 0xff;
322                    mode = LOWER;
323                }
324                else if ((v & MIXED) != 0) {
325                    dest[ptr++] = ML;
326                    dest[ptr++] = v & 0xff;
327                    mode = MIXED;
328                }
329                else if ((getTextTypeAndValue(input, length, k + 1) & getTextTypeAndValue(input, length, k + 2) & PUNCTUATION) != 0) {
330                    dest[ptr++] = ML;
331                    dest[ptr++] = PL;
332                    dest[ptr++] = v & 0xff;
333                    mode = PUNCTUATION;
334                }
335                else {
336                    dest[ptr++] = PS;
337                    dest[ptr++] = v & 0xff;
338                }
339                break;
340            case LOWER:
341                if ((v & ALPHA) != 0) {
342                    if ((getTextTypeAndValue(input, length, k + 1) & getTextTypeAndValue(input, length, k + 2) & ALPHA) != 0) {
343                        dest[ptr++] = ML;
344                        dest[ptr++] = AL;
345                        mode = ALPHA;
346                    }
347                    else {
348                        dest[ptr++] = AS;
349                    }
350                    dest[ptr++] = v & 0xff;
351                }
352                else if ((v & MIXED) != 0) {
353                    dest[ptr++] = ML;
354                    dest[ptr++] = v & 0xff;
355                    mode = MIXED;
356                }
357                else if ((getTextTypeAndValue(input, length, k + 1) & getTextTypeAndValue(input, length, k + 2) & PUNCTUATION) != 0) {
358                    dest[ptr++] = ML;
359                    dest[ptr++] = PL;
360                    dest[ptr++] = v & 0xff;
361                    mode = PUNCTUATION;
362                }
363                else {
364                    dest[ptr++] = PS;
365                    dest[ptr++] = v & 0xff;
366                }
367                break;
368            case MIXED:
369                if ((v & LOWER) != 0) {
370                    dest[ptr++] = LL;
371                    dest[ptr++] = v & 0xff;
372                    mode = LOWER;
373                }
374                else if ((v & ALPHA) != 0) {
375                    dest[ptr++] = AL;
376                    dest[ptr++] = v & 0xff;
377                    mode = ALPHA;
378                }
379                else if ((getTextTypeAndValue(input, length, k + 1) & getTextTypeAndValue(input, length, k + 2) & PUNCTUATION) != 0) {
380                    dest[ptr++] = PL;
381                    dest[ptr++] = v & 0xff;
382                    mode = PUNCTUATION;
383                }
384                else {
385                    dest[ptr++] = PS;
386                    dest[ptr++] = v & 0xff;
387                }
388                break;
389            case PUNCTUATION:
390                dest[ptr++] = PAL;
391                mode = ALPHA;
392                --k;
393                break;
394            }
395        }
396        if ((ptr & 1) != 0)
397            dest[ptr++] = PS;
398        size = (ptr + fullBytes) / 2;
399        if (size + cwPtr > MAX_DATA_CODEWORDS) {
400            throw new IndexOutOfBoundsException(MessageLocalization.getComposedMessage("the.text.is.too.big"));
401        }
402        length = ptr;
403        ptr = 0;
404        while (ptr < length) {
405            v = dest[ptr++];
406            if (v >= 30) {
407                codewords[cwPtr++] = v;
408                codewords[cwPtr++] = dest[ptr++];
409            }
410            else
411                codewords[cwPtr++] = v * 30 + dest[ptr++];
412        }
413    }
414    protected void textCompaction(int start, int length) {
415        textCompaction(text, start, length);
416    }
417
418    protected void basicNumberCompaction(int start, int length) {
419        basicNumberCompaction(text, start, length);
420    }
421
422    private void basicNumberCompaction(byte[] input, int start, int length) {
423        int ret = cwPtr;
424        int retLast = length / 3;
425        int ni, k;
426        cwPtr += retLast + 1;
427        for (k = 0; k <= retLast; ++k)
428            codewords[ret + k] = 0;
429        codewords[ret + retLast] = 1;
430        length += start;
431        for (ni = start; ni < length; ++ni) {
432            // multiply by 10
433            for (k = retLast; k >= 0; --k)
434                codewords[ret + k] *= 10;
435            // add the digit
436            codewords[ret + retLast] += input[ni] - '0';
437            // propagate carry
438            for (k = retLast; k > 0; --k) {
439                codewords[ret + k - 1] += codewords[ret + k] / 900;
440                codewords[ret + k] %= 900;
441            }
442        }
443    }
444
445    private void numberCompaction(byte[] input, int start, int length) {
446        int full = length / 44 * 15;
447        int size = length % 44;
448        int k;
449        if (size == 0)
450            size = full;
451        else
452            size = full + size / 3 + 1;
453        if (size + cwPtr > MAX_DATA_CODEWORDS) {
454            throw new IndexOutOfBoundsException(MessageLocalization.getComposedMessage("the.text.is.too.big"));
455        }
456        length += start;
457        for (k = start; k < length; k += 44) {
458            size = length - k < 44 ? length - k : 44;
459            basicNumberCompaction(input, k, size);
460        }
461        }
462
463    protected void numberCompaction(int start, int length) {
464        numberCompaction(text, start, length);
465    }
466
467    protected void byteCompaction6(int start) {
468        int length = 6;
469        int ret = cwPtr;
470        int retLast = 4;
471        int ni, k;
472        cwPtr += retLast + 1;
473        for (k = 0; k <= retLast ; ++k)
474            codewords[ret + k] = 0;
475        length += start;
476        for (ni = start; ni < length; ++ni) {
477            // multiply by 256
478            for (k = retLast; k >= 0; --k)
479                codewords[ret + k] *= 256;
480            // add the digit
481            codewords[ret + retLast] += text[ni] & 0xff;
482            // propagate carry
483            for (k = retLast; k > 0; --k) {
484                codewords[ret + k - 1] += codewords[ret + k] / 900;
485                codewords[ret + k] %= 900;
486            }
487        }
488    }
489
490    void byteCompaction(int start, int length) {
491        int k, j;
492        int size = length / 6 * 5 + length % 6;
493        if (size + cwPtr > MAX_DATA_CODEWORDS) {
494            throw new IndexOutOfBoundsException(MessageLocalization.getComposedMessage("the.text.is.too.big"));
495        }
496        length += start;
497        for (k = start; k < length; k += 6) {
498            size = length - k < 44 ? length - k : 6;
499            if (size < 6) {
500                for (j = 0; j < size; ++j)
501                    codewords[cwPtr++] = text[k + j] & 0xff;
502            }
503            else {
504                byteCompaction6(k);
505            }
506        }
507    }
508
509    void breakString() {
510        int textLength = text.length;
511        int lastP = 0;
512        int startN = 0;
513        int nd = 0;
514        char c = 0;
515        int k, j;
516        boolean lastTxt, txt;
517        Segment v;
518        Segment vp;
519        Segment vn;
520
521        if ((options & PDF417_FORCE_BINARY) != 0) {
522            segmentList.add('B', 0, textLength);
523            return;
524        }
525        for (k = 0; k < textLength; ++k) {
526            c = (char)(text[k] & 0xff);
527            if (c >= '0' && c <= '9') {
528                if (nd == 0)
529                    startN = k;
530                ++nd;
531                continue;
532            }
533            if (nd >= 13) {
534                if (lastP != startN) {
535                    c = (char)(text[lastP] & 0xff);
536                    lastTxt = c >= ' ' && c < 127 || c == '\r' || c == '\n' || c == '\t';
537                    for (j = lastP; j < startN; ++j) {
538                        c = (char)(text[j] & 0xff);
539                        txt = c >= ' ' && c < 127 || c == '\r' || c == '\n' || c == '\t';
540                        if (txt != lastTxt) {
541                            segmentList.add(lastTxt ? 'T' : 'B', lastP, j);
542                            lastP = j;
543                            lastTxt = txt;
544                        }
545                    }
546                    segmentList.add(lastTxt ? 'T' : 'B', lastP, startN);
547                }
548                segmentList.add('N', startN, k);
549                lastP = k;
550            }
551            nd = 0;
552        }
553        if (nd < 13)
554            startN = textLength;
555        if (lastP != startN) {
556            c = (char)(text[lastP] & 0xff);
557            lastTxt = c >= ' ' && c < 127 || c == '\r' || c == '\n' || c == '\t';
558            for (j = lastP; j < startN; ++j) {
559                c = (char)(text[j] & 0xff);
560                txt = c >= ' ' && c < 127 || c == '\r' || c == '\n' || c == '\t';
561                if (txt != lastTxt) {
562                    segmentList.add(lastTxt ? 'T' : 'B', lastP, j);
563                    lastP = j;
564                    lastTxt = txt;
565                }
566            }
567            segmentList.add(lastTxt ? 'T' : 'B', lastP, startN);
568        }
569        if (nd >= 13)
570            segmentList.add('N', startN, textLength);
571        //optimize
572        //merge short binary
573        for (k = 0; k < segmentList.size(); ++k) {
574            v = segmentList.get(k);
575            vp = segmentList.get(k - 1);
576            vn = segmentList.get(k + 1);
577            if (checkSegmentType(v, 'B') && getSegmentLength(v) == 1) {
578                if (checkSegmentType(vp, 'T') && checkSegmentType(vn, 'T')
579                    && getSegmentLength(vp) + getSegmentLength(vn) >= 3) {
580                    vp.end = vn.end;
581                    segmentList.remove(k);
582                    segmentList.remove(k);
583                    k = -1;
584                    continue;
585                }
586            }
587        }
588        //merge text sections
589        for (k = 0; k < segmentList.size(); ++k) {
590            v = segmentList.get(k);
591            vp = segmentList.get(k - 1);
592            vn = segmentList.get(k + 1);
593            if (checkSegmentType(v, 'T') && getSegmentLength(v) >= 5) {
594                boolean redo = false;
595                if (checkSegmentType(vp, 'B') && getSegmentLength(vp) == 1 || checkSegmentType(vp, 'T')) {
596                    redo = true;
597                    v.start = vp.start;
598                    segmentList.remove(k - 1);
599                    --k;
600                }
601                if (checkSegmentType(vn, 'B') && getSegmentLength(vn) == 1 || checkSegmentType(vn, 'T')) {
602                    redo = true;
603                    v.end = vn.end;
604                    segmentList.remove(k + 1);
605                }
606                if (redo) {
607                    k = -1;
608                    continue;
609                }
610            }
611        }
612        //merge binary sections
613        for (k = 0; k < segmentList.size(); ++k) {
614            v = segmentList.get(k);
615            vp = segmentList.get(k - 1);
616            vn = segmentList.get(k + 1);
617            if (checkSegmentType(v, 'B')) {
618                boolean redo = false;
619                if (checkSegmentType(vp, 'T') && getSegmentLength(vp) < 5 || checkSegmentType(vp, 'B')) {
620                    redo = true;
621                    v.start = vp.start;
622                    segmentList.remove(k - 1);
623                    --k;
624                }
625                if (checkSegmentType(vn, 'T') && getSegmentLength(vn) < 5 || checkSegmentType(vn, 'B')) {
626                    redo = true;
627                    v.end = vn.end;
628                    segmentList.remove(k + 1);
629                }
630                if (redo) {
631                    k = -1;
632                    continue;
633                }
634            }
635        }
636        // check if all numbers
637        if (segmentList.size() == 1 && (v = segmentList.get(0)).type == 'T' && getSegmentLength(v) >= 8) {
638            for (k = v.start; k < v.end; ++k) {
639                c = (char)(text[k] & 0xff);
640                if (c < '0' || c > '9')
641                    break;
642            }
643            if (k == v.end)
644                v.type = 'N';
645        }
646    }
647
648    protected void assemble() {
649        int k;
650        if (segmentList.size() == 0)
651            return;
652        cwPtr = 1;
653        for (k = 0; k < segmentList.size(); ++k) {
654            Segment v = segmentList.get(k);
655            switch (v.type) {
656            case 'T':
657                if (k != 0)
658                    codewords[cwPtr++] = TEXT_MODE;
659                textCompaction(v.start, getSegmentLength(v));
660                break;
661            case 'N':
662                codewords[cwPtr++] = NUMERIC_MODE;
663                numberCompaction(v.start, getSegmentLength(v));
664                break;
665            case 'B':
666                codewords[cwPtr++] = getSegmentLength(v) % 6 != 0 ? BYTE_MODE : BYTE_MODE_6;
667                byteCompaction(v.start, getSegmentLength(v));
668                break;
669            }
670        }
671
672        if ((options & PDF417_USE_MACRO) != 0) {
673            macroCodes();
674        }
675
676    }
677
678    private void macroCodes() {
679        if (macroSegmentId < 0) {
680            throw new IllegalStateException(MessageLocalization.getComposedMessage("macrosegmentid.must.be.gt.eq.0"));
681        }
682        if (macroSegmentId >= macroSegmentCount) {
683            throw new IllegalStateException(MessageLocalization.getComposedMessage("macrosegmentid.must.be.lt.macrosemgentcount"));
684        }
685        if (macroSegmentCount < 1) {
686            throw new IllegalStateException(MessageLocalization.getComposedMessage("macrosemgentcount.must.be.gt.0"));
687        }
688
689        macroIndex = cwPtr;
690        codewords[cwPtr++] = MACRO_SEGMENT_ID;
691        append(macroSegmentId, 5);
692
693        if (macroFileId != null) {
694            append(macroFileId);
695        }
696
697        if (macroSegmentId >= macroSegmentCount-1) {
698            codewords[cwPtr++] = MACRO_LAST_SEGMENT;
699        }
700
701    }
702
703    private void append(int in, int len) {
704        StringBuffer sb = new StringBuffer(len+1);
705        sb.append(Integer.toString(in));
706        for(int i = sb.length(); i < len; i++) {
707            sb.insert(0, "0");
708        }
709
710        byte[] bytes = PdfEncodings.convertToBytes(sb.toString(), "cp437");
711        numberCompaction(bytes, 0, bytes.length);
712    }
713
714    private void append(String s) {
715        byte[] bytes = PdfEncodings.convertToBytes(s, "cp437");
716        textCompaction(bytes, 0, bytes.length);
717    }
718
719
720    protected static int maxPossibleErrorLevel(int remain) {
721        int level = 8;
722        int size = 512;
723        while (level > 0) {
724            if (remain >= size)
725                return level;
726            --level;
727            size >>= 1;
728        }
729        return 0;
730    }
731
732    protected void dumpList() {
733        if (segmentList.size() == 0)
734            return;
735        for (int k = 0; k < segmentList.size(); ++k) {
736            Segment v = segmentList.get(k);
737            int len = getSegmentLength(v);
738            char c[] = new char[len];
739            for (int j = 0; j < len; ++j) {
740                c[j] = (char)(text[v.start + j] & 0xff);
741                if (c[j] == '\r')
742                    c[j] = '\n';
743            }
744            StringBuffer sb = new StringBuffer();
745            sb.append(v.type);
746            sb.append(c);
747            System.out.println(sb.toString());
748        }
749    }
750
751    protected int getMaxSquare() {
752        if (codeColumns > 21) {
753            codeColumns = 29;
754            codeRows = 32;
755        }
756        else {
757            codeColumns = 16;
758            codeRows = 58;
759        }
760        return MAX_DATA_CODEWORDS + 2;
761    }
762
763    /** Paints the barcode. If no exception was thrown a valid barcode is available. */
764    public void paintCode() {
765        int maxErr, lenErr, tot, pad;
766        if ((options & PDF417_USE_RAW_CODEWORDS) != 0) {
767            if (lenCodewords > MAX_DATA_CODEWORDS || lenCodewords < 1 || lenCodewords != codewords[0]) {
768                throw new IllegalArgumentException(MessageLocalization.getComposedMessage("invalid.codeword.size"));
769            }
770        }
771        else {
772            if (text == null)
773                throw new NullPointerException(MessageLocalization.getComposedMessage("text.cannot.be.null"));
774            if (text.length > ABSOLUTE_MAX_TEXT_SIZE) {
775                throw new IndexOutOfBoundsException(MessageLocalization.getComposedMessage("the.text.is.too.big"));
776            }
777            segmentList = new SegmentList();
778            breakString();
779            //dumpList();
780            assemble();
781            segmentList = null;
782            codewords[0] = lenCodewords = cwPtr;
783        }
784        maxErr = maxPossibleErrorLevel(MAX_DATA_CODEWORDS + 2 - lenCodewords);
785        if ((options & PDF417_USE_ERROR_LEVEL) == 0) {
786            if (lenCodewords < 41)
787                errorLevel = 2;
788            else if (lenCodewords < 161)
789                errorLevel = 3;
790            else if (lenCodewords < 321)
791                errorLevel = 4;
792            else
793                errorLevel = 5;
794        }
795        if (errorLevel < 0)
796            errorLevel = 0;
797        else if (errorLevel > maxErr)
798            errorLevel = maxErr;
799        if (codeColumns < 1)
800            codeColumns = 1;
801        else if (codeColumns > 30)
802            codeColumns = 30;
803        if (codeRows < 3)
804            codeRows = 3;
805        else if (codeRows > 90)
806            codeRows = 90;
807        lenErr = 2 << errorLevel;
808        boolean fixedColumn = (options & PDF417_FIXED_ROWS) == 0;
809        boolean skipRowColAdjust = false;
810        tot = lenCodewords + lenErr;
811        if ((options & PDF417_FIXED_RECTANGLE) != 0) {
812            tot = codeColumns * codeRows;
813            if (tot > MAX_DATA_CODEWORDS + 2) {
814                tot = getMaxSquare();
815            }
816            if (tot < lenCodewords + lenErr)
817                tot = lenCodewords + lenErr;
818            else
819                skipRowColAdjust = true;
820        }
821        else if ((options & (PDF417_FIXED_COLUMNS | PDF417_FIXED_ROWS)) == 0) {
822            double c, b;
823            fixedColumn = true;
824            if (aspectRatio < 0.001)
825                aspectRatio = 0.001f;
826            else if (aspectRatio > 1000)
827                aspectRatio = 1000;
828            b = 73 * aspectRatio - 4;
829            c = (-b + Math.sqrt(b * b + 4 * 17 * aspectRatio * (lenCodewords + lenErr) * yHeight)) / (2 * 17 * aspectRatio);
830            codeColumns = (int)(c + 0.5);
831            if (codeColumns < 1)
832                codeColumns = 1;
833            else if (codeColumns > 30)
834                codeColumns = 30;
835        }
836        if (!skipRowColAdjust) {
837            if (fixedColumn) {
838                codeRows = (tot - 1) / codeColumns + 1;
839                if (codeRows < 3)
840                    codeRows = 3;
841                else if (codeRows > 90) {
842                    codeRows = 90;
843                    codeColumns = (tot - 1) / 90 + 1;
844                }
845            }
846            else {
847                codeColumns = (tot - 1) / codeRows + 1;
848                if (codeColumns > 30) {
849                    codeColumns = 30;
850                    codeRows = (tot - 1) / 30 + 1;
851                }
852            }
853            tot = codeRows * codeColumns;
854        }
855        if (tot > MAX_DATA_CODEWORDS + 2) {
856            tot = getMaxSquare();
857        }
858        errorLevel = maxPossibleErrorLevel(tot - lenCodewords);
859        lenErr = 2 << errorLevel;
860        pad = tot - lenErr - lenCodewords;
861        if ((options & PDF417_USE_MACRO) != 0) {
862            // the padding comes before the control block
863            System.arraycopy(codewords, macroIndex, codewords, macroIndex + pad, pad);
864            cwPtr = lenCodewords + pad;
865            while (pad-- != 0)
866                codewords[macroIndex++] = TEXT_MODE;
867        }
868        else {
869            cwPtr = lenCodewords;
870            while (pad-- != 0)
871                codewords[cwPtr++] = TEXT_MODE;
872        }
873        codewords[0] = lenCodewords = cwPtr;
874        calculateErrorCorrection(lenCodewords);
875        lenCodewords = tot;
876        outPaintCode();
877    }
878
879    /** Gets an <CODE>Image</CODE> with the barcode. The image will have to be
880     * scaled in the Y direction by <CODE>yHeight</CODE>for the barcode
881     * to have the right printing aspect.
882     * @return the barcode <CODE>Image</CODE>
883     * @throws BadElementException on error
884     */
885    public Image getImage() throws BadElementException {
886        paintCode();
887        byte g4[] = CCITTG4Encoder.compress(outBits, bitColumns, codeRows);
888        return Image.getInstance(bitColumns, codeRows, false, Image.CCITTG4, (options & PDF417_INVERT_BITMAP) == 0 ? 0 : Image.CCITT_BLACKIS1, g4, null);
889    }
890
891    /** Creates a <CODE>java.awt.Image</CODE>.
892     * @param foreground the color of the bars
893     * @param background the color of the background
894     * @return the image
895     */
896    public java.awt.Image createAwtImage(java.awt.Color foreground, java.awt.Color background) {
897        int f = foreground.getRGB();
898        int g = background.getRGB();
899        Canvas canvas = new Canvas();
900
901        paintCode();
902        int h = (int)yHeight;
903        int pix[] = new int[bitColumns * codeRows * h];
904        int stride = (bitColumns + 7) / 8;
905        int ptr = 0;
906        for (int k = 0; k < codeRows; ++k) {
907            int p = k * stride;
908            for (int j = 0; j < bitColumns; ++j) {
909                int b = outBits[p + j / 8] & 0xff;
910                b <<= j % 8;
911                pix[ptr++] = (b & 0x80) == 0 ? g : f;
912            }
913            for (int j = 1; j < h; ++j) {
914                System.arraycopy(pix, ptr - bitColumns, pix, ptr + bitColumns * (j - 1), bitColumns);
915            }
916            ptr += bitColumns * (h - 1);
917        }
918
919        java.awt.Image img = canvas.createImage(new MemoryImageSource(bitColumns, codeRows * h, pix, 0, bitColumns));
920        return img;
921    }
922
923    /** Gets the raw image bits of the barcode. The image will have to
924     * be scaled in the Y direction by <CODE>yHeight</CODE>.
925     * @return The raw barcode image
926     */
927    public byte[] getOutBits() {
928        return this.outBits;
929    }
930
931    /** Gets the number of X pixels of <CODE>outBits</CODE>.
932     * @return the number of X pixels of <CODE>outBits</CODE>
933     */
934    public int getBitColumns() {
935        return this.bitColumns;
936    }
937
938    /** Gets the number of Y pixels of <CODE>outBits</CODE>.
939     * It is also the number of rows in the barcode.
940     * @return the number of Y pixels of <CODE>outBits</CODE>
941     */
942    public int getCodeRows() {
943        return this.codeRows;
944    }
945
946    /** Sets the number of barcode rows. This number may be changed
947     * to keep the barcode valid.
948     * @param codeRows the number of barcode rows
949     */
950    public void setCodeRows(int codeRows) {
951        this.codeRows = codeRows;
952    }
953
954    /** Gets the number of barcode data columns.
955     * @return he number of barcode data columns
956     */
957    public int getCodeColumns() {
958        return this.codeColumns;
959    }
960
961    /** Sets the number of barcode data columns.
962     * This number may be changed to keep the barcode valid.
963     * @param codeColumns the number of barcode data columns
964     */
965    public void setCodeColumns(int codeColumns) {
966        this.codeColumns = codeColumns;
967    }
968
969    /** Gets the codeword array. This array is always 928 elements long.
970     * It can be written to if the option <CODE>PDF417_USE_RAW_CODEWORDS</CODE>
971     * is set.
972     * @return the codeword array
973     */
974    public int[] getCodewords() {
975        return this.codewords;
976    }
977
978    /** Gets the length of the codewords.
979     * @return the length of the codewords
980     */
981    public int getLenCodewords() {
982        return this.lenCodewords;
983    }
984
985    /** Sets the length of the codewords.
986     * @param lenCodewords the length of the codewords
987     */
988    public void setLenCodewords(int lenCodewords) {
989        this.lenCodewords = lenCodewords;
990    }
991
992    /** Gets the error level correction used for the barcode. It may different
993     * from the previously set value.
994     * @return the error level correction used for the barcode
995     */
996    public int getErrorLevel() {
997        return this.errorLevel;
998    }
999
1000    /** Sets the error level correction for the barcode.
1001     * @param errorLevel the error level correction for the barcode
1002     */
1003    public void setErrorLevel(int errorLevel) {
1004        this.errorLevel = errorLevel;
1005    }
1006
1007    /** Gets the bytes that form the barcode. This bytes should
1008     * be interpreted in the codepage Cp437.
1009     * @return the bytes that form the barcode
1010     */
1011    public byte[] getText() {
1012        return this.text;
1013    }
1014
1015    /** Sets the bytes that form the barcode. This bytes should
1016     * be interpreted in the codepage Cp437.
1017     * @param text the bytes that form the barcode
1018     */
1019    public void setText(byte[] text) {
1020        this.text = text;
1021    }
1022
1023    /** Sets the text that will form the barcode. This text is converted
1024     * to bytes using the encoding Cp437.
1025     * @param s the text that will form the barcode
1026     */
1027    public void setText(String s) {
1028        this.text = PdfEncodings.convertToBytes(s, "cp437");
1029    }
1030
1031    /** Gets the options to generate the barcode.
1032     * @return the options to generate the barcode
1033     */
1034    public int getOptions() {
1035        return this.options;
1036    }
1037
1038    /** Sets the options to generate the barcode. This can be all
1039     * the <CODE>PDF417_*</CODE> constants.
1040     * @param options the options to generate the barcode
1041     */
1042    public void setOptions(int options) {
1043        this.options = options;
1044    }
1045
1046    /** Gets the barcode aspect ratio.
1047     * @return the barcode aspect ratio
1048     */
1049    public float getAspectRatio() {
1050        return this.aspectRatio;
1051    }
1052
1053    /** Sets the barcode aspect ratio. A ratio or 0.5 will make the
1054     * barcode width twice as large as the height.
1055     * @param aspectRatio the barcode aspect ratio
1056     */
1057    public void setAspectRatio(float aspectRatio) {
1058        this.aspectRatio = aspectRatio;
1059    }
1060
1061    /** Gets the Y pixel height relative to X.
1062     * @return the Y pixel height relative to X
1063     */
1064    public float getYHeight() {
1065        return this.yHeight;
1066    }
1067
1068    /** Sets the Y pixel height relative to X. It is usually 3.
1069     * @param yHeight the Y pixel height relative to X
1070     */
1071    public void setYHeight(float yHeight) {
1072        this.yHeight = yHeight;
1073    }
1074
1075    protected static final int START_PATTERN = 0x1fea8;
1076    protected static final int STOP_PATTERN = 0x3fa29;
1077    protected static final int START_CODE_SIZE = 17;
1078    protected static final int STOP_SIZE = 18;
1079    protected static final int MOD = 929;
1080    protected static final int ALPHA = 0x10000;
1081    protected static final int LOWER = 0x20000;
1082    protected static final int MIXED = 0x40000;
1083    protected static final int PUNCTUATION = 0x80000;
1084    protected static final int ISBYTE = 0x100000;
1085    protected static final int BYTESHIFT = 913;
1086    protected static final int PL = 25;
1087    protected static final int LL = 27;
1088    protected static final int AS = 27;
1089    protected static final int ML = 28;
1090    protected static final int AL = 28;
1091    protected static final int PS = 29;
1092    protected static final int PAL = 29;
1093    protected static final int SPACE = 26;
1094    protected static final int TEXT_MODE = 900;
1095    protected static final int BYTE_MODE_6 = 924;
1096    protected static final int BYTE_MODE = 901;
1097    protected static final int NUMERIC_MODE = 902;
1098    protected static final int ABSOLUTE_MAX_TEXT_SIZE = 5420;
1099    protected static final int MAX_DATA_CODEWORDS = 926;
1100    protected static final int MACRO_SEGMENT_ID=928;
1101    protected static final int MACRO_LAST_SEGMENT=922;
1102
1103    private static final String MIXED_SET = "0123456789&\r\t,:#-.$/+%*=^";
1104    private static final String PUNCTUATION_SET = ";<>@[\\]_`~!\r\t,:\n-.$/\"|*()?{}'";
1105
1106    private static final int CLUSTERS[][] =
1107    {{
1108         0x1d5c0, 0x1eaf0, 0x1f57c, 0x1d4e0, 0x1ea78, 0x1f53e, 0x1a8c0, 0x1d470,
1109         0x1a860, 0x15040, 0x1a830, 0x15020, 0x1adc0, 0x1d6f0, 0x1eb7c, 0x1ace0,
1110         0x1d678, 0x1eb3e, 0x158c0, 0x1ac70, 0x15860, 0x15dc0, 0x1aef0, 0x1d77c,
1111         0x15ce0, 0x1ae78, 0x1d73e, 0x15c70, 0x1ae3c, 0x15ef0, 0x1af7c, 0x15e78,
1112         0x1af3e, 0x15f7c, 0x1f5fa, 0x1d2e0, 0x1e978, 0x1f4be, 0x1a4c0, 0x1d270,
1113         0x1e93c, 0x1a460, 0x1d238, 0x14840, 0x1a430, 0x1d21c, 0x14820, 0x1a418,
1114         0x14810, 0x1a6e0, 0x1d378, 0x1e9be, 0x14cc0, 0x1a670, 0x1d33c, 0x14c60,
1115         0x1a638, 0x1d31e, 0x14c30, 0x1a61c, 0x14ee0, 0x1a778, 0x1d3be, 0x14e70,
1116         0x1a73c, 0x14e38, 0x1a71e, 0x14f78, 0x1a7be, 0x14f3c, 0x14f1e, 0x1a2c0,
1117         0x1d170, 0x1e8bc, 0x1a260, 0x1d138, 0x1e89e, 0x14440, 0x1a230, 0x1d11c,
1118         0x14420, 0x1a218, 0x14410, 0x14408, 0x146c0, 0x1a370, 0x1d1bc, 0x14660,
1119         0x1a338, 0x1d19e, 0x14630, 0x1a31c, 0x14618, 0x1460c, 0x14770, 0x1a3bc,
1120         0x14738, 0x1a39e, 0x1471c, 0x147bc, 0x1a160, 0x1d0b8, 0x1e85e, 0x14240,
1121         0x1a130, 0x1d09c, 0x14220, 0x1a118, 0x1d08e, 0x14210, 0x1a10c, 0x14208,
1122         0x1a106, 0x14360, 0x1a1b8, 0x1d0de, 0x14330, 0x1a19c, 0x14318, 0x1a18e,
1123         0x1430c, 0x14306, 0x1a1de, 0x1438e, 0x14140, 0x1a0b0, 0x1d05c, 0x14120,
1124         0x1a098, 0x1d04e, 0x14110, 0x1a08c, 0x14108, 0x1a086, 0x14104, 0x141b0,
1125         0x14198, 0x1418c, 0x140a0, 0x1d02e, 0x1a04c, 0x1a046, 0x14082, 0x1cae0,
1126         0x1e578, 0x1f2be, 0x194c0, 0x1ca70, 0x1e53c, 0x19460, 0x1ca38, 0x1e51e,
1127         0x12840, 0x19430, 0x12820, 0x196e0, 0x1cb78, 0x1e5be, 0x12cc0, 0x19670,
1128         0x1cb3c, 0x12c60, 0x19638, 0x12c30, 0x12c18, 0x12ee0, 0x19778, 0x1cbbe,
1129         0x12e70, 0x1973c, 0x12e38, 0x12e1c, 0x12f78, 0x197be, 0x12f3c, 0x12fbe,
1130         0x1dac0, 0x1ed70, 0x1f6bc, 0x1da60, 0x1ed38, 0x1f69e, 0x1b440, 0x1da30,
1131         0x1ed1c, 0x1b420, 0x1da18, 0x1ed0e, 0x1b410, 0x1da0c, 0x192c0, 0x1c970,
1132         0x1e4bc, 0x1b6c0, 0x19260, 0x1c938, 0x1e49e, 0x1b660, 0x1db38, 0x1ed9e,
1133         0x16c40, 0x12420, 0x19218, 0x1c90e, 0x16c20, 0x1b618, 0x16c10, 0x126c0,
1134         0x19370, 0x1c9bc, 0x16ec0, 0x12660, 0x19338, 0x1c99e, 0x16e60, 0x1b738,
1135         0x1db9e, 0x16e30, 0x12618, 0x16e18, 0x12770, 0x193bc, 0x16f70, 0x12738,
1136         0x1939e, 0x16f38, 0x1b79e, 0x16f1c, 0x127bc, 0x16fbc, 0x1279e, 0x16f9e,
1137         0x1d960, 0x1ecb8, 0x1f65e, 0x1b240, 0x1d930, 0x1ec9c, 0x1b220, 0x1d918,
1138         0x1ec8e, 0x1b210, 0x1d90c, 0x1b208, 0x1b204, 0x19160, 0x1c8b8, 0x1e45e,
1139         0x1b360, 0x19130, 0x1c89c, 0x16640, 0x12220, 0x1d99c, 0x1c88e, 0x16620,
1140         0x12210, 0x1910c, 0x16610, 0x1b30c, 0x19106, 0x12204, 0x12360, 0x191b8,
1141         0x1c8de, 0x16760, 0x12330, 0x1919c, 0x16730, 0x1b39c, 0x1918e, 0x16718,
1142         0x1230c, 0x12306, 0x123b8, 0x191de, 0x167b8, 0x1239c, 0x1679c, 0x1238e,
1143         0x1678e, 0x167de, 0x1b140, 0x1d8b0, 0x1ec5c, 0x1b120, 0x1d898, 0x1ec4e,
1144         0x1b110, 0x1d88c, 0x1b108, 0x1d886, 0x1b104, 0x1b102, 0x12140, 0x190b0,
1145         0x1c85c, 0x16340, 0x12120, 0x19098, 0x1c84e, 0x16320, 0x1b198, 0x1d8ce,
1146         0x16310, 0x12108, 0x19086, 0x16308, 0x1b186, 0x16304, 0x121b0, 0x190dc,
1147         0x163b0, 0x12198, 0x190ce, 0x16398, 0x1b1ce, 0x1638c, 0x12186, 0x16386,
1148         0x163dc, 0x163ce, 0x1b0a0, 0x1d858, 0x1ec2e, 0x1b090, 0x1d84c, 0x1b088,
1149         0x1d846, 0x1b084, 0x1b082, 0x120a0, 0x19058, 0x1c82e, 0x161a0, 0x12090,
1150         0x1904c, 0x16190, 0x1b0cc, 0x19046, 0x16188, 0x12084, 0x16184, 0x12082,
1151         0x120d8, 0x161d8, 0x161cc, 0x161c6, 0x1d82c, 0x1d826, 0x1b042, 0x1902c,
1152         0x12048, 0x160c8, 0x160c4, 0x160c2, 0x18ac0, 0x1c570, 0x1e2bc, 0x18a60,
1153         0x1c538, 0x11440, 0x18a30, 0x1c51c, 0x11420, 0x18a18, 0x11410, 0x11408,
1154         0x116c0, 0x18b70, 0x1c5bc, 0x11660, 0x18b38, 0x1c59e, 0x11630, 0x18b1c,
1155         0x11618, 0x1160c, 0x11770, 0x18bbc, 0x11738, 0x18b9e, 0x1171c, 0x117bc,
1156         0x1179e, 0x1cd60, 0x1e6b8, 0x1f35e, 0x19a40, 0x1cd30, 0x1e69c, 0x19a20,
1157         0x1cd18, 0x1e68e, 0x19a10, 0x1cd0c, 0x19a08, 0x1cd06, 0x18960, 0x1c4b8,
1158         0x1e25e, 0x19b60, 0x18930, 0x1c49c, 0x13640, 0x11220, 0x1cd9c, 0x1c48e,
1159         0x13620, 0x19b18, 0x1890c, 0x13610, 0x11208, 0x13608, 0x11360, 0x189b8,
1160         0x1c4de, 0x13760, 0x11330, 0x1cdde, 0x13730, 0x19b9c, 0x1898e, 0x13718,
1161         0x1130c, 0x1370c, 0x113b8, 0x189de, 0x137b8, 0x1139c, 0x1379c, 0x1138e,
1162         0x113de, 0x137de, 0x1dd40, 0x1eeb0, 0x1f75c, 0x1dd20, 0x1ee98, 0x1f74e,
1163         0x1dd10, 0x1ee8c, 0x1dd08, 0x1ee86, 0x1dd04, 0x19940, 0x1ccb0, 0x1e65c,
1164         0x1bb40, 0x19920, 0x1eedc, 0x1e64e, 0x1bb20, 0x1dd98, 0x1eece, 0x1bb10,
1165         0x19908, 0x1cc86, 0x1bb08, 0x1dd86, 0x19902, 0x11140, 0x188b0, 0x1c45c,
1166         0x13340, 0x11120, 0x18898, 0x1c44e, 0x17740, 0x13320, 0x19998, 0x1ccce,
1167         0x17720, 0x1bb98, 0x1ddce, 0x18886, 0x17710, 0x13308, 0x19986, 0x17708,
1168         0x11102, 0x111b0, 0x188dc, 0x133b0, 0x11198, 0x188ce, 0x177b0, 0x13398,
1169         0x199ce, 0x17798, 0x1bbce, 0x11186, 0x13386, 0x111dc, 0x133dc, 0x111ce,
1170         0x177dc, 0x133ce, 0x1dca0, 0x1ee58, 0x1f72e, 0x1dc90, 0x1ee4c, 0x1dc88,
1171         0x1ee46, 0x1dc84, 0x1dc82, 0x198a0, 0x1cc58, 0x1e62e, 0x1b9a0, 0x19890,
1172         0x1ee6e, 0x1b990, 0x1dccc, 0x1cc46, 0x1b988, 0x19884, 0x1b984, 0x19882,
1173         0x1b982, 0x110a0, 0x18858, 0x1c42e, 0x131a0, 0x11090, 0x1884c, 0x173a0,
1174         0x13190, 0x198cc, 0x18846, 0x17390, 0x1b9cc, 0x11084, 0x17388, 0x13184,
1175         0x11082, 0x13182, 0x110d8, 0x1886e, 0x131d8, 0x110cc, 0x173d8, 0x131cc,
1176         0x110c6, 0x173cc, 0x131c6, 0x110ee, 0x173ee, 0x1dc50, 0x1ee2c, 0x1dc48,
1177         0x1ee26, 0x1dc44, 0x1dc42, 0x19850, 0x1cc2c, 0x1b8d0, 0x19848, 0x1cc26,
1178         0x1b8c8, 0x1dc66, 0x1b8c4, 0x19842, 0x1b8c2, 0x11050, 0x1882c, 0x130d0,
1179         0x11048, 0x18826, 0x171d0, 0x130c8, 0x19866, 0x171c8, 0x1b8e6, 0x11042,
1180         0x171c4, 0x130c2, 0x171c2, 0x130ec, 0x171ec, 0x171e6, 0x1ee16, 0x1dc22,
1181         0x1cc16, 0x19824, 0x19822, 0x11028, 0x13068, 0x170e8, 0x11022, 0x13062,
1182         0x18560, 0x10a40, 0x18530, 0x10a20, 0x18518, 0x1c28e, 0x10a10, 0x1850c,
1183         0x10a08, 0x18506, 0x10b60, 0x185b8, 0x1c2de, 0x10b30, 0x1859c, 0x10b18,
1184         0x1858e, 0x10b0c, 0x10b06, 0x10bb8, 0x185de, 0x10b9c, 0x10b8e, 0x10bde,
1185         0x18d40, 0x1c6b0, 0x1e35c, 0x18d20, 0x1c698, 0x18d10, 0x1c68c, 0x18d08,
1186         0x1c686, 0x18d04, 0x10940, 0x184b0, 0x1c25c, 0x11b40, 0x10920, 0x1c6dc,
1187         0x1c24e, 0x11b20, 0x18d98, 0x1c6ce, 0x11b10, 0x10908, 0x18486, 0x11b08,
1188         0x18d86, 0x10902, 0x109b0, 0x184dc, 0x11bb0, 0x10998, 0x184ce, 0x11b98,
1189         0x18dce, 0x11b8c, 0x10986, 0x109dc, 0x11bdc, 0x109ce, 0x11bce, 0x1cea0,
1190         0x1e758, 0x1f3ae, 0x1ce90, 0x1e74c, 0x1ce88, 0x1e746, 0x1ce84, 0x1ce82,
1191         0x18ca0, 0x1c658, 0x19da0, 0x18c90, 0x1c64c, 0x19d90, 0x1cecc, 0x1c646,
1192         0x19d88, 0x18c84, 0x19d84, 0x18c82, 0x19d82, 0x108a0, 0x18458, 0x119a0,
1193         0x10890, 0x1c66e, 0x13ba0, 0x11990, 0x18ccc, 0x18446, 0x13b90, 0x19dcc,
1194         0x10884, 0x13b88, 0x11984, 0x10882, 0x11982, 0x108d8, 0x1846e, 0x119d8,
1195         0x108cc, 0x13bd8, 0x119cc, 0x108c6, 0x13bcc, 0x119c6, 0x108ee, 0x119ee,
1196         0x13bee, 0x1ef50, 0x1f7ac, 0x1ef48, 0x1f7a6, 0x1ef44, 0x1ef42, 0x1ce50,
1197         0x1e72c, 0x1ded0, 0x1ef6c, 0x1e726, 0x1dec8, 0x1ef66, 0x1dec4, 0x1ce42,
1198         0x1dec2, 0x18c50, 0x1c62c, 0x19cd0, 0x18c48, 0x1c626, 0x1bdd0, 0x19cc8,
1199         0x1ce66, 0x1bdc8, 0x1dee6, 0x18c42, 0x1bdc4, 0x19cc2, 0x1bdc2, 0x10850,
1200         0x1842c, 0x118d0, 0x10848, 0x18426, 0x139d0, 0x118c8, 0x18c66, 0x17bd0,
1201         0x139c8, 0x19ce6, 0x10842, 0x17bc8, 0x1bde6, 0x118c2, 0x17bc4, 0x1086c,
1202         0x118ec, 0x10866, 0x139ec, 0x118e6, 0x17bec, 0x139e6, 0x17be6, 0x1ef28,
1203         0x1f796, 0x1ef24, 0x1ef22, 0x1ce28, 0x1e716, 0x1de68, 0x1ef36, 0x1de64,
1204         0x1ce22, 0x1de62, 0x18c28, 0x1c616, 0x19c68, 0x18c24, 0x1bce8, 0x19c64,
1205         0x18c22, 0x1bce4, 0x19c62, 0x1bce2, 0x10828, 0x18416, 0x11868, 0x18c36,
1206         0x138e8, 0x11864, 0x10822, 0x179e8, 0x138e4, 0x11862, 0x179e4, 0x138e2,
1207         0x179e2, 0x11876, 0x179f6, 0x1ef12, 0x1de34, 0x1de32, 0x19c34, 0x1bc74,
1208         0x1bc72, 0x11834, 0x13874, 0x178f4, 0x178f2, 0x10540, 0x10520, 0x18298,
1209         0x10510, 0x10508, 0x10504, 0x105b0, 0x10598, 0x1058c, 0x10586, 0x105dc,
1210         0x105ce, 0x186a0, 0x18690, 0x1c34c, 0x18688, 0x1c346, 0x18684, 0x18682,
1211         0x104a0, 0x18258, 0x10da0, 0x186d8, 0x1824c, 0x10d90, 0x186cc, 0x10d88,
1212         0x186c6, 0x10d84, 0x10482, 0x10d82, 0x104d8, 0x1826e, 0x10dd8, 0x186ee,
1213         0x10dcc, 0x104c6, 0x10dc6, 0x104ee, 0x10dee, 0x1c750, 0x1c748, 0x1c744,
1214         0x1c742, 0x18650, 0x18ed0, 0x1c76c, 0x1c326, 0x18ec8, 0x1c766, 0x18ec4,
1215         0x18642, 0x18ec2, 0x10450, 0x10cd0, 0x10448, 0x18226, 0x11dd0, 0x10cc8,
1216         0x10444, 0x11dc8, 0x10cc4, 0x10442, 0x11dc4, 0x10cc2, 0x1046c, 0x10cec,
1217         0x10466, 0x11dec, 0x10ce6, 0x11de6, 0x1e7a8, 0x1e7a4, 0x1e7a2, 0x1c728,
1218         0x1cf68, 0x1e7b6, 0x1cf64, 0x1c722, 0x1cf62, 0x18628, 0x1c316, 0x18e68,
1219         0x1c736, 0x19ee8, 0x18e64, 0x18622, 0x19ee4, 0x18e62, 0x19ee2, 0x10428,
1220         0x18216, 0x10c68, 0x18636, 0x11ce8, 0x10c64, 0x10422, 0x13de8, 0x11ce4,
1221         0x10c62, 0x13de4, 0x11ce2, 0x10436, 0x10c76, 0x11cf6, 0x13df6, 0x1f7d4,
1222         0x1f7d2, 0x1e794, 0x1efb4, 0x1e792, 0x1efb2, 0x1c714, 0x1cf34, 0x1c712,
1223         0x1df74, 0x1cf32, 0x1df72, 0x18614, 0x18e34, 0x18612, 0x19e74, 0x18e32,
1224         0x1bef4
1225    }, {
1226        0x1f560, 0x1fab8, 0x1ea40, 0x1f530, 0x1fa9c, 0x1ea20, 0x1f518, 0x1fa8e,
1227        0x1ea10, 0x1f50c, 0x1ea08, 0x1f506, 0x1ea04, 0x1eb60, 0x1f5b8, 0x1fade,
1228        0x1d640, 0x1eb30, 0x1f59c, 0x1d620, 0x1eb18, 0x1f58e, 0x1d610, 0x1eb0c,
1229        0x1d608, 0x1eb06, 0x1d604, 0x1d760, 0x1ebb8, 0x1f5de, 0x1ae40, 0x1d730,
1230        0x1eb9c, 0x1ae20, 0x1d718, 0x1eb8e, 0x1ae10, 0x1d70c, 0x1ae08, 0x1d706,
1231        0x1ae04, 0x1af60, 0x1d7b8, 0x1ebde, 0x15e40, 0x1af30, 0x1d79c, 0x15e20,
1232        0x1af18, 0x1d78e, 0x15e10, 0x1af0c, 0x15e08, 0x1af06, 0x15f60, 0x1afb8,
1233        0x1d7de, 0x15f30, 0x1af9c, 0x15f18, 0x1af8e, 0x15f0c, 0x15fb8, 0x1afde,
1234        0x15f9c, 0x15f8e, 0x1e940, 0x1f4b0, 0x1fa5c, 0x1e920, 0x1f498, 0x1fa4e,
1235        0x1e910, 0x1f48c, 0x1e908, 0x1f486, 0x1e904, 0x1e902, 0x1d340, 0x1e9b0,
1236        0x1f4dc, 0x1d320, 0x1e998, 0x1f4ce, 0x1d310, 0x1e98c, 0x1d308, 0x1e986,
1237        0x1d304, 0x1d302, 0x1a740, 0x1d3b0, 0x1e9dc, 0x1a720, 0x1d398, 0x1e9ce,
1238        0x1a710, 0x1d38c, 0x1a708, 0x1d386, 0x1a704, 0x1a702, 0x14f40, 0x1a7b0,
1239        0x1d3dc, 0x14f20, 0x1a798, 0x1d3ce, 0x14f10, 0x1a78c, 0x14f08, 0x1a786,
1240        0x14f04, 0x14fb0, 0x1a7dc, 0x14f98, 0x1a7ce, 0x14f8c, 0x14f86, 0x14fdc,
1241        0x14fce, 0x1e8a0, 0x1f458, 0x1fa2e, 0x1e890, 0x1f44c, 0x1e888, 0x1f446,
1242        0x1e884, 0x1e882, 0x1d1a0, 0x1e8d8, 0x1f46e, 0x1d190, 0x1e8cc, 0x1d188,
1243        0x1e8c6, 0x1d184, 0x1d182, 0x1a3a0, 0x1d1d8, 0x1e8ee, 0x1a390, 0x1d1cc,
1244        0x1a388, 0x1d1c6, 0x1a384, 0x1a382, 0x147a0, 0x1a3d8, 0x1d1ee, 0x14790,
1245        0x1a3cc, 0x14788, 0x1a3c6, 0x14784, 0x14782, 0x147d8, 0x1a3ee, 0x147cc,
1246        0x147c6, 0x147ee, 0x1e850, 0x1f42c, 0x1e848, 0x1f426, 0x1e844, 0x1e842,
1247        0x1d0d0, 0x1e86c, 0x1d0c8, 0x1e866, 0x1d0c4, 0x1d0c2, 0x1a1d0, 0x1d0ec,
1248        0x1a1c8, 0x1d0e6, 0x1a1c4, 0x1a1c2, 0x143d0, 0x1a1ec, 0x143c8, 0x1a1e6,
1249        0x143c4, 0x143c2, 0x143ec, 0x143e6, 0x1e828, 0x1f416, 0x1e824, 0x1e822,
1250        0x1d068, 0x1e836, 0x1d064, 0x1d062, 0x1a0e8, 0x1d076, 0x1a0e4, 0x1a0e2,
1251        0x141e8, 0x1a0f6, 0x141e4, 0x141e2, 0x1e814, 0x1e812, 0x1d034, 0x1d032,
1252        0x1a074, 0x1a072, 0x1e540, 0x1f2b0, 0x1f95c, 0x1e520, 0x1f298, 0x1f94e,
1253        0x1e510, 0x1f28c, 0x1e508, 0x1f286, 0x1e504, 0x1e502, 0x1cb40, 0x1e5b0,
1254        0x1f2dc, 0x1cb20, 0x1e598, 0x1f2ce, 0x1cb10, 0x1e58c, 0x1cb08, 0x1e586,
1255        0x1cb04, 0x1cb02, 0x19740, 0x1cbb0, 0x1e5dc, 0x19720, 0x1cb98, 0x1e5ce,
1256        0x19710, 0x1cb8c, 0x19708, 0x1cb86, 0x19704, 0x19702, 0x12f40, 0x197b0,
1257        0x1cbdc, 0x12f20, 0x19798, 0x1cbce, 0x12f10, 0x1978c, 0x12f08, 0x19786,
1258        0x12f04, 0x12fb0, 0x197dc, 0x12f98, 0x197ce, 0x12f8c, 0x12f86, 0x12fdc,
1259        0x12fce, 0x1f6a0, 0x1fb58, 0x16bf0, 0x1f690, 0x1fb4c, 0x169f8, 0x1f688,
1260        0x1fb46, 0x168fc, 0x1f684, 0x1f682, 0x1e4a0, 0x1f258, 0x1f92e, 0x1eda0,
1261        0x1e490, 0x1fb6e, 0x1ed90, 0x1f6cc, 0x1f246, 0x1ed88, 0x1e484, 0x1ed84,
1262        0x1e482, 0x1ed82, 0x1c9a0, 0x1e4d8, 0x1f26e, 0x1dba0, 0x1c990, 0x1e4cc,
1263        0x1db90, 0x1edcc, 0x1e4c6, 0x1db88, 0x1c984, 0x1db84, 0x1c982, 0x1db82,
1264        0x193a0, 0x1c9d8, 0x1e4ee, 0x1b7a0, 0x19390, 0x1c9cc, 0x1b790, 0x1dbcc,
1265        0x1c9c6, 0x1b788, 0x19384, 0x1b784, 0x19382, 0x1b782, 0x127a0, 0x193d8,
1266        0x1c9ee, 0x16fa0, 0x12790, 0x193cc, 0x16f90, 0x1b7cc, 0x193c6, 0x16f88,
1267        0x12784, 0x16f84, 0x12782, 0x127d8, 0x193ee, 0x16fd8, 0x127cc, 0x16fcc,
1268        0x127c6, 0x16fc6, 0x127ee, 0x1f650, 0x1fb2c, 0x165f8, 0x1f648, 0x1fb26,
1269        0x164fc, 0x1f644, 0x1647e, 0x1f642, 0x1e450, 0x1f22c, 0x1ecd0, 0x1e448,
1270        0x1f226, 0x1ecc8, 0x1f666, 0x1ecc4, 0x1e442, 0x1ecc2, 0x1c8d0, 0x1e46c,
1271        0x1d9d0, 0x1c8c8, 0x1e466, 0x1d9c8, 0x1ece6, 0x1d9c4, 0x1c8c2, 0x1d9c2,
1272        0x191d0, 0x1c8ec, 0x1b3d0, 0x191c8, 0x1c8e6, 0x1b3c8, 0x1d9e6, 0x1b3c4,
1273        0x191c2, 0x1b3c2, 0x123d0, 0x191ec, 0x167d0, 0x123c8, 0x191e6, 0x167c8,
1274        0x1b3e6, 0x167c4, 0x123c2, 0x167c2, 0x123ec, 0x167ec, 0x123e6, 0x167e6,
1275        0x1f628, 0x1fb16, 0x162fc, 0x1f624, 0x1627e, 0x1f622, 0x1e428, 0x1f216,
1276        0x1ec68, 0x1f636, 0x1ec64, 0x1e422, 0x1ec62, 0x1c868, 0x1e436, 0x1d8e8,
1277        0x1c864, 0x1d8e4, 0x1c862, 0x1d8e2, 0x190e8, 0x1c876, 0x1b1e8, 0x1d8f6,
1278        0x1b1e4, 0x190e2, 0x1b1e2, 0x121e8, 0x190f6, 0x163e8, 0x121e4, 0x163e4,
1279        0x121e2, 0x163e2, 0x121f6, 0x163f6, 0x1f614, 0x1617e, 0x1f612, 0x1e414,
1280        0x1ec34, 0x1e412, 0x1ec32, 0x1c834, 0x1d874, 0x1c832, 0x1d872, 0x19074,
1281        0x1b0f4, 0x19072, 0x1b0f2, 0x120f4, 0x161f4, 0x120f2, 0x161f2, 0x1f60a,
1282        0x1e40a, 0x1ec1a, 0x1c81a, 0x1d83a, 0x1903a, 0x1b07a, 0x1e2a0, 0x1f158,
1283        0x1f8ae, 0x1e290, 0x1f14c, 0x1e288, 0x1f146, 0x1e284, 0x1e282, 0x1c5a0,
1284        0x1e2d8, 0x1f16e, 0x1c590, 0x1e2cc, 0x1c588, 0x1e2c6, 0x1c584, 0x1c582,
1285        0x18ba0, 0x1c5d8, 0x1e2ee, 0x18b90, 0x1c5cc, 0x18b88, 0x1c5c6, 0x18b84,
1286        0x18b82, 0x117a0, 0x18bd8, 0x1c5ee, 0x11790, 0x18bcc, 0x11788, 0x18bc6,
1287        0x11784, 0x11782, 0x117d8, 0x18bee, 0x117cc, 0x117c6, 0x117ee, 0x1f350,
1288        0x1f9ac, 0x135f8, 0x1f348, 0x1f9a6, 0x134fc, 0x1f344, 0x1347e, 0x1f342,
1289        0x1e250, 0x1f12c, 0x1e6d0, 0x1e248, 0x1f126, 0x1e6c8, 0x1f366, 0x1e6c4,
1290        0x1e242, 0x1e6c2, 0x1c4d0, 0x1e26c, 0x1cdd0, 0x1c4c8, 0x1e266, 0x1cdc8,
1291        0x1e6e6, 0x1cdc4, 0x1c4c2, 0x1cdc2, 0x189d0, 0x1c4ec, 0x19bd0, 0x189c8,
1292        0x1c4e6, 0x19bc8, 0x1cde6, 0x19bc4, 0x189c2, 0x19bc2, 0x113d0, 0x189ec,
1293        0x137d0, 0x113c8, 0x189e6, 0x137c8, 0x19be6, 0x137c4, 0x113c2, 0x137c2,
1294        0x113ec, 0x137ec, 0x113e6, 0x137e6, 0x1fba8, 0x175f0, 0x1bafc, 0x1fba4,
1295        0x174f8, 0x1ba7e, 0x1fba2, 0x1747c, 0x1743e, 0x1f328, 0x1f996, 0x132fc,
1296        0x1f768, 0x1fbb6, 0x176fc, 0x1327e, 0x1f764, 0x1f322, 0x1767e, 0x1f762,
1297        0x1e228, 0x1f116, 0x1e668, 0x1e224, 0x1eee8, 0x1f776, 0x1e222, 0x1eee4,
1298        0x1e662, 0x1eee2, 0x1c468, 0x1e236, 0x1cce8, 0x1c464, 0x1dde8, 0x1cce4,
1299        0x1c462, 0x1dde4, 0x1cce2, 0x1dde2, 0x188e8, 0x1c476, 0x199e8, 0x188e4,
1300        0x1bbe8, 0x199e4, 0x188e2, 0x1bbe4, 0x199e2, 0x1bbe2, 0x111e8, 0x188f6,
1301        0x133e8, 0x111e4, 0x177e8, 0x133e4, 0x111e2, 0x177e4, 0x133e2, 0x177e2,
1302        0x111f6, 0x133f6, 0x1fb94, 0x172f8, 0x1b97e, 0x1fb92, 0x1727c, 0x1723e,
1303        0x1f314, 0x1317e, 0x1f734, 0x1f312, 0x1737e, 0x1f732, 0x1e214, 0x1e634,
1304        0x1e212, 0x1ee74, 0x1e632, 0x1ee72, 0x1c434, 0x1cc74, 0x1c432, 0x1dcf4,
1305        0x1cc72, 0x1dcf2, 0x18874, 0x198f4, 0x18872, 0x1b9f4, 0x198f2, 0x1b9f2,
1306        0x110f4, 0x131f4, 0x110f2, 0x173f4, 0x131f2, 0x173f2, 0x1fb8a, 0x1717c,
1307        0x1713e, 0x1f30a, 0x1f71a, 0x1e20a, 0x1e61a, 0x1ee3a, 0x1c41a, 0x1cc3a,
1308        0x1dc7a, 0x1883a, 0x1987a, 0x1b8fa, 0x1107a, 0x130fa, 0x171fa, 0x170be,
1309        0x1e150, 0x1f0ac, 0x1e148, 0x1f0a6, 0x1e144, 0x1e142, 0x1c2d0, 0x1e16c,
1310        0x1c2c8, 0x1e166, 0x1c2c4, 0x1c2c2, 0x185d0, 0x1c2ec, 0x185c8, 0x1c2e6,
1311        0x185c4, 0x185c2, 0x10bd0, 0x185ec, 0x10bc8, 0x185e6, 0x10bc4, 0x10bc2,
1312        0x10bec, 0x10be6, 0x1f1a8, 0x1f8d6, 0x11afc, 0x1f1a4, 0x11a7e, 0x1f1a2,
1313        0x1e128, 0x1f096, 0x1e368, 0x1e124, 0x1e364, 0x1e122, 0x1e362, 0x1c268,
1314        0x1e136, 0x1c6e8, 0x1c264, 0x1c6e4, 0x1c262, 0x1c6e2, 0x184e8, 0x1c276,
1315        0x18de8, 0x184e4, 0x18de4, 0x184e2, 0x18de2, 0x109e8, 0x184f6, 0x11be8,
1316        0x109e4, 0x11be4, 0x109e2, 0x11be2, 0x109f6, 0x11bf6, 0x1f9d4, 0x13af8,
1317        0x19d7e, 0x1f9d2, 0x13a7c, 0x13a3e, 0x1f194, 0x1197e, 0x1f3b4, 0x1f192,
1318        0x13b7e, 0x1f3b2, 0x1e114, 0x1e334, 0x1e112, 0x1e774, 0x1e332, 0x1e772,
1319        0x1c234, 0x1c674, 0x1c232, 0x1cef4, 0x1c672, 0x1cef2, 0x18474, 0x18cf4,
1320        0x18472, 0x19df4, 0x18cf2, 0x19df2, 0x108f4, 0x119f4, 0x108f2, 0x13bf4,
1321        0x119f2, 0x13bf2, 0x17af0, 0x1bd7c, 0x17a78, 0x1bd3e, 0x17a3c, 0x17a1e,
1322        0x1f9ca, 0x1397c, 0x1fbda, 0x17b7c, 0x1393e, 0x17b3e, 0x1f18a, 0x1f39a,
1323        0x1f7ba, 0x1e10a, 0x1e31a, 0x1e73a, 0x1ef7a, 0x1c21a, 0x1c63a, 0x1ce7a,
1324        0x1defa, 0x1843a, 0x18c7a, 0x19cfa, 0x1bdfa, 0x1087a, 0x118fa, 0x139fa,
1325        0x17978, 0x1bcbe, 0x1793c, 0x1791e, 0x138be, 0x179be, 0x178bc, 0x1789e,
1326        0x1785e, 0x1e0a8, 0x1e0a4, 0x1e0a2, 0x1c168, 0x1e0b6, 0x1c164, 0x1c162,
1327        0x182e8, 0x1c176, 0x182e4, 0x182e2, 0x105e8, 0x182f6, 0x105e4, 0x105e2,
1328        0x105f6, 0x1f0d4, 0x10d7e, 0x1f0d2, 0x1e094, 0x1e1b4, 0x1e092, 0x1e1b2,
1329        0x1c134, 0x1c374, 0x1c132, 0x1c372, 0x18274, 0x186f4, 0x18272, 0x186f2,
1330        0x104f4, 0x10df4, 0x104f2, 0x10df2, 0x1f8ea, 0x11d7c, 0x11d3e, 0x1f0ca,
1331        0x1f1da, 0x1e08a, 0x1e19a, 0x1e3ba, 0x1c11a, 0x1c33a, 0x1c77a, 0x1823a,
1332        0x1867a, 0x18efa, 0x1047a, 0x10cfa, 0x11dfa, 0x13d78, 0x19ebe, 0x13d3c,
1333        0x13d1e, 0x11cbe, 0x13dbe, 0x17d70, 0x1bebc, 0x17d38, 0x1be9e, 0x17d1c,
1334        0x17d0e, 0x13cbc, 0x17dbc, 0x13c9e, 0x17d9e, 0x17cb8, 0x1be5e, 0x17c9c,
1335        0x17c8e, 0x13c5e, 0x17cde, 0x17c5c, 0x17c4e, 0x17c2e, 0x1c0b4, 0x1c0b2,
1336        0x18174, 0x18172, 0x102f4, 0x102f2, 0x1e0da, 0x1c09a, 0x1c1ba, 0x1813a,
1337        0x1837a, 0x1027a, 0x106fa, 0x10ebe, 0x11ebc, 0x11e9e, 0x13eb8, 0x19f5e,
1338        0x13e9c, 0x13e8e, 0x11e5e, 0x13ede, 0x17eb0, 0x1bf5c, 0x17e98, 0x1bf4e,
1339        0x17e8c, 0x17e86, 0x13e5c, 0x17edc, 0x13e4e, 0x17ece, 0x17e58, 0x1bf2e,
1340        0x17e4c, 0x17e46, 0x13e2e, 0x17e6e, 0x17e2c, 0x17e26, 0x10f5e, 0x11f5c,
1341        0x11f4e, 0x13f58, 0x19fae, 0x13f4c, 0x13f46, 0x11f2e, 0x13f6e, 0x13f2c,
1342        0x13f26
1343    }, {
1344        0x1abe0, 0x1d5f8, 0x153c0, 0x1a9f0, 0x1d4fc, 0x151e0, 0x1a8f8, 0x1d47e,
1345        0x150f0, 0x1a87c, 0x15078, 0x1fad0, 0x15be0, 0x1adf8, 0x1fac8, 0x159f0,
1346        0x1acfc, 0x1fac4, 0x158f8, 0x1ac7e, 0x1fac2, 0x1587c, 0x1f5d0, 0x1faec,
1347        0x15df8, 0x1f5c8, 0x1fae6, 0x15cfc, 0x1f5c4, 0x15c7e, 0x1f5c2, 0x1ebd0,
1348        0x1f5ec, 0x1ebc8, 0x1f5e6, 0x1ebc4, 0x1ebc2, 0x1d7d0, 0x1ebec, 0x1d7c8,
1349        0x1ebe6, 0x1d7c4, 0x1d7c2, 0x1afd0, 0x1d7ec, 0x1afc8, 0x1d7e6, 0x1afc4,
1350        0x14bc0, 0x1a5f0, 0x1d2fc, 0x149e0, 0x1a4f8, 0x1d27e, 0x148f0, 0x1a47c,
1351        0x14878, 0x1a43e, 0x1483c, 0x1fa68, 0x14df0, 0x1a6fc, 0x1fa64, 0x14cf8,
1352        0x1a67e, 0x1fa62, 0x14c7c, 0x14c3e, 0x1f4e8, 0x1fa76, 0x14efc, 0x1f4e4,
1353        0x14e7e, 0x1f4e2, 0x1e9e8, 0x1f4f6, 0x1e9e4, 0x1e9e2, 0x1d3e8, 0x1e9f6,
1354        0x1d3e4, 0x1d3e2, 0x1a7e8, 0x1d3f6, 0x1a7e4, 0x1a7e2, 0x145e0, 0x1a2f8,
1355        0x1d17e, 0x144f0, 0x1a27c, 0x14478, 0x1a23e, 0x1443c, 0x1441e, 0x1fa34,
1356        0x146f8, 0x1a37e, 0x1fa32, 0x1467c, 0x1463e, 0x1f474, 0x1477e, 0x1f472,
1357        0x1e8f4, 0x1e8f2, 0x1d1f4, 0x1d1f2, 0x1a3f4, 0x1a3f2, 0x142f0, 0x1a17c,
1358        0x14278, 0x1a13e, 0x1423c, 0x1421e, 0x1fa1a, 0x1437c, 0x1433e, 0x1f43a,
1359        0x1e87a, 0x1d0fa, 0x14178, 0x1a0be, 0x1413c, 0x1411e, 0x141be, 0x140bc,
1360        0x1409e, 0x12bc0, 0x195f0, 0x1cafc, 0x129e0, 0x194f8, 0x1ca7e, 0x128f0,
1361        0x1947c, 0x12878, 0x1943e, 0x1283c, 0x1f968, 0x12df0, 0x196fc, 0x1f964,
1362        0x12cf8, 0x1967e, 0x1f962, 0x12c7c, 0x12c3e, 0x1f2e8, 0x1f976, 0x12efc,
1363        0x1f2e4, 0x12e7e, 0x1f2e2, 0x1e5e8, 0x1f2f6, 0x1e5e4, 0x1e5e2, 0x1cbe8,
1364        0x1e5f6, 0x1cbe4, 0x1cbe2, 0x197e8, 0x1cbf6, 0x197e4, 0x197e2, 0x1b5e0,
1365        0x1daf8, 0x1ed7e, 0x169c0, 0x1b4f0, 0x1da7c, 0x168e0, 0x1b478, 0x1da3e,
1366        0x16870, 0x1b43c, 0x16838, 0x1b41e, 0x1681c, 0x125e0, 0x192f8, 0x1c97e,
1367        0x16de0, 0x124f0, 0x1927c, 0x16cf0, 0x1b67c, 0x1923e, 0x16c78, 0x1243c,
1368        0x16c3c, 0x1241e, 0x16c1e, 0x1f934, 0x126f8, 0x1937e, 0x1fb74, 0x1f932,
1369        0x16ef8, 0x1267c, 0x1fb72, 0x16e7c, 0x1263e, 0x16e3e, 0x1f274, 0x1277e,
1370        0x1f6f4, 0x1f272, 0x16f7e, 0x1f6f2, 0x1e4f4, 0x1edf4, 0x1e4f2, 0x1edf2,
1371        0x1c9f4, 0x1dbf4, 0x1c9f2, 0x1dbf2, 0x193f4, 0x193f2, 0x165c0, 0x1b2f0,
1372        0x1d97c, 0x164e0, 0x1b278, 0x1d93e, 0x16470, 0x1b23c, 0x16438, 0x1b21e,
1373        0x1641c, 0x1640e, 0x122f0, 0x1917c, 0x166f0, 0x12278, 0x1913e, 0x16678,
1374        0x1b33e, 0x1663c, 0x1221e, 0x1661e, 0x1f91a, 0x1237c, 0x1fb3a, 0x1677c,
1375        0x1233e, 0x1673e, 0x1f23a, 0x1f67a, 0x1e47a, 0x1ecfa, 0x1c8fa, 0x1d9fa,
1376        0x191fa, 0x162e0, 0x1b178, 0x1d8be, 0x16270, 0x1b13c, 0x16238, 0x1b11e,
1377        0x1621c, 0x1620e, 0x12178, 0x190be, 0x16378, 0x1213c, 0x1633c, 0x1211e,
1378        0x1631e, 0x121be, 0x163be, 0x16170, 0x1b0bc, 0x16138, 0x1b09e, 0x1611c,
1379        0x1610e, 0x120bc, 0x161bc, 0x1209e, 0x1619e, 0x160b8, 0x1b05e, 0x1609c,
1380        0x1608e, 0x1205e, 0x160de, 0x1605c, 0x1604e, 0x115e0, 0x18af8, 0x1c57e,
1381        0x114f0, 0x18a7c, 0x11478, 0x18a3e, 0x1143c, 0x1141e, 0x1f8b4, 0x116f8,
1382        0x18b7e, 0x1f8b2, 0x1167c, 0x1163e, 0x1f174, 0x1177e, 0x1f172, 0x1e2f4,
1383        0x1e2f2, 0x1c5f4, 0x1c5f2, 0x18bf4, 0x18bf2, 0x135c0, 0x19af0, 0x1cd7c,
1384        0x134e0, 0x19a78, 0x1cd3e, 0x13470, 0x19a3c, 0x13438, 0x19a1e, 0x1341c,
1385        0x1340e, 0x112f0, 0x1897c, 0x136f0, 0x11278, 0x1893e, 0x13678, 0x19b3e,
1386        0x1363c, 0x1121e, 0x1361e, 0x1f89a, 0x1137c, 0x1f9ba, 0x1377c, 0x1133e,
1387        0x1373e, 0x1f13a, 0x1f37a, 0x1e27a, 0x1e6fa, 0x1c4fa, 0x1cdfa, 0x189fa,
1388        0x1bae0, 0x1dd78, 0x1eebe, 0x174c0, 0x1ba70, 0x1dd3c, 0x17460, 0x1ba38,
1389        0x1dd1e, 0x17430, 0x1ba1c, 0x17418, 0x1ba0e, 0x1740c, 0x132e0, 0x19978,
1390        0x1ccbe, 0x176e0, 0x13270, 0x1993c, 0x17670, 0x1bb3c, 0x1991e, 0x17638,
1391        0x1321c, 0x1761c, 0x1320e, 0x1760e, 0x11178, 0x188be, 0x13378, 0x1113c,
1392        0x17778, 0x1333c, 0x1111e, 0x1773c, 0x1331e, 0x1771e, 0x111be, 0x133be,
1393        0x177be, 0x172c0, 0x1b970, 0x1dcbc, 0x17260, 0x1b938, 0x1dc9e, 0x17230,
1394        0x1b91c, 0x17218, 0x1b90e, 0x1720c, 0x17206, 0x13170, 0x198bc, 0x17370,
1395        0x13138, 0x1989e, 0x17338, 0x1b99e, 0x1731c, 0x1310e, 0x1730e, 0x110bc,
1396        0x131bc, 0x1109e, 0x173bc, 0x1319e, 0x1739e, 0x17160, 0x1b8b8, 0x1dc5e,
1397        0x17130, 0x1b89c, 0x17118, 0x1b88e, 0x1710c, 0x17106, 0x130b8, 0x1985e,
1398        0x171b8, 0x1309c, 0x1719c, 0x1308e, 0x1718e, 0x1105e, 0x130de, 0x171de,
1399        0x170b0, 0x1b85c, 0x17098, 0x1b84e, 0x1708c, 0x17086, 0x1305c, 0x170dc,
1400        0x1304e, 0x170ce, 0x17058, 0x1b82e, 0x1704c, 0x17046, 0x1302e, 0x1706e,
1401        0x1702c, 0x17026, 0x10af0, 0x1857c, 0x10a78, 0x1853e, 0x10a3c, 0x10a1e,
1402        0x10b7c, 0x10b3e, 0x1f0ba, 0x1e17a, 0x1c2fa, 0x185fa, 0x11ae0, 0x18d78,
1403        0x1c6be, 0x11a70, 0x18d3c, 0x11a38, 0x18d1e, 0x11a1c, 0x11a0e, 0x10978,
1404        0x184be, 0x11b78, 0x1093c, 0x11b3c, 0x1091e, 0x11b1e, 0x109be, 0x11bbe,
1405        0x13ac0, 0x19d70, 0x1cebc, 0x13a60, 0x19d38, 0x1ce9e, 0x13a30, 0x19d1c,
1406        0x13a18, 0x19d0e, 0x13a0c, 0x13a06, 0x11970, 0x18cbc, 0x13b70, 0x11938,
1407        0x18c9e, 0x13b38, 0x1191c, 0x13b1c, 0x1190e, 0x13b0e, 0x108bc, 0x119bc,
1408        0x1089e, 0x13bbc, 0x1199e, 0x13b9e, 0x1bd60, 0x1deb8, 0x1ef5e, 0x17a40,
1409        0x1bd30, 0x1de9c, 0x17a20, 0x1bd18, 0x1de8e, 0x17a10, 0x1bd0c, 0x17a08,
1410        0x1bd06, 0x17a04, 0x13960, 0x19cb8, 0x1ce5e, 0x17b60, 0x13930, 0x19c9c,
1411        0x17b30, 0x1bd9c, 0x19c8e, 0x17b18, 0x1390c, 0x17b0c, 0x13906, 0x17b06,
1412        0x118b8, 0x18c5e, 0x139b8, 0x1189c, 0x17bb8, 0x1399c, 0x1188e, 0x17b9c,
1413        0x1398e, 0x17b8e, 0x1085e, 0x118de, 0x139de, 0x17bde, 0x17940, 0x1bcb0,
1414        0x1de5c, 0x17920, 0x1bc98, 0x1de4e, 0x17910, 0x1bc8c, 0x17908, 0x1bc86,
1415        0x17904, 0x17902, 0x138b0, 0x19c5c, 0x179b0, 0x13898, 0x19c4e, 0x17998,
1416        0x1bcce, 0x1798c, 0x13886, 0x17986, 0x1185c, 0x138dc, 0x1184e, 0x179dc,
1417        0x138ce, 0x179ce, 0x178a0, 0x1bc58, 0x1de2e, 0x17890, 0x1bc4c, 0x17888,
1418        0x1bc46, 0x17884, 0x17882, 0x13858, 0x19c2e, 0x178d8, 0x1384c, 0x178cc,
1419        0x13846, 0x178c6, 0x1182e, 0x1386e, 0x178ee, 0x17850, 0x1bc2c, 0x17848,
1420        0x1bc26, 0x17844, 0x17842, 0x1382c, 0x1786c, 0x13826, 0x17866, 0x17828,
1421        0x1bc16, 0x17824, 0x17822, 0x13816, 0x17836, 0x10578, 0x182be, 0x1053c,
1422        0x1051e, 0x105be, 0x10d70, 0x186bc, 0x10d38, 0x1869e, 0x10d1c, 0x10d0e,
1423        0x104bc, 0x10dbc, 0x1049e, 0x10d9e, 0x11d60, 0x18eb8, 0x1c75e, 0x11d30,
1424        0x18e9c, 0x11d18, 0x18e8e, 0x11d0c, 0x11d06, 0x10cb8, 0x1865e, 0x11db8,
1425        0x10c9c, 0x11d9c, 0x10c8e, 0x11d8e, 0x1045e, 0x10cde, 0x11dde, 0x13d40,
1426        0x19eb0, 0x1cf5c, 0x13d20, 0x19e98, 0x1cf4e, 0x13d10, 0x19e8c, 0x13d08,
1427        0x19e86, 0x13d04, 0x13d02, 0x11cb0, 0x18e5c, 0x13db0, 0x11c98, 0x18e4e,
1428        0x13d98, 0x19ece, 0x13d8c, 0x11c86, 0x13d86, 0x10c5c, 0x11cdc, 0x10c4e,
1429        0x13ddc, 0x11cce, 0x13dce, 0x1bea0, 0x1df58, 0x1efae, 0x1be90, 0x1df4c,
1430        0x1be88, 0x1df46, 0x1be84, 0x1be82, 0x13ca0, 0x19e58, 0x1cf2e, 0x17da0,
1431        0x13c90, 0x19e4c, 0x17d90, 0x1becc, 0x19e46, 0x17d88, 0x13c84, 0x17d84,
1432        0x13c82, 0x17d82, 0x11c58, 0x18e2e, 0x13cd8, 0x11c4c, 0x17dd8, 0x13ccc,
1433        0x11c46, 0x17dcc, 0x13cc6, 0x17dc6, 0x10c2e, 0x11c6e, 0x13cee, 0x17dee,
1434        0x1be50, 0x1df2c, 0x1be48, 0x1df26, 0x1be44, 0x1be42, 0x13c50, 0x19e2c,
1435        0x17cd0, 0x13c48, 0x19e26, 0x17cc8, 0x1be66, 0x17cc4, 0x13c42, 0x17cc2,
1436        0x11c2c, 0x13c6c, 0x11c26, 0x17cec, 0x13c66, 0x17ce6, 0x1be28, 0x1df16,
1437        0x1be24, 0x1be22, 0x13c28, 0x19e16, 0x17c68, 0x13c24, 0x17c64, 0x13c22,
1438        0x17c62, 0x11c16, 0x13c36, 0x17c76, 0x1be14, 0x1be12, 0x13c14, 0x17c34,
1439        0x13c12, 0x17c32, 0x102bc, 0x1029e, 0x106b8, 0x1835e, 0x1069c, 0x1068e,
1440        0x1025e, 0x106de, 0x10eb0, 0x1875c, 0x10e98, 0x1874e, 0x10e8c, 0x10e86,
1441        0x1065c, 0x10edc, 0x1064e, 0x10ece, 0x11ea0, 0x18f58, 0x1c7ae, 0x11e90,
1442        0x18f4c, 0x11e88, 0x18f46, 0x11e84, 0x11e82, 0x10e58, 0x1872e, 0x11ed8,
1443        0x18f6e, 0x11ecc, 0x10e46, 0x11ec6, 0x1062e, 0x10e6e, 0x11eee, 0x19f50,
1444        0x1cfac, 0x19f48, 0x1cfa6, 0x19f44, 0x19f42, 0x11e50, 0x18f2c, 0x13ed0,
1445        0x19f6c, 0x18f26, 0x13ec8, 0x11e44, 0x13ec4, 0x11e42, 0x13ec2, 0x10e2c,
1446        0x11e6c, 0x10e26, 0x13eec, 0x11e66, 0x13ee6, 0x1dfa8, 0x1efd6, 0x1dfa4,
1447        0x1dfa2, 0x19f28, 0x1cf96, 0x1bf68, 0x19f24, 0x1bf64, 0x19f22, 0x1bf62,
1448        0x11e28, 0x18f16, 0x13e68, 0x11e24, 0x17ee8, 0x13e64, 0x11e22, 0x17ee4,
1449        0x13e62, 0x17ee2, 0x10e16, 0x11e36, 0x13e76, 0x17ef6, 0x1df94, 0x1df92,
1450        0x19f14, 0x1bf34, 0x19f12, 0x1bf32, 0x11e14, 0x13e34, 0x11e12, 0x17e74,
1451        0x13e32, 0x17e72, 0x1df8a, 0x19f0a, 0x1bf1a, 0x11e0a, 0x13e1a, 0x17e3a,
1452        0x1035c, 0x1034e, 0x10758, 0x183ae, 0x1074c, 0x10746, 0x1032e, 0x1076e,
1453        0x10f50, 0x187ac, 0x10f48, 0x187a6, 0x10f44, 0x10f42, 0x1072c, 0x10f6c,
1454        0x10726, 0x10f66, 0x18fa8, 0x1c7d6, 0x18fa4, 0x18fa2, 0x10f28, 0x18796,
1455        0x11f68, 0x18fb6, 0x11f64, 0x10f22, 0x11f62, 0x10716, 0x10f36, 0x11f76,
1456        0x1cfd4, 0x1cfd2, 0x18f94, 0x19fb4, 0x18f92, 0x19fb2, 0x10f14, 0x11f34,
1457        0x10f12, 0x13f74, 0x11f32, 0x13f72, 0x1cfca, 0x18f8a, 0x19f9a, 0x10f0a,
1458        0x11f1a, 0x13f3a, 0x103ac, 0x103a6, 0x107a8, 0x183d6, 0x107a4, 0x107a2,
1459        0x10396, 0x107b6, 0x187d4, 0x187d2, 0x10794, 0x10fb4, 0x10792, 0x10fb2,
1460        0x1c7ea
1461    }};
1462
1463    private static final int ERROR_LEVEL[][] =
1464    {{
1465         27, 917
1466    }, {
1467        522, 568, 723, 809
1468    }, {
1469        237, 308, 436, 284, 646, 653, 428, 379
1470    }, {
1471        274, 562, 232, 755, 599, 524, 801, 132, 295, 116, 442, 428, 295, 42, 176, 65
1472    }, {
1473        361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517,
1474        273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410
1475    }, {
1476        539, 422, 6, 93, 862, 771, 453, 106, 610, 287, 107, 505, 733, 877, 381, 612,
1477        723, 476, 462, 172, 430, 609, 858, 822, 543, 376, 511, 400, 672, 762, 283, 184,
1478        440, 35, 519, 31, 460, 594, 225, 535, 517, 352, 605, 158, 651, 201, 488, 502,
1479        648, 733, 717, 83, 404, 97, 280, 771, 840, 629, 4, 381, 843, 623, 264, 543
1480    }, {
1481        521, 310, 864, 547, 858, 580, 296, 379, 53, 779, 897, 444, 400, 925, 749, 415,
1482        822, 93, 217, 208, 928, 244, 583, 620, 246, 148, 447, 631, 292, 908, 490, 704,
1483        516, 258, 457, 907, 594, 723, 674, 292, 272, 96, 684, 432, 686, 606, 860, 569,
1484        193, 219, 129, 186, 236, 287, 192, 775, 278, 173, 40, 379, 712, 463, 646, 776,
1485        171, 491, 297, 763, 156, 732, 95, 270, 447, 90, 507, 48, 228, 821, 808, 898,
1486        784, 663, 627, 378, 382, 262, 380, 602, 754, 336, 89, 614, 87, 432, 670, 616,
1487        157, 374, 242, 726, 600, 269, 375, 898, 845, 454, 354, 130, 814, 587, 804, 34,
1488        211, 330, 539, 297, 827, 865, 37, 517, 834, 315, 550, 86, 801, 4, 108, 539
1489    }, {
1490        524, 894, 75, 766, 882, 857, 74, 204, 82, 586, 708, 250, 905, 786, 138, 720,
1491        858, 194, 311, 913, 275, 190, 375, 850, 438, 733, 194, 280, 201, 280, 828, 757,
1492        710, 814, 919, 89, 68, 569, 11, 204, 796, 605, 540, 913, 801, 700, 799, 137,
1493        439, 418, 592, 668, 353, 859, 370, 694, 325, 240, 216, 257, 284, 549, 209, 884,
1494        315, 70, 329, 793, 490, 274, 877, 162, 749, 812, 684, 461, 334, 376, 849, 521,
1495        307, 291, 803, 712, 19, 358, 399, 908, 103, 511, 51, 8, 517, 225, 289, 470,
1496        637, 731, 66, 255, 917, 269, 463, 830, 730, 433, 848, 585, 136, 538, 906, 90,
1497        2, 290, 743, 199, 655, 903, 329, 49, 802, 580, 355, 588, 188, 462, 10, 134,
1498        628, 320, 479, 130, 739, 71, 263, 318, 374, 601, 192, 605, 142, 673, 687, 234,
1499        722, 384, 177, 752, 607, 640, 455, 193, 689, 707, 805, 641, 48, 60, 732, 621,
1500        895, 544, 261, 852, 655, 309, 697, 755, 756, 60, 231, 773, 434, 421, 726, 528,
1501        503, 118, 49, 795, 32, 144, 500, 238, 836, 394, 280, 566, 319, 9, 647, 550,
1502        73, 914, 342, 126, 32, 681, 331, 792, 620, 60, 609, 441, 180, 791, 893, 754,
1503        605, 383, 228, 749, 760, 213, 54, 297, 134, 54, 834, 299, 922, 191, 910, 532,
1504        609, 829, 189, 20, 167, 29, 872, 449, 83, 402, 41, 656, 505, 579, 481, 173,
1505        404, 251, 688, 95, 497, 555, 642, 543, 307, 159, 924, 558, 648, 55, 497, 10
1506    }, {
1507        352, 77, 373, 504, 35, 599, 428, 207, 409, 574, 118, 498, 285, 380, 350, 492,
1508        197, 265, 920, 155, 914, 299, 229, 643, 294, 871, 306, 88, 87, 193, 352, 781,
1509        846, 75, 327, 520, 435, 543, 203, 666, 249, 346, 781, 621, 640, 268, 794, 534,
1510        539, 781, 408, 390, 644, 102, 476, 499, 290, 632, 545, 37, 858, 916, 552, 41,
1511        542, 289, 122, 272, 383, 800, 485, 98, 752, 472, 761, 107, 784, 860, 658, 741,
1512        290, 204, 681, 407, 855, 85, 99, 62, 482, 180, 20, 297, 451, 593, 913, 142,
1513        808, 684, 287, 536, 561, 76, 653, 899, 729, 567, 744, 390, 513, 192, 516, 258,
1514        240, 518, 794, 395, 768, 848, 51, 610, 384, 168, 190, 826, 328, 596, 786, 303,
1515        570, 381, 415, 641, 156, 237, 151, 429, 531, 207, 676, 710, 89, 168, 304, 402,
1516        40, 708, 575, 162, 864, 229, 65, 861, 841, 512, 164, 477, 221, 92, 358, 785,
1517        288, 357, 850, 836, 827, 736, 707, 94, 8, 494, 114, 521, 2, 499, 851, 543,
1518        152, 729, 771, 95, 248, 361, 578, 323, 856, 797, 289, 51, 684, 466, 533, 820,
1519        669, 45, 902, 452, 167, 342, 244, 173, 35, 463, 651, 51, 699, 591, 452, 578,
1520        37, 124, 298, 332, 552, 43, 427, 119, 662, 777, 475, 850, 764, 364, 578, 911,
1521        283, 711, 472, 420, 245, 288, 594, 394, 511, 327, 589, 777, 699, 688, 43, 408,
1522        842, 383, 721, 521, 560, 644, 714, 559, 62, 145, 873, 663, 713, 159, 672, 729,
1523        624, 59, 193, 417, 158, 209, 563, 564, 343, 693, 109, 608, 563, 365, 181, 772,
1524        677, 310, 248, 353, 708, 410, 579, 870, 617, 841, 632, 860, 289, 536, 35, 777,
1525        618, 586, 424, 833, 77, 597, 346, 269, 757, 632, 695, 751, 331, 247, 184, 45,
1526        787, 680, 18, 66, 407, 369, 54, 492, 228, 613, 830, 922, 437, 519, 644, 905,
1527        789, 420, 305, 441, 207, 300, 892, 827, 141, 537, 381, 662, 513, 56, 252, 341,
1528        242, 797, 838, 837, 720, 224, 307, 631, 61, 87, 560, 310, 756, 665, 397, 808,
1529        851, 309, 473, 795, 378, 31, 647, 915, 459, 806, 590, 731, 425, 216, 548, 249,
1530        321, 881, 699, 535, 673, 782, 210, 815, 905, 303, 843, 922, 281, 73, 469, 791,
1531        660, 162, 498, 308, 155, 422, 907, 817, 187, 62, 16, 425, 535, 336, 286, 437,
1532        375, 273, 610, 296, 183, 923, 116, 667, 751, 353, 62, 366, 691, 379, 687, 842,
1533        37, 357, 720, 742, 330, 5, 39, 923, 311, 424, 242, 749, 321, 54, 669, 316,
1534        342, 299, 534, 105, 667, 488, 640, 672, 576, 540, 316, 486, 721, 610, 46, 656,
1535        447, 171, 616, 464, 190, 531, 297, 321, 762, 752, 533, 175, 134, 14, 381, 433,
1536        717, 45, 111, 20, 596, 284, 736, 138, 646, 411, 877, 669, 141, 919, 45, 780,
1537        407, 164, 332, 899, 165, 726, 600, 325, 498, 655, 357, 752, 768, 223, 849, 647,
1538        63, 310, 863, 251, 366, 304, 282, 738, 675, 410, 389, 244, 31, 121, 303, 263
1539    }};
1540
1541    /** Holds value of property outBits. */
1542    private byte[] outBits;
1543
1544    /** Holds value of property bitColumns. */
1545    private int bitColumns;
1546
1547    /** Holds value of property codeRows. */
1548    private int codeRows;
1549
1550    /** Holds value of property codeColumns. */
1551    private int codeColumns;
1552
1553    /** Holds value of property codewords. */
1554    private int[] codewords = new int[MAX_DATA_CODEWORDS + 2];
1555
1556    /** Holds value of property lenCodewords. */
1557    private int lenCodewords;
1558
1559    /** Holds value of property errorLevel. */
1560    private int errorLevel;
1561
1562    /** Holds value of property text. */
1563    private byte[] text;
1564
1565    /** Holds value of property options. */
1566    private int options;
1567
1568    /** Holds value of property aspectRatio. */
1569    private float aspectRatio;
1570
1571    /** Holds value of property yHeight. */
1572    private float yHeight;
1573
1574    protected static class Segment {
1575        public char type;
1576        public int start;
1577        public int end;
1578
1579        public Segment(char type, int start, int end) {
1580            this.type = type;
1581            this.start = start;
1582            this.end = end;
1583        }
1584    }
1585
1586    protected static class SegmentList {
1587        protected ArrayList<Segment> list = new ArrayList<Segment>();
1588
1589        public void add(char type, int start, int end) {
1590            list.add(new Segment(type, start, end));
1591        }
1592
1593        public Segment get(int idx) {
1594            if (idx < 0 || idx >= list.size())
1595                return null;
1596            return list.get(idx);
1597        }
1598
1599        public void remove(int idx) {
1600            if (idx < 0 || idx >= list.size())
1601                return;
1602            list.remove(idx);
1603        }
1604
1605        public int size() {
1606            return list.size();
1607        }
1608    }
1609}