Class: HexaPDF::Revision
- Inherits:
-
Object
- Object
- HexaPDF::Revision
- Includes:
- Enumerable
- Defined in:
- lib/hexapdf/revision.rb
Overview
Embodies one revision of a PDF file, either the initial version or an incremental update.
The purpose of a Revision object is to manage the objects and the trailer of one revision. These objects can either be added manually or loaded from a cross-reference section or stream. Since a PDF file can be incrementally updated, it can have multiple revisions.
If a revision doesn’t have an associated cross-reference section, it wasn’t created from a PDF file.
See: PDF1.7 s7.5.6, Revisions
Instance Attribute Summary collapse
-
#loader ⇒ Object
The callable object responsible for loading objects.
-
#trailer ⇒ Object
readonly
The trailer dictionary.
Instance Method Summary collapse
-
#add(obj) ⇒ Object
:call-seq: revision.add(obj) -> obj.
-
#delete(ref_or_oid, mark_as_free: true) ⇒ Object
:call-seq: revision.delete(ref, mark_as_free: true) revision.delete(oid, mark_as_free: true).
-
#each ⇒ Object
:call-seq: revision.each {|obj| block } -> revision revision.each -> Enumerator.
-
#initialize(trailer, xref_section: nil, loader: nil, &block) ⇒ Revision
constructor
:call-seq: Revision.new(trailer) -> revision Revision.new(trailer, xref_section: section, loader: loader) -> revision Revision.new(trailer, xref_section: section) {|entry| block } -> revision.
-
#next_free_oid ⇒ Object
Returns the next free object number for adding an object to this revision.
-
#object(ref) ⇒ Object
:call-seq: revision.object(ref) -> obj or nil revision.object(oid) -> obj or nil.
-
#object?(ref) ⇒ Boolean
:call-seq: revision.object?(ref) -> true or false revision.object?(oid) -> true or false.
Constructor Details
#initialize(trailer, xref_section: nil, loader: nil, &block) ⇒ Revision
:call-seq:
Revision.new(trailer) -> revision
Revision.new(trailer, xref_section: section, loader: loader) -> revision
Revision.new(trailer, xref_section: section) {|entry| block } -> revision
Creates a new Revision object.
Options:
- xref_section
-
An XRefSection object that contains information on how to load objects. If this option is specified, then a
loader
or a block also needs to be specified! - loader
-
The loader object needs to respond to
call
taking a cross-reference entry and returning the loaded object. If noxref_section
is supplied, this value is not used.If a block is given, it is used instead of the loader object.
77 78 79 80 81 82 |
# File 'lib/hexapdf/revision.rb', line 77 def initialize(trailer, xref_section: nil, loader: nil, &block) @trailer = trailer @loader = xref_section && (block || loader) @xref_section = xref_section || XRefSection.new @objects = HexaPDF::Utils::ObjectHash.new end |
Instance Attribute Details
#loader ⇒ Object
The callable object responsible for loading objects.
57 58 59 |
# File 'lib/hexapdf/revision.rb', line 57 def loader @loader end |
#trailer ⇒ Object (readonly)
The trailer dictionary
54 55 56 |
# File 'lib/hexapdf/revision.rb', line 54 def trailer @trailer end |
Instance Method Details
#add(obj) ⇒ Object
:call-seq:
revision.add(obj) -> obj
Adds the given object (needs to be a HexaPDF::Object) to this revision and returns it.
135 136 137 138 139 140 141 142 |
# File 'lib/hexapdf/revision.rb', line 135 def add(obj) if object?(obj.oid) raise HexaPDF::Error, "A revision can only contain one object with a given object number" elsif !obj.indirect? raise HexaPDF::Error, "A revision can only contain indirect objects" end add_without_check(obj) end |
#delete(ref_or_oid, mark_as_free: true) ⇒ Object
:call-seq:
revision.delete(ref, mark_as_free: true)
revision.delete(oid, mark_as_free: true)
Deletes the object specified either by reference or by object number from this revision by marking it as free.
If the mark_as_free
option is set to false
, the object is really deleted.
152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/hexapdf/revision.rb', line 152 def delete(ref_or_oid, mark_as_free: true) return unless object?(ref_or_oid) ref_or_oid = ref_or_oid.oid if ref_or_oid.respond_to?(:oid) obj = object(ref_or_oid) obj.data.value = nil if mark_as_free add_without_check(HexaPDF::Object.new(nil, oid: obj.oid, gen: obj.gen)) else @xref_section.delete(ref_or_oid) @objects.delete(ref_or_oid) end end |
#each ⇒ Object
:call-seq:
revision.each {|obj| block } -> revision
revision.each -> Enumerator
Calls the given block once for every object of the revision.
Objects that are loadable via an associated cross-reference section but are currently not, are loaded automatically.
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/hexapdf/revision.rb', line 174 def each return to_enum(__method__) unless block_given? if defined?(@all_objects_loaded) @objects.each {|_oid, _gen, data| yield(data)} else seen = {} @objects.each {|oid, _gen, data| seen[oid] = true; yield(data)} @xref_section.each do |oid, _gen, data| next if seen.key?(oid) yield(@objects[oid] || load_object(data)) end @all_objects_loaded = true end self end |
#next_free_oid ⇒ Object
Returns the next free object number for adding an object to this revision.
85 86 87 |
# File 'lib/hexapdf/revision.rb', line 85 def next_free_oid ((a = @xref_section.max_oid) < (b = @objects.max_oid) ? b : a) + 1 end |
#object(ref) ⇒ Object
:call-seq:
revision.object(ref) -> obj or nil
revision.object(oid) -> obj or nil
Returns the object for the given reference or object number if such an object is available in this revision, or nil
otherwise.
If the revision has an entry but one that is pointing to a free entry in the cross-reference section, an object representing PDF null is returned.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/hexapdf/revision.rb', line 98 def object(ref) if ref.respond_to?(:oid) oid = ref.oid gen = ref.gen else oid = ref end if @objects.entry?(oid, gen) @objects[oid, gen] elsif (xref_entry = @xref_section[oid, gen]) load_object(xref_entry) else nil end end |
#object?(ref) ⇒ Boolean
:call-seq:
revision.object?(ref) -> true or false
revision.object?(oid) -> true or false
Returns true
if the revision contains an object
-
for the exact reference if the argument responds to :oid, or else
-
for the given object number.
123 124 125 126 127 128 129 |
# File 'lib/hexapdf/revision.rb', line 123 def object?(ref) if ref.respond_to?(:oid) @objects.entry?(ref.oid, ref.gen) || @xref_section.entry?(ref.oid, ref.gen) else @objects.entry?(ref) || @xref_section.entry?(ref) end end |