001/* 002 * $Id: BarcodePostnet.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; 045import java.awt.Canvas; 046import java.awt.Image; 047import java.awt.image.MemoryImageSource; 048 049import com.itextpdf.text.Rectangle; 050import com.itextpdf.text.BaseColor; 051 052/** Implements the Postnet and Planet barcodes. The default parameters are: 053 * <pre> 054 *n = 72f / 22f; // distance between bars 055 *x = 0.02f * 72f; // bar width 056 *barHeight = 0.125f * 72f; // height of the tall bars 057 *size = 0.05f * 72f; // height of the short bars 058 *codeType = POSTNET; // type of code 059 * </pre> 060 * 061 * @author Paulo Soares 062 */ 063public class BarcodePostnet extends Barcode{ 064 065 /** The bars for each character. 066 */ 067 private static final byte BARS[][] = 068 { 069 {1,1,0,0,0}, 070 {0,0,0,1,1}, 071 {0,0,1,0,1}, 072 {0,0,1,1,0}, 073 {0,1,0,0,1}, 074 {0,1,0,1,0}, 075 {0,1,1,0,0}, 076 {1,0,0,0,1}, 077 {1,0,0,1,0}, 078 {1,0,1,0,0} 079 }; 080 081 /** Creates new BarcodePostnet */ 082 public BarcodePostnet() { 083 n = 72f / 22f; // distance between bars 084 x = 0.02f * 72f; // bar width 085 barHeight = 0.125f * 72f; // height of the tall bars 086 size = 0.05f * 72f; // height of the short bars 087 codeType = POSTNET; // type of code 088 } 089 090 /** Creates the bars for Postnet. 091 * @param text the code to be created without checksum 092 * @return the bars 093 */ 094 public static byte[] getBarsPostnet(String text) { 095 int total = 0; 096 for (int k = text.length() - 1; k >= 0; --k) { 097 int n = text.charAt(k) - '0'; 098 total += n; 099 } 100 text += (char)(((10 - (total % 10)) % 10) + '0'); 101 byte bars[] = new byte[text.length() * 5 + 2]; 102 bars[0] = 1; 103 bars[bars.length - 1] = 1; 104 for (int k = 0; k < text.length(); ++k) { 105 int c = text.charAt(k) - '0'; 106 System.arraycopy(BARS[c], 0, bars, k * 5 + 1, 5); 107 } 108 return bars; 109 } 110 111 /** Gets the maximum area that the barcode and the text, if 112 * any, will occupy. The lower left corner is always (0, 0). 113 * @return the size the barcode occupies. 114 */ 115 public Rectangle getBarcodeSize() { 116 float width = ((code.length() + 1) * 5 + 1) * n + x; 117 return new Rectangle(width, barHeight); 118 } 119 120 /** Places the barcode in a <CODE>PdfContentByte</CODE>. The 121 * barcode is always placed at coordinates (0, 0). Use the 122 * translation matrix to move it elsewhere.<p> 123 * The bars and text are written in the following colors:<p> 124 * <P><TABLE BORDER=1> 125 * <TR> 126 * <TH><P><CODE>barColor</CODE></TH> 127 * <TH><P><CODE>textColor</CODE></TH> 128 * <TH><P>Result</TH> 129 * </TR> 130 * <TR> 131 * <TD><P><CODE>null</CODE></TD> 132 * <TD><P><CODE>null</CODE></TD> 133 * <TD><P>bars and text painted with current fill color</TD> 134 * </TR> 135 * <TR> 136 * <TD><P><CODE>barColor</CODE></TD> 137 * <TD><P><CODE>null</CODE></TD> 138 * <TD><P>bars and text painted with <CODE>barColor</CODE></TD> 139 * </TR> 140 * <TR> 141 * <TD><P><CODE>null</CODE></TD> 142 * <TD><P><CODE>textColor</CODE></TD> 143 * <TD><P>bars painted with current color<br>text painted with <CODE>textColor</CODE></TD> 144 * </TR> 145 * <TR> 146 * <TD><P><CODE>barColor</CODE></TD> 147 * <TD><P><CODE>textColor</CODE></TD> 148 * <TD><P>bars painted with <CODE>barColor</CODE><br>text painted with <CODE>textColor</CODE></TD> 149 * </TR> 150 * </TABLE> 151 * @param cb the <CODE>PdfContentByte</CODE> where the barcode will be placed 152 * @param barColor the color of the bars. It can be <CODE>null</CODE> 153 * @param textColor the color of the text. It can be <CODE>null</CODE> 154 * @return the dimensions the barcode occupies 155 */ 156 public Rectangle placeBarcode(PdfContentByte cb, BaseColor barColor, BaseColor textColor) { 157 if (barColor != null) 158 cb.setColorFill(barColor); 159 byte bars[] = getBarsPostnet(code); 160 byte flip = 1; 161 if (codeType == PLANET) { 162 flip = 0; 163 bars[0] = 0; 164 bars[bars.length - 1] = 0; 165 } 166 float startX = 0; 167 for (int k = 0; k < bars.length; ++k) { 168 cb.rectangle(startX, 0, x - inkSpreading, bars[k] == flip ? barHeight : size); 169 startX += n; 170 } 171 cb.fill(); 172 return getBarcodeSize(); 173 } 174 175 /** Creates a <CODE>java.awt.Image</CODE>. This image only 176 * contains the bars without any text. 177 * @param foreground the color of the bars 178 * @param background the color of the background 179 * @return the image 180 * 181 */ 182 public java.awt.Image createAwtImage(java.awt.Color foreground, java.awt.Color background) { 183 int f = foreground.getRGB(); 184 int g = background.getRGB(); 185 Canvas canvas = new Canvas(); 186 int barWidth = (int)x; 187 if (barWidth <= 0) 188 barWidth = 1; 189 int barDistance = (int)n; 190 if (barDistance <= barWidth) 191 barDistance = barWidth + 1; 192 int barShort = (int)size; 193 if (barShort <= 0) 194 barShort = 1; 195 int barTall = (int)barHeight; 196 if (barTall <= barShort) 197 barTall = barShort + 1; 198 int width = ((code.length() + 1) * 5 + 1) * barDistance + barWidth; 199 int pix[] = new int[width * barTall]; 200 byte bars[] = getBarsPostnet(code); 201 byte flip = 1; 202 if (codeType == PLANET) { 203 flip = 0; 204 bars[0] = 0; 205 bars[bars.length - 1] = 0; 206 } 207 int idx = 0; 208 for (int k = 0; k < bars.length; ++k) { 209 boolean dot = (bars[k] == flip); 210 for (int j = 0; j < barDistance; ++j) { 211 pix[idx + j] = ((dot && j < barWidth) ? f : g); 212 } 213 idx += barDistance; 214 } 215 int limit = width * (barTall - barShort); 216 for (int k = width; k < limit; k += width) 217 System.arraycopy(pix, 0, pix, k, width); 218 idx = limit; 219 for (int k = 0; k < bars.length; ++k) { 220 for (int j = 0; j < barDistance; ++j) { 221 pix[idx + j] = ((j < barWidth) ? f : g); 222 } 223 idx += barDistance; 224 } 225 for (int k = limit + width; k < pix.length; k += width) 226 System.arraycopy(pix, limit, pix, k, width); 227 Image img = canvas.createImage(new MemoryImageSource(width, barTall, pix, 0, width)); 228 229 return img; 230 } 231}