1 49 package com.lowagie.text.pdf; 50 import java.awt.Canvas ; 51 import java.awt.Color ; 52 import java.awt.Image ; 53 import java.awt.image.MemoryImageSource ; 54 55 import com.lowagie.text.Element; 56 import com.lowagie.text.ExceptionConverter; 57 import com.lowagie.text.Rectangle; 58 59 80 public class Barcode128 extends Barcode{ 81 82 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 196 private static final byte BARS_STOP[] = {2, 3, 3, 1, 1, 1, 2}; 197 199 public static final char CODE_AB_TO_C = 99; 200 202 public static final char CODE_AC_TO_B = 100; 203 205 public static final char CODE_BC_TO_A = 101; 206 208 public static final char FNC1_INDEX = 102; 209 211 public static final char START_A = 103; 212 214 public static final char START_B = 104; 215 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 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 e) { 244 throw new ExceptionConverter(e); 245 } 246 } 247 248 253 public static String removeFNC1(String code) { 254 int len = code.length(); 255 StringBuffer buf = new StringBuffer (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 269 public static String getHumanReadableUCCEAN(String code) { 270 StringBuffer buf = new StringBuffer (); 271 String 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 e) { 309 } 311 buf.append(removeFNC1(code)); 312 return buf.toString(); 313 } 314 315 322 static boolean isNextDigits(String 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 349 static String getPackedRawDigits(String text, int textIndex, int numDigits) { 350 String 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 373 public static String getRawText(String text, boolean ucc) { 374 String 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 ("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 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 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 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 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 503 public static byte[] getBarsCode128Raw(String 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 524 public Rectangle getBarcodeSize() { 525 float fontX = 0; 526 float fontY = 0; 527 String 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 599 public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) { 600 String 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 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 687 public java.awt.Image createAwtImage(Color foreground, Color background) { 688 int f = foreground.getRGB(); 689 int g = background.getRGB(); 690 Canvas canvas = new Canvas (); 691 String 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 img = canvas.createImage(new MemoryImageSource (fullWidth, height, pix, 0, fullWidth)); 723 724 return img; 725 } 726 727 734 public void setCode(String code) { 735 if (getCodeType() == Barcode128.CODE128_UCC && code.startsWith("(")) { 736 int idx = 0; 737 String ret = ""; 738 while (idx >= 0) { 739 int end = code.indexOf(')', idx); 740 if (end < 0) 741 throw new IllegalArgumentException ("Badly formed UCC string: " + code); 742 String sai = code.substring(idx + 1, end); 743 if (sai.length() < 2) 744 throw new IllegalArgumentException ("AI too short: (" + sai + ")"); 745 int ai = Integer.parseInt(sai); 746 int len = ais.get(ai); 747 if (len == 0) 748 throw new IllegalArgumentException ("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 ("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 |