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(); 938 float x2 = rectangle.getRight(); 939 float y2 = rectangle.getTop(); 940 941 Color background = rectangle.getBackgroundColor(); 943 if (background != null) { 944 setColorFill(background); 945 rectangle(x1, y1, x2 - x1, y2 - y1); 946 fill(); 947 resetRGBColorFill(); 948 } 949 950 if (! rectangle.hasBorders()) { 952 return; 953 } 954 955 if (rectangle.isUseVariableBorders()) { 959 variableRectangle(rectangle); 960 } 961 else { 962 if (rectangle.getBorderWidth() != Rectangle.UNDEFINED) { 964 setLineWidth(rectangle.getBorderWidth()); 965 } 966 967 Color color = rectangle.getBorderColor(); 969 if (color != null) { 970 setColorStroke(color); 971 } 972 973 if (rectangle.hasBorder(Rectangle.BOX)) { 975 rectangle(x1, y1, x2 - x1, y2 - y1); 976 } 977 else { 979 if (rectangle.hasBorder(Rectangle.RIGHT)) { 980 moveTo(x2, y1); 981 lineTo(x2, y2); 982 } 983 if (rectangle.hasBorder(Rectangle.LEFT)) { 984 moveTo(x1, y1); 985 lineTo(x1, y2); 986 } 987 if (rectangle.hasBorder(Rectangle.BOTTOM)) { 988 moveTo(x1, y1); 989 lineTo(x2, y1); 990 } 991 if (rectangle.hasBorder(Rectangle.TOP)) { 992 moveTo(x1, y2); 993 lineTo(x2, y2); 994 } 995 } 996 997 stroke(); 998 999 if (color != null) { 1000 resetRGBColorStroke(); 1001 } 1002 } 1003 } 1004 1005 1009 1010 public void closePath() { 1011 content.append("h").append_i(separator); 1012 } 1013 1014 1017 1018 public void newPath() { 1019 content.append("n").append_i(separator); 1020 } 1021 1022 1025 1026 public void stroke() { 1027 content.append("S").append_i(separator); 1028 } 1029 1030 1033 1034 public void closePathStroke() { 1035 content.append("s").append_i(separator); 1036 } 1037 1038 1041 1042 public void fill() { 1043 content.append("f").append_i(separator); 1044 } 1045 1046 1049 1050 public void eoFill() { 1051 content.append("f*").append_i(separator); 1052 } 1053 1054 1057 1058 public void fillStroke() { 1059 content.append("B").append_i(separator); 1060 } 1061 1062 1065 1066 public void closePathFillStroke() { 1067 content.append("b").append_i(separator); 1068 } 1069 1070 1073 1074 public void eoFillStroke() { 1075 content.append("B*").append_i(separator); 1076 } 1077 1078 1081 1082 public void closePathEoFillStroke() { 1083 content.append("b*").append_i(separator); 1084 } 1085 1086 1092 public void addImage(Image image) throws DocumentException { 1093 addImage(image, false); 1094 } 1095 1096 1103 public void addImage(Image image, boolean inlineImage) throws DocumentException { 1104 if (!image.hasAbsoluteY()) 1105 throw new DocumentException("The image must have absolute positioning."); 1106 float matrix[] = image.matrix(); 1107 matrix[Image.CX] = image.getAbsoluteX() - matrix[Image.CX]; 1108 matrix[Image.CY] = image.getAbsoluteY() - matrix[Image.CY]; 1109 addImage(image, matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5], inlineImage); 1110 } 1111 1112 1125 public void addImage(Image image, float a, float b, float c, float d, float e, float f) throws DocumentException { 1126 addImage(image, a, b, c, d, e, f, false); 1127 } 1128 1129 1143 public void addImage(Image image, float a, float b, float c, float d, float e, float f, boolean inlineImage) throws DocumentException { 1144 try { 1145 if (image.getLayer() != null) 1146 beginLayer(image.getLayer()); 1147 if (image.isImgTemplate()) { 1148 writer.addDirectImageSimple(image); 1149 PdfTemplate template = image.getTemplateData(); 1150 float w = template.getWidth(); 1151 float h = template.getHeight(); 1152 addTemplate(template, a / w, b / w, c / h, d / h, e, f); 1153 } 1154 else { 1155 content.append("q "); 1156 content.append(a).append(' '); 1157 content.append(b).append(' '); 1158 content.append(c).append(' '); 1159 content.append(d).append(' '); 1160 content.append(e).append(' '); 1161 content.append(f).append(" cm"); 1162 if (inlineImage) { 1163 content.append("\nBI\n"); 1164 PdfImage pimage = new PdfImage(image, "", null); 1165 for (Iterator it = pimage.getKeys().iterator(); it.hasNext();) { 1166 PdfName key = (PdfName)it.next(); 1167 PdfObject value = pimage.get(key); 1168 String s = (String )abrev.get(key); 1169 if (s == null) 1170 continue; 1171 content.append(s); 1172 boolean check = true; 1173 if (key.equals(PdfName.COLORSPACE) && value.isArray()) { 1174 ArrayList ar = ((PdfArray)value).getArrayList(); 1175 if (ar.size() == 4 1176 && PdfName.INDEXED.equals(ar.get(0)) 1177 && ((PdfObject)ar.get(1)).isName() 1178 && ((PdfObject)ar.get(2)).isNumber() 1179 && ((PdfObject)ar.get(3)).isString() 1180 ) { 1181 check = false; 1182 } 1183 1184 } 1185 if (check && key.equals(PdfName.COLORSPACE) && !value.isName()) { 1186 PdfName cs = writer.getColorspaceName(); 1187 PageResources prs = getPageResources(); 1188 prs.addColor(cs, writer.addToBody(value).getIndirectReference()); 1189 value = cs; 1190 } 1191 value.toPdf(null, content); 1192 content.append('\n'); 1193 } 1194 content.append("ID\n"); 1195 pimage.writeContent(content); 1196 content.append("\nEI\nQ").append_i(separator); 1197 } 1198 else { 1199 PdfName name; 1200 PageResources prs = getPageResources(); 1201 Image maskImage = image.getImageMask(); 1202 if (maskImage != null) { 1203 name = writer.addDirectImageSimple(maskImage); 1204 prs.addXObject(name, writer.getImageReference(name)); 1205 } 1206 name = writer.addDirectImageSimple(image); 1207 name = prs.addXObject(name, writer.getImageReference(name)); 1208 content.append(' ').append(name.getBytes()).append(" Do Q").append_i(separator); 1209 } 1210 } 1211 if (image.hasBorders()) { 1212 saveState(); 1213 float w = image.getWidth(); 1214 float h = image.getHeight(); 1215 concatCTM(a / w, b / w, c / h, d / h, e, f); 1216 rectangle(image); 1217 restoreState(); 1218 } 1219 if (image.getLayer() != null) 1220 endLayer(); 1221 Annotation annot = image.getAnnotation(); 1222 if (annot == null) 1223 return; 1224 float[] r = new float[unitRect.length]; 1225 for (int k = 0; k < unitRect.length; k += 2) { 1226 r[k] = a * unitRect[k] + c * unitRect[k + 1] + e; 1227 r[k + 1] = b * unitRect[k] + d * unitRect[k + 1] + f; 1228 } 1229 float llx = r[0]; 1230 float lly = r[1]; 1231 float urx = llx; 1232 float ury = lly; 1233 for (int k = 2; k < r.length; k += 2) { 1234 llx = Math.min(llx, r[k]); 1235 lly = Math.min(lly, r[k + 1]); 1236 urx = Math.max(urx, r[k]); 1237 ury = Math.max(ury, r[k + 1]); 1238 } 1239 annot = new Annotation(annot); 1240 annot.setDimensions(llx, lly, urx, ury); 1241 PdfAnnotation an = PdfAnnotationsImp.convertAnnotation(writer, annot, new Rectangle(llx, lly, urx, ury)); 1242 if (an == null) 1243 return; 1244 addAnnotation(an); 1245 } 1246 catch (Exception ee) { 1247 throw new DocumentException(ee); 1248 } 1249 } 1250 1251 1254 public void reset() { 1255 content.reset(); 1256 stateList.clear(); 1257 state = new GraphicState(); 1258 } 1259 1260 1263 public void beginText() { 1264 state.xTLM = 0; 1265 state.yTLM = 0; 1266 content.append("BT").append_i(separator); 1267 } 1268 1269 1272 public void endText() { 1273 content.append("ET").append_i(separator); 1274 } 1275 1276 1280 public void saveState() { 1281 content.append("q").append_i(separator); 1282 stateList.add(new GraphicState(state)); 1283 } 1284 1285 1289 public void restoreState() { 1290 content.append("Q").append_i(separator); 1291 int idx = stateList.size() - 1; 1292 if (idx < 0) 1293 throw new RuntimeException ("Unbalanced save/restore state operators."); 1294 state = (GraphicState)stateList.get(idx); 1295 stateList.remove(idx); 1296 } 1297 1298 1303 public void setCharacterSpacing(float charSpace) { 1304 state.charSpace = charSpace; 1305 content.append(charSpace).append(" Tc").append_i(separator); 1306 } 1307 1308 1313 public void setWordSpacing(float wordSpace) { 1314 state.wordSpace = wordSpace; 1315 content.append(wordSpace).append(" Tw").append_i(separator); 1316 } 1317 1318 1323 public void setHorizontalScaling(float scale) { 1324 state.scale = scale; 1325 content.append(scale).append(" Tz").append_i(separator); 1326 } 1327 1328 1336 public void setLeading(float leading) { 1337 state.leading = leading; 1338 content.append(leading).append(" TL").append_i(separator); 1339 } 1340 1341 1347 public void setFontAndSize(BaseFont bf, float size) { 1348 checkWriter(); 1349 state.size = size; 1350 state.fontDetails = writer.addSimple(bf); 1351 PageResources prs = getPageResources(); 1352 PdfName name = state.fontDetails.getFontName(); 1353 name = prs.addFont(name, state.fontDetails.getIndirectReference()); 1354 content.append(name.getBytes()).append(' ').append(size).append(" Tf").append_i(separator); 1355 } 1356 1357 1362 public void setTextRenderingMode(int rendering) { 1363 content.append(rendering).append(" Tr").append_i(separator); 1364 } 1365 1366 1373 public void setTextRise(float rise) { 1374 content.append(rise).append(" Ts").append_i(separator); 1375 } 1376 1377 1383 private void showText2(String text) { 1384 if (state.fontDetails == null) 1385 throw new NullPointerException ("Font and size must be set before writing any text"); 1386 byte b[] = state.fontDetails.convertToBytes(text); 1387 escapeString(b, content); 1388 } 1389 1390 1395 public void showText(String text) { 1396 showText2(text); 1397 content.append("Tj").append_i(separator); 1398 } 1399 1400 1406 public static PdfTextArray getKernArray(String text, BaseFont font) { 1407 PdfTextArray pa = new PdfTextArray(); 1408 StringBuffer acc = new StringBuffer (); 1409 int len = text.length() - 1; 1410 char c[] = text.toCharArray(); 1411 if (len >= 0) 1412 acc.append(c, 0, 1); 1413 for (int k = 0; k < len; ++k) { 1414 char c2 = c[k + 1]; 1415 int kern = font.getKerning(c[k], c2); 1416 if (kern == 0) { 1417 acc.append(c2); 1418 } 1419 else { 1420 pa.add(acc.toString()); 1421 acc.setLength(0); 1422 acc.append(c, k + 1, 1); 1423 pa.add(-kern); 1424 } 1425 } 1426 pa.add(acc.toString()); 1427 return pa; 1428 } 1429 1430 1435 public void showTextKerned(String text) { 1436 if (state.fontDetails == null) 1437 throw new NullPointerException ("Font and size must be set before writing any text"); 1438 BaseFont bf = state.fontDetails.getBaseFont(); 1439 if (bf.hasKernPairs()) 1440 showText(getKernArray(text, bf)); 1441 else 1442 showText(text); 1443 } 1444 1445 1450 public void newlineShowText(String text) { 1451 state.yTLM -= state.leading; 1452 showText2(text); 1453 content.append("'").append_i(separator); 1454 } 1455 1456 1463 public void newlineShowText(float wordSpacing, float charSpacing, String text) { 1464 state.yTLM -= state.leading; 1465 content.append(wordSpacing).append(' ').append(charSpacing); 1466 showText2(text); 1467 content.append("\"").append_i(separator); 1468 1469 state.charSpace = charSpacing; 1472 state.wordSpace = wordSpacing; 1473 } 1474 1475 1487 public void setTextMatrix(float a, float b, float c, float d, float x, float y) { 1488 state.xTLM = x; 1489 state.yTLM = y; 1490 content.append(a).append(' ').append(b).append_i(' ') 1491 .append(c).append_i(' ').append(d).append_i(' ') 1492 .append(x).append_i(' ').append(y).append(" Tm").append_i(separator); 1493 } 1494 1495 1503 public void setTextMatrix(float x, float y) { 1504 setTextMatrix(1, 0, 0, 1, x, y); 1505 } 1506 1507 1513 public void moveText(float x, float y) { 1514 state.xTLM += x; 1515 state.yTLM += y; 1516 content.append(x).append(' ').append(y).append(" Td").append_i(separator); 1517 } 1518 1519 1527 public void moveTextWithLeading(float x, float y) { 1528 state.xTLM += x; 1529 state.yTLM += y; 1530 state.leading = -y; 1531 content.append(x).append(' ').append(y).append(" TD").append_i(separator); 1532 } 1533 1534 1537 public void newlineText() { 1538 state.yTLM -= state.leading; 1539 content.append("T*").append_i(separator); 1540 } 1541 1542 1547 int size() { 1548 return content.size(); 1549 } 1550 1551 1557 static byte[] escapeString(byte b[]) { 1558 ByteBuffer content = new ByteBuffer(); 1559 escapeString(b, content); 1560 return content.toByteArray(); 1561 } 1562 1563 1569 static void escapeString(byte b[], ByteBuffer content) { 1570 content.append_i('('); 1571 for (int k = 0; k < b.length; ++k) { 1572 byte c = b[k]; 1573 switch ((int)c) { 1574 case '\r': 1575 content.append("\\r"); 1576 break; 1577 case '\n': 1578 content.append("\\n"); 1579 break; 1580 case '\t': 1581 content.append("\\t"); 1582 break; 1583 case '\b': 1584 content.append("\\b"); 1585 break; 1586 case '\f': 1587 content.append("\\f"); 1588 break; 1589 case '(': 1590 case ')': 1591 case '\\': 1592 content.append_i('\\').append_i(c); 1593 break; 1594 default: 1595 content.append_i(c); 1596 } 1597 } 1598 content.append(")"); 1599 } 1600 1601 1608 public void addOutline(PdfOutline outline) { 1609 } 1611 1617 public void addOutline(PdfOutline outline, String name) { 1618 checkWriter(); 1619 pdf.addOutline(outline, name); 1620 } 1621 1626 public PdfOutline getRootOutline() { 1627 checkWriter(); 1628 return pdf.getRootOutline(); 1629 } 1630 1631 1641 1642 public float getEffectiveStringWidth(String text, boolean kerned) { 1643 BaseFont bf = state.fontDetails.getBaseFont(); 1644 1645 float w; 1646 if (kerned) 1647 w = bf.getWidthPointKerned(text, state.size); 1648 else 1649 w = bf.getWidthPoint(text, state.size); 1650 1651 if (state.charSpace != 0.0f && text.length() > 1) { 1652 w += state.charSpace * (text.length() -1); 1653 } 1654 1655 int ft = bf.getFontType(); 1656 if (state.wordSpace != 0.0f && (ft == BaseFont.FONT_TYPE_T1 || ft == BaseFont.FONT_TYPE_TT || ft == BaseFont.FONT_TYPE_T3)) { 1657 for (int i = 0; i < (text.length() -1); i++) { 1658 if (text.charAt(i) == ' ') 1659 w += state.wordSpace; 1660 } 1661 } 1662 if (state.scale != 100.0) 1663 w = (w * state.scale) / 100.0f; 1664 1665 return w; 1667 } 1668 1669 1677 public void showTextAligned(int alignment, String text, float x, float y, float rotation) { 1678 showTextAligned(alignment, text, x, y, rotation, false); 1679 } 1680 1681 private void showTextAligned(int alignment, String text, float x, float y, float rotation, boolean kerned) { 1682 if (state.fontDetails == null) 1683 throw new NullPointerException ("Font and size must be set before writing any text"); 1684 if (rotation == 0) { 1685 switch (alignment) { 1686 case ALIGN_CENTER: 1687 x -= getEffectiveStringWidth(text, kerned) / 2; 1688 break; 1689 case ALIGN_RIGHT: 1690 x -= getEffectiveStringWidth(text, kerned); 1691 break; 1692 } 1693 setTextMatrix(x, y); 1694 if (kerned) 1695 showTextKerned(text); 1696 else 1697 showText(text); 1698 } 1699 else { 1700 double alpha = rotation * Math.PI / 180.0; 1701 float cos = (float)Math.cos(alpha); 1702 float sin = (float)Math.sin(alpha); 1703 float len; 1704 switch (alignment) { 1705 case ALIGN_CENTER: 1706 len = getEffectiveStringWidth(text, kerned) / 2; 1707 x -= len * cos; 1708 y -= len * sin; 1709 break; 1710 case ALIGN_RIGHT: 1711 len = getEffectiveStringWidth(text, kerned); 1712 x -= len * cos; 1713 y -= len * sin; 1714 break; 1715 } 1716 setTextMatrix(cos, sin, -sin, cos, x, y); 1717 if (kerned) 1718 showTextKerned(text); 1719 else 1720 showText(text); 1721 setTextMatrix(0f, 0f); 1722 } 1723 } 1724 1725 1733 public void showTextAlignedKerned(int alignment, String text, float x, float y, float rotation) { 1734 showTextAligned(alignment, text, x, y, rotation, true); 1735 } 1736 1737 1746 public void concatCTM(float a, float b, float c, float d, float e, float f) { 1747 content.append(a).append(' ').append(b).append(' ').append(c).append(' '); 1748 content.append(d).append(' ').append(e).append(' ').append(f).append(" cm").append_i(separator); 1749 } 1750 1751 1775 public static ArrayList bezierArc(float x1, float y1, float x2, float y2, float startAng, float extent) { 1776 float tmp; 1777 if (x1 > x2) { 1778 tmp = x1; 1779 x1 = x2; 1780 x2 = tmp; 1781 } 1782 if (y2 > y1) { 1783 tmp = y1; 1784 y1 = y2; 1785 y2 = tmp; 1786 } 1787 1788 float fragAngle; 1789 int Nfrag; 1790 if (Math.abs(extent) <= 90f) { 1791 fragAngle = extent; 1792 Nfrag = 1; 1793 } 1794 else { 1795 Nfrag = (int)(Math.ceil(Math.abs(extent)/90f)); 1796 fragAngle = extent / Nfrag; 1797 } 1798 float x_cen = (x1+x2)/2f; 1799 float y_cen = (y1+y2)/2f; 1800 float rx = (x2-x1)/2f; 1801 float ry = (y2-y1)/2f; 1802 float halfAng = (float)(fragAngle * Math.PI / 360.); 1803 float kappa = (float)(Math.abs(4. / 3. * (1. - Math.cos(halfAng)) / Math.sin(halfAng))); 1804 ArrayList pointList = new ArrayList (); 1805 for (int i = 0; i < Nfrag; ++i) { 1806 float theta0 = (float)((startAng + i*fragAngle) * Math.PI / 180.); 1807 float theta1 = (float)((startAng + (i+1)*fragAngle) * Math.PI / 180.); 1808 float cos0 = (float)Math.cos(theta0); 1809 float cos1 = (float)Math.cos(theta1); 1810 float sin0 = (float)Math.sin(theta0); 1811 float sin1 = (float)Math.sin(theta1); 1812 if (fragAngle > 0f) { 1813 pointList.add(new float[]{x_cen + rx * cos0, 1814 y_cen - ry * sin0, 1815 x_cen + rx * (cos0 - kappa * sin0), 1816 y_cen - ry * (sin0 + kappa * cos0), 1817 x_cen + rx * (cos1 + kappa * sin1), 1818 y_cen - ry * (sin1 - kappa * cos1), 1819 x_cen + rx * cos1, 1820 y_cen - ry * sin1}); 1821 } 1822 else { 1823 pointList.add(new float[]{x_cen + rx * cos0, 1824 y_cen - ry * sin0, 1825 x_cen + rx * (cos0 + kappa * sin0), 1826 y_cen - ry * (sin0 - kappa * cos0), 1827 x_cen + rx * (cos1 - kappa * sin1), 1828 y_cen - ry * (sin1 + kappa * cos1), 1829 x_cen + rx * cos1, 1830 y_cen - ry * sin1}); 1831 } 1832 } 1833 return pointList; 1834 } 1835 1836 1848 public void arc(float x1, float y1, float x2, float y2, float startAng, float extent) { 1849 ArrayList ar = bezierArc(x1, y1, x2, y2, startAng, extent); 1850 if (ar.isEmpty()) 1851 return; 1852 float pt[] = (float [])ar.get(0); 1853 moveTo(pt[0], pt[1]); 1854 for (int k = 0; k < ar.size(); ++k) { 1855 pt = (float [])ar.get(k); 1856 curveTo(pt[2], pt[3], pt[4], pt[5], pt[6], pt[7]); 1857 } 1858 } 1859 1860 1868 public void ellipse(float x1, float y1, float x2, float y2) { 1869 arc(x1, y1, x2, y2, 0f, 360f); 1870 } 1871 1872 1883 public PdfPatternPainter createPattern(float width, float height, float xstep, float ystep) { 1884 checkWriter(); 1885 if ( xstep == 0.0f || ystep == 0.0f ) 1886 throw new RuntimeException ("XStep or YStep can not be ZERO."); 1887 PdfPatternPainter painter = new PdfPatternPainter(writer); 1888 painter.setWidth(width); 1889 painter.setHeight(height); 1890 painter.setXStep(xstep); 1891 painter.setYStep(ystep); 1892 writer.addSimplePattern(painter); 1893 return painter; 1894 } 1895 1896 1903 public PdfPatternPainter createPattern(float width, float height) { 1904 return createPattern(width, height, width, height); 1905 } 1906 1907 1919 public PdfPatternPainter createPattern(float width, float height, float xstep, float ystep, Color color) { 1920 checkWriter(); 1921 if ( xstep == 0.0f || ystep == 0.0f ) 1922 throw new RuntimeException ("XStep or YStep can not be ZERO."); 1923 PdfPatternPainter painter = new PdfPatternPainter(writer, color); 1924 painter.setWidth(width); 1925 painter.setHeight(height); 1926 painter.setXStep(xstep); 1927 painter.setYStep(ystep); 1928 writer.addSimplePattern(painter); 1929 return painter; 1930 } 1931 1932 1941 public PdfPatternPainter createPattern(float width, float height, Color color) { 1942 return createPattern(width, height, width, height, color); 1943 } 1944 1945 1957 public PdfTemplate createTemplate(float width, float height) { 1958 return createTemplate(width, height, null); 1959 } 1960 1961 PdfTemplate createTemplate(float width, float height, PdfName forcedName) { 1962 checkWriter(); 1963 PdfTemplate template = new PdfTemplate(writer); 1964 template.setWidth(width); 1965 template.setHeight(height); 1966 writer.addDirectTemplateSimple(template, forcedName); 1967 return template; 1968 } 1969 1970 1977 public PdfAppearance createAppearance(float width, float height) { 1978 return createAppearance(width, height, null); 1979 } 1980 1981 PdfAppearance createAppearance(float width, float height, PdfName forcedName) { 1982 checkWriter(); 1983 PdfAppearance template = new PdfAppearance(writer); 1984 template.setWidth(width); 1985 template.setHeight(height); 1986 writer.addDirectTemplateSimple(template, forcedName); 1987 return template; 1988 } 1989 1990 1995 public void addPSXObject(PdfPSXObject psobject) { 1996 checkWriter(); 1997 PdfName name = writer.addDirectTemplateSimple(psobject, null); 1998 PageResources prs = getPageResources(); 1999 name = prs.addXObject(name, psobject.getIndirectReference()); 2000 content.append(name.getBytes()).append(" Do").append_i(separator); 2001 } 2002 2003 2014 public void addTemplate(PdfTemplate template, float a, float b, float c, float d, float e, float f) { 2015 checkWriter(); 2016 checkNoPattern(template); 2017 PdfName name = writer.addDirectTemplateSimple(template, null); 2018 PageResources prs = getPageResources(); 2019 name = prs.addXObject(name, template.getIndirectReference()); 2020 content.append("q "); 2021 content.append(a).append(' '); 2022 content.append(b).append(' '); 2023 content.append(c).append(' '); 2024 content.append(d).append(' '); 2025 content.append(e).append(' '); 2026 content.append(f).append(" cm "); 2027 content.append(name.getBytes()).append(" Do Q").append_i(separator); 2028 } 2029 2030 void addTemplateReference(PdfIndirectReference template, PdfName name, float a, float b, float c, float d, float e, float f) { 2031 checkWriter(); 2032 PageResources prs = getPageResources(); 2033 name = prs.addXObject(name, template); 2034 content.append("q "); 2035 content.append(a).append(' '); 2036 content.append(b).append(' '); 2037 content.append(c).append(' '); 2038 content.append(d).append(' '); 2039 content.append(e).append(' '); 2040 content.append(f).append(" cm "); 2041 content.append(name.getBytes()).append(" Do Q").append_i(separator); 2042 } 2043 2044 2051 public void addTemplate(PdfTemplate template, float x, float y) { 2052 addTemplate(template, 1, 0, 0, 1, x, y); 2053 } 2054 2055 2072 2073 public void setCMYKColorFill(int cyan, int magenta, int yellow, int black) { 2074 content.append((float)(cyan & 0xFF) / 0xFF); 2075 content.append(' '); 2076 content.append((float)(magenta & 0xFF) / 0xFF); 2077 content.append(' '); 2078 content.append((float)(yellow & 0xFF) / 0xFF); 2079 content.append(' '); 2080 content.append((float)(black & 0xFF) / 0xFF); 2081 content.append(" k").append_i(separator); 2082 } 2083 2099 2100 public void setCMYKColorStroke(int cyan, int magenta, int yellow, int black) { 2101 content.append((float)(cyan & 0xFF) / 0xFF); 2102 content.append(' '); 2103 content.append((float)(magenta & 0xFF) / 0xFF); 2104 content.append(' '); 2105 content.append((float)(yellow & 0xFF) / 0xFF); 2106 content.append(' '); 2107 content.append((float)(black & 0xFF) / 0xFF); 2108 content.append(" K").append_i(separator); 2109 } 2110 2111 2127 2128 public void setRGBColorFill(int red, int green, int blue) { 2129 HelperRGB((float)(red & 0xFF) / 0xFF, (float)(green & 0xFF) / 0xFF, (float)(blue & 0xFF) / 0xFF); 2130 content.append(" rg").append_i(separator); 2131 } 2132 2133 2148 2149 public void setRGBColorStroke(int red, int green, int blue) { 2150 HelperRGB((float)(red & 0xFF) / 0xFF, (float)(green & 0xFF) / 0xFF, (float)(blue & 0xFF) / 0xFF); 2151 content.append(" RG").append_i(separator); 2152 } 2153 2154 2158 public void setColorStroke(Color color) { 2159 PdfXConformanceImp.checkPDFXConformance(writer, PdfXConformanceImp.PDFXKEY_COLOR, color); 2160 int type = ExtendedColor.getType(color); 2161 switch (type) { 2162 case ExtendedColor.TYPE_GRAY: { 2163 setGrayStroke(((GrayColor)color).getGray()); 2164 break; 2165 } 2166 case ExtendedColor.TYPE_CMYK: { 2167 CMYKColor cmyk = (CMYKColor)color; 2168 setCMYKColorStrokeF(cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack()); 2169 break; 2170 } 2171 case ExtendedColor.TYPE_SEPARATION: { 2172 SpotColor spot = (SpotColor)color; 2173 setColorStroke(spot.getPdfSpotColor(), spot.getTint()); 2174 break; 2175 } 2176 case ExtendedColor.TYPE_PATTERN: { 2177 PatternColor pat = (PatternColor) color; 2178 setPatternStroke(pat.getPainter()); 2179 break; 2180 } 2181 case ExtendedColor.TYPE_SHADING: { 2182 ShadingColor shading = (ShadingColor) color; 2183 setShadingStroke(shading.getPdfShadingPattern()); 2184 break; 2185 } 2186 default: 2187 setRGBColorStroke(color.getRed(), color.getGreen(), color.getBlue()); 2188 } 2189 } 2190 2191 2195 public void setColorFill(Color color) { 2196 PdfXConformanceImp.checkPDFXConformance(writer, PdfXConformanceImp.PDFXKEY_COLOR, color); 2197 int type = ExtendedColor.getType(color); 2198 switch (type) { 2199 case ExtendedColor.TYPE_GRAY: { 2200 setGrayFill(((GrayColor)color).getGray()); 2201 break; 2202 } 2203 case ExtendedColor.TYPE_CMYK: { 2204 CMYKColor cmyk = (CMYKColor)color; 2205 setCMYKColorFillF(cmyk.getCyan(), cmyk.getMagenta(), cmyk.getYellow(), cmyk.getBlack()); 2206 break; 2207 } 2208 case ExtendedColor.TYPE_SEPARATION: { 2209 SpotColor spot = (SpotColor)color; 2210 setColorFill(spot.getPdfSpotColor(), spot.getTint()); 2211 break; 2212 } 2213 case ExtendedColor.TYPE_PATTERN: { 2214 PatternColor pat = (PatternColor) color; 2215 setPatternFill(pat.getPainter()); 2216 break; 2217 } 2218 case ExtendedColor.TYPE_SHADING: { 2219 ShadingColor shading = (ShadingColor) color; 2220 setShadingFill(shading.getPdfShadingPattern()); 2221 break; 2222 } 2223 default: 2224 setRGBColorFill(color.getRed(), color.getGreen(), color.getBlue()); 2225 } 2226 } 2227 2228 2233 public void setColorFill(PdfSpotColor sp, float tint) { 2234 checkWriter(); 2235 state.colorDetails = writer.addSimple(sp); 2236 PageResources prs = getPageResources(); 2237 PdfName name = state.colorDetails.getColorName(); 2238 name = prs.addColor(name, state.colorDetails.getIndirectReference()); 2239 content.append(name.getBytes()).append(" cs ").append(tint).append(" scn").append_i(separator); 2240 } 2241 2242 2247 public void setColorStroke(PdfSpotColor sp, float tint) { 2248 checkWriter(); 2249 state.colorDetails = writer.addSimple(sp); 2250 PageResources prs = getPageResources(); 2251 PdfName name = state.colorDetails.getColorName(); 2252 name = prs.addColor(name, state.colorDetails.getIndirectReference()); 2253 content.append(name.getBytes()).append(" CS ").append(tint).append(" SCN").append_i(separator); 2254 } 2255 2256 2260 public void setPatternFill(PdfPatternPainter p) { 2261 if (p.isStencil()) { 2262 setPatternFill(p, p.getDefaultColor()); 2263 return; 2264 } 2265 checkWriter(); 2266 PageResources prs = getPageResources(); 2267 PdfName name = writer.addSimplePattern(p); 2268 name = prs.addPattern(name, p.getIndirectReference()); 2269 content.append(PdfName.PATTERN.getBytes()).append(" cs ").append(name.getBytes()).append(" scn").append_i(separator); 2270 } 2271 2272 2276 void outputColorNumbers(Color color, float tint) { 2277 PdfXConformanceImp.checkPDFXConformance(writer, PdfXConformanceImp.PDFXKEY_COLOR, color); 2278 int type = ExtendedColor.getType(color); 2279 switch (type) { 2280 case ExtendedColor.TYPE_RGB: 2281 content.append((float)(color.getRed()) / 0xFF); 2282 content.append(' '); 2283 content.append((float)(color.getGreen()) / 0xFF); 2284 content.append(' '); 2285 content.append((float)(color.getBlue()) / 0xFF); 2286 break; 2287 case ExtendedColor.TYPE_GRAY: 2288 content.append(((GrayColor)color).getGray()); 2289 break; 2290 case ExtendedColor.TYPE_CMYK: { 2291 CMYKColor cmyk = (CMYKColor)color; 2292 content.append(cmyk.getCyan()).append(' ').append(cmyk.getMagenta()); 2293 content.append(' ').append(cmyk.getYellow()).append(' ').append(cmyk.getBlack()); 2294 break; 2295 } 2296 case ExtendedColor.TYPE_SEPARATION: 2297 content.append(tint); 2298 break; 2299 default: 2300 throw new RuntimeException ("Invalid color type."); 2301 } 2302 } 2303 2304 2308 public void setPatternFill(PdfPatternPainter p, Color color) { 2309 if (ExtendedColor.getType(color) == ExtendedColor.TYPE_SEPARATION) 2310 setPatternFill(p, color, ((SpotColor)color).getTint()); 2311 else 2312 setPatternFill(p, color, 0); 2313 } 2314 2315 2320 public void setPatternFill(PdfPatternPainter p, Color color, float tint) { 2321 checkWriter(); 2322 if (!p.isStencil()) 2323 throw new RuntimeException ("An uncolored pattern was expected."); 2324 PageResources prs = getPageResources(); 2325 PdfName name = writer.addSimplePattern(p); 2326 name = prs.addPattern(name, p.getIndirectReference()); 2327 ColorDetails csDetail = writer.addSimplePatternColorspace(color); 2328 PdfName cName = prs.addColor(csDetail.getColorName(), csDetail.getIndirectReference()); 2329 content.append(cName.getBytes()).append(" cs").append_i(separator); 2330 outputColorNumbers(color, tint); 2331 content.append(' ').append(name.getBytes()).append(" scn").append_i(separator); 2332 } 2333 2334 2338 public void setPatternStroke(PdfPatternPainter p, Color color) { 2339 if (ExtendedColor.getType(color) == ExtendedColor.TYPE_SEPARATION) 2340 setPatternStroke(p, color, ((SpotColor)color).getTint()); 2341 else 2342 setPatternStroke(p, color, 0); 2343 } 2344 2345 2350 public void setPatternStroke(PdfPatternPainter p, Color color, float tint) { 2351 checkWriter(); 2352 if (!p.isStencil()) 2353 throw new RuntimeException ("An uncolored pattern was expected."); 2354 PageResources prs = getPageResources(); 2355 PdfName name = writer.addSimplePattern(p); 2356 name = prs.addPattern(name, p.getIndirectReference()); 2357 ColorDetails csDetail = writer.addSimplePatternColorspace(color); 2358 PdfName cName = prs.addColor(csDetail.getColorName(), csDetail.getIndirectReference()); 2359 content.append(cName.getBytes()).append(" CS").append_i(separator); 2360 outputColorNumbers(color, tint); 2361 content.append(' ').append(name.getBytes()).append(" SCN").append_i(separator); 2362 } 2363 2364 2368 public void setPatternStroke(PdfPatternPainter p) { 2369 if (p.isStencil()) { 2370 setPatternStroke(p, p.getDefaultColor()); 2371 return; 2372 } 2373 checkWriter(); 2374 PageResources prs = getPageResources(); 2375 PdfName name = writer.addSimplePattern(p); 2376 name = prs.addPattern(name, p.getIndirectReference()); 2377 content.append(PdfName.PATTERN.getBytes()).append(" CS ").append(name.getBytes()).append(" SCN").append_i(separator); 2378 } 2379 2380 2384 public void paintShading(PdfShading shading) { 2385 writer.addSimpleShading(shading); 2386 PageResources prs = getPageResources(); 2387 PdfName name = prs.addShading(shading.getShadingName(), shading.getShadingReference()); 2388 content.append(name.getBytes()).append(" sh").append_i(separator); 2389 ColorDetails details = shading.getColorDetails(); 2390 if (details != null) 2391 prs.addColor(details.getColorName(), details.getIndirectReference()); 2392 } 2393 2394 2398 public void paintShading(PdfShadingPattern shading) { 2399 paintShading(shading.getShading()); 2400 } 2401 2402 2406 public void setShadingFill(PdfShadingPattern shading) { 2407 writer.addSimpleShadingPattern(shading); 2408 PageResources prs = getPageResources(); 2409 PdfName name = prs.addPattern(shading.getPatternName(), shading.getPatternReference()); 2410 content.append(PdfName.PATTERN.getBytes()).append(" cs ").append(name.getBytes()).append(" scn").append_i(separator); 2411 ColorDetails details = shading.getColorDetails(); 2412 if (details != null) 2413 prs.addColor(details.getColorName(), details.getIndirectReference()); 2414 } 2415 2416 2420 public void setShadingStroke(PdfShadingPattern shading) { 2421 writer.addSimpleShadingPattern(shading); 2422 PageResources prs = getPageResources(); 2423 PdfName name = prs.addPattern(shading.getPatternName(), shading.getPatternReference()); 2424 content.append(PdfName.PATTERN.getBytes()).append(" CS ").append(name.getBytes()).append(" SCN").append_i(separator); 2425 ColorDetails details = shading.getColorDetails(); 2426 if (details != null) 2427 prs.addColor(details.getColorName(), details.getIndirectReference()); 2428 } 2429 2430 2433 protected void checkWriter() { 2434 if (writer == null) 2435 throw new NullPointerException ("The writer in PdfContentByte is null."); 2436 } 2437 2438 2442 public void showText(PdfTextArray text) { 2443 if (state.fontDetails == null) 2444 throw new NullPointerException ("Font and size must be set before writing any text"); 2445 content.append("["); 2446 ArrayList arrayList = text.getArrayList(); 2447 boolean lastWasNumber = false; 2448 for (int k = 0; k < arrayList.size(); ++k) { 2449 Object obj = arrayList.get(k); 2450 if (obj instanceof String ) { 2451 showText2((String )obj); 2452 lastWasNumber = false; 2453 } 2454 else { 2455 if (lastWasNumber) 2456 content.append(' '); 2457 else 2458 lastWasNumber = true; 2459 content.append(((Float )obj).floatValue()); 2460 } 2461 } 2462 content.append("]TJ").append_i(separator); 2463 } 2464 2465 2469 public PdfWriter getPdfWriter() { 2470 return writer; 2471 } 2472 2473 2477 public PdfDocument getPdfDocument() { 2478 return pdf; 2479 } 2480 2481 2490 public void localGoto(String name, float llx, float lly, float urx, float ury) { 2491 pdf.localGoto(name, llx, lly, urx, ury); 2492 } 2493 2494 2503 public boolean localDestination(String name, PdfDestination destination) { 2504 return pdf.localDestination(name, destination); 2505 } 2506 2507 2513 public PdfContentByte getDuplicate() { 2514 return new PdfContentByte(writer); 2515 } 2516 2517 2526 public void remoteGoto(String filename, String name, float llx, float lly, float urx, float ury) { 2527 pdf.remoteGoto(filename, name, llx, lly, urx, ury); 2528 } 2529 2530 2539 public void remoteGoto(String filename, int page, float llx, float lly, float urx, float ury) { 2540 pdf.remoteGoto(filename, page, llx, lly, urx, ury); 2541 } 2542 2551 public void roundRectangle(float x, float y, float w, float h, float r) { 2552 if (w < 0) { 2553 x += w; 2554 w = -w; 2555 } 2556 if (h < 0) { 2557 y += h; 2558 h = -h; 2559 } 2560 if (r < 0) 2561 r = -r; 2562 float b = 0.4477f; 2563 moveTo(x + r, y); 2564 lineTo(x + w - r, y); 2565 curveTo(x + w - r * b, y, x + w, y + r * b, x + w, y + r); 2566 lineTo(x + w, y + h - r); 2567 curveTo(x + w, y + h - r * b, x + w - r * b, y + h, x + w - r, y + h); 2568 lineTo(x + r, y + h); 2569 curveTo(x + r * b, y + h, x, y + h - r * b, x, y + h - r); 2570 lineTo(x, y + r); 2571 curveTo(x, y + r * b, x + r * b, y, x + r, y); 2572 } 2573 2574 2581 public void setAction(PdfAction action, float llx, float lly, float urx, float ury) { 2582 pdf.setAction(action, llx, lly, urx, ury); 2583 } 2584 2585 2588 public void setLiteral(String s) { 2589 content.append(s); 2590 } 2591 2592 2595 public void setLiteral(char c) { 2596 content.append(c); 2597 } 2598 2599 2602 public void setLiteral(float n) { 2603 content.append(n); 2604 } 2605 2606 2609 void checkNoPattern(PdfTemplate t) { 2610 if (t.getType() == PdfTemplate.TYPE_PATTERN) 2611 throw new RuntimeException ("Invalid use of a pattern. A template was expected."); 2612 } 2613 2614 2622 public void drawRadioField(float llx, float lly, float urx, float ury, boolean on) { 2623 if (llx > urx) { float x = llx; llx = urx; urx = x; } 2624 if (lly > ury) { float y = lly; lly = ury; ury = y; } 2625 setLineWidth(1); 2627 setLineCap(1); 2628 setColorStroke(new Color (0xC0, 0xC0, 0xC0)); 2629 arc(llx + 1f, lly + 1f, urx - 1f, ury - 1f, 0f, 360f); 2630 stroke(); 2631 setLineWidth(1); 2633 setLineCap(1); 2634 setColorStroke(new Color (0xA0, 0xA0, 0xA0)); 2635 arc(llx + 0.5f, lly + 0.5f, urx - 0.5f, ury - 0.5f, 45, 180); 2636 stroke(); 2637 setLineWidth(1); 2639 setLineCap(1); 2640 setColorStroke(new Color (0x00, 0x00, 0x00)); 2641 arc(llx + 1.5f, lly + 1.5f, urx - 1.5f, ury - 1.5f, 45, 180); 2642 stroke(); 2643 if (on) { 2644 setLineWidth(1); 2646 setLineCap(1); 2647 setColorFill(new Color (0x00, 0x00, 0x00)); 2648 arc(llx + 4f, lly + 4f, urx - 4f, ury - 4f, 0, 360); 2649 fill(); 2650 } 2651 } 2652 2653 2660 public void drawTextField(float llx, float lly, float urx, float ury) { 2661 if (llx > urx) { float x = llx; llx = urx; urx = x; } 2662 if (lly > ury) { float y = lly; lly = ury; ury = y; } 2663 setColorStroke(new Color (0xC0, 0xC0, 0xC0)); 2665 setLineWidth(1); 2666 setLineCap(0); 2667 rectangle(llx, lly, urx - llx, ury - lly); 2668 stroke(); 2669 setLineWidth(1); 2671 setLineCap(0); 2672 setColorFill(new Color (0xFF, 0xFF, 0xFF)); 2673 rectangle(llx + 0.5f, lly + 0.5f, urx - llx - 1f, ury -lly - 1f); 2674 fill(); 2675 setColorStroke(new Color (0xC0, 0xC0, 0xC0)); 2677 setLineWidth(1); 2678 setLineCap(0); 2679 moveTo(llx + 1f, lly + 1.5f); 2680 lineTo(urx - 1.5f, lly + 1.5f); 2681 lineTo(urx - 1.5f, ury - 1f); 2682 stroke(); 2683 setColorStroke(new Color (0xA0, 0xA0, 0xA0)); 2685 setLineWidth(1); 2686 setLineCap(0); 2687 moveTo(llx + 1f, lly + 1); 2688 lineTo(llx + 1f, ury - 1f); 2689 lineTo(urx - 1f, ury - 1f); 2690 stroke(); 2691 setColorStroke(new Color (0x00, 0x00, 0x00)); 2693 setLineWidth(1); 2694 setLineCap(0); 2695 moveTo(llx + 2f, lly + 2f); 2696 lineTo(llx + 2f, ury - 2f); 2697 lineTo(urx - 2f, ury - 2f); 2698 stroke(); 2699 } 2700 2701 2711 public void drawButton(float llx, float lly, float urx, float ury, String text, BaseFont bf, float size) { 2712 if (llx > urx) { float x = llx; llx = urx; urx = x; } 2713 if (lly > ury) { float y = lly; lly = ury; ury = y; } 2714 setColorStroke(new Color (0x00, 0x00, 0x00)); 2716 setLineWidth(1); 2717 setLineCap(0); 2718 rectangle(llx, lly, urx - llx, ury - lly); 2719 stroke(); 2720 setLineWidth(1); 2722 setLineCap(0); 2723 setColorFill(new Color (0xC0, 0xC0, 0xC0)); 2724 rectangle(llx + 0.5f, lly + 0.5f, urx - llx - 1f, ury -lly - 1f); 2725 fill(); 2726 setColorStroke(new Color (0xFF, 0xFF, 0xFF)); 2728 setLineWidth(1); 2729 setLineCap(0); 2730 moveTo(llx + 1f, lly + 1f); 2731 lineTo(llx + 1f, ury - 1f); 2732 lineTo(urx - 1f, ury - 1f); 2733 stroke(); 2734 setColorStroke(new Color (0xA0, 0xA0, 0xA0)); 2736 setLineWidth(1); 2737 setLineCap(0); 2738 moveTo(llx + 1f, lly + 1f); 2739 lineTo(urx - 1f, lly + 1f); 2740 lineTo(urx - 1f, ury - 1f); 2741 stroke(); 2742 resetRGBColorFill(); 2744 beginText(); 2745 setFontAndSize(bf, size); 2746 showTextAligned(PdfContentByte.ALIGN_CENTER, text, llx + (urx - llx) / 2, lly + (ury - lly - size) / 2, 0); 2747 endText(); 2748 } 2749 2750 2756 public java.awt.Graphics2D createGraphicsShapes(float width, float height) { 2757 return new PdfGraphics2D(this, width, height, null, true, false, 0); 2758 } 2759 2760 2767 public java.awt.Graphics2D createPrinterGraphicsShapes(float width, float height, PrinterJob printerJob) { 2768 return new PdfPrinterGraphics2D(this, width, height, null, true, false, 0, printerJob); 2769 } 2770 2771 2777 public java.awt.Graphics2D createGraphics(float width, float height) { 2778 return new PdfGraphics2D(this, width, height, null, false, false, 0); 2779 } 2780 2781 2788 public java.awt.Graphics2D createPrinterGraphics(float width, float height, PrinterJob printerJob) { 2789 return new PdfPrinterGraphics2D(this, width, height, null, false, false, 0, printerJob); 2790 } 2791 2792 2800 public java.awt.Graphics2D createGraphics(float width, float height, boolean convertImagesToJPEG, float quality) { 2801 return new PdfGraphics2D(this, width, height, null, false, convertImagesToJPEG, quality); 2802 } 2803 2804 2813 public java.awt.Graphics2D createPrinterGraphics(float width, float height, boolean convertImagesToJPEG, float quality, PrinterJob printerJob) { 2814 return new PdfPrinterGraphics2D(this, width, height, null, false, convertImagesToJPEG, quality, printerJob); 2815 } 2816 2817 2825 public java.awt.Graphics2D createGraphicsShapes(float width, float height, boolean convertImagesToJPEG, float quality) { 2826 return new PdfGraphics2D(this, width, height, null, true, convertImagesToJPEG, quality); 2827 } 2828 2829 2838 public java.awt.Graphics2D createPrinterGraphicsShapes(float width, float height, boolean convertImagesToJPEG, float quality, PrinterJob printerJob) { 2839 return new PdfPrinterGraphics2D(this, width, height, null, true, convertImagesToJPEG, quality, printerJob); 2840 } 2841 2842 2849 public java.awt.Graphics2D createGraphics(float width, float height, FontMapper fontMapper) { 2850 return new PdfGraphics2D(this, width, height, fontMapper, false, false, 0); 2851 } 2852 2853 2861 public java.awt.Graphics2D createPrinterGraphics(float width, float height, FontMapper fontMapper, PrinterJob printerJob) { 2862 return new PdfPrinterGraphics2D(this, width, height, fontMapper, false, false, 0, printerJob); 2863 } 2864 2865 2874 public java.awt.Graphics2D createGraphics(float width, float height, FontMapper fontMapper, boolean convertImagesToJPEG, float quality) { 2875 return new PdfGraphics2D(this, width, height, fontMapper, false, convertImagesToJPEG, quality); 2876 } 2877 2878 2888 public java.awt.Graphics2D createPrinterGraphics(float width, float height, FontMapper fontMapper, boolean convertImagesToJPEG, float quality, PrinterJob printerJob) { 2889 return new PdfPrinterGraphics2D(this, width, height, fontMapper, false, convertImagesToJPEG, quality, printerJob); 2890 } 2891 2892 PageResources getPageResources() { 2893 return pdf.getPageResources(); 2894 } 2895 2896 2899 public void setGState(PdfGState gstate) { 2900 PdfObject obj[] = writer.addSimpleExtGState(gstate); 2901 PageResources prs = getPageResources(); 2902 PdfName name = prs.addExtGState((PdfName)obj[0], (PdfIndirectReference)obj[1]); 2903 content.append(name.getBytes()).append(" gs").append_i(separator); 2904 } 2905 2906 2914 public void beginLayer(PdfOCG layer) { 2915 if ((layer instanceof PdfLayer) && ((PdfLayer)layer).getTitle() != null) 2916 throw new IllegalArgumentException ("A title is not a layer"); 2917 if (layerDepth == null) 2918 layerDepth = new ArrayList (); 2919 if (layer instanceof PdfLayerMembership) { 2920 layerDepth.add(new Integer (1)); 2921 beginLayer2(layer); 2922 return; 2923 } 2924 int n = 0; 2925 PdfLayer la = (PdfLayer)layer; 2926 while (la != null) { 2927 if (la.getTitle() == null) { 2928 beginLayer2(la); 2929 ++n; 2930 } 2931 la = la.getParent(); 2932 } 2933 layerDepth.add(new Integer (n)); 2934 } 2935 2936 private void beginLayer2(PdfOCG layer) { 2937 PdfName name = (PdfName)writer.addSimpleProperty(layer, layer.getRef())[0]; 2938 PageResources prs = getPageResources(); 2939 name = prs.addProperty(name, layer.getRef()); 2940 content.append("/OC ").append(name.getBytes()).append(" BDC").append_i(separator); 2941 } 2942 2943 2946 public void endLayer() { 2947 int n = 1; 2948 if (layerDepth != null && !layerDepth.isEmpty()) { 2949 n = ((Integer )layerDepth.get(layerDepth.size() - 1)).intValue(); 2950 layerDepth.remove(layerDepth.size() - 1); 2951 } 2952 while (n-- > 0) 2953 content.append("EMC").append_i(separator); 2954 } 2955 2956 2960 public void transform(AffineTransform af) { 2961 double arr[] = new double[6]; 2962 af.getMatrix(arr); 2963 content.append(arr[0]).append(' ').append(arr[1]).append(' ').append(arr[2]).append(' '); 2964 content.append(arr[3]).append(' ').append(arr[4]).append(' ').append(arr[5]).append(" cm").append_i(separator); 2965 } 2966 2967 void addAnnotation(PdfAnnotation annot) { 2968 writer.addAnnotation(annot); 2969 } 2970 2971 2977 public void setDefaultColorspace(PdfName name, PdfObject obj) { 2978 PageResources prs = getPageResources(); 2979 prs.addDefaultColor(name, obj); 2980 } 2981 2982 2988 public void beginMarkedContentSequence(PdfStructureElement struc) { 2989 PdfObject obj = struc.get(PdfName.K); 2990 int mark = pdf.getMarkPoint(); 2991 if (obj != null) { 2992 PdfArray ar = null; 2993 if (obj.isNumber()) { 2994 ar = new PdfArray(); 2995 ar.add(obj); 2996 struc.put(PdfName.K, ar); 2997 } 2998 else if (obj.isArray()) { 2999 ar = (PdfArray)obj; 3000 if (!((PdfObject)ar.getArrayList().get(0)).isNumber()) 3001 throw new IllegalArgumentException ("The structure has kids."); 3002 } 3003 else 3004 throw new IllegalArgumentException ("Unknown object at /K " + obj.getClass().toString()); 3005 PdfDictionary dic = new PdfDictionary(PdfName.MCR); 3006 dic.put(PdfName.PG, writer.getCurrentPage()); 3007 dic.put(PdfName.MCID, new PdfNumber(mark)); 3008 ar.add(dic); 3009 struc.setPageMark(writer.getPageNumber() - 1, -1); 3010 } 3011 else { 3012 struc.setPageMark(writer.getPageNumber() - 1, mark); 3013 struc.put(PdfName.PG, writer.getCurrentPage()); 3014 } 3015 pdf.incMarkPoint(); 3016 content.append(struc.get(PdfName.S).getBytes()).append(" <</MCID ").append(mark).append(">> BDC").append_i(separator); 3017 } 3018 3019 3022 public void endMarkedContentSequence() { 3023 content.append("EMC").append_i(separator); 3024 } 3025 3026 3034 public void beginMarkedContentSequence(PdfName tag, PdfDictionary property, boolean inline) { 3035 if (property == null) { 3036 content.append(tag.getBytes()).append(" BMC").append_i(separator); 3037 return; 3038 } 3039 content.append(tag.getBytes()).append(' '); 3040 if (inline) 3041 try { 3042 property.toPdf(writer, content); 3043 } 3044 catch (Exception e) { 3045 throw new ExceptionConverter(e); 3046 } 3047 else { 3048 PdfObject[] objs; 3049 if (writer.propertyExists(property)) 3050 objs = writer.addSimpleProperty(property, null); 3051 else 3052 objs = writer.addSimpleProperty(property, writer.getPdfIndirectReference()); 3053 PdfName name = (PdfName)objs[0]; 3054 PageResources prs = getPageResources(); 3055 name = prs.addProperty(name, (PdfIndirectReference)objs[1]); 3056 content.append(name.getBytes()); 3057 } 3058 content.append(" BDC").append_i(separator); 3059 } 3060 3061 3065 public void beginMarkedContentSequence(PdfName tag) { 3066 beginMarkedContentSequence(tag, null, false); 3067 } 3068} 3069 | Popular Tags |