class PDF::Core::Renderer
Attributes
Public Class Methods
# 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
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
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
# File lib/pdf/core/renderer.rb, line 237 def close_graphics_state add_content 'Q' end
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
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
# 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
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
# File lib/pdf/core/renderer.rb, line 268 def graphic_stack state.page.stack end
# File lib/pdf/core/renderer.rb, line 272 def graphic_state save_graphics_state unless graphic_stack.current_state graphic_stack.current_state end
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
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
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
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
# File lib/pdf/core/renderer.rb, line 233 def open_graphics_state add_content 'q' end
# File lib/pdf/core/renderer.rb, line 125 def page_count state.page_count end
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
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
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
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
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
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
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
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
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
# 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
# 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