module Prawn::Stamp

The Prawn::Stamp module is used to create content that will be included multiple times in a document. Using a stamp has three advantages over creating content anew each time it is placed on the page:

i.   faster document creation
ii.  smaller final document
iii. faster display on subsequent displays of the repeated
element because the viewer application can cache the rendered
results

Example:

pdf.create_stamp("my_stamp") {
  pdf.fill_circle([10, 15], 5)
  pdf.draw_text("hello world", :at => [20, 10])
}
pdf.stamp("my_stamp")

Public Instance Methods

create_stamp(name, &block) click to toggle source

Creates a re-usable stamp named name

raises Prawn::Errors::NameTaken if a stamp already exists in this document with this name raises Prawn::Errors::InvalidName if name.empty?

Example:

pdf.create_stamp("my_stamp") {
  pdf.fill_circle([10, 15], 5)
  pdf.draw_text("hello world", :at => [20, 10])
}
# File lib/prawn/stamp.rb, line 76
def create_stamp(name, &block)
  dictionary = create_stamp_dictionary(name)

  state.page.stamp_stream(dictionary, &block)
end
stamp(name) click to toggle source

Renders the stamp named name to the page raises Prawn::Errors::InvalidName if name.empty? raises Prawn::Errors::UndefinedObjectName if no stamp has been created with this name

Example:

pdf.create_stamp("my_stamp") {
  pdf.fill_circle([10, 15], 5)
  pdf.text("hello world", :at => [20, 10])
}
pdf.stamp("my_stamp")
# File lib/prawn/stamp.rb, line 40
def stamp(name)
  dictionary_name, dictionary = stamp_dictionary(name)
  renderer.add_content "/#{dictionary_name} Do"
  update_annotation_references dictionary.data[:Annots]
  state.page.xobjects.merge!(dictionary_name => dictionary)
end
stamp_at(name, point) click to toggle source

Renders the stamp named name at a position offset from the initial coords at which the elements of the stamp was created

Example:

pdf.create_stamp("circle") do
  pdf.fill_circle([0, 0], 25)
end
# draws a circle at 100, 100
pdf.stamp_at("circle", [100, 100])

See stamp() for exceptions that might be raised

# File lib/prawn/stamp.rb, line 60
def stamp_at(name, point)
  translate(point[0], point[1]) { stamp(name) }
end

Private Instance Methods

create_stamp_dictionary(name) click to toggle source
# File lib/prawn/stamp.rb, line 105
def create_stamp_dictionary(name)
  raise Prawn::Errors::InvalidName if name.empty?
  raise Prawn::Errors::NameTaken unless stamp_dictionary_registry[name].nil?
  # BBox origin is the lower left margin of the page, so we need
  # it to be the full dimension of the page, or else things that
  # should appear near the top or right margin are invisible
  dictionary = ref!(
    Type: :XObject,
    Subtype: :Form,
    BBox: [
      0, 0,
      state.page.dimensions[2], state.page.dimensions[3]
    ]
  )

  dictionary_name = "Stamp#{next_stamp_dictionary_id}"

  stamp_dictionary_registry[name] = {
    stamp_dictionary_name: dictionary_name,
    stamp_dictionary: dictionary
  }
  dictionary
end
freeze_stamp_graphics() click to toggle source
# File lib/prawn/stamp.rb, line 140
def freeze_stamp_graphics
  update_colors
  write_line_width
  write_stroke_cap_style
  write_stroke_join_style
  write_stroke_dash
end
next_stamp_dictionary_id() click to toggle source
# File lib/prawn/stamp.rb, line 88
def next_stamp_dictionary_id
  stamp_dictionary_registry.length + 1
end
stamp_dictionary(name) click to toggle source
# File lib/prawn/stamp.rb, line 92
def stamp_dictionary(name)
  raise Prawn::Errors::InvalidName if name.empty?
  if stamp_dictionary_registry[name].nil?
    raise Prawn::Errors::UndefinedObjectName
  end

  dict = stamp_dictionary_registry[name]

  dictionary_name = dict[:stamp_dictionary_name]
  dictionary = dict[:stamp_dictionary]
  [dictionary_name, dictionary]
end
stamp_dictionary_registry() click to toggle source
# File lib/prawn/stamp.rb, line 84
def stamp_dictionary_registry
  @stamp_dictionary_registry ||= {}
end
update_annotation_references(annots) click to toggle source

Referencing annotations from a stamp XObject doesn't result in a working link. Instead, the references must be appended to the /Annot dictionary of the object that contains the call to the stamp object.

# File lib/prawn/stamp.rb, line 133
def update_annotation_references(annots)
  if annots && annots.any?
    state.page.dictionary.data[:Annots] ||= []
    state.page.dictionary.data[:Annots] |= annots
  end
end