Beispiel #1
0
 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++;
     }
 }
Beispiel #2
0
        /// <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;
            }
        }
Beispiel #3
0
        private static void VerifyFlushedObjectsNum(PdfDocument pdfDoc, int total, int flushedExpected, int notReadExpected
                                                    )
        {
            int flushedActual = 0;
            int notReadActual = 0;

            for (int i = 0; i < pdfDoc.GetXref().Size(); ++i)
            {
                PdfIndirectReference indRef = pdfDoc.GetXref().Get(i);
                if (indRef.CheckState(PdfObject.FLUSHED))
                {
                    ++flushedActual;
                }
                else
                {
                    if (!indRef.IsFree() && indRef.refersTo == null)
                    {
                        ++notReadActual;
                    }
                }
            }
            if (pdfDoc.GetXref().Size() != total || flushedActual != flushedExpected || notReadActual != notReadExpected
                )
            {
                NUnit.Framework.Assert.Fail(MessageFormatUtil.Format("\nExpected total: {0}, flushed: {1}, not read: {2};"
                                                                     + "\nbut actual was: {3}, flushed: {4}, not read: {5}.", total, flushedExpected, notReadExpected, pdfDoc
                                                                     .GetXref().Size(), flushedActual, notReadActual));
            }
            NUnit.Framework.Assert.AreEqual(total, pdfDoc.GetXref().Size(), "wrong num of total objects");
            NUnit.Framework.Assert.AreEqual(flushedExpected, flushedActual, "wrong num of flushed objects");
            NUnit.Framework.Assert.AreEqual(notReadExpected, notReadActual, "wrong num of not read objects");
        }
Beispiel #4
0
 private void Write(PdfIndirectReference indirectReference)
 {
     if (document != null && !indirectReference.GetDocument().Equals(document))
     {
         throw new PdfException(PdfException.PdfIndirectObjectBelongsToOtherPdfDocument);
     }
     if (indirectReference.IsFree())
     {
         ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfOutputStream));
         logger.Error(iText.IO.LogMessageConstant.FLUSHED_OBJECT_CONTAINS_FREE_REFERENCE);
         Write(PdfNull.PDF_NULL);
     }
     else
     {
         if (indirectReference.refersTo == null && (indirectReference.CheckState(PdfObject.MODIFIED) || indirectReference
                                                    .GetReader() == null || !(indirectReference.GetOffset() > 0 || indirectReference.GetIndex() >= 0)))
         {
             ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfOutputStream));
             logger.Error(iText.IO.LogMessageConstant.FLUSHED_OBJECT_CONTAINS_REFERENCE_WHICH_NOT_REFER_TO_ANY_OBJECT);
             Write(PdfNull.PDF_NULL);
         }
         else
         {
             if (indirectReference.GetGenNumber() == 0)
             {
                 WriteInteger(indirectReference.GetObjNumber()).WriteBytes(endIndirectWithZeroGenNr);
             }
             else
             {
                 WriteInteger(indirectReference.GetObjNumber()).WriteSpace().WriteInteger(indirectReference.GetGenNumber())
                 .WriteBytes(endIndirect);
             }
         }
     }
 }
Beispiel #5
0
        /// <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;
            }
        }
Beispiel #6
0
        public virtual void SetLinkDestinationToPageAppendMode()
        {
            String      input  = sourceFolder + "100pages.pdf";
            String      output = destinationFolder + "setLinkDestinationToPageAppendMode.pdf";
            PdfDocument pdfDoc = new PdfDocument(new PdfReader(input), new PdfWriter(output), new StampingProperties()
                                                 .UseAppendMode());
            PdfPage page1 = pdfDoc.GetPage(1);
            PdfPage page2 = pdfDoc.GetPage(2);
            PdfIndirectReference page1IndRef = page1.GetPdfObject().GetIndirectReference();
            PdfIndirectReference page2IndRef = page2.GetPdfObject().GetIndirectReference();
            PdfDictionary        aDict       = ((PdfLinkAnnotation)page1.GetAnnotations()[0]).GetAction();

            new PdfAction(aDict).Put(PdfName.D, PdfExplicitDestination.CreateXYZ(page2, 300, 400, 1).GetPdfObject());
            PageFlushingHelper flushingHelper = new PageFlushingHelper(pdfDoc);

            flushingHelper.AppendModeFlush(2);
            flushingHelper.UnsafeFlushDeep(1);
            // annotation is flushed
            NUnit.Framework.Assert.IsTrue(aDict.IsFlushed());
            // page is not flushed
            NUnit.Framework.Assert.IsFalse(page1IndRef.CheckState(PdfObject.FLUSHED));
            // page is released
            NUnit.Framework.Assert.IsNull(page1IndRef.refersTo);
            // page is not flushed
            NUnit.Framework.Assert.IsFalse(page2IndRef.CheckState(PdfObject.FLUSHED));
            // page is released
            NUnit.Framework.Assert.IsNull(page2IndRef.refersTo);
            // exception is not thrown
            pdfDoc.Close();
        }
Beispiel #7
0
 protected internal virtual void FreeReference(PdfIndirectReference reference)
 {
     reference.SetOffset(0);
     reference.SetState(PdfObject.FREE);
     if (!reference.CheckState(PdfObject.FLUSHED))
     {
         if (reference.refersTo != null)
         {
             reference.refersTo.SetIndirectReference(null).SetState(PdfObject.MUST_BE_INDIRECT);
             reference.refersTo = null;
         }
         if (reference.GetGenNumber() < MAX_GENERATION)
         {
             freeReferences.Add(reference.GetObjNumber());
             xref[reference.GetObjNumber()] = null;
         }
     }
 }
Beispiel #8
0
        private IList <int> CreateSections(PdfDocument document, bool dropObjectsFromObjectStream)
        {
            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) || dropObjectsFromObjectStream &&
                                                                            reference.GetObjStreamNumber() != 0))
                {
                    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);
            }
            return(sections);
        }
Beispiel #9
0
        public virtual void ModifyAnnotationOnlyAppendMode()
        {
            String      input  = sourceFolder + "100pages.pdf";
            String      output = destinationFolder + "modifyAnnotOnly.pdf";
            PdfDocument pdfDoc = new PdfDocument(new PdfReader(input), new PdfWriter(output), new StampingProperties()
                                                 .UseAppendMode());
            PdfPage page = pdfDoc.GetPage(1);
            PdfIndirectReference pageIndRef = page.GetPdfObject().GetIndirectReference();
            PdfDictionary        annotObj   = page.GetAnnotations()[0].SetRectangle(new PdfArray(new Rectangle(0, 0, 300, 300))
                                                                                    ).SetPage(page).GetPdfObject();
            PageFlushingHelper flushingHelper = new PageFlushingHelper(pdfDoc);

            flushingHelper.AppendModeFlush(1);
            // annotation is flushed
            NUnit.Framework.Assert.IsTrue(annotObj.IsFlushed());
            // page is not flushed
            NUnit.Framework.Assert.IsFalse(pageIndRef.CheckState(PdfObject.FLUSHED));
            // page is released
            NUnit.Framework.Assert.IsNull(pageIndRef.refersTo);
            // exception is not thrown
            pdfDoc.Close();
        }
Beispiel #10
0
 private void MarkObjectToFlush(PdfObject pdfObject)
 {
     if (pdfObject != null)
     {
         PdfIndirectReference indirectReference = pdfObject.GetIndirectReference();
         if (indirectReference != null)
         {
             if (!indirectReference.CheckState(PdfObject.FLUSHED))
             {
                 indirectReference.SetState(PdfObject.MUST_BE_FLUSHED);
             }
         }
         else
         {
             if (pdfObject.GetObjectType() == PdfObject.INDIRECT_REFERENCE)
             {
                 if (!pdfObject.CheckState(PdfObject.FLUSHED))
                 {
                     pdfObject.SetState(PdfObject.MUST_BE_FLUSHED);
                 }
             }
             else
             {
                 if (pdfObject.GetObjectType() == PdfObject.ARRAY)
                 {
                     MarkArrayContentToFlush((PdfArray)pdfObject);
                 }
                 else
                 {
                     if (pdfObject.GetObjectType() == PdfObject.DICTIONARY)
                     {
                         MarkDictionaryContentToFlush((PdfDictionary)pdfObject);
                     }
                 }
             }
         }
     }
 }
Beispiel #11
0
 public virtual void Release()
 {
     // In case ForbidRelease flag is set, release will not be performed.
     if (IsReleaseForbidden())
     {
         ILog logger = LogManager.GetLogger(typeof(PdfObject));
         logger.Warn(iText.IO.LogMessageConstant.FORBID_RELEASE_IS_SET);
     }
     else
     {
         if (indirectReference != null && indirectReference.GetReader() != null && !indirectReference.CheckState(FLUSHED
                                                                                                                 ))
         {
             indirectReference.refersTo = null;
             indirectReference          = null;
             SetState(READ_ONLY);
         }
     }
 }
Beispiel #12
0
        /// <summary>Indicates is the object has been set as modified or not.</summary>
        /// <remarks>Indicates is the object has been set as modified or not. Useful for incremental updates (e.g. appendMode).
        ///     </remarks>
        /// <returns>true is object has been set as modified, otherwise false.</returns>
        public virtual bool IsModified()
        {
            PdfIndirectReference indirectReference = GetIndirectReference();

            return(indirectReference != null && indirectReference.CheckState(MODIFIED));
        }
Beispiel #13
0
        /// <summary>Indicates is the object has been flushed or not.</summary>
        /// <returns>true if object has been flushed, otherwise false.</returns>
        public virtual bool IsFlushed()
        {
            PdfIndirectReference indirectReference = GetIndirectReference();

            return(indirectReference != null && indirectReference.CheckState(FLUSHED));
        }
        private void FlushObjectRecursively(PdfObject obj, PageFlushingHelper.DeepFlushingContext context)
        {
            if (obj == null)
            {
                return;
            }
            bool avoidReleaseForIndirectObjInstance = false;

            if (obj.IsIndirectReference())
            {
                PdfIndirectReference indRef = (PdfIndirectReference)obj;
                if (indRef.refersTo == null || indRef.CheckState(PdfObject.FLUSHED))
                {
                    return;
                }
                obj = indRef.GetRefersTo();
            }
            else
            {
                if (obj.IsFlushed())
                {
                    return;
                }
                else
                {
                    if (release && obj.IsIndirect())
                    {
                        // We should avoid the case when object is going to be released but is stored in containing object
                        // not as indirect reference. This can happen when containing object is somehow modified.
                        // Generally containing objects should not contain released read-only object instance.
                        System.Diagnostics.Debug.Assert(obj.IsReleaseForbidden() || obj.GetIndirectReference() == null);
                        avoidReleaseForIndirectObjInstance = true;
                    }
                }
            }
            if (pdfDoc.IsDocumentFont(obj.GetIndirectReference()) || layersRefs.Contains(obj.GetIndirectReference()))
            {
                return;
            }
            if (obj.IsDictionary() || obj.IsStream())
            {
                if (!currNestedObjParents.Add(obj))
                {
                    return;
                }
                FlushDictRecursively((PdfDictionary)obj, context);
                currNestedObjParents.Remove(obj);
            }
            else
            {
                if (obj.IsArray())
                {
                    if (!currNestedObjParents.Add(obj))
                    {
                        return;
                    }
                    PdfArray array = (PdfArray)obj;
                    for (int i = 0; i < array.Size(); ++i)
                    {
                        FlushObjectRecursively(array.Get(i, false), context);
                    }
                    currNestedObjParents.Remove(obj);
                }
            }
            if (!avoidReleaseForIndirectObjInstance)
            {
                FlushOrRelease(obj);
            }
        }
Beispiel #15
0
        /// <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();
        }
Beispiel #16
0
        /// <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;
        }
        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");
        }