Class: Pdfrb::Writer

Inherits:
Object
  • Object
show all
Defined in:
lib/pdfrb/writer.rb

Overview

Writes a Document to an IO as a complete PDF file: header, indirect objects, xref section, trailer.

Two modes:

* +write+ (default) — full rewrite; assign oids to new objects,
emit every object the document references.
* +write_incremental+ — append a new revision to an existing
byte stream. Only valid when the document was opened from an
IO; the original bytes are preserved verbatim, and a new
xref + trailer are appended with /Prev pointing back.

Constant Summary collapse

DEFAULT_VERSION =
"1.4"

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(document, io) ⇒ Writer

Returns a new instance of Writer.



19
20
21
22
23
24
25
26
27
# File 'lib/pdfrb/writer.rb', line 19

def initialize(document, io)
  @document = document
  @io = io
  @serializer = Serializer.new(
    compress_streams: document.config["writer.compress_streams"],
    compress_min_size: document.config["writer.compress_min_size"]
  )
  @xref_offsets = {} # oid -> byte offset
end

Instance Attribute Details

#documentObject (readonly)

Returns the value of attribute document.



17
18
19
# File 'lib/pdfrb/writer.rb', line 17

def document
  @document
end

#ioObject (readonly)

Returns the value of attribute io.



17
18
19
# File 'lib/pdfrb/writer.rb', line 17

def io
  @io
end

#serializerObject (readonly)

Returns the value of attribute serializer.



17
18
19
# File 'lib/pdfrb/writer.rb', line 17

def serializer
  @serializer
end

Class Method Details

.write(document, io) ⇒ Object



29
30
31
# File 'lib/pdfrb/writer.rb', line 29

def self.write(document, io)
  new(document, io).write
end

.write_incremental(document, io) ⇒ Object



33
34
35
# File 'lib/pdfrb/writer.rb', line 33

def self.write_incremental(document, io)
  new(document, io).write_incremental
end

Instance Method Details

#writeObject



37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/pdfrb/writer.rb', line 37

def write
  @io.binmode
  @io.truncate(0) if @io.respond_to?(:truncate)
  write_header
  dispatch_before_write
  each_indirect_object do |obj|
    @xref_offsets[obj.oid] = @io.pos
    @io << @serializer.serialize_indirect(obj)
  end
  xref_pos = write_xref
  write_trailer(xref_pos)
  @io.flush
  self
end

#write_incrementalObject

Append a new revision to the original byte stream. Requires the document to have been opened from an IO (so we can copy its original bytes verbatim) and the IO the writer is given is the target output.

Raises:



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/pdfrb/writer.rb', line 56

def write_incremental
  raise Pdfrb::Error, "incremental write requires a source IO" unless document.io

  @io.binmode
  # Copy the original bytes verbatim.
  document.io.seek(0, IO::SEEK_SET)
  @io << document.io.read
  dispatch_before_write
  # Emit only the modified objects.
  document.instance_variable_get(:@objects).each_value do |obj|
    next unless obj.indirect?

    @xref_offsets[obj.oid] = @io.pos
    @io << @serializer.serialize_indirect(obj)
  end
  xref_pos = write_xref(prev: previous_xref_offset)
  write_trailer(xref_pos, prev: previous_xref_offset)
  @io.flush
  self
end