Class: PDF::Core::ObjectStore

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/pdf/core/object_store.rb

Overview

:nodoc:

Constant Summary collapse

BASE_OBJECTS =
%w[info pages root]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ ObjectStore

Returns a new instance of ObjectStore.



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/pdf/core/object_store.rb', line 21

def initialize(opts = {})
  @objects = {}
  @identifiers = []

  load_file(opts[:template]) if opts[:template]

  @info  ||= ref(opts[:info] || {}).identifier
  @root  ||= ref(:Type => :Catalog).identifier
  if opts[:print_scaling] == :none
    root.data[:ViewerPreferences] = {:PrintScaling => :None}
  end
  if pages.nil?
    root.data[:Pages] = ref(:Type => :Pages, :Count => 0, :Kids => [])
  end
end

Instance Attribute Details

#min_versionObject (readonly)

Returns the value of attribute min_version.



17
18
19
# File 'lib/pdf/core/object_store.rb', line 17

def min_version
  @min_version
end

Instance Method Details

#[](id) ⇒ Object



81
82
83
# File 'lib/pdf/core/object_store.rb', line 81

def [](id)
  @objects[id]
end

#compactObject



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/pdf/core/object_store.rb', line 90

def compact
  # Clear live markers
  each { |o| o.live = false }

  # Recursively mark reachable objects live, starting from the roots
  # (the only objects referenced in the trailer)
  root.mark_live
  info.mark_live

  # Renumber live objects to eliminate gaps (shrink the xref table)
  if @objects.any?{ |_, o| !o.live }
    new_id = 1
    new_objects = {}
    new_identifiers = []

    each do |obj|
      if obj.live
        obj.identifier = new_id
        new_objects[new_id] = obj
        new_identifiers << new_id
        new_id += 1
      end
    end

    @objects = new_objects
    @identifiers = new_identifiers
  end
end

#eachObject



75
76
77
78
79
# File 'lib/pdf/core/object_store.rb', line 75

def each
  @identifiers.each do |id|
    yield @objects[id]
  end
end

#import_page(input, page_num) ⇒ Object

imports all objects required to render a page from another PDF. The objects are added to the current object store, but NOT linked anywhere.

The object ID of the root Page object is returned, it’s up to the calling code to link that into the document structure somewhere. If this isn’t done the imported objects will just be removed when the store is compacted.

Imports nothing and returns nil if the requested page number doesn’t exist. page_num is 1 indexed, so 1 indicates the first page.



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/pdf/core/object_store.rb', line 147

def import_page(input, page_num)
  @loaded_objects = {}
  if template_id = indexed_template(input, page_num)
    return template_id
  end

  io = if input.respond_to?(:seek) && input.respond_to?(:read)
         input
       elsif File.file?(input.to_s)
         StringIO.new(File.binread(input.to_s))
       else
         raise ArgumentError, "input must be an IO-like object or a filename"
       end

          # unless File.file?(filename)
  #   raise ArgumentError, "#{filename} does not exist"
  # end

  hash = indexed_hash(input, io)
  ref  = hash.page_references[page_num - 1]

  if ref.nil?
    nil
  else
    index_template(input, page_num, load_object_graph(hash, ref).identifier)
  end

rescue PDF::Reader::MalformedPDFError, PDF::Reader::InvalidObjectError => e
  msg = "Error reading template file. If you are sure it's a valid PDF, it may be a bug.\n#{e.message}"
  raise PDF::Core::Errors::TemplateError, msg
rescue PDF::Reader::UnsupportedFeatureError
  msg = "Template file contains unsupported PDF features"
  raise PDF::Core::Errors::TemplateError, msg
end

#infoObject



41
42
43
# File 'lib/pdf/core/object_store.rb', line 41

def info
  @objects[@info]
end

#object_id_for_page(k) ⇒ Object

returns the object ID for a particular page in the document. Pages are indexed starting at 1 (not 0!).

object_id_for_page(1)
=> 5
object_id_for_page(10)
=> 87
object_id_for_page(-11)
=> 17


129
130
131
132
133
# File 'lib/pdf/core/object_store.rb', line 129

def object_id_for_page(k)
  k -= 1 if k > 0
  flat_page_ids = get_page_objects(pages).flatten
  flat_page_ids[k]
end

#page_countObject



53
54
55
# File 'lib/pdf/core/object_store.rb', line 53

def page_count
  pages.data[:Count]
end

#pagesObject



49
50
51
# File 'lib/pdf/core/object_store.rb', line 49

def pages
  root.data[:Pages]
end

#push(*args, &block) ⇒ Object Also known as: <<

Adds the given reference to the store and returns the reference object. If the object provided is not a PDF::Core::Reference, one is created from the arguments provided.



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/pdf/core/object_store.rb', line 61

def push(*args, &block)
  reference = if args.first.is_a?(PDF::Core::Reference)
    args.first
  else
    PDF::Core::Reference.new(*args, &block)
  end

  @objects[reference.identifier] = reference
  @identifiers << reference.identifier
  reference
end

#ref(data, &block) ⇒ Object



37
38
39
# File 'lib/pdf/core/object_store.rb', line 37

def ref(data, &block)
  push(size + 1, data, &block)
end

#rootObject



45
46
47
# File 'lib/pdf/core/object_store.rb', line 45

def root
  @objects[@root]
end

#sizeObject Also known as: length



85
86
87
# File 'lib/pdf/core/object_store.rb', line 85

def size
  @identifiers.size
end