private void FlushIfModified(PdfObject o)
 {
     if (o != null && !(o is PdfIndirectReference))
     {
         MakeIndirectIfNeeded(o);
         o = o.GetIndirectReference();
     }
     if (o != null && o.CheckState(PdfObject.MODIFIED) && !o.CheckState(PdfObject.FLUSHED))
     {
         ((PdfIndirectReference)o).GetRefersTo().Flush();
     }
 }
 private void MakeIndirectIfNeeded(PdfObject o)
 {
     if (o.CheckState(PdfObject.MUST_BE_INDIRECT))
     {
         o.MakeIndirect(pdfDoc);
     }
 }
Beispiel #3
0
 private void Write(PdfDictionary pdfDictionary)
 {
     WriteBytes(openDict);
     foreach (PdfName key in pdfDictionary.KeySet())
     {
         bool isAlreadyWriteSpace = false;
         Write(key);
         PdfObject value = pdfDictionary.Get(key, false);
         if (value == null)
         {
             ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Pdf.PdfOutputStream));
             logger.Warn(MessageFormatUtil.Format(iText.IO.LogMessageConstant.INVALID_KEY_VALUE_KEY_0_HAS_NULL_VALUE, key
                                                  ));
             value = PdfNull.PDF_NULL;
         }
         if ((value.GetObjectType() == PdfObject.NUMBER || value.GetObjectType() == PdfObject.LITERAL || value.GetObjectType
                  () == PdfObject.BOOLEAN || value.GetObjectType() == PdfObject.NULL || value.GetObjectType() == PdfObject
              .INDIRECT_REFERENCE || value.CheckState(PdfObject.MUST_BE_INDIRECT)))
         {
             isAlreadyWriteSpace = true;
             WriteSpace();
         }
         PdfIndirectReference indirectReference;
         if ((indirectReference = value.GetIndirectReference()) != null)
         {
             if (!isAlreadyWriteSpace)
             {
                 WriteSpace();
             }
             Write(indirectReference);
         }
         else
         {
             Write(value);
         }
     }
     WriteBytes(closeDict);
 }
Beispiel #4
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);
                     }
                 }
             }
         }
     }
 }
        /// <summary>
        /// Flushes to the output stream modified objects that can belong only to the given page, which makes this method
        /// "safe" compared to the
        /// <see cref="UnsafeFlushDeep(int)"/>
        /// . Flushed object frees the memory, but it's impossible to
        /// modify such objects or read data from them. This method releases all other page structure objects that are not
        /// modified.
        /// <p>
        /// This method is mainly designed for the append mode. It is similar to the
        /// <see cref="PdfPage.Flush()"/>
        /// , but it
        /// additionally releases all page objects that were not flushed. This method is ideal for small amendments of pages,
        /// but it makes more sense to use
        /// <see cref="PdfPage.Flush()"/>
        /// for newly created or heavily modified pages. <br />
        /// This method will throw an exception for documents opened in reading mode (see
        /// <see cref="PageFlushingHelper"/>
        /// for more details on modes). It is also not advised to be used in stamping mode: even though it will indeed
        /// release the objects and free the memory, the released objects will definitely be re-read again on document
        /// closing, which would affect performance.
        /// </p>
        /// <p>
        /// When using this method in append mode (or in stamping mode), be careful not to try to modify the object instances
        /// obtained before this method call! See
        /// <see cref="PageFlushingHelper"/>
        /// for details on released and flushed objects state.
        /// </p>
        /// <p>
        /// This method shall be used only when it's known that the page and its inner structures processing is finished.
        /// This includes reading data from pages, page modification and page handling via addons/utilities.
        /// </p>
        /// </summary>
        /// <param name="pageNum">the page number which low level objects structure is to be flushed or released from memory.
        ///     </param>
        public virtual void AppendModeFlush(int pageNum)
        {
            if (pdfDoc.GetWriter() == null)
            {
                throw new ArgumentException(PdfException.FlushingHelperFLushingModeIsNotForDocReadingMode);
            }
            PdfPage page = pdfDoc.GetPage(pageNum);

            if (page.IsFlushed())
            {
                return;
            }
            page.GetDocument().DispatchEvent(new PdfDocumentEvent(PdfDocumentEvent.END_PAGE, page));
            bool pageWasModified = page.GetPdfObject().IsModified();

            page.SetModified();
            release         = true;
            pageWasModified = FlushPage(pageNum) || pageWasModified;
            PdfArray annots = page.GetPdfObject().GetAsArray(PdfName.Annots);

            if (annots != null && !annots.IsFlushed())
            {
                ArrayFlushIfModified(annots);
            }
            PdfObject thumb = page.GetPdfObject().Get(PdfName.Thumb, false);

            FlushIfModified(thumb);
            PdfObject contents = page.GetPdfObject().Get(PdfName.Contents, false);

            if (contents is PdfIndirectReference)
            {
                if (contents.CheckState(PdfObject.MODIFIED) && !contents.CheckState(PdfObject.FLUSHED))
                {
                    PdfObject contentsDirectObj = ((PdfIndirectReference)contents).GetRefersTo();
                    if (contentsDirectObj.IsArray())
                    {
                        ArrayFlushIfModified((PdfArray)contentsDirectObj);
                    }
                    else
                    {
                        contentsDirectObj.Flush();
                    }
                }
            }
            else
            {
                // already checked that modified
                if (contents is PdfArray)
                {
                    ArrayFlushIfModified((PdfArray)contents);
                }
                else
                {
                    if (contents is PdfStream)
                    {
                        FlushIfModified(contents);
                    }
                }
            }
            // Page tags flushing is supported only in PdfPage#flush and #unsafeFlushDeep: it makes sense to flush tags
            // completely for heavily modified or new pages. For the slightly modified pages it should be enough to release
            // the tag structure objects via tag structure releasing utility.
            if (!pageWasModified)
            {
                page.GetPdfObject().GetIndirectReference().ClearState(PdfObject.MODIFIED);
                pdfDoc.GetCatalog().GetPageTree().ReleasePage(pageNum);
                page.UnsetForbidRelease();
                page.GetPdfObject().Release();
            }
            else
            {
                // inherited and modified resources are handled in #flushPage call in the beginning of method
                page.ReleaseInstanceFields();
                page.GetPdfObject().Flush();
            }
        }
Beispiel #6
0
        // For internal usage only
        /// <summary>Write a PdfObject to the outputstream.</summary>
        /// <param name="pdfObject">PdfObject to write</param>
        /// <returns>this PdfOutPutStream</returns>
        public virtual iText.Kernel.Pdf.PdfOutputStream Write(PdfObject pdfObject)
        {
            if (pdfObject.CheckState(PdfObject.MUST_BE_INDIRECT) && document != null)
            {
                pdfObject.MakeIndirect(document);
                pdfObject = pdfObject.GetIndirectReference();
            }
            if (pdfObject.CheckState(PdfObject.READ_ONLY))
            {
                throw new PdfException(PdfException.CannotWriteObjectAfterItWasReleased);
            }
            switch (pdfObject.GetObjectType())
            {
            case PdfObject.ARRAY: {
                Write((PdfArray)pdfObject);
                break;
            }

            case PdfObject.DICTIONARY: {
                Write((PdfDictionary)pdfObject);
                break;
            }

            case PdfObject.INDIRECT_REFERENCE: {
                Write((PdfIndirectReference)pdfObject);
                break;
            }

            case PdfObject.NAME: {
                Write((PdfName)pdfObject);
                break;
            }

            case PdfObject.NULL:
            case PdfObject.BOOLEAN: {
                Write((PdfPrimitiveObject)pdfObject);
                break;
            }

            case PdfObject.LITERAL: {
                Write((PdfLiteral)pdfObject);
                break;
            }

            case PdfObject.STRING: {
                Write((PdfString)pdfObject);
                break;
            }

            case PdfObject.NUMBER: {
                Write((PdfNumber)pdfObject);
                break;
            }

            case PdfObject.STREAM: {
                Write((PdfStream)pdfObject);
                break;
            }
            }
            return(this);
        }