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); } }
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); }
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(); } }
// 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); }