/// <summary> /// Initializes this instance from an exisiting PDF document. /// </summary> void Initialize() { string title; if (Elements.TryGetString(Keys.Title, out title)) { Title = title; } PdfReference parentRef = Elements.GetReference(Keys.Parent); if (parentRef != null) { PdfOutline parent = parentRef.Value as PdfOutline; if (parent != null) { Parent = parent; } } Count = Elements.GetInteger(Keys.Count); PdfArray colors = Elements.GetArray(Keys.C); if (colors != null && colors.Elements.Count == 3) { double r = colors.Elements.GetReal(0); double g = colors.Elements.GetReal(1); double b = colors.Elements.GetReal(2); TextColor = XColor.FromArgb((int)(r * 255), (int)(g * 255), (int)(b * 255)); } // Style directly works on dictionary element. PdfItem dest = Elements.GetValue(Keys.Dest); PdfItem a = Elements.GetValue(Keys.A); Debug.Assert(dest == null || a == null, "Either destination or goto action."); if (dest != null) { if (dest is PdfArray destArray) { SplitDestinationPage(destArray); } else { Debug.Assert(false, "See what to do when this happened."); } } else if (a != null) { // The dictionary should be a GoTo action. PdfDictionary action = a as PdfDictionary; if (action != null && action.Elements.GetName(PdfAction.Keys.S) == "/GoTo") { dest = action.Elements[PdfGoToAction.Keys.D]; if (dest is PdfArray destArray) { // Replace Action with /Dest entry. Elements.Remove(Keys.A); Elements.Add(Keys.Dest, destArray); SplitDestinationPage(destArray); } else if (dest is PdfReference detRef) { // Replace Action with /Dest entry. Elements.Remove(Keys.A); Elements.Add(Keys.Dest, detRef.Value); SplitDestinationPage((PdfArray)detRef.Value); } else { throw new Exception("Destination Array expected."); } } else { Debug.Assert(false, "See what to do when this happened."); } } else { // Neither destination page nor GoTo action. } InitializeChildren(); }
void SplitDestinationPage(PdfArray destination) // Reference: 8.2 Destination syntax / Page 582 { // ReSharper disable HeuristicUnreachableCode #pragma warning disable 162 // The destination page may not yet transformed to PdfPage. PdfDictionary destPage = (PdfDictionary)((PdfReference)(destination.Elements[0])).Value; PdfPage page = destPage as PdfPage; if (page == null) { page = new PdfPage(destPage); } DestinationPage = page; PdfName type = destination.Elements[1] as PdfName; if (type != null) { PageDestinationType = (PdfPageDestinationType)Enum.Parse(typeof(PdfPageDestinationType), type.Value.Substring(1), true); switch (PageDestinationType) { // [page /XYZ left top zoom] case PdfPageDestinationType.Xyz: Left = destination.Elements.GetReal(2); Top = destination.Elements.GetReal(3); Zoom = destination.Elements.GetReal(4); break; // [page /Fit] case PdfPageDestinationType.Fit: // /Fit has no parameters. break; // [page /FitH top] case PdfPageDestinationType.FitH: Top = destination.Elements.GetReal(2); break; // [page /FitV left] case PdfPageDestinationType.FitV: Left = destination.Elements.GetReal(2); break; // [page /FitR left bottom right top] case PdfPageDestinationType.FitR: Left = destination.Elements.GetReal(2); Bottom = destination.Elements.GetReal(3); Right = destination.Elements.GetReal(4); Top = destination.Elements.GetReal(5); break; // [page /FitB] case PdfPageDestinationType.FitB: // /Fit has no parameters. break; // [page /FitBH top] case PdfPageDestinationType.FitBH: Top = destination.Elements.GetReal(2); break; // [page /FitBV left] case PdfPageDestinationType.FitBV: Left = destination.Elements.GetReal(2); break; default: throw new ArgumentOutOfRangeException(); } } #pragma warning restore 162 // ReSharper restore HeuristicUnreachableCode }
/// <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> /// <param name="annotationCopying">Annotation copying action, by default annotations are not copied.</param> public void InsertRange(int index, PdfDocument document, int startIndex, int pageCount, AnnotationCopyingType annotationCopying = AnnotationCopyingType.DoNotCopy) { 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, annotationCopying); insertPages[idx] = page; importPages[idx] = importPage; Owner._irefTable.Add(page); // Add page substitute to importedObjectTable. PdfImportedObjectTable importedObjectTable = Owner.FormTable.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) { PdfReference iref = destArray.Elements[0] as PdfReference; if (iref != null) { 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); } } } }