| 1 50 51 package com.lowagie.text.pdf; 52 import java.awt.Color ; 53 import java.awt.geom.AffineTransform ; 54 import java.awt.print.PrinterJob ; 55 import java.util.ArrayList ; 56 import java.util.HashMap ; 57 import java.util.Iterator ; 58 59 import com.lowagie.text.Annotation; 60 import com.lowagie.text.DocumentException; 61 import com.lowagie.text.Element; 62 import com.lowagie.text.ExceptionConverter; 63 import com.lowagie.text.Image; 64 import com.lowagie.text.Rectangle; 65 import com.lowagie.text.pdf.internal.PdfAnnotationsImp; 66 import com.lowagie.text.pdf.internal.PdfXConformanceImp; 67 68 73 74 public class PdfContentByte { 75 76 79 80 static class GraphicState { 81 82 83 FontDetails fontDetails; 84 85 86 ColorDetails colorDetails; 87 88 89 float size; 90 91 92 protected float xTLM = 0; 93 94 protected float yTLM = 0; 95 96 97 protected float leading = 0; 98 99 100 protected float scale = 100; 101 102 103 protected float charSpace = 0; 104 105 106 protected float wordSpace = 0; 107 108 GraphicState() { 109 } 110 111 GraphicState(GraphicState cp) { 112 fontDetails = cp.fontDetails; 113 colorDetails = cp.colorDetails; 114 size = cp.size; 115 xTLM = cp.xTLM; 116 yTLM = cp.yTLM; 117 leading = cp.leading; 118 scale = cp.scale; 119 charSpace = cp.charSpace; 120 wordSpace = cp.wordSpace; 121 } 122 } 123 124 125 public static final int ALIGN_CENTER = Element.ALIGN_CENTER; 126 127 128 public static final int ALIGN_LEFT = Element.ALIGN_LEFT; 129 130 131 public static final int ALIGN_RIGHT = Element.ALIGN_RIGHT; 132 133 134 public static final int LINE_CAP_BUTT = 0; 135 136 public static final int LINE_CAP_ROUND = 1; 137 138 public static final int LINE_CAP_PROJECTING_SQUARE = 2; 139 140 141 public static final int LINE_JOIN_MITER = 0; 142 143 public static final int LINE_JOIN_ROUND = 1; 144 145 public static final int LINE_JOIN_BEVEL = 2; 146 147 148 public static final int TEXT_RENDER_MODE_FILL = 0; 149 150 public static final int TEXT_RENDER_MODE_STROKE = 1; 151 152 public static final int TEXT_RENDER_MODE_FILL_STROKE = 2; 153 154 public static final int TEXT_RENDER_MODE_INVISIBLE = 3; 155 156 public static final int TEXT_RENDER_MODE_FILL_CLIP = 4; 157 158 public static final int TEXT_RENDER_MODE_STROKE_CLIP = 5; 159 160 public static final int TEXT_RENDER_MODE_FILL_STROKE_CLIP = 6; 161 162 public static final int TEXT_RENDER_MODE_CLIP = 7; 163 164 private static final float[] unitRect = {0, 0, 0, 1, 1, 0, 1, 1}; 165 167 168 protected ByteBuffer content = new ByteBuffer(); 169 170 171 protected PdfWriter writer; 172 173 174 protected PdfDocument pdf; 175 176 177 protected GraphicState state = new GraphicState(); 178 179 180 protected ArrayList stateList = new ArrayList (); 181 182 183 protected ArrayList layerDepth; 184 185 187 protected int separator = '\n'; 188 189 private static HashMap abrev = new HashMap (); 190 191 static { 192 abrev.put(PdfName.BITSPERCOMPONENT, "/BPC "); 193 abrev.put(PdfName.COLORSPACE, "/CS "); 194 abrev.put(PdfName.DECODE, "/D "); 195 abrev.put(PdfName.DECODEPARMS, "/DP "); 196 abrev.put(PdfName.FILTER, "/F "); 197 abrev.put(PdfName.HEIGHT, "/H "); 198 abrev.put(PdfName.IMAGEMASK, "/IM "); 199 abrev.put(PdfName.INTENT, "/Intent "); 200 abrev.put(PdfName.INTERPOLATE, "/I "); 201 abrev.put(PdfName.WIDTH, "/W "); 202 } 203 204 206 211 212 public PdfContentByte(PdfWriter wr) { 213 if (wr != null) { 214 writer = wr; 215 pdf = writer.getPdfDocument(); 216 } 217 } 218 219 221 226 227 public String toString() { 228 return content.toString(); 229 } 230 231 235 public ByteBuffer getInternalBuffer() { 236 return content; 237 } 238 239 244 245 public byte[] toPdf(PdfWriter writer) { 246 return content.toByteArray(); 247 } 248 249 251 256 257 public void add(PdfContentByte other) { 258 if (other.writer != null && writer != other.writer) 259 throw new RuntimeException ("Inconsistent writers. Are you mixing two documents?"); 260 content.append(other.content); 261 } 262 263 268 public float getXTLM() { 269 return state.xTLM; 270 } 271 272 277 public float getYTLM() { 278 return state.yTLM; 279 } 280 281 286 public float getLeading() { 287 return state.leading; 288 } 289 290 295 public float getCharacterSpacing() { 296 return state.charSpace; 297 } 298 299 304 public float getWordSpacing() { 305 return state.wordSpace; 306 } 307 308 313 public float getHorizontalScaling() { 314 return state.scale; 315 } 316 317 325 326 public void setFlatness(float flatness) { 327 if (flatness >= 0 && flatness <= 100) { 328 content.append(flatness).append(" i").append_i(separator); 329 } 330 } 331 332 341 342 public void setLineCap(int style) { 343 if (style >= 0 && style <= 2) { 344 content.append(style).append(" J").append_i(separator); 345 } 346 } 347 348 358 359 public void setLineDash(float phase) { 360 content.append("[] ").append(phase).append(" d").append_i(separator); 361 } 362 363 374 375 public void setLineDash(float unitsOn, float phase) { 376 content.append("[").append(unitsOn).append("] ").append(phase).append(" d").append_i(separator); 377 } 378 379 391 392 public void setLineDash(float unitsOn, float unitsOff, float phase) { 393 content.append("[").append(unitsOn).append(' ').append(unitsOff).append("] ").append(phase).append(" d").append_i(separator); 394 } 395 396 407 408 public final void setLineDash(float[] array, float phase) { 409 content.append("["); 410 for (int i = 0; i < array.length; i++) { 411 content.append(array[i]); 412 if (i < array.length - 1) content.append(' '); 413 } 414 content.append("] ").append(phase).append(" d").append_i(separator); 415 } 416 417 426 427 public void setLineJoin(int style) { 428 if (style >= 0 && style <= 2) { 429 content.append(style).append(" j").append_i(separator); 430 } 431 } 432 433 441 442 public void setLineWidth(float w) { 443 content.append(w).append(" w").append_i(separator); 444 } 445 446 456 457 public void setMiterLimit(float miterLimit) { 458 if (miterLimit > 1) { 459 content.append(miterLimit).append(" M").append_i(separator); 460 } 461 } 462 463 468 469 public void clip() { 470 content.append("W").append_i(separator); 471 } 472 473 477 478 public void eoClip() { 479 content.append("W*").append_i(separator); 480 } 481 482 490 491 public void setGrayFill(float gray) { 492 content.append(gray).append(" g").append_i(separator); 493 } 494 495 498 499 public void resetGrayFill() { 500 content.append("0 g").append_i(separator); 501 } 502 503 511 512 public void setGrayStroke(float gray) { 513 content.append(gray).append(" G").append_i(separator); 514 } 515 516 519 520 public void resetGrayStroke() { 521 content.append("0 G").append_i(separator); 522 } 523 524 530 private void HelperRGB(float red, float green, float blue) { 531 PdfXConformanceImp.checkPDFXConformance(writer, PdfXConformanceImp.PDFXKEY_RGB, null); 532 if (red < 0) 533 red = 0.0f; 534 else if (red > 1.0f) 535 red = 1.0f; 536 if (green < 0) 537 green = 0.0f; 538 else if (green > 1.0f) 539 green = 1.0f; 540 if (blue < 0) 541 blue = 0.0f; 542 else if (blue > 1.0f) 543 blue = 1.0f; 544 content.append(red).append(' ').append(green).append(' ').append(blue); 545 } 546 547 560 561 public void setRGBColorFillF(float red, float green, float blue) { 562 HelperRGB(red, green, blue); 563 content.append(" rg").append_i(separator); 564 } 565 566 569 570 public void resetRGBColorFill() { 571 content.append("0 g").append_i(separator); 572 } 573 574 587 588 public void setRGBColorStrokeF(float red, float green, float blue) { 589 HelperRGB(red, green, blue); 590 content.append(" RG").append_i(separator); 591 } 592 593 597 598 public void resetRGBColorStroke() { 599 content.append("0 G").append_i(separator); 600 } 601 602 610 private void HelperCMYK(float cyan, float magenta, float yellow, float black) { 611 if (cyan < 0) 612 cyan = 0.0f; 613 else if (cyan > 1.0f) 614 cyan = 1.0f; 615 if (magenta < 0) 616 magenta = 0.0f; 617 else if (magenta > 1.0f) 618 magenta = 1.0f; 619 if (yellow < 0) 620 yellow = 0.0f; 621 else if (yellow > 1.0f) 622 yellow = 1.0f; 623 if (black < 0) 624 black = 0.0f; 625 else if (black > 1.0f) 626 black = 1.0f; 627 content.append(cyan).append(' ').append(magenta).append(' ').append(yellow).append(' ').append(black); 628 } 629 630 644 645 public void setCMYKColorFillF(float cyan, float magenta, float yellow, float black) { 646 HelperCMYK(cyan, magenta, yellow, black); 647 content.append(" k").append_i(separator); 648 } 649 650 654 655 public void resetCMYKColorFill() { 656 content.append("0 0 0 1 k").append_i(separator); 657 } 658 659 673 674 public void setCMYKColorStrokeF(float cyan, float magenta, float yellow, float black) { 675 HelperCMYK(cyan, magenta, yellow, black); 676 content.append(" K").append_i(separator); 677 } 678 679 683 684 public void resetCMYKColorStroke() { 685 content.append("0 0 0 1 K").append_i(separator); 686 } 687 688 694 695 public void moveTo(float x, float y) { 696 content.append(x).append(' ').append(y).append(" m").append_i(separator); 697 } 698 699 706 707 public void lineTo(float x, float y) { 708 content.append(x).append(' ').append(y).append(" l").append_i(separator); 709 } 710 711 721 722 public void curveTo(float x1, float y1, float x2, float y2, float x3, float y3) { 723 content.append(x1).append(' ').append(y1).append(' ').append(x2).append(' ').append(y2).append(' ').append(x3).append(' ').append(y3).append(" c").append_i(separator); 724 } 725 726 734 735 public void curveTo(float x2, float y2, float x3, float y3) { 736 content.append(x2).append(' ').append(y2).append(' ').append(x3).append(' ').append(y3).append(" v").append_i(separator); 737 } 738 739 747 748 public void curveFromTo(float x1, float y1, float x3, float y3) { 749 content.append(x1).append(' ').append(y1).append(' ').append(x3).append(' ').append(y3).append(" y").append_i(separator); 750 } 751 752 758 public void circle(float x, float y, float r) { 759 float b = 0.5523f; 760 moveTo(x + r, y); 761 curveTo(x + r, y + r * b, x + r * b, y + r, x, y + r); 762 curveTo(x - r * b, y + r, x - r, y + r * b, x - r, y); 763 curveTo(x - r, y - r * b, x - r * b, y - r, x, y - r); 764 curveTo(x + r * b, y - r, x + r, y - r * b, x + r, y); 765 } 766 767 768 769 777 778 public void rectangle(float x, float y, float w, float h) { 779 content.append(x).append(' ').append(y).append(' ').append(w).append(' ').append(h).append(" re").append_i(separator); 780 } 781 782 private boolean compareColors(Color c1, Color c2) { 783 if (c1 == null && c2 == null) 784 return true; 785 if (c1 == null || c2 == null) 786 return false; 787 if (c1 instanceof ExtendedColor) 788 return c1.equals(c2); 789 return c2.equals(c1); 790 } 791 792 798 public void variableRectangle(Rectangle rect) { 799 float t = rect.getTop(); 800 float b = rect.getBottom(); 801 float r = rect.getRight(); 802 float l = rect.getLeft(); 803 float wt = rect.getBorderWidthTop(); 804 float wb = rect.getBorderWidthBottom(); 805 float wr = rect.getBorderWidthRight(); 806 float wl = rect.getBorderWidthLeft(); 807 Color ct = rect.getBorderColorTop(); 808 Color cb = rect.getBorderColorBottom(); 809 Color cr = rect.getBorderColorRight(); 810 Color cl = rect.getBorderColorLeft(); 811 saveState(); 812 setLineCap(PdfContentByte.LINE_CAP_BUTT); 813 setLineJoin(PdfContentByte.LINE_JOIN_MITER); 814 float clw = 0; 815 boolean cdef = false; 816 Color ccol = null; 817 boolean cdefi = false; 818 Color cfil = null; 819 if (wt > 0) { 821 setLineWidth(clw = wt); 822 cdef = true; 823 if (ct == null) 824 resetRGBColorStroke(); 825 else 826 setColorStroke(ct); 827 ccol = ct; 828 moveTo(l, t - wt / 2f); 829 lineTo(r, t - wt / 2f); 830 stroke(); 831 } 832 833 if (wb > 0) { 835 if (wb != clw) 836 setLineWidth(clw = wb); 837 if (!cdef || !compareColors(ccol, cb)) { 838 cdef = true; 839 if (cb == null) 840 resetRGBColorStroke(); 841 else 842 setColorStroke(cb); 843 ccol = cb; 844 } 845 moveTo(r, b + wb / 2f); 846 lineTo(l, b + wb / 2f); 847 stroke(); 848 } 849 850 if (wr > 0) { 852 if (wr != clw) 853 setLineWidth(clw = wr); 854 if (!cdef || !compareColors(ccol, cr)) { 855 cdef = true; 856 if (cr == null) 857 resetRGBColorStroke(); 858 else 859 setColorStroke(cr); 860 ccol = cr; 861 } 862 boolean bt = compareColors(ct, cr); 863 boolean bb = compareColors(cb, cr); 864 moveTo(r - wr / 2f, bt ? t : t - wt); 865 lineTo(r - wr / 2f, bb ? b : b + wb); 866 stroke(); 867 if (!bt || !bb) { 868 cdefi = true; 869 if (cr == null) 870 resetRGBColorFill(); 871 else 872 setColorFill(cr); 873 cfil = cr; 874 if (!bt) { 875 moveTo(r, t); 876 lineTo(r, t - wt); 877 lineTo(r - wr, t - wt); 878 fill(); 879 } 880 if (!bb) { 881 moveTo(r, b); 882 lineTo(r, b + wb); 883 lineTo(r - wr, b + wb); 884 fill(); 885 } 886 } 887 } 888 889 if (wl > 0) { 891 if (wl != clw) 892 setLineWidth(wl); 893 if (!cdef || !compareColors(ccol, cl)) { 894 if (cl == null) 895 resetRGBColorStroke(); 896 else 897 setColorStroke(cl); 898 } 899 boolean bt = compareColors(ct, cl); 900 boolean bb = compareColors(cb, cl); 901 moveTo(l + wl / 2f, bt ? t : t - wt); 902 lineTo(l + wl / 2f, bb ? b : b + wb); 903 stroke(); 904 if (!bt || !bb) { 905 if (!cdefi || !compareColors(cfil, cl)) { 906 if (cl == null) 907 resetRGBColorFill(); 908 else 909 setColorFill(cl); 910 } 911 if (!bt) { 912 moveTo(l, t); 913 lineTo(l, t - wt); 914 lineTo(l + wl, t - wt); 915 fill(); 916 } 917 if (!bb) { 918 moveTo(l, b); 919 lineTo(l, b + wb); 920 lineTo(l + wl, b + wb); 921 fill(); 922 } 923 } 924 } 925 restoreState(); 926 } 927 928 933 934 public void rectangle(Rectangle rectangle) { 935 float x1 = rectangle.getLeft(); 937 float y1 = rectangle.getBottom(); 9
|