prawn-core 0.5.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (186) hide show
  1. data/COPYING +340 -0
  2. data/LICENSE +56 -0
  3. data/README +121 -0
  4. data/Rakefile +74 -0
  5. data/data/encodings/win_ansi.txt +29 -0
  6. data/data/fonts/Action Man.dfont +0 -0
  7. data/data/fonts/Activa.ttf +0 -0
  8. data/data/fonts/Chalkboard.ttf +0 -0
  9. data/data/fonts/Courier-Bold.afm +342 -0
  10. data/data/fonts/Courier-BoldOblique.afm +342 -0
  11. data/data/fonts/Courier-Oblique.afm +342 -0
  12. data/data/fonts/Courier.afm +342 -0
  13. data/data/fonts/DejaVuSans.ttf +0 -0
  14. data/data/fonts/Dustismo_Roman.ttf +0 -0
  15. data/data/fonts/Helvetica-Bold.afm +2827 -0
  16. data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  17. data/data/fonts/Helvetica-Oblique.afm +3051 -0
  18. data/data/fonts/Helvetica.afm +3051 -0
  19. data/data/fonts/MustRead.html +19 -0
  20. data/data/fonts/Symbol.afm +213 -0
  21. data/data/fonts/Times-Bold.afm +2588 -0
  22. data/data/fonts/Times-BoldItalic.afm +2384 -0
  23. data/data/fonts/Times-Italic.afm +2667 -0
  24. data/data/fonts/Times-Roman.afm +2419 -0
  25. data/data/fonts/ZapfDingbats.afm +225 -0
  26. data/data/fonts/comicsans.ttf +0 -0
  27. data/data/fonts/gkai00mp.ttf +0 -0
  28. data/data/images/16bit.alpha +0 -0
  29. data/data/images/16bit.dat +0 -0
  30. data/data/images/16bit.png +0 -0
  31. data/data/images/arrow.png +0 -0
  32. data/data/images/arrow2.png +0 -0
  33. data/data/images/barcode_issue.png +0 -0
  34. data/data/images/dice.alpha +0 -0
  35. data/data/images/dice.dat +0 -0
  36. data/data/images/dice.png +0 -0
  37. data/data/images/dice_interlaced.png +0 -0
  38. data/data/images/fractal.jpg +0 -0
  39. data/data/images/letterhead.jpg +0 -0
  40. data/data/images/page_white_text.alpha +0 -0
  41. data/data/images/page_white_text.dat +0 -0
  42. data/data/images/page_white_text.png +0 -0
  43. data/data/images/pigs.jpg +0 -0
  44. data/data/images/rails.dat +0 -0
  45. data/data/images/rails.png +0 -0
  46. data/data/images/ruport.png +0 -0
  47. data/data/images/ruport_data.dat +0 -0
  48. data/data/images/ruport_transparent.png +0 -0
  49. data/data/images/ruport_type0.png +0 -0
  50. data/data/images/stef.jpg +0 -0
  51. data/data/images/tru256.bmp +0 -0
  52. data/data/images/web-links.dat +1 -0
  53. data/data/images/web-links.png +0 -0
  54. data/data/shift_jis_text.txt +1 -0
  55. data/examples/bounding_box/bounding_boxes.rb +44 -0
  56. data/examples/bounding_box/russian_boxes.rb +37 -0
  57. data/examples/column_box/column_box_example.rb +44 -0
  58. data/examples/general/background.rb +20 -0
  59. data/examples/general/canvas.rb +16 -0
  60. data/examples/general/measurement_units.rb +52 -0
  61. data/examples/general/metadata-info.rb +17 -0
  62. data/examples/general/multi_page_layout.rb +17 -0
  63. data/examples/general/page_geometry.rb +32 -0
  64. data/examples/graphics/basic_images.rb +24 -0
  65. data/examples/graphics/cmyk.rb +13 -0
  66. data/examples/graphics/curves.rb +12 -0
  67. data/examples/graphics/hexagon.rb +14 -0
  68. data/examples/graphics/image_fit.rb +16 -0
  69. data/examples/graphics/image_flow.rb +38 -0
  70. data/examples/graphics/image_position.rb +18 -0
  71. data/examples/graphics/line.rb +33 -0
  72. data/examples/graphics/png_types.rb +23 -0
  73. data/examples/graphics/polygons.rb +17 -0
  74. data/examples/graphics/remote_images.rb +12 -0
  75. data/examples/graphics/ruport_style_helpers.rb +20 -0
  76. data/examples/graphics/stroke_bounds.rb +21 -0
  77. data/examples/m17n/chinese_text_wrapping.rb +20 -0
  78. data/examples/m17n/euro.rb +16 -0
  79. data/examples/m17n/sjis.rb +29 -0
  80. data/examples/m17n/utf8.rb +14 -0
  81. data/examples/m17n/win_ansi_charset.rb +55 -0
  82. data/examples/text/alignment.rb +19 -0
  83. data/examples/text/dfont.rb +49 -0
  84. data/examples/text/family_based_styling.rb +25 -0
  85. data/examples/text/font_calculations.rb +92 -0
  86. data/examples/text/font_size.rb +34 -0
  87. data/examples/text/kerning.rb +31 -0
  88. data/examples/text/simple_text.rb +18 -0
  89. data/examples/text/simple_text_ttf.rb +18 -0
  90. data/examples/text/span.rb +30 -0
  91. data/examples/text/text_box.rb +26 -0
  92. data/examples/text/text_flow.rb +68 -0
  93. data/lib/prawn/compatibility.rb +38 -0
  94. data/lib/prawn/core.rb +79 -0
  95. data/lib/prawn/document.rb +399 -0
  96. data/lib/prawn/document/annotations.rb +63 -0
  97. data/lib/prawn/document/bounding_box.rb +377 -0
  98. data/lib/prawn/document/column_box.rb +89 -0
  99. data/lib/prawn/document/destinations.rb +81 -0
  100. data/lib/prawn/document/internals.rb +133 -0
  101. data/lib/prawn/document/page_geometry.rb +149 -0
  102. data/lib/prawn/document/span.rb +55 -0
  103. data/lib/prawn/document/text.rb +186 -0
  104. data/lib/prawn/document/text/box.rb +83 -0
  105. data/lib/prawn/document/text/wrapping.rb +59 -0
  106. data/lib/prawn/encoding.rb +121 -0
  107. data/lib/prawn/errors.rb +49 -0
  108. data/lib/prawn/font.rb +292 -0
  109. data/lib/prawn/font/afm.rb +202 -0
  110. data/lib/prawn/font/dfont.rb +31 -0
  111. data/lib/prawn/font/ttf.rb +327 -0
  112. data/lib/prawn/graphics.rb +257 -0
  113. data/lib/prawn/graphics/color.rb +141 -0
  114. data/lib/prawn/images.rb +339 -0
  115. data/lib/prawn/images/jpg.rb +45 -0
  116. data/lib/prawn/images/png.rb +217 -0
  117. data/lib/prawn/literal_string.rb +14 -0
  118. data/lib/prawn/measurement_extensions.rb +46 -0
  119. data/lib/prawn/measurements.rb +71 -0
  120. data/lib/prawn/name_tree.rb +165 -0
  121. data/lib/prawn/pdf_object.rb +77 -0
  122. data/lib/prawn/reference.rb +59 -0
  123. data/spec/annotations_spec.rb +90 -0
  124. data/spec/bounding_box_spec.rb +141 -0
  125. data/spec/destinations_spec.rb +15 -0
  126. data/spec/document_spec.rb +178 -0
  127. data/spec/font_spec.rb +274 -0
  128. data/spec/graphics_spec.rb +209 -0
  129. data/spec/images_spec.rb +79 -0
  130. data/spec/jpg_spec.rb +25 -0
  131. data/spec/measurement_units_spec.rb +23 -0
  132. data/spec/name_tree_spec.rb +103 -0
  133. data/spec/pdf_object_spec.rb +117 -0
  134. data/spec/png_spec.rb +236 -0
  135. data/spec/reference_spec.rb +42 -0
  136. data/spec/span_spec.rb +45 -0
  137. data/spec/spec_helper.rb +23 -0
  138. data/spec/text_box_spec.rb +83 -0
  139. data/spec/text_spec.rb +178 -0
  140. data/vendor/pdf-inspector/README +18 -0
  141. data/vendor/pdf-inspector/lib/pdf/inspector.rb +25 -0
  142. data/vendor/pdf-inspector/lib/pdf/inspector/graphics.rb +80 -0
  143. data/vendor/pdf-inspector/lib/pdf/inspector/page.rb +16 -0
  144. data/vendor/pdf-inspector/lib/pdf/inspector/text.rb +31 -0
  145. data/vendor/pdf-inspector/lib/pdf/inspector/xobject.rb +19 -0
  146. data/vendor/ttfunk/data/fonts/DejaVuSans.ttf +0 -0
  147. data/vendor/ttfunk/data/fonts/comicsans.ttf +0 -0
  148. data/vendor/ttfunk/example.rb +45 -0
  149. data/vendor/ttfunk/lib/ttfunk.rb +102 -0
  150. data/vendor/ttfunk/lib/ttfunk/directory.rb +17 -0
  151. data/vendor/ttfunk/lib/ttfunk/encoding/mac_roman.rb +88 -0
  152. data/vendor/ttfunk/lib/ttfunk/encoding/windows_1252.rb +69 -0
  153. data/vendor/ttfunk/lib/ttfunk/reader.rb +44 -0
  154. data/vendor/ttfunk/lib/ttfunk/resource_file.rb +78 -0
  155. data/vendor/ttfunk/lib/ttfunk/subset.rb +18 -0
  156. data/vendor/ttfunk/lib/ttfunk/subset/base.rb +141 -0
  157. data/vendor/ttfunk/lib/ttfunk/subset/mac_roman.rb +46 -0
  158. data/vendor/ttfunk/lib/ttfunk/subset/unicode.rb +48 -0
  159. data/vendor/ttfunk/lib/ttfunk/subset/unicode_8bit.rb +63 -0
  160. data/vendor/ttfunk/lib/ttfunk/subset/windows_1252.rb +51 -0
  161. data/vendor/ttfunk/lib/ttfunk/subset_collection.rb +72 -0
  162. data/vendor/ttfunk/lib/ttfunk/table.rb +46 -0
  163. data/vendor/ttfunk/lib/ttfunk/table/cmap.rb +34 -0
  164. data/vendor/ttfunk/lib/ttfunk/table/cmap/format00.rb +54 -0
  165. data/vendor/ttfunk/lib/ttfunk/table/cmap/format04.rb +126 -0
  166. data/vendor/ttfunk/lib/ttfunk/table/cmap/subtable.rb +79 -0
  167. data/vendor/ttfunk/lib/ttfunk/table/glyf.rb +64 -0
  168. data/vendor/ttfunk/lib/ttfunk/table/glyf/compound.rb +81 -0
  169. data/vendor/ttfunk/lib/ttfunk/table/glyf/simple.rb +37 -0
  170. data/vendor/ttfunk/lib/ttfunk/table/head.rb +44 -0
  171. data/vendor/ttfunk/lib/ttfunk/table/hhea.rb +41 -0
  172. data/vendor/ttfunk/lib/ttfunk/table/hmtx.rb +47 -0
  173. data/vendor/ttfunk/lib/ttfunk/table/kern.rb +79 -0
  174. data/vendor/ttfunk/lib/ttfunk/table/kern/format0.rb +62 -0
  175. data/vendor/ttfunk/lib/ttfunk/table/loca.rb +43 -0
  176. data/vendor/ttfunk/lib/ttfunk/table/maxp.rb +40 -0
  177. data/vendor/ttfunk/lib/ttfunk/table/name.rb +119 -0
  178. data/vendor/ttfunk/lib/ttfunk/table/os2.rb +78 -0
  179. data/vendor/ttfunk/lib/ttfunk/table/post.rb +91 -0
  180. data/vendor/ttfunk/lib/ttfunk/table/post/format10.rb +43 -0
  181. data/vendor/ttfunk/lib/ttfunk/table/post/format20.rb +35 -0
  182. data/vendor/ttfunk/lib/ttfunk/table/post/format25.rb +23 -0
  183. data/vendor/ttfunk/lib/ttfunk/table/post/format30.rb +17 -0
  184. data/vendor/ttfunk/lib/ttfunk/table/post/format40.rb +17 -0
  185. data/vendor/ttfunk/lib/ttfunk/table/simple.rb +14 -0
  186. metadata +245 -0
@@ -0,0 +1,68 @@
1
+ # encoding: utf-8
2
+ #
3
+ # Basic text flowing example including the use of bounding boxes. A somewhat
4
+ # old example, mostly retained for nostalgia.
5
+ #
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', '..', 'lib'))
7
+ require "prawn/core"
8
+
9
+ content = <<-EOS
10
+ How does
11
+ Prawn deal with
12
+ white
13
+ space
14
+
15
+ and
16
+
17
+ line
18
+ breaks?
19
+ EOS
20
+
21
+ poem = <<-EOS
22
+ GOOD-BYE
23
+
24
+ Good-bye, proud world! I'm going home: Thou art not my friend, and I'm not thine. Long through thy weary crowds I roam; A river-ark on the ocean brine, Long I've been tossed like the driven foam: But now, proud world! I'm going home.
25
+
26
+ Good-bye to Flattery's fawning face; To Grandeur with his wise grimace; To upstart Wealth's averted eye; To supple Office, low and high; To crowded halls, to court and street; To frozen hearts and hasting feet; To those who go, and those who come; Good-bye, proud world! I'm going home.
27
+
28
+ I am going to my own hearth-stone, Bosomed in yon green hills alone,-- secret nook in a pleasant land, Whose groves the frolic fairies planned; Where arches green, the livelong day, Echo the blackbird's roundelay, And vulgar feet have never trod A spot that is sacred to thought and God.
29
+
30
+ O, when I am safe in my sylvan home, I tread on the pride of Greece and Rome; And when I am stretched beneath the pines, Where the evening star so holy shines, I laugh at the lore and the pride of man, At the sophist schools and the learned clan; For what are they all, in their high conceit, When man in the bush with God may meet?
31
+ EOS
32
+
33
+ overflow = "This text should flow gracefully onto the next page, like a stream"+
34
+ " flows elegantly from a mountain lake down into the village below."
35
+
36
+ Prawn::Document.generate("flow.pdf") do |pdf|
37
+
38
+ pdf.font "Times-Roman"
39
+ pdf.stroke_line [pdf.bounds.left, pdf.bounds.top],
40
+ [pdf.bounds.right, pdf.bounds.top]
41
+
42
+ pdf.text content, :size => 10
43
+
44
+ pdf.bounding_box([100,600], :width => 200, :height => 525) do
45
+ pdf.stroke_line [pdf.bounds.left, pdf.bounds.top],
46
+ [pdf.bounds.right, pdf.bounds.top]
47
+ pdf.text poem, :size => 12
48
+ end
49
+
50
+ pdf.bounding_box([325,600], :width => 200, :height => 525) do
51
+ pdf.stroke_line [pdf.bounds.left, pdf.bounds.top],
52
+ [pdf.bounds.right, pdf.bounds.top]
53
+ pdf.text poem.reverse, :size => 12
54
+ end
55
+
56
+ pdf.text overflow * 10, :size => 14
57
+
58
+ pdf.text "Hooray! We've conquered the evil PDF gods", :size => 36
59
+
60
+ pdf.bounding_box([100,450], :width => 300) do
61
+ pdf.stroke_line [pdf.bounds.left, pdf.bounds.top],
62
+ [pdf.bounds.right, pdf.bounds.top]
63
+ pdf.text poem, :size => 10, :spacing => 5
64
+ end
65
+
66
+ pdf.text "And this text automatically goes below the poem", :size => 18
67
+
68
+ end
@@ -0,0 +1,38 @@
1
+ # coding: utf-8
2
+ #
3
+ # Why would we ever use Ruby 1.8.7 when we can backport with something
4
+ # as simple as this?
5
+ #
6
+ class String #:nodoc:
7
+ unless "".respond_to?(:lines)
8
+ alias_method :lines, :to_a
9
+ end
10
+ end
11
+
12
+ unless File.respond_to?(:binread)
13
+ def File.binread(file)
14
+ File.open(file,"rb") { |f| f.read }
15
+ end
16
+ end
17
+
18
+ if RUBY_VERSION < "1.9"
19
+
20
+ def ruby_18 #:nodoc:
21
+ yield
22
+ end
23
+
24
+ def ruby_19 #:nodoc:
25
+ false
26
+ end
27
+
28
+ else
29
+
30
+ def ruby_18 #:nodoc:
31
+ false
32
+ end
33
+
34
+ def ruby_19 #:nodoc:
35
+ yield
36
+ end
37
+
38
+ end
@@ -0,0 +1,79 @@
1
+ # encoding: utf-8
2
+
3
+ # prawn.rb : A library for PDF generation in Ruby
4
+ #
5
+ # Copyright April 2008, Gregory Brown. All Rights Reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+
9
+ %w[ttfunk/lib].each do |dep|
10
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + "/../../vendor/#{dep}")
11
+ end
12
+
13
+ begin
14
+ require 'ttfunk'
15
+ rescue LoadError
16
+ puts "Failed to load ttfunk. If you are running Prawn from git:"
17
+ puts " git submodule init"
18
+ puts " git submodule update"
19
+ exit
20
+ end
21
+
22
+ module Prawn
23
+ file = __FILE__
24
+ file = File.readlink(file) if File.symlink?(file)
25
+ dir = File.dirname(file)
26
+
27
+ # The base source directory for Prawn as installed on the system
28
+ BASEDIR = File.expand_path(File.join(dir, '..', '..'))
29
+
30
+ VERSION = "0.5.0.1"
31
+
32
+ extend self
33
+
34
+ # Whe set to true, Prawn will verify hash options to ensure only valid keys
35
+ # are used. Off by default.
36
+ #
37
+ attr_accessor :debug
38
+
39
+ def verify_options(accepted,actual) #:nodoc:
40
+ return unless debug || $DEBUG
41
+ require "set"
42
+ unless (act=Set[*actual.keys]).subset?(acc=Set[*accepted])
43
+ raise Prawn::Errors::UnknownOption,
44
+ "\nDetected unknown option(s): #{(act - acc).to_a.inspect}\n" <<
45
+ "Accepted options are: #{accepted.inspect}"
46
+ end
47
+ yield if block_given?
48
+ end
49
+
50
+ module Configurable #:nodoc:
51
+ def configuration(*args)
52
+ @config ||= Marshal.load(Marshal.dump(default_configuration))
53
+ if Hash === args[0]
54
+ @config.update(args[0])
55
+ elsif args.length > 1
56
+ @config.values_at(*args)
57
+ elsif args.length == 1
58
+ @config[args[0]]
59
+ else
60
+ @config
61
+ end
62
+ end
63
+
64
+ alias_method :C, :configuration
65
+ end
66
+ end
67
+
68
+ require "prawn/compatibility"
69
+ require "prawn/errors"
70
+ require "prawn/pdf_object"
71
+ require "prawn/graphics"
72
+ require "prawn/images"
73
+ require "prawn/images/jpg"
74
+ require "prawn/images/png"
75
+ require "prawn/document"
76
+ require "prawn/reference"
77
+ require "prawn/font"
78
+ require "prawn/encoding"
79
+ require "prawn/measurements"
@@ -0,0 +1,399 @@
1
+ # encoding: utf-8
2
+
3
+ # document.rb : Implements PDF document generation for Prawn
4
+ #
5
+ # Copyright April 2008, Gregory Brown. All Rights Reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+
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/text"
16
+ require "prawn/document/annotations"
17
+ require "prawn/document/destinations"
18
+
19
+ module Prawn
20
+ # The Prawn::Document class is how you start creating a PDF document.
21
+ #
22
+ # There are three basic ways you can instantiate PDF Documents in Prawn, they
23
+ # are through assignment, implicit block or explicit block. Below is an exmple
24
+ # of each type, each example does exactly the same thing, makes a PDF document
25
+ # with all the defaults and puts in the default font "Hello There" and then
26
+ # saves it to the current directory as "example.pdf"
27
+ #
28
+ # For example, assignment can be like this:
29
+ #
30
+ # pdf = Prawn::Document.new
31
+ # pdf.text "Hello There"
32
+ # pdf.render_file "example.pdf"
33
+ #
34
+ # Or you can do an implied block form:
35
+ #
36
+ # Prawn::Document.generate "example.pdf" do
37
+ # text "Hello There"
38
+ # end
39
+ #
40
+ # Or if you need to access a variable outside the scope of the block, the
41
+ # explicit block form:
42
+ #
43
+ # words = "Hello There"
44
+ # Prawn::Document.generate "example.pdf" do |pdf|
45
+ # pdf.text words
46
+ # end
47
+ #
48
+ # Usually, the block forms are used when you are simply creating a PDF document
49
+ # that you want to immediately save or render out.
50
+ #
51
+ # See the new and generate methods for further details on the above.
52
+ class Document
53
+
54
+ include Text
55
+ include PageGeometry
56
+ include Internals
57
+ include Annotations
58
+ include Destinations
59
+ include Prawn::Graphics
60
+ include Prawn::Images
61
+
62
+ attr_accessor :y, :margin_box
63
+ attr_reader :margins, :page_size, :page_layout
64
+ attr_writer :font_size
65
+
66
+ # Creates and renders a PDF document.
67
+ #
68
+ # When using the implicit block form, Prawn will evaluate the block
69
+ # within an instance of Prawn::Document, simplifying your syntax.
70
+ # However, please note that you will not be able to reference variables
71
+ # from the enclosing scope within this block.
72
+ #
73
+ # # Using implicit block form and rendering to a file
74
+ # Prawn::Document.generate "example.pdf" do
75
+ # # self here is set to the newly instantiated Prawn::Document
76
+ # # and so any variables in the outside scope are unavailable
77
+ # font "Times-Roman"
78
+ # text "Hello World", :at => [200,720], :size => 32
79
+ # end
80
+ #
81
+ # If you need to access your local and instance variables, use the explicit
82
+ # block form shown below. In this case, Prawn yields an instance of
83
+ # PDF::Document and the block is an ordinary closure:
84
+ #
85
+ # # Using explicit block form and rendering to a file
86
+ # content = "Hello World"
87
+ # Prawn::Document.generate "example.pdf" do |pdf|
88
+ # # self here is left alone
89
+ # pdf.font "Times-Roman"
90
+ # pdf.text content, :at => [200,720], :size => 32
91
+ # end
92
+ #
93
+ def self.generate(filename,options={},&block)
94
+ pdf = new(options,&block)
95
+ pdf.render_file(filename)
96
+ end
97
+
98
+ # Creates a new PDF Document. The following options are available (with
99
+ # the default values marked in [])
100
+ #
101
+ # <tt>:page_size</tt>:: One of the Document::PageGeometry sizes [LETTER]
102
+ # <tt>:page_layout</tt>:: Either <tt>:portrait</tt> or <tt>:landscape</tt>
103
+ # <tt>:left_margin</tt>:: Sets the left margin in points [0.5 inch]
104
+ # <tt>:right_margin</tt>:: Sets the right margin in points [0.5 inch]
105
+ # <tt>:top_margin</tt>:: Sets the top margin in points [0.5 inch]
106
+ # <tt>:bottom_margin</tt>:: Sets the bottom margin in points [0.5 inch]
107
+ # <tt>:skip_page_creation</tt>:: Creates a document without starting the first page [false]
108
+ # <tt>:compress</tt>:: Compresses content streams before rendering them [false]
109
+ # <tt>:background</tt>:: An image path to be used as background on all pages [nil]
110
+ # <tt>:info</tt>:: Generic hash allowing for custom metadata properties [nil]
111
+
112
+ # Additionally, :page_size can be specified as a simple two value array giving
113
+ # the width and height of the document you need in PDF Points.
114
+ #
115
+ # Usage:
116
+ #
117
+ # # New document, US Letter paper, portrait orientation
118
+ # pdf = Prawn::Document.new
119
+ #
120
+ # # New document, A4 paper, landscaped
121
+ # pdf = Prawn::Document.new(:page_size => "A4", :page_layout => :landscape)
122
+ #
123
+ # # New document, Custom size
124
+ # pdf = Prawn::Document.new(:page_size => [200, 300])
125
+ #
126
+ # # New document, with background
127
+ # pdf = Prawn::Document.new(:background => "#{Prawn::BASEDIR}/data/images/pigs.jpg")
128
+ #
129
+ def initialize(options={},&block)
130
+ Prawn.verify_options [:page_size, :page_layout, :left_margin,
131
+ :right_margin, :top_margin, :bottom_margin, :skip_page_creation,
132
+ :compress, :skip_encoding, :text_options, :background, :info], options
133
+
134
+ options[:info] ||= {}
135
+ options[:info][:Creator] ||= "Prawn"
136
+ options[:info][:Producer] = "Prawn"
137
+
138
+ options[:info].keys.each do |key|
139
+ if options[:info][key].kind_of?(String)
140
+ options[:info][key] = Prawn::LiteralString.new(options[:info][key])
141
+ end
142
+ end
143
+
144
+ @version = 1.3
145
+ @objects = []
146
+ @info = ref(options[:info])
147
+ @pages = ref(:Type => :Pages, :Count => 0, :Kids => [])
148
+ @root = ref(:Type => :Catalog, :Pages => @pages)
149
+ @page_size = options[:page_size] || "LETTER"
150
+ @page_layout = options[:page_layout] || :portrait
151
+ @compress = options[:compress] || false
152
+ @skip_encoding = options[:skip_encoding]
153
+ @background = options[:background]
154
+ @font_size = 12
155
+
156
+ text_options.update(options[:text_options] || {})
157
+
158
+ @margins = { :left => options[:left_margin] || 36,
159
+ :right => options[:right_margin] || 36,
160
+ :top => options[:top_margin] || 36,
161
+ :bottom => options[:bottom_margin] || 36 }
162
+
163
+ generate_margin_box
164
+
165
+ @bounding_box = @margin_box
166
+
167
+ start_new_page unless options[:skip_page_creation]
168
+
169
+ if block
170
+ block.arity < 1 ? instance_eval(&block) : block[self]
171
+ end
172
+ end
173
+
174
+ # Creates and advances to a new page in the document.
175
+ #
176
+ # Page size, margins, and layout can also be set when generating a
177
+ # new page. These values will become the new defaults for page creation
178
+ #
179
+ # pdf.start_new_page #=> Starts new page keeping current values
180
+ # pdf.start_new_page(:size => "LEGAL", :layout => :landscape)
181
+ # pdf.start_new_page(:left_margin => 50, :right_margin => 50)
182
+ #
183
+ def start_new_page(options = {})
184
+ @page_size = options[:size] if options[:size]
185
+ @page_layout = options[:layout] if options[:layout]
186
+
187
+ [:left,:right,:top,:bottom].each do |side|
188
+ if options[:"#{side}_margin"]
189
+ @margins[side] = options[:"#{side}_margin"]
190
+ end
191
+ end
192
+
193
+ finish_page_content if @page_content
194
+ build_new_page_content
195
+
196
+ @pages.data[:Kids] << @current_page
197
+ @pages.data[:Count] += 1
198
+
199
+ add_content "q"
200
+
201
+ @y = @bounding_box.absolute_top
202
+
203
+ image(@background, :at => [0,@y]) if @background
204
+ end
205
+
206
+ # Returns the number of pages in the document
207
+ #
208
+ # pdf = Prawn::Document.new
209
+ # pdf.page_count #=> 1
210
+ # 3.times { pdf.start_new_page }
211
+ # pdf.page_count #=> 4
212
+ #
213
+ def page_count
214
+ @pages.data[:Count]
215
+ end
216
+
217
+ # The current y drawing position relative to the innermost bounding box,
218
+ # or to the page margins at the top level.
219
+ #
220
+ def cursor
221
+ y - bounds.absolute_bottom
222
+ end
223
+
224
+ # Renders the PDF document to string, useful for example in a Rails
225
+ # application where you want to stream out the PDF to a web browser:
226
+ #
227
+ # def show
228
+ # pdf = Prawn::Document.new do
229
+ # text "Putting PDF generation code in a controller is _BAD_"
230
+ # end
231
+ # send(pdf.render, :filename => 'silly.pdf', :type => 'application/pdf', :disposition => 'inline)
232
+ # end
233
+ #
234
+ def render
235
+ output = StringIO.new
236
+ finish_page_content
237
+
238
+ render_header(output)
239
+ render_body(output)
240
+ render_xref(output)
241
+ render_trailer(output)
242
+ str = output.string
243
+ str.force_encoding("ASCII-8BIT") if str.respond_to?(:force_encoding)
244
+ str
245
+ end
246
+
247
+ # Renders the PDF document to file.
248
+ #
249
+ # pdf.render_file "foo.pdf"
250
+ #
251
+ def render_file(filename)
252
+ Kernel.const_defined?("Encoding") ? mode = "wb:ASCII-8BIT" : mode = "wb"
253
+ File.open(filename,mode) { |f| f << render }
254
+ end
255
+
256
+ # The bounds method returns the current bounding box you are currently in,
257
+ # which is by default the box represented by the margin box on the
258
+ # document itself. When called from within a created <tt>bounding_box</tt>
259
+ # block, the box defined by that call will be returned instead of the
260
+ # document margin box.
261
+ #
262
+ # Another important point about bounding boxes is that all x and y measurements
263
+ # within a bounding box code block are relative to the bottom left corner of the
264
+ # bounding box.
265
+ #
266
+ # For example:
267
+ #
268
+ # Prawn::Document.new do
269
+ # # In the default "margin box" of a Prawn document of 0.5in along each edge
270
+ #
271
+ # # Draw a border around the page (the manual way)
272
+ # stroke do
273
+ # line(bounds.bottom_left, bounds.bottom_right)
274
+ # line(bounds.bottom_right, bounds.top_right)
275
+ # line(bounds.top_right, bounds.top_left)
276
+ # line(bounds.top_left, bounds.bottom_left)
277
+ # end
278
+ #
279
+ # # Draw a border around the page (the easy way)
280
+ # stroke_bounds
281
+ # end
282
+ #
283
+ def bounds
284
+ @bounding_box
285
+ end
286
+
287
+ # Sets Document#bounds to the BoundingBox provided. See above for a brief
288
+ # description of what a bounding box is. This function is useful if you
289
+ # really need to change the bounding box manually, but usually, just entering
290
+ # and existing bounding box code blocks is good enough.
291
+ #
292
+ def bounds=(bounding_box)
293
+ @bounding_box = bounding_box
294
+ end
295
+
296
+ # Moves up the document by n points relative to the current position inside
297
+ # the current bounding box.
298
+ #
299
+ def move_up(n)
300
+ self.y += n
301
+ end
302
+
303
+ # Moves down the document by n points relative to the current position inside
304
+ # the current bounding box.
305
+ #
306
+ def move_down(n)
307
+ self.y -= n
308
+ end
309
+
310
+ # Moves down the document and then executes a block.
311
+ #
312
+ # pdf.text "some text"
313
+ # pdf.pad_top(100) do
314
+ # pdf.text "This is 100 points below the previous line of text"
315
+ # end
316
+ # pdf.text "This text appears right below the previous line of text"
317
+ #
318
+ def pad_top(y)
319
+ move_down(y)
320
+ yield
321
+ end
322
+
323
+ # Executes a block then moves down the document
324
+ #
325
+ # pdf.text "some text"
326
+ # pdf.pad_bottom(100) do
327
+ # pdf.text "This text appears right below the previous line of text"
328
+ # end
329
+ # pdf.text "This is 100 points below the previous line of text"
330
+ #
331
+ def pad_bottom(y)
332
+ yield
333
+ move_down(y)
334
+ end
335
+
336
+ # Moves down the document by y, executes a block, then moves down the
337
+ # document by y again.
338
+ #
339
+ # pdf.text "some text"
340
+ # pdf.pad(100) do
341
+ # pdf.text "This is 100 points below the previous line of text"
342
+ # end
343
+ # pdf.text "This is 100 points below the previous line of text"
344
+ #
345
+ def pad(y)
346
+ move_down(y)
347
+ yield
348
+ move_down(y)
349
+ end
350
+
351
+ def mask(*fields) # :nodoc:
352
+ # Stores the current state of the named attributes, executes the block, and
353
+ # then restores the original values after the block has executed.
354
+ # -- I will remove the nodoc if/when this feature is a little less hacky
355
+ stored = {}
356
+ fields.each { |f| stored[f] = send(f) }
357
+ yield
358
+ fields.each { |f| send("#{f}=", stored[f]) }
359
+ end
360
+
361
+ # Returns true if content streams will be compressed before rendering,
362
+ # false otherwise
363
+ #
364
+ def compression_enabled?
365
+ !!@compress
366
+ end
367
+
368
+ private
369
+
370
+ # See Prawn::Document::Internals for low-level PDF functions
371
+
372
+ def build_new_page_content
373
+ generate_margin_box
374
+ @page_content = ref(:Length => 0)
375
+
376
+ @current_page = ref(:Type => :Page,
377
+ :Parent => @pages,
378
+ :MediaBox => page_dimensions,
379
+ :Contents => @page_content)
380
+ update_colors
381
+ end
382
+
383
+ def generate_margin_box
384
+ old_margin_box = @margin_box
385
+ @margin_box = BoundingBox.new(
386
+ self,
387
+ [ @margins[:left], page_dimensions[-1] - @margins[:top] ] ,
388
+ :width => page_dimensions[-2] - (@margins[:left] + @margins[:right]),
389
+ :height => page_dimensions[-1] - (@margins[:top] + @margins[:bottom])
390
+ )
391
+
392
+ # update bounding box if not flowing from the previous page
393
+ # FIXME: This may have a bug where the old margin is restored
394
+ # when the bounding box exits.
395
+ @bounding_box = @margin_box if old_margin_box == @bounding_box
396
+ end
397
+
398
+ end
399
+ end