private void ImportAcroField(PdfPage page, PdfPage importPage, PdfAcroForm localForm, PdfImportedObjectTable importedObjectTable, PdfAcroField fieldObj, bool isChild)
 {
     if (fieldObj != null)
     {
         PdfDictionary importedObject;
         if (!importedObjectTable.Contains(fieldObj.ObjectID))
         {
             // Do not use PdfObject.DeepCopyClosure as that would also create new Pages when encountering the "/P" Entry  !
             importedObject = ImportClosure(importedObjectTable, _document, fieldObj) as PdfDictionary;
         }
         else
         {
             importedObject = importedObjectTable[fieldObj.ObjectID].Value as PdfDictionary;
         }
         Debug.Assert(importedObject != null, "Imported AcroField is null");
         if (importedObject != null)
         {
             var name = importedObject is PdfAcroField ? ((PdfAcroField)importedObject).FullyQualifiedName : "NoName";
             Debug.WriteLine(String.Format("Importing {0} '{1}' ({2})", importedObject.GetType().Name, name, importedObject.ObjectID));
             if (importedObject.Elements.ContainsKey("/P"))
             {
                 var fieldPage = importedObject.Elements.GetObject(PdfAnnotation.Keys.Page);
                 Debug.Assert(_document._irefTable.Contains(fieldPage.ObjectID), "Page of imported field should exist in current document");
             }
             if (!isChild && !IsInArray(localForm.Fields, importedObject))
             {
                 localForm.Fields.Elements.Add(importedObject);
             }
         }
     }
 }
        private PdfReference FixDocumentRef(PdfItem objItem, PdfImportedObjectTable importedObjectTable)
        {
            if (objItem == null)
            {
                return(null);
            }
            var obj = objItem as PdfObject;

            if (obj != null)
            {
                obj._document = _document;
            }
            var dict = obj as PdfDictionary;

            if (dict != null)
            {
                foreach (var key in dict.Elements.KeyNames)
                {
                    var r = FixDocumentRef(dict.Elements[key], importedObjectTable);
                    if (r != null)
                    {
                        dict.Elements.SetReference(key.Value, r.Value);
                    }
                }
            }
            var array = obj as PdfArray;

            if (array != null)
            {
                for (var i = 0; i < array.Elements.Count; i++)
                {
                    var r = FixDocumentRef(array.Elements[i], importedObjectTable);
                    if (r != null)
                    {
                        array.Elements[i] = r;
                    }
                }
            }
            var reference = objItem as PdfReference;

            if (reference != null && reference.Document != _document)
            {
                if (importedObjectTable.Contains(reference.ObjectID))
                {
                    return(importedObjectTable[reference.ObjectID]);
                }
                var value = ImportClosure(importedObjectTable, _document, reference.Value);
                Debug.Assert(value.Reference != null);
                return(value.Reference);
            }
            return(null);
        }
        ///// <summary>
        ///// Imports an object and its transitive closure to the specified document.
        ///// </summary>
        /// <param name="importedObjectTable">The imported object table of the owner for the external document.</param>
        /// <param name="owner">The document that owns the cloned objects.</param>
        /// <param name="externalObject">The root object to be cloned.</param>
        /// <returns>The clone of the root object</returns>
        internal static PdfObject ImportClosure(PdfImportedObjectTable importedObjectTable, PdfDocument owner, PdfObject externalObject)
        {
            Debug.Assert(ReferenceEquals(importedObjectTable.Owner, owner), "importedObjectTable does not belong to the owner.");
            Debug.Assert(ReferenceEquals(importedObjectTable.ExternalDocument, externalObject.Owner),
                         "The ExternalDocument of the importedObjectTable does not belong to the owner of object to be imported.");

            // Get transitive closure of external object.
            PdfObject[] elements = externalObject.Owner.Internals.GetClosure(externalObject);
            int         count    = elements.Length;

#if DEBUG_
            for (int idx = 0; idx < count; idx++)
            {
                Debug.Assert(elements[idx].XRef != null);
                Debug.Assert(elements[idx].XRef.Document != null);
                Debug.Assert(elements[idx].Document != null);
                if (elements[idx].ObjectID.ObjectNumber == 12)
                {
                    GetType();
                }
            }
#endif
            // 1st loop. Already imported objects are reused and new ones are cloned.
            for (int idx = 0; idx < count; idx++)
            {
                PdfObject obj = elements[idx];
                Debug.Assert(!ReferenceEquals(obj.Owner, owner));

                if (importedObjectTable.Contains(obj.ObjectID))
                {
#if DEBUG_
                    if (obj.ObjectID.ObjectNumber == 5894)
                    {
                        obj.GetType();
                    }
#endif
                    // Case: External object was already imported.
                    PdfReference iref = importedObjectTable[obj.ObjectID];
                    Debug.Assert(iref != null);
                    Debug.Assert(iref.Value != null);
                    Debug.Assert(iref.Document == owner);
                    // Replace external object by the already cloned counterpart.
                    elements[idx] = iref.Value;
                }
                else
                {
                    // Case: External object was not yet imported earlier and must be cloned.
                    PdfObject clone = obj.Clone();
                    Debug.Assert(clone.Reference == null);
                    clone.Document = owner;
                    if (obj.Reference != null)
                    {
                        // Case: The cloned object was an indirect object.
                        // Add clone to new owner document.
                        owner._irefTable.Add(clone);
                        Debug.Assert(clone.Reference != null);
                        // Save an association from old object identifier to new iref.
                        importedObjectTable.Add(obj.ObjectID, clone.Reference);
                    }
                    else
                    {
                        // Case: The cloned object was a direct object.
                        // Only the root object can be a direct object.
                        Debug.Assert(idx == 0);
                    }
                    // Replace external object by its clone.
                    elements[idx] = clone;
                }
            }
#if DEBUG_
            for (int idx = 0; idx < count; idx++)
            {
                //Debug.Assert(elements[idx].Reference != null);
                //Debug.Assert(elements[idx].Reference.Document != null);
                Debug.Assert(elements[idx].IsIndirect == false);
                Debug.Assert(elements[idx].Owner != null);
                //if (elements[idx].ObjectID.ObjectNumber == 12)
                //    GetType();
            }
#endif
            // 2nd loop. Fix up indirect references that still refers to the external document.
            for (int idx = 0; idx < count; idx++)
            {
                PdfObject obj = elements[idx];
                Debug.Assert(owner != null);
                FixUpObject(importedObjectTable, importedObjectTable.Owner, obj);
            }

            // Return the imported root object.
            return(elements[0]);
        }
 private void FixAcroFields(PdfAcroField.PdfAcroFieldCollection formFields, PdfImportedObjectTable importedObjectTable)
 {
     for (var i = 0; i < formFields.Elements.Count; i++)
     {
         var field = formFields[i];
         if (field.Owner != _document)
         {
             field._document = _document;
         }
         field.Reference.Document = _document;
         if (field.ObjectID.IsEmpty || !_document._irefTable.Contains(field.ObjectID))
         {
             _document._irefTable.Add(field);
         }
         //// fix the /P entry for Field-Annotations
         //var fieldPage = field.Elements.GetDictionary(PdfAcroField.Keys.Page);
         //if (fieldPage != null && fieldPage.Owner != _document)
         //{
         //    var importedPage = importedObjectTable.Contains(fieldPage.ObjectID) ? importedObjectTable[fieldPage.ObjectID] : null;
         //    if (importedPage != null)
         //    {
         //        field.Elements.SetReference(PdfAcroField.Keys.Page, importedPage.Value);
         //        Debug.WriteLine(String.Format("Fixed page of '{0}' ({1}) -> {2} = {3}", field.FullyQualifiedName, field.ObjectID, fieldPage.ObjectID, importedPage.ObjectID));
         //    }
         //    else
         //        Debug.WriteLine(String.Format("Can't fix page of '{0}' ({1}), imported page not found", field.FullyQualifiedName, field.ObjectID));
         //}
         // Annotations are "partly" imported, we need to fix the /P entry
         for (var a = 0; a < field.Annotations.Elements.Count; a++)
         {
             var widget = field.Annotations.Elements[a];
             if (widget != null)
             {
                 // the owner has to be fixed as well...
                 // Note: it was observed that some objects referenced by the widget were still owned by the imported document, but that seems to be fixed on saving...
                 if (widget.Owner != _document)
                 {
                     if (_document._irefTable.Contains(widget.ObjectID))
                     {
                         widget._document          = _document;
                         widget.Reference.Document = _document;
                         if (!_document._irefTable.Contains(widget.ObjectID))
                         {
                             _document._irefTable.Add(widget);
                         }
                     }
                     else
                     {
                         // this was never needed during debugging, we leave it here just in case...
                         var importedWidget = ImportClosure(importedObjectTable, _document, widget) as PdfDictionary;
                         if (importedWidget != null)
                         {
                             widget = new PdfWidgetAnnotation(importedWidget);
                         }
                     }
                     FixDocumentRef(widget, importedObjectTable);
                 }
                 var widgetPage = widget.Page;
                 if (widgetPage != null && widgetPage.Owner != _document)
                 {
                     var importedPage = importedObjectTable.Contains(widgetPage.ObjectID) ? importedObjectTable[widgetPage.ObjectID] : null;
                     if (importedPage != null)
                     {
                         widget.Elements.SetReference(PdfAnnotation.Keys.Page, importedPage.Value);
                         Debug.WriteLine(String.Format("Fixed page of Widget '{0}' ({1}) -> {2} = {3}", field.FullyQualifiedName, field.ObjectID, widgetPage.ObjectID, importedPage.ObjectID));
                         var ip = importedPage.Value as PdfPage;
                         // the widget is a PdfWidgetAnnotation, but the "real" object may be something else (e.g. a PdfGenericField), so we check the referenced object instead
                         if (ip != null && !ip.Annotations.Elements.Contains(widget.Reference))
                         {
                             ip.Annotations.Elements.Add(widget.Reference.Value);
                         }
                     }
                 }
                 else if (widgetPage is PdfPage)
                 {
                     // add widget to the pages' annotations if not already present
                     if (!((PdfPage)widgetPage).Annotations.Elements.Contains(widget.Reference))
                     {
                         ((PdfPage)widgetPage).Annotations.Elements.Add(widget);
                     }
                 }
             }
         }
         if (field.HasKids)
         {
             FixAcroFields(field.Fields, importedObjectTable);
         }
     }
 }