Class: PDF::Core::Renderer

Inherits:
Object
  • Object
show all
Defined in:
lib/pdf/core/renderer.rb

Overview

Document renderer serializes document into its binary representation.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(state) ⇒ Renderer

Returns a new instance of Renderer.

Parameters:



10
11
12
13
14
15
16
17
# File 'lib/pdf/core/renderer.rb', line 10

def initialize(state)
  @state = state
  @state.populate_pages_from_store(self)

  min_version(state.store.min_version) if state.store.min_version

  @page_number = 0
end

Instance Attribute Details

#statePDF::Core::DocumentState (readonly)

Document state



21
22
23
# File 'lib/pdf/core/renderer.rb', line 21

def state
  @state
end

Instance Method Details

#add_content(str) ⇒ void

This method returns an undefined value.

Appends a raw string to the current page content.

Examples:

Raw line drawing example

x1, y1, x2, y2 = 100, 500, 300, 550

pdf.add_content("#{PDF::Core.real_params([x1, y1])} m")   # move
pdf.add_content("#{PDF::Core.real_params([ x2, y2 ])} l") # draw path
pdf.add_content('S') # stroke

Parameters:

  • str (String)


66
67
68
69
# File 'lib/pdf/core/renderer.rb', line 66

def add_content(str)
  save_graphics_state if graphic_state.nil?
  state.page.content << str << "\n"
end

#before_render {|document_state| ... } ⇒ void

This method returns an undefined value.

Defines a block to be called just before the document is rendered.

Yield Parameters:



92
93
94
# File 'lib/pdf/core/renderer.rb', line 92

def before_render(&block)
  state.before_render_callbacks << block
end

#close_graphics_statevoid

This method returns an undefined value.

Close current graphic state (restore previous) in the content stream.



290
291
292
# File 'lib/pdf/core/renderer.rb', line 290

def close_graphics_state
  add_content('Q')
end

#compression_enabled?Boolean

Returns true if content streams will be compressed before rendering, false otherwise

Returns:

  • (Boolean)


316
317
318
# File 'lib/pdf/core/renderer.rb', line 316

def compression_enabled?
  state.compress
end

#deref(obj) ⇒ any

At any stage in the object tree an object can be replaced with an indirect reference. To get access to the object safely, regardless of if it’s hidden behind a PDF::Core::Reference, wrap it in ‘deref()`.

Parameters:

Returns:

  • (any)


51
52
53
# File 'lib/pdf/core/renderer.rb', line 51

def deref(obj)
  obj.is_a?(PDF::Core::Reference) ? obj.data : obj
end

#finalize_all_page_contentsvoid

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Finalize all pages



166
167
168
169
170
171
172
173
174
# File 'lib/pdf/core/renderer.rb', line 166

def finalize_all_page_contents
  (1..page_count).each do |i|
    go_to_page(i)
    while graphic_stack.present?
      restore_graphics_state
    end
    state.page.finalize
  end
end

#go_to_page(page_number) ⇒ void

This method returns an undefined value.

Re-opens the page with the given (1-based) page number so that you can draw on it.

Parameters:

  • page_number (Integer)

See Also:

  • Prawn::Document#number_pages for a sample usage of this capability.


157
158
159
160
# File 'lib/pdf/core/renderer.rb', line 157

def go_to_page(page_number)
  @page_number = page_number
  state.page = state.pages[page_number - 1]
end

#graphic_stackPDF::Core::GraphicStateStack

Graphic state stack of the current document.



336
337
338
# File 'lib/pdf/core/renderer.rb', line 336

def graphic_stack
  state.page.stack
end

#graphic_statePDF::Core::GraphicState

Current graphic state



343
344
345
346
# File 'lib/pdf/core/renderer.rb', line 343

def graphic_state
  save_graphics_state unless graphic_stack.current_state
  graphic_stack.current_state
end

#min_version(min) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Raise the PDF version of the file we’re going to generate. A private method, designed for internal use when the user adds a feature to their document that requires a particular version.

Parameters:

  • min (Float)


183
184
185
# File 'lib/pdf/core/renderer.rb', line 183

def min_version(min)
  state.version = min if min > state.version
end

#namesPDF::Core::Reference<Hash>

The Name dictionary for this document. It is lazily initialized, so that documents that do not need a name dictionary do not incur the additional overhead.

Returns:

See Also:

  • PDF 1.7 spec, section 3.6.3 Name Dictionary


77
78
79
# File 'lib/pdf/core/renderer.rb', line 77

def names
  state.store.root.data[:Names] ||= ref!(Type: :Names)
end

#names?Boolean

Returns true if the Names dictionary is in use for this document.

Returns:

  • (Boolean)


84
85
86
# File 'lib/pdf/core/renderer.rb', line 84

def names?
  state.store.root.data.key?(:Names)
end

#on_page_create {|document_state| ... } ⇒ void

This method returns an undefined value.

Defines a block to be called just before a new page is started.

Yield Parameters:



100
101
102
# File 'lib/pdf/core/renderer.rb', line 100

def on_page_create(&block)
  state.on_page_create_callback = block
end

#open_graphics_statevoid

This method returns an undefined value.

Open (save) current graphic state in the content stream.



283
284
285
# File 'lib/pdf/core/renderer.rb', line 283

def open_graphics_state
  add_content('q')
end

#page_countInteger

Number of pages in the document.

Returns:

  • (Integer)


147
148
149
# File 'lib/pdf/core/renderer.rb', line 147

def page_count
  state.page_count
end

#ref(data) ⇒ Integer

Creates a new Reference and adds it to the Document’s object list.

Parameters:

Returns:

  • (Integer)

    the identifier of the reference



27
28
29
# File 'lib/pdf/core/renderer.rb', line 27

def ref(data)
  ref!(data).identifier
end

#ref!(data) ⇒ PDF::Core::Reference

Like #ref, but returns the actual reference instead of its identifier.

While you can use this to build up nested references within the object tree, it is recommended to persist only identifiers, and then provide helper methods to look up the actual references in the ObjectStore if needed. If you take this approach, ‘Document::Snapshot` will probably work with your extension.

Parameters:

Returns:



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

def ref!(data)
  state.store.ref(data)
end

#render(output = nil) ⇒ String

Renders the PDF document to string. Pass an open file descriptor to render to file.

Parameters:

  • output (#<<) (defaults to: nil)

Returns:

  • (String)


192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/pdf/core/renderer.rb', line 192

def render(output = nil)
  buffer = StringIO.new.binmode

  finalize_all_page_contents

  render_header(buffer)
  render_body(buffer)
  render_xref(buffer)
  render_trailer(buffer)

  if output.respond_to?(:<<)
    output << buffer.string
  end

  buffer.string
end

#render_body(output) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Write out the PDF Body, as per spec 3.4.2

Parameters:

  • output ((#<<, #size))


240
241
242
# File 'lib/pdf/core/renderer.rb', line 240

def render_body(output)
  state.render_body(output)
end

#render_file(filename) ⇒ void

This method returns an undefined value.

Renders the PDF document to file.

Examples:

pdf.render_file 'foo.pdf'

Parameters:

  • filename (String, #to_path, Integer)


216
217
218
# File 'lib/pdf/core/renderer.rb', line 216

def render_file(filename)
  File.open(filename, 'wb') { |f| render(f) }
end

#render_header(output) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Write out the PDF Header, as per spec 3.4.1

Parameters:

  • output (#<<)


225
226
227
228
229
230
231
232
233
# File 'lib/pdf/core/renderer.rb', line 225

def render_header(output)
  state.before_render_actions(self)

  # pdf version
  output << "%PDF-#{state.version}\n"

  # 4 binary chars, as recommended by the spec
  output << "%\xFF\xFF\xFF\xFF\n"
end

#render_trailer(output) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Write out the PDF Trailer, as per spec 3.4.4

Parameters:

  • output (#<<)


265
266
267
268
269
270
271
272
273
274
275
276
277
278
# File 'lib/pdf/core/renderer.rb', line 265

def render_trailer(output)
  trailer_hash = {
    Size: state.store.size + 1,
    Root: state.store.root,
    Info: state.store.info,
  }
  trailer_hash.merge!(state.trailer) if state.trailer

  output << "trailer\n"
  output << PDF::Core.pdf_object(trailer_hash) << "\n"
  output << "startxref\n"
  output << @xref_offset << "\n"
  output << '%%EOF' << "\n"
end

#render_xref(output) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Write out the PDF Cross Reference Table, as per spec 3.4.3

Parameters:

  • output ((#<<, #size))


249
250
251
252
253
254
255
256
257
258
# File 'lib/pdf/core/renderer.rb', line 249

def render_xref(output)
  @xref_offset = output.size
  output << "xref\n"
  output << "0 #{state.store.size + 1}\n"
  output << "0000000000 65535 f \n"
  state.store.each do |ref|
    output.printf('%<offset>010d', offset: ref.offset)
    output << " 00000 n \n"
  end
end

#restore_graphics_statevoid

This method returns an undefined value.

Pops the last saved graphics state off the graphics state stack and restores the state to those values



324
325
326
327
328
329
330
331
# File 'lib/pdf/core/renderer.rb', line 324

def restore_graphics_state
  if graphic_stack.empty?
    raise PDF::Core::Errors::EmptyGraphicStateStack,
      "\n You have reached the end of the graphic state stack"
  end
  close_graphics_state
  graphic_stack.restore_graphic_state
end

#save_graphics_state(graphic_state = nil) { ... } ⇒ void

This method returns an undefined value.

Save surrent graphic state both in the graphic state stack and in the page content stream.

If a block is given graphic state is automatically restored after the block execution.

Parameters:

Yields:



303
304
305
306
307
308
309
310
# File 'lib/pdf/core/renderer.rb', line 303

def save_graphics_state(graphic_state = nil)
  graphic_stack.save_graphic_state(graphic_state)
  open_graphics_state
  if block_given?
    yield
    restore_graphics_state
  end
end

#start_new_page(options = {}) ⇒ void

This method returns an undefined value.

Create a new page and set it current.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • :size (String, Array<Numeric>)
  • :layout (:portrait, :landscape)


110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/pdf/core/renderer.rb', line 110

def start_new_page(options = {})
  last_page = state.page
  if last_page
    last_page_size = last_page.size
    last_page_layout = last_page.layout
    last_page_margins = last_page.margins
  end

  page_options = {
    size: options[:size] || last_page_size,
    layout: options[:layout] || last_page_layout,
    margins: last_page_margins,
  }
  if last_page
    if last_page.graphic_state
      new_graphic_state = last_page.graphic_state.dup
    end

    # Erase the color space so that it gets reset on new page for fussy
    # pdf-readers
    if new_graphic_state
      new_graphic_state.color_space = {}
    end
    page_options[:graphic_state] = new_graphic_state
  end

  state.page = PDF::Core::Page.new(self, page_options)

  state.insert_page(state.page, @page_number)
  @page_number += 1

  state.on_page_create_action(self)
end