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.
Source Code
10 | def initialize(state) |
11 | @state = state |
12 | @state.populate_pages_from_store(self) |
13 | |
14 | min_version(state.store.min_version) if state.store.min_version |
15 | |
16 | @page_number = 0 |
17 | end
|
Instance Attribute Details
#state ⇒ PDF::Core::DocumentState (readonly)
Document state
Source Code
21 | def state |
22 | @state
|
23 | end
|
Instance Method Details
#add_content(str) ⇒ void
This method returns an undefined value.
Appends a raw string to the current page content.
Source Code
66 | def add_content(str) |
67 | save_graphics_state if graphic_state.nil? |
68 | state.page.content << str << "\n" |
69 | end
|
#before_render {|document_state| ... } ⇒ void
This method returns an undefined value.
Defines a block to be called just before the document is rendered.
Source Code
92 | def before_render(&block) |
93 | state.before_render_callbacks << block |
94 | end
|
#close_graphics_state ⇒ void
This method returns an undefined value.
Close current graphic state (restore previous) in the content stream.
Source Code
290 | def close_graphics_state |
291 | add_content('Q') |
292 | end
|
#compression_enabled? ⇒ Boolean
Returns true if content streams will be compressed before rendering, false otherwise
Source Code
316 | def compression_enabled? |
317 | state.compress |
318 | 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()
.
Source Code
51 | def deref(obj) |
52 | obj.is_a?(PDF::Core::Reference) ? obj.data : obj |
53 | 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
Source Code
166 | def finalize_all_page_contents |
167 | (1..page_count).each do |i| |
168 | go_to_page(i) |
169 | while graphic_stack.present? |
170 | restore_graphics_state
|
171 | end
|
172 | state.page.finalize |
173 | end
|
174 | 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.
Source Code
157 | def go_to_page(page_number) |
158 | @page_number = page_number |
159 | state.page = state.pages[page_number - 1] |
160 | end
|
#graphic_stack ⇒ PDF::Core::GraphicStateStack
Graphic state stack of the current document.
Source Code
336 | def graphic_stack |
337 | state.page.stack |
338 | end
|
#graphic_state ⇒ PDF::Core::GraphicState
Current graphic state
Source Code
343 | def graphic_state |
344 | save_graphics_state unless graphic_stack.current_state |
345 | graphic_stack.current_state |
346 | 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.
Source Code
183 | def min_version(min) |
184 | state.version = min if min > state.version |
185 | 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.
Source Code
77 | def names |
78 | state.store.root.data[:Names] ||= ref!(Type: :Names) |
79 | end
|
#names? ⇒ Boolean
Returns true if the Names dictionary is in use for this document.
Source Code
84 | def names? |
85 | state.store.root.data.key?(:Names) |
86 | 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.
Source Code
100 | def on_page_create(&block) |
101 | state.on_page_create_callback = block |
102 | end
|
#open_graphics_state ⇒ void
This method returns an undefined value.
Open (save) current graphic state in the content stream.
Source Code
283 | def open_graphics_state |
284 | add_content('q') |
285 | end
|
#page_count ⇒ Integer
Number of pages in the document.
Source Code
147 | def page_count |
148 | state.page_count |
149 | end
|
#ref(data) ⇒ Integer
Creates a new Reference and adds it to the Document’s object list.
Source Code
27 | def ref(data) |
28 | ref!(data).identifier |
29 | 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.
Source Code
41 | def ref!(data) |
42 | state.store.ref(data) |
43 | end
|
#render(output = nil) ⇒ String
Renders the PDF document to string. Pass an open file descriptor to render to file.
Source Code
192 | def render(output = nil) |
193 | buffer = StringIO.new.binmode |
194 | |
195 | finalize_all_page_contents
|
196 | |
197 | render_header(buffer) |
198 | render_body(buffer) |
199 | render_xref(buffer) |
200 | render_trailer(buffer) |
201 | |
202 | if output.respond_to?(:<<) |
203 | output << buffer.string |
204 | end
|
205 | |
206 | buffer.string |
207 | 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
Source Code
240 | def render_body(output) |
241 | state.render_body(output) |
242 | end
|
#render_file(filename) ⇒ void
This method returns an undefined value.
Renders the PDF document to file.
Source Code
216 | def render_file(filename) |
217 | File.open(filename, 'wb') { |f| render(f) } |
218 | 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
Source Code
225 | def render_header(output) |
226 | state.before_render_actions(self) |
227 | |
228 | # pdf version
|
229 | output << "%PDF-#{state.version}\n" |
230 | |
231 | # 4 binary chars, as recommended by the spec
|
232 | output << "%\xFF\xFF\xFF\xFF\n" |
233 | 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
Source Code
265 | def render_trailer(output) |
266 | trailer_hash = { |
267 | Size: state.store.size + 1, |
268 | Root: state.store.root, |
269 | Info: state.store.info, |
270 | }
|
271 | trailer_hash.merge!(state.trailer) if state.trailer |
272 | |
273 | output << "trailer\n" |
274 | output << PDF::Core.pdf_object(trailer_hash) << "\n" |
275 | output << "startxref\n" |
276 | output << @xref_offset << "\n" |
277 | output << '%%EOF' << "\n" |
278 | 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
Source Code
249 | def render_xref(output) |
250 | @xref_offset = output.size |
251 | output << "xref\n" |
252 | output << "0 #{state.store.size + 1}\n" |
253 | output << "0000000000 65535 f \n" |
254 | state.store.each do |ref| |
255 | output.printf('%<offset>010d', offset: ref.offset) |
256 | output << " 00000 n \n" |
257 | end
|
258 | 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
Source Code
324 | def restore_graphics_state |
325 | if graphic_stack.empty? |
326 | raise PDF::Core::Errors::EmptyGraphicStateStack, |
327 | "\n You have reached the end of the graphic state stack" |
328 | end
|
329 | close_graphics_state
|
330 | graphic_stack.restore_graphic_state |
331 | 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.
Source Code
303 | def save_graphics_state(graphic_state = nil) |
304 | graphic_stack.save_graphic_state(graphic_state) |
305 | open_graphics_state
|
306 | if block_given? |
307 | yield
|
308 | restore_graphics_state
|
309 | end
|
310 | end
|
#start_new_page(options = {}) ⇒ void
This method returns an undefined value.
Create a new page and set it current.
Source Code
110 | def start_new_page(options = {}) |
111 | last_page = state.page |
112 | if last_page |
113 | last_page_size = last_page.size |
114 | last_page_layout = last_page.layout |
115 | last_page_margins = last_page.margins |
116 | end
|
117 | |
118 | page_options = { |
119 | size: options[:size] || last_page_size, |
120 | layout: options[:layout] || last_page_layout, |
121 | margins: last_page_margins, |
122 | }
|
123 | if last_page |
124 | if last_page.graphic_state |
125 | new_graphic_state = last_page.graphic_state.dup |
126 | end
|
127 | |
128 | # Erase the color space so that it gets reset on new page for fussy
|
129 | # pdf-readers
|
130 | if new_graphic_state |
131 | new_graphic_state.color_space = {} |
132 | end
|
133 | page_options[:graphic_state] = new_graphic_state |
134 | end
|
135 | |
136 | state.page = PDF::Core::Page.new(self, page_options) |
137 | |
138 | state.insert_page(state.page, @page_number) |
139 | @page_number += 1 |
140 | |
141 | state.on_page_create_action(self) |
142 | end
|