Skip to content

Commit

Permalink
After importing template content streams, create a new empty content …
Browse files Browse the repository at this point in the history
…stream for each page

* prawn will add it's content to the new stream
* means we can leave the old streams in the pristene state they were
  imported in, even if they use filters we don't recognise, etc
  • Loading branch information
yob committed Mar 28, 2010
1 parent 681a4a4 commit d899a5e
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 7 deletions.
25 changes: 23 additions & 2 deletions lib/prawn/core/page.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,20 @@ def content
@stamp_stream || document.state.store[@content]
end

# As per the PDF spec, each page can have multiple content streams. This will
# add a fresh, empty content stream this the page, mainly for use in loading
# template files.
#
def new_content_stream
return if in_stamp_stream?

unless dictionary.data[:Contents].is_a?(Array)
dictionary.data[:Contents] = [content]
end
@content = document.ref(:Length => 0)
dictionary.data[:Contents] << document.state.store[@content]
end

def dictionary
@stamp_dictionary || document.state.store[@dictionary]
end
Expand Down Expand Up @@ -102,8 +116,15 @@ def ext_gstates
end

def finalize
content.compress_stream if document.compression_enabled?
content.data[:Length] = content.stream.size
if dictionary.data[:Contents].is_a?(Array)
dictionary.data[:Contents].each do |stream|
stream.compress_stream if document.compression_enabled?
stream.data[:Length] = stream.stream.size
end
else
content.compress_stream if document.compression_enabled?
content.data[:Length] = content.stream.size
end
end

private
Expand Down
10 changes: 5 additions & 5 deletions lib/prawn/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,10 @@ def initialize(options={},&block)
options[:size] = options.delete(:page_size)
options[:layout] = options.delete(:page_layout)

if !options[:template]
if options[:template]
fresh_content_streams
go_to_page(1)
else
if options[:skip_page_creation] || options[:template]
start_new_page(options.merge(:orphan => true))
else
Expand All @@ -207,7 +210,6 @@ def initialize(options={},&block)
end

@bounding_box = @margin_box
go_to_page(1) if options[:template]

if block
block.arity < 1 ? instance_eval(&block) : block[self]
Expand Down Expand Up @@ -291,8 +293,7 @@ def page_count
end

# Re-opens the page with the given (1-based) page number so that you can
# draw on it. Does not restore page state such as margins, page orientation,
# or paper size, so you'll have to handle that yourself.
# draw on it.
#
# See Prawn::Document#number_pages for a sample usage of this capability.
#
Expand All @@ -315,7 +316,6 @@ def cursor
y - bounds.absolute_bottom
end


# Moves to the specified y position in relative terms to the bottom margin.
#
def move_cursor_to(new_y)
Expand Down
11 changes: 11 additions & 0 deletions lib/prawn/document/internals.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ def on_page_create(&block)

private

# adds a new, empty content stream to each page. Used in templating so
# that imported content streams can be left pristine
#
def fresh_content_streams
(1..page_count).each do |i|
go_to_page i
state.page.new_content_stream
use_graphic_settings
end
end

def finalize_all_page_contents
(1..page_count).each do |i|
go_to_page i
Expand Down
26 changes: 26 additions & 0 deletions spec/document_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -433,3 +433,29 @@
text.strings.include?("Healy").should == true
end
end

describe "content stream characteristics" do
it "should have 1 single content stream for a single page PDF with no templates" do
@pdf = Prawn::Document.new
@pdf.text "James"
output = StringIO.new(@pdf.render)
hash = PDF::Hash.new(output)

streams = hash.values.select { |obj| obj.kind_of?(PDF::Reader::Stream) }

streams.size.should == 1
end

it "should have 1 single content stream for a single page PDF with no templates, even if go_to_page is used" do
@pdf = Prawn::Document.new
@pdf.text "James"
@pdf.go_to_page(1)
@pdf.text "Healy"
output = StringIO.new(@pdf.render)
hash = PDF::Hash.new(output)

streams = hash.values.select { |obj| obj.kind_of?(PDF::Reader::Stream) }

streams.size.should == 1
end
end
12 changes: 12 additions & 0 deletions spec/template_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@
pages.size.should == 1
end

it "should have two content streams if importing a single page template" do
filename = "#{Prawn::BASEDIR}/data/pdfs/hexagon.pdf"

@pdf = Prawn::Document.new(:template => filename)
output = StringIO.new(@pdf.render)
hash = PDF::Hash.new(output)

streams = hash.values.select { |obj| obj.kind_of?(PDF::Reader::Stream) }

streams.size.should == 2
end

it "should allow text to be added to a single page template" do
filename = "#{Prawn::BASEDIR}/data/pdfs/hexagon.pdf"

Expand Down

0 comments on commit d899a5e

Please sign in to comment.