1 58 package org.krysalis.barcode.impl; 59 60 65 public class DefaultCode128Encoder implements Code128Encoder { 66 67 private static final int CODESET_A = 1; 68 private static final int CODESET_B = 2; 69 private static final int CODESET_C = 4; 70 71 private static final int START_A = 103; 72 private static final int START_B = 104; 73 private static final int START_C = 105; 74 private static final int GOTO_A = 101; 75 private static final int GOTO_B = 100; 76 private static final int GOTO_C = 99; 77 private static final int FNC_1 = 102; 78 private static final int FNC_2 = 97; 79 private static final int FNC_3 = 96; 80 private static final int SHIFT = 98; 81 82 83 private final boolean inCodeset(char c, int codeset) { 84 switch (codeset) { 85 case CODESET_A: return Code128LogicImpl.isInCodeSetA(c); 86 case CODESET_B: return Code128LogicImpl.isInCodeSetB(c); 87 case CODESET_C: return Code128LogicImpl.canBeInCodeSetC(c); 88 default: throw new IllegalArgumentException ("Invalid codeset"); 89 } 90 } 91 92 private boolean needA(char c) { 93 return (c < 32); 95 } 96 97 private boolean needB(char c) { 98 return (c >= 96) && (c < 128); 100 } 101 102 private int determineAorB(char c) { 103 if (needA(c)) { 104 return CODESET_A; 105 } else if (Code128LogicImpl.isInCodeSetB(c)) { 106 return CODESET_B; 107 } 108 return 0; 109 } 110 111 private int getStartControl(int codeset) { 112 switch (codeset) { 113 case CODESET_A: return START_A; 114 case CODESET_B: return START_B; 115 case CODESET_C: return START_C; 116 default: throw new IllegalArgumentException ("Invalid codeset"); 117 } 118 } 119 120 private boolean nextLotInCodeset(String msg, int startpos, int codeset, int count) { 121 if (startpos + count > msg.length()) { 122 return false; 124 } 125 for (int i = 0; i < count; i++) { 126 if (!inCodeset(msg.charAt(startpos + i), codeset)) { 127 return false; 128 } 129 } 130 return true; 131 } 132 133 private int countCharsInSameCodeset(String msg, int startpos, int codeset) { 134 int count = 0; 135 while (startpos + count < msg.length()) { 136 if (!inCodeset(msg.charAt(startpos + count), codeset)) { 137 break; 138 } 139 count++; 140 } 141 return count; 142 } 143 144 private int encodeAorB(char c, int codeset) { 145 if (c == Code128LogicImpl.FNC_1) { 147 return FNC_1; 148 } 149 if (c == Code128LogicImpl.FNC_2) { 150 return FNC_2; 151 } 152 if (c == Code128LogicImpl.FNC_3) { 153 return FNC_3; 154 } 155 if (c == Code128LogicImpl.FNC_4) { 156 if (codeset == CODESET_A) { 157 return 101; 158 } else { 159 return 100; 160 } 161 } 162 if (codeset == CODESET_A) { 164 if ((c >= 0) && (c < 32)) { 165 return c + 64; 166 } else if ((c >= 32) && (c <= 95)) { 167 return c - 32; 168 } else { 169 throw new IllegalArgumentException ("Illegal character: " + c); 170 } 171 } else if (codeset == CODESET_B) { 172 if ((c >= 32) && (c < 128)) { 173 return c - 32; 174 } else { 175 throw new IllegalArgumentException ("Illegal character: " + c); 176 } 177 } else { 178 throw new IllegalArgumentException ("Only A or B allowed"); 179 } 180 } 181 182 183 public int[] encode(String msg) { 184 int[] encoded = new int[msg.length() * 2 + 5]; 186 int currentCodeset; 187 int respos = 0; 188 int msgpos = 0; 189 if ((msg.length() == 2) 191 && nextLotInCodeset(msg, 0, CODESET_C, 2)) { 192 currentCodeset = CODESET_C; 193 } else if ((msg.length() >= 4) 194 && nextLotInCodeset(msg, 0, CODESET_C, 4)) { 195 currentCodeset = CODESET_C; 196 } else { 197 currentCodeset = determineAorB(msg.charAt(0)); 198 if (currentCodeset == 0) { 199 currentCodeset = CODESET_B; } 201 } 202 encoded[respos] = getStartControl(currentCodeset); 203 respos++; 204 205 while (msgpos < msg.length()) { 207 switch (currentCodeset) { 208 case CODESET_C: 209 if (msg.charAt(msgpos) == Code128LogicImpl.FNC_1) { 210 encoded[respos] = FNC_1; 212 respos++; 213 msgpos++; 214 } else if (nextLotInCodeset(msg, msgpos, CODESET_C, 2)) { 215 encoded[respos] = 217 Character.digit(msg.charAt(msgpos), 10) * 10 218 + Character.digit(msg.charAt(msgpos + 1), 10); 219 respos++; 220 msgpos += 2; 221 } else { 222 currentCodeset = determineAorB(msg.charAt(msgpos)); 224 if (currentCodeset == 0) { 225 currentCodeset = CODESET_B; 226 } 227 if (currentCodeset == CODESET_A) { 228 encoded[respos] = GOTO_A; 229 } else { 230 encoded[respos] = GOTO_B; 231 } 232 respos++; 233 } 234 break; 235 case CODESET_B: 236 case CODESET_A: 237 int c = countCharsInSameCodeset(msg, msgpos, CODESET_C); 238 if (c >= 4) { 239 if ((c % 2) != 0) { 241 encoded[respos] = Character.digit(msg.charAt(msgpos), 10) + 16; 244 respos++; 245 msgpos++; 246 } 247 encoded[respos] = GOTO_C; 248 respos++; 249 currentCodeset = CODESET_C; 250 } else if ((currentCodeset == CODESET_A) && needB(msg.charAt(msgpos))) { 251 if (msgpos + 1 < msg.length()) { 253 int preview = determineAorB(msg.charAt(msgpos + 1)); 254 if (preview == CODESET_B) { 255 encoded[respos] = GOTO_B; 257 respos++; 258 currentCodeset = CODESET_B; 259 } 260 } 261 if (currentCodeset == CODESET_A) { 262 encoded[respos] = SHIFT; 264 respos++; 265 encoded[respos] = encodeAorB(msg.charAt(msgpos), CODESET_B); 266 respos++; 267 msgpos++; 268 } 269 } else if ((currentCodeset == CODESET_B) && needA(msg.charAt(msgpos))) { 270 if (msgpos + 1 < msg.length()) { 272 int preview = determineAorB(msg.charAt(msgpos + 1)); 273 if (preview == CODESET_A) { 274 encoded[respos] = GOTO_A; 276 respos++; 277 currentCodeset = CODESET_A; 278 } 279 } 280 if (currentCodeset == CODESET_B) { 281 encoded[respos] = SHIFT; 283 respos++; 284 encoded[respos] = encodeAorB(msg.charAt(msgpos), CODESET_A); 285 respos++; 286 msgpos++; 287 } 288 } else { 289 encoded[respos] = encodeAorB(msg.charAt(msgpos), currentCodeset); 290 respos++; 291 msgpos++; 292 } 293 break; 294 } 295 } 296 int[] result = new int[respos]; 297 System.arraycopy(encoded, 0, result, 0, result.length); 298 return result; 299 } 300 301 302 } 303 | Popular Tags |