Class: PDF::Core::Renderer
- Inherits:
-
Object
- Object
- PDF::Core::Renderer
- Defined in:
- lib/pdf/core/renderer.rb
Overview
Document renderer serializes document into its binary representation.
Instance Attribute Summary collapse
-
#state ⇒ PDF::Core::DocumentState
readonly
Document state.
Instance Method Summary collapse
-
#add_content(str) ⇒ void
Appends a raw string to the current page content.
-
#before_render {|document_state| ... } ⇒ void
Defines a block to be called just before the document is rendered.
-
#close_graphics_state ⇒ void
Close current graphic state (restore previous) in the content stream.
-
#compression_enabled? ⇒ Boolean
Returns true if content streams will be compressed before rendering, false otherwise.
-
#deref(obj) ⇒ any
At any stage in the object tree an object can be replaced with an indirect reference.
-
#finalize_all_page_contents ⇒ void
private
Finalize all pages.
-
#go_to_page(page_number) ⇒ void
Re-opens the page with the given (1-based) page number so that you can draw on it.
-
#graphic_stack ⇒ PDF::Core::GraphicStateStack
Graphic state stack of the current document.
-
#graphic_state ⇒ PDF::Core::GraphicState
Current graphic state.
-
#initialize(state) ⇒ Renderer
constructor
A new instance of Renderer.
-
#min_version(min) ⇒ void
private
Raise the PDF version of the file we’re going to generate.
-
#names ⇒ PDF::Core::Reference<Hash>
The Name dictionary for this document.
-
#names? ⇒ Boolean
Returns true if the Names dictionary is in use for this document.
-
#on_page_create {|document_state| ... } ⇒ void
Defines a block to be called just before a new page is started.
-
#open_graphics_state ⇒ void
Open (save) current graphic state in the content stream.
-
#page_count ⇒ Integer
Number of pages in the document.
-
#ref(data) ⇒ Integer
Creates a new Reference and adds it to the Document’s object list.
-
#ref!(data) ⇒ PDF::Core::Reference
Like #ref, but returns the actual reference instead of its identifier.
-
#render(output = nil) ⇒ String
Renders the PDF document to string.
-
#render_body(output) ⇒ void
private
Write out the PDF Body, as per spec 3.4.2.
-
#render_file(filename) ⇒ void
Renders the PDF document to file.
-
#render_header(output) ⇒ void
private
Write out the PDF Header, as per spec 3.4.1.
-
#render_trailer(output) ⇒ void
private
Write out the PDF Trailer, as per spec 3.4.4.
-
#render_xref(output) ⇒ void
private
Write out the PDF Cross Reference Table, as per spec 3.4.3.
-
#restore_graphics_state ⇒ void
Pops the last saved graphics state off the graphics state stack and restores the state to those values.
-
#save_graphics_state(graphic_state = nil) { ... } ⇒ void
Save surrent graphic state both in the graphic state stack and in the page content stream.
-
#start_new_page(options = {}) ⇒ void
Create a new page and set it current.
Constructor Details
#initialize(state) ⇒ Renderer
Returns a new instance of Renderer.
10 11 12 13 14 15 16 17 |
# File 'lib/pdf/core/renderer.rb', line 10 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 |
Instance Attribute Details
#state ⇒ PDF::Core::DocumentState (readonly)
Document state
21 22 23 |
# File 'lib/pdf/core/renderer.rb', line 21 def state @state end |
Instance Method Details
#add_content(str) ⇒ void
This method returns an undefined value.
Appends a raw string to the current page content.
66 67 68 69 |
# File 'lib/pdf/core/renderer.rb', line 66 def add_content(str) save_graphics_state if graphic_state.nil? state.page.content << str << "\n" end |
#before_render {|document_state| ... } ⇒ void
This method returns an undefined value.
Defines a block to be called just before the document is rendered.
92 93 94 |
# File 'lib/pdf/core/renderer.rb', line 92 def before_render(&block) state.before_render_callbacks << block end |
#close_graphics_state ⇒ void
This method returns an undefined value.
Close current graphic state (restore previous) in the content stream.
290 291 292 |
# File 'lib/pdf/core/renderer.rb', line 290 def close_graphics_state add_content('Q') end |
#compression_enabled? ⇒ Boolean
Returns true if content streams will be compressed before rendering, false otherwise
316 317 318 |
# File 'lib/pdf/core/renderer.rb', line 316 def compression_enabled? state.compress end |
#deref(obj) ⇒ any
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 PDF::Core::Reference, wrap it in ‘deref()`.
51 52 53 |
# File 'lib/pdf/core/renderer.rb', line 51 def deref(obj) obj.is_a?(PDF::Core::Reference) ? obj.data : obj end |
#finalize_all_page_contents ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Finalize all pages
166 167 168 169 170 171 172 173 174 |
# File 'lib/pdf/core/renderer.rb', line 166 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 |
#go_to_page(page_number) ⇒ void
This method returns an undefined value.
Re-opens the page with the given (1-based) page number so that you can draw on it.
157 158 159 160 |
# File 'lib/pdf/core/renderer.rb', line 157 def go_to_page(page_number) @page_number = page_number state.page = state.pages[page_number - 1] end |
#graphic_stack ⇒ PDF::Core::GraphicStateStack
Graphic state stack of the current document.
336 337 338 |
# File 'lib/pdf/core/renderer.rb', line 336 def graphic_stack state.page.stack end |
#graphic_state ⇒ PDF::Core::GraphicState
Current graphic state
343 344 345 346 |
# File 'lib/pdf/core/renderer.rb', line 343 def graphic_state save_graphics_state unless graphic_stack.current_state graphic_stack.current_state end |
#min_version(min) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
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.
183 184 185 |
# File 'lib/pdf/core/renderer.rb', line 183 def min_version(min) state.version = min if min > state.version end |
#names ⇒ PDF::Core::Reference<Hash>
The Name dictionary for this document. It is lazily initialized, so that documents that do not need a name dictionary do not incur the additional overhead.
77 78 79 |
# File 'lib/pdf/core/renderer.rb', line 77 def names state.store.root.data[:Names] ||= ref!(Type: :Names) end |
#names? ⇒ Boolean
Returns true if the Names dictionary is in use for this document.
84 85 86 |
# File 'lib/pdf/core/renderer.rb', line 84 def names? state.store.root.data.key?(:Names) end |
#on_page_create {|document_state| ... } ⇒ void
This method returns an undefined value.
Defines a block to be called just before a new page is started.
100 101 102 |
# File 'lib/pdf/core/renderer.rb', line 100 def on_page_create(&block) state.on_page_create_callback = block end |
#open_graphics_state ⇒ void
This method returns an undefined value.
Open (save) current graphic state in the content stream.
283 284 285 |
# File 'lib/pdf/core/renderer.rb', line 283 def open_graphics_state add_content('q') end |
#page_count ⇒ Integer
Number of pages in the document.
147 148 149 |
# File 'lib/pdf/core/renderer.rb', line 147 def page_count state.page_count end |
#ref(data) ⇒ Integer
Creates a new Reference and adds it to the Document’s object list.
27 28 29 |
# File 'lib/pdf/core/renderer.rb', line 27 def ref(data) ref!(data).identifier end |
#ref!(data) ⇒ PDF::Core::Reference
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.
41 42 43 |
# File 'lib/pdf/core/renderer.rb', line 41 def ref!(data) state.store.ref(data) end |
#render(output = nil) ⇒ String
Renders the PDF document to string. Pass an open file descriptor to render to file.
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/pdf/core/renderer.rb', line 192 def render(output = nil) buffer = StringIO.new.binmode finalize_all_page_contents render_header(buffer) render_body(buffer) render_xref(buffer) render_trailer(buffer) if output.respond_to?(:<<) output << buffer.string end buffer.string end |
#render_body(output) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Write out the PDF Body, as per spec 3.4.2
240 241 242 |
# File 'lib/pdf/core/renderer.rb', line 240 def render_body(output) state.render_body(output) end |
#render_file(filename) ⇒ void
This method returns an undefined value.
Renders the PDF document to file.
216 217 218 |
# File 'lib/pdf/core/renderer.rb', line 216 def render_file(filename) File.open(filename, 'wb') { |f| render(f) } end |
#render_header(output) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Write out the PDF Header, as per spec 3.4.1
225 226 227 228 229 230 231 232 233 |
# File 'lib/pdf/core/renderer.rb', line 225 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 |
#render_trailer(output) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Write out the PDF Trailer, as per spec 3.4.4
265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
# File 'lib/pdf/core/renderer.rb', line 265 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 |
#render_xref(output) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
Write out the PDF Cross Reference Table, as per spec 3.4.3
249 250 251 252 253 254 255 256 257 258 |
# File 'lib/pdf/core/renderer.rb', line 249 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 |
#restore_graphics_state ⇒ void
This method returns an undefined value.
Pops the last saved graphics state off the graphics state stack and restores the state to those values
324 325 326 327 328 329 330 331 |
# File 'lib/pdf/core/renderer.rb', line 324 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 |
#save_graphics_state(graphic_state = nil) { ... } ⇒ void
This method returns an undefined value.
Save surrent graphic state both in the graphic state stack and in the page content stream.
If a block is given graphic state is automatically restored after the block execution.
303 304 305 306 307 308 309 310 |
# File 'lib/pdf/core/renderer.rb', line 303 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 |
#start_new_page(options = {}) ⇒ void
This method returns an undefined value.
Create a new page and set it current.
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/pdf/core/renderer.rb', line 110 def start_new_page( = {}) 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 = { size: [:size] || last_page_size, layout: [: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 [:graphic_state] = new_graphic_state end state.page = PDF::Core::Page.new(self, ) state.insert_page(state.page, @page_number) @page_number += 1 state.on_page_create_action(self) end |