You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CrossReferenceStream.java 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.pdf.xref;
  19. import java.io.ByteArrayOutputStream;
  20. import java.io.DataOutputStream;
  21. import java.io.IOException;
  22. import java.io.OutputStream;
  23. import java.util.ArrayList;
  24. import java.util.List;
  25. import org.apache.fop.pdf.PDFArray;
  26. import org.apache.fop.pdf.PDFDictionary;
  27. import org.apache.fop.pdf.PDFDocument;
  28. import org.apache.fop.pdf.PDFFilterList;
  29. import org.apache.fop.pdf.PDFName;
  30. import org.apache.fop.pdf.PDFStream;
  31. /**
  32. * A cross-reference stream, as described in Section 3.4.7 of the PDF 1.5 Reference.
  33. */
  34. public class CrossReferenceStream extends CrossReferenceObject {
  35. private static final PDFName XREF = new PDFName("XRef");
  36. private final PDFDocument document;
  37. private final int objectNumber;
  38. private final List<ObjectReference> objectReferences;
  39. public CrossReferenceStream(PDFDocument document,
  40. int objectNumber,
  41. TrailerDictionary trailerDictionary,
  42. long startxref,
  43. List<Long> uncompressedObjectReferences,
  44. List<CompressedObjectReference> compressedObjectReferences) {
  45. super(trailerDictionary, startxref);
  46. this.document = document;
  47. this.objectNumber = objectNumber;
  48. this.objectReferences = new ArrayList<ObjectReference>(uncompressedObjectReferences.size());
  49. for (Long offset : uncompressedObjectReferences) {
  50. objectReferences.add(offset == null ? null : new UncompressedObjectReference(offset));
  51. }
  52. for (CompressedObjectReference ref : compressedObjectReferences) {
  53. this.objectReferences.set(ref.getObjectNumber() - 1, ref);
  54. }
  55. }
  56. /** {@inheritDoc} */
  57. public void output(OutputStream stream) throws IOException {
  58. populateDictionary();
  59. PDFStream helperStream = new PDFStream(trailerDictionary.getDictionary(), false) {
  60. @Override
  61. protected void setupFilterList() {
  62. PDFFilterList filterList = getFilterList();
  63. assert !filterList.isInitialized();
  64. filterList.addDefaultFilters(document.getFilterMap(), getDefaultFilterName());
  65. }
  66. };
  67. helperStream.setObjectNumber(objectNumber);
  68. helperStream.setDocument(document);
  69. ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
  70. DataOutputStream data = new DataOutputStream(byteArray);
  71. addFreeEntryForObject0(data);
  72. for (ObjectReference objectReference : objectReferences) {
  73. assert objectReference != null;
  74. objectReference.output(data);
  75. }
  76. new UncompressedObjectReference(startxref).output(data);
  77. data.close();
  78. helperStream.setData(byteArray.toByteArray());
  79. PDFDocument.outputIndirectObject(helperStream, stream);
  80. }
  81. private void populateDictionary() throws IOException {
  82. int objectCount = objectReferences.size() + 1;
  83. PDFDictionary dictionary = trailerDictionary.getDictionary();
  84. dictionary.put("/Type", XREF);
  85. dictionary.put("/Size", objectCount + 1);
  86. dictionary.put("/W", new PDFArray(1, 8, 2));
  87. }
  88. private void addFreeEntryForObject0(DataOutputStream data) throws IOException {
  89. data.write(new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, (byte) 0xff, (byte) 0xff});
  90. }
  91. }