class HexaPDF::Importer
The Importer
class manages the process of copying objects from one Document
to another.
It may seem unnecessary using an importer containing state for the task. However, by retaining some information about the already copied objects we can make sure that already imported objects don't get imported again.
Two types of indirect objects are never imported from one document to another: the catalog and page tree nodes. If the catalog was imported, the whole source document would be imported. And if one page tree node would imported, the whole page tree would be imported.
See: Document#import
Public Class Methods
Returns the Importer
object for copying objects from the source
to the destination
document.
# File lib/hexapdf/importer.rb, line 64 def self.for(source:, destination:) @map ||= {} @map.keep_if {|_, v| v.source.weakref_alive? && v.destination.weakref_alive? } source = NullableWeakRef.new(source) destination = NullableWeakRef.new(destination) @map[[source.hash, destination.hash]] ||= new(source: source, destination: destination) end
Initializes a new importer that can import objects from the source
document to the destination
document.
# File lib/hexapdf/importer.rb, line 78 def initialize(source:, destination:) @source = source @destination = destination @mapper = {} end
Public Instance Methods
Imports the given object
from the source to the destination object and returns the imported object.
Note: Indirect objects are automatically added to the destination document but direct or simple objects are not.
An error is raised if the object doesn't belong to the source
document.
# File lib/hexapdf/importer.rb, line 91 def import(object) mapped_object = @mapper[object.data]&.__getobj__ if object.kind_of?(HexaPDF::Object) if object.kind_of?(HexaPDF::Object) && object.document? && @source != object.document raise HexaPDF::Error, "Import error: Incorrect document object for importer" elsif mapped_object && mapped_object == @destination.object(mapped_object) mapped_object else duplicate(object) end end
Private Instance Methods
Recursively duplicates the object.
PDF objects are automatically added to the destination document if they are indirect objects in the source document.
# File lib/hexapdf/importer.rb, line 108 def duplicate(object) case object when Hash object.transform_values {|v| duplicate(v) } when Array object.map {|v| duplicate(v) } when HexaPDF::Reference import(@source.object(object)) when HexaPDF::Object if object.type == :Catalog || object.type == :Pages @mapper[object.data] = nil else obj = object.dup @mapper[object.data] = NullableWeakRef.new(obj) obj.document = @destination.__getobj__ obj.instance_variable_set(:@data, obj.data.dup) obj.data.oid = 0 obj.data.gen = 0 @destination.add(obj) if object.indirect? obj.data.stream = obj.data.stream.dup if obj.data.stream.kind_of?(String) obj.data.value = duplicate(obj.data.value) obj.data.value.update(duplicate(object.copy_inherited_values)) if object.type == :Page obj end when String object.dup else object end end