1 47 package com.lowagie.text.pdf; 48 49 import java.awt.Canvas ; 50 import java.awt.Color ; 51 import java.awt.Image ; 52 import java.awt.image.MemoryImageSource ; 53 import java.util.Arrays ; 54 55 import com.lowagie.text.ExceptionConverter; 56 import com.lowagie.text.Rectangle; 57 58 73 public class BarcodeEAN extends Barcode{ 74 75 76 private static final int GUARD_EMPTY[] = {}; 77 78 private static final int GUARD_UPCA[] = {0, 2, 4, 6, 28, 30, 52, 54, 56, 58}; 79 80 private static final int GUARD_EAN13[] = {0, 2, 28, 30, 56, 58}; 81 82 private static final int GUARD_EAN8[] = {0, 2, 20, 22, 40, 42}; 83 84 private static final int GUARD_UPCE[] = {0, 2, 28, 30, 32}; 85 86 private static final float TEXTPOS_EAN13[] = {6.5f, 13.5f, 20.5f, 27.5f, 34.5f, 41.5f, 53.5f, 60.5f, 67.5f, 74.5f, 81.5f, 88.5f}; 87 88 private static final float TEXTPOS_EAN8[] = {6.5f, 13.5f, 20.5f, 27.5f, 39.5f, 46.5f, 53.5f, 60.5f}; 89 90 private static final byte BARS[][] = 91 { 92 {3, 2, 1, 1}, {2, 2, 2, 1}, {2, 1, 2, 2}, {1, 4, 1, 1}, {1, 1, 3, 2}, {1, 2, 3, 1}, {1, 1, 1, 4}, {1, 3, 1, 2}, {1, 2, 1, 3}, {3, 1, 1, 2} }; 103 104 105 private static final int TOTALBARS_EAN13 = 11 + 12 * 4; 106 107 private static final int TOTALBARS_EAN8 = 11 + 8 * 4; 108 109 private static final int TOTALBARS_UPCE = 9 + 6 * 4; 110 111 private static final int TOTALBARS_SUPP2 = 13; 112 113 private static final int TOTALBARS_SUPP5 = 31; 114 115 private static final int ODD = 0; 116 117 private static final int EVEN = 1; 118 119 120 private static final byte PARITY13[][] = 121 { 122 {ODD, ODD, ODD, ODD, ODD, ODD}, {ODD, ODD, EVEN, ODD, EVEN, EVEN}, {ODD, ODD, EVEN, EVEN, ODD, EVEN}, {ODD, ODD, EVEN, EVEN, EVEN, ODD}, {ODD, EVEN, ODD, ODD, EVEN, EVEN}, {ODD, EVEN, EVEN, ODD, ODD, EVEN}, {ODD, EVEN, EVEN, EVEN, ODD, ODD}, {ODD, EVEN, ODD, EVEN, ODD, EVEN}, {ODD, EVEN, ODD, EVEN, EVEN, ODD}, {ODD, EVEN, EVEN, ODD, EVEN, ODD} }; 133 134 135 private static final byte PARITY2[][] = 136 { 137 {ODD, ODD}, {ODD, EVEN}, {EVEN, ODD}, {EVEN, EVEN} }; 142 143 144 private static final byte PARITY5[][] = 145 { 146 {EVEN, EVEN, ODD, ODD, ODD}, {EVEN, ODD, EVEN, ODD, ODD}, {EVEN, ODD, ODD, EVEN, ODD}, {EVEN, ODD, ODD, ODD, EVEN}, {ODD, EVEN, EVEN, ODD, ODD}, {ODD, ODD, EVEN, EVEN, ODD}, {ODD, ODD, ODD, EVEN, EVEN}, {ODD, EVEN, ODD, EVEN, ODD}, {ODD, EVEN, ODD, ODD, EVEN}, {ODD, ODD, EVEN, ODD, EVEN} }; 157 158 159 private static final byte PARITYE[][] = 160 { 161 {EVEN, EVEN, EVEN, ODD, ODD, ODD}, {EVEN, EVEN, ODD, EVEN, ODD, ODD}, {EVEN, EVEN, ODD, ODD, EVEN, ODD}, {EVEN, EVEN, ODD, ODD, ODD, EVEN}, {EVEN, ODD, EVEN, EVEN, ODD, ODD}, {EVEN, ODD, ODD, EVEN, EVEN, ODD}, {EVEN, ODD, ODD, ODD, EVEN, EVEN}, {EVEN, ODD, EVEN, ODD, EVEN, ODD}, {EVEN, ODD, EVEN, ODD, ODD, EVEN}, {EVEN, ODD, ODD, EVEN, ODD, EVEN} }; 172 173 174 public BarcodeEAN() { 175 try { 176 x = 0.8f; 177 font = BaseFont.createFont("Helvetica", "winansi", false); 178 size = 8; 179 baseline = size; 180 barHeight = size * 3; 181 guardBars = true; 182 codeType = EAN13; 183 code = ""; 184 } 185 catch (Exception e) { 186 throw new ExceptionConverter(e); 187 } 188 } 189 190 194 public static int calculateEANParity(String code) { 195 int mul = 3; 196 int total = 0; 197 for (int k = code.length() - 1; k >= 0; --k) { 198 int n = code.charAt(k) - '0'; 199 total += mul * n; 200 mul ^= 2; 201 } 202 return (10 - (total % 10)) % 10; 203 } 204 205 211 static public String convertUPCAtoUPCE(String text) { 212 if (text.length() != 12 || !(text.startsWith("0") || text.startsWith("1"))) 213 return null; 214 if (text.substring(3, 6).equals("000") || text.substring(3, 6).equals("100") 215 || text.substring(3, 6).equals("200")) { 216 if (text.substring(6, 8).equals("00")) 217 return text.substring(0, 1) + text.substring(1, 3) + text.substring(8, 11) + text.substring(3, 4) + text.substring(11); 218 } 219 else if (text.substring(4, 6).equals("00")) { 220 if (text.substring(6, 9).equals("000")) 221 return text.substring(0, 1) + text.substring(1, 4) + text.substring(9, 11) + "3" + text.substring(11); 222 } 223 else if (text.substring(5, 6).equals("0")) { 224 if (text.substring(6, 10).equals("0000")) 225 return text.substring(0, 1) + text.substring(1, 5) + text.substring(10, 11) + "4" + text.substring(11); 226 } 227 else if (text.charAt(10) >= '5') { 228 if (text.substring(6, 10).equals("0000")) 229 return text.substring(0, 1) + text.substring(1, 6) + text.substring(10, 11) + text.substring(11); 230 } 231 return null; 232 } 233 234 238 public static byte[] getBarsEAN13(String _code) { 239 int code[] = new int[_code.length()]; 240 for (int k = 0; k < code.length; ++k) 241 code[k] = _code.charAt(k) - '0'; 242 byte bars[] = new byte[TOTALBARS_EAN13]; 243 int pb = 0; 244 bars[pb++] = 1; 245 bars[pb++] = 1; 246 bars[pb++] = 1; 247 byte sequence[] = PARITY13[code[0]]; 248 for (int k = 0; k < sequence.length; ++k) { 249 int c = code[k + 1]; 250 byte stripes[] = BARS[c]; 251 if (sequence[k] == ODD) { 252 bars[pb++] = stripes[0]; 253 bars[pb++] = stripes[1]; 254 bars[pb++] = stripes[2]; 255 bars[pb++] = stripes[3]; 256 } 257 else { 258 bars[pb++] = stripes[3]; 259 bars[pb++] = stripes[2]; 260 bars[pb++] = stripes[1]; 261 bars[pb++] = stripes[0]; 262 } 263 } 264 bars[pb++] = 1; 265 bars[pb++] = 1; 266 bars[pb++] = 1; 267 bars[pb++] = 1; 268 bars[pb++] = 1; 269 for (int k = 7; k < 13; ++k) { 270 int c = code[k]; 271 byte stripes[] = BARS[c]; 272 bars[pb++] = stripes[0]; 273 bars[pb++] = stripes[1]; 274 bars[pb++] = stripes[2]; 275 bars[pb++] = stripes[3]; 276 } 277 bars[pb++] = 1; 278 bars[pb++] = 1; 279 bars[pb++] = 1; 280 return bars; 281 } 282 283 287 public static byte[] getBarsEAN8(String _code) { 288 int code[] = new int[_code.length()]; 289 for (int k = 0; k < code.length; ++k) 290 code[k] = _code.charAt(k) - '0'; 291 byte bars[] = new byte[TOTALBARS_EAN8]; 292 int pb = 0; 293 bars[pb++] = 1; 294 bars[pb++] = 1; 295 bars[pb++] = 1; 296 for (int k = 0; k < 4; ++k) { 297 int c = code[k]; 298 byte stripes[] = BARS[c]; 299 bars[pb++] = stripes[0]; 300 bars[pb++] = stripes[1]; 301 bars[pb++] = stripes[2]; 302 bars[pb++] = stripes[3]; 303 } 304 bars[pb++] = 1; 305 bars[pb++] = 1; 306 bars[pb++] = 1; 307 bars[pb++] = 1; 308 bars[pb++] = 1; 309 for (int k = 4; k < 8; ++k) { 310 int c = code[k]; 311 byte stripes[] = BARS[c]; 312 bars[pb++] = stripes[0]; 313 bars[pb++] = stripes[1]; 314 bars[pb++] = stripes[2]; 315 bars[pb++] = stripes[3]; 316 } 317 bars[pb++] = 1; 318 bars[pb++] = 1; 319 bars[pb++] = 1; 320 return bars; 321 } 322 323 327 public static byte[] getBarsUPCE(String _code) { 328 int code[] = new int[_code.length()]; 329 for (int k = 0; k < code.length; ++k) 330 code[k] = _code.charAt(k) - '0'; 331 byte bars[] = new byte[TOTALBARS_UPCE]; 332 boolean flip = (code[0] != 0); 333 int pb = 0; 334 bars[pb++] = 1; 335 bars[pb++] = 1; 336 bars[pb++] = 1; 337 byte sequence[] = PARITYE[code[code.length - 1]]; 338 for (int k = 1; k < code.length - 1; ++k) { 339 int c = code[k]; 340 byte stripes[] = BARS[c]; 341 if (sequence[k - 1] == (flip ? EVEN : ODD)) { 342 bars[pb++] = stripes[0]; 343 bars[pb++] = stripes[1]; 344 bars[pb++] = stripes[2]; 345 bars[pb++] = stripes[3]; 346 } 347 else { 348 bars[pb++] = stripes[3]; 349 bars[pb++] = stripes[2]; 350 bars[pb++] = stripes[1]; 351 bars[pb++] = stripes[0]; 352 } 353 } 354 bars[pb++] = 1; 355 bars[pb++] = 1; 356 bars[pb++] = 1; 357 bars[pb++] = 1; 358 bars[pb++] = 1; 359 bars[pb++] = 1; 360 return bars; 361 } 362 363 367 public static byte[] getBarsSupplemental2(String _code) { 368 int code[] = new int[2]; 369 for (int k = 0; k < code.length; ++k) 370 code[k] = _code.charAt(k) - '0'; 371 byte bars[] = new byte[TOTALBARS_SUPP2]; 372 int pb = 0; 373 int parity = (code[0] * 10 + code[1]) % 4; 374 bars[pb++] = 1; 375 bars[pb++] = 1; 376 bars[pb++] = 2; 377 byte sequence[] = PARITY2[parity]; 378 for (int k = 0; k < sequence.length; ++k) { 379 if (k == 1) { 380 bars[pb++] = 1; 381 bars[pb++] = 1; 382 } 383 int c = code[k]; 384 byte stripes[] = BARS[c]; 385 if (sequence[k] == ODD) { 386 bars[pb++] = stripes[0]; 387 bars[pb++] = stripes[1]; 388 bars[pb++] = stripes[2]; 389 bars[pb++] = stripes[3]; 390 } 391 else { 392 bars[pb++] = stripes[3]; 393 bars[pb++] = stripes[2]; 394 bars[pb++] = stripes[1]; 395 bars[pb++] = stripes[0]; 396 } 397 } 398 return bars; 399 } 400 401 405 public static byte[] getBarsSupplemental5(String _code) { 406 int code[] = new int[5]; 407 for (int k = 0; k < code.length; ++k) 408 code[k] = _code.charAt(k) - '0'; 409 byte bars[] = new byte[TOTALBARS_SUPP5]; 410 int pb = 0; 411 int parity = (((code[0] + code[2] + code[4]) * 3) + ((code[1] + code[3]) * 9)) % 10; 412 bars[pb++] = 1; 413 bars[pb++] = 1; 414 bars[pb++] = 2; 415 byte sequence[] = PARITY5[parity]; 416 for (int k = 0; k < sequence.length; ++k) { 417 if (k != 0) { 418 bars[pb++] = 1; 419 bars[pb++] = 1; 420 } 421 int c = code[k]; 422 byte stripes[] = BARS[c]; 423 if (sequence[k] == ODD) { 424 bars[pb++] = stripes[0]; 425 bars[pb++] = stripes[1]; 426 bars[pb++] = stripes[2]; 427 bars[pb++] = stripes[3]; 428 } 429 else { 430 bars[pb++] = stripes[3]; 431 bars[pb++] = stripes[2]; 432 bars[pb++] = stripes[1]; 433 bars[pb++] = stripes[0]; 434 } 435 } 436 return bars; 437 } 438 439 443 public Rectangle getBarcodeSize() { 444 float width = 0; 445 float height = barHeight; 446 if (font != null) { 447 if (baseline <= 0) 448 height += -baseline + size; 449 else 450 height += baseline - font.getFontDescriptor(BaseFont.DESCENT, size); 451 } 452 switch (codeType) { 453 case EAN13: 454 width = x * (11 + 12 * 7); 455 if (font != null) { 456 width += font.getWidthPoint(code.charAt(0), size); 457 } 458 break; 459 case EAN8: 460 width = x * (11 + 8 * 7); 461 break; 462 case UPCA: 463 width = x * (11 + 12 * 7); 464 if (font != null) { 465 width += font.getWidthPoint(code.charAt(0), size) + font.getWidthPoint(code.charAt(11), size); 466 } 467 break; 468 case UPCE: 469 width = x * (9 + 6 * 7); 470 if (font != null) { 471 width += font.getWidthPoint(code.charAt(0), size) + font.getWidthPoint(code.charAt(7), size); 472 } 473 break; 474 case SUPP2: 475 width = x * (6 + 2 * 7); 476 break; 477 case SUPP5: 478 width = x * (4 + 5 * 7 + 4 * 2); 479 break; 480 default: 481 throw new RuntimeException ("Invalid code type."); 482 } 483 return new Rectangle(width, height); 484 } 485 486 522 public Rectangle placeBarcode(PdfContentByte cb, Color barColor, Color textColor) { 523 Rectangle rect = getBarcodeSize(); 524 float barStartX = 0; 525 float barStartY = 0; 526 float textStartY = 0; 527 if (font != null) { 528 if (baseline <= 0) 529 textStartY = barHeight - baseline; 530 else { 531 textStartY = -font.getFontDescriptor(BaseFont.DESCENT, size); 532 barStartY = textStartY + baseline; 533 } 534 } 535 switch (codeType) { 536 case EAN13: 537 case UPCA: 538 case UPCE: 539 if (font != null) 540 barStartX += font.getWidthPoint(code.charAt(0), size); 541 break; 542 } 543 byte bars[] = null; 544 int guard[] = GUARD_EMPTY; 545 switch (codeType) { 546 case EAN13: 547 bars = getBarsEAN13(code); 548 guard = GUARD_EAN13; 549 break; 550 case EAN8: 551 bars = getBarsEAN8(code); 552 guard = GUARD_EAN8; 553 break; 554 case UPCA: 555 bars = getBarsEAN13("0" + code); 556 guard = GUARD_UPCA; 557 break; 558 case UPCE: 559 bars = getBarsUPCE(code); 560 guard = GUARD_UPCE; 561 break; 562 case SUPP2: 563 bars = getBarsSupplemental2(code); 564 break; 565 case SUPP5: 566 bars = getBarsSupplemental5(code); 567 break; 568 } 569 float keepBarX = barStartX; 570 boolean print = true; 571 float gd = 0; 572 if (font != null && baseline > 0 && guardBars) { 573 gd = baseline / 2; 574 } 575 if (barColor != null) 576 cb.setColorFill(barColor); 577 for (int k = 0; k < bars.length; ++k) { 578 float w = bars[k] * x; 579 if (print) { 580 if (Arrays.binarySearch(guard, k) >= 0) 581 cb.rectangle(barStartX, barStartY - gd, w - inkSpreading, barHeight + gd); 582 else 583 cb.rectangle(barStartX, barStartY, w - inkSpreading, barHeight); 584 } 585 print = !print; 586 barStartX += w; 587 } 588 cb.fill(); 589 if (font != null) { 590 if (textColor != null) 591 cb.setColorFill(textColor); 592 cb.beginText(); 593 cb.setFontAndSize(font, size); 594 switch (codeType) { 595 case EAN13: 596 cb.setTextMatrix(0, textStartY); 597 cb.showText(code.substring(0, 1)); 598 for (int k = 1; k < 13; ++k) { 599 String c = code.substring(k, k + 1); 600 float len = font.getWidthPoint(c, size); 601 float pX = keepBarX + TEXTPOS_EAN13[k - 1] * x - len / 2; 602 cb.setTextMatrix(pX, textStartY); 603 cb.showText(c); 604 } 605 break; 606 case EAN8: 607 for (int k = 0; k < 8; ++k) { 608 String c = code.substring(k, k + 1); 609 float len = font.getWidthPoint(c, size); 610 float pX = TEXTPOS_EAN8[k] * x - len / 2; 611 cb.setTextMatrix(pX, textStartY); 612 cb.showText(c); 613 } 614 break; 615 case UPCA: 616 cb.setTextMatrix(0, textStartY); 617 cb.showText(code.substring(0, 1)); 618 for (int k = 1; k < 11; ++k) { 619 String c = code.substring(k, k + 1); 620 float len = font.getWidthPoint(c, size); 621 float pX = keepBarX + TEXTPOS_EAN13[k] * x - len / 2; 622 cb.setTextMatrix(pX, textStartY); 623 cb.showText(c); 624 } 625 cb.setTextMatrix(keepBarX + x * (11 + 12 * 7), textStartY); 626 cb.showText(code.substring(11, 12)); 627 break; 628 case UPCE: 629 cb.setTextMatrix(0, textStartY); 630 cb.showText(code.substring(0, 1)); 631 for (int k = 1; k < 7; ++k) { 632 String c = code.substring(k, k + 1); 633 float len = font.getWidthPoint(c, size); 634 float pX = keepBarX + TEXTPOS_EAN13[k - 1] * x - len / 2; 635 cb.setTextMatrix(pX, textStartY); 636 cb.showText(c); 637 } 638 cb.setTextMatrix(keepBarX + x * (9 + 6 * 7), textStartY); 639 cb.showText(code.substring(7, 8)); 640 break; 641 case SUPP2: 642 case SUPP5: 643 for (int k = 0; k < code.length(); ++k) { 644 String c = code.substring(k, k + 1); 645 float len = font.getWidthPoint(c, size); 646 float pX = (7.5f + (9 * k)) * x - len / 2; 647 cb.setTextMatrix(pX, textStartY); 648 cb.showText(c); 649 } 650 break; 651 } 652 cb.endText(); 653 } 654 return rect; 655 } 656 657 663 public java.awt.Image createAwtImage(Color foreground, Color background) { 664 int f = foreground.getRGB(); 665 int g = background.getRGB(); 666 Canvas canvas = new Canvas (); 667 668 int width = 0; 669 byte bars[] = null; 670 switch (codeType) { 671 case EAN13: 672 bars = getBarsEAN13(code); 673 width = 11 + 12 * 7; 674 break; 675 case EAN8: 676 bars = getBarsEAN8(code); 677 width = 11 + 8 * 7; 678 break; 679 case UPCA: 680 bars = getBarsEAN13("0" + code); 681 width = 11 + 12 * 7; 682 break; 683 case UPCE: 684 bars = getBarsUPCE(code); 685 width = 9 + 6 * 7; 686 break; 687 case SUPP2: 688 bars = getBarsSupplemental2(code); 689 width = 6 + 2 * 7; 690 break; 691 case SUPP5: 692 bars = getBarsSupplemental5(code); 693 width = 4 + 5 * 7 + 4 * 2; 694 break; 695 default: 696 throw new RuntimeException ("Invalid code type."); 697 } 698 699 boolean print = true; 700 int ptr = 0; 701 int height = (int)barHeight; 702 int pix[] = new int[width * height]; 703 for (int k = 0; k < bars.length; ++k) { 704 int w = bars[k]; 705 int c = g; 706 if (print) 707 c = f; 708 print = !print; 709 for (int j = 0; j < w; ++j) 710 pix[ptr++] = c; 711 } 712 for (int k = width; k < pix.length; k += width) { 713 System.arraycopy(pix, 0, pix, k, width); 714 } 715 Image img = canvas.createImage(new MemoryImageSource (width, height, pix, 0, width)); 716 717 return img; 718 } 719 } 720 | Popular Tags |