prawn 0.11.1 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/GPLv2 +340 -0
  2. data/GPLv3 +674 -0
  3. data/README.md +96 -0
  4. data/Rakefile +0 -12
  5. data/examples/example_helper.rb +3 -0
  6. data/lib/prawn.rb +1 -1
  7. data/lib/prawn/core/page.rb +4 -2
  8. data/lib/prawn/core/pdf_object.rb +7 -7
  9. data/lib/prawn/core/text/formatted/arranger.rb +2 -1
  10. data/lib/prawn/core/text/formatted/line_wrap.rb +2 -1
  11. data/lib/prawn/core/text/formatted/wrap.rb +5 -1
  12. data/lib/prawn/document.rb +135 -112
  13. data/lib/prawn/document/bounding_box.rb +51 -5
  14. data/lib/prawn/document/column_box.rb +0 -19
  15. data/lib/prawn/document/internals.rb +1 -0
  16. data/lib/prawn/document/snapshot.rb +3 -0
  17. data/lib/prawn/font.rb +4 -3
  18. data/lib/prawn/font/afm.rb +11 -2
  19. data/lib/prawn/font/ttf.rb +15 -0
  20. data/lib/prawn/images.rb +1 -1
  21. data/lib/prawn/table.rb +23 -7
  22. data/lib/prawn/table/cell.rb +31 -9
  23. data/lib/prawn/table/cell/text.rb +2 -2
  24. data/prawn.gemspec +5 -6
  25. data/spec/bounding_box_spec.rb +157 -0
  26. data/spec/data/curves.pdf +66 -0
  27. data/spec/document_spec.rb +59 -4
  28. data/spec/extensions/mocha.rb +1 -3
  29. data/spec/font_spec.rb +23 -0
  30. data/spec/formatted_text_box_spec.rb +40 -0
  31. data/spec/images_spec.rb +7 -0
  32. data/spec/object_store_spec.rb +3 -3
  33. data/spec/snapshot_spec.rb +33 -0
  34. data/spec/table_spec.rb +75 -0
  35. data/spec/template_spec.rb +11 -5
  36. data/spec/text_spacing_spec.rb +18 -0
  37. data/spec/text_spec.rb +32 -0
  38. metadata +217 -283
  39. data/HACKING +0 -50
  40. data/README +0 -141
  41. data/examples/bounding_box/bounding_boxes.rb +0 -44
  42. data/examples/bounding_box/indentation.rb +0 -35
  43. data/examples/bounding_box/stretched_nesting.rb +0 -68
  44. data/examples/general/background.rb +0 -24
  45. data/examples/general/canvas.rb +0 -16
  46. data/examples/general/float.rb +0 -12
  47. data/examples/general/margin.rb +0 -37
  48. data/examples/general/measurement_units.rb +0 -52
  49. data/examples/general/metadata-info.rb +0 -17
  50. data/examples/general/multi_page_layout.rb +0 -19
  51. data/examples/general/outlines.rb +0 -67
  52. data/examples/general/page_geometry.rb +0 -32
  53. data/examples/general/page_numbering.rb +0 -40
  54. data/examples/general/page_templates.rb +0 -20
  55. data/examples/general/repeaters.rb +0 -48
  56. data/examples/general/stamp.rb +0 -42
  57. data/examples/general/templates.rb +0 -14
  58. data/examples/graphics/basic_images.rb +0 -24
  59. data/examples/graphics/curves.rb +0 -12
  60. data/examples/graphics/hexagon.rb +0 -14
  61. data/examples/graphics/image_fit.rb +0 -16
  62. data/examples/graphics/image_flow.rb +0 -38
  63. data/examples/graphics/image_position.rb +0 -18
  64. data/examples/graphics/line.rb +0 -33
  65. data/examples/graphics/polygons.rb +0 -17
  66. data/examples/graphics/rounded_polygons.rb +0 -20
  67. data/examples/graphics/rounded_rectangle.rb +0 -21
  68. data/examples/graphics/ruport_style_helpers.rb +0 -20
  69. data/examples/graphics/stroke_bounds.rb +0 -21
  70. data/examples/graphics/stroke_cap_and_join.rb +0 -46
  71. data/examples/graphics/stroke_dash.rb +0 -43
  72. data/examples/graphics/transformations.rb +0 -53
  73. data/examples/graphics/transparency.rb +0 -27
  74. data/examples/grid/bounding_boxes.rb +0 -22
  75. data/examples/grid/column_gutter_grid.rb +0 -21
  76. data/examples/grid/multi_boxes.rb +0 -52
  77. data/examples/grid/show_grid.rb +0 -14
  78. data/examples/grid/simple_grid.rb +0 -21
  79. data/examples/m17n/chinese_text_wrapping.rb +0 -18
  80. data/examples/m17n/euro.rb +0 -16
  81. data/examples/m17n/utf8.rb +0 -14
  82. data/examples/security/hello_foo.rb +0 -9
  83. data/examples/table/borders.rb +0 -25
  84. data/examples/table/cell.rb +0 -13
  85. data/examples/table/checkerboard.rb +0 -23
  86. data/examples/table/inline_format_table.rb +0 -13
  87. data/examples/table/multi_page_table.rb +0 -10
  88. data/examples/table/simple_table.rb +0 -25
  89. data/examples/table/subtable.rb +0 -13
  90. data/examples/table/widths.rb +0 -21
  91. data/examples/text/alignment.rb +0 -19
  92. data/examples/text/character_spacing.rb +0 -13
  93. data/examples/text/dfont.rb +0 -49
  94. data/examples/text/family_based_styling.rb +0 -25
  95. data/examples/text/font_size.rb +0 -34
  96. data/examples/text/inline_format.rb +0 -104
  97. data/examples/text/kerning.rb +0 -31
  98. data/examples/text/rendering_mode.rb +0 -21
  99. data/examples/text/rotated.rb +0 -99
  100. data/examples/text/shaped_text_box.rb +0 -32
  101. data/examples/text/simple_text.rb +0 -18
  102. data/examples/text/simple_text_ttf.rb +0 -18
  103. data/examples/text/span.rb +0 -30
  104. data/examples/text/text_box.rb +0 -90
  105. data/examples/text/text_box_returning_excess.rb +0 -52
  106. data/examples/text/text_flow.rb +0 -68
@@ -0,0 +1,96 @@
1
+ # Prawn: Fast, Nimble PDF Generation For Ruby
2
+
3
+ Prawn is a pure Ruby PDF generation library that provides a lot of great functionality while trying to remain simple and reasonably performant. Here are some of the important features we provide:
4
+
5
+ * Vector drawing support, including lines, polygons, curves, ellipses, etc.
6
+ * Extensive text rendering support, including flowing text and limited inline formatting options.
7
+ * Support for both PDF builtin fonts as well as embedded TrueType fonts
8
+ * A variety of low level tools for basic layout needs, including a simple grid system
9
+ * PNG and JPG image embedding, with flexible scaling options
10
+ * Reporting tools for rendering complex data tables, with pagination support
11
+ * Security features including encryption and password protection
12
+ * Tools for rendering repeatable content (i.e headers, footers, and page numbers)
13
+ * Comprehensive internationalization features, including full support for UTF-8 based fonts, right-to-left text rendering, fallback font support, and extension points for customizable text wrapping.
14
+ * Support for PDF outlines for document navigation
15
+ * Low level PDF features, allowing users to create custom extensions by dropping down all the way to the PDF object tree layer. (Mostly useful to those with knowledge of the PDF specification)
16
+ * Lots of other stuff!
17
+
18
+ ## Should You Use Prawn?
19
+
20
+ If you are looking for a highly flexible PDF document generation system, Prawn might be the tool for you. It is not a reporting tool or a publishing toolchain, though it could be fairly easily used to build those things.
21
+
22
+ One thing Prawn is not, and will never be, is an HTML to PDF generator. For those needs, consider looking into FlyingSaucer via JRuby, or one of the webkit based tools, like Wicked or PDFKit. We do have basic support for inline styling but it is limited to a very small subset of functionality and is not suitable for rendering rich HTML documents.
23
+
24
+ ## Supported Ruby Versions and Implementations
25
+
26
+ Because Prawn is pure Ruby and virtually all of its dependencies are maintained by our core team, it should run pretty much anywhere, including Rubinius, JRuby, MacRuby, etc. While we officially support MRI 1.8.7 and 1.9.2 only, we will accept patches to fix problems on other Ruby platforms if they aren't too invasive.
27
+
28
+ ## Installing Prawn
29
+
30
+ Prawn is distributed via RubyGems, and can be installed the usual way that you install gems: by simply typing `gem install prawn` on the command line.
31
+
32
+ You can also install from git if you'd like, the _master_ branch contains the latest developments, and _stable_ represents the latest bug fixes to the currently released version of Prawn. If you go this route, using Bundler is encouraged.
33
+
34
+ ## Release Policies
35
+
36
+ We may introduce backwards incompatible changes each time our minor version number is bumped, but that any tiny version number bump should be bug fixes and internal changes only. Be sure to read the release notes each time we cut a new release and lock your gems accordingly. You can find the project CHANGELOG at: https://github.com/sandal/prawn/wiki/CHANGELOG
37
+
38
+ ## Hello World!
39
+
40
+ If the following code runs and produces a working PDF file, you've successfully installed Prawn.
41
+
42
+ require "prawn"
43
+
44
+ Prawn::Document.generate("hello.pdf") do
45
+ text "Hello World!"
46
+ end
47
+
48
+ Of course, you'll probably want to do more interesting things than that...
49
+
50
+ ## Manual
51
+
52
+ Mendicant University student Felipe Doria provided us with a beautiful system for generating a user manual from our examples. This can be generated from the prawn source or you can download a pre-generated snapshot of it at http://prawn.majesticseacreature.com/manual.pdf
53
+
54
+ Note that while we will try to keep the downloadable manual up to date, that it's provided as a convenience only and you should generate the manual yourself if you want to be sure the code in it actually runs and works as expected. To build the manual, here's what you need to do:
55
+
56
+ 1. clone the repository
57
+ 2. switch to the stable branch (optional, stay on master for development version)
58
+ 3. install bundler if necessay
59
+ 4. run `bundle install`
60
+ 5. run `bundle exec rake manual`, which will generate _manual.pdf_ in the project root
61
+
62
+ ## Support
63
+
64
+ The easiest way to get help with Prawn is to post a message to our mailing list:
65
+
66
+ <http://groups.google.com/group/prawn-ruby>
67
+
68
+ Feel free to post any Prawn related question there, our community is very responsive and will be happy to help you figure out how to use Prawn, or help you determine whether it's the right tool for the task you are working on.
69
+
70
+ Please make your posts to the list as specific as possible, including code samples and output where relevant. Do not post any information that should not be shared publicly, and be sure to reduce your example code as much as possible so that those who are responding to your question can more easily see what the issue might be.
71
+
72
+ ## Contributing
73
+
74
+ If you've found a bug, want to submit a patch, or have a feature request, please enter a ticket into our github tracker:
75
+
76
+ <http://github.com/sandal/prawn/issues>
77
+
78
+ We strongly encourage bug reports to come with failing tests or at least a reduced example that demonstrates the problem. Similarly, patches should include tests, API documentation, and an update to the manual where relevant. Feel free to send a pull request early though, if you just want some feedback or a code review before preparing your code to be merged.
79
+
80
+ If you are unsure about whether or not you've found a bug, or want to check to see whether we'd be interested in the feature you want to add before you start working on it, feel free to post to our mailing list.
81
+
82
+ ## Authorship
83
+
84
+ Prawn was originally developed by Gregory Brown, under the auspices of the Ruby Mendicant Project, a grassroots initiative in which the Ruby community collectively provided funding so that Gregory could take several months off of work to focus on this project.
85
+
86
+ Over the last several years, we've received code contributions from over 50 people, which is amazing considering the low-level nature of this project. In 2010, Gregory officially handed the project off to the Prawn core team. Currently active maintainers include Brad Ediger, Daniel Nelson, James Healy, and Jonathan Greenberg.
87
+
88
+ While he was only with us for a short time before moving on to other things, we'd also like to thank Prawn core team emeritus Jamis Buck for his contributions. He was responsible for introducing font subsetting as well as the first implementation of our inline formatting support.
89
+
90
+ You can find the full list of folks who have at least one patch accepted to Prawn on github at https://github.com/sandal/prawn/contributors
91
+
92
+ ## License
93
+
94
+ Prawn is released under a slightly modified form of the License of Ruby, allowing you to choose between Matz's terms, the GPLv2, or GPLv3. For details, please see the LICENSE, GPLv2, and GPLv3 files.
95
+
96
+ If you wish to contribute to Prawn, you will retain your own copyright but must agree to license your code under the same terms as the project itself.
data/Rakefile CHANGED
@@ -34,17 +34,6 @@ Rake::RDocTask.new do |rdoc|
34
34
  rdoc.main = "README"
35
35
  rdoc.rdoc_dir = "doc/html"
36
36
  rdoc.title = "Prawn Documentation"
37
- end
38
-
39
- desc "run all examples"
40
- task :examples do
41
- mkdir_p "output"
42
- examples = Dir["examples/**/*.rb"]
43
- t = Time.now
44
- puts "Running Examples"
45
- examples.each { |file| `ruby -Ilib #{file}` }
46
- puts "Ran in #{Time.now - t} s"
47
- `mv *.pdf output`
48
37
  end
49
38
 
50
39
  desc "Generate the 'Prawn by Example' manual"
@@ -60,4 +49,3 @@ Rake::GemPackageTask.new(spec) do |pkg|
60
49
  pkg.need_zip = true
61
50
  pkg.need_tar = true
62
51
  end
63
-
@@ -1,5 +1,8 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  require 'rubygems'
3
+ require "bundler"
4
+ Bundler.setup
5
+
3
6
  require 'prawn'
4
7
  require 'prawn/security'
5
8
  require "prawn/layout"
@@ -5,7 +5,7 @@
5
5
  # into the lib/prawn/core/* source tree.
6
6
  #
7
7
  module Prawn #:nodoc:
8
- VERSION = "0.11.1"
8
+ VERSION = "0.12.0"
9
9
  end
10
10
 
11
11
  require "prawn/core"
@@ -28,7 +28,7 @@ module Prawn
28
28
  init_from_object(options)
29
29
  else
30
30
  init_new_page(options)
31
- end
31
+ end
32
32
  end
33
33
 
34
34
  def layout
@@ -58,7 +58,7 @@ module Prawn
58
58
  document.save_graphics_state
59
59
  document.send(:freeze_stamp_graphics)
60
60
  yield if block_given?
61
-
61
+
62
62
  until graphic_stack_size == stack.stack.size
63
63
  document.restore_graphics_state
64
64
  end
@@ -160,6 +160,8 @@ module Prawn
160
160
 
161
161
  def init_from_object(options)
162
162
  @dictionary = options[:object_id].to_i
163
+ dictionary.data[:Parent] = document.state.store.pages
164
+
163
165
  unless dictionary.data[:Contents].is_a?(Array) # content only on leafs
164
166
  @content = dictionary.data[:Contents].identifier
165
167
  end
@@ -13,7 +13,13 @@ module Prawn
13
13
 
14
14
  module_function
15
15
 
16
- ruby_18 do
16
+ if "".respond_to?(:encode)
17
+ # Ruby 1.9+
18
+ def utf8_to_utf16(str)
19
+ "\xFE\xFF".force_encoding("UTF-16BE") + str.encode("UTF-16BE")
20
+ end
21
+ else
22
+ # Ruby 1.8
17
23
  def utf8_to_utf16(str)
18
24
  utf16 = "\xFE\xFF"
19
25
 
@@ -31,12 +37,6 @@ module Prawn
31
37
  utf16
32
38
  end
33
39
  end
34
-
35
- ruby_19 do
36
- def utf8_to_utf16(str)
37
- "\xFE\xFF".force_encoding("UTF-16BE") + str.encode("UTF-16BE")
38
- end
39
- end
40
40
 
41
41
  # Serializes Ruby objects to their PDF equivalents. Most primitive objects
42
42
  # will work as expected, but please note that Name objects are represented
@@ -23,10 +23,11 @@ module Prawn
23
23
  attr_reader :fragments
24
24
  attr_reader :current_format_state
25
25
 
26
- def initialize(document)
26
+ def initialize(document, options={})
27
27
  @document = document
28
28
  @fragments = []
29
29
  @unconsumed = []
30
+ @kerning = options[:kerning]
30
31
  end
31
32
 
32
33
  def space_count
@@ -203,7 +203,8 @@ module Prawn
203
203
  @previous_fragment = @fragment_output.dup
204
204
  pf = @previous_fragment
205
205
  @previous_fragment_ended_with_breakable = pf =~ /[#{break_chars}]$/
206
- last_word_length = pf.slice(/[^#{break_chars}]*$/).length
206
+ last_word = pf.slice(/[^#{break_chars}]*$/)
207
+ last_word_length = last_word.nil? ? 0 : last_word.length
207
208
  @previous_fragment_output_without_last_word = pf.slice(0, pf.length - last_word_length)
208
209
  end
209
210
 
@@ -9,7 +9,8 @@ module Prawn
9
9
 
10
10
  def initialize(array, options)
11
11
  @line_wrap = Prawn::Core::Text::Formatted::LineWrap.new
12
- @arranger = Prawn::Core::Text::Formatted::Arranger.new(@document)
12
+ @arranger = Prawn::Core::Text::Formatted::Arranger.new(@document,
13
+ :kerning => options[:kerning])
13
14
  end
14
15
 
15
16
 
@@ -38,6 +39,9 @@ module Prawn
38
39
 
39
40
  stop = false
40
41
  while !stop
42
+ # wrap before testing if enough height for this line because the
43
+ # height of the highest fragment on this line will be used to
44
+ # determine the line height
41
45
  @line_wrap.wrap_line(:document => @document,
42
46
  :kerning => @kerning,
43
47
  :width => available_width,
@@ -169,113 +169,122 @@ module Prawn
169
169
  # pdf = Prawn::Document.new(:background => "#{Prawn::BASEDIR}/data/images/pigs.jpg")
170
170
  #
171
171
  def initialize(options={},&block)
172
- Prawn.verify_options [:page_size, :page_layout, :margin, :left_margin,
173
- :right_margin, :top_margin, :bottom_margin, :skip_page_creation,
174
- :compress, :skip_encoding, :background, :info,
175
- :optimize_objects, :template], options
176
-
177
- # need to fix, as the refactoring breaks this
178
- # raise NotImplementedError if options[:skip_page_creation]
179
-
180
- self.class.extensions.reverse_each { |e| extend e }
181
- @internal_state = Prawn::Core::DocumentState.new(options)
182
- @internal_state.populate_pages_from_store(self)
183
- min_version(state.store.min_version) if state.store.min_version
184
-
185
- @background = options[:background]
186
- @font_size = 12
187
-
188
- @bounding_box = nil
189
- @margin_box = nil
190
-
191
- @page_number = 0
192
-
193
- options[:size] = options.delete(:page_size)
194
- options[:layout] = options.delete(:page_layout)
195
-
196
- if options[:template]
197
- fresh_content_streams(options)
198
- go_to_page(1)
199
- else
200
- if options[:skip_page_creation] || options[:template]
201
- start_new_page(options.merge(:orphan => true))
202
- else
203
- start_new_page(options)
204
- end
205
- end
206
-
207
- @bounding_box = @margin_box
208
-
209
- if block
210
- block.arity < 1 ? instance_eval(&block) : block[self]
211
- end
212
- end
213
-
214
- attr_accessor :margin_box
215
- attr_reader :margins, :y
216
- attr_writer :font_size
217
- attr_accessor :page_number
218
-
219
- def state
220
- @internal_state
221
- end
222
-
223
- def page
224
- state.page
225
- end
226
-
227
- # Creates and advances to a new page in the document.
228
- #
229
- # Page size, margins, and layout can also be set when generating a
230
- # new page. These values will become the new defaults for page creation
231
- #
232
- # pdf.start_new_page #=> Starts new page keeping current values
233
- # pdf.start_new_page(:size => "LEGAL", :layout => :landscape)
234
- # pdf.start_new_page(:left_margin => 50, :right_margin => 50)
235
- # pdf.start_new_page(:margin => 100)
236
- #
237
- # A template for a page can be specified by pointing to the path of and existing pdf.
238
- # One can also specify which page of the template which defaults otherwise to 1.
239
- #
240
- # pdf.start_new_page(:template => multipage_template.pdf, :template_page => 2)
241
- #
242
- def start_new_page(options = {})
243
- if last_page = state.page
244
- last_page_size = last_page.size
245
- last_page_layout = last_page.layout
246
- last_page_margins = last_page.margins
247
- end
248
-
249
- page_options = {:size => options[:size] || last_page_size,
250
- :layout => options[:layout] || last_page_layout,
251
- :margins => last_page_margins}
252
- if last_page
253
- new_graphic_state = last_page.graphic_state.dup
254
- #erase the color space so that it gets reset on new page for fussy pdf-readers
255
- new_graphic_state.color_space = {}
256
- page_options.merge!(:graphic_state => new_graphic_state)
257
- end
258
- merge_template_options(page_options, options) if options[:template]
259
-
260
- state.page = Prawn::Core::Page.new(self, page_options)
261
-
262
- apply_margin_options(options)
263
- state.page.new_content_stream if options[:template]
264
- use_graphic_settings(options[:template])
265
-
266
- unless options[:orphan]
267
- state.insert_page(state.page, @page_number)
268
- @page_number += 1
269
-
270
- canvas { image(@background, :at => bounds.top_left) } if @background
271
- @y = @bounding_box.absolute_top
272
-
273
- float do
274
- state.on_page_create_action(self)
275
- end
276
- end
172
+ options = options.dup
173
+
174
+ Prawn.verify_options [:page_size, :page_layout, :margin, :left_margin,
175
+ :right_margin, :top_margin, :bottom_margin, :skip_page_creation,
176
+ :compress, :skip_encoding, :background, :info,
177
+ :optimize_objects, :template], options
178
+
179
+ # need to fix, as the refactoring breaks this
180
+ # raise NotImplementedError if options[:skip_page_creation]
181
+
182
+ self.class.extensions.reverse_each { |e| extend e }
183
+ @internal_state = Prawn::Core::DocumentState.new(options)
184
+ @internal_state.populate_pages_from_store(self)
185
+ min_version(state.store.min_version) if state.store.min_version
186
+
187
+ @background = options[:background]
188
+ @font_size = 12
189
+
190
+ @bounding_box = nil
191
+ @margin_box = nil
192
+
193
+ @page_number = 0
194
+
195
+ options[:size] = options.delete(:page_size)
196
+ options[:layout] = options.delete(:page_layout)
197
+
198
+ if options[:template]
199
+ fresh_content_streams(options)
200
+ go_to_page(1)
201
+ else
202
+ if options[:skip_page_creation] || options[:template]
203
+ start_new_page(options.merge(:orphan => true))
204
+ else
205
+ start_new_page(options)
206
+ end
207
+ end
208
+
209
+ @bounding_box = @margin_box
210
+
211
+ if block
212
+ block.arity < 1 ? instance_eval(&block) : block[self]
213
+ end
214
+ end
215
+
216
+ attr_accessor :margin_box
217
+ attr_reader :margins, :y
218
+ attr_writer :font_size
219
+ attr_accessor :page_number
220
+
221
+ def state
222
+ @internal_state
223
+ end
224
+
225
+ def page
226
+ state.page
227
+ end
228
+
229
+ # Creates and advances to a new page in the document.
230
+ #
231
+ # Page size, margins, and layout can also be set when generating a
232
+ # new page. These values will become the new defaults for page creation
233
+ #
234
+ # pdf.start_new_page #=> Starts new page keeping current values
235
+ # pdf.start_new_page(:size => "LEGAL", :layout => :landscape)
236
+ # pdf.start_new_page(:left_margin => 50, :right_margin => 50)
237
+ # pdf.start_new_page(:margin => 100)
238
+ #
239
+ # A template for a page can be specified by pointing to the path of and existing pdf.
240
+ # One can also specify which page of the template which defaults otherwise to 1.
241
+ #
242
+ # pdf.start_new_page(:template => multipage_template.pdf, :template_page => 2)
243
+ #
244
+ def start_new_page(options = {})
245
+ if last_page = state.page
246
+ last_page_size = last_page.size
247
+ last_page_layout = last_page.layout
248
+ last_page_margins = last_page.margins
249
+ end
250
+
251
+ page_options = {:size => options[:size] || last_page_size,
252
+ :layout => options[:layout] || last_page_layout,
253
+ :margins => last_page_margins}
254
+ if last_page
255
+ new_graphic_state = last_page.graphic_state.dup
256
+ #erase the color space so that it gets reset on new page for fussy pdf-readers
257
+ new_graphic_state.color_space = {}
258
+ page_options.merge!(:graphic_state => new_graphic_state)
259
+ end
260
+ merge_template_options(page_options, options) if options[:template]
261
+
262
+ state.page = Prawn::Core::Page.new(self, page_options)
263
+
264
+ apply_margin_options(options)
265
+ generate_margin_box
266
+
267
+ # Reset the bounding box if the new page has different size or layout
268
+ if last_page && (last_page.size != state.page.size ||
269
+ last_page.layout != state.page.layout)
270
+ @bounding_box = @margin_box
271
+ end
272
+
273
+ state.page.new_content_stream if options[:template]
274
+ use_graphic_settings(options[:template])
277
275
 
278
- end
276
+ unless options[:orphan]
277
+ state.insert_page(state.page, @page_number)
278
+ @page_number += 1
279
+
280
+ canvas { image(@background, :at => bounds.top_left) } if @background
281
+ @y = @bounding_box.absolute_top
282
+
283
+ float do
284
+ state.on_page_create_action(self)
285
+ end
286
+ end
287
+ end
279
288
 
280
289
  # Returns the number of pages in the document
281
290
  #
@@ -318,7 +327,9 @@ module Prawn
318
327
  self.y = new_y + bounds.absolute_bottom
319
328
  end
320
329
 
321
- # Executes a block and then restores the original y position
330
+ # Executes a block and then restores the original y position. If new pages
331
+ # were created during this block, it will teleport back to the original
332
+ # page when done.
322
333
  #
323
334
  # pdf.text "A"
324
335
  #
@@ -330,7 +341,11 @@ module Prawn
330
341
  # pdf.text "B"
331
342
  #
332
343
  def float
333
- mask(:y) { yield }
344
+ original_page = page_number
345
+ original_y = y
346
+ yield
347
+ go_to_page(original_page) unless page_number == original_page
348
+ self.y = original_y
334
349
  end
335
350
 
336
351
  # Renders the PDF document to string
@@ -388,6 +403,12 @@ module Prawn
388
403
  @bounding_box
389
404
  end
390
405
 
406
+ # Returns the innermost non-stretchy bounding box.
407
+ #
408
+ def reference_bounds
409
+ @bounding_box.reference_bounds
410
+ end
411
+
391
412
  # Sets Document#bounds to the BoundingBox provided. See above for a brief
392
413
  # description of what a bounding box is. This function is useful if you
393
414
  # really need to change the bounding box manually, but usually, just entering
@@ -548,7 +569,11 @@ module Prawn
548
569
  def number_pages(string, options={})
549
570
  opts = options.dup
550
571
  start_count_at = opts.delete(:start_count_at).to_i
551
- page_filter = opts.delete(:page_filter)
572
+ page_filter = if opts.has_key?(:page_filter)
573
+ opts.delete(:page_filter)
574
+ else
575
+ :all
576
+ end
552
577
  total_pages = opts.delete(:total_pages)
553
578
  txtcolor = opts.delete(:color)
554
579
  # An explicit height so that we can draw page numbers in the margins
@@ -642,7 +667,7 @@ module Prawn
642
667
  )
643
668
 
644
669
  # This check maintains indentation settings across page breaks
645
- if (old_margin_box)
670
+ if old_margin_box
646
671
  @margin_box.add_left_padding(old_margin_box.total_left_padding)
647
672
  @margin_box.add_right_padding(old_margin_box.total_right_padding)
648
673
  end
@@ -671,8 +696,6 @@ module Prawn
671
696
  state.page.margins[side] = margin
672
697
  end
673
698
  end
674
-
675
- generate_margin_box
676
699
  end
677
700
  end
678
701
  end