1 58 package org.krysalis.barcode.impl; 59 60 import org.krysalis.barcode.BarGroup; 61 import org.krysalis.barcode.ChecksumMode; 62 import org.krysalis.barcode.ClassicBarcodeLogicHandler; 63 64 70 public class Code39LogicImpl { 71 72 private static final char[] CHARACTERS = 73 {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 74 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 75 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 76 'U', 'V', 'W', 'X', 'Y', 'Z', 77 '-', '.', ' ', '$', '/', '+', '%', '*'}; 78 79 private static final char STARTSTOP = '*'; 81 private static final byte[][] CHARSET = 82 {{0, 0, 0, 1, 1, 0, 1, 0, 0}, {1, 0, 0, 1, 0, 0, 0, 0, 1}, {0, 0, 1, 1, 0, 0, 0, 0, 1}, {1, 0, 1, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 1, 0, 0, 0, 1}, {1, 0, 0, 1, 1, 0, 0, 0, 0}, {0, 0, 1, 1, 1, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 1, 0, 1}, {1, 0, 0, 1, 0, 0, 1, 0, 0}, {0, 0, 1, 1, 0, 0, 1, 0, 0}, {1, 0, 0, 0, 0, 1, 0, 0, 1}, {0, 0, 1, 0, 0, 1, 0, 0, 1}, {1, 0, 1, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 1, 1, 0, 0, 1}, {1, 0, 0, 0, 1, 1, 0, 0, 0}, {0, 0, 1, 0, 1, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 1, 1, 0, 1}, {1, 0, 0, 0, 0, 1, 1, 0, 0}, {0, 0, 1, 0, 0, 1, 1, 0, 0}, {0, 0, 0, 0, 1, 1, 1, 0, 0}, {1, 0, 0, 0, 0, 0, 0, 1, 1}, {0, 0, 1, 0, 0, 0, 0, 1, 1}, {1, 0, 1, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 1, 0, 0, 1, 1}, {1, 0, 0, 0, 1, 0, 0, 1, 0}, {0, 0, 1, 0, 1, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 1, 1, 1}, {1, 0, 0, 0, 0, 0, 1, 1, 0}, {0, 0, 1, 0, 0, 0, 1, 1, 0}, {0, 0, 0, 0, 1, 0, 1, 1, 0}, {1, 1, 0, 0, 0, 0, 0, 0, 1}, {0, 1, 1, 0, 0, 0, 0, 0, 1}, {1, 1, 1, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 1, 0, 0, 0, 1}, {1, 1, 0, 0, 1, 0, 0, 0, 0}, {0, 1, 1, 0, 1, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 1, 0, 1}, {1, 1, 0, 0, 0, 0, 1, 0, 0}, {0, 1, 1, 0, 0, 0, 1, 0, 0}, {0, 1, 0, 1, 0, 1, 0, 0, 0}, {0, 1, 0, 1, 0, 0, 0, 1, 0}, {0, 1, 0, 0, 0, 1, 0, 1, 0}, {0, 0, 0, 1, 0, 1, 0, 1, 0}, {0, 1, 0, 0, 1, 0, 1, 0, 0}}; 127 private ChecksumMode checksumMode = ChecksumMode.CP_AUTO; 128 129 130 134 public Code39LogicImpl(ChecksumMode mode) { 135 this.checksumMode = mode; 136 } 137 138 142 public ChecksumMode getChecksumMode() { 143 return this.checksumMode; 144 } 145 146 152 public static char calcChecksum(String msg) { 153 int checksum = 0; 154 for (int i = 0; i < msg.length(); i++) { 155 final int chidx = getCharIndex(msg.charAt(i)); 156 if (chidx >= 0) { 157 checksum += chidx; 158 } else { 159 throw new IllegalArgumentException ("Invalid character: " + msg.charAt(i)); 160 } 161 } 162 return CHARACTERS[checksum % 43]; 163 } 164 165 166 171 public static boolean validateChecksum(String msg) { 172 char actual = msg.charAt(msg.length() - 1); 173 char expected = calcChecksum(msg.substring(0, msg.length() - 1)); 174 return (actual == expected); 175 } 176 177 private static int getCharIndex(char ch) { 178 final char effch; 179 if ((ch >= 'a') && (ch <= 'z')) { 180 effch = Character.toUpperCase(ch); 181 } else { 182 effch = ch; 183 } 184 for (int i = 0; i < CHARACTERS.length; i++) { 185 if (effch == CHARACTERS[i]) { 186 return i; 187 } 188 } 189 return -1; 190 } 191 192 193 private static boolean isValidChar(char ch) { 194 if (ch == STARTSTOP) return false; 195 return (getCharIndex(ch) >= 0); 196 } 197 198 private int widthAt(char ch, int index) { 199 final int chidx = getCharIndex(ch); 200 if (chidx >= 0) { 201 int binary = CHARSET[chidx][index]; 202 return binary + 1; 203 } else { 204 throw new IllegalArgumentException ("Invalid character: " + ch); 205 } 206 } 207 208 213 protected void encodeChar(ClassicBarcodeLogicHandler logic, char c) { 214 logic.startBarGroup(BarGroup.MSG_CHARACTER, new Character (c).toString()); 215 for (byte i = 0; i < 9; i++) { 216 int width = widthAt(c, i); 217 boolean black = (i % 2 == 0); 218 logic.addBar(black, width); 219 } 220 logic.endBarGroup(); 221 } 222 223 private void addIntercharacterGap(ClassicBarcodeLogicHandler logic) { 224 logic.addBar(false, -1); } 227 228 private void handleChecksum(StringBuffer sb) { 229 if (getChecksumMode() == ChecksumMode.CP_ADD) { 230 sb.append(calcChecksum(sb.toString())); 231 } else if (getChecksumMode() == ChecksumMode.CP_CHECK) { 232 if (!validateChecksum(sb.toString())) { 233 throw new IllegalArgumentException ("Message '" 234 + sb.toString() 235 + "' has a bad checksum. Expected: " 236 + calcChecksum(sb.toString())); 237 } 238 } else if (getChecksumMode() == ChecksumMode.CP_IGNORE) { 239 return; 240 } else if (getChecksumMode() == ChecksumMode.CP_AUTO) { 241 return; } 243 } 244 245 250 public void generateBarcodeLogic(ClassicBarcodeLogicHandler logic, String msg) { 251 logic.startBarcode(msg); 252 253 StringBuffer sb = new StringBuffer (msg); 254 255 handleChecksum(sb); 257 258 logic.startBarGroup(BarGroup.START_CHARACTER, new Character (STARTSTOP).toString()); 260 encodeChar(logic, STARTSTOP); 261 logic.endBarGroup(); 262 263 for (int i = 0; i < sb.length(); i++) { 264 addIntercharacterGap(logic); 265 266 final char ch = sb.charAt(i); 267 if (!isValidChar(ch)) throw new IllegalArgumentException ("Invalid character: " + ch); 268 encodeChar(logic, ch); 269 } 270 271 addIntercharacterGap(logic); 272 273 logic.startBarGroup(BarGroup.STOP_CHARACTER, new Character (STARTSTOP).toString()); 275 encodeChar(logic, STARTSTOP); 276 logic.endBarGroup(); 277 278 logic.endBarcode(); 279 } 280 281 282 } 283 | Popular Tags |