class PDF::Core::Renderer

Attributes

state[R]

Public Class Methods

new(state) click to toggle source
# File lib/pdf/core/renderer.rb, line 8
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

Public Instance Methods

add_content(str) click to toggle source

Appends a raw string to the current page content.

# 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
# File lib/pdf/core/renderer.rb, line 57
def add_content(str)
  save_graphics_state if graphic_state.nil?
  state.page.content << str << "\n"
end
before_render(&block) click to toggle source

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

# File lib/pdf/core/renderer.rb, line 78
def before_render(&block)
  state.before_render_callbacks << block
end
close_graphics_state() click to toggle source
# File lib/pdf/core/renderer.rb, line 237
def close_graphics_state
  add_content 'Q'
end
compression_enabled?() click to toggle source

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

# File lib/pdf/core/renderer.rb, line 253
def compression_enabled?
  state.compress
end
deref(obj) click to toggle source

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 Prawn::Reference, wrap it in deref().

# File lib/pdf/core/renderer.rb, line 44
def deref(obj)
  obj.is_a?(PDF::Core::Reference) ? obj.data : obj
end
finalize_all_page_contents() click to toggle source
# File lib/pdf/core/renderer.rb, line 139
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) click to toggle source

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

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

# File lib/pdf/core/renderer.rb, line 134
def go_to_page(page_number)
  @page_number = page_number
  state.page = state.pages[page_number - 1]
end
graphic_stack() click to toggle source
# File lib/pdf/core/renderer.rb, line 268
def graphic_stack
  state.page.stack
end
graphic_state() click to toggle source
# File lib/pdf/core/renderer.rb, line 272
def graphic_state
  save_graphics_state unless graphic_stack.current_state
  graphic_stack.current_state
end
min_version(min) click to toggle source

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.

# File lib/pdf/core/renderer.rb, line 153
def min_version(min)
  state.version = min if min > state.version
end
names() click to toggle source

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

# File lib/pdf/core/renderer.rb, line 66
def names
  state.store.root.data[:Names] ||= ref!(Type: :Names)
end
names?() click to toggle source

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

# File lib/pdf/core/renderer.rb, line 72
def names?
  state.store.root.data[:Names]
end
on_page_create(&block) click to toggle source

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

# File lib/pdf/core/renderer.rb, line 84
def on_page_create(&block)
  state.on_page_create_callback =
    if block_given?
      block
    end
end
open_graphics_state() click to toggle source
# File lib/pdf/core/renderer.rb, line 233
def open_graphics_state
  add_content 'q'
end
page_count() click to toggle source
# File lib/pdf/core/renderer.rb, line 125
def page_count
  state.page_count
end
ref(data) click to toggle source

Creates a new Reference and adds it to the Document’s object list. The data argument is anything that Prawn.pdf_object() can convert.

Returns the identifier which points to the reference in the ObjectStore

# File lib/pdf/core/renderer.rb, line 24
def ref(data)
  ref!(data).identifier
end
ref!(data) click to toggle source

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

# File lib/pdf/core/renderer.rb, line 36
def ref!(data)
  state.store.ref(data)
end
render(output = StringIO.new) click to toggle source

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

# File lib/pdf/core/renderer.rb, line 160
def render(output = StringIO.new)
  if output.instance_of?(StringIO)
    output.set_encoding(::Encoding::ASCII_8BIT)
  end
  finalize_all_page_contents

  render_header(output)
  render_body(output)
  render_xref(output)
  render_trailer(output)
  if output.instance_of?(StringIO)
    str = output.string
    str.force_encoding(::Encoding::ASCII_8BIT)
    str
  end
end
render_body(output) click to toggle source

Write out the PDF Body, as per spec 3.4.2

# File lib/pdf/core/renderer.rb, line 199
def render_body(output)
  state.render_body(output)
end
render_file(filename) click to toggle source

Renders the PDF document to file.

pdf.render_file 'foo.pdf'
# File lib/pdf/core/renderer.rb, line 181
def render_file(filename)
  File.open(filename, 'wb') { |f| render(f) }
end
render_header(output) click to toggle source

Write out the PDF Header, as per spec 3.4.1

# File lib/pdf/core/renderer.rb, line 187
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) click to toggle source

Write out the PDF Trailer, as per spec 3.4.4

# File lib/pdf/core/renderer.rb, line 218
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) click to toggle source

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

# File lib/pdf/core/renderer.rb, line 205
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_state() click to toggle source

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

# File lib/pdf/core/renderer.rb, line 259
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) { || ... } click to toggle source
# File lib/pdf/core/renderer.rb, line 241
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 = {}) click to toggle source
# File lib/pdf/core/renderer.rb, line 91
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