prawn 1.0.0.rc2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +9 -0
  3. data/COPYING +2 -2
  4. data/Gemfile +8 -15
  5. data/LICENSE +1 -1
  6. data/Rakefile +25 -16
  7. data/data/images/16bit.alpha +0 -0
  8. data/data/images/16bit.color +0 -0
  9. data/data/images/dice.alpha +0 -0
  10. data/data/images/dice.color +0 -0
  11. data/data/images/indexed_color.dat +0 -0
  12. data/data/images/indexed_color.png +0 -0
  13. data/data/images/license.md +8 -0
  14. data/data/images/page_white_text.alpha +0 -0
  15. data/data/images/page_white_text.color +0 -0
  16. data/lib/prawn.rb +85 -23
  17. data/lib/prawn/document.rb +134 -116
  18. data/lib/prawn/document/bounding_box.rb +33 -4
  19. data/lib/prawn/document/column_box.rb +18 -6
  20. data/lib/prawn/document/graphics_state.rb +11 -74
  21. data/lib/prawn/document/internals.rb +24 -23
  22. data/lib/prawn/document/span.rb +12 -10
  23. data/lib/prawn/encoding.rb +8 -9
  24. data/lib/prawn/errors.rb +13 -32
  25. data/lib/prawn/font.rb +137 -105
  26. data/lib/prawn/font/afm.rb +76 -32
  27. data/lib/prawn/font/dfont.rb +4 -3
  28. data/lib/prawn/font/ttf.rb +33 -25
  29. data/lib/prawn/font_metric_cache.rb +47 -0
  30. data/lib/prawn/graphics.rb +177 -57
  31. data/lib/prawn/graphics/cap_style.rb +4 -3
  32. data/lib/prawn/graphics/color.rb +5 -4
  33. data/lib/prawn/graphics/dash.rb +53 -31
  34. data/lib/prawn/graphics/join_style.rb +9 -7
  35. data/lib/prawn/graphics/patterns.rb +4 -15
  36. data/lib/prawn/graphics/transformation.rb +10 -9
  37. data/lib/prawn/graphics/transparency.rb +3 -1
  38. data/lib/prawn/{layout/grid.rb → grid.rb} +72 -54
  39. data/lib/prawn/image_handler.rb +42 -0
  40. data/lib/prawn/images.rb +58 -54
  41. data/lib/prawn/images/image.rb +6 -22
  42. data/lib/prawn/images/jpg.rb +20 -14
  43. data/lib/prawn/images/png.rb +58 -121
  44. data/lib/prawn/layout.rb +12 -15
  45. data/lib/prawn/measurement_extensions.rb +10 -6
  46. data/lib/prawn/measurements.rb +27 -21
  47. data/lib/prawn/outline.rb +108 -147
  48. data/lib/prawn/repeater.rb +10 -8
  49. data/lib/prawn/security.rb +59 -40
  50. data/lib/prawn/security/arcfour.rb +52 -0
  51. data/lib/prawn/soft_mask.rb +4 -4
  52. data/lib/prawn/stamp.rb +5 -3
  53. data/lib/prawn/table.rb +83 -60
  54. data/lib/prawn/table/cell.rb +17 -21
  55. data/lib/prawn/table/cell/image.rb +2 -3
  56. data/lib/prawn/table/cell/in_table.rb +8 -2
  57. data/lib/prawn/table/cell/span_dummy.rb +5 -0
  58. data/lib/prawn/table/cell/subtable.rb +3 -2
  59. data/lib/prawn/table/cell/text.rb +14 -12
  60. data/lib/prawn/table/cells.rb +58 -14
  61. data/lib/prawn/table/column_width_calculator.rb +61 -0
  62. data/lib/prawn/text.rb +27 -26
  63. data/lib/prawn/text/box.rb +12 -6
  64. data/lib/prawn/text/formatted.rb +5 -4
  65. data/lib/prawn/text/formatted/arranger.rb +290 -0
  66. data/lib/prawn/text/formatted/box.rb +85 -57
  67. data/lib/prawn/text/formatted/fragment.rb +11 -11
  68. data/lib/prawn/text/formatted/line_wrap.rb +266 -0
  69. data/lib/prawn/text/formatted/parser.rb +11 -4
  70. data/lib/prawn/text/formatted/wrap.rb +156 -0
  71. data/lib/prawn/utilities.rb +5 -3
  72. data/manual/document_and_page_options/document_and_page_options.rb +2 -1
  73. data/manual/document_and_page_options/metadata.rb +3 -3
  74. data/manual/document_and_page_options/page_size.rb +2 -2
  75. data/manual/document_and_page_options/print_scaling.rb +20 -0
  76. data/manual/example_file.rb +2 -7
  77. data/manual/example_helper.rb +62 -81
  78. data/manual/graphics/common_lines.rb +2 -0
  79. data/manual/graphics/helper.rb +11 -4
  80. data/manual/graphics/stroke_dash.rb +19 -14
  81. data/manual/manual/cover.rb +16 -0
  82. data/manual/manual/manual.rb +1 -5
  83. data/manual/text/fallback_fonts.rb +4 -4
  84. data/manual/text/formatted_text.rb +5 -5
  85. data/manual/text/inline.rb +2 -4
  86. data/manual/text/registering_families.rb +12 -12
  87. data/manual/text/single_usage.rb +4 -4
  88. data/manual/text/text.rb +0 -2
  89. data/prawn.gemspec +21 -13
  90. data/spec/acceptance/png.rb +23 -0
  91. data/spec/annotations_spec.rb +16 -32
  92. data/spec/bounding_box_spec.rb +22 -5
  93. data/spec/cell_spec.rb +49 -5
  94. data/spec/column_box_spec.rb +32 -0
  95. data/spec/destinations_spec.rb +5 -5
  96. data/spec/document_spec.rb +112 -118
  97. data/spec/extensions/encoding_helpers.rb +5 -2
  98. data/spec/font_metric_cache_spec.rb +52 -0
  99. data/spec/font_spec.rb +121 -120
  100. data/spec/formatted_text_arranger_spec.rb +24 -24
  101. data/spec/formatted_text_box_spec.rb +31 -32
  102. data/spec/formatted_text_fragment_spec.rb +2 -2
  103. data/spec/graphics_spec.rb +63 -45
  104. data/spec/grid_spec.rb +24 -13
  105. data/spec/image_handler_spec.rb +54 -0
  106. data/spec/images_spec.rb +34 -21
  107. data/spec/inline_formatted_text_parser_spec.rb +69 -20
  108. data/spec/jpg_spec.rb +3 -3
  109. data/spec/line_wrap_spec.rb +25 -14
  110. data/spec/measurement_units_spec.rb +5 -5
  111. data/spec/outline_spec.rb +68 -64
  112. data/spec/png_spec.rb +15 -18
  113. data/spec/reference_spec.rb +2 -82
  114. data/spec/repeater_spec.rb +1 -1
  115. data/spec/security_spec.rb +41 -9
  116. data/spec/soft_mask_spec.rb +0 -40
  117. data/spec/span_spec.rb +6 -11
  118. data/spec/spec_helper.rb +20 -2
  119. data/spec/stamp_spec.rb +19 -20
  120. data/spec/stroke_styles_spec.rb +31 -13
  121. data/spec/table/span_dummy_spec.rb +17 -0
  122. data/spec/table_spec.rb +268 -43
  123. data/spec/text_at_spec.rb +13 -27
  124. data/spec/text_box_spec.rb +35 -30
  125. data/spec/text_spec.rb +56 -40
  126. data/spec/transparency_spec.rb +5 -5
  127. metadata +214 -217
  128. data/README.md +0 -98
  129. data/data/fonts/Action Man.dfont +0 -0
  130. data/data/fonts/Activa.ttf +0 -0
  131. data/data/fonts/Chalkboard.ttf +0 -0
  132. data/data/fonts/DejaVuSans.ttf +0 -0
  133. data/data/fonts/Dustismo_Roman.ttf +0 -0
  134. data/data/fonts/comicsans.ttf +0 -0
  135. data/data/fonts/gkai00mp.ttf +0 -0
  136. data/data/images/16bit.dat +0 -0
  137. data/data/images/barcode_issue.png +0 -0
  138. data/data/images/dice.dat +0 -0
  139. data/data/images/page_white_text.dat +0 -0
  140. data/data/images/rails.dat +0 -0
  141. data/data/images/rails.png +0 -0
  142. data/lib/prawn/compatibility.rb +0 -87
  143. data/lib/prawn/core.rb +0 -87
  144. data/lib/prawn/core/annotations.rb +0 -61
  145. data/lib/prawn/core/byte_string.rb +0 -9
  146. data/lib/prawn/core/destinations.rb +0 -90
  147. data/lib/prawn/core/document_state.rb +0 -79
  148. data/lib/prawn/core/literal_string.rb +0 -16
  149. data/lib/prawn/core/name_tree.rb +0 -177
  150. data/lib/prawn/core/object_store.rb +0 -320
  151. data/lib/prawn/core/page.rb +0 -212
  152. data/lib/prawn/core/pdf_object.rb +0 -125
  153. data/lib/prawn/core/reference.rb +0 -119
  154. data/lib/prawn/core/text.rb +0 -268
  155. data/lib/prawn/core/text/formatted/arranger.rb +0 -294
  156. data/lib/prawn/core/text/formatted/line_wrap.rb +0 -288
  157. data/lib/prawn/core/text/formatted/wrap.rb +0 -153
  158. data/lib/prawn/document/page_geometry.rb +0 -136
  159. data/lib/prawn/document/snapshot.rb +0 -89
  160. data/manual/manual/foreword.rb +0 -13
  161. data/manual/templates/full_template.rb +0 -23
  162. data/manual/templates/page_template.rb +0 -47
  163. data/manual/templates/templates.rb +0 -26
  164. data/manual/text/group.rb +0 -29
  165. data/spec/name_tree_spec.rb +0 -112
  166. data/spec/object_store_spec.rb +0 -170
  167. data/spec/pdf_object_spec.rb +0 -172
  168. data/spec/snapshot_spec.rb +0 -186
  169. data/spec/template_spec.rb +0 -351
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: edf9e637f24e5c4554e995712cb589f0b21737fb
4
+ data.tar.gz: 97750f73864c853ff874f8a5a0f7984a6f9d8279
5
+ SHA512:
6
+ metadata.gz: bd80b65ac0360fa6786b6bffacfc34a87511cc8d79e260dfd8db78b86a5003182a41d5ad559e5c1403724273c83b71b29d426c31a422fd7b1e5986a859ac1a5d
7
+ data.tar.gz: 4b63fc53c8481155ed173cb3e4b8146ac052173e0bd91f4fa27aece66525ad5f6968a48230addbb5ae2a043a3bc33829c79c9447a8c734f3bd2da45468b913da
@@ -0,0 +1,9 @@
1
+ --charset UTF-8
2
+ --main README.md
3
+ --title 'Prawn Documentation'
4
+ --no-private
5
+ -
6
+ CONTRIBUTING.md
7
+ COPYING
8
+ LICENSE
9
+ README.md
data/COPYING CHANGED
@@ -1,2 +1,2 @@
1
- Prawn may be used under Matz's terms for Ruby, or GPLv2 or GPLv3. See LICENSE
2
- for Matz's terms, or GPLv2 and GPLv3 files.
1
+ Prawn may be used under Matz's original licensing terms for Ruby, or GPLv2 or GPLv3.
2
+ See LICENSE for Matz's terms, or GPLv2 and GPLv3 files.
data/Gemfile CHANGED
@@ -1,18 +1,11 @@
1
- source :rubygems
1
+ source "https://rubygems.org"
2
2
 
3
- gem "ttfunk", "~>1.0.3"
4
- gem "pdf-reader", "~> 1.2"
5
- gem "ruby-rc4"
6
- gem "afm"
3
+ gemspec
7
4
 
8
- group :development do
9
- gem "coderay", "~> 1.0.7"
10
- gem "rdoc"
11
- end
12
-
13
- group :test do
14
- gem "pdf-inspector", "~> 1.0.2", :require => "pdf/inspector"
15
- gem "rspec"
16
- gem "mocha", :require => false
17
- gem "rake"
5
+ if ENV["CI"]
6
+ platforms :rbx do
7
+ gem "rubysl-singleton", "~> 2.0"
8
+ gem "rubysl-digest", "~> 2.0"
9
+ gem "rubysl-enumerator", "~> 2.0"
10
+ end
18
11
  end
data/LICENSE CHANGED
@@ -1,7 +1,7 @@
1
1
  Prawn is copyrighted free software produced by Gregory Brown along with
2
2
  community contributions. See git log for authorship information.
3
3
 
4
- Licensing terms follow (License of Ruby):
4
+ Licensing terms follow:
5
5
 
6
6
  You can redistribute Prawn and/or modify it under either the terms of the GPLv2
7
7
  or GPLv3 (see GPLv2 and GPLv3 files), or the conditions below:
data/Rakefile CHANGED
@@ -3,32 +3,29 @@ Bundler.setup
3
3
 
4
4
  require 'rake'
5
5
  require 'rspec/core/rake_task'
6
- require 'rdoc/task'
6
+ require 'yard'
7
7
  require 'rubygems/package_task'
8
8
 
9
9
  task :default => [:spec]
10
-
10
+
11
11
  desc "Run all rspec files"
12
- RSpec::Core::RakeTask.new("spec")
12
+ RSpec::Core::RakeTask.new("spec") do |c|
13
+ c.rspec_opts = "-t ~unresolved"
14
+ end
13
15
 
14
16
  desc "Show library's code statistics"
15
17
  task :stats do
16
- require 'code_statistics'
17
- CodeStatistics::TEST_TYPES << "Specs"
18
- CodeStatistics.new( ["Prawn", "lib"],
19
- ["Specs", "spec"] ).to_s
18
+ require 'code_statistics'
19
+ CodeStatistics::TEST_TYPES << "Specs"
20
+ CodeStatistics.new( ["Prawn", "lib"],
21
+ ["Specs", "spec"] ).to_s
20
22
  end
21
23
 
22
- desc "genrates documentation"
23
- RDoc::Task.new do |rdoc|
24
- rdoc.rdoc_files.include( "README",
25
- "COPYING",
26
- "LICENSE",
27
- "HACKING", "lib/" )
28
- rdoc.main = "README"
29
- rdoc.rdoc_dir = "doc/html"
30
- rdoc.title = "Prawn Documentation"
24
+ YARD::Rake::YardocTask.new do |t|
25
+ t.options = ['--output-dir', 'doc/html']
31
26
  end
27
+ task :docs => :yard
28
+
32
29
 
33
30
  desc "Generate the 'Prawn by Example' manual"
34
31
  task :manual do
@@ -43,3 +40,15 @@ Gem::PackageTask.new(spec) do |pkg|
43
40
  pkg.need_zip = true
44
41
  pkg.need_tar = true
45
42
  end
43
+
44
+ desc "Run a console with Prawn loaded"
45
+ task :console do
46
+ require 'irb'
47
+ require 'irb/completion'
48
+ require_relative 'lib/prawn'
49
+ Prawn.debug = true
50
+
51
+ ARGV.clear
52
+ IRB.start
53
+ end
54
+
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,8 @@
1
+ All images distributed with Prawn need to be freely distributable under
2
+ a license that is compatible with our own (see LICENSE and COPYING files).
3
+
4
+ It is our understanding that all files in this folder are compatible
5
+ with our licensing, but if you notice any problems, please
6
+ file an issue in our tracker on Github and we will promptly address it:
7
+
8
+ https://github.com/prawnpdf/prawn/issues
@@ -1,29 +1,91 @@
1
1
  # Welcome to Prawn, the best PDF Generation library ever.
2
2
  # This documentation covers user level functionality.
3
3
  #
4
- # Those looking to contribute code or write extensions should look
5
- # into the lib/prawn/core/* source tree.
6
- #
7
- module Prawn #:nodoc:
8
- VERSION = "1.0.0.rc2"
4
+ require "set"
5
+
6
+ require 'ttfunk'
7
+ require "pdf/core"
8
+
9
+ module Prawn
10
+ VERSION = "1.0.0"
11
+
12
+ extend self
13
+
14
+ file = __FILE__
15
+ file = File.readlink(file) if File.symlink?(file)
16
+ dir = File.dirname(file)
17
+
18
+ # The base source directory for Prawn as installed on the system
19
+ #
20
+ #
21
+ BASEDIR = File.expand_path(File.join(dir, '..'))
22
+ DATADIR = File.expand_path(File.join(dir, '..', 'data'))
23
+
24
+ FLOAT_PRECISION = 1.0e-9
25
+
26
+ # Whe set to true, Prawn will verify hash options to ensure only valid keys
27
+ # are used. Off by default.
28
+ #
29
+ # Example:
30
+ # >> Prawn::Document.new(:tomato => "Juicy")
31
+ # Prawn::Errors::UnknownOption:
32
+ # Detected unknown option(s): [:tomato]
33
+ # Accepted options are: [:page_size, :page_layout, :left_margin, ...]
34
+ #
35
+ attr_accessor :debug # @private
36
+
37
+ def verify_options(accepted, actual) # @private
38
+ return unless debug || $DEBUG
39
+ unless (act=Set[*actual.keys]).subset?(acc=Set[*accepted])
40
+ raise Prawn::Errors::UnknownOption,
41
+ "\nDetected unknown option(s): #{(act - acc).to_a.inspect}\n" <<
42
+ "Accepted options are: #{accepted.inspect}"
43
+ end
44
+ yield if block_given?
45
+ end
46
+
47
+ module Configurable # @private
48
+ def configuration(*args)
49
+ @config ||= Marshal.load(Marshal.dump(default_configuration))
50
+ if Hash === args[0]
51
+ @config.update(args[0])
52
+ elsif args.length > 1
53
+ @config.values_at(*args)
54
+ elsif args.length == 1
55
+ @config[args[0]]
56
+ else
57
+ @config
58
+ end
59
+ end
60
+
61
+ alias_method :C, :configuration
62
+ end
9
63
  end
10
64
 
11
- require "prawn/utilities"
12
- require "prawn/core"
13
- require "prawn/text"
14
- require "prawn/graphics"
15
- require "prawn/images"
16
- require "prawn/images/image"
17
- require "prawn/images/jpg"
18
- require "prawn/images/png"
19
- require "prawn/stamp"
20
- require "prawn/soft_mask"
21
- require "prawn/security"
22
- require "prawn/document"
23
- require "prawn/font"
24
- require "prawn/encoding"
25
- require "prawn/measurements"
26
- require "prawn/repeater"
27
- require "prawn/outline"
28
- require "prawn/layout"
65
+ require_relative "prawn/errors"
66
+
67
+
68
+ require_relative "prawn/utilities"
69
+ require_relative "prawn/text"
70
+ require_relative "prawn/graphics"
71
+ require_relative "prawn/images"
72
+ require_relative "prawn/images/image"
73
+ require_relative "prawn/images/jpg"
74
+ require_relative "prawn/images/png"
75
+ require_relative "prawn/stamp"
76
+ require_relative "prawn/soft_mask"
77
+ require_relative "prawn/security"
78
+ require_relative "prawn/document"
79
+ require_relative "prawn/font"
80
+ require_relative "prawn/encoding"
81
+ require_relative "prawn/measurements"
82
+ require_relative "prawn/repeater"
83
+ require_relative "prawn/outline"
84
+ require_relative "prawn/layout"
85
+
86
+ require_relative "prawn/image_handler"
87
+
88
+
29
89
 
90
+ Prawn.image_handler.register(Prawn::Images::PNG)
91
+ Prawn.image_handler.register(Prawn::Images::JPG)
@@ -7,13 +7,12 @@
7
7
  # This is free software. Please see the LICENSE and COPYING files for details.
8
8
 
9
9
  require "stringio"
10
- require "prawn/document/page_geometry"
11
- require "prawn/document/bounding_box"
12
- require "prawn/document/column_box"
13
- require "prawn/document/internals"
14
- require "prawn/document/span"
15
- require "prawn/document/snapshot"
16
- require "prawn/document/graphics_state"
10
+
11
+ require_relative "document/bounding_box"
12
+ require_relative "document/column_box"
13
+ require_relative "document/internals"
14
+ require_relative "document/span"
15
+ require_relative "document/graphics_state"
17
16
 
18
17
  module Prawn
19
18
 
@@ -52,9 +51,8 @@ module Prawn
52
51
  #
53
52
  class Document
54
53
  include Prawn::Document::Internals
55
- include Prawn::Core::Annotations
56
- include Prawn::Core::Destinations
57
- include Prawn::Document::Snapshot
54
+ include PDF::Core::Annotations
55
+ include PDF::Core::Destinations
58
56
  include Prawn::Document::GraphicsState
59
57
  include Prawn::Document::Security
60
58
  include Prawn::Text
@@ -63,6 +61,16 @@ module Prawn
63
61
  include Prawn::Stamp
64
62
  include Prawn::SoftMask
65
63
 
64
+ # @group Extension API
65
+
66
+ # NOTE: We probably need to rethink the options validation system, but this
67
+ # constant temporarily allows for extensions to modify the list.
68
+
69
+ VALID_OPTIONS = [:page_size, :page_layout, :margin, :left_margin,
70
+ :right_margin, :top_margin, :bottom_margin, :skip_page_creation,
71
+ :compress, :skip_encoding, :background, :info,
72
+ :text_formatter, :print_scaling]
73
+
66
74
  # Any module added to this array will be included into instances of
67
75
  # Prawn::Document at the per-object level. These will also be inherited by
68
76
  # any subclasses.
@@ -83,14 +91,28 @@ module Prawn
83
91
  # party!
84
92
  # end
85
93
  #
94
+ #
86
95
  def self.extensions
87
96
  @extensions ||= []
88
97
  end
89
98
 
90
- def self.inherited(base) #:nodoc:
99
+ # @private
100
+ def self.inherited(base)
91
101
  extensions.each { |e| base.extensions << e }
92
102
  end
93
103
 
104
+ # @group Stable Attributes
105
+
106
+ attr_accessor :margin_box
107
+ attr_reader :margins, :y
108
+ attr_accessor :page_number
109
+
110
+ # @group Extension Attributes
111
+
112
+ attr_accessor :text_formatter
113
+
114
+ # @group Stable API
115
+
94
116
  # Creates and renders a PDF document.
95
117
  #
96
118
  # When using the implicit block form, Prawn will evaluate the block
@@ -135,11 +157,10 @@ module Prawn
135
157
  # <tt>:bottom_margin</tt>:: Sets the bottom margin in points [0.5 inch]
136
158
  # <tt>:skip_page_creation</tt>:: Creates a document without starting the first page [false]
137
159
  # <tt>:compress</tt>:: Compresses content streams before rendering them [false]
138
- # <tt>:optimize_objects</tt>:: Reduce number of PDF objects in output, at expense of render time [false]
139
160
  # <tt>:background</tt>:: An image path to be used as background on all pages [nil]
140
161
  # <tt>:background_scale</tt>:: Backgound image scale [1] [nil]
141
162
  # <tt>:info</tt>:: Generic hash allowing for custom metadata properties [nil]
142
- # <tt>:template</tt>:: The path to an existing PDF file to use as a template [nil]
163
+ # <tt>:text_formatter</tt>: The text formatter to use for <tt>:inline_format</tt>ted text [Prawn::Text::Formatted::Parser]
143
164
  #
144
165
  # Setting e.g. the :margin to 100 points and the :left_margin to 50 will result in margins
145
166
  # of 100 points on every side except for the left, where it will be 50.
@@ -173,19 +194,18 @@ module Prawn
173
194
  def initialize(options={},&block)
174
195
  options = options.dup
175
196
 
176
- Prawn.verify_options [:page_size, :page_layout, :margin, :left_margin,
177
- :right_margin, :top_margin, :bottom_margin, :skip_page_creation,
178
- :compress, :skip_encoding, :background, :info,
179
- :optimize_objects, :template], options
197
+ Prawn.verify_options VALID_OPTIONS, options
180
198
 
181
199
  # need to fix, as the refactoring breaks this
182
200
  # raise NotImplementedError if options[:skip_page_creation]
183
201
 
184
202
  self.class.extensions.reverse_each { |e| extend e }
185
- @internal_state = Prawn::Core::DocumentState.new(options)
203
+ @internal_state = PDF::Core::DocumentState.new(options)
186
204
  @internal_state.populate_pages_from_store(self)
187
205
  min_version(state.store.min_version) if state.store.min_version
188
206
 
207
+ min_version(1.6) if options[:print_scaling] == :none
208
+
189
209
  @background = options[:background]
190
210
  @background_scale = options[:background_scale] || 1
191
211
  @font_size = 12
@@ -195,19 +215,12 @@ module Prawn
195
215
 
196
216
  @page_number = 0
197
217
 
218
+ @text_formatter = options.delete(:text_formatter) || Text::Formatted::Parser
219
+
198
220
  options[:size] = options.delete(:page_size)
199
221
  options[:layout] = options.delete(:page_layout)
200
222
 
201
- if options[:template]
202
- fresh_content_streams(options)
203
- go_to_page(1)
204
- else
205
- if options[:skip_page_creation] || options[:template]
206
- start_new_page(options.merge(:orphan => true))
207
- else
208
- start_new_page(options)
209
- end
210
- end
223
+ initialize_first_page(options)
211
224
 
212
225
  @bounding_box = @margin_box
213
226
 
@@ -216,18 +229,7 @@ module Prawn
216
229
  end
217
230
  end
218
231
 
219
- attr_accessor :margin_box
220
- attr_reader :margins, :y
221
- attr_writer :font_size
222
- attr_accessor :page_number
223
-
224
- def state
225
- @internal_state
226
- end
227
-
228
- def page
229
- state.page
230
- end
232
+ # @group Stable API
231
233
 
232
234
  # Creates and advances to a new page in the document.
233
235
  #
@@ -239,14 +241,6 @@ module Prawn
239
241
  # pdf.start_new_page(:left_margin => 50, :right_margin => 50)
240
242
  # pdf.start_new_page(:margin => 100)
241
243
  #
242
- # A template for a page can be specified by pointing to the path of and existing pdf.
243
- # One can also specify which page of the template which defaults otherwise to 1.
244
- #
245
- # pdf.start_new_page(:template => multipage_template.pdf, :template_page => 2)
246
- #
247
- # Note: templates get indexed by either the object_id of the filename or stream
248
- # entered so that if you reuse the same template multiple times be sure to use the
249
- # same instance for more efficient use of resources and smaller rendered pdfs.
250
244
  def start_new_page(options = {})
251
245
  if last_page = state.page
252
246
  last_page_size = last_page.size
@@ -258,14 +252,13 @@ module Prawn
258
252
  :layout => options[:layout] || last_page_layout,
259
253
  :margins => last_page_margins}
260
254
  if last_page
261
- new_graphic_state = last_page.graphic_state.dup
255
+ new_graphic_state = last_page.graphic_state.dup if last_page.graphic_state
262
256
  #erase the color space so that it gets reset on new page for fussy pdf-readers
263
- new_graphic_state.color_space = {}
257
+ new_graphic_state.color_space = {} if new_graphic_state
264
258
  page_options.merge!(:graphic_state => new_graphic_state)
265
259
  end
266
- merge_template_options(page_options, options) if options[:template]
267
260
 
268
- state.page = Prawn::Core::Page.new(self, page_options)
261
+ state.page = PDF::Core::Page.new(self, page_options)
269
262
 
270
263
  apply_margin_options(options)
271
264
  generate_margin_box
@@ -276,8 +269,7 @@ module Prawn
276
269
  @bounding_box = @margin_box
277
270
  end
278
271
 
279
- state.page.new_content_stream if options[:template]
280
- use_graphic_settings(options[:template])
272
+ use_graphic_settings
281
273
 
282
274
  unless options[:orphan]
283
275
  state.insert_page(state.page, @page_number)
@@ -354,19 +346,26 @@ module Prawn
354
346
  self.y = original_y
355
347
  end
356
348
 
357
- # Renders the PDF document to string
349
+ # Renders the PDF document to string.
350
+ # Pass an open file descriptor to render to file.
358
351
  #
359
- def render
360
- output = StringIO.new
352
+ def render(output = StringIO.new)
353
+ if output.instance_of?(StringIO)
354
+ output.set_encoding(::Encoding::ASCII_8BIT)
355
+ end
361
356
  finalize_all_page_contents
362
357
 
363
358
  render_header(output)
364
359
  render_body(output)
365
360
  render_xref(output)
366
361
  render_trailer(output)
367
- str = output.string
368
- str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
369
- str
362
+ if output.instance_of?(StringIO)
363
+ str = output.string
364
+ str.force_encoding(::Encoding::ASCII_8BIT)
365
+ return str
366
+ else
367
+ return nil
368
+ end
370
369
  end
371
370
 
372
371
  # Renders the PDF document to file.
@@ -374,8 +373,7 @@ module Prawn
374
373
  # pdf.render_file "foo.pdf"
375
374
  #
376
375
  def render_file(filename)
377
- Kernel.const_defined?("Encoding") ? mode = "wb:ASCII-8BIT" : mode = "wb"
378
- File.open(filename,mode) { |f| f << render }
376
+ File.open(filename, "wb") { |f| render(f) }
379
377
  end
380
378
 
381
379
  # The bounds method returns the current bounding box you are currently in,
@@ -411,6 +409,7 @@ module Prawn
411
409
 
412
410
  # Returns the innermost non-stretchy bounding box.
413
411
  #
412
+ # @private
414
413
  def reference_bounds
415
414
  @bounding_box.reference_bounds
416
415
  end
@@ -496,47 +495,6 @@ module Prawn
496
495
  bounds.indent(left, right, &block)
497
496
  end
498
497
 
499
-
500
- def mask(*fields) # :nodoc:
501
- # Stores the current state of the named attributes, executes the block, and
502
- # then restores the original values after the block has executed.
503
- # -- I will remove the nodoc if/when this feature is a little less hacky
504
- stored = {}
505
- fields.each { |f| stored[f] = send(f) }
506
- yield
507
- fields.each { |f| send("#{f}=", stored[f]) }
508
- end
509
-
510
- # Attempts to group the given block vertically within the current context.
511
- # First attempts to render it in the current position on the current page.
512
- # If that attempt overflows, it is tried anew after starting a new context
513
- # (page or column). Returns a logically true value if the content fits in
514
- # one page/column, false if a new page or column was needed.
515
- #
516
- # Raises CannotGroup if the provided content is too large to fit alone in
517
- # the current page or column.
518
- #
519
- def group(second_attempt=false)
520
- old_bounding_box = @bounding_box
521
- @bounding_box = SimpleDelegator.new(@bounding_box)
522
-
523
- def @bounding_box.move_past_bottom
524
- raise RollbackTransaction
525
- end
526
-
527
- success = transaction { yield }
528
-
529
- @bounding_box = old_bounding_box
530
-
531
- unless success
532
- raise Prawn::Errors::CannotGroup if second_attempt
533
- old_bounding_box.move_past_bottom
534
- group(second_attempt=true) { yield }
535
- end
536
-
537
- success
538
- end
539
-
540
498
  # Places a text box on specified pages for page numbering. This should be called
541
499
  # towards the end of document creation, after all your content is already in
542
500
  # place. In your template string, <page> refers to the current page, and
@@ -609,6 +567,42 @@ module Prawn
609
567
  end
610
568
  end
611
569
 
570
+ # Returns true if content streams will be compressed before rendering,
571
+ # false otherwise
572
+ #
573
+ def compression_enabled?
574
+ !!state.compress
575
+ end
576
+
577
+ # @group Experimental API
578
+
579
+ # Attempts to group the given block vertically within the current context.
580
+ # First attempts to render it in the current position on the current page.
581
+ # If that attempt overflows, it is tried anew after starting a new context
582
+ # (page or column). Returns a logically true value if the content fits in
583
+ # one page/column, false if a new page or column was needed.
584
+ #
585
+ # Raises CannotGroup if the provided content is too large to fit alone in
586
+ # the current page or column.
587
+ #
588
+ # @private
589
+ def group(*a, &b)
590
+ raise NotImplementedError,
591
+ "Document#group has been disabled because its implementation "+
592
+ "lead to corrupted documents whenever a page boundary was "+
593
+ "crossed. We will try to work on reimplementing it in a "+
594
+ "future release"
595
+ end
596
+
597
+ # @private
598
+ def transaction
599
+ raise NotImplementedError,
600
+ "Document#transaction has been disabled because its implementation "+
601
+ "lead to corrupted documents whenever a page boundary was "+
602
+ "crossed. We will try to work on reimplementing it in a "+
603
+ "future release"
604
+ end
605
+
612
606
  # Provides a way to execute a block of code repeatedly based on a
613
607
  # page_filter.
614
608
  #
@@ -634,23 +628,45 @@ module Prawn
634
628
  end
635
629
  end
636
630
 
631
+ # @private
632
+
633
+ def mask(*fields)
634
+ # Stores the current state of the named attributes, executes the block, and
635
+ # then restores the original values after the block has executed.
636
+ # -- I will remove the nodoc if/when this feature is a little less hacky
637
+ stored = {}
638
+ fields.each { |f| stored[f] = send(f) }
639
+ yield
640
+ fields.each { |f| send("#{f}=", stored[f]) }
641
+ end
637
642
 
638
- # Returns true if content streams will be compressed before rendering,
639
- # false otherwise
640
- #
641
- def compression_enabled?
642
- !!state.compress
643
+ # @group Extension API
644
+
645
+ def initialize_first_page(options)
646
+ if options[:skip_page_creation]
647
+ start_new_page(options.merge(:orphan => true))
648
+ else
649
+ start_new_page(options)
650
+ end
643
651
  end
644
652
 
645
- private
653
+ ## Internals. Don't depend on them!
646
654
 
647
- def merge_template_options(page_options, options)
648
- object_id = state.store.import_page(options[:template], options[:template_page] || 1)
649
- page_options.merge!(:object_id => object_id, :page_template => true)
655
+ # @private
656
+ def state
657
+ @internal_state
650
658
  end
651
659
 
660
+ # @private
661
+ def page
662
+ state.page
663
+ end
664
+
665
+ private
666
+
667
+
652
668
  # setting override_settings to true ensures that a new graphic state does not end up using
653
- # previous settings especially from imported template streams
669
+ # previous settings.
654
670
  def use_graphic_settings(override_settings = false)
655
671
  set_fill_color if current_fill_color != "000000" || override_settings
656
672
  set_stroke_color if current_stroke_color != "000000" || override_settings
@@ -680,9 +696,7 @@ module Prawn
680
696
 
681
697
  # we must update bounding box if not flowing from the previous page
682
698
  #
683
- # FIXME: This may have a bug where the old margin is restored
684
- # when the bounding box exits.
685
- @bounding_box = @margin_box if old_margin_box == @bounding_box
699
+ @bounding_box = @margin_box unless @bounding_box && @bounding_box.parent
686
700
  end
687
701
 
688
702
  def apply_margin_options(options)
@@ -703,5 +717,9 @@ module Prawn
703
717
  end
704
718
  end
705
719
  end
720
+
721
+ def font_metric_cache #:nodoc:
722
+ @font_metric_cache ||= FontMetricCache.new( self )
723
+ end
706
724
  end
707
725
  end