class Prawn::Document
The ‘Prawn::Document` class is how you start creating a PDF document.
There are three basic ways you can instantiate PDF Documents in Prawn, they are through assignment, implicit block or explicit block. Below is an example of each type, each example does exactly the same thing, makes a PDF document with all the defaults and puts in the default font “Hello There” and then saves it to the current directory as example.pdf.
For example, assignment can be like this:
“‘ruby pdf = Prawn::Document.new pdf.text “Hello There” pdf.render_file “example.pdf” “`
Or you can do an implied block form:
“‘ruby Prawn::Document.generate “example.pdf” do
text "Hello There"
end “‘
Or if you need to access a variable outside the scope of the block, the explicit block form:
“‘ruby words = “Hello There” Prawn::Document.generate “example.pdf” do |pdf|
pdf.text words
end “‘
Usually, the block forms are used when you are simply creating a PDF document that you want to immediately save or render out.
See the {#initialize new} and {.generate generate} methods for further details on the above.
Constants
- DEFAULT_OPTS
-
Default empty options.
- VALID_OPTIONS
-
List of recognised options.
Attributes
Current margin box. @return [Prawn::Document::BoundingBox]
Current page margins. @return [{:left, :top, :right, :bottom => Number}]
Current page number. @return [Integer]
@private
Current text formatter. By default it’s {Text::Formatted::Parser} @return [Object]
Absolute cursor position. @return [Number]
Public Class Methods
Source
# File lib/prawn/document.rb, line 95 def self.extensions @extensions ||= [] end
Any module added to this array will be included into instances of {Prawn::Document} at the per-object level. These will also be inherited by any subclasses.
@example
module MyFancyModule def party! text "It's a big party!" end end Prawn::Document.extensions << MyFancyModule Prawn::Document.generate("foo.pdf") do party! end
@return [Array<Module>]
Source
# File lib/prawn/document.rb, line 161 def self.generate(filename, options = {}, &block) pdf = new(options, &block) pdf.render_file(filename) end
Creates and renders a PDF document.
When using the implicit block form, Prawn will evaluate the block within an instance of {Prawn::Document}, simplifying your syntax. However, please note that you will not be able to reference variables from the enclosing scope within this block.
“‘ruby # Using implicit block form and rendering to a file Prawn::Document.generate “example.pdf” do
# self here is set to the newly instantiated Prawn::Document # and so any variables in the outside scope are unavailable font "Times-Roman" draw_text "Hello World", at: [200,720], size: 32
end “‘
If you need to access your local and instance variables, use the explicit block form shown below. In this case, Prawn yields an instance of {Prawn::Document} and the block is an ordinary closure:
“‘ruby # Using explicit block form and rendering to a file content = “Hello World” Prawn::Document.generate “example.pdf” do |pdf|
# self here is left alone pdf.font "Times-Roman" pdf.draw_text content, at: [200,720], size: 32
end “‘
Source
# File lib/prawn/document.rb, line 100 def self.inherited(base) super extensions.each { |e| base.extensions << e } end
@private
Source
# File lib/prawn/document.rb, line 227 def initialize(options = {}, &block) options = options.dup Prawn.verify_options(VALID_OPTIONS, options) # need to fix, as the refactoring breaks this # raise NotImplementedError if options[:skip_page_creation] self.class.extensions.reverse_each { |e| extend(e) } self.state = PDF::Core::DocumentState.new(options) state.populate_pages_from_store(self) renderer.min_version(state.store.min_version) if state.store.min_version renderer.min_version(1.6) if options[:print_scaling] == :none @background = options[:background] @background_scale = options[:background_scale] || 1 @font_size = 12 @bounding_box = nil @margin_box = nil @page_number = 0 @text_formatter = options.delete(:text_formatter) || Text::Formatted::Parser options[:size] = options.delete(:page_size) options[:layout] = options.delete(:page_layout) initialize_first_page(options) @bounding_box = @margin_box if block block.arity < 1 ? instance_eval(&block) : block[self] end end
Setting e.g. the ‘:margin` to 100 points and the `:left_margin` to 50 will result in margins of 100 points on every side except for the left, where it will be 50.
The ‘:margin` can also be an array much like CSS shorthand:
“‘ruby # Top and bottom are 20, left and right are 100. margin: [20, 100] # Top is 50, left and right are 100, bottom is 20. margin: [50, 100, 20] # Top is 10, right is 20, bottom is 30, left is 40. margin: [10, 20, 30, 40] “`
Additionally, ‘:page_size` can be specified as a simple two value array giving the width and height of the document you need in PDF Points.
@example New document, US Letter paper, portrait orientation
pdf = Prawn::Document.new
@example New document, A4 paper, landscaped
pdf = Prawn::Document.new(page_size: "A4", page_layout: :landscape)
@example New document, Custom size
pdf = Prawn::Document.new(page_size: [200, 300])
@example New document, with background
pdf = Prawn::Document.new( background: "#{Prawn::DATADIR}/images/pigs.jpg" )
@param options [Hash{Symbol => any}] @option options :page_size [String, Array(Number, Number)] (LETTER)
One of the `PDF::Core::PageGeometry` sizes.
@option options :page_layout [:portrait, :landscape]
Page orientation.
@option options :margin [Number, Array<Number>] ([32])
Sets the margin on all sides in points.
@option options :left_margin [Number] (32)
Sets the left margin in points.
@option options :right_margin [Number] (32)
Sets the right margin in points.
@option options :top_margin [Number] (32)
Sets the top margin in points.
@option options :bottom_margin [Number] (32)
Sets the bottom margin in points.
@option options :skip_page_creation [Boolean] (false)
Creates a document without starting the first page.
@option options :compress [Boolean] (false)
Compresses content streams before rendering them.
@option options :background [String?] (nil)
An image path to be used as background on all pages.
@option options :background_scale [Number?] (1)
Background image scale.
@option options :info [Hash{Symbol => any}?] (nil)
Generic hash allowing for custom metadata properties.
@option options :text_formatter [Object] (Prawn::Text::Formatted::Parser)
The text formatter to use for `:inline_format`ted text.
Public Instance Methods
Source
# File lib/prawn/document/bounding_box.rb, line 174 def bounding_box(point, *args, &block) init_bounding_box(block) do |parent_box| point = map_to_absolute(point) @bounding_box = BoundingBox.new(self, parent_box, point, *args) end end
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
#### Positioning
Bounding boxes are positioned relative to their top left corner and the width measurement is towards the right and height measurement is downwards.
Usage:
-
Bounding box 100pt×100pt in the absolute bottom left of the containing box:
“‘ruby pdf.bounding_box([0, 100], width: 100, height: 100)
stroke_boundsend “‘
-
Bounding box 200pt×400pt high in the center of the page:
“‘ruby x_pos = ((bounds.width / 2) - 150) y_pos = ((bounds.height / 2) + 200) pdf.bounding_box([x_pos, y_pos], width: 300, height: 400) do
stroke_boundsend “‘
#### Flowing Text
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 cursor position will be moved to the bottom of the bounding box (y - height). If flowing text exceeds the height of the bounding box, the text will be continued on the next page, starting again at the top-left corner of the bounding box.
Usage:
“‘ruby pdf.bounding_box([100, 500], 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 “‘
Note, this is a low level tool and is designed primarily for building other abstractions. If you just need to flow text on the page, you will want to look at {span} and {text_box} instead.
#### Translating Coordinates
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:
“‘ruby 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]`
“‘ruby 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:
“‘ruby pdf.bounding_box([200, 450], width: 200, height: 250) do
pdf.stroke do pdf.polygon [0, 250], [0, 0], [150, 100] pdf.polygon [100, 0], [150, 100], [200, 0] end
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.
#### Nesting Bounding Boxes
At the top level, 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
Usage:
“‘ruby pdf.bounding_box([200, 450], width: 200, height: 250) do
pdf.stroke_bounds # Show the containing bounding box 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. pdf.stroke_bounds end
end “‘
#### Stretchiness
If you do not specify a height to a bounding box, it will become stretchy and its height will be calculated automatically as you stretch the box downwards.
pdf.bounding_box([100, 400], width: 400) do pdf.text("The height of this box is #{pdf.bounds.height}") pdf.text('this is some text') pdf.text('this is some more text') pdf.text('and finally a bit more') pdf.text("Now the height of this box is #{pdf.bounds.height}") end
#### Absolute Positioning
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()
“‘ruby pdf.bounding_box([50, 500], width: 200, height: 300) do
pdf.stroke_bounds
pdf.canvas do
Positioned outside the containing box at the 'real' (300, 450)
pdf.bounding_box([300, 450], width: 200, height: 200) do
pdf.stroke_bounds
end
end
end “‘
Of course, if you use canvas, you will be responsible for ensuring that you remain within the printable area of your document.
@overload bounding_box(point, options = {}, &block)
@param point [Array(Number, Number)]
top left corner of the new bounding box
@param options [Hash{Symbol => any}]
@option options :width [Number]
width of the new bounding box, must be specified.
@option options :height [Number]
height of the new bounding box, stretchy box if omitted.
@yieldparam parent_box [BoundingBox] parent bounding box
@yieldreturn [void]
@return [void]
Source
# File lib/prawn/document.rb, line 504 def bounds @bounding_box end
The bounds method returns the current bounding box you are currently in, which is by default the box represented by the margin box on the document itself. When called from within a created ‘bounding_box` block, the box defined by that call will be returned instead of the document margin box.
Another important point about bounding boxes is that all x and y measurements within a bounding box code block are relative to the bottom left corner of the bounding box.
@example
Prawn::Document.new do # In the default "margin box" of a Prawn document of 0.5in along each # edge # Draw a border around the page (the manual way) stroke do line(bounds.bottom_left, bounds.bottom_right) line(bounds.bottom_right, bounds.top_right) line(bounds.top_right, bounds.top_left) line(bounds.top_left, bounds.bottom_left) end # Draw a border around the page (the easy way) stroke_bounds end
@return [Prawn::Document::BoundingBox]
Source
# File lib/prawn/document.rb, line 523 def bounds=(bounding_box) @bounding_box = bounding_box end
Sets {Document#bounds} to the {BoundingBox} provided. See {#bounds} for a brief description of what a bounding box is. This function is useful if you really need to change the bounding box manually, but usually, just entering and exiting bounding box code blocks is good enough.
@param bounding_box [Prawn::Document::BoundingBox] @return [bounding_box]
Source
# File lib/prawn/document/bounding_box.rb, line 191 def canvas(&block) init_bounding_box(block, hold_position: true) do |_| # Canvas bbox acts like margin_box in that its parent bounds are unset. @bounding_box = BoundingBox.new( self, nil, [0, page.dimensions[3]], width: page.dimensions[2], height: page.dimensions[3], ) end end
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.
@example
pdf.canvas do pdf.line pdf.bounds.bottom_left, pdf.bounds.top_right end
@yieldreturn [void] @return [void]
Source
# File lib/prawn/document/column_box.rb, line 34 def column_box(*args, &block) init_column_box(block) do |parent_box| map_to_absolute!(args[0]) @bounding_box = ColumnBox.new(self, parent_box, *args) end end
A column box is a bounding box with the additional property that when text flows past the bottom, it will wrap first to another column on the same page, and only flow to the next page when all the columns are filled.
‘column_box` accepts the same parameters as {bounding_box}, as well as the number of `:columns` and a `:spacer` (in points) between columns. If resetting the top margin is desired on a new page (e.g. to allow for initial page wide column titles) the option `reflow_margins: true` can be set.
@overload column_box(point, options = {})
@param point [Array(Number, Number)]
@param options [Hash{Symbol => any}]
@option options :width [Number]
width of the new column box, must be specified.
@option options :height [Number]
height of the new column box, stretchy box if omitted.
@option options :hold_position [Boolean]
whether to put cursor at the bottom of the column box.
@option options :columns [Integer] (3)
@option options :spacer [Number] (font_size)
@option options :reflow_margins [Boolean] (false)
@yieldparam parent_box [BoundingBox] parent bounding box
@return [void]
Source
# File lib/prawn/document.rb, line 415 def cursor y - bounds.absolute_bottom end
The current y drawing position relative to the innermost bounding box, or to the page margins at the top level.
@return [Number]
Source
# File lib/prawn/grid.rb, line 24 def define_grid(options = {}) @boxes = nil @grid = Grid.new(self, options) end
Defines the grid system for a particular document. Takes the number of rows and columns and the width to use for the gutter as the keys :rows, :columns, :gutter, :row_gutter, :column_gutter
@note A completely new grid object is built each time ‘define_grid`
is called. This means that all subsequent calls to grid() will use the newly defined Grid object -- grids are not nestable like bounding boxes are.
@param options [Hash{Symbol => any}] @option options :columns [Integer] Number of columns in the grid. @option options :rows [Integer] Number of rows in the grid. @option options :gutter [Number] Gutter size. ‘:row_gutter` and
`:column_gutter` are ignored if specified.
@option options :row_gutter [Number] Row gutter size. @option options :column_gutter [Number] Column gutter size. @return [Grid]
Source
# File lib/prawn/document.rb, line 366 def delete_page(index) return false if index.abs > (state.pages.count - 1) state.pages.delete_at(index) state.store.pages.data[:Kids].delete_at(index) state.store.pages.data[:Count] -= 1 @page_number -= 1 true end
Remove page of the document by index.
@example
pdf = Prawn::Document.new pdf.page_count #=> 1 3.times { pdf.start_new_page } pdf.page_count #=> 4 pdf.delete_page(-1) pdf.page_count #=> 3
@param index [Integer] @return [Boolean]
Source
# File lib/prawn/document.rb, line 442 def float original_page = page_number original_y = y yield go_to_page(original_page) unless page_number == original_page self.y = original_y end
Executes a block and then restores the original y position. If new pages were created during this block, it will teleport back to the original page when done.
@example
pdf.text "A" pdf.float do pdf.move_down 100 pdf.text "C" end pdf.text "B"
@return [void]
Source
# File lib/prawn/font.rb, line 56 def font(name = nil, options = DEFAULT_OPTS) return((defined?(@font) && @font) || font('Helvetica')) if name.nil? if state.pages.empty? && !state.page.in_stamp_stream? raise Prawn::Errors::NotOnPage end new_font = find_font(name.to_s, options) if block_given? save_font do set_font(new_font, options[:size]) yield end else set_font(new_font, options[:size]) end @font end
Without arguments, this returns the currently selected font. Otherwise, it sets the current font. When a block is used, the font is applied transactionally and is rolled back when the block exits.
“‘ruby Prawn::Document.generate(“font.pdf”) do
text "Default font is Helvetica" font "Times-Roman" text "Now using Times-Roman" font("DejaVuSans.ttf") do text "Using TTF font from file DejaVuSans.ttf" font "Courier", style: :bold text "You see this in bold Courier" end text "Times-Roman, again"
end “‘
The ‘name` parameter must be a string. It can be one of the 14 built-in fonts supported by PDF, or the location of a TTF file. The {Fonts::AFM::BUILT_INS} array specifies the valid built in font names.
If a TTF/OTF font is specified, the glyphs necessary to render your document will be embedded in the rendered PDF. This should be your preferred option in most cases. It will increase the size of the resulting file, but also make it more portable.
The options parameter is an optional hash providing size and style. To use the :style option you need to map those font styles to their respective font files.
@param name [String] font name. It can be:
- One of 14 PDF built-in fonts.
- A font file path.
- A font name defined in {font_families}
@param options [Hash{Symbol => any}] @option options :style [Symbol] font style @yield @return [Font] @see font_families @see Font::AFM::BUILT_INS
Source
# File lib/prawn/font.rb, line 212 def font_families @font_families ||= {}.merge!( 'Courier' => { bold: 'Courier-Bold', italic: 'Courier-Oblique', bold_italic: 'Courier-BoldOblique', normal: 'Courier', }, 'Times-Roman' => { bold: 'Times-Bold', italic: 'Times-Italic', bold_italic: 'Times-BoldItalic', normal: 'Times-Roman', }, 'Helvetica' => { bold: 'Helvetica-Bold', italic: 'Helvetica-Oblique', bold_italic: 'Helvetica-BoldOblique', normal: 'Helvetica', }, ) end
Hash that maps font family names to their styled individual font definitions.
To add support for another font family, append to this hash, e.g:
“‘ruby pdf.font_families.update(
"MyTrueTypeFamily" => { bold: "foo-bold.ttf", italic: "foo-italic.ttf", bold_italic: "foo-bold-italic.ttf", normal: "foo.ttf", }
) “‘
This will then allow you to use the fonts like so:
“‘ruby pdf.font(“MyTrueTypeFamily”, style: :bold) pdf.text “Some bold text” pdf.font(“MyTrueTypeFamily”) pdf.text “Some normal text” “`
This assumes that you have appropriate TTF/OTF fonts for each style you wish to support.
By default the styles ‘:bold`, `:italic`, `:bold_italic`, and `:normal` are defined for fonts “Courier”, “Times-Roman” and “Helvetica”. When defining your own font families, you can map any or all of these styles to whatever font files you’d like.
Font definition can be either a hash or just a string.
A hash font definition can specify a number of options:
-
‘:file` – path to the font file (required)
-
‘:subset` – whether to subset the font (default false). Only applicable to TrueType and OpenType fonts (includnig DFont and TTC).
A string font definition is equivalent to hash definition with only ‘:file` being specified.
@return [Hash{String => Hash{Symbol => String, Hash{Symbol => String}}}]
Source
# File lib/prawn/font.rb, line 314 def font_registry @font_registry ||= {} end
Hash of Font objects keyed by names.
@private @return [Hash{String => Font}]
Source
# File lib/prawn/font.rb, line 106 def font_size(points = nil) return @font_size unless points size_before_yield = @font_size @font_size = points block_given? ? yield : return @font_size = size_before_yield end
When called with no argument, returns the current font size.
When called with a single argument but no block, sets the current font size. When a block is used, the font size is applied transactionally and is rolled back when the block exits. You may still change the font size within a transactional block for individual text segments, or nested calls to ‘font_size`.
@example
Prawn::Document.generate("font_size.pdf") do font_size 16 text "At size 16" font_size(10) do text "At size 10" text "At size 6", size: 6 text "At size 10" end text "At size 16" end
@overload font_size()
@return [Number] vurrent font size
@overload font_size(points)
@param points [Number] new font size @yield if block is provided font size is set only for the duration of the block @return [void]
Source
# File lib/prawn/font.rb, line 119 def font_size=(size) font_size(size) end
Sets the font size.
@param size [Number] @return [Number]
Source
# File lib/prawn/document.rb, line 395 def go_to_page(page_number) @page_number = page_number state.page = state.pages[page_number - 1] generate_margin_box @y = @bounding_box.absolute_top end
Re-opens the page with the given (1-based) page number so that you can draw on it.
@param page_number [Integer] @return [void]
Source
# File lib/prawn/grid.rb, line 50 def grid(*args) @boxes ||= {} @boxes[args] ||= if args.empty? @grid else g1, g2 = args if g1.is_a?(Array) && g2.is_a?(Array) && g1.length == 2 && g2.length == 2 multi_box(single_box(*g1), single_box(*g2)) else single_box(g1, g2) end end end
A method that can either be used to access a particular grid on the page or work with the grid system directly.
@overload grid
Get current grid. @return [Grid]
@overload grid(row, column)
Get a grid box. @param row [Integer] @param column [Integer] @return [GridBox]
@overload grid(box1, box2)
Get a grid multi-box. @param box1 [Array(Integer, Integer)] Start box coordinates. @param box2 [Array(Integer, Integer)] End box coordinates. @return [MultiBox]
Source
# File lib/prawn/document.rb, line 700 def group(*_arguments) raise NotImplementedError, 'Document#group has been disabled because its implementation ' \ 'lead to corrupted documents whenever a page boundary was ' \ 'crossed. We will try to work on reimplementing it in a ' \ 'future release' end
@private
Source
# File lib/prawn/document.rb, line 615 def indent(left, right = 0, &block) bounds.indent(left, right, &block) end
Indents the specified number of PDF points for the duration of the block
@example
pdf.text "some text" pdf.indent(20) do pdf.text "This is indented 20 points" end pdf.text "This starts 20 points left of the above line " + "and is flush with the first line" pdf.indent 20, 20 do pdf.text "This line is indented on both sides." end
@param left [Number] @param right [Number] @yield @return [void]
Source
# File lib/prawn/document.rb, line 767 def initialize_first_page(options) if options[:skip_page_creation] start_new_page(options.merge(orphan: true)) else start_new_page(options) end end
Initializes the first page in a new document. This methods allows customisation of this process in extensions such as Prawn::Template.
@param options [Hash] @return [void]
Source
# File lib/prawn/document.rb, line 749 def mask(*fields) # 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] = public_send(f) } yield fields.each { |f| public_send(:"#{f}=", stored[f]) } end
@private
Source
# File lib/prawn/document.rb, line 423 def move_cursor_to(new_y) self.y = new_y + bounds.absolute_bottom end
Moves to the specified y position in relative terms to the bottom margin.
@param new_y [Number] @return [void]
Source
# File lib/prawn/document.rb, line 541 def move_down(amount) self.y -= amount end
Moves down the document by n points relative to the current position inside the current bounding box.
@param amount [Number] @return [void]
Source
# File lib/prawn/document.rb, line 532 def move_up(amount) self.y += amount end
Moves up the document by n points relative to the current position inside the current bounding box.
@param amount [Number] @return [void]
Source
# File lib/prawn/document.rb, line 652 def number_pages(string, options = {}) opts = options.dup start_count_at = opts.delete(:start_count_at) page_filter = if opts.key?(:page_filter) opts.delete(:page_filter) else :all end total_pages = opts.delete(:total_pages) txtcolor = opts.delete(:color) # An explicit height so that we can draw page numbers in the margins opts[:height] = 50 unless opts.key?(:height) start_count = false pseudopage = 0 (1..page_count).each do |p| unless start_count pseudopage = case start_count_at when String Integer(start_count_at, 10) when (1..) Integer(start_count_at) else 1 end end if page_match?(page_filter, p) go_to_page(p) # have to use fill_color here otherwise text reverts back to default # fill color fill_color(txtcolor) unless txtcolor.nil? total_pages = page_count if total_pages.nil? str = string.gsub('<page>', pseudopage.to_s) .gsub('<total>', total_pages.to_s) text_box(str, opts) start_count = true # increment page count as soon as first match found end pseudopage += 1 if start_count end end
Places a text box on specified pages for page numbering. This should be called towards the end of document creation, after all your content is already in place. In your template string, ‘<page>` refers to the current page, and `<total>` refers to the total amount of pages in the document. Page numbering should occur at the end of your {Prawn::Document.generate} block because the method iterates through existing pages after they are created.
Please refer to {Prawn::Text#text_box} for additional options concerning text formatting and placement.
@example Print page numbers on every page except for the first. Start counting from five.
Prawn::Document.generate("page_with_numbering.pdf") do number_pages "<page> in a total of <total>", { start_count_at: 5, page_filter: lambda { |pg| pg != 1 }, at: [bounds.right - 50, 0], align: :right, size: 14 } end
@param string [String] Template string for page number wording.
Should include `<page>` and, optionally, `<total>`.
@param options [Hash{Symbol => any}] A hash for page numbering and text box options. @option options :page_filter []
A filter to specify which pages to place page numbers on. Refer to the method {#page_match?}
@option options :start_count_at [Integer]
The starting count to increment pages from.
@option options :total_pages [Integer]
If provided, will replace `<total>` with the value given. Useful to override the total number of pages when using the start_count_at option.
@option options :color [String, Array<Number>] Text fill color.
Source
# File lib/prawn/outline.rb, line 12 def outline @outline ||= Outline.new(self) end
Lazily instantiates a Prawn::Outline object for document. This is used as point of entry to methods to build the outline tree for a document’s table of contents.
@return [Prawn::Outline]
Source
# File lib/prawn/document.rb, line 592 def pad(y) move_down(y) yield move_down(y) end
Moves down the document by y, executes a block, then moves down the document by y again.
@example
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"
@param y [Number] @return [void] @yield
Source
# File lib/prawn/document.rb, line 574 def pad_bottom(y) yield move_down(y) end
Executes a block then moves down the document
@example
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"
@param y [Number] @return [void] @yield
Source
# File lib/prawn/document.rb, line 557 def pad_top(y) move_down(y) yield end
Moves down the document and then executes a block.
@example
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"
@param y [Number] @return [void] @yield
Source
# File lib/prawn/document.rb, line 386 def page_count state.page_count end
Number of pages in the document.
@example
pdf = Prawn::Document.new pdf.page_count #=> 1 3.times { pdf.start_new_page } pdf.page_count #=> 4
@return [Integer]
Source
# File lib/prawn/document.rb, line 733 def page_match?(page_filter, page_number) case page_filter when :all true when :odd page_number.odd? when :even page_number.even? when Range, Array page_filter.include?(page_number) when Proc page_filter.call(page_number) end end
Provides a way to execute a block of code repeatedly based on a page_filter.
Available page filters are:
:all repeats on every page :odd repeats on odd pages
@param page_filter [:all, :odd, :even, Array<Number>, Range, Proc]
* `:all`: repeats on every page * `:odd`: repeats on odd pages * `:even`: repeats on even pages * array: repeats on every page listed in the array * range: repeats on every page included in the range * lambda: yields page number and repeats for true return values
@param page_number [Integer] @return [Boolean]
Source
# File lib/prawn/document.rb, line 512 def reference_bounds @bounding_box.reference_bounds end
Returns the innermost non-stretchy bounding box.
@private @return [Prawn::Document::BoundingBox]
Source
# File lib/prawn/document.rb, line 456 def render(*arguments) (1..page_count).each do |i| go_to_page(i) repeaters.each { |r| r.run(i) } end renderer.render(*arguments) end
Renders the PDF document to string. Pass an open file descriptor to render to file.
@overload render(output = nil)
@param output [#<<] @return [String]
Source
# File lib/prawn/document.rb, line 472 def render_file(filename) File.open(filename, 'wb') { |f| render(f) } end
Renders the PDF document to file.
@example
pdf.render_file "foo.pdf"
@param filename [String] @return [void]
Source
# File lib/prawn/repeater.rb, line 77 def repeat(page_filter, options = {}, &block) dynamic = options.fetch(:dynamic, false) repeaters << Prawn::Repeater.new( self, page_filter, dynamic, &block ) end
Provides a way to execute a block of code repeatedly based on a ‘page_filter`. Since Stamp is used under the hood, this method is very space efficient.
Also accepts an optional second argument for dynamic content which executes the code in the context of the filtered pages without using a Stamp.
@example
Prawn::Document.generate("repeat.pdf", skip_page_creation: true) do repeat :all do draw_text "ALLLLLL", at: bounds.top_left end repeat :odd do draw_text "ODD", at: [0, 0] end repeat :even do draw_text "EVEN", at: [0, 0] end repeat [1, 2] do draw_text "[1, 2]", at: [100, 0] end repeat 2..4 do draw_text "2..4", at: [200, 0] end repeat(lambda { |pg| pg % 3 == 0 }) do draw_text "Every third", at: [250, 20] end 10.times do start_new_page draw_text "A wonderful page", at: [400, 400] end repeat(:all, dynamic: true) do text page_number, at: [500, 0] end end
@param page_filter [:all, :odd, :even, Array<Integer>, Range, Proc]
Pages to draw the repeater content on. Available page filters are: - `:all` -- repeats on every page. - `:odd` -- repeats on odd pages. - `:even` -- repeats on even pages. - Array of Integers -- repeats on every page listed in the array. - Range -- repeats on every page included in the range. - Proc -- yields page number and repeats for true return values.
@param options [Hash] @option options :dynamic [Boolean] (false)
A dynamic repeater executes block on every matched page. A static
repeater uses {stamp} to prepare the content (runs the block once) and
puts it on every matched page.
@return [void]
Source
# File lib/prawn/repeater.rb, line 10 def repeaters @repeaters ||= [] end
A list of all repeaters in the document. See {repeat} for details.
@private @return [Array]
Source
# File lib/prawn/font.rb, line 255 def save_font @font ||= find_font('Helvetica') original_font = @font original_size = @font_size yield ensure set_font(original_font, original_size) if original_font end
Saves the current font, and then yields. When the block finishes, the original font is restored.
@yield @return [void]
Source
# File lib/prawn/font.rb, line 245 def set_font(font, size = nil) @font = font @font_size = size if size end
Sets the font directly, given an actual {Font} object and size.
@private @param font [Font] @param size [Number] @return [void]
Source
# File lib/prawn/document/span.rb, line 31 def span(width, options = {}) Prawn.verify_options([:position], options) original_position = y # FIXME: Any way to move this upstream? left_boundary = case options.fetch(:position, :left) when :left margin_box.absolute_left when :center margin_box.absolute_left + (margin_box.width / 2.0) - (width / 2.0) when :right margin_box.absolute_right - width when Numeric margin_box.absolute_left + options[:position] else raise ArgumentError, 'Invalid option for :position' end # we need to bust out of whatever nested bounding boxes we're in. canvas do bounding_box( [ left_boundary, margin_box.absolute_top, ], width: width, ) do self.y = original_position yield end end end
A span is a special purpose bounding box that allows a column of elements to be positioned relative to the margin_box.
This method is typically used for flowing a column of text from one page to the next.
@example
span(350, position: :center) do text "Here's some centered text in a 350 point column. " * 100 end
@param width [Number] The width of the column in PDF points @param options [Hash{Symbol => any }] @option options :position [:left, :center, :right, Number]
position of the span relative to the page margins.
@yield @return [void] @raise [ArgumentError] For unsupported ‘:position` value.
Source
# File lib/prawn/document.rb, line 299 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.dup 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 new_graphic_state&.color_space = {} page_options[:graphic_state] = new_graphic_state end state.page = PDF::Core::Page.new(self, page_options) apply_margin_options(options) generate_margin_box # Reset the bounding box if the new page has different size or layout if last_page && (last_page.size != state.page.size || last_page.layout != state.page.layout) @bounding_box = @margin_box end use_graphic_settings unless options[:orphan] state.insert_page(state.page, @page_number) @page_number += 1 if @background canvas do image(@background, scale: @background_scale, at: bounds.top_left) end end @y = @bounding_box.absolute_top float do state.on_page_create_action(self) end end end
Creates and advances to a new page in the document.
Page size, margins, and layout can also be set when generating a new page. These values will become the new defaults for page creation.
@example
pdf.start_new_page #=> Starts new page keeping current values pdf.start_new_page(size: "LEGAL", :layout => :landscape) pdf.start_new_page(left_margin: 50, right_margin: 50) pdf.start_new_page(margin: 100)
@param options [Hash] @option options :margins [Hash{:left, :right, :top, :bottom => Number}, nil]
({ left: 0, right: 0, top: 0, bottom: 0 }) Page margins
@option options :crop [Hash{:left, :right, :top, :bottom => Number}, nil] (PDF::Core::Page::ZERO_INDENTS)
Page crop box
@option options :bleed [Hash{:left, :right, :top, :bottom => Number}, nil] (PDF::Core::Page::ZERO_INDENTS)
Page bleed box
@option options :trims [Hash{:left, :right, :top, :bottom => Number}, nil] (PDF::Core::Page::ZERO_INDENTS)
Page trim box
@option options :art_indents [Hash{:left, :right, :top, :bottom => Number}, nil] (PDF::Core::Page::ZERO_INDENTS)
Page art box indents.
@option options :graphic_state [PDF::Core::GraphicState, nil] (nil)
Initial graphic state
@option options :size [String, Array<Number>, nil] (‘LETTER’)
Page size. A string identifies a named page size defined in `PDF::Core::PageGeometry`. An array must be a two element array specifying width and height in points.
@option options :layout [:portrait, :landscape, nil] (:portrait)
Page orientation.
@return [void]
Source
# File lib/prawn/document.rb, line 709 def transaction raise NotImplementedError, 'Document#transaction has been disabled because its implementation ' \ 'lead to corrupted documents whenever a page boundary was ' \ 'crossed. We will try to work on reimplementing it in a ' \ 'future release' end
@private
Source
# File lib/prawn/font.rb, line 150 def width_of(string, options = {}) if options.key?(:inline_format) p = options[:inline_format] p = [] unless p.is_a?(Array) # Build up an Arranger with the entire string on one line, finalize it, # and find its width. arranger = Prawn::Text::Formatted::Arranger.new(self, options) arranger.consumed = text_formatter.format(string, *p) arranger.finalize_line arranger.line_width else width_of_string(string, options) end end
Returns the width of the given string using the given font. If ‘:size` is not specified as one of the options, the string is measured using the current font size. You can also pass `:kerning` as an option to indicate whether kerning should be used when measuring the width (defaults to `false`).
Note that the string must be encoded properly for the font being used. For AFM fonts, this is WinAnsi. For TTF/OTF, make sure the font is encoded as UTF-8. You can use the Font#normalize_encoding method to make sure strings are in an encoding appropriate for the current font.
@devnote
For the record, this method used to be a method of Font (and still delegates to width computations on Font). However, having the primary interface for calculating string widths exist on Font made it tricky to write extensions for Prawn in which widths are computed differently (e.g., taking formatting tags into account, or the like). By putting width_of here, on Document itself, extensions may easily override it and redefine the width calculation behavior.
@param string [String] @param options [Hash{Symbol => any}] @option options :inline_format [Boolean] (false) @option options :kerning [Boolean] (false) @option options :style [Symbol] @return [Number]
Source
# File lib/prawn/document.rb, line 406 def y=(new_y) @y = new_y bounds.update_height end
Set cursor absolute position.
@param new_y [Number] @return [new_y]