public virtual void InsertIntermediateParentTest() { String filename = "insertIntermediateParentTest.pdf"; PdfReader reader = new PdfReader(sourceFolder + filename); PdfWriter writer = new PdfWriter(new MemoryStream()); PdfDocument pdfDoc = new PdfDocument(reader, writer, new StampingProperties().UseAppendMode()); PdfPage page = pdfDoc.GetFirstPage(); PdfPages pdfPages = new PdfPages(page.parentPages.GetFrom(), pdfDoc, page.parentPages); page.parentPages.GetKids().Set(0, pdfPages.GetPdfObject()); page.parentPages.DecrementCount(); pdfPages.AddPage(page.GetPdfObject()); pdfDoc.Close(); NUnit.Framework.Assert.IsTrue(page.GetPdfObject().IsModified()); }
private PdfObject GetParentValue(PdfPages parentPages, PdfName pdfName) { if (parentPages != null) { PdfDictionary parentDictionary = parentPages.GetPdfObject(); PdfObject value = parentDictionary.Get(pdfName); if (value != null) { return(value); } else { return(GetParentValue(parentPages.GetParent(), pdfName)); } } return(null); }
/// <summary>Generate PdfPages tree.</summary> /// <returns> /// root /// <see cref="PdfPages"/> /// </returns> /// <exception cref="iText.Kernel.PdfException">in case empty document</exception> protected internal virtual PdfObject GenerateTree() { if (pageRefs.Count == 0) { throw new PdfException(PdfException.DocumentHasNoPages); } if (generated) { throw new PdfException(PdfException.PdfPagesTreeCouldBeGeneratedOnlyOnce); } if (root == null) { while (parents.Count != 1) { IList <PdfPages> nextParents = new List <PdfPages>(); //dynamicLeafSize helps to avoid PdfPages leaf with only one page int dynamicLeafSize = leafSize; PdfPages current = null; for (int i = 0; i < parents.Count; i++) { PdfPages pages = parents[i]; int pageCount = pages.GetCount(); if (i % dynamicLeafSize == 0) { if (pageCount <= 1) { dynamicLeafSize++; } else { current = new PdfPages(-1, document); nextParents.Add(current); dynamicLeafSize = leafSize; } } System.Diagnostics.Debug.Assert(current != null); current.AddPages(pages); } parents = nextParents; } root = parents[0]; } generated = true; return(root.GetPdfObject()); }
public virtual void ReadSinglePageTest() { String srcFile = sourceFolder + "allPagesAreLeaves.pdf"; PdfPagesTest.CustomPdfReader reader = new PdfPagesTest.CustomPdfReader(this, srcFile); reader.SetMemorySavingMode(true); PdfDocument document = new PdfDocument(reader); int amountOfPages = document.GetNumberOfPages(); PdfPages pdfPages = document.catalog.GetPageTree().GetRoot(); PdfArray pageIndRefArray = ((PdfDictionary)pdfPages.GetPdfObject()).GetAsArray(PdfName.Kids); document.GetPage(amountOfPages); NUnit.Framework.Assert.AreEqual(1, GetAmountOfReadPages(pageIndRefArray)); document.GetPage(amountOfPages / 2); NUnit.Framework.Assert.AreEqual(2, GetAmountOfReadPages(pageIndRefArray)); document.GetPage(1); NUnit.Framework.Assert.AreEqual(3, GetAmountOfReadPages(pageIndRefArray)); document.Close(); }
private void LoadPage(int pageNum) { PdfDictionary targetPage = pageRefs[pageNum]; if (targetPage != null) { return; } //if we go here, we have to split PdfPages that contains pageNum int parentIndex = FindPageParent(pageNum); PdfPages parent = parents[parentIndex]; PdfArray kids = parent.GetKids(); if (kids == null) { throw new PdfException(PdfException.InvalidPageStructure1).SetMessageParams(pageNum + 1); } int kidsCount = parent.GetCount(); // we should handle separated pages, it means every PdfArray kids must contain either PdfPage or PdfPages, // mix of PdfPage and PdfPages not allowed. bool findPdfPages = false; // NOTE optimization? when we already found needed index for (int i = 0; i < kids.Size(); i++) { PdfDictionary page = kids.GetAsDictionary(i); if (page == null) { // null values not allowed in pages tree. throw new PdfException(PdfException.InvalidPageStructure1).SetMessageParams(pageNum + 1); } PdfObject pageKids = page.Get(PdfName.Kids); if (pageKids != null) { if (pageKids.GetObjectType() == PdfObject.ARRAY) { findPdfPages = true; } else { // kids must be of type array throw new PdfException(PdfException.InvalidPageStructure1).SetMessageParams(pageNum + 1); } } } if (findPdfPages) { // handle mix of PdfPage and PdfPages. // handle count property! IList <PdfPages> newParents = new List <PdfPages>(kids.Size()); PdfPages lastPdfPages = null; for (int i_1 = 0; i_1 < kids.Size() && kidsCount > 0; i_1++) { PdfDictionary pdfPagesObject = kids.GetAsDictionary(i_1); if (pdfPagesObject.GetAsArray(PdfName.Kids) == null) { // pdfPagesObject is PdfPage if (lastPdfPages == null) { // possible if only first kid is PdfPage lastPdfPages = new PdfPages(parent.GetFrom(), document, parent); kids.Set(i_1, lastPdfPages.GetPdfObject()); newParents.Add(lastPdfPages); } lastPdfPages.AddPage(pdfPagesObject); kids.Remove(i_1); i_1--; kidsCount--; } else { // pdfPagesObject is PdfPages int from = lastPdfPages == null?parent.GetFrom() : lastPdfPages.GetFrom() + lastPdfPages.GetCount(); lastPdfPages = new PdfPages(from, kidsCount, pdfPagesObject, parent); newParents.Add(lastPdfPages); kidsCount -= lastPdfPages.GetCount(); } } parents.JRemoveAt(parentIndex); for (int i_2 = newParents.Count - 1; i_2 >= 0; i_2--) { parents.Add(parentIndex, newParents[i_2]); } // recursive call, to load needed pageRef. // NOTE optimization? add to loadPage startParentIndex. LoadPage(pageNum); } else { int from = parent.GetFrom(); // Possible exception in case kids.getSize() < parent.getCount(). // In any case parent.getCount() has higher priority. // NOTE optimization? when we already found needed index for (int i_1 = 0; i_1 < parent.GetCount(); i_1++) { pageRefs[from + i_1] = kids.GetAsDictionary(i_1); } } }
private void LoadPage(int pageNum) { PdfIndirectReference targetPage = pageRefs[pageNum]; if (targetPage != null) { return; } //if we go here, we have to split PdfPages that contains pageNum int parentIndex = FindPageParent(pageNum); PdfPages parent = parents[parentIndex]; PdfArray kids = parent.GetKids(); if (kids == null) { throw new PdfException(PdfException.InvalidPageStructure1).SetMessageParams(pageNum + 1); } int kidsCount = parent.GetCount(); // we should handle separated pages, it means every PdfArray kids must contain either PdfPage or PdfPages, // mix of PdfPage and PdfPages not allowed. bool findPdfPages = false; // NOTE optimization? when we already found needed index for (int i = 0; i < kids.Size(); i++) { PdfDictionary page = kids.GetAsDictionary(i); // null values not allowed in pages tree. if (page == null) { throw new PdfException(PdfException.InvalidPageStructure1).SetMessageParams(pageNum + 1); } PdfObject pageKids = page.Get(PdfName.Kids); if (pageKids != null) { if (pageKids.IsArray()) { findPdfPages = true; } else { // kids must be of type array throw new PdfException(PdfException.InvalidPageStructure1).SetMessageParams(pageNum + 1); } } if (document.GetReader().IsMemorySavingMode() && !findPdfPages && parent.GetFrom() + i != pageNum) { page.Release(); } } if (findPdfPages) { // handle mix of PdfPage and PdfPages. // handle count property! IList <PdfPages> newParents = new List <PdfPages>(kids.Size()); PdfPages lastPdfPages = null; for (int i = 0; i < kids.Size() && kidsCount > 0; i++) { /* * We don't release pdfPagesObject in the end of each loop because we enter this for-cycle only when parent has PdfPages kids. * If all of the kids are PdfPages, then there's nothing to release, because we don't release PdfPages at this point. * If there are kids that are instances of PdfPage, then there's no sense in releasing them: * in this case ParentTreeStructure is being rebuilt by inserting an intermediate PdfPages between the parent and a PdfPage, * thus modifying the page object by resetting its parent, thus making it impossible to release the object. */ PdfDictionary pdfPagesObject = kids.GetAsDictionary(i); if (pdfPagesObject.GetAsArray(PdfName.Kids) == null) { // pdfPagesObject is PdfPage // possible if only first kid is PdfPage if (lastPdfPages == null) { lastPdfPages = new PdfPages(parent.GetFrom(), document, parent); kids.Set(i, lastPdfPages.GetPdfObject()); newParents.Add(lastPdfPages); } else { // Only remove from kids if we did not replace the entry with new PdfPages kids.Remove(i); i--; } // decrement count first so that page is not counted twice when moved to lastPdfPages parent.DecrementCount(); lastPdfPages.AddPage(pdfPagesObject); kidsCount--; } else { // pdfPagesObject is PdfPages int from = lastPdfPages == null?parent.GetFrom() : lastPdfPages.GetFrom() + lastPdfPages.GetCount(); lastPdfPages = new PdfPages(from, kidsCount, pdfPagesObject, parent); newParents.Add(lastPdfPages); kidsCount -= lastPdfPages.GetCount(); } } parents.JRemoveAt(parentIndex); for (int i = newParents.Count - 1; i >= 0; i--) { parents.Add(parentIndex, newParents[i]); } // recursive call, to load needed pageRef. // NOTE optimization? add to loadPage startParentIndex. LoadPage(pageNum); } else { int from = parent.GetFrom(); // Possible exception in case kids.getSize() < parent.getCount(). // In any case parent.getCount() has higher priority. // NOTE optimization? when we already found needed index for (int i = 0; i < parent.GetCount(); i++) { PdfObject kid = kids.Get(i, false); if (kid is PdfIndirectReference) { pageRefs[from + i] = (PdfIndirectReference)kid; } else { pageRefs[from + i] = kid.GetIndirectReference(); } } } }