public virtual void PdfIndirectReferenceFlags() { PdfIndirectReference reference = new PdfIndirectReference(null, 1); reference.SetState(PdfObject.FREE); reference.SetState(PdfObject.READING); reference.SetState(PdfObject.MODIFIED); NUnit.Framework.Assert.AreEqual(true, reference.CheckState(PdfObject.FREE), "Free"); NUnit.Framework.Assert.AreEqual(true, reference.CheckState(PdfObject.READING), "Reading"); NUnit.Framework.Assert.AreEqual(true, reference.CheckState(PdfObject.MODIFIED), "Modified"); NUnit.Framework.Assert.AreEqual(true, reference.CheckState((byte)(PdfObject.FREE | PdfObject.MODIFIED | PdfObject .READING)), "Free|Reading|Modified"); reference.ClearState(PdfObject.FREE); NUnit.Framework.Assert.AreEqual(false, reference.CheckState(PdfObject.FREE), "Free"); NUnit.Framework.Assert.AreEqual(true, reference.CheckState(PdfObject.READING), "Reading"); NUnit.Framework.Assert.AreEqual(true, reference.CheckState(PdfObject.MODIFIED), "Modified"); NUnit.Framework.Assert.AreEqual(true, reference.CheckState((byte)(PdfObject.READING | PdfObject.MODIFIED)) , "Reading|Modified"); NUnit.Framework.Assert.AreEqual(false, reference.CheckState((byte)(PdfObject.FREE | PdfObject.READING | PdfObject .MODIFIED)), "Free|Reading|Modified"); reference.ClearState(PdfObject.READING); NUnit.Framework.Assert.AreEqual(false, reference.CheckState(PdfObject.FREE), "Free"); NUnit.Framework.Assert.AreEqual(false, reference.CheckState(PdfObject.READING), "Reading"); NUnit.Framework.Assert.AreEqual(true, reference.CheckState(PdfObject.MODIFIED), "Modified"); NUnit.Framework.Assert.AreEqual(false, reference.CheckState((byte)(PdfObject.FREE | PdfObject.READING)), "Free|Reading" ); reference.ClearState(PdfObject.MODIFIED); NUnit.Framework.Assert.AreEqual(false, reference.CheckState(PdfObject.FREE), "Free"); NUnit.Framework.Assert.AreEqual(false, reference.CheckState(PdfObject.READING), "Reading"); NUnit.Framework.Assert.AreEqual(false, reference.CheckState(PdfObject.MODIFIED), "Modified"); NUnit.Framework.Assert.AreEqual(true, !reference.IsFree(), "Is InUse"); reference.SetState(PdfObject.FREE); NUnit.Framework.Assert.AreEqual(false, !reference.IsFree(), "Not IsInUse"); }
/// <summary>Flushes all modified objects which have not been flushed yet.</summary> /// <remarks>Flushes all modified objects which have not been flushed yet. Used in case incremental updates.</remarks> /// <param name="forbiddenToFlush"> /// a /// <see cref="Java.Util.Set{E}"/> /// of /// <see cref="PdfIndirectReference">references</see> /// that are forbidden to be flushed automatically. /// </param> protected internal virtual void FlushModifiedWaitingObjects(ICollection <PdfIndirectReference> forbiddenToFlush ) { PdfXrefTable xref = document.GetXref(); for (int i = 1; i < xref.Size(); i++) { PdfIndirectReference indirectReference = xref.Get(i); if (null != indirectReference && !indirectReference.IsFree() && !forbiddenToFlush.Contains(indirectReference )) { bool isModified = indirectReference.CheckState(PdfObject.MODIFIED); if (isModified) { PdfObject obj = indirectReference.GetRefersTo(false); if (obj != null) { if (!obj.Equals(objectStream)) { obj.Flush(); } } } } } if (objectStream != null && objectStream.GetSize() > 0) { objectStream.Flush(); objectStream = null; } }
/// <summary>Flushes all objects which have not been flushed yet.</summary> /// <param name="forbiddenToFlush"> /// a /// <see cref="Java.Util.Set{E}"/> /// of /// <see cref="PdfIndirectReference">references</see> /// that are forbidden to be flushed automatically. /// </param> protected internal virtual void FlushWaitingObjects(ICollection <PdfIndirectReference> forbiddenToFlush) { PdfXrefTable xref = document.GetXref(); bool needFlush = true; while (needFlush) { needFlush = false; for (int i = 1; i < xref.Size(); i++) { PdfIndirectReference indirectReference = xref.Get(i); if (indirectReference != null && !indirectReference.IsFree() && indirectReference.CheckState(PdfObject.MUST_BE_FLUSHED ) && !forbiddenToFlush.Contains(indirectReference)) { PdfObject obj = indirectReference.GetRefersTo(false); if (obj != null) { obj.Flush(); needFlush = true; } } } } if (objectStream != null && objectStream.GetSize() > 0) { objectStream.Flush(); objectStream = null; } }
protected internal virtual void FreeReference(PdfIndirectReference reference) { if (reference.IsFree()) { return; } if (reference.CheckState(PdfObject.MUST_BE_FLUSHED)) { ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfXrefTable)); logger.Error(iText.IO.LogMessageConstant.INDIRECT_REFERENCE_USED_IN_FLUSHED_OBJECT_MADE_FREE); return; } if (reference.CheckState(PdfObject.FLUSHED)) { ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfXrefTable)); logger.Error(iText.IO.LogMessageConstant.ALREADY_FLUSHED_INDIRECT_OBJECT_MADE_FREE); return; } reference.SetState(PdfObject.FREE).SetState(PdfObject.MODIFIED); AppendNewRefToFreeList(reference); if (reference.GetGenNumber() < MAX_GENERATION) { reference.genNr++; } }
public virtual void TestCreateAndUpdateTwiceXMP() { String created = destinationFolder + "testCreateAndUpdateTwiceXMP_create.pdf"; String updated = destinationFolder + "testCreateAndUpdateTwiceXMP_update.pdf"; String updatedAgain = destinationFolder + "testCreateAndUpdateTwiceXMP_updatedAgain.pdf"; PdfDocument pdfDocument = new PdfDocument(new PdfWriter(created)); pdfDocument.AddNewPage(); pdfDocument.GetXmpMetadata(true); // create XMP metadata pdfDocument.Close(); pdfDocument = new PdfDocument(new PdfReader(created), new PdfWriter(updated)); PdfDictionary catalog = pdfDocument.GetCatalog().GetPdfObject(); ((PdfIndirectReference)catalog.Remove(PdfName.Metadata)).SetFree(); pdfDocument.Close(); pdfDocument = new PdfDocument(new PdfReader(updated), new PdfWriter(updatedAgain)); catalog = pdfDocument.GetCatalog().GetPdfObject(); ((PdfIndirectReference)catalog.Remove(PdfName.Metadata)).SetFree(); PdfXrefTable xref = pdfDocument.GetXref(); PdfIndirectReference ref0 = xref.Get(0); PdfIndirectReference freeRef1 = xref.Get(6); PdfIndirectReference freeRef2 = xref.Get(7); pdfDocument.Close(); /* * Current xref structure: * xref * 0 9 * 0000000006 65535 f % this is object 0; 6 refers to free object 6 * 0000000203 00000 n * 0000000510 00000 n * 0000000263 00000 n * 0000000088 00000 n * 0000000015 00000 n * 0000000007 00001 f % this is object 6; 7 refers to free object 7; note generation number * 0000000000 00001 f % this is object 7; 0 refers to free object 0; note generation number * 0000000561 00000 n */ NUnit.Framework.Assert.IsTrue(freeRef1.IsFree()); NUnit.Framework.Assert.AreEqual(ref0.offsetOrIndex, freeRef1.objNr); NUnit.Framework.Assert.AreEqual(1, freeRef1.genNr); NUnit.Framework.Assert.IsTrue(freeRef2.IsFree()); NUnit.Framework.Assert.AreEqual(freeRef1.offsetOrIndex, freeRef2.objNr); NUnit.Framework.Assert.AreEqual(1, freeRef2.genNr); pdfDocument.Close(); }
/// <summary>Removes indirect reference from free references linked list.</summary> /// <remarks> /// Removes indirect reference from free references linked list. /// It does not removes it from xref table and affects only the linked list formed by offset values of free references. /// </remarks> /// <param name="freeRefObjNr"> /// object number of the reference to be removed. /// Removes the free reference with the least object number if this parameter is less than zero: /// this could be used for finding the next free reference for reusing. /// </param> /// <returns> /// /// <see cref="PdfIndirectReference"/> /// instance of the removed free reference corresponding to the object number /// passed as parameter. /// <see langword="null"/> /// - if given object number doesn't correspond to free reference or equals to zero. /// </returns> private PdfIndirectReference RemoveFreeRefFromList(int freeRefObjNr) { if (freeReferencesLinkedList.IsEmpty <int, PdfIndirectReference>()) { System.Diagnostics.Debug.Assert(false); // free references list is not initialized yet return(null); } if (freeRefObjNr == 0) { return(null); } if (freeRefObjNr < 0) { int?leastFreeRefObjNum = null; foreach (KeyValuePair <int, PdfIndirectReference> entry in freeReferencesLinkedList) { if (entry.Key <= 0 || xref[entry.Key].GetGenNumber() >= MAX_GENERATION) { continue; } leastFreeRefObjNum = entry.Key; break; } if (leastFreeRefObjNum == null) { return(null); } freeRefObjNr = (int)leastFreeRefObjNum; } PdfIndirectReference freeRef = xref[freeRefObjNr]; if (!freeRef.IsFree()) { return(null); } PdfIndirectReference prevFreeRef = freeReferencesLinkedList.JRemove(freeRef.GetObjNumber()); if (prevFreeRef != null) { freeReferencesLinkedList.Put((int)freeRef.GetOffset(), prevFreeRef); ((PdfIndirectReference)prevFreeRef.SetState(PdfObject.MODIFIED)).SetOffset(freeRef.GetOffset()); } return(freeRef); }
/// <summary>Writes cross reference table and trailer to PDF.</summary> /// <exception cref="System.IO.IOException"/> /// <exception cref="iText.Kernel.PdfException"/> protected internal virtual void WriteXrefTableAndTrailer(PdfDocument document, PdfObject fileId, PdfObject crypto) { PdfWriter writer = document.GetWriter(); if (document.IsAppendMode()) { // Increment generation number for all freed references. foreach (int?objNr in freeReferences) { xref[(int)objNr].genNr++; } } else { foreach (int?objNr in freeReferences) { xref[(int)objNr] = null; } } freeReferences.Clear(); for (int i = count; i > 0; --i) { PdfIndirectReference lastRef = xref[i]; if (lastRef == null || (lastRef.IsFree() && lastRef.GetGenNumber() == 0) || (!lastRef.CheckState(PdfObject .FLUSHED) && !(document.properties.appendMode && !lastRef.CheckState(PdfObject.MODIFIED)))) { --count; } else { break; } } IList <int> sections = new List <int>(); int first = 0; int len = 1; if (document.IsAppendMode()) { first = 1; len = 0; } for (int i_1 = 1; i_1 < Size(); i_1++) { PdfIndirectReference reference = xref[i_1]; if (reference != null) { if ((document.properties.appendMode && !reference.CheckState(PdfObject.MODIFIED)) || (reference.IsFree() && reference.GetGenNumber() == 0) || (!reference.CheckState(PdfObject.FLUSHED))) { reference = null; } } if (reference == null) { if (len > 0) { sections.Add(first); sections.Add(len); } len = 0; } else { if (len > 0) { len++; } else { first = i_1; len = 1; } } } if (len > 0) { sections.Add(first); sections.Add(len); } if (document.properties.appendMode && sections.Count == 0) { // no modifications. xref = null; return; } long startxref = writer.GetCurrentPos(); if (writer.IsFullCompression()) { PdfStream xrefStream = ((PdfStream) new PdfStream().MakeIndirect(document)); xrefStream.MakeIndirect(document); xrefStream.Put(PdfName.Type, PdfName.XRef); xrefStream.Put(PdfName.ID, fileId); if (crypto != null) { xrefStream.Put(PdfName.Encrypt, crypto); } xrefStream.Put(PdfName.Size, new PdfNumber(this.Size())); List <PdfObject> tmpArray = new List <PdfObject>(3); tmpArray.Add(new PdfNumber(1)); tmpArray.Add(new PdfNumber(4)); tmpArray.Add(new PdfNumber(2)); xrefStream.Put(PdfName.W, new PdfArray(tmpArray)); xrefStream.Put(PdfName.Info, document.GetDocumentInfo().GetPdfObject()); xrefStream.Put(PdfName.Root, document.GetCatalog().GetPdfObject()); PdfArray index = new PdfArray(); foreach (int?section in sections) { index.Add(new PdfNumber((int)section)); } if (document.properties.appendMode) { PdfNumber lastXref = new PdfNumber(document.reader.GetLastXref()); xrefStream.Put(PdfName.Prev, lastXref); } xrefStream.Put(PdfName.Index, index); iText.Kernel.Pdf.PdfXrefTable xrefTable = document.GetXref(); for (int k = 0; k < sections.Count; k += 2) { first = (int)sections[k]; len = (int)sections[k + 1]; for (int i_2 = first; i_2 < first + len; i_2++) { PdfIndirectReference reference = xrefTable.Get(i_2); if (reference == null) { continue; } if (reference.IsFree()) { xrefStream.GetOutputStream().Write(0); //NOTE The object number of the next free object should be at this position due to spec. xrefStream.GetOutputStream().Write(IntToBytes(0)); xrefStream.GetOutputStream().Write(ShortToBytes(reference.GetGenNumber())); } else { if (reference.GetObjStreamNumber() == 0) { xrefStream.GetOutputStream().Write(1); System.Diagnostics.Debug.Assert(reference.GetOffset() < int.MaxValue); xrefStream.GetOutputStream().Write(IntToBytes((int)reference.GetOffset())); xrefStream.GetOutputStream().Write(ShortToBytes(reference.GetGenNumber())); } else { xrefStream.GetOutputStream().Write(2); xrefStream.GetOutputStream().Write(IntToBytes(reference.GetObjStreamNumber())); xrefStream.GetOutputStream().Write(ShortToBytes(reference.GetIndex())); } } } } xrefStream.Flush(); } else { writer.WriteString("xref\n"); iText.Kernel.Pdf.PdfXrefTable xrefTable = document.GetXref(); for (int k = 0; k < sections.Count; k += 2) { first = (int)sections[k]; len = (int)sections[k + 1]; writer.WriteInteger(first).WriteSpace().WriteInteger(len).WriteByte((byte)'\n'); for (int i_2 = first; i_2 < first + len; i_2++) { PdfIndirectReference reference = xrefTable.Get(i_2); writer.WriteString(DecimalFormatUtil.FormatNumber(reference.GetOffset(), objectOffsetFormatter)).WriteSpace ().WriteString(DecimalFormatUtil.FormatNumber(reference.GetGenNumber(), objectGenerationFormatter)).WriteSpace (); if (reference.IsFree()) { writer.WriteBytes(freeXRefEntry); } else { writer.WriteBytes(inUseXRefEntry); } } } PdfDictionary trailer = document.GetTrailer(); // Remove all unused keys in case stamp mode in case original file has full compression, but destination file has not. trailer.Remove(PdfName.W); trailer.Remove(PdfName.Index); trailer.Remove(PdfName.Type); trailer.Remove(PdfName.Length); trailer.Put(PdfName.Size, new PdfNumber(this.Size())); trailer.Put(PdfName.ID, fileId); if (crypto != null) { trailer.Put(PdfName.Encrypt, crypto); } writer.WriteString("trailer\n"); if (document.properties.appendMode) { PdfNumber lastXref = new PdfNumber(document.reader.GetLastXref()); trailer.Put(PdfName.Prev, lastXref); } writer.Write(document.GetTrailer()); writer.Write('\n'); } WriteKeyInfo(writer); writer.WriteString("startxref\n").WriteLong(startxref).WriteString("\n%%EOF\n"); xref = null; }
/// <summary>Writes cross reference table and trailer to PDF.</summary> protected internal virtual void WriteXrefTableAndTrailer(PdfDocument document, PdfObject fileId, PdfObject crypto) { PdfWriter writer = document.GetWriter(); if (!document.properties.appendMode) { for (int i = count; i > 0; --i) { PdfIndirectReference lastRef = xref[i]; if (lastRef == null || lastRef.IsFree()) { RemoveFreeRefFromList(i); --count; } else { break; } } } IList <int> sections = CreateSections(document, false); if (document.properties.appendMode && sections.Count == 0) { // no modifications. xref = null; return; } long startxref = writer.GetCurrentPos(); long xRefStmPos = -1; if (writer.IsFullCompression()) { PdfStream xrefStream = (PdfStream) new PdfStream().MakeIndirect(document); xrefStream.MakeIndirect(document); xrefStream.Put(PdfName.Type, PdfName.XRef); xrefStream.Put(PdfName.ID, fileId); if (crypto != null) { xrefStream.Put(PdfName.Encrypt, crypto); } xrefStream.Put(PdfName.Size, new PdfNumber(this.Size())); int offsetSize = GetOffsetSize(Math.Max(startxref, Size())); xrefStream.Put(PdfName.W, new PdfArray(JavaUtil.ArraysAsList((PdfObject) new PdfNumber(1), new PdfNumber(offsetSize ), new PdfNumber(2)))); xrefStream.Put(PdfName.Info, document.GetDocumentInfo().GetPdfObject()); xrefStream.Put(PdfName.Root, document.GetCatalog().GetPdfObject()); PdfArray index = new PdfArray(); foreach (int?section in sections) { index.Add(new PdfNumber((int)section)); } if (document.properties.appendMode && !document.reader.hybridXref) { // "not meaningful in hybrid-reference files" PdfNumber lastXref = new PdfNumber(document.reader.GetLastXref()); xrefStream.Put(PdfName.Prev, lastXref); } xrefStream.Put(PdfName.Index, index); iText.Kernel.Pdf.PdfXrefTable xrefTable = document.GetXref(); for (int k = 0; k < sections.Count; k += 2) { int first = (int)sections[k]; int len = (int)sections[k + 1]; for (int i = first; i < first + len; i++) { PdfIndirectReference reference = xrefTable.Get(i); if (reference.IsFree()) { xrefStream.GetOutputStream().Write(0); xrefStream.GetOutputStream().Write(reference.GetOffset(), offsetSize); xrefStream.GetOutputStream().Write(reference.GetGenNumber(), 2); } else { if (reference.GetObjStreamNumber() == 0) { xrefStream.GetOutputStream().Write(1); xrefStream.GetOutputStream().Write(reference.GetOffset(), offsetSize); xrefStream.GetOutputStream().Write(reference.GetGenNumber(), 2); } else { xrefStream.GetOutputStream().Write(2); xrefStream.GetOutputStream().Write(reference.GetObjStreamNumber(), offsetSize); xrefStream.GetOutputStream().Write(reference.GetIndex(), 2); } } } } xrefStream.Flush(); xRefStmPos = startxref; } // For documents with hybrid cross-reference table, i.e. containing xref streams as well as regular xref sections, // we write additional regular xref section at the end of the document because the /Prev reference from // xref stream to a regular xref section doesn't seem to be valid bool needsRegularXref = !writer.IsFullCompression() || document.properties.appendMode && document.reader.hybridXref; if (needsRegularXref) { startxref = writer.GetCurrentPos(); writer.WriteString("xref\n"); iText.Kernel.Pdf.PdfXrefTable xrefTable = document.GetXref(); if (xRefStmPos != -1) { // Get rid of all objects from object stream. This is done for hybrid documents sections = CreateSections(document, true); } for (int k = 0; k < sections.Count; k += 2) { int first = (int)sections[k]; int len = (int)sections[k + 1]; writer.WriteInteger(first).WriteSpace().WriteInteger(len).WriteByte((byte)'\n'); for (int i = first; i < first + len; i++) { PdfIndirectReference reference = xrefTable.Get(i); StringBuilder off = new StringBuilder("0000000000").Append(reference.GetOffset()); StringBuilder gen = new StringBuilder("00000").Append(reference.GetGenNumber()); writer.WriteString(off.JSubstring(off.Length - 10, off.Length)).WriteSpace().WriteString(gen.JSubstring(gen .Length - 5, gen.Length)).WriteSpace(); if (reference.IsFree()) { writer.WriteBytes(freeXRefEntry); } else { writer.WriteBytes(inUseXRefEntry); } } } PdfDictionary trailer = document.GetTrailer(); // Remove all unused keys in case stamp mode in case original file has full compression, but destination file has not. trailer.Remove(PdfName.W); trailer.Remove(PdfName.Index); trailer.Remove(PdfName.Type); trailer.Remove(PdfName.Length); trailer.Put(PdfName.Size, new PdfNumber(this.Size())); trailer.Put(PdfName.ID, fileId); if (xRefStmPos != -1) { trailer.Put(PdfName.XRefStm, new PdfNumber(xRefStmPos)); } if (crypto != null) { trailer.Put(PdfName.Encrypt, crypto); } writer.WriteString("trailer\n"); if (document.properties.appendMode) { PdfNumber lastXref = new PdfNumber(document.reader.GetLastXref()); trailer.Put(PdfName.Prev, lastXref); } writer.Write(document.GetTrailer()); writer.Write('\n'); } WriteKeyInfo(document); writer.WriteString("startxref\n").WriteLong(startxref).WriteString("\n%%EOF\n"); xref = null; freeReferencesLinkedList.Clear(); }
internal virtual void InitFreeReferencesList(PdfDocument pdfDocument) { freeReferencesLinkedList.Clear(); // ensure zero object is free xref[0].SetState(PdfObject.FREE); SortedSet <int> freeReferences = new SortedSet <int>(); for (int i = 1; i < Size(); ++i) { PdfIndirectReference @ref = xref[i]; if (@ref == null || @ref.IsFree()) { freeReferences.Add(i); } } PdfIndirectReference prevFreeRef = xref[0]; while (!freeReferences.IsEmpty <int>()) { int currFreeRefObjNr = -1; if (prevFreeRef.GetOffset() <= int.MaxValue) { currFreeRefObjNr = (int)prevFreeRef.GetOffset(); } if (!freeReferences.Contains(currFreeRefObjNr) || xref[currFreeRefObjNr] == null) { break; } freeReferencesLinkedList.Put(currFreeRefObjNr, prevFreeRef); prevFreeRef = xref[currFreeRefObjNr]; freeReferences.Remove(currFreeRefObjNr); } while (!freeReferences.IsEmpty <int>()) { int next = freeReferences.PollFirst(); if (xref[next] == null) { if (pdfDocument.properties.appendMode) { continue; } xref[next] = (PdfIndirectReference) new PdfIndirectReference(pdfDocument, next, 0).SetState(PdfObject.FREE) .SetState(PdfObject.MODIFIED); } else { if (xref[next].GetGenNumber() == MAX_GENERATION && xref[next].GetOffset() == 0) { continue; } } if (prevFreeRef.GetOffset() != (long)next) { ((PdfIndirectReference)prevFreeRef.SetState(PdfObject.MODIFIED)).SetOffset(next); } freeReferencesLinkedList.Put(next, prevFreeRef); prevFreeRef = xref[next]; } if (prevFreeRef.GetOffset() != 0) { ((PdfIndirectReference)prevFreeRef.SetState(PdfObject.MODIFIED)).SetOffset(0); } freeReferencesLinkedList.Put(0, prevFreeRef); }
/// <summary>Writes cross reference table and trailer to PDF.</summary> /// <exception cref="System.IO.IOException"/> protected internal virtual void WriteXrefTableAndTrailer(PdfDocument document, PdfObject fileId, PdfObject crypto) { PdfWriter writer = document.GetWriter(); if (!document.properties.appendMode) { for (int i = count; i > 0; --i) { PdfIndirectReference lastRef = xref[i]; if (lastRef == null || lastRef.IsFree()) { RemoveFreeRefFromList(i); --count; } else { break; } } } IList <int> sections = new List <int>(); int first = 0; int len = 0; for (int i = 0; i < Size(); i++) { PdfIndirectReference reference = xref[i]; if (document.properties.appendMode && reference != null && !reference.CheckState(PdfObject.MODIFIED)) { reference = null; } if (reference == null) { if (len > 0) { sections.Add(first); sections.Add(len); } len = 0; } else { if (len > 0) { len++; } else { first = i; len = 1; } } } if (len > 0) { sections.Add(first); sections.Add(len); } if (document.properties.appendMode && sections.Count == 0) { // no modifications. xref = null; return; } long startxref = writer.GetCurrentPos(); if (writer.IsFullCompression()) { PdfStream xrefStream = (PdfStream) new PdfStream().MakeIndirect(document); xrefStream.MakeIndirect(document); xrefStream.Put(PdfName.Type, PdfName.XRef); xrefStream.Put(PdfName.ID, fileId); if (crypto != null) { xrefStream.Put(PdfName.Encrypt, crypto); } xrefStream.Put(PdfName.Size, new PdfNumber(this.Size())); List <PdfObject> tmpArray = new List <PdfObject>(3); tmpArray.Add(new PdfNumber(1)); tmpArray.Add(new PdfNumber(4)); tmpArray.Add(new PdfNumber(2)); xrefStream.Put(PdfName.W, new PdfArray(tmpArray)); xrefStream.Put(PdfName.Info, document.GetDocumentInfo().GetPdfObject()); xrefStream.Put(PdfName.Root, document.GetCatalog().GetPdfObject()); PdfArray index = new PdfArray(); foreach (int?section in sections) { index.Add(new PdfNumber((int)section)); } if (document.properties.appendMode) { PdfNumber lastXref = new PdfNumber(document.reader.GetLastXref()); xrefStream.Put(PdfName.Prev, lastXref); } xrefStream.Put(PdfName.Index, index); iText.Kernel.Pdf.PdfXrefTable xrefTable = document.GetXref(); for (int k = 0; k < sections.Count; k += 2) { first = (int)sections[k]; len = (int)sections[k + 1]; for (int i = first; i < first + len; i++) { PdfIndirectReference reference = xrefTable.Get(i); if (reference.IsFree()) { xrefStream.GetOutputStream().Write(0); System.Diagnostics.Debug.Assert(reference.GetOffset() < int.MaxValue); xrefStream.GetOutputStream().Write(IntToBytes((int)reference.GetOffset())); xrefStream.GetOutputStream().Write(ShortToBytes(reference.GetGenNumber())); } else { if (reference.GetObjStreamNumber() == 0) { xrefStream.GetOutputStream().Write(1); System.Diagnostics.Debug.Assert(reference.GetOffset() < int.MaxValue); xrefStream.GetOutputStream().Write(IntToBytes((int)reference.GetOffset())); xrefStream.GetOutputStream().Write(ShortToBytes(reference.GetGenNumber())); } else { xrefStream.GetOutputStream().Write(2); xrefStream.GetOutputStream().Write(IntToBytes(reference.GetObjStreamNumber())); xrefStream.GetOutputStream().Write(ShortToBytes(reference.GetIndex())); } } } } xrefStream.Flush(); } else { writer.WriteString("xref\n"); iText.Kernel.Pdf.PdfXrefTable xrefTable = document.GetXref(); for (int k = 0; k < sections.Count; k += 2) { first = (int)sections[k]; len = (int)sections[k + 1]; writer.WriteInteger(first).WriteSpace().WriteInteger(len).WriteByte((byte)'\n'); for (int i = first; i < first + len; i++) { PdfIndirectReference reference = xrefTable.Get(i); StringBuilder off = new StringBuilder("0000000000").Append(reference.GetOffset()); StringBuilder gen = new StringBuilder("00000").Append(reference.GetGenNumber()); writer.WriteString(off.JSubstring(off.Length - 10, off.Length)).WriteSpace().WriteString(gen.JSubstring(gen .Length - 5, gen.Length)).WriteSpace(); if (reference.IsFree()) { writer.WriteBytes(freeXRefEntry); } else { writer.WriteBytes(inUseXRefEntry); } } } PdfDictionary trailer = document.GetTrailer(); // Remove all unused keys in case stamp mode in case original file has full compression, but destination file has not. trailer.Remove(PdfName.W); trailer.Remove(PdfName.Index); trailer.Remove(PdfName.Type); trailer.Remove(PdfName.Length); trailer.Put(PdfName.Size, new PdfNumber(this.Size())); trailer.Put(PdfName.ID, fileId); if (crypto != null) { trailer.Put(PdfName.Encrypt, crypto); } writer.WriteString("trailer\n"); if (document.properties.appendMode) { PdfNumber lastXref = new PdfNumber(document.reader.GetLastXref()); trailer.Put(PdfName.Prev, lastXref); } writer.Write(document.GetTrailer()); writer.Write('\n'); } WriteKeyInfo(document); writer.WriteString("startxref\n").WriteLong(startxref).WriteString("\n%%EOF\n"); xref = null; freeReferencesLinkedList.Clear(); }