/// <summary> /// Initializes a new instance from an existing dictionary. Used for object type transformation. /// </summary> /// <param name="array">The array.</param> protected PDFArray(PDFArray array) : base(array) { if (array._elements != null) { array._elements.ChangeOwner(this); } }
/// <summary> /// Moves this instance to another array during object type transformation. /// </summary> internal void ChangeOwner(PDFArray array) { if (_ownerArray != null) { // ??? } // Set new owner. _ownerArray = array; // Set owners elements to this. array._elements = this; }
/// <summary> /// Recursively converts the page tree into a flat array. /// </summary> PDFDictionary[] GetKids(PDFReference iref, PDFPage.InheritedValues values, PDFDictionary parent) { // TODO: inherit inheritable keys... PDFDictionary kid = (PDFDictionary)iref.Value; #if true string type = kid.Elements.GetName(Keys.Type); if (type == "/Page") { PDFPage.InheritValues(kid, values); return(new PDFDictionary[] { kid }); } if (String.IsNullOrEmpty(type)) { // Type is required. If type is missing, assume it is "/Page" and hope it will work. // TODO Implement a "Strict" mode in PDFSharp and don't do this in "Strict" mode. PDFPage.InheritValues(kid, values); return(new PDFDictionary[] { kid }); } #else if (kid.Elements.GetName(Keys.Type) == "/Page") { PDFPage.InheritValues(kid, values); return(new PDFDictionary[] { kid }); } #endif Debug.Assert(kid.Elements.GetName(Keys.Type) == "/Pages"); PDFPage.InheritValues(kid, ref values); List <PDFDictionary> list = new List <PDFDictionary>(); PDFArray kids = kid.Elements["/Kids"] as PDFArray; if (kids == null) { if (kid.Elements["/Kids"] is PDFReference xref3) { kids = xref3.Value as PDFArray; } } foreach (PDFReference xref2 in kids) { list.AddRange(GetKids(xref2, values, kid)); } int count = list.Count; Debug.Assert(count == kid.Elements.GetInteger("/Count")); return(list.ToArray()); }
/// <summary> /// Implements the copy mechanism. /// </summary> protected override object Copy() { PDFArray array = (PDFArray)base.Copy(); if (array._elements != null) { array._elements = array._elements.Clone(); int count = array._elements.Count; for (int idx = 0; idx < count; idx++) { PDFItem item = array._elements[idx]; if (item is PDFObject) { array._elements[idx] = item.Clone(); } } } return(array); }
/// <summary> /// Replaces the page tree by a flat array of indirect references to the pages objects. /// </summary> internal void FlattenPageTree() { // Acrobat creates a balanced tree if the number of pages is roughly more than ten. This is // not difficult but obviously also not necessary. I created a document with 50000 pages with // PDF4NET and Acrobat opened it in less than 2 seconds. //PDFReference xrefRoot = Document.Catalog.Elements[PDFCatalog.Keys.Pages] as PDFReference; //PDFDictionary[] pages = GetKids(xrefRoot, null); // Promote inheritable values down the page tree PDFPage.InheritedValues values = new PDFPage.InheritedValues(); PDFPage.InheritValues(this, ref values); PDFDictionary[] pages = GetKids(Reference, values, null); // Replace /Pages in catalog by this object // xrefRoot.Value = this; PDFArray array = new PDFArray(Owner); foreach (PDFDictionary page in pages) { // Fix the parent page.Elements[PDFPage.Keys.Parent] = Reference; array.Elements.Add(page.Reference); } Elements.SetName(Keys.Type, "/Pages"); #if true // Direct array. Elements.SetValue(Keys.Kids, array); #else // Indirect array. Document.xrefTable.Add(array); Elements.SetValue(Keys.Kids, array.XRef); #endif Elements.SetInteger(Keys.Count, array.Elements.Count); }
/// <summary> /// Inserts pages of the specified document into this document. /// </summary> /// <param name="index">The index in this document where to insert the page .</param> /// <param name="document">The document to be inserted.</param> /// <param name="startIndex">The index of the first page to be inserted.</param> /// <param name="pageCount">The number of pages to be inserted.</param> public void InsertRange(int index, PDFDocument document, int startIndex, int pageCount) { if (document == null) { throw new ArgumentNullException("document"); } if (index < 0 || index > Count) { throw new ArgumentOutOfRangeException("index", "Argument 'index' out of range."); } int importDocumentPageCount = document.PageCount; if (startIndex < 0 || startIndex + pageCount > importDocumentPageCount) { throw new ArgumentOutOfRangeException("startIndex", "Argument 'startIndex' out of range."); } if (pageCount > importDocumentPageCount) { throw new ArgumentOutOfRangeException("pageCount", "Argument 'pageCount' out of range."); } PDFPage[] insertPages = new PDFPage[pageCount]; PDFPage[] importPages = new PDFPage[pageCount]; // 1st create all new pages. for (int idx = 0, insertIndex = index, importIndex = startIndex; importIndex < startIndex + pageCount; idx++, insertIndex++, importIndex++) { PDFPage importPage = document.Pages[importIndex]; PDFPage page = ImportExternalPage(importPage); insertPages[idx] = page; importPages[idx] = importPage; Owner.IrefTable.Add(page); // Add page substitute to importedObjectTable. PDFImportedObjectTable importedObjectTable = Owner.ExternalDocumentTable.GetImportedObjectTable(importPage); importedObjectTable.Add(importPage.ObjectID, page.Reference); PagesArray.Elements.Insert(insertIndex, page.Reference); if (Owner.Settings.TrimMargins.AreSet) { page.TrimMargins = Owner.Settings.TrimMargins; } } Elements.SetInteger(Keys.Count, PagesArray.Elements.Count); // 2nd copy link annotations that are in the range of the imported pages. for (int idx = 0, importIndex = startIndex; importIndex < startIndex + pageCount; idx++, importIndex++) { PDFPage importPage = document.Pages[importIndex]; PDFPage page = insertPages[idx]; // Get annotations. PDFArray annots = importPage.Elements.GetArray(PDFPage.Keys.Annots); if (annots != null) { PDFAnnotations annotations = new PDFAnnotations(Owner); // Loop through annotations. int count = annots.Elements.Count; for (int idxAnnotation = 0; idxAnnotation < count; idxAnnotation++) { PDFDictionary annot = annots.Elements.GetDictionary(idxAnnotation); if (annot != null) { string subtype = annot.Elements.GetString(PDFAnnotation.Keys.Subtype); if (subtype == "/Link") { bool addAnnotation = false; PDFLinkAnnotation newAnnotation = new PDFLinkAnnotation(Owner); PDFName[] importAnnotationKeyNames = annot.Elements.KeyNames; foreach (PDFName pdfItem in importAnnotationKeyNames) { PDFItem impItem; switch (pdfItem.Value) { case "/BS": newAnnotation.Elements.Add("/BS", new PDFLiteral("<</W 0>>")); break; case "/F": // /F 4 impItem = annot.Elements.GetValue("/F"); Debug.Assert(impItem is PDFInteger); newAnnotation.Elements.Add("/F", impItem.Clone()); break; case "/Rect": // /Rect [68.6 681.08 145.71 702.53] impItem = annot.Elements.GetValue("/Rect"); Debug.Assert(impItem is PDFArray); newAnnotation.Elements.Add("/Rect", impItem.Clone()); break; case "/StructParent": // /StructParent 3 impItem = annot.Elements.GetValue("/StructParent"); Debug.Assert(impItem is PDFInteger); newAnnotation.Elements.Add("/StructParent", impItem.Clone()); break; case "/Subtype": // Already set. break; case "/Dest": // /Dest [30 0 R /XYZ 68 771 0] impItem = annot.Elements.GetValue("/Dest"); impItem = impItem.Clone(); // Is value an array with 5 elements where the first one is an iref? PDFArray destArray = impItem as PDFArray; if (destArray != null && destArray.Elements.Count == 5) { if (destArray.Elements[0] is PDFReference iref) { iref = RemapReference(insertPages, importPages, iref); if (iref != null) { destArray.Elements[0] = iref; newAnnotation.Elements.Add("/Dest", destArray); addAnnotation = true; } } } break; default: #if DEBUG_ Debug - Break.Break(true); #endif break; } } // Add newAnnotations only it points to an imported page. if (addAnnotation) { annotations.Add(newAnnotation); } } } } // At least one link annotation found? if (annotations.Count > 0) { //Owner._irefTable.Add(annotations); page.Elements.Add(PDFPage.Keys.Annots, annotations); } } } }
internal ArrayElements(PDFArray array) { _elements = new List <PDFItem>(); _ownerArray = array; }