Ruport::Formatter::PDF

This class provides PDF output for Ruport's Table, Group, and Grouping renderers. It wraps Austin Ziegler's PDF::Writer to provide a higher level interface and provides a number of helpers designed to make generating PDF reports much easier. You will typically want to build subclasses of this formatter to customize it as needed.

Many methods forward options to PDF::Writer, so you may wish to consult its API docs.

Rendering Options

General:
  * paper_size  #=> "LETTER"
  * paper_orientation #=> :portrait

Text:
  * text_format (sets options to be passed to add_text by default)  

Table:
  * table_format (a hash that can take any of the options available
      to PDF::SimpleTable)
  * table_format[:maximum_width] #=> 500   

Grouping:
  * style (:inline,:justified,:separated,:offset)

Attributes

pdf_writer[W]

Public Class Methods

new() click to toggle source
# File lib/ruport/formatter/pdf.rb, line 91
def initialize
  Ruport.quiet do   
    require "pdf/writer"
    require "pdf/simpletable"
  end
end

Public Instance Methods

add_text(text, format_opts={}) click to toggle source

Call PDF::Writer#text with the given arguments, using text_format defaults, if they are defined.

Example:

options.text_format { :font_size => 14 }

add_text("Hello Joe") #renders at 14pt
add_text("Hello Mike",:font_size => 16) # renders at 16pt
# File lib/ruport/formatter/pdf.rb, line 172
def add_text(text, format_opts={})
  format_opts = text_format.merge(format_opts) if text_format
  pdf_writer.text(text, format_opts)
end
apply_template() click to toggle source

Hook for setting available options using a template. See the template documentation for the available options and their format.

# File lib/ruport/formatter/pdf.rb, line 100
def apply_template
  apply_page_format_template(template.page_format)
  apply_text_format_template(template.text_format)
  apply_table_format_template(template.table_format)
  apply_column_format_template(template.column_format)
  apply_heading_format_template(template.heading_format)
  apply_grouping_format_template(template.grouping_format)
end
build_group_body() click to toggle source

Renders the group as a table for Renderer::Group.

# File lib/ruport/formatter/pdf.rb, line 138
def build_group_body
  render_table data, options.to_hash.merge(:formatter => pdf_writer)
end
build_group_header() click to toggle source

Generates a header with the group name for Renderer::Group.

# File lib/ruport/formatter/pdf.rb, line 133
def build_group_header
  pad(10) { add_text data.name.to_s, :justification => :center }
end
build_grouping_body() click to toggle source

Determines which style to use and renders the main body for Renderer::Grouping.

# File lib/ruport/formatter/pdf.rb, line 144
def build_grouping_body 
  case style
  when :inline
    render_inline_grouping(options.to_hash.merge(:formatter => pdf_writer,
        :skip_finalize_table => true))
  when :justified, :separated
    render_justified_or_separated_grouping
  when :offset
    render_offset_grouping
  else
    raise NotImplementedError, "Unknown style"
  end
end
build_table_body() click to toggle source

Calls the draw_table method.

# File lib/ruport/formatter/pdf.rb, line 121
def build_table_body
  draw_table(data)
end
center_image_in_box(path, image_opts={}) click to toggle source
  • If the image is bigger than the box, it will be scaled down until it fits.

  • If the image is smaller than the box, it won't be resized.

options:

  • :x: left bound of box

  • :y: bottom bound of box

  • :width: width of box

  • :height: height of box

# File lib/ruport/formatter/pdf.rb, line 192
def center_image_in_box(path, image_opts={}) 
  x = image_opts[:x]
  y = image_opts[:y]
  width = image_opts[:width]
  height = image_opts[:height]
  info = ::PDF::Writer::Graphics::ImageInfo.new(File.open(path, "rb"))

  # reduce the size of the image until it fits into the requested box
  img_width, img_height =
    fit_image_in_box(info.width,width,info.height,height)
  
  # if the image is smaller than the box, calculate the white space buffer
  x, y = add_white_space(x,y,img_width,width,img_height,height)

  pdf_writer.add_image_from_file(path, x, y, img_width, img_height) 
end
draw_table(table_data, format_opts={}) click to toggle source

Draws a PDF::SimpleTable using the given data (usually a Data::Table). Takes all the options you can set on a PDF::SimpleTable object, see the PDF::Writer API docs for details, or check our quick reference at:

stonecode.svnrepository.com/ruport/trac.cgi/wiki/PdfWriterQuickRef

# File lib/ruport/formatter/pdf.rb, line 315
def draw_table(table_data, format_opts={})
  m = "PDF Formatter requires column_names to be defined"
  raise FormatterError, m if table_data.column_names.empty?
  
  table_data.rename_columns { |c| c.to_s } 
  
  if table_format
    format_opts = Marshal.load(Marshal.dump(table_format.merge(format_opts))) 
  end
    
  old = pdf_writer.font_size
  
  ::PDF::SimpleTable.new do |table| 
    table.extend(PDFSimpleTableOrderingPatch)             
    table.maximum_width = 500
    table.column_order  = table_data.column_names
    table.data = table_data
    table.data = [{}] if table.data.empty?                                                 
    apply_pdf_table_column_opts(table,table_data,format_opts)

    format_opts.each {|k,v| table.send("#{k}=", v) }  
    table.render_on(pdf_writer)
  end                                              
  
  pdf_writer.font_size = old
end
finalize_grouping() click to toggle source

Calls render_pdf.

# File lib/ruport/formatter/pdf.rb, line 159
def finalize_grouping
  render_pdf
end
finalize_table() click to toggle source

Appends the results of PDF::Writer#render to output for your pdf_writer object.

# File lib/ruport/formatter/pdf.rb, line 128
def finalize_table
  render_pdf unless options.skip_finalize_table
end
move_cursor(n) click to toggle source

Adds n to pdf_writer.y, moving the vertical drawing position in the document.

# File lib/ruport/formatter/pdf.rb, line 269
def move_cursor(n) 
  pdf_writer.y += n
end
move_cursor_to(n) click to toggle source

Moves the cursor to a specific y coordinate in the document.

# File lib/ruport/formatter/pdf.rb, line 274
def move_cursor_to(n)
  pdf_writer.y = n
end
pad(y,&block) click to toggle source

Adds a specified amount of whitespace above and below the code in your block. For example, if you want to surround the top and bottom of a line of text with 5 pixels of whitespace:

pad(5) { add_text "This will be padded top and bottom" }
# File lib/ruport/formatter/pdf.rb, line 283
def pad(y,&block)
  move_cursor(-y)
  block.call
  move_cursor(-y)
end
pad_bottom(y,&block) click to toggle source

Adds a specified amount of whitespace below the code in your block. For example, if you want to add a 10 pixel buffer to the bottom of a line of text:

pad_bottom(10) { add_text "This will be padded on bottom" }
# File lib/ruport/formatter/pdf.rb, line 304
def pad_bottom(y,&block)
  block.call
  move_cursor(-y)
end
pad_top(y,&block) click to toggle source

Adds a specified amount of whitespace above the code in your block. For example, if you want to add a 10 pixel buffer to the top of a line of text:

pad_top(10) { add_text "This will be padded on top" }
# File lib/ruport/formatter/pdf.rb, line 294
def pad_top(y,&block)
  move_cursor(-y)
  block.call
end
pdf_writer() click to toggle source

Returns the current PDF::Writer object or creates a new one if it has not been set yet.

# File lib/ruport/formatter/pdf.rb, line 112
def pdf_writer
  @pdf_writer ||= options.formatter ||
    ::PDF::Writer.new( :paper => paper_size || "LETTER",
          :orientation => paper_orientation || :portrait)
  @pdf_writer.extend(PDFWriterMemoryPatch)
end
render_pdf() click to toggle source

Calls PDF::Writer#render and appends to output.

# File lib/ruport/formatter/pdf.rb, line 178
def render_pdf
  output << pdf_writer.render
end
rounded_text_box(text) click to toggle source

Draws some text on the canvas, surrounded by a box with rounded corners.

Yields an OpenStruct which options can be defined on.

Example:

rounded_text_box(options.text) do |o|
  o.radius = 5
  o.width     = options.width  || 400
  o.height    = options.height || 130
  o.font_size = options.font_size || 12
  o.heading   = options.heading

  o.x = pdf_writer.absolute_x_middle - o.width/2
  o.y = 300
end
# File lib/ruport/formatter/pdf.rb, line 226
def rounded_text_box(text)
  opts = OpenStruct.new
  yield(opts)
  
  resize_text_to_box(text, opts)
  
  pdf_writer.save_state
  draw_box(opts.x, opts.y, opts.width, opts.height, opts.radius, 
    opts.fill_color, opts.stroke_color)
  add_text_with_bottom_border(opts.heading, opts.x, opts.y,
    opts.width, opts.font_size) if opts.heading
  pdf_writer.restore_state

  start_position = opts.heading ? opts.y - 20 : opts.y
  draw_text(text, :y              => start_position,
                  :left           => opts.x,
                  :right          => opts.x + opts.width,
                  :justification  => opts.justification || :center,
                  :font_size      => opts.font_size)
  move_cursor_to(opts.y - opts.height)
end
save_output(filename) click to toggle source

Save the output to a file.

# File lib/ruport/formatter/pdf.rb, line 343
def save_output(filename)
  File.open(filename,"wb") {|f| f << output }
end
watermark(imgpath) click to toggle source

Adds an image to every page. The color and size won't be modified, but it will be centered.

# File lib/ruport/formatter/pdf.rb, line 251
def watermark(imgpath)
  x = pdf_writer.absolute_left_margin
  y = pdf_writer.absolute_bottom_margin
  width = pdf_writer.absolute_right_margin - x
  height = pdf_writer.absolute_top_margin - y

  pdf_writer.open_object do |wm|
    pdf_writer.save_state
    center_image_in_box(imgpath, :x => x, :y => y,
      :width => width, :height => height)
    pdf_writer.restore_state
    pdf_writer.close_object
    pdf_writer.add_object(wm, :all_pages)
  end
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.