KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lowagie > text > pdf > Barcode128


1 /*
2  * $Id: Barcode128.java 2387 2006-09-16 19:08:00Z xlv $
3  *
4  * Copyright 2002-2006 by Paulo Soares.
5  *
6  * The contents of this file are subject to the Mozilla Public License Version 1.1
7  * (the "License"); you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at http://www.mozilla.org/MPL/
9  *
10  * Software distributed under the License is distributed on an "AS IS" basis,
11  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12  * for the specific language governing rights and limitations under the License.
13  *
14  * The Original Code is 'iText, a free JAVA-PDF library'.
15  *
16  * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
17  * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
18  * All Rights Reserved.
19  * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
20  * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
21  *
22  * Contributor(s): all the names of the contributors are added in the source code
23  * where applicable.
24  *
25  * Alternatively, the contents of this file may be used under the terms of the
26  * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
27  * provisions of LGPL are applicable instead of those above. If you wish to
28  * allow use of your version of this file only under the terms of the LGPL
29  * License and not to allow others to use your version of this file under
30  * the MPL, indicate your decision by deleting the provisions above and
31  * replace them with the notice and other provisions required by the LGPL.
32  * If you do not delete the provisions above, a recipient may use your version
33  * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
34  *
35  * This library is free software; you can redistribute it and/or modify it
36  * under the terms of the MPL as stated above or under the terms of the GNU
37  * Library General Public License as published by the Free Software Foundation;
38  * either version 2 of the License, or any later version.
39  *
40  * This library is distributed in the hope that it will be useful, but WITHOUT
41  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
42  * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
43  * details.
44  *
45  * If you didn't download this code from the following link, you should check if
46  * you aren't using an obsolete version:
47  * http://www.lowagie.com/iText/
48  */

49 package com.lowagie.text.pdf;
50 import java.awt.Canvas JavaDoc;
51 import java.awt.Color JavaDoc;
52 import java.awt.Image JavaDoc;
53 import java.awt.image.MemoryImageSource JavaDoc;
54
55 import com.lowagie.text.Element;
56 import com.lowagie.text.ExceptionConverter;
57 import com.lowagie.text.Rectangle;
58
59 /**
60  * Implements the code 128 and UCC/EAN-128. Other symbologies are allowed in raw mode.<p>
61  * The code types allowed are:<br>
62  * <ul>
63  * <li><b>CODE128</b> - plain barcode 128.
64  * <li><b>CODE128_UCC</b> - support for UCC/EAN-128 with a full list of AI.
65  * <li><b>CODE128_RAW</b> - raw mode. The code attribute has the actual codes from 0
66  * to 105 followed by '&#92;uffff' and the human readable text.
67  * </ul>
68  * The default parameters are:
69  * <pre>
70  * x = 0.8f;
71  * font = BaseFont.createFont("Helvetica", "winansi", false);
72  * size = 8;
73  * baseline = size;
74  * barHeight = size * 3;
75  * textAlignment = Element.ALIGN_CENTER;
76  * codeType = CODE128;
77  * </pre>
78  * @author Paulo Soares (psoares@consiste.pt)
79  */

80 public class Barcode128 extends Barcode{
81
82     /** The bars to generate the code.
83      */

84     private static final byte BARS[][] =
85     {
86         {2, 1, 2, 2, 2, 2},
87         {2, 2, 2, 1, 2, 2},
88         {2, 2, 2, 2, 2, 1},
89         {1, 2, 1, 2, 2, 3},
90         {1, 2, 1, 3, 2, 2},
91         {1, 3, 1, 2, 2, 2},
92         {1, 2, 2, 2, 1, 3},
93         {1, 2, 2, 3, 1, 2},
94         {1, 3, 2, 2, 1, 2},
95         {2, 2, 1, 2, 1, 3},
96         {2, 2, 1, 3, 1, 2},
97         {2, 3, 1, 2, 1, 2},
98         {1, 1, 2, 2, 3, 2},
99         {1, 2, 2, 1, 3, 2},
100         {1, 2, 2, 2, 3, 1},
101         {1, 1, 3, 2, 2, 2},
102         {1, 2, 3, 1, 2, 2},
103         {1, 2, 3, 2, 2, 1},
104         {2, 2, 3, 2, 1, 1},
105         {2, 2, 1, 1, 3, 2},
106         {2, 2, 1, 2, 3, 1},
107         {2, 1, 3, 2, 1, 2},
108         {2, 2, 3, 1, 1, 2},
109         {3, 1, 2, 1, 3, 1},
110         {3, 1, 1, 2, 2, 2},
111         {3, 2, 1, 1, 2, 2},
112         {3, 2, 1, 2, 2, 1},
113         {3, 1, 2, 2, 1, 2},
114         {3, 2, 2, 1, 1, 2},
115         {3, 2, 2, 2, 1, 1},
116         {2, 1, 2, 1, 2, 3},
117         {2, 1, 2, 3, 2, 1},
118         {2, 3, 2, 1, 2, 1},
119         {1, 1, 1, 3, 2, 3},
120         {1, 3, 1, 1, 2, 3},
121         {1, 3, 1, 3, 2, 1},
122         {1, 1, 2, 3, 1, 3},
123         {1, 3, 2, 1, 1, 3},
124         {1, 3, 2, 3, 1, 1},
125         {2, 1, 1, 3, 1, 3},
126         {2, 3, 1, 1, 1, 3},
127         {2, 3, 1, 3, 1, 1},
128         {1, 1, 2, 1, 3, 3},
129         {1, 1, 2, 3, 3, 1},
130         {1, 3, 2, 1, 3, 1},
131         {1, 1, 3, 1, 2, 3},
132         {1, 1, 3, 3, 2, 1},
133         {1, 3, 3, 1, 2, 1},
134         {3, 1, 3, 1, 2, 1},
135         {2, 1, 1, 3, 3, 1},
136         {2, 3, 1, 1, 3, 1},
137         {2, 1, 3, 1, 1, 3},
138         {2, 1, 3, 3, 1, 1},
139         {2, 1, 3, 1, 3, 1},
140         {3, 1, 1, 1, 2, 3},
141         {3, 1, 1, 3, 2, 1},
142         {3, 3, 1, 1, 2, 1},
143         {3, 1, 2, 1, 1, 3},
144         {3, 1, 2, 3, 1, 1},
145         {3, 3, 2, 1, 1, 1},
146         {3, 1, 4, 1, 1, 1},
147         {2, 2, 1, 4, 1, 1},
148         {4, 3, 1, 1, 1, 1},
149         {1, 1, 1, 2, 2, 4},
150         {1, 1, 1, 4, 2, 2},
151         {1, 2, 1, 1, 2, 4},
152         {1, 2, 1, 4, 2, 1},
153         {1, 4, 1, 1, 2, 2},
154         {1, 4, 1, 2, 2, 1},
155         {1, 1, 2, 2, 1, 4},
156         {1, 1, 2, 4, 1, 2},
157         {1, 2, 2, 1, 1, 4},
158         {1, 2, 2, 4, 1, 1},
159         {1, 4, 2, 1, 1, 2},
160         {1, 4, 2, 2, 1, 1},
161         {2, 4, 1, 2, 1, 1},
162         {2, 2, 1, 1, 1, 4},
163         {4, 1, 3, 1, 1, 1},
164         {2, 4, 1, 1, 1, 2},
165         {1, 3, 4, 1, 1, 1},
166         {1, 1, 1, 2, 4, 2},
167         {1, 2, 1, 1, 4, 2},
168         {1, 2, 1, 2, 4, 1},
169         {1, 1, 4, 2, 1, 2},
170         {1, 2, 4, 1, 1, 2},
171         {1, 2, 4, 2, 1, 1},
172         {4, 1, 1, 2, 1, 2},
173         {4, 2, 1, 1, 1, 2},
174         {4, 2, 1, 2, 1, 1},
175         {2, 1, 2, 1, 4, 1},
176         {2, 1, 4, 1, 2, 1},
177         {4, 1, 2, 1, 2, 1},
178         {1, 1, 1, 1, 4, 3},
179         {1, 1, 1, 3, 4, 1},
180         {1, 3, 1, 1, 4, 1},
181         {1, 1, 4, 1, 1, 3},
182         {1, 1, 4, 3, 1, 1},
183         {4, 1, 1, 1, 1, 3},
184         {4, 1, 1, 3, 1, 1},
185         {1, 1, 3, 1, 4, 1},
186         {1, 1, 4, 1, 3, 1},
187         {3, 1, 1, 1, 4, 1},
188         {4, 1, 1, 1, 3, 1},
189         {2, 1, 1, 4, 1, 2},
190         {2, 1, 1, 2, 1, 4},
191         {2, 1, 1, 2, 3, 2}
192     };
193     
194     /** The stop bars.
195      */

196     private static final byte BARS_STOP[] = {2, 3, 3, 1, 1, 1, 2};
197     /** The charset code change.
198      */

199     public static final char CODE_AB_TO_C = 99;
200     /** The charset code change.
201      */

202     public static final char CODE_AC_TO_B = 100;
203     /** The charset code change.
204      */

205     public static final char CODE_BC_TO_A = 101;
206     /** The code for UCC/EAN-128.
207      */

208     public static final char FNC1_INDEX = 102;
209     /** The start code.
210      */

211     public static final char START_A = 103;
212     /** The start code.
213      */

214     public static final char START_B = 104;
215     /** The start code.
216      */

217     public static final char START_C = 105;
218
219     public static final char FNC1 = '\u00ca';
220     public static final char DEL = '\u00c3';
221     public static final char FNC3 = '\u00c4';
222     public static final char FNC2 = '\u00c5';
223     public static final char SHIFT = '\u00c6';
224     public static final char CODE_C = '\u00c7';
225     public static final char CODE_A = '\u00c8';
226     public static final char FNC4 = '\u00c8';
227     public static final char STARTA = '\u00cb';
228     public static final char STARTB = '\u00cc';
229     public static final char STARTC = '\u00cd';
230     
231     private static final IntHashtable ais = new IntHashtable();
232     /** Creates new Barcode128 */
233     public Barcode128() {
234         try {
235             x = 0.8f;
236             font = BaseFont.createFont("Helvetica", "winansi", false);
237             size = 8;
238             baseline = size;
239             barHeight = size * 3;
240             textAlignment = Element.ALIGN_CENTER;
241             codeType = CODE128;
242         }
243         catch (Exception JavaDoc e) {
244             throw new ExceptionConverter(e);
245         }
246     }
247
248     /**
249      * Removes the FNC1 codes in the text.
250      * @param code the text to clean
251      * @return the cleaned text
252      */

253     public static String JavaDoc removeFNC1(String JavaDoc code) {
254         int len = code.length();
255         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(len);
256         for (int k = 0; k < len; ++k) {
257             char c = code.charAt(k);
258             if (c >= 32 && c <= 126)
259                 buf.append(c);
260         }
261         return buf.toString();
262     }
263     
264     /**
265      * Gets the human readable text of a sequence of AI.
266      * @param code the text
267      * @return the human readable text
268      */

269     public static String JavaDoc getHumanReadableUCCEAN(String JavaDoc code) {
270         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
271         String JavaDoc fnc1 = String.valueOf(FNC1);
272         try {
273             while (true) {
274                 if (code.startsWith(fnc1)) {
275                     code = code.substring(1);
276                     continue;
277                 }
278                 int n = 0;
279                 int idlen = 0;
280                 for (int k = 2; k < 5; ++k) {
281                     if (code.length() < k)
282                         break;
283                     if ((n = ais.get(Integer.parseInt(code.substring(0, k)))) != 0) {
284                         idlen = k;
285                         break;
286                     }
287                 }
288                 if (idlen == 0)
289                     break;
290                 buf.append('(').append(code.substring(0, idlen)).append(')');
291                 code = code.substring(idlen);
292                 if (n > 0) {
293                     n -= idlen;
294                     if (code.length() <= n)
295                         break;
296                     buf.append(removeFNC1(code.substring(0, n)));
297                     code = code.substring(n);
298                 }
299                 else {
300                     int idx = code.indexOf(FNC1);
301                     if (idx < 0)
302                         break;
303                     buf.append(code.substring(0,idx));
304                     code = code.substring(idx + 1);
305                 }
306             }
307         }
308         catch (Exception JavaDoc e) {
309             //empty
310
}
311         buf.append(removeFNC1(code));
312         return buf.toString();
313     }
314     
315     /** Returns <CODE>true</CODE> if the next <CODE>numDigits</CODE>
316      * starting from index <CODE>textIndex</CODE> are numeric skipping any FNC1.
317      * @param text the text to check
318      * @param textIndex where to check from
319      * @param numDigits the number of digits to check
320      * @return the check result
321      */

322     static boolean isNextDigits(String JavaDoc text, int textIndex, int numDigits) {
323         int len = text.length();
324         while (textIndex < len && numDigits > 0) {
325             if (text.charAt(textIndex) == FNC1) {
326                 ++textIndex;
327                 continue;
328             }
329             int n = Math.min(2, numDigits);
330             if (textIndex + n > len)
331                 return false;
332             while (n-- > 0) {
333                 char c = text.charAt(textIndex++);
334                 if (c < '0' || c > '9')
335                     return false;
336                 --numDigits;
337             }
338         }
339         return numDigits == 0;
340     }
341     
342     /** Packs the digits for charset C also considering FNC1. It assumes that all the parameters
343      * are valid.
344      * @param text the text to pack
345      * @param textIndex where to pack from
346      * @param numDigits the number of digits to pack. It is always an even number
347      * @return the packed digits, two digits per character
348      */

349     static String JavaDoc getPackedRawDigits(String JavaDoc text, int textIndex, int numDigits) {
350         String JavaDoc out = "";
351         int start = textIndex;
352         while (numDigits > 0) {
353             if (text.charAt(textIndex) == FNC1) {
354                 out += FNC1_INDEX;
355                 ++textIndex;
356                 continue;
357             }
358             numDigits -= 2;
359             int c1 = text.charAt(textIndex++) - '0';
360             int c2 = text.charAt(textIndex++) - '0';
361             out += (char)(c1 * 10 + c2);
362         }
363         return (char)(textIndex - start) + out;
364     }
365     
366     /** Converts the human readable text to the characters needed to
367      * create a barcode. Some optimization is done to get the shortest code.
368      * @param text the text to convert
369      * @param ucc <CODE>true</CODE> if it is an UCC/EAN-128. In this case
370      * the character FNC1 is added
371      * @return the code ready to be fed to getBarsCode128Raw()
372      */

373     public static String JavaDoc getRawText(String JavaDoc text, boolean ucc) {
374         String JavaDoc out = "";
375         int tLen = text.length();
376         if (tLen == 0) {
377             out += START_B;
378             if (ucc)
379                 out += FNC1_INDEX;
380             return out;
381         }
382         int c = 0;
383         for (int k = 0; k < tLen; ++k) {
384             c = text.charAt(k);
385             if (c > 127 && c != FNC1)
386                 throw new RuntimeException JavaDoc("There are illegal characters for barcode 128 in '" + text + "'.");
387         }
388         c = text.charAt(0);
389         char currentCode = START_B;
390         int index = 0;
391         if (isNextDigits(text, index, 2)) {
392             currentCode = START_C;
393             out += currentCode;
394             if (ucc)
395                 out += FNC1_INDEX;
396             String JavaDoc out2 = getPackedRawDigits(text, index, 2);
397             index += (int)out2.charAt(0);
398             out += out2.substring(1);
399         }
400         else if (c < ' ') {
401             currentCode = START_A;
402             out += currentCode;
403             if (ucc)
404                 out += FNC1_INDEX;
405             out += (char)(c + 64);
406             ++index;
407         }
408         else {
409             out += currentCode;
410             if (ucc)
411                 out += FNC1_INDEX;
412             if (c == FNC1)
413                 out += FNC1_INDEX;
414             else
415                 out += (char)(c - ' ');
416             ++index;
417         }
418         while (index < tLen) {
419             switch (currentCode) {
420                 case START_A:
421                     {
422                         if (isNextDigits(text, index, 4)) {
423                             currentCode = START_C;
424                             out += CODE_AB_TO_C;
425                             String JavaDoc out2 = getPackedRawDigits(text, index, 4);
426                             index += (int)out2.charAt(0);
427                             out += out2.substring(1);
428                         }
429                         else {
430                             c = text.charAt(index++);
431                             if (c == FNC1)
432                                 out += FNC1_INDEX;
433                             else if (c > '_') {
434                                 currentCode = START_B;
435                                 out += CODE_AC_TO_B;
436                                 out += (char)(c - ' ');
437                             }
438                             else if (c < ' ')
439                                 out += (char)(c + 64);
440                             else
441                                 out += (char)(c - ' ');
442                         }
443                     }
444                     break;
445                 case START_B:
446                     {
447                         if (isNextDigits(text, index, 4)) {
448                             currentCode = START_C;
449                             out += CODE_AB_TO_C;
450                             String JavaDoc out2 = getPackedRawDigits(text, index, 4);
451                             index += (int)out2.charAt(0);
452                             out += out2.substring(1);
453                         }
454                         else {
455                             c = text.charAt(index++);
456                             if (c == FNC1)
457                                 out += FNC1_INDEX;
458                             else if (c < ' ') {
459                                 currentCode = START_A;
460                                 out += CODE_BC_TO_A;
461                                 out += (char)(c + 64);
462                             }
463                             else {
464                                 out += (char)(c - ' ');
465                             }
466                         }
467                     }
468                     break;
469                 case START_C:
470                     {
471                         if (isNextDigits(text, index, 2)) {
472                             String JavaDoc out2 = getPackedRawDigits(text, index, 2);
473                             index += (int)out2.charAt(0);
474                             out += out2.substring(1);
475                         }
476                         else {
477                             c = text.charAt(index++);
478                             if (c == FNC1)
479                                 out += FNC1_INDEX;
480                             else if (c < ' ') {
481                                 currentCode = START_A;
482                                 out += CODE_BC_TO_A;
483                                 out += (char)(c + 64);
484                             }
485                             else {
486                                 currentCode = START_B;
487                                 out += CODE_AC_TO_B;
488                                 out += (char)(c - ' ');
489                             }
490                         }
491                     }
492                     break;
493             }
494         }
495         return out;
496     }
497     
498     /** Generates the bars. The input has the actual barcodes, not
499      * the human readable text.
500      * @param text the barcode
501      * @return the bars
502      */

503     public static byte[] getBarsCode128Raw(String JavaDoc text) {
504         int idx = text.indexOf('\uffff');
505         if (idx >= 0)
506             text = text.substring(0, idx);
507         int chk = text.charAt(0);
508         for (int k = 1; k < text.length(); ++k)
509             chk += k * text.charAt(k);
510         chk = chk % 103;
511         text += (char)chk;
512         byte bars[] = new byte[(text.length() + 1) * 6 + 7];
513         int k;
514         for (k = 0; k < text.length(); ++k)
515             System.arraycopy(BARS[text.charAt(k)], 0, bars, k * 6, 6);
516         System.arraycopy(BARS_STOP, 0, bars, k * 6, 7);
517         return bars;
518     }
519     
520     /** Gets the maximum area that the barcode and the text, if
521      * any, will occupy. The lower left corner is always (0, 0).
522      * @return the size the barcode occupies.
523      */

524     public Rectangle getBarcodeSize() {
525         float fontX = 0;
526         float fontY = 0;
527         String JavaDoc fullCode;
528         if (font != null) {
529             if (baseline > 0)
530                 fontY = baseline - font.getFontDescriptor(BaseFont.DESCENT, size);
531             else
532                 fontY = -baseline + size;
533             if (codeType == CODE128_RAW) {
534                 int idx = code.indexOf('\uffff');
535                 if (idx < 0)
536                     fullCode = "";
537                 else
538                     fullCode = code.substring(idx + 1);
539             }
540             else if (codeType == CODE128_UCC)
541                 fullCode = getHumanReadableUCCEAN(code);
542             else
543                 fullCode = removeFNC1(code);
544             fontX = font.getWidthPoint(altText != null ? altText : fullCode, size);
545         }
546         if (codeType == CODE128_RAW) {
547             int idx = code.indexOf('\uffff');
548             if (idx >= 0)
549                 fullCode = code.substring(0, idx);
550             else
551                 fullCode = code;
552         }
553         else {
554             fullCode = getRawText(code, codeType == CODE128_UCC);
555         }
556         int len = fullCode.length();
557         float fullWidth = (len + 2) * 11 * x + 2 * x;
558         fullWidth = Math.max(fullWidth, fontX);
559         float fullHeight = barHeight + fontY;
560         return new Rectangle(fullWidth, fullHeight);
561     }
562     
563     /** Places the barcode in a <CODE>PdfContentByte</CODE>. The
564      * barcode is always placed at coodinates (0, 0). Use the
565      * translation matrix to move it elsewhere.<p>
566      * The bars and text are written in the following colors:<p>
567      * <P><TABLE BORDER=1>
568      * <TR>
569      * <TH><P><CODE>barColor</CODE></TH>
570      * <TH><P><CODE>textColor</CODE></TH>
571      * <TH><P>Result</TH>
572      * </TR>
573      * <TR>
574      * <TD><P><CODE>null</CODE></TD>
575      * <TD><P><CODE>null</CODE></TD>
576      * <TD><P>bars and text painted with current fill color</TD>
577      * </TR>
578      * <TR>
579      * <TD><P><CODE>barColor</CODE></TD>
580      * <TD><P><CODE>null</CODE></TD>
581      * <TD><P>bars and text painted with <CODE>barColor</CODE></TD>
582      * </TR>
583      * <TR>
584      * <TD><P><CODE>null</CODE></TD>
585      * <TD><P><CODE>textColor</CODE></TD>
586      * <TD><P>bars painted with current color<br>text painted with <CODE>textColor</CODE></TD>
587      * </TR>
588      * <TR>
589      * <TD><P><CODE>barColor</CODE></TD>
590      * <TD><P><CODE>textColor</CODE></TD>
591      * <TD><P>bars painted with <CODE>barColor</CODE><br>text painted with <CODE>textColor</CODE></TD>
592      * </TR>
593      * </TABLE>
594      * @param cb the <CODE>PdfContentByte</CODE> where the barcode will be placed
595      * @param barColor the color of the bars. It can be <CODE>null</CODE>
596      * @param textColor the color of the text. It can be <CODE>null</CODE>
597      * @return the dimensions the barcode occupies
598      */

599     public Rectangle placeBarcode(PdfContentByte cb, Color JavaDoc barColor, Color JavaDoc textColor) {
600         String JavaDoc fullCode;
601         if (codeType == CODE128_RAW) {
602             int idx = code.indexOf('\uffff');
603             if (idx < 0)
604                 fullCode = "";
605             else
606                 fullCode = code.substring(idx + 1);
607         }
608         else if (codeType == CODE128_UCC)
609             fullCode = getHumanReadableUCCEAN(code);
610         else
611             fullCode = removeFNC1(code);
612         float fontX = 0;
613         if (font != null) {
614             fontX = font.getWidthPoint(fullCode = altText != null ? altText : fullCode, size);
615         }
616         String JavaDoc bCode;
617         if (codeType == CODE128_RAW) {
618             int idx = code.indexOf('\uffff');
619             if (idx >= 0)
620                 bCode = code.substring(0, idx);
621             else
622                 bCode = code;
623         }
624         else {
625             bCode = getRawText(code, codeType == CODE128_UCC);
626         }
627         int len = bCode.length();
628         float fullWidth = (len + 2) * 11 * x + 2 * x;
629         float barStartX = 0;
630         float textStartX = 0;
631         switch (textAlignment) {
632             case Element.ALIGN_LEFT:
633                 break;
634             case Element.ALIGN_RIGHT:
635                 if (fontX > fullWidth)
636                     barStartX = fontX - fullWidth;
637                 else
638                     textStartX = fullWidth - fontX;
639                 break;
640             default:
641                 if (fontX > fullWidth)
642                     barStartX = (fontX - fullWidth) / 2;
643                 else
644                     textStartX = (fullWidth - fontX) / 2;
645                 break;
646         }
647         float barStartY = 0;
648         float textStartY = 0;
649         if (font != null) {
650             if (baseline <= 0)
651                 textStartY = barHeight - baseline;
652             else {
653                 textStartY = -font.getFontDescriptor(BaseFont.DESCENT, size);
654                 barStartY = textStartY + baseline;
655             }
656         }
657         byte bars[] = getBarsCode128Raw(bCode);
658         boolean print = true;
659         if (barColor != null)
660             cb.setColorFill(barColor);
661         for (int k = 0; k < bars.length; ++k) {
662             float w = bars[k] * x;
663             if (print)
664                 cb.rectangle(barStartX, barStartY, w - inkSpreading, barHeight);
665             print = !print;
666             barStartX += w;
667         }
668         cb.fill();
669         if (font != null) {
670             if (textColor != null)
671                 cb.setColorFill(textColor);
672             cb.beginText();
673             cb.setFontAndSize(font, size);
674             cb.setTextMatrix(textStartX, textStartY);
675             cb.showText(fullCode);
676             cb.endText();
677         }
678         return getBarcodeSize();
679     }
680     
681     /** Creates a <CODE>java.awt.Image</CODE>. This image only
682      * contains the bars without any text.
683      * @param foreground the color of the bars
684      * @param background the color of the background
685      * @return the image
686      */

687     public java.awt.Image JavaDoc createAwtImage(Color JavaDoc foreground, Color JavaDoc background) {
688         int f = foreground.getRGB();
689         int g = background.getRGB();
690         Canvas JavaDoc canvas = new Canvas JavaDoc();
691         String JavaDoc bCode;
692         if (codeType == CODE128_RAW) {
693             int idx = code.indexOf('\uffff');
694             if (idx >= 0)
695                 bCode = code.substring(0, idx);
696             else
697                 bCode = code;
698         }
699         else {
700             bCode = getRawText(code, codeType == CODE128_UCC);
701         }
702         int len = bCode.length();
703         int fullWidth = (len + 2) * 11 + 2;
704         byte bars[] = getBarsCode128Raw(bCode);
705         
706         boolean print = true;
707         int ptr = 0;
708         int height = (int)barHeight;
709         int pix[] = new int[fullWidth * height];
710         for (int k = 0; k < bars.length; ++k) {
711             int w = bars[k];
712             int c = g;
713             if (print)
714                 c = f;
715             print = !print;
716             for (int j = 0; j < w; ++j)
717                 pix[ptr++] = c;
718         }
719         for (int k = fullWidth; k < pix.length; k += fullWidth) {
720             System.arraycopy(pix, 0, pix, k, fullWidth);
721         }
722         Image JavaDoc img = canvas.createImage(new MemoryImageSource JavaDoc(fullWidth, height, pix, 0, fullWidth));
723         
724         return img;
725     }
726     
727     /**
728      * Sets the code to generate. If it's an UCC code and starts with '(' it will
729      * be split by the AI. This code in UCC mode is valid:
730      * <p>
731      * <code>(01)00000090311314(10)ABC123(15)060916</code>
732      * @param code the code to generate
733      */

734     public void setCode(String JavaDoc code) {
735         if (getCodeType() == Barcode128.CODE128_UCC && code.startsWith("(")) {
736             int idx = 0;
737             String JavaDoc ret = "";
738             while (idx >= 0) {
739                 int end = code.indexOf(')', idx);
740                 if (end < 0)
741                     throw new IllegalArgumentException JavaDoc("Badly formed UCC string: " + code);
742                 String JavaDoc sai = code.substring(idx + 1, end);
743                 if (sai.length() < 2)
744                     throw new IllegalArgumentException JavaDoc("AI too short: (" + sai + ")");
745                 int ai = Integer.parseInt(sai);
746                 int len = ais.get(ai);
747                 if (len == 0)
748                     throw new IllegalArgumentException JavaDoc("AI not found: (" + sai + ")");
749                 sai = String.valueOf(ai);
750                 if (sai.length() == 1)
751                     sai = "0" + sai;
752                 idx = code.indexOf('(', end);
753                 int next = (idx < 0 ? code.length() : idx);
754                 ret += sai + code.substring(end + 1, next);
755                 if (len < 0) {
756                     if (idx >= 0)
757                         ret += FNC1;
758                 }
759                 else if (next - end - 1 + sai.length() != len)
760                     throw new IllegalArgumentException JavaDoc("Invalid AI length: (" + sai + ")");
761             }
762             super.setCode(ret);
763         }
764         else
765             super.setCode(code);
766     }
767     
768     static {
769         ais.put(0, 20);
770         ais.put(1, 16);
771         ais.put(2, 16);
772         ais.put(10, -1);
773         ais.put(11, 9);
774         ais.put(12, 8);
775         ais.put(13, 8);
776         ais.put(15, 8);
777         ais.put(17, 8);
778         ais.put(20, 4);
779         ais.put(21, -1);
780         ais.put(22, -1);
781         ais.put(23, -1);
782         ais.put(240, -1);
783         ais.put(241, -1);
784         ais.put(250, -1);
785         ais.put(251, -1);
786         ais.put(252, -1);
787         ais.put(30, -1);
788         for (int k = 3100; k < 3700; ++k)
789             ais.put(k, 10);
790         ais.put(37, -1);
791         for (int k = 3900; k < 3940; ++k)
792             ais.put(k, -1);
793         ais.put(400, -1);
794         ais.put(401, -1);
795         ais.put(402, 20);
796         ais.put(403, -1);
797         for (int k = 410; k < 416; ++k)
798             ais.put(k, 16);
799         ais.put(420, -1);
800         ais.put(421, -1);
801         ais.put(422, 6);
802         ais.put(423, -1);
803         ais.put(424, 6);
804         ais.put(425, 6);
805         ais.put(426, 6);
806         ais.put(7001, 17);
807         ais.put(7002, -1);
808         for (int k = 7030; k < 704; ++k)
809             ais.put(k, -1);
810         ais.put(8001, 18);
811         ais.put(8002, -1);
812         ais.put(8003, -1);
813         ais.put(8004, -1);
814         ais.put(8005, 10);
815         ais.put(8006, 22);
816         ais.put(8007, -1);
817         ais.put(8008, -1);
818         ais.put(8018, 22);
819         ais.put(8020, -1);
820         ais.put(8100, 10);
821         ais.put(8101, 14);
822         ais.put(8102, 6);
823         for (int k = 90; k < 100; ++k)
824             ais.put(k, -1);
825     }
826 }
827
Popular Tags