Пример #1
0
 /// <summary>
 /// Maps the specified external object to the substitute object in this document.
 /// Returns null if no such object exists.
 /// </summary>
 public PdfObject MapExternalObject(PdfObject externalObject)
 {
     PdfFormXObjectTable table = _document.FormTable;
     PdfImportedObjectTable iot = table.GetImportedObjectTable(externalObject.Owner);
     PdfReference reference = iot[externalObject.ObjectID];
     return reference == null ? null : reference.Value;
 }
Пример #2
0
        public void DetachDocument(PdfDocument.DocumentHandle handle)
        {
            if (handle.IsAlive)
            {
                foreach (Selector selector in _forms.Keys)
                {
                    PdfImportedObjectTable table = _forms[selector];
                    if (table.ExternalDocument != null && table.ExternalDocument.Handle == handle)
                    {
                        _forms.Remove(selector);
                        break;
                    }
                }
            }

            // Clean table
            bool itemRemoved = true;

            while (itemRemoved)
            {
                itemRemoved = false;
                foreach (Selector selector in _forms.Keys)
                {
                    PdfImportedObjectTable table = _forms[selector];
                    if (table.ExternalDocument == null)
                    {
                        _forms.Remove(selector);
                        itemRemoved = true;
                        break;
                    }
                }
            }
        }
Пример #3
0
        /// <summary>
        /// Gets the imported object table.
        /// </summary>
        public PdfImportedObjectTable GetImportedObjectTable(PdfPage page)
        {
            // Is the external PDF file from which is imported already known for the current document?
            Selector selector = new Selector(page);
            PdfImportedObjectTable importedObjectTable;

            if (!_forms.TryGetValue(selector, out importedObjectTable))
            {
                importedObjectTable = new PdfImportedObjectTable(Owner, page.Owner);
                _forms[selector]    = importedObjectTable;
            }
            return(importedObjectTable);
        }
Пример #4
0
        /// <summary>
        /// Gets a PdfFormXObject from an XPdfForm. Because the returned objects must be unique, always
        /// a new instance of PdfFormXObject is created if none exists for the specified form.
        /// </summary>
        public PdfFormXObject GetForm(XForm form)
        {
            // If the form already has a PdfFormXObject, return it.
            if (form._pdfForm != null)
            {
                Debug.Assert(form.IsTemplate, "An XPdfForm must not have a PdfFormXObject.");
                if (ReferenceEquals(form._pdfForm.Owner, Owner))
                {
                    return(form._pdfForm);
                }
                //throw new InvalidOperationException("Because of a current limitation of PDFsharp an XPdfForm object can be used only within one single PdfDocument.");

                // Dispose PdfFromXObject when document has changed
                form._pdfForm = null;
            }

            XPdfForm pdfForm = form as XPdfForm;

            if (pdfForm != null)
            {
                // Is the external PDF file from which is imported already known for the current document?
                Selector selector = new Selector(form);
                PdfImportedObjectTable importedObjectTable;
                if (!_forms.TryGetValue(selector, out importedObjectTable))
                {
                    // No: Get the external document from the form and create ImportedObjectTable.
                    PdfDocument doc = pdfForm.ExternalDocument;
                    importedObjectTable = new PdfImportedObjectTable(Owner, doc);
                    _forms[selector]    = importedObjectTable;
                }

                PdfFormXObject xObject = importedObjectTable.GetXObject(pdfForm.PageNumber);
                if (xObject == null)
                {
                    xObject = new PdfFormXObject(Owner, importedObjectTable, pdfForm);
                    importedObjectTable.SetXObject(pdfForm.PageNumber, xObject);
                }
                return(xObject);
            }
            Debug.Assert(form.GetType() == typeof(XForm));
            form._pdfForm = new PdfFormXObject(Owner, form);
            return(form._pdfForm);
        }
Пример #5
0
        /// <summary>
        /// Gets the imported object table.
        /// </summary>
        public PdfImportedObjectTable GetImportedObjectTable(PdfDocument document)
        {
            if (document == null)
            {
                throw new ArgumentNullException("document");
            }

            // Is the external PDF file from which is imported already known for the current document?
            Selector selector = new Selector(document);
            PdfImportedObjectTable importedObjectTable;

            if (!_forms.TryGetValue(selector, out importedObjectTable))
            {
                // Create new table for document.
                importedObjectTable = new PdfImportedObjectTable(Owner, document);
                _forms[selector]    = importedObjectTable;
            }
            return(importedObjectTable);
        }
Пример #6
0
        /// <summary>
        /// Gets a PdfFormXObject from an XPdfForm. Because the returned objects must be unique, always
        /// a new instance of PdfFormXObject is created if none exists for the specified form. 
        /// </summary>
        public PdfFormXObject GetForm(XForm form)
        {
            // If the form already has a PdfFormXObject, return it.
            if (form._pdfForm != null)
            {
                Debug.Assert(form.IsTemplate, "An XPdfForm must not have a PdfFormXObject.");
                if (ReferenceEquals(form._pdfForm.Owner, Owner))
                    return form._pdfForm;
                //throw new InvalidOperationException("Because of a current limitation of PDFsharp an XPdfForm object can be used only within one single PdfDocument.");

                // Dispose PdfFromXObject when document has changed
                form._pdfForm = null;
            }

            XPdfForm pdfForm = form as XPdfForm;
            if (pdfForm != null)
            {
                // Is the external PDF file from which is imported already known for the current document?
                Selector selector = new Selector(form);
                PdfImportedObjectTable importedObjectTable;
                if (!_forms.TryGetValue(selector, out importedObjectTable))
                {
                    // No: Get the external document from the form and create ImportedObjectTable.
                    PdfDocument doc = pdfForm.ExternalDocument;
                    importedObjectTable = new PdfImportedObjectTable(Owner, doc);
                    _forms[selector] = importedObjectTable;
                }

                PdfFormXObject xObject = importedObjectTable.GetXObject(pdfForm.PageNumber);
                if (xObject == null)
                {
                    xObject = new PdfFormXObject(Owner, importedObjectTable, pdfForm);
                    importedObjectTable.SetXObject(pdfForm.PageNumber, xObject);
                }
                return xObject;
            }
            Debug.Assert(form.GetType() == typeof(XForm));
            form._pdfForm = new PdfFormXObject(Owner, form);
            return form._pdfForm;
        }
Пример #7
0
        internal PdfFormXObject(PdfDocument thisDocument, PdfImportedObjectTable importedObjectTable, XPdfForm form)
            : base(thisDocument)
        {
            Debug.Assert(ReferenceEquals(thisDocument, importedObjectTable.Owner));
            Elements.SetName(Keys.Type, "/XObject");
            Elements.SetName(Keys.Subtype, "/Form");

            if (form.IsTemplate)
            {
                Debug.Assert(importedObjectTable == null);
                // TODO more initialization here???
                return;
            }
            Debug.Assert(importedObjectTable != null);

            XPdfForm pdfForm = form;
            // Get import page
            PdfPages importPages = importedObjectTable.ExternalDocument.Pages;

            if (pdfForm.PageNumber < 1 || pdfForm.PageNumber > importPages.Count)
            {
                PSSR.ImportPageNumberOutOfRange(pdfForm.PageNumber, importPages.Count, form._path);
            }
            PdfPage importPage = importPages[pdfForm.PageNumber - 1];

            // Import resources
            PdfItem res = importPage.Elements["/Resources"];

            if (res != null) // unlikely but possible
            {
#if true
                // Get root object
                PdfObject root;
                if (res is PdfReference)
                {
                    root = ((PdfReference)res).Value;
                }
                else
                {
                    root = (PdfDictionary)res;
                }

                root = ImportClosure(importedObjectTable, thisDocument, root);
                // If the root was a direct object, make it indirect.
                if (root.Reference == null)
                {
                    thisDocument._irefTable.Add(root);
                }

                Debug.Assert(root.Reference != null);
                Elements["/Resources"] = root.Reference;
#else
                // Get transitive closure
                PdfObject[] resources = importPage.Owner.Internals.GetClosure(resourcesRoot);
                int         count     = resources.Length;
#if DEBUG_
                for (int idx = 0; idx < count; idx++)
                {
                    Debug.Assert(resources[idx].XRef != null);
                    Debug.Assert(resources[idx].XRef.Document != null);
                    Debug.Assert(resources[idx].Document != null);
                    if (resources[idx].ObjectID.ObjectNumber == 12)
                    {
                        GetType();
                    }
                }
#endif
                // 1st step. Already imported objects are reused and new ones are cloned.
                for (int idx = 0; idx < count; idx++)
                {
                    PdfObject obj = resources[idx];
                    if (importedObjectTable.Contains(obj.ObjectID))
                    {
                        // 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 clone counterpart
                        resources[idx] = iref.Value;
                    }
                    else
                    {
                        // External object was not imported ealier and must be cloned
                        PdfObject clone = obj.Clone();
                        Debug.Assert(clone.Reference == null);
                        clone.Document = Owner;
                        if (obj.Reference != null)
                        {
                            // add it to this (the importer) document
                            Owner.irefTable.Add(clone);
                            Debug.Assert(clone.Reference != null);
                            // save old object identifier
                            importedObjectTable.Add(obj.ObjectID, clone.Reference);
                            //Debug.WriteLine("Cloned: " + obj.ObjectID.ToString());
                        }
                        else
                        {
                            // The root object (the /Resources value) is not an indirect object
                            Debug.Assert(idx == 0);
                            // add it to this (the importer) document
                            Owner.irefTable.Add(clone);
                            Debug.Assert(clone.Reference != null);
                        }
                        // replace external object by its clone
                        resources[idx] = clone;
                    }
                }
#if DEBUG_
                for (int idx = 0; idx < count; idx++)
                {
                    Debug.Assert(resources[idx].XRef != null);
                    Debug.Assert(resources[idx].XRef.Document != null);
                    Debug.Assert(resources[idx].Document != null);
                    if (resources[idx].ObjectID.ObjectNumber == 12)
                    {
                        GetType();
                    }
                }
#endif

                // 2nd step. Fix up indirect references that still refers to the import document.
                for (int idx = 0; idx < count; idx++)
                {
                    PdfObject obj = resources[idx];
                    Debug.Assert(obj.Owner != null);
                    FixUpObject(importedObjectTable, importedObjectTable.Owner, obj);
                }

                // Set resources key to the root of the clones
                Elements["/Resources"] = resources[0].Reference;
#endif
            }

            // Take /Rotate into account
            PdfRectangle rect   = importPage.Elements.GetRectangle(PdfPage.Keys.MediaBox);
            int          rotate = importPage.Elements.GetInteger(PdfPage.Keys.Rotate);
            //rotate = 0;
            if (rotate == 0)
            {
                // Set bounding box to media box
                Elements["/BBox"] = rect;
            }
            else
            {
                // TODO: Have to adjust bounding box? (I think not, but I'm not sure -> wait for problem)
                Elements["/BBox"] = rect;

                // Rotate the image such that it is upright
                XMatrix matrix = new XMatrix();
                double  width  = rect.Width;
                double  height = rect.Height;
                matrix.RotateAtPrepend(-rotate, new XPoint(width / 2, height / 2));

                if (rotate != 180)
                {
                    // Translate the image such that its center lies on the center of the rotated bounding box
                    double offset = (height - width) / 2;
                    if (height > width)
                    {
                        matrix.TranslatePrepend(offset, offset);
                    }
                    else
                    {
                        matrix.TranslatePrepend(-offset, -offset);
                    }
                }

                //string item = "[" + PdfEncoders.ToString(matrix) + "]";
                //Elements[Keys.Matrix] = new PdfLiteral(item);
                Elements.SetMatrix(Keys.Matrix, matrix);
            }

            // Preserve filter because the content keeps unmodified
            PdfContent content = importPage.Contents.CreateSingleContent();
#if !DEBUG
            content.Compressed = true;
#endif
            PdfItem filter = content.Elements["/Filter"];
            if (filter != null)
            {
                Elements["/Filter"] = filter.Clone();
            }

            // (no cloning needed because the bytes keep untouched)
            Stream = content.Stream; // new PdfStream(bytes, this);
            Elements.SetInteger("/Length", content.Stream.Value.Length);
        }
Пример #8
0
        /// <summary>
        /// Replace all indirect references to external objects by their cloned counterparts
        /// owned by the importer document.
        /// </summary>
        void FixUpObject_old(PdfImportedObjectTable iot, PdfObject value)
        {
            // TODO: merge with PdfXObject.FixUpObject
            PdfDictionary dict;
            PdfArray      array;

            if ((dict = value as PdfDictionary) != null)
            {
                // Set document for cloned direct objects
                if (dict.Owner == null)
                {
                    dict.Document = Owner;
                }
                else
                {
                    Debug.Assert(dict.Owner == Owner);
                }

                // Search for indirect references in all keys
                PdfName[] names = dict.Elements.KeyNames;
                foreach (PdfName name in names)
                {
                    PdfItem item = dict.Elements[name];
                    // Is item an iref?
                    PdfReference iref = item as PdfReference;
                    if (iref != null)
                    {
                        // Does the iref already belong to this document?
                        if (iref.Document == Owner)
                        {
                            // Yes: fine
                            continue;
                        }
                        else
                        {
                            Debug.Assert(iref.Document == iot.ExternalDocument);
                            // No: replace with iref of cloned object
                            PdfReference newXRef = iot[iref.ObjectID];
                            Debug.Assert(newXRef != null);
                            Debug.Assert(newXRef.Document == Owner);
                            dict.Elements[name] = newXRef;
                        }
                    }
                    else if (item is PdfObject)
                    {
                        // Fix up inner objects
                        FixUpObject_old(iot, (PdfObject)item);
                    }
                }
            }
            else if ((array = value as PdfArray) != null)
            {
                // Set document for cloned direct objects
                if (array.Owner == null)
                {
                    array.Document = Owner;
                }
                else
                {
                    Debug.Assert(array.Owner == Owner);
                }

                // Search for indirect references in all array elements
                int count = array.Elements.Count;
                for (int idx = 0; idx < count; idx++)
                {
                    PdfItem item = array.Elements[idx];
                    // Is item an iref?
                    PdfReference iref = item as PdfReference;
                    if (iref != null)
                    {
                        // Does the iref belongs to this document?
                        if (iref.Document == Owner)
                        {
                            // Yes: fine
                            continue;
                        }
                        else
                        {
                            Debug.Assert(iref.Document == iot.ExternalDocument);
                            // No: replace with iref of cloned object
                            PdfReference newXRef = iot[iref.ObjectID];
                            Debug.Assert(newXRef != null);
                            Debug.Assert(newXRef.Document == Owner);
                            array.Elements[idx] = newXRef;
                        }
                    }
                    else if (item is PdfObject)
                    {
                        // Fix up inner objects
                        FixUpObject_old(iot, (PdfObject)item);
                    }
                }
            }
        }
Пример #9
0
        /// <summary>
        /// Gets the imported object table.
        /// </summary>
        public PdfImportedObjectTable GetImportedObjectTable(PdfDocument document)
        {
            if (document == null)
                throw new ArgumentNullException("document");

            // Is the external PDF file from which is imported already known for the current document?
            Selector selector = new Selector(document);
            PdfImportedObjectTable importedObjectTable;
            if (!_forms.TryGetValue(selector, out importedObjectTable))
            {
                // Create new table for document.
                importedObjectTable = new PdfImportedObjectTable(Owner, document);
                _forms[selector] = importedObjectTable;
            }
            return importedObjectTable;
        }
Пример #10
0
 /// <summary>
 /// Gets the imported object table.
 /// </summary>
 public PdfImportedObjectTable GetImportedObjectTable(PdfPage page)
 {
     // Is the external PDF file from which is imported already known for the current document?
     Selector selector = new Selector(page);
     PdfImportedObjectTable importedObjectTable;
     if (!_forms.TryGetValue(selector, out importedObjectTable))
     {
         importedObjectTable = new PdfImportedObjectTable(Owner, page.Owner);
         _forms[selector] = importedObjectTable;
     }
     return importedObjectTable;
 }
Пример #11
0
    internal PdfFormXObject(PdfDocument thisDocument, PdfImportedObjectTable importedObjectTable, XPdfForm form)
      : base(thisDocument)
    {
      Debug.Assert(Object.ReferenceEquals(thisDocument, importedObjectTable.Owner));
      Elements.SetName(Keys.Type, "/XObject");
      Elements.SetName(Keys.Subtype, "/Form");

      if (form.IsTemplate)
      {
        Debug.Assert(importedObjectTable == null);
        // TODO more initialization here???
        return;
      }
      Debug.Assert(importedObjectTable != null);

      XPdfForm pdfForm = (XPdfForm)form;
      // Get import page
      PdfPages importPages = importedObjectTable.ExternalDocument.Pages;
      if (pdfForm.PageNumber < 1 || pdfForm.PageNumber > importPages.Count)
        PSSR.ImportPageNumberOutOfRange(pdfForm.PageNumber, importPages.Count, form.path);
      PdfPage importPage = importPages[pdfForm.PageNumber - 1];

      // Import resources
      PdfItem res = importPage.Elements["/Resources"];
      if (res != null) // unlikely but possible
      {
#if true
        // Get root object
        PdfObject root;
        if (res is PdfReference)
          root = ((PdfReference)res).Value;
        else
          root = (PdfDictionary)res;

        root = ImportClosure(importedObjectTable, thisDocument, root);
        // If the root was a direct object, make it indirect.
        if (root.Reference == null)
          thisDocument.irefTable.Add(root);

        Debug.Assert(root.Reference != null);
        Elements["/Resources"] = root.Reference;
#else
        // Get transitive closure
        PdfObject[] resources = importPage.Owner.Internals.GetClosure(resourcesRoot);
        int count = resources.Length;
#if DEBUG_
        for (int idx = 0; idx < count; idx++)
        {
          Debug.Assert(resources[idx].XRef != null);
          Debug.Assert(resources[idx].XRef.Document != null);
          Debug.Assert(resources[idx].Document != null);
          if (resources[idx].ObjectID.ObjectNumber == 12)
            GetType();
        }
#endif
        // 1st step. Already imported objects are reused and new ones are cloned.
        for (int idx = 0; idx < count; idx++)
        {
          PdfObject obj = resources[idx];
          if (importedObjectTable.Contains(obj.ObjectID))
          {
            // external object was already imported
            PdfReference iref = importedObjectTable[obj.ObjectID];
            Debug.Assert(iref != null);
            Debug.Assert(iref.Value != null);
            Debug.Assert(iref.Document == this.Owner);
            // replace external object by the already clone counterpart
            resources[idx] = iref.Value;
          }
          else
          {
            // External object was not imported ealier and must be cloned
            PdfObject clone = obj.Clone();
            Debug.Assert(clone.Reference == null);
            clone.Document = this.Owner;
            if (obj.Reference != null)
            {
              // add it to this (the importer) document
              this.Owner.irefTable.Add(clone);
              Debug.Assert(clone.Reference != null);
              // save old object identifier
              importedObjectTable.Add(obj.ObjectID, clone.Reference);
              //Debug.WriteLine("Cloned: " + obj.ObjectID.ToString());
            }
            else
            {
              // The root object (the /Resources value) is not an indirect object
              Debug.Assert(idx == 0);
              // add it to this (the importer) document
              this.Owner.irefTable.Add(clone);
              Debug.Assert(clone.Reference != null);
            }
            // replace external object by its clone
            resources[idx] = clone;
          }
        }
#if DEBUG_
        for (int idx = 0; idx < count; idx++)
        {
          Debug.Assert(resources[idx].XRef != null);
          Debug.Assert(resources[idx].XRef.Document != null);
          Debug.Assert(resources[idx].Document != null);
          if (resources[idx].ObjectID.ObjectNumber == 12)
            GetType();
        }
#endif

        // 2nd step. Fix up indirect references that still refers to the import document.
        for (int idx = 0; idx < count; idx++)
        {
          PdfObject obj = resources[idx];
          Debug.Assert(obj.Owner != null);
          FixUpObject(importedObjectTable, importedObjectTable.Owner, obj);
        }

        // Set resources key to the root of the clones
        Elements["/Resources"] = resources[0].Reference;
#endif
      }

      // Take /Rotate into account
      PdfRectangle rect = importPage.Elements.GetRectangle(PdfPage.Keys.MediaBox);
      int rotate = importPage.Elements.GetInteger(PdfPage.Keys.Rotate);
      //rotate = 0;
      if (rotate == 0)
      {
        // Set bounding box to media box
        this.Elements["/BBox"] = rect;
      }
      else
      {
        // TODO: Have to adjust bounding box? (I think not, but I'm not sure -> wait for problem)
        this.Elements["/BBox"] = rect;

        // Rotate the image such that it is upright
        XMatrix matrix = XMatrix.Identity;
        double width = rect.Width;
        double height = rect.Height;
        matrix.RotateAtPrepend(-rotate, new XPoint(width / 2, height / 2));

        // Translate the image such that its center lies on the center of the rotated bounding box
        double offset = (height - width) / 2;
        if (height > width)
          matrix.TranslatePrepend(offset, offset);
        else
          matrix.TranslatePrepend(-offset, -offset);

        //string item = "[" + PdfEncoders.ToString(matrix) + "]";
        //Elements[Keys.Matrix] = new PdfLiteral(item);
        Elements.SetMatrix(Keys.Matrix, matrix);
      }

      // Preserve filter because the content keeps unmodified
      PdfContent content = importPage.Contents.CreateSingleContent();
#if !DEBUG
      content.Compressed = true;
#endif
      PdfItem filter = content.Elements["/Filter"];
      if (filter != null)
        this.Elements["/Filter"] = filter.Clone();

      // (no cloning needed because the bytes keep untouched)
      this.Stream = content.Stream; // new PdfStream(bytes, this);
      Elements.SetInteger("/Length", content.Stream.Value.Length);
    }
Пример #12
0
    /// <summary>
    /// Replace all indirect references to external objects by their cloned counterparts
    /// owned by the importer document.
    /// </summary>
    void FixUpObject_old(PdfImportedObjectTable iot, PdfObject value)
    {
      // TODO: merge with PdfXObject.FixUpObject
      PdfDictionary dict;
      PdfArray array;
      if ((dict = value as PdfDictionary) != null)
      {
        // Set document for cloned direct objects
        if (dict.Owner == null)
          dict.Document = this.Owner;
        else
          Debug.Assert(dict.Owner == this.Owner);

        // Search for indirect references in all keys
        PdfName[] names = dict.Elements.KeyNames;
        foreach (PdfName name in names)
        {
          PdfItem item = dict.Elements[name];
          // Is item an iref?
          PdfReference iref = item as PdfReference;
          if (iref != null)
          {
            // Does the iref already belong to this document?
            if (iref.Document == this.Owner)
            {
              // Yes: fine
              continue;
            }
            else
            {
              Debug.Assert(iref.Document == iot.ExternalDocument);
              // No: replace with iref of cloned object
              PdfReference newXRef = iot[iref.ObjectID];
              Debug.Assert(newXRef != null);
              Debug.Assert(newXRef.Document == this.Owner);
              dict.Elements[name] = newXRef;
            }
          }
          else if (item is PdfObject)
          {
            // Fix up inner objects
            FixUpObject_old(iot, (PdfObject)item);
          }
        }
      }
      else if ((array = value as PdfArray) != null)
      {
        // Set document for cloned direct objects
        if (array.Owner == null)
          array.Document = this.Owner;
        else
          Debug.Assert(array.Owner == this.Owner);

        // Search for indirect references in all array elements
        int count = array.Elements.Count;
        for (int idx = 0; idx < count; idx++)
        {
          PdfItem item = array.Elements[idx];
          // Is item an iref?
          PdfReference iref = item as PdfReference;
          if (iref != null)
          {
            // Does the iref belongs to this document?
            if (iref.Document == this.Owner)
            {
              // Yes: fine
              continue;
            }
            else
            {
              Debug.Assert(iref.Document == iot.ExternalDocument);
              // No: replace with iref of cloned object
              PdfReference newXRef = iot[iref.ObjectID];
              Debug.Assert(newXRef != null);
              Debug.Assert(newXRef.Document == this.Owner);
              array.Elements[idx] = newXRef;
            }
          }
          else if (item is PdfObject)
          {
            // Fix up inner objects
            FixUpObject_old(iot, (PdfObject)item);
          }
        }
      }
    }
Пример #13
0
    ///// <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))
        {
          // 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
        {
          // External object was not imported ealier 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);
            //// add it to this (the importer) document
            //owner.irefTable.Add(clone);
            //Debug.Assert(clone.Reference != null);
          }
          // replace external object by its clone
          elements[idx] = clone;
        }
      }
#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 (resources[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];
    }
Пример #14
0
    ///// <summary>
    ///// Creates a deep copy of the specified value and its transitive closure and adds the
    ///// new objects to the specified owner document.
    ///// </summary>
    /// <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 DeepCopyClosure(PdfDocument owner, PdfObject externalObject)
    {
      // Get transitive closure
      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. Replace all objects by their clones.
      PdfImportedObjectTable iot = new PdfImportedObjectTable(owner, externalObject.Owner);
      for (int idx = 0; idx < count; idx++)
      {
        PdfObject obj = elements[idx];
        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);
          // the clone gets an iref by adding it to its new owner
          Debug.Assert(clone.Reference != null);
          // save an association from old object identifier to new iref
          iot.Add(obj.ObjectID, clone.Reference);
        }
        else
        {
          // Case: The cloned object was an 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].XRef != null);
          Debug.Assert(elements[idx].XRef.Document != null);
          Debug.Assert(resources[idx].Document != null);
          if (elements[idx].ObjectID.ObjectNumber == 12)
            GetType();
        }
#endif

      // 2nd loop. Fix up all indirect references that still refers to the import document.
      for (int idx = 0; idx < count; idx++)
      {
        PdfObject obj = elements[idx];
        Debug.Assert(obj.Owner == owner);
        FixUpObject(iot, owner, obj);
      }

      // return the clone of the former root object
      return elements[0];
    }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="page"></param>
 /// <returns></returns>
 public PdfImportedObjectTable GetImportedObjectTable(PdfPage page)
 {
   // Is the external PDF file from which is imported already known for the current document?
   Selector selector = new Selector(page);
   PdfImportedObjectTable importedObjectTable = this.forms[selector] as PdfImportedObjectTable;
   if (importedObjectTable == null)
   {
     importedObjectTable = new PdfImportedObjectTable(this.owner, page.Owner);
     this.forms[selector] = importedObjectTable;
   }
   return importedObjectTable;
 }
Пример #16
0
        /// <summary>
        /// Replace all indirect references to external objects by their cloned counterparts
        /// owned by the importer document.
        /// </summary>
        static void FixUpObject(PdfImportedObjectTable iot, PdfDocument owner, PdfObject value)
        {
            Debug.Assert(ReferenceEquals(iot.Owner, owner));

            PdfDictionary dict;
            PdfArray array;
            if ((dict = value as PdfDictionary) != null)
            {
                // Case: The object is a dictionary.
                // Set document for cloned direct objects.
                if (dict.Owner == null)
                {
                    // If the dictionary has not yet an owner set the owner to the importing document.
                    dict.Document = owner;
                }
                else
                {
                    // If the dictionary already has an owner it must be the importing document.
                    Debug.Assert(dict.Owner == owner);
                }

                // Search for indirect references in all dictionary elements.
                PdfName[] names = dict.Elements.KeyNames;
                foreach (PdfName name in names)
                {
                    PdfItem item = dict.Elements[name];
                    Debug.Assert(item != null, "A dictionary element cannot be null.");

                    // Is item an iref?
                    PdfReference iref = item as PdfReference;
                    if (iref != null)
                    {
                        // Case: The item is a reference.
                        // Does the iref already belongs to the new owner?
                        if (iref.Document == owner)
                        {
                            // Yes: fine. Happens when an already cloned object is reused.
                            continue;
                        }

                        //Debug.Assert(iref.Document == iot.Document);
                        // No: Replace with iref of cloned object.
                        PdfReference newXRef = iot[iref.ObjectID];  // TODO: Explain this line of code in all details.
                        Debug.Assert(newXRef != null);
                        Debug.Assert(newXRef.Document == owner);
                        dict.Elements[name] = newXRef;
                    }
                    else
                    {
                        // Case: The item is not a reference.
                        // If item is an object recursively fix its inner items.
                        PdfObject pdfObject = item as PdfObject;
                        if (pdfObject != null)
                        {
                            // Fix up inner objects, i.e. recursively walk down the object tree.
                            FixUpObject(iot, owner, pdfObject);
                        }
                        else
                        {
                            // The item is something else, e.g. a name.
                            // Nothing to do.

                            // ...but let's double check this case in DEBUG build.
                            DebugCheckNonObjects(item);
                        }
                    }
                }
            }
            else if ((array = value as PdfArray) != null)
            {
                // Case: The object is an array.
                // Set document for cloned direct objects.
                if (array.Owner == null)
                {
                    // If the array has not yet an owner set the owner to the importing document.
                    array.Document = owner;
                }
                else
                {
                    // If the array already has an owner it must be the importing document.
                    Debug.Assert(array.Owner == owner);
                }

                // Search for indirect references in all array elements.
                int count = array.Elements.Count;
                for (int idx = 0; idx < count; idx++)
                {
                    PdfItem item = array.Elements[idx];
                    Debug.Assert(item != null, "An array element cannot be null.");

                    // Is item an iref?
                    PdfReference iref = item as PdfReference;
                    if (iref != null)
                    {
                        // Case: The item is a reference.
                        // Does the iref already belongs to the owner?
                        if (iref.Document == owner)
                        {
                            // Yes: fine. Happens when an already cloned object is reused.
                            continue;
                        }

                        // No: replace with iref of cloned object.
                        Debug.Assert(iref.Document == iot.ExternalDocument);
                        PdfReference newXRef = iot[iref.ObjectID];
                        Debug.Assert(newXRef != null);
                        Debug.Assert(newXRef.Document == owner);
                        array.Elements[idx] = newXRef;
                    }
                    else
                    {
                        // Case: The item is not a reference.
                        // If item is an object recursively fix its inner items.
                        PdfObject pdfObject = item as PdfObject;
                        if (pdfObject != null)
                        {
                            // Fix up inner objects, i.e. recursively walk down the object tree.
                            FixUpObject(iot, owner, pdfObject);
                        }
                        else
                        {
                            // The item is something else, e.g. a name.
                            // Nothing to do.

                            // ...but let's double check this case in DEBUG build.
                            DebugCheckNonObjects(item);
                        }
                    }
                }
            }
            else
            {
                // Case: The item is some other indirect object.
                // Indirect integers, booleans, etc. are allowed, but PDFsharp do not create them.
                // If such objects occur in imported PDF files from other producers, nothing more is to do.
                // The owner was already set, which is double checked by the assertions below.
                if (value is PdfNameObject || value is PdfStringObject || value is PdfBooleanObject || value is PdfIntegerObject || value is PdfNumberObject)
                {
                    Debug.Assert(value.IsIndirect);
                    Debug.Assert(value.Owner == owner);
                }
                else
                    Debug.Assert(false, "Should not come here. Object is neither a dictionary nor an array.");
            }
        }