/// <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
        }
Ejemplo n.º 3
0
        /// <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);
                    }
                }
            }
        }