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(k) ⇒ 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.
6 7 8 9 10 11 12 13 |
# File 'lib/pdf/core/renderer.rb', line 6 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.
15 16 17 |
# File 'lib/pdf/core/renderer.rb', line 15 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("%.3f %.3f m" % [ x1, y1 ]) # move
pdf.add_content("%.3f %.3f l" % [ x2, y2 ]) # draw path
pdf.add_content("S") # stroke
54 55 56 57 |
# File 'lib/pdf/core/renderer.rb', line 54 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.
75 76 77 |
# File 'lib/pdf/core/renderer.rb', line 75 def before_render(&block) state.before_render_callbacks << block end |
#close_graphics_state ⇒ Object
227 228 229 |
# File 'lib/pdf/core/renderer.rb', line 227 def close_graphics_state add_content "Q" end |
#compression_enabled? ⇒ Boolean
Returns true if content streams will be compressed before rendering, false otherwise
243 244 245 |
# File 'lib/pdf/core/renderer.rb', line 243 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().
42 43 44 |
# File 'lib/pdf/core/renderer.rb', line 42 def deref(obj) obj.is_a?(PDF::Core::Reference) ? obj.data : obj end |
#finalize_all_page_contents ⇒ Object
129 130 131 132 133 134 135 136 137 |
# File 'lib/pdf/core/renderer.rb', line 129 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(k) ⇒ 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.
124 125 126 127 |
# File 'lib/pdf/core/renderer.rb', line 124 def go_to_page(k) @page_number = k state.page = state.pages[k-1] end |
#graphic_stack ⇒ Object
258 259 260 |
# File 'lib/pdf/core/renderer.rb', line 258 def graphic_stack state.page.stack end |
#graphic_state ⇒ Object
262 263 264 265 |
# File 'lib/pdf/core/renderer.rb', line 262 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.
143 144 145 |
# File 'lib/pdf/core/renderer.rb', line 143 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.
63 64 65 |
# File 'lib/pdf/core/renderer.rb', line 63 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.
69 70 71 |
# File 'lib/pdf/core/renderer.rb', line 69 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.
81 82 83 84 85 86 87 |
# File 'lib/pdf/core/renderer.rb', line 81 def on_page_create(&block) if block_given? state.on_page_create_callback = block else state.on_page_create_callback = nil end end |
#open_graphics_state ⇒ Object
223 224 225 |
# File 'lib/pdf/core/renderer.rb', line 223 def open_graphics_state add_content "q" end |
#page_count ⇒ Object
115 116 117 |
# File 'lib/pdf/core/renderer.rb', line 115 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::PdfObject() can convert.
Returns the identifier which points to the reference in the ObjectStore
22 23 24 |
# File 'lib/pdf/core/renderer.rb', line 22 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
34 35 36 |
# File 'lib/pdf/core/renderer.rb', line 34 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.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/pdf/core/renderer.rb', line 150 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) return str else return nil end end |
#render_body(output) ⇒ Object
Write out the PDF Body, as per spec 3.4.2
191 192 193 |
# File 'lib/pdf/core/renderer.rb', line 191 def render_body(output) state.render_body(output) end |
#render_file(filename) ⇒ Object
Renders the PDF document to file.
pdf.render_file "foo.pdf"
173 174 175 |
# File 'lib/pdf/core/renderer.rb', line 173 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
179 180 181 182 183 184 185 186 187 |
# File 'lib/pdf/core/renderer.rb', line 179 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
210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/pdf/core/renderer.rb', line 210 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::PdfObject(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
197 198 199 200 201 202 203 204 205 206 |
# File 'lib/pdf/core/renderer.rb', line 197 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("%010d", 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
249 250 251 252 253 254 255 256 |
# File 'lib/pdf/core/renderer.rb', line 249 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
231 232 233 234 235 236 237 238 |
# File 'lib/pdf/core/renderer.rb', line 231 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
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/pdf/core/renderer.rb', line 89 def start_new_page( = {}) if last_page = state.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 new_graphic_state = last_page.graphic_state.dup if last_page.graphic_state #erase the color space so that it gets reset on new page for fussy pdf-readers new_graphic_state.color_space = {} if new_graphic_state .merge!(: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 |