Class: PDF::Core::Renderer
- Inherits:
-
Object
- Object
- PDF::Core::Renderer
- Defined in:
- lib/pdf/core/renderer.rb
Instance Attribute Summary collapse
-
#state ⇒ Object
readonly
Returns the value of attribute state.
Instance Method Summary collapse
-
#add_content(str) ⇒ Object
Appends a raw string to the current page content.
-
#before_render(&block) ⇒ Object
Defines a block to be called just before the document is rendered.
- #close_graphics_state ⇒ Object
-
#compression_enabled? ⇒ Boolean
Returns true if content streams will be compressed before rendering, false otherwise.
-
#deref(obj) ⇒ Object
At any stage in the object tree an object can be replaced with an indirect reference.
- #finalize_all_page_contents ⇒ Object
-
#go_to_page(page_number) ⇒ Object
Re-opens the page with the given (1-based) page number so that you can draw on it.
- #graphic_stack ⇒ Object
- #graphic_state ⇒ Object
-
#initialize(state) ⇒ Renderer
constructor
A new instance of Renderer.
-
#min_version(min) ⇒ Object
raise the PDF version of the file we’re going to generate.
-
#names ⇒ Object
The Name dictionary (PDF spec 3.6.3) for this document.
-
#names? ⇒ Boolean
Returns true if the Names dictionary is in use for this document.
-
#on_page_create(&block) ⇒ Object
Defines a block to be called just before a new page is started.
- #open_graphics_state ⇒ Object
- #page_count ⇒ Object
-
#ref(data) ⇒ Object
Creates a new Reference and adds it to the Document’s object list.
-
#ref!(data) ⇒ Object
Like ref, but returns the actual reference instead of its identifier.
-
#render(output = StringIO.new) ⇒ Object
Renders the PDF document to string.
-
#render_body(output) ⇒ Object
Write out the PDF Body, as per spec 3.4.2.
-
#render_file(filename) ⇒ Object
Renders the PDF document to file.
-
#render_header(output) ⇒ Object
Write out the PDF Header, as per spec 3.4.1.
-
#render_trailer(output) ⇒ Object
Write out the PDF Trailer, as per spec 3.4.4.
-
#render_xref(output) ⇒ Object
Write out the PDF Cross Reference Table, as per spec 3.4.3.
-
#restore_graphics_state ⇒ Object
Pops the last saved graphics state off the graphics state stack and restores the state to those values.
- #save_graphics_state(graphic_state = nil) ⇒ Object
- #start_new_page(options = {}) ⇒ Object
Constructor Details
#initialize(state) ⇒ Renderer
Returns a new instance of Renderer.
8 9 10 11 12 13 14 15 |
# 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 |
Instance Attribute Details
#state ⇒ Object (readonly)
Returns the value of attribute state.
17 18 19 |
# File 'lib/pdf/core/renderer.rb', line 17 def state @state end |
Instance Method Details
#add_content(str) ⇒ Object
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
57 58 59 60 |
# 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 |
#before_render(&block) ⇒ Object
Defines a block to be called just before the document is rendered.
78 79 80 |
# File 'lib/pdf/core/renderer.rb', line 78 def before_render(&block) state.before_render_callbacks << block end |
#close_graphics_state ⇒ Object
237 238 239 |
# File 'lib/pdf/core/renderer.rb', line 237 def close_graphics_state add_content 'Q' end |
#compression_enabled? ⇒ Boolean
Returns true if content streams will be compressed before rendering, false otherwise
253 254 255 |
# File 'lib/pdf/core/renderer.rb', line 253 def compression_enabled? state.compress end |
#deref(obj) ⇒ Object
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().
44 45 46 |
# File 'lib/pdf/core/renderer.rb', line 44 def deref(obj) obj.is_a?(PDF::Core::Reference) ? obj.data : obj end |
#finalize_all_page_contents ⇒ Object
139 140 141 142 143 144 145 146 147 |
# 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 |
#go_to_page(page_number) ⇒ Object
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.
134 135 136 137 |
# 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 |
#graphic_stack ⇒ Object
268 269 270 |
# File 'lib/pdf/core/renderer.rb', line 268 def graphic_stack state.page.stack end |
#graphic_state ⇒ Object
272 273 274 275 |
# File 'lib/pdf/core/renderer.rb', line 272 def graphic_state save_graphics_state unless graphic_stack.current_state graphic_stack.current_state end |
#min_version(min) ⇒ Object
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.
153 154 155 |
# File 'lib/pdf/core/renderer.rb', line 153 def min_version(min) state.version = min if min > state.version end |
#names ⇒ Object
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.
66 67 68 |
# File 'lib/pdf/core/renderer.rb', line 66 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.
72 73 74 |
# File 'lib/pdf/core/renderer.rb', line 72 def names? state.store.root.data[:Names] end |
#on_page_create(&block) ⇒ Object
Defines a block to be called just before a new page is started.
84 85 86 87 88 89 |
# File 'lib/pdf/core/renderer.rb', line 84 def on_page_create(&block) state.on_page_create_callback = if block_given? block end end |
#open_graphics_state ⇒ Object
233 234 235 |
# File 'lib/pdf/core/renderer.rb', line 233 def open_graphics_state add_content 'q' end |
#page_count ⇒ Object
125 126 127 |
# File 'lib/pdf/core/renderer.rb', line 125 def page_count state.page_count end |
#ref(data) ⇒ Object
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
24 25 26 |
# File 'lib/pdf/core/renderer.rb', line 24 def ref(data) ref!(data).identifier end |
#ref!(data) ⇒ Object
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
36 37 38 |
# File 'lib/pdf/core/renderer.rb', line 36 def ref!(data) state.store.ref(data) end |
#render(output = StringIO.new) ⇒ Object
Renders the PDF document to string. Pass an open file descriptor to render to file.
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# 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 |
#render_body(output) ⇒ Object
Write out the PDF Body, as per spec 3.4.2
199 200 201 |
# File 'lib/pdf/core/renderer.rb', line 199 def render_body(output) state.render_body(output) end |
#render_file(filename) ⇒ Object
Renders the PDF document to file.
pdf.render_file 'foo.pdf'
181 182 183 |
# File 'lib/pdf/core/renderer.rb', line 181 def render_file(filename) File.open(filename, 'wb') { |f| render(f) } end |
#render_header(output) ⇒ Object
Write out the PDF Header, as per spec 3.4.1
187 188 189 190 191 192 193 194 195 |
# 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 |
#render_trailer(output) ⇒ Object
Write out the PDF Trailer, as per spec 3.4.4
218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# 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 |
#render_xref(output) ⇒ Object
Write out the PDF Cross Reference Table, as per spec 3.4.3
205 206 207 208 209 210 211 212 213 214 |
# 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 |
#restore_graphics_state ⇒ Object
Pops the last saved graphics state off the graphics state stack and restores the state to those values
259 260 261 262 263 264 265 266 |
# 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 |
#save_graphics_state(graphic_state = nil) ⇒ Object
241 242 243 244 245 246 247 248 |
# 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 |
#start_new_page(options = {}) ⇒ Object
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/pdf/core/renderer.rb', line 91 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 |