KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * $Id: Barcode39.java 2737 2007-05-03 19:35:09Z psoares33 $
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
51 import java.awt.Canvas JavaDoc;
52 import java.awt.Color JavaDoc;
53 import java.awt.Image JavaDoc;
54 import java.awt.image.MemoryImageSource JavaDoc;
55
56 import com.lowagie.text.Element;
57 import com.lowagie.text.ExceptionConverter;
58 import com.lowagie.text.Rectangle;
59
60 /** Implements the code 39 and code 39 extended. The default parameters are:
61  * <pre>
62  *x = 0.8f;
63  *n = 2;
64  *font = BaseFont.createFont("Helvetica", "winansi", false);
65  *size = 8;
66  *baseline = size;
67  *barHeight = size * 3;
68  *textAlignment = Element.ALIGN_CENTER;
69  *generateChecksum = false;
70  *checksumText = false;
71  *startStopText = true;
72  *extended = false;
73  * </pre>
74  *
75  * @author Paulo Soares (psoares@consiste.pt)
76  */

77 public class Barcode39 extends Barcode{
78
79     /** The bars to generate the code.
80      */

81     private static final byte BARS[][] =
82     {
83         {0,0,0,1,1,0,1,0,0},
84         {1,0,0,1,0,0,0,0,1},
85         {0,0,1,1,0,0,0,0,1},
86         {1,0,1,1,0,0,0,0,0},
87         {0,0,0,1,1,0,0,0,1},
88         {1,0,0,1,1,0,0,0,0},
89         {0,0,1,1,1,0,0,0,0},
90         {0,0,0,1,0,0,1,0,1},
91         {1,0,0,1,0,0,1,0,0},
92         {0,0,1,1,0,0,1,0,0},
93         {1,0,0,0,0,1,0,0,1},
94         {0,0,1,0,0,1,0,0,1},
95         {1,0,1,0,0,1,0,0,0},
96         {0,0,0,0,1,1,0,0,1},
97         {1,0,0,0,1,1,0,0,0},
98         {0,0,1,0,1,1,0,0,0},
99         {0,0,0,0,0,1,1,0,1},
100         {1,0,0,0,0,1,1,0,0},
101         {0,0,1,0,0,1,1,0,0},
102         {0,0,0,0,1,1,1,0,0},
103         {1,0,0,0,0,0,0,1,1},
104         {0,0,1,0,0,0,0,1,1},
105         {1,0,1,0,0,0,0,1,0},
106         {0,0,0,0,1,0,0,1,1},
107         {1,0,0,0,1,0,0,1,0},
108         {0,0,1,0,1,0,0,1,0},
109         {0,0,0,0,0,0,1,1,1},
110         {1,0,0,0,0,0,1,1,0},
111         {0,0,1,0,0,0,1,1,0},
112         {0,0,0,0,1,0,1,1,0},
113         {1,1,0,0,0,0,0,0,1},
114         {0,1,1,0,0,0,0,0,1},
115         {1,1,1,0,0,0,0,0,0},
116         {0,1,0,0,1,0,0,0,1},
117         {1,1,0,0,1,0,0,0,0},
118         {0,1,1,0,1,0,0,0,0},
119         {0,1,0,0,0,0,1,0,1},
120         {1,1,0,0,0,0,1,0,0},
121         {0,1,1,0,0,0,1,0,0},
122         {0,1,0,1,0,1,0,0,0},
123         {0,1,0,1,0,0,0,1,0},
124         {0,1,0,0,0,1,0,1,0},
125         {0,0,0,1,0,1,0,1,0},
126         {0,1,0,0,1,0,1,0,0}
127     };
128  
129     /** The index chars to <CODE>BARS</CODE>.
130      */

131     private static final String JavaDoc CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*";
132     
133     /** The character combinations to make the code 39 extended.
134      */

135     private static final String JavaDoc EXTENDED = "%U" +
136         "$A$B$C$D$E$F$G$H$I$J$K$L$M$N$O$P$Q$R$S$T$U$V$W$X$Y$Z" +
137         "%A%B%C%D%E /A/B/C/D/E/F/G/H/I/J/K/L - ./O" +
138         " 0 1 2 3 4 5 6 7 8 9/Z%F%G%H%I%J%V" +
139         " A B C D E F G H I J K L M N O P Q R S T U V W X Y Z" +
140         "%K%L%M%N%O%W" +
141         "+A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+R+S+T+U+V+W+X+Y+Z" +
142         "%P%Q%R%S%T";
143         
144     /** Creates a new Barcode39.
145      */

146     public Barcode39() {
147         try {
148             x = 0.8f;
149             n = 2;
150             font = BaseFont.createFont("Helvetica", "winansi", false);
151             size = 8;
152             baseline = size;
153             barHeight = size * 3;
154             textAlignment = Element.ALIGN_CENTER;
155             generateChecksum = false;
156             checksumText = false;
157             startStopText = true;
158             extended = false;
159         }
160         catch (Exception JavaDoc e) {
161             throw new ExceptionConverter(e);
162         }
163     }
164     
165     /** Creates the bars.
166      * @param text the text to create the bars. This text does not include the start and
167      * stop characters
168      * @return the bars
169      */

170     public static byte[] getBarsCode39(String JavaDoc text) {
171         text = "*" + text + "*";
172         byte bars[] = new byte[text.length() * 10 - 1];
173         for (int k = 0; k < text.length(); ++k) {
174             int idx = CHARS.indexOf(text.charAt(k));
175             if (idx < 0)
176                 throw new IllegalArgumentException JavaDoc("The character '" + text.charAt(k) + "' is illegal in code 39.");
177             System.arraycopy(BARS[idx], 0, bars, k * 10, 9);
178         }
179         return bars;
180     }
181     
182     /** Converts the extended text into a normal, escaped text,
183      * ready to generate bars.
184      * @param text the extended text
185      * @return the escaped text
186      */

187     public static String JavaDoc getCode39Ex(String JavaDoc text) {
188         String JavaDoc out = "";
189         for (int k = 0; k < text.length(); ++k) {
190             char c = text.charAt(k);
191             if (c > 127)
192                 throw new IllegalArgumentException JavaDoc("The character '" + c + "' is illegal in code 39 extended.");
193             char c1 = EXTENDED.charAt(c * 2);
194             char c2 = EXTENDED.charAt(c * 2 + 1);
195             if (c1 != ' ')
196                 out += c1;
197             out += c2;
198         }
199         return out;
200     }
201     
202     /** Calculates the checksum.
203      * @param text the text
204      * @return the checksum
205      */

206     static char getChecksum(String JavaDoc text) {
207         int chk = 0;
208         for (int k = 0; k < text.length(); ++k) {
209             int idx = CHARS.indexOf(text.charAt(k));
210             if (idx < 0)
211                 throw new IllegalArgumentException JavaDoc("The character '" + text.charAt(k) + "' is illegal in code 39.");
212             chk += idx;
213         }
214         return CHARS.charAt(chk % 43);
215     }
216     
217     /** Gets the maximum area that the barcode and the text, if
218      * any, will occupy. The lower left corner is always (0, 0).
219      * @return the size the barcode occupies.
220      */

221     public Rectangle getBarcodeSize() {
222         float fontX = 0;
223         float fontY = 0;
224         String JavaDoc fCode = code;
225         if (extended)
226             fCode = getCode39Ex(code);
227         if (font != null) {
228             if (baseline > 0)
229                 fontY = baseline - font.getFontDescriptor(BaseFont.DESCENT, size);
230             else
231                 fontY = -baseline + size;
232             String JavaDoc fullCode = code;
233             if (generateChecksum && checksumText)
234                 fullCode += getChecksum(fCode);
235             if (startStopText)
236                 fullCode = "*" + fullCode + "*";
237             fontX = font.getWidthPoint(altText != null ? altText : fullCode, size);
238         }
239         int len = fCode.length() + 2;
240         if (generateChecksum)
241             ++len;
242         float fullWidth = len * (6 * x + 3 * x * n) + (len - 1) * x;
243         fullWidth = Math.max(fullWidth, fontX);
244         float fullHeight = barHeight + fontY;
245         return new Rectangle(fullWidth, fullHeight);
246     }
247     
248     /** Places the barcode in a <CODE>PdfContentByte</CODE>. The
249      * barcode is always placed at coodinates (0, 0). Use the
250      * translation matrix to move it elsewhere.<p>
251      * The bars and text are written in the following colors:<p>
252      * <P><TABLE BORDER=1>
253      * <TR>
254      * <TH><P><CODE>barColor</CODE></TH>
255      * <TH><P><CODE>textColor</CODE></TH>
256      * <TH><P>Result</TH>
257      * </TR>
258      * <TR>
259      * <TD><P><CODE>null</CODE></TD>
260      * <TD><P><CODE>null</CODE></TD>
261      * <TD><P>bars and text painted with current fill color</TD>
262      * </TR>
263      * <TR>
264      * <TD><P><CODE>barColor</CODE></TD>
265      * <TD><P><CODE>null</CODE></TD>
266      * <TD><P>bars and text painted with <CODE>barColor</CODE></TD>
267      * </TR>
268      * <TR>
269      * <TD><P><CODE>null</CODE></TD>
270      * <TD><P><CODE>textColor</CODE></TD>
271      * <TD><P>bars painted with current color<br>text painted with <CODE>textColor</CODE></TD>
272      * </TR>
273      * <TR>
274      * <TD><P><CODE>barColor</CODE></TD>
275      * <TD><P><CODE>textColor</CODE></TD>
276      * <TD><P>bars painted with <CODE>barColor</CODE><br>text painted with <CODE>textColor</CODE></TD>
277      * </TR>
278      * </TABLE>
279      * @param cb the <CODE>PdfContentByte</CODE> where the barcode will be placed
280      * @param barColor the color of the bars. It can be <CODE>null</CODE>
281      * @param textColor the color of the text. It can be <CODE>null</CODE>
282      * @return the dimensions the barcode occupies
283      */

284     public Rectangle placeBarcode(PdfContentByte cb, Color JavaDoc barColor, Color JavaDoc textColor) {
285         String JavaDoc fullCode = code;
286         float fontX = 0;
287         String JavaDoc bCode = code;
288         if (extended)
289             bCode = getCode39Ex(code);
290         if (font != null) {
291             if (generateChecksum && checksumText)
292                 fullCode += getChecksum(bCode);
293             if (startStopText)
294                 fullCode = "*" + fullCode + "*";
295             fontX = font.getWidthPoint(fullCode = altText != null ? altText : fullCode, size);
296         }
297         if (generateChecksum)
298             bCode += getChecksum(bCode);
299         int len = bCode.length() + 2;
300         float fullWidth = len * (6 * x + 3 * x * n) + (len - 1) * x;
301         float barStartX = 0;
302         float textStartX = 0;
303         switch (textAlignment) {
304             case Element.ALIGN_LEFT:
305                 break;
306             case Element.ALIGN_RIGHT:
307                 if (fontX > fullWidth)
308                     barStartX = fontX - fullWidth;
309                 else
310                     textStartX = fullWidth - fontX;
311                 break;
312             default:
313                 if (fontX > fullWidth)
314                     barStartX = (fontX - fullWidth) / 2;
315                 else
316                     textStartX = (fullWidth - fontX) / 2;
317                 break;
318         }
319         float barStartY = 0;
320         float textStartY = 0;
321         if (font != null) {
322             if (baseline <= 0)
323                 textStartY = barHeight - baseline;
324             else {
325                 textStartY = -font.getFontDescriptor(BaseFont.DESCENT, size);
326                 barStartY = textStartY + baseline;
327             }
328         }
329         byte bars[] = getBarsCode39(bCode);
330         boolean print = true;
331         if (barColor != null)
332             cb.setColorFill(barColor);
333         for (int k = 0; k < bars.length; ++k) {
334             float w = (bars[k] == 0 ? x : x * n);
335             if (print)
336                 cb.rectangle(barStartX, barStartY, w - inkSpreading, barHeight);
337             print = !print;
338             barStartX += w;
339         }
340         cb.fill();
341         if (font != null) {
342             if (textColor != null)
343                 cb.setColorFill(textColor);
344             cb.beginText();
345             cb.setFontAndSize(font, size);
346             cb.setTextMatrix(textStartX, textStartY);
347             cb.showText(fullCode);
348             cb.endText();
349         }
350         return getBarcodeSize();
351     }
352     
353     /** Creates a <CODE>java.awt.Image</CODE>. This image only
354      * contains the bars without any text.
355      * @param foreground the color of the bars
356      * @param background the color of the background
357      * @return the image
358      */

359     public java.awt.Image JavaDoc createAwtImage(Color JavaDoc foreground, Color JavaDoc background) {
360         int f = foreground.getRGB();
361         int g = background.getRGB();
362         Canvas JavaDoc canvas = new Canvas JavaDoc();
363
364         String JavaDoc bCode = code;
365         if (extended)
366             bCode = getCode39Ex(code);
367         if (generateChecksum)
368             bCode += getChecksum(bCode);
369         int len = bCode.length() + 2;
370         int nn = (int)n;
371         int fullWidth = len * (6 + 3 * nn) + (len - 1);
372         byte bars[] = getBarsCode39(bCode);
373         boolean print = true;
374         int ptr = 0;
375         int height = (int)barHeight;
376         int pix[] = new int[fullWidth * height];
377         for (int k = 0; k < bars.length; ++k) {
378             int w = (bars[k] == 0 ? 1 : nn);
379             int c = g;
380             if (print)
381                 c = f;
382             print = !print;
383             for (int j = 0; j < w; ++j)
384                 pix[ptr++] = c;
385         }
386         for (int k = fullWidth; k < pix.length; k += fullWidth) {
387             System.arraycopy(pix, 0, pix, k, fullWidth);
388         }
389         Image JavaDoc img = canvas.createImage(new MemoryImageSource JavaDoc(fullWidth, height, pix, 0, fullWidth));
390         
391         return img;
392     }
393 }
394
Popular Tags