Class: Prawn::Document
- Inherits:
-
Object
- Object
- Prawn::Document
- Includes:
- PageGeometry, Text, Graphics, Images
- Defined in:
- lib/prawn/document.rb,
lib/prawn/document/text.rb,
lib/prawn/graphics/cell.rb,
lib/prawn/document/table.rb,
lib/prawn/document/bounding_box.rb,
lib/prawn/document/page_geometry.rb
Defined Under Namespace
Modules: PageGeometry, Text Classes: BoundingBox, Table
Constant Summary
Constants included from PageGeometry
Constants included from Text
Text::BUILT_INS, Text::DEFAULT_FONT_SIZE
Constants included from Graphics
Instance Attribute Summary collapse
-
#margin_box ⇒ Object
Returns the value of attribute margin_box.
-
#margins ⇒ Object
readonly
Returns the value of attribute margins.
-
#page_layout ⇒ Object
readonly
Returns the value of attribute page_layout.
-
#page_size ⇒ Object
readonly
Returns the value of attribute page_size.
-
#y ⇒ Object
Returns the value of attribute y.
Class Method Summary collapse
-
.generate(filename, options = {}, &block) ⇒ Object
Creates and renders a PDF document.
Instance Method Summary collapse
-
#bounding_box(*args, &block) ⇒ Object
A bounding box serves two important purposes: * Provide bounds for flowing text, starting at a given point * Translate the origin (0,0) for graphics primitives, for the purposes of simplifying coordinate math.
-
#bounds ⇒ Object
Returns the current BoundingBox object, which is by default the box represented by the margin box.
-
#canvas(&block) ⇒ Object
A shortcut to produce a bounding box which is mapped to the document’s absolute coordinates, regardless of how things are nested or margin sizes.
-
#cell(point, options = {}) ⇒ Object
Builds and renders a Graphics::Cell.
-
#initialize(options = {}) ⇒ Document
constructor
Creates a new PDF Document.
-
#mask(*fields) ⇒ Object
:nodoc:.
-
#move_down(n) ⇒ Object
Moves down the document by n point.
-
#move_up(n) ⇒ Object
Moves up the document by n points.
-
#pad(y) ⇒ Object
Moves down the document by y, executes a block, then moves down the document by y again.
-
#pad_bottom(y) ⇒ Object
Executes a block then moves down the document.
-
#pad_top(y) ⇒ Object
Moves down the document and then executes a block.
-
#page_count ⇒ Object
Returns the number of pages in the document pdf = Prawn::Document.new pdf.page_count #=> 1 3.times { pdf.start_new_page } pdf.page_count #=> 4.
-
#render ⇒ Object
Renders the PDF document to string.
-
#render_file(filename) ⇒ Object
Renders the PDF document to file.
-
#start_new_page(options = {}) ⇒ Object
Creates and advances to a new page in the document.
-
#table(data, options = {}) ⇒ Object
Builds and renders a Document::Table object from raw data.
Methods included from PageGeometry
Methods included from Text
#font, #font_metrics, #font_size, #font_size!, #text
Methods included from Images
Methods included from Graphics
#circle_at, #curve, #curve_to, #ellipse_at, #fill, #fill_and_stroke, #fill_color, #horizontal_line, #horizontal_rule, #line, #line_to, #line_width, #line_width=, #method_missing, #move_to, #polygon, #rectangle, #stroke, #stroke_color, #vertical_line_at
Constructor Details
#initialize(options = {}) ⇒ Document
Creates a new PDF Document. The following options are available:
:page_size-
One of the Document::PageGeometry::SIZES [LETTER]
:page_layout-
Either
:portraitor:landscape :on_page_start-
Optional proc run at each page start
:on_page_stop-
Optional proc run at each page stop
:left_margin-
Sets the left margin in points [ 0.5 inch]
:right_margin-
Sets the right margin in points [ 0.5 inch]
:top_margin-
Sets the top margin in points [ 0.5 inch]
:bottom_margin-
Sets the bottom margin in points [0.5 inch]
:skip_page_creation-
Creates a document without starting the first page [false]
# New document, US Letter paper, portrait orientation
pdf = Prawn::Document.new
# New document, A4 paper, landscaped
pdf = Prawn::Document.new(:page_size => "A4", :page_layout => :landscape)
# New document, draws a line at the start of each new page
pdf = Prawn::Document.new(:on_page_start =>
lambda { |doc| doc.line [0,100], [300,100] } )
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/prawn/document.rb', line 74 def initialize(={}) @objects = [] @info = ref(:Creator => "Prawn", :Producer => "Prawn") @pages = ref(:Type => :Pages, :Count => 0, :Kids => []) @root = ref(:Type => :Catalog, :Pages => @pages) @page_start_proc = [:on_page_start] @page_stop_proc = [:on_page_end] @page_size = [:page_size] || "LETTER" @page_layout = [:page_layout] || :portrait @margins = { :left => [:left_margin] || 36, :right => [:right_margin] || 36, :top => [:top_margin] || 36, :bottom => [:bottom_margin] || 36 } generate_margin_box @bounding_box = @margin_box start_new_page unless [:skip_page_creation] end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Prawn::Graphics
Instance Attribute Details
#margin_box ⇒ Object
Returns the value of attribute margin_box.
23 24 25 |
# File 'lib/prawn/document.rb', line 23 def margin_box @margin_box end |
#margins ⇒ Object (readonly)
Returns the value of attribute margins.
24 25 26 |
# File 'lib/prawn/document.rb', line 24 def margins @margins end |
#page_layout ⇒ Object (readonly)
Returns the value of attribute page_layout.
24 25 26 |
# File 'lib/prawn/document.rb', line 24 def page_layout @page_layout end |
#page_size ⇒ Object (readonly)
Returns the value of attribute page_size.
24 25 26 |
# File 'lib/prawn/document.rb', line 24 def page_size @page_size end |
#y ⇒ Object
Returns the value of attribute y.
23 24 25 |
# File 'lib/prawn/document.rb', line 23 def y @y end |
Class Method Details
.generate(filename, options = {}, &block) ⇒ Object
Creates and renders a PDF document.
The block argument is necessary only when you need to make use of a closure.
# Using implicit block form and rendering to a file
Prawn::Document.generate "foo.pdf" do
font "Times-Roman"
text "Hello World", :at => [200,720], :size => 32
end
# Using explicit block form and rendering to a file
content = "Hello World"
Prawn::Document.generate "foo.pdf" do |pdf|
pdf.font "Times-Roman"
pdf.text content, :at => [200,720], :size => 32
end
45 46 47 48 49 |
# File 'lib/prawn/document.rb', line 45 def self.generate(filename,={},&block) pdf = Prawn::Document.new() block.arity < 1 ? pdf.instance_eval(&block) : yield(pdf) pdf.render_file(filename) end |
Instance Method Details
#bounding_box(*args, &block) ⇒ Object
A bounding box serves two important purposes:
-
Provide bounds for flowing text, starting at a given point
-
Translate the origin (0,0) for graphics primitives, for the purposes
of simplifying coordinate math.
When flowing text, the usage of a bounding box is simple. Text will begin at the point specified, flowing the width of the bounding box. After the block exits, the text drawing position will be moved to the bottom of the bounding box (y - height). Currently, Prawn allows text to overflow the bottom border of the bounding box, so it is up to the user to ensure the text provided will fit within the height of the bounding box.
pdf.bounding_box(, :width => 100, :height => 300) do pdf.text “This text will flow in a very narrow box starting” + “from [100,500]. The pointer will then be moved to [100,200]” + “and return to the margin_box” end
When translating coordinates, the idea is to allow the user to draw relative to the origin, and then translate their drawing to a specified area of the document, rather than adjust all their drawing coordinates to match this new region.
Take for example two triangles which share one point, drawn from the origin:
pdf.polygon [0,250], [0,0], [150,100]
pdf.polygon [100,0], [150,100], [200,0]
It would be easy enough to translate these triangles to another point, e.g [200,200]
pdf.polygon [200,450], [200,200], [350,300]
pdf.polygon [300,200], [350,300], [400,200]
However, each time you want to move the drawing, you’d need to alter every point in the drawing calls, which as you might imagine, can become tedious.
If instead, we think of the drawing as being bounded by a box, we can see that the image is 200 points wide by 250 points tall.
To translate it to a new origin, we simply select a point at (x,y+height)
Using the [200,200] example:
pdf.bounding_box([200,450], :width => 200, :height => 250) do
pdf.polygon [0,250], [0,0], [150,100]
pdf.polygon [100,0], [150,100], [200,0]
end
Notice that the drawing is still relative to the origin. If we want to move this drawing around the document, we simply need to recalculate the top-left corner of the rectangular bounding-box, and all of our graphics calls remain unmodified.
By default, bounding boxes are specified relative to the document’s margin_box (which is itself a bounding box). You can also nest bounding boxes, allowing you to build components which are relative to each other
pdf.bouding_box(, :width => 200, :height => 250) do
pdf.bounding_box([50,200], :width => 50, :height => 50) do
# a 50x50 bounding box that starts 50 pixels left and 50 pixels down
# the parent bounding box.
end
end
If you wish to position the bounding boxes at absolute coordinates rather than relative to the margins or other bounding boxes, you can use canvas()
pdf.canvas do
pdf.bounding_box([200,450], :width => 200, :height => 250) do
# positioned at 'real' (200,450)
end
end
Of course, if you use canvas, you will be responsible for ensuring that you remain within the printable area of your document.
86 87 88 89 90 91 92 93 94 95 |
# File 'lib/prawn/document/bounding_box.rb', line 86 def bounding_box(*args, &block) init_bounding_box(block) do |parent_box| # Offset to relative positions top_left = args[0] top_left[0] += parent_box.absolute_left top_left[1] += parent_box.absolute_bottom @bounding_box = BoundingBox.new(self, *args) end end |
#bounds ⇒ Object
Returns the current BoundingBox object, which is by default the box represented by the margin box. When called from within a bounding_box block, the box defined by that call will be used.
175 176 177 |
# File 'lib/prawn/document.rb', line 175 def bounds @bounding_box end |
#canvas(&block) ⇒ Object
A shortcut to produce a bounding box which is mapped to the document’s absolute coordinates, regardless of how things are nested or margin sizes.
pdf.canvas do
pdf.line pdf.bounds.bottom_left, pdf.bounds.top_right
end
104 105 106 107 108 109 110 111 |
# File 'lib/prawn/document/bounding_box.rb', line 104 def canvas(&block) init_bounding_box(block) do |_| @bounding_box = BoundingBox.new(self, [0,page_dimensions[3]], :width => page_dimensions[2], :height => page_dimensions[3] ) end end |
#cell(point, options = {}) ⇒ Object
Builds and renders a Graphics::Cell. A cell is essentially a special-purpose bounding box designed for flowing text within a bordered area. For available options, see Graphics::Cell#new.
Prawn::Document.generate("cell.pdf") do
cell [100,500],
:width => 200,
:text => "The rain in Spain falls mainly on the plains"
end
22 23 24 25 |
# File 'lib/prawn/graphics/cell.rb', line 22 def cell(point, ={}) Prawn::Graphics::Cell.new( .merge(:document => self, :point => point)).draw end |
#mask(*fields) ⇒ Object
:nodoc:
233 234 235 236 237 238 239 240 241 |
# File 'lib/prawn/document.rb', line 233 def mask(*fields) # :nodoc: # Stores the current state of the named attributes, executes the block, and # then restores the original values after the block has executed. # -- I will remove the nodoc if/when this feature is a little less hacky stored = {} fields.each { |f| stored[f] = send(f) } yield fields.each { |f| send("#{f}=", stored[f]) } end |
#move_down(n) ⇒ Object
Moves down the document by n point
187 188 189 |
# File 'lib/prawn/document.rb', line 187 def move_down(n) self.y -= n end |
#move_up(n) ⇒ Object
Moves up the document by n points
181 182 183 |
# File 'lib/prawn/document.rb', line 181 def move_up(n) self.y += n end |
#pad(y) ⇒ Object
Moves down the document by y, executes a block, then moves down the document by y again.
pdf.text "some text"
pdf.pad(100) do
pdf.text "This is 100 points below the previous line of text"
end
pdf.text "This is 100 points below the previous line of text"
226 227 228 229 230 |
# File 'lib/prawn/document.rb', line 226 def pad(y) move_down(y) yield move_down(y) end |
#pad_bottom(y) ⇒ Object
Executes a block then moves down the document
pdf.text "some text"
pdf.pad_bottom(100) do
pdf.text "This text appears right below the previous line of text"
end
pdf.text "This is 100 points below the previous line of text"
212 213 214 215 |
# File 'lib/prawn/document.rb', line 212 def pad_bottom(y) yield move_down(y) end |
#pad_top(y) ⇒ Object
Moves down the document and then executes a block.
pdf.text "some text"
pdf.pad_top(100) do
pdf.text "This is 100 points below the previous line of text"
end
pdf.text "This text appears right below the previous line of text"
199 200 201 202 |
# File 'lib/prawn/document.rb', line 199 def pad_top(y) move_down(y) yield end |
#page_count ⇒ Object
142 143 144 |
# File 'lib/prawn/document.rb', line 142 def page_count @pages.data[:Count] end |
#render ⇒ Object
Renders the PDF document to string
148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/prawn/document.rb', line 148 def render output = StringIO.new finish_page_content render_header(output) render_body(output) render_xref(output) render_trailer(output) str = output.string str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding) str end |
#render_file(filename) ⇒ Object
Renders the PDF document to file.
pdf.render_file "foo.pdf"
165 166 167 168 |
# File 'lib/prawn/document.rb', line 165 def render_file(filename) Kernel.const_defined?("Encoding") ? mode = "wb:ASCII-8BIT" : mode = "wb" File.open(filename,mode) { |f| f << render } end |
#start_new_page(options = {}) ⇒ Object
Creates and advances to a new page in the document. Runs the on_page_start lambda if one was provided at document creation time (See Document.new).
Page size, margins, and layout can also be set when generating a new page. These values will become the new defaults for page creation
pdf.start_new_page(:size => "LEGAL", :layout => :landscape)
pdf.start_new_page(:left_margin => 50, :right_margin => 50)
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/prawn/document.rb', line 106 def start_new_page( = {}) @page_size = [:size] if [:size] @page_layout = [:layout] if [:layout] [:left,:right,:top,:bottom].each do |side| if [:"#{side}_margin"] @margins[side] = [:"#{side}_margin"] end end finish_page_content if @page_content generate_margin_box @page_content = ref(:Length => 0) @current_page = ref(:Type => :Page, :Parent => @pages, :MediaBox => page_dimensions, :Contents => @page_content) set_current_font update_colors @pages.data[:Kids] << @current_page @pages.data[:Count] += 1 add_content "q" @y = @margin_box.absolute_top @page_start_proc[self] if @page_start_proc end |
#table(data, options = {}) ⇒ Object
Builds and renders a Document::Table object from raw data. For details on the options that can be passed, see Document::Table.new
data = [["Gregory","Brown"],["James","Healy"],["Jia","Wu"]]
Prawn::Document.generate("table.pdf") do
# Default table, without headers
table(data)
# Default table with headers
table data, :headers => ["First Name", "Last Name"]
# Very close to PDF::Writer's default SimpleTable output
table data, :headers => ["First Name", "Last Name"],
:font_size => 10,
:vertical_padding => 2,
:horizontal_padding => 5,
:position => :center,
:row_colors => :pdf_writer,
# Grid border style with explicit column widths.
table data, :border_style => :grid,
:widths => { 0 => 100, 1 => 150 }
end
40 41 42 |
# File 'lib/prawn/document/table.rb', line 40 def table(data,={}) Prawn::Document::Table.new(data,self,).draw end |