class PDF::Reader::XRef
file.
object needs to be found, the Xref table is used to find where it is stored in the
An Xref table is a map of object identifiers and byte offsets. Any time a particular
An internal PDF::Reader class that represents the Xref table in a PDF file
###############################################################################
def initialize (buffer)
###############################################################################
def initialize (buffer) @buffer = buffer @xref = {} end
def load (offset = nil)
will be loaded from there, otherwise the default offset will be located and used.
Read the xref table from the underlying buffer. If offset is specified the table
###############################################################################
def load (offset = nil) offset ||= @buffer.find_first_xref_offset @buffer.seek(offset) token = @buffer.token if token == "xref" || token == "ref" load_xref_table else raise PDF::Reader::MalformedPDFError, "xref table not found at offset #{offset} (#{token} != xref)" end end
def load_xref_table
Assumes the underlying buffer is positioned at the start of an Xref table and
###############################################################################
def load_xref_table tok_one = tok_two = nil begin # loop over all subsections of the xref table # In a well formed PDF, the 'trailer' token will indicate # the end of the table. However we need to be careful in case # we're processing a malformed pdf that is missing the trailer. loop do tok_one, tok_two = @buffer.token, @buffer.token if tok_one != "trailer" && !tok_one.match(/\d+/) raise MalformedPDFError, "PDF malformed, missing trailer after cross reference" end break if tok_one == "trailer" or tok_one.nil? objid, count = tok_one.to_i, tok_two.to_i count.times do offset = @buffer.token.to_i generation = @buffer.token.to_i state = @buffer.token store(objid, generation, offset) if state == "n" objid += 1 end end rescue EOFError => e raise MalformedPDFError, "PDF malformed, missing trailer after cross reference" end raise MalformedPDFError, "PDF malformed, trailer should be a dictionary" unless tok_two == "<<" trailer = Parser.new(@buffer, self).dictionary load(trailer['Prev'].to_i) if trailer.has_key?('Prev') trailer end
def object (ref, save_pos = true)
number
by specifying a PDF::Reader::Reference object that contains the objects ID and revision
Return a string containing the contents of an entire PDF object. The object is requested
###############################################################################
def object (ref, save_pos = true) return ref unless ref.kind_of?(Reference) pos = @buffer.pos if save_pos obj, stream = Parser.new(@buffer.seek(offset_for(ref)), self).object(ref.id, ref.gen) @buffer.seek(pos) if save_pos if stream return obj, stream else return obj end end
def offset_for (ref)
returns the byte offset for the specified PDF object.
###############################################################################
def offset_for (ref) @xref[ref.id][ref.gen] end
def store (id, gen, offset)
###############################################################################
def store (id, gen, offset) (@xref[id] ||= {})[gen] ||= offset end