1 51 package org.apache.fop.pdf; 52 53 import org.apache.fop.image.FopImage; 56 57 import org.apache.fop.layout.LinkSet; 58 import org.apache.fop.datatypes.ColorSpace; 59 60 import org.apache.fop.render.pdf.CIDFont; 61 import org.apache.fop.render.pdf.fonts.LazyFont; 62 63 import org.apache.fop.datatypes.IDReferences; 64 import org.apache.fop.layout.Page; 65 import org.apache.fop.layout.FontMetric; 66 import org.apache.fop.layout.FontDescriptor; 67 import java.io.IOException ; 69 import java.io.OutputStream ; 70 import java.io.UnsupportedEncodingException ; 71 import java.util.List ; 72 import java.util.Map ; 73 import java.awt.Rectangle ; 74 75 101 public class PDFDocument { 102 private static final Integer locationPlaceholder = new Integer (0); 103 106 protected static final String pdfVersion = "1.3"; 107 108 111 protected int position = 0; 112 113 116 protected List location = new java.util.ArrayList (); 117 118 119 private List trailerObjects = new java.util.ArrayList (); 120 121 124 protected int objectcount = 0; 125 126 129 protected List objects = new java.util.ArrayList (); 130 131 134 protected int xref; 135 136 139 protected PDFRoot root; 140 141 142 private PDFOutline outlineRoot = null; 143 144 145 private PDFPages pages; 146 147 150 protected PDFInfo info; 151 152 155 protected PDFResources resources; 156 157 160 protected IDReferences idReferences; 161 162 165 protected PDFEncryption encryption; 166 167 170 protected ColorSpace colorspace = new ColorSpace(ColorSpace.DEVICE_RGB); 172 173 176 protected int patternCount = 0; 177 178 181 protected int shadingCount = 0; 182 183 186 protected int xObjectCount = 0; 187 188 191 protected List xObjects = new java.util.ArrayList (); 192 193 197 protected Map xObjectsMap = new java.util.HashMap (); 198 199 202 protected List pendingLinks = null; 203 204 207 public static final String ENCODING = "ISO-8859-1"; 208 209 221 public PDFDocument() { 222 223 224 this.pages = makePages(); 225 226 this.root = makeRoot(pages); 228 229 this.resources = makeResources(); 231 232 this.info = makeInfo(); 234 } 235 236 241 public void setProducer(String producer) { 242 this.info.setProducer(producer); 243 } 244 245 255 public void setEncryption(String ownerPassword, String userPassword, 256 boolean allowPrint, boolean allowCopyContent, 257 boolean allowEditContent, boolean allowEditAnnotations) { 258 this.encryption = new PDFEncryption(++this.objectcount); 259 this.encryption.setOwnerPassword(ownerPassword); 260 this.encryption.setUserPassword(userPassword); 261 this.encryption.setAllowPrint(allowPrint); 262 this.encryption.setAllowCopyContent(allowCopyContent); 263 this.encryption.setAllowEditContent(allowEditContent); 264 this.encryption.setAllowEditAnnotation(allowEditAnnotations); 265 this.encryption.init(); 266 addTrailerObject(this.encryption); 267 } 268 269 273 public PDFRoot makeRoot(PDFPages pages) { 274 275 278 PDFRoot pdfRoot = new PDFRoot(++this.objectcount, pages); 279 addTrailerObject(pdfRoot); 280 return pdfRoot; 281 } 282 283 286 287 public PDFPages makePages() { 288 PDFPages pdfPages = new PDFPages(++this.objectcount); 289 addTrailerObject(pdfPages); 290 return pdfPages; 291 } 292 293 296 public PDFResources makeResources() { 297 PDFResources pdfResources = new PDFResources(++this.objectcount); 298 addTrailerObject(pdfResources); 299 return pdfResources; 300 } 301 302 308 protected PDFInfo makeInfo() { 309 310 314 PDFInfo pdfInfo = new PDFInfo(++this.objectcount); 315 pdfInfo.setProducer(org.apache.fop.apps.Version.getVersion()); 317 this.objects.add(pdfInfo); 318 return pdfInfo; 319 } 320 321 374 public PDFFunction makeFunction(int theFunctionType, List theDomain, 375 List theRange, List theSize, 376 int theBitsPerSample, int theOrder, 377 List theEncode, List theDecode, 378 StringBuffer theFunctionDataStream, 379 List theFilter) { PDFFunction function = new PDFFunction(++this.objectcount, 381 theFunctionType, theDomain, 382 theRange, theSize, 383 theBitsPerSample, theOrder, 384 theEncode, theDecode, 385 theFunctionDataStream, 386 theFilter); 387 388 this.objects.add(function); 389 return (function); 390 } 391 392 417 public PDFFunction makeFunction(int theFunctionType, List theDomain, 418 List theRange, List theCZero, 419 List theCOne, 420 double theInterpolationExponentN) { PDFFunction function = new PDFFunction(++this.objectcount, 422 theFunctionType, theDomain, 423 theRange, theCZero, theCOne, 424 theInterpolationExponentN); 425 426 this.objects.add(function); 427 return (function); 428 } 429 430 462 public PDFFunction makeFunction(int theFunctionType, List theDomain, 463 List theRange, List theFunctions, 464 List theBounds, 465 List theEncode) { 467 PDFFunction function = new PDFFunction(++this.objectcount, 468 theFunctionType, theDomain, 469 theRange, theFunctions, 470 theBounds, theEncode); 471 472 this.objects.add(function); 473 return (function); 474 } 475 476 485 public PDFFunction makeFunction(int theNumber, int theFunctionType, 486 List theDomain, List theRange, 487 StringBuffer theFunctionDataStream) { PDFFunction function = new PDFFunction(++this.objectcount, 489 theFunctionType, theDomain, 490 theRange, 491 theFunctionDataStream); 492 493 this.objects.add(function); 494 return (function); 495 496 } 497 498 519 public PDFShading makeShading(int theShadingType, 520 ColorSpace theColorSpace, 521 List theBackground, List theBBox, 522 boolean theAntiAlias, List theDomain, 523 List theMatrix, 524 PDFFunction theFunction) { String theShadingName = new String ("Sh" + (++this.shadingCount)); 526 527 PDFShading shading = new PDFShading(++this.objectcount, 528 theShadingName, theShadingType, 529 theColorSpace, theBackground, 530 theBBox, theAntiAlias, theDomain, 531 theMatrix, theFunction); 532 this.objects.add(shading); 533 534 this.resources.addShading(shading); 536 537 return (shading); 538 } 539 540 559 public PDFShading makeShading(int theShadingType, 560 ColorSpace theColorSpace, 561 List theBackground, List theBBox, 562 boolean theAntiAlias, List theCoords, 563 List theDomain, PDFFunction theFunction, 564 List theExtend) { String theShadingName = new String ("Sh" + (++this.shadingCount)); 566 567 PDFShading shading = new PDFShading(++this.objectcount, 568 theShadingName, theShadingType, 569 theColorSpace, theBackground, 570 theBBox, theAntiAlias, theCoords, 571 theDomain, theFunction, 572 theExtend); 573 574 this.resources.addShading(shading); 575 576 this.objects.add(shading); 577 return (shading); 578 } 579 580 602 public PDFShading makeShading(int theShadingType, 603 ColorSpace theColorSpace, 604 List theBackground, List theBBox, 605 boolean theAntiAlias, 606 int theBitsPerCoordinate, 607 int theBitsPerComponent, 608 int theBitsPerFlag, List theDecode, 609 PDFFunction theFunction) { String theShadingName = new String ("Sh" + (++this.shadingCount)); 611 612 PDFShading shading = new PDFShading(++this.objectcount, 613 theShadingName, theShadingType, 614 theColorSpace, theBackground, 615 theBBox, theAntiAlias, 616 theBitsPerCoordinate, 617 theBitsPerComponent, 618 theBitsPerFlag, theDecode, 619 theFunction); 620 621 this.resources.addShading(shading); 622 623 this.objects.add(shading); 624 return (shading); 625 } 626 627 647 public PDFShading makeShading(int theShadingType, 648 ColorSpace theColorSpace, 649 List theBackground, List theBBox, 650 boolean theAntiAlias, 651 int theBitsPerCoordinate, 652 int theBitsPerComponent, List theDecode, 653 int theVerticesPerRow, 654 PDFFunction theFunction) { String theShadingName = new String ("Sh" + (++this.shadingCount)); 656 657 PDFShading shading = new PDFShading(++this.objectcount, 658 theShadingName, theShadingType, 659 theColorSpace, theBackground, 660 theBBox, theAntiAlias, 661 theBitsPerCoordinate, 662 theBitsPerComponent, theDecode, 663 theVerticesPerRow, theFunction); 664 665 this.resources.addShading(shading); 666 667 this.objects.add(shading); 668 669 return (shading); 670 } 671 672 686 public PDFPattern makePattern(int thePatternType, PDFResources theResources, int thePaintType, int theTilingType, 688 List theBBox, double theXStep, double theYStep, List theMatrix, 689 List theXUID, StringBuffer thePatternDataStream) { 690 String thePatternName = new String ("Pa" + (++this.patternCount)); 691 PDFPattern pattern = new PDFPattern(++this.objectcount, 694 thePatternName, theResources, 1, 695 thePaintType, theTilingType, 696 theBBox, theXStep, theYStep, 697 theMatrix, theXUID, 698 thePatternDataStream); 699 700 this.resources.addPattern(pattern); 701 this.objects.add(pattern); 702 703 return (pattern); 704 } 705 706 715 public PDFPattern makePattern(int thePatternType, PDFShading theShading, 716 List theXUID, StringBuffer theExtGState, 717 List theMatrix) { 718 String thePatternName = new String ("Pa" + (++this.patternCount)); 719 720 PDFPattern pattern = new PDFPattern(++this.objectcount, 721 thePatternName, 2, theShading, 722 theXUID, theExtGState, theMatrix); 723 724 this.resources.addPattern(pattern); 725 this.objects.add(pattern); 726 727 return (pattern); 728 } 729 730 public int getColorSpace() { 731 return (this.colorspace.getColorSpace()); 732 } 733 734 public void setColorSpace(int theColorspace) { 735 this.colorspace.setColorSpace(theColorspace); 736 return; 737 } 738 739 public PDFPattern createGradient(boolean radial, 740 ColorSpace theColorspace, 741 List theColors, List theBounds, 742 List theCoords) { 743 PDFShading myShad; 744 PDFFunction myfunky; 745 PDFFunction myfunc; 746 List theCzero; 747 List theCone; 748 PDFPattern myPattern; 749 ColorSpace theColorSpace; 750 double interpolation = (double)1.000; 751 List theFunctions = new java.util.ArrayList (); 752 753 int currentPosition; 754 int lastPosition = theColors.size() - 1; 755 756 757 761 for (currentPosition = 0; currentPosition < lastPosition; 762 currentPosition++) { PDFColor currentColor = 764 (PDFColor)theColors.get(currentPosition); 765 PDFColor nextColor = (PDFColor)theColors.get(currentPosition 766 + 1); 767 if (this.colorspace.getColorSpace() 769 != currentColor.getColorSpace()) 770 currentColor.setColorSpace(this.colorspace.getColorSpace()); 771 772 if (this.colorspace.getColorSpace() != nextColor.getColorSpace()) 773 nextColor.setColorSpace(this.colorspace.getColorSpace()); 774 775 theCzero = currentColor.getVector(); 776 theCone = nextColor.getVector(); 777 778 myfunc = this.makeFunction(2, null, null, theCzero, theCone, 779 interpolation); 780 781 theFunctions.add(myfunc); 782 783 } 785 myfunky = this.makeFunction(3, null, null, theFunctions, theBounds, 786 null); 787 788 if (radial) { 789 if (theCoords.size() == 6) { 790 myShad = this.makeShading(3, this.colorspace, null, null, 791 false, theCoords, null, myfunky, 792 null); 793 } else { List newCoords = new java.util.ArrayList (); 797 newCoords.add(theCoords.get(0)); 798 newCoords.add(theCoords.get(1)); 799 newCoords.add(theCoords.get(2)); 800 newCoords.add(theCoords.get(0)); 801 newCoords.add(theCoords.get(1)); 802 newCoords.add(new Double (0.0)); 803 804 myShad = this.makeShading(3, this.colorspace, null, null, 805 false, newCoords, null, myfunky, 806 null); 807 808 } 809 } else { 810 myShad = this.makeShading(2, this.colorspace, null, null, false, 811 theCoords, null, myfunky, null); 812 813 } 814 815 myPattern = this.makePattern(2, myShad, null, null, null); 816 817 return (myPattern); 818 } 819 820 821 827 public PDFEncoding makeEncoding(String encodingName) { 828 829 833 PDFEncoding encoding = new PDFEncoding(++this.objectcount, 834 encodingName); 835 this.objects.add(encoding); 836 return encoding; 837 } 838 839 840 public PDFICCStream makePDFICCStream() { 841 PDFICCStream iccStream = new PDFICCStream(++this.objectcount); 842 this.objects.add(iccStream); 843 return iccStream; 844 } 845 846 856 public PDFFont makeFont(String fontname, String basefont, 857 String encoding, FontMetric metrics, 858 FontDescriptor descriptor) { 859 860 864 if (descriptor == null) { 865 PDFFont font = new PDFFont(++this.objectcount, fontname, 866 PDFFont.TYPE1, basefont, encoding); 867 this.objects.add(font); 868 return font; 869 } else { 870 byte subtype = PDFFont.TYPE1; 871 if (metrics instanceof org.apache.fop.render.pdf.Font) 872 subtype = 873 ((org.apache.fop.render.pdf.Font)metrics).getSubType(); 874 875 PDFFontDescriptor pdfdesc = makeFontDescriptor(descriptor, 876 subtype); 877 878 PDFFontNonBase14 font = null; 879 if (subtype == PDFFont.TYPE0) { 880 891 font = 892 (PDFFontNonBase14)PDFFont.createFont(++this.objectcount, 893 fontname, subtype, 894 basefont, 895 "Identity-H"); 896 } else { 897 898 font = 899 (PDFFontNonBase14)PDFFont.createFont(++this.objectcount, 900 fontname, subtype, 901 basefont, encoding); 902 } 903 this.objects.add(font); 904 905 font.setDescriptor(pdfdesc); 906 907 if (subtype == PDFFont.TYPE0) { 908 CIDFont cidMetrics; 909 if(metrics instanceof LazyFont){ 910 cidMetrics = (CIDFont) ((LazyFont) metrics).getRealFont(); 911 }else{ 912 cidMetrics = (CIDFont)metrics; 913 } 914 PDFCIDSystemInfo sysInfo = 915 new PDFCIDSystemInfo(cidMetrics.getRegistry(), 916 cidMetrics.getOrdering(), 917 cidMetrics.getSupplement()); 918 PDFCIDFont cidFont = 919 new PDFCIDFont(++this.objectcount, basefont, 920 cidMetrics.getCidType(), 921 cidMetrics.getDefaultWidth(), 922 cidMetrics.getWidths(), sysInfo, 923 (PDFCIDFontDescriptor)pdfdesc); 924 this.objects.add(cidFont); 925 926 928 ((PDFFontType0)font).setDescendantFonts(cidFont); 929 } else { 930 font.setWidthMetrics(metrics.getFirstChar(), 931 metrics.getLastChar(), 932 makeArray(metrics.getWidths(1))); 933 } 934 935 return font; 936 } 937 } 938 939 940 943 public PDFFontDescriptor makeFontDescriptor(FontDescriptor desc, 944 byte subtype) { 945 PDFFontDescriptor font = null; 946 947 if (subtype == PDFFont.TYPE0) { 948 font = new PDFCIDFontDescriptor(++this.objectcount, 950 desc.fontName(), 951 desc.getFontBBox(), 952 desc.getCapHeight(), desc.getFlags(), 955 desc.getItalicAngle(), desc.getStemV(), null); } 959 else { 960 font = new PDFFontDescriptor(++this.objectcount, desc.fontName(), 962 desc.getAscender(), 963 desc.getDescender(), 964 desc.getCapHeight(), 965 desc.getFlags(), 966 new PDFRectangle(desc.getFontBBox()), 967 desc.getStemV(), 968 desc.getItalicAngle()); 969 } 970 this.objects.add(font); 971 972 if (desc.isEmbeddable()) { 974 PDFStream stream = desc.getFontFile(this.objectcount + 1); 975 if (stream != null) { 976 this.objectcount++; 977 font.setFontFile(desc.getSubType(), stream); 978 this.objects.add(stream); 979 } 980 } 981 return font; 982 } 983 984 985 988 public PDFArray makeArray(int[] values) { 989 990 PDFArray array = new PDFArray(++this.objectcount, values); 991 this.objects.add(array); 992 return array; 993 } 994 995 996 public int addImage(FopImage img) { 997 String url = img.getURL(); 999 PDFXObject xObject = (PDFXObject)this.xObjectsMap.get(url); 1000 if (xObject != null) 1001 return xObject.getXNumber(); 1002 xObject = new PDFXObject(++this.objectcount, ++this.xObjectCount, img, this); 1004 this.objects.add(xObject); 1005 this.xObjects.add(xObject); 1006 this.xObjectsMap.put(url, xObject); 1007 return xObjectCount; 1008 } 1009 1010 1020 public PDFPage makePage(PDFResources resources, PDFStream contents, 1021 int pagewidth, int pageheight, Page currentPage) { 1022 1023 1027 PDFPage page = new PDFPage(++this.objectcount, resources, contents, 1028 pagewidth, pageheight); 1029 1030 if(pendingLinks != null) { 1031 for(int i = 0; i< pendingLinks.size(); i++ ) { 1032 PendingLink pl = (PendingLink)pendingLinks.get(i); 1033 PDFGoTo gt = new PDFGoTo(++this.objectcount, 1034 page.referencePDF()); 1035 gt.setDestination(pl.dest); 1036 addTrailerObject(gt); 1037 PDFInternalLink internalLink = 1038 new PDFInternalLink(gt.referencePDF()); 1039 pl.link.setAction(internalLink); 1040 } 1041 pendingLinks = null; 1042 } 1043 1044 if (currentPage != null) { 1045 for(int i = 0; i< currentPage.getIDList().size(); i++ ) { 1046 String id = currentPage.getIDList().get(i).toString(); 1047 idReferences.setInternalGoToPageReference(id, 1048 page.referencePDF()); 1049 } 1050 } 1051 1052 1053 this.objects.add(page); 1054 1055 1056 this.root.addPage(page); 1057 1058 return page; 1059 } 1060 1061 1069 public PDFLink makeLink(Rectangle rect, String destination, 1070 int linkType) { 1071 1072 PDFLink linkObject; 1073 PDFAction action; 1074 int index; 1075 1076 PDFLink link = new PDFLink(++this.objectcount, rect); 1077 this.objects.add(link); 1078 1079 if (linkType == LinkSet.EXTERNAL) { 1080 if (destination.endsWith(".pdf")) { PDFFileSpec fileSpec = new PDFFileSpec(++this.objectcount, 1083 destination); 1084 this.objects.add(fileSpec); 1085 action = new PDFGoToRemote(++this.objectcount, fileSpec); 1086 this.objects.add(action); 1087 link.setAction(action); 1088 } else if ((index = destination.indexOf(".pdf#page=")) > 0) { 1089 String file = destination.substring(0, index + 4); 1090 int page = Integer.parseInt(destination.substring(index + 10)); 1091 PDFFileSpec fileSpec = new PDFFileSpec(++this.objectcount, file); 1092 this.objects.add(fileSpec); 1093 action = new PDFGoToRemote(++this.objectcount, fileSpec, page); 1094 this.objects.add(action); 1095 link.setAction(action); 1096 } else if ((index = destination.indexOf(".pdf#dest=")) > 0) { 1097 String file = destination.substring(0, index + 4); 1098 String dest = destination.substring(index + 10); 1099 PDFFileSpec fileSpec = new PDFFileSpec(++this.objectcount, file); 1100 this.objects.add(fileSpec); 1101 action = new PDFGoToRemote(++this.objectcount, fileSpec, dest); 1102 this.objects.add(action); 1103 link.setAction(action); 1104 } else { PDFUri uri = new PDFUri(destination); 1106 link.setAction(uri); 1107 } 1108 } else { String goToReference = getGoToReference(destination); 1110 PDFInternalLink internalLink = new PDFInternalLink(goToReference); 1111 link.setAction(internalLink); 1112 } 1113 return link; 1114 } 1115 1116 private String getGoToReference(String destination) { 1117 String goToReference; 1118 if (idReferences.doesIDExist(destination)) { 1119 if (idReferences.doesGoToReferenceExist(destination)) { 1120 goToReference = 1121 idReferences.getInternalLinkGoToReference(destination); 1122 } else { goToReference = 1124 idReferences.createInternalLinkGoTo(destination, 1125 ++this.objectcount); 1126 addTrailerObject(idReferences.getPDFGoTo(destination)); 1127 } 1128 } else { 1130 1134 idReferences.createUnvalidatedID(destination); 1135 idReferences.addToIdValidationList(destination); 1136 goToReference = idReferences.createInternalLinkGoTo(destination, 1137 ++this.objectcount); 1138 addTrailerObject(idReferences.getPDFGoTo(destination)); 1139 } 1140 return goToReference; 1141 } 1142 1143 public void addTrailerObject(PDFObject object) { 1144 this.trailerObjects.add(object); 1145 } 1146 1147 class PendingLink { 1148 PDFLink link; 1149 String dest; 1150 } 1151 1152 public PDFLink makeLinkCurrentPage(Rectangle rect, String dest) { 1153 PDFLink link = new PDFLink(++this.objectcount, rect); 1154 this.objects.add(link); 1155 PendingLink pl = new PendingLink(); 1156 pl.link = link; 1157 pl.dest = dest; 1158 if(pendingLinks == null) { 1159 pendingLinks = new java.util.ArrayList (); 1160 } 1161 pendingLinks.add(pl); 1162 1163 return link; 1164 } 1165 1166 public PDFLink makeLink(Rectangle rect, String page, String dest) { 1167 PDFLink link = new PDFLink(++this.objectcount, rect); 1168 this.objects.add(link); 1169 1170 PDFGoTo gt = new PDFGoTo(++this.objectcount, page); 1171 gt.setDestination(dest); 1172 addTrailerObject(gt); 1173 PDFInternalLink internalLink = new PDFInternalLink(gt.referencePDF()); 1174 link.setAction(internalLink); 1175 1176 return link; 1177 } 1178 1179 1183 private void prepareLocations() { 1184 while(location.size() < objectcount) 1185 location.add(locationPlaceholder); 1186 } 1187 1188 1193 public PDFStream makeStream() { 1194 1195 1200 PDFStream obj = new PDFStream(++this.objectcount); 1201 obj.addDefaultFilters(); 1202 if (this.encryption != null) { 1203 obj.addFilter(this.encryption.makeFilter(obj.number,obj.generation)); 1204 } 1205 1206 this.objects.add(obj); 1207 return obj; 1208 } 1209 1210 1211 1216 public PDFAnnotList makeAnnotList() { 1217 1218 1222 PDFAnnotList obj = new PDFAnnotList(++this.objectcount); 1223 this.objects.add(obj); 1224 return obj; 1225 } 1226 1227 1232 public PDFOutline getOutlineRoot() { 1233 if(outlineRoot != null) 1234 return outlineRoot; 1235 1236 outlineRoot = new PDFOutline(++this.objectcount, null, null); 1237 addTrailerObject(outlineRoot); 1238 root.setRootOutline(outlineRoot); 1239 return outlineRoot; 1240 } 1241 1242 1248 public PDFOutline makeOutline(PDFOutline parent, String label, 1249 String destination) { 1250 String goToRef = getGoToReference(destination); 1251 1252 PDFOutline obj = new PDFOutline(++this.objectcount, label, goToRef); 1253 1255 if (parent != null) { 1256 parent.addOutline(obj); 1257 } 1258 this.objects.add(obj); 1259 return obj; 1260 1261 } 1262 1263 1268 public PDFResources getResources() { 1269 return this.resources; 1270 } 1271 1272 1277 public void output(OutputStream stream) throws IOException { 1278 1279 prepareLocations(); 1280 1281 for (int i = 0; i < objects.size(); i++) { 1282 1283 PDFObject object = (PDFObject)objects.get(i); 1284 1285 1289 location.set(object.getNumber() - 1, 1290 new Integer (this.position)); 1291 1292 1296 this.position += object.output(stream); 1297 } 1298 1299 this.objects.clear(); 1300 } 1301 1302 1311 public void outputHeader(OutputStream stream) 1312 throws IOException { 1313 this.position=0; 1314 1315 byte[] pdf; 1316 try { 1317 pdf = ("%PDF-" + this.pdfVersion + "\n").getBytes(PDFDocument.ENCODING); 1318 } catch (UnsupportedEncodingException ue) { 1319 pdf = ("%PDF-" + this.pdfVersion + "\n").getBytes(); 1320 } 1321 stream.write(pdf); 1322 this.position += pdf.length; 1323 1324 byte[] bin = { 1326 (byte)'%', (byte)0xAA, (byte)0xAB, (byte)0xAC, (byte)0xAD, 1327 (byte)'\n' 1328 }; 1329 stream.write(bin); 1330 this.position += bin.length; 1331 1332 this.resources.setXObjects(xObjects); 1333 } 1334 1335 1340 public void outputTrailer(OutputStream stream) 1341 throws IOException { 1342 output(stream); 1343 for (int i = 0; i < trailerObjects.size(); i++) { 1344 PDFObject o = (PDFObject) trailerObjects.get(i); 1345 this.location.set(o.getNumber() - 1, new Integer (this.position)); 1346 this.position += o.output(stream); 1347 } 1348 1350 this.position += outputXref(stream); 1351 1352 String encryptEntry = ""; 1354 1355 if (this.encryption != null) { 1356 encryptEntry = 1357 "/Encrypt " + this.encryption.number + " " + this.encryption.generation + " R\n"+ 1358 "/ID[<"+this.encryption.getFileID(1)+"><"+this.encryption.getFileID(2)+">]\n"; 1359 } 1360 1361 1362 String pdf = 1363 "trailer\n" + 1364 "<<\n" + 1365 "/Size " + (this.objectcount + 1) + "\n" + 1366 "/Root " + this.root.number + " " + this.root.generation + " R\n" + 1367 "/Info " + this.info.number + " " + this.info.generation + " R\n" + 1368 encryptEntry + 1369 ">>\n" + 1370 "startxref\n" + 1371 this.xref + "\n" + 1372 "%%EOF\n"; 1373 1374 1375 byte[] trailer; 1376 try { 1377 trailer = pdf.getBytes(PDFDocument.ENCODING); 1378 } catch (UnsupportedEncodingException ue) { 1379 trailer = pdf.getBytes(); 1380 } 1381 stream.write(trailer); 1382 } 1383 1384 1390 private int outputXref(OutputStream stream) throws IOException { 1391 1392 1393 this.xref = this.position; 1394 1395 1396 StringBuffer pdf = new StringBuffer ("xref\n0 " 1397 + (this.objectcount + 1) 1398 + "\n0000000000 65535 f \n"); 1399 1400 for (int i = 0; i< this.location.size(); i++ ) { 1401 String x = this.location.get(i).toString(); 1402 1403 1404 String padding = "0000000000"; 1405 String loc = padding.substring(x.length()) + x; 1406 1407 1408 pdf = pdf.append(loc + " 00000 n \n"); 1409 } 1410 1411 1412 byte[] pdfBytes; 1413 try { 1414 pdfBytes = pdf.toString().getBytes(PDFDocument.ENCODING); 1415 } catch (UnsupportedEncodingException ue) { 1416 pdfBytes = pdf.toString().getBytes(); 1417 } 1418 stream.write(pdfBytes); 1419 return pdfBytes.length; 1420 } 1421 1422 public void setIDReferences(IDReferences idReferences) { 1423 this.idReferences = idReferences; 1424 } 1425 1426 1431 public void addDestination(String destinationName, String internalDest) { 1432 if (!idReferences.doesIDExist(internalDest)) { 1433 idReferences.addToUnvalidatedIdList(internalDest); 1434 } 1435 PDFDestination obj = new PDFDestination(idReferences, destinationName, internalDest); 1436 root.getDestinations().add(obj); 1437 } 1438 1439} 1440 | Popular Tags |