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
@@ -1,212 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # prawn/core/page.rb : Implements low-level representation of a PDF page
4
- #
5
- # Copyright February 2010, Gregory Brown. All Rights Reserved.
6
- #
7
- # This is free software. Please see the LICENSE and COPYING files for details.
8
- #
9
-
10
- require 'prawn/document/graphics_state'
11
-
12
- module Prawn
13
- module Core
14
- class Page #:nodoc:
15
-
16
- include Prawn::Core::Page::GraphicsState
17
-
18
- attr_accessor :document, :content, :dictionary, :margins, :stack
19
-
20
- def initialize(document, options={})
21
- @document = document
22
- @margins = options[:margins] || { :left => 36,
23
- :right => 36,
24
- :top => 36,
25
- :bottom => 36 }
26
- @stack = Prawn::GraphicStateStack.new(options[:graphic_state])
27
- if options[:object_id]
28
- init_from_object(options)
29
- else
30
- init_new_page(options)
31
- end
32
- end
33
-
34
- def layout
35
- return @layout if @layout
36
-
37
- mb = dictionary.data[:MediaBox]
38
- if mb[3] > mb[2]
39
- :portrait
40
- else
41
- :landscape
42
- end
43
- end
44
-
45
- def size
46
- @size || dimensions[2,2]
47
- end
48
-
49
- def in_stamp_stream?
50
- !!@stamp_stream
51
- end
52
-
53
- def stamp_stream(dictionary)
54
- @stamp_stream = ""
55
- @stamp_dictionary = dictionary
56
- graphic_stack_size = stack.stack.size
57
-
58
- document.save_graphics_state
59
- document.send(:freeze_stamp_graphics)
60
- yield if block_given?
61
-
62
- until graphic_stack_size == stack.stack.size
63
- document.restore_graphics_state
64
- end
65
-
66
- @stamp_dictionary << @stamp_stream
67
-
68
- @stamp_stream = nil
69
- @stamp_dictionary = nil
70
- end
71
-
72
- def content
73
- @stamp_stream || document.state.store[@content]
74
- end
75
-
76
- # As per the PDF spec, each page can have multiple content streams. This will
77
- # add a fresh, empty content stream this the page, mainly for use in loading
78
- # template files.
79
- #
80
- def new_content_stream
81
- return if in_stamp_stream?
82
-
83
- unless dictionary.data[:Contents].is_a?(Array)
84
- dictionary.data[:Contents] = [content]
85
- end
86
- @content = document.ref({})
87
- dictionary.data[:Contents] << document.state.store[@content]
88
- document.open_graphics_state
89
- end
90
-
91
- def dictionary
92
- @stamp_dictionary || document.state.store[@dictionary]
93
- end
94
-
95
- def resources
96
- if dictionary.data[:Resources]
97
- document.deref(dictionary.data[:Resources])
98
- else
99
- dictionary.data[:Resources] = {}
100
- end
101
- end
102
-
103
- def fonts
104
- if resources[:Font]
105
- document.deref(resources[:Font])
106
- else
107
- resources[:Font] = {}
108
- end
109
- end
110
-
111
- def xobjects
112
- if resources[:XObject]
113
- document.deref(resources[:XObject])
114
- else
115
- resources[:XObject] = {}
116
- end
117
- end
118
-
119
- def ext_gstates
120
- if resources[:ExtGState]
121
- document.deref(resources[:ExtGState])
122
- else
123
- resources[:ExtGState] = {}
124
- end
125
- end
126
-
127
- def finalize
128
- if dictionary.data[:Contents].is_a?(Array)
129
- dictionary.data[:Contents].each do |stream|
130
- stream.compress_stream if document.compression_enabled?
131
- end
132
- else
133
- content.compress_stream if document.compression_enabled?
134
- end
135
- end
136
-
137
- def imported_page?
138
- @imported_page
139
- end
140
-
141
- def dimensions
142
- return inherited_dictionary_value(:MediaBox) if imported_page?
143
-
144
- coords = Prawn::Document::PageGeometry::SIZES[size] || size
145
- [0,0] + case(layout)
146
- when :portrait
147
- coords
148
- when :landscape
149
- coords.reverse
150
- else
151
- raise Prawn::Errors::InvalidPageLayout,
152
- "Layout must be either :portrait or :landscape"
153
- end
154
- end
155
-
156
- private
157
-
158
- def init_from_object(options)
159
- @dictionary = options[:object_id].to_i
160
- dictionary.data[:Parent] = document.state.store.pages if options[:page_template]
161
-
162
- unless dictionary.data[:Contents].is_a?(Array) # content only on leafs
163
- @content = dictionary.data[:Contents].identifier
164
- end
165
-
166
- @stamp_stream = nil
167
- @stamp_dictionary = nil
168
- @imported_page = true
169
- end
170
-
171
- def init_new_page(options)
172
- @size = options[:size] || "LETTER"
173
- @layout = options[:layout] || :portrait
174
-
175
- @content = document.ref({})
176
- content << "q" << "\n"
177
- @dictionary = document.ref(:Type => :Page,
178
- :Parent => document.state.store.pages,
179
- :MediaBox => dimensions,
180
- :Contents => content)
181
-
182
- resources[:ProcSet] = [:PDF, :Text, :ImageB, :ImageC, :ImageI]
183
-
184
- @stamp_stream = nil
185
- @stamp_dictionary = nil
186
- end
187
-
188
- # some entries in the Page dict can be inherited from parent Pages dicts.
189
- #
190
- # Starting with the current page dict, this method will walk up the
191
- # inheritance chain return the first value that is found for key
192
- #
193
- # inherited_dictionary_value(:MediaBox)
194
- # => [ 0, 0, 595, 842 ]
195
- #
196
- def inherited_dictionary_value(key, local_dict = nil)
197
- local_dict ||= dictionary.data
198
-
199
- if local_dict.has_key?(key)
200
- local_dict[key]
201
- elsif local_dict.has_key?(:Parent)
202
- inherited_dictionary_value(key, local_dict[:Parent].data)
203
- else
204
- nil
205
- end
206
- end
207
-
208
- end
209
-
210
- end
211
- end
212
-
@@ -1,125 +0,0 @@
1
- # encoding: utf-8
2
- #
3
- # pdf_object.rb : Handles Ruby to PDF object serialization
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
- # Top level Module
10
- #
11
- module Prawn
12
- module Core #:nodoc:
13
-
14
- module_function
15
-
16
- if "".respond_to?(:encode)
17
- # Ruby 1.9+
18
- def utf8_to_utf16(str)
19
- utf16 = "\xFE\xFF".force_encoding("UTF-16BE") + str.encode("UTF-16BE")
20
- end
21
-
22
- # encodes any string into a hex representation. The result is a string
23
- # with only 0-9 and a-f characters. That result is valid ASCII so tag
24
- # it as such to account for behaviour of different ruby VMs
25
- def string_to_hex(str)
26
- str.unpack("H*").first.force_encoding("ascii")
27
- end
28
- else
29
- # Ruby 1.8
30
- def utf8_to_utf16(str)
31
- utf16 = "\xFE\xFF"
32
-
33
- str.codepoints do |cp|
34
- if cp < 0x10000 # Basic Multilingual Plane
35
- utf16 << [cp].pack("n")
36
- else
37
- # pull out high/low 10 bits
38
- hi, lo = (cp - 0x10000).divmod(2**10)
39
- # encode a surrogate pair
40
- utf16 << [0xD800 + hi, 0xDC00 + lo].pack("n*")
41
- end
42
- end
43
-
44
- utf16
45
- end
46
-
47
- def string_to_hex(str)
48
- str.unpack("H*").first
49
- end
50
- end
51
-
52
- # Serializes Ruby objects to their PDF equivalents. Most primitive objects
53
- # will work as expected, but please note that Name objects are represented
54
- # by Ruby Symbol objects and Dictionary objects are represented by Ruby hashes
55
- # (keyed by symbols)
56
- #
57
- # Examples:
58
- #
59
- # PdfObject(true) #=> "true"
60
- # PdfObject(false) #=> "false"
61
- # PdfObject(1.2124) #=> "1.2124"
62
- # PdfObject("foo bar") #=> "(foo bar)"
63
- # PdfObject(:Symbol) #=> "/Symbol"
64
- # PdfObject(["foo",:bar, [1,2]]) #=> "[foo /bar [1 2]]"
65
- #
66
- def PdfObject(obj, in_content_stream = false)
67
- case(obj)
68
- when NilClass then "null"
69
- when TrueClass then "true"
70
- when FalseClass then "false"
71
- when Numeric
72
- if (str = String(obj)) =~ /e/i
73
- # scientific notation is not supported in PDF
74
- sprintf("%.16f", obj).gsub(/\.?0+\z/, "")
75
- else
76
- str
77
- end
78
- when Array
79
- "[" << obj.map { |e| PdfObject(e, in_content_stream) }.join(' ') << "]"
80
- when Prawn::Core::LiteralString
81
- obj = obj.gsub(/[\\\n\r\t\b\f\(\)]/n) { |m| "\\#{m}" }
82
- "(#{obj})"
83
- when Time
84
- obj = obj.strftime("D:%Y%m%d%H%M%S%z").chop.chop + "'00'"
85
- obj = obj.gsub(/[\\\n\r\t\b\f\(\)]/n) { |m| "\\#{m}" }
86
- "(#{obj})"
87
- when Prawn::Core::ByteString
88
- "<" << obj.unpack("H*").first << ">"
89
- when String
90
- obj = utf8_to_utf16(obj) unless in_content_stream
91
- "<" << string_to_hex(obj) << ">"
92
- when Symbol
93
- "/" + obj.to_s.unpack("C*").map { |n|
94
- if n < 33 || n > 126 || [35,40,41,47,60,62].include?(n)
95
- "#" + n.to_s(16).upcase
96
- else
97
- [n].pack("C*")
98
- end
99
- }.join
100
- when Hash
101
- output = "<< "
102
- obj.each do |k,v|
103
- unless String === k || Symbol === k
104
- raise Prawn::Errors::FailedObjectConversion,
105
- "A PDF Dictionary must be keyed by names"
106
- end
107
- output << PdfObject(k.to_sym, in_content_stream) << " " <<
108
- PdfObject(v, in_content_stream) << "\n"
109
- end
110
- output << ">>"
111
- when Prawn::Core::Reference
112
- obj.to_s
113
- when Prawn::Core::NameTree::Node
114
- PdfObject(obj.to_hash)
115
- when Prawn::Core::NameTree::Value
116
- PdfObject(obj.name) + " " + PdfObject(obj.value)
117
- when Prawn::OutlineRoot, Prawn::OutlineItem
118
- PdfObject(obj.to_hash)
119
- else
120
- raise Prawn::Errors::FailedObjectConversion,
121
- "This object cannot be serialized to PDF (#{obj.inspect})"
122
- end
123
- end
124
- end
125
- end
@@ -1,119 +0,0 @@
1
- # encoding: utf-8
2
-
3
- # reference.rb : Implementation of PDF indirect objects
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 'zlib'
10
-
11
- module Prawn
12
- module Core
13
-
14
- class Reference #:nodoc:
15
-
16
- attr_accessor :gen, :data, :offset, :stream, :live, :identifier
17
-
18
- def initialize(id, data)
19
- @identifier = id
20
- @gen = 0
21
- @data = data
22
- @compressed = false
23
- @stream = nil
24
- end
25
-
26
- def object
27
- output = "#{@identifier} #{gen} obj\n" <<
28
- Prawn::Core::PdfObject(data) << "\n"
29
- if @stream
30
- output << "stream\n" << @stream << "\nendstream\n"
31
- end
32
- output << "endobj\n"
33
- end
34
-
35
- def <<(data)
36
- raise 'Cannot add data to a stream that is compressed' if @compressed
37
- (@stream ||= "") << data
38
- @data[:Length] = @stream.length
39
- @stream
40
- end
41
-
42
- def to_s
43
- "#{@identifier} #{gen} R"
44
- end
45
-
46
- def compress_stream
47
- @stream = Zlib::Deflate.deflate(@stream)
48
- @data[:Filter] = :FlateDecode
49
- @data[:Length] = @stream.length
50
- @compressed = true
51
- end
52
-
53
- def compressed?
54
- @compressed
55
- end
56
-
57
- # Creates a deep copy of this ref. If +share+ is provided, shares the
58
- # given dictionary entries between the old ref and the new.
59
- #
60
- def deep_copy(share=[])
61
- r = dup
62
-
63
- case r.data
64
- when Hash
65
- # Copy each entry not in +share+.
66
- (r.data.keys - share).each do |k|
67
- r.data[k] = Marshal.load(Marshal.dump(r.data[k]))
68
- end
69
- when Prawn::Core::NameTree::Node
70
- r.data = r.data.deep_copy
71
- else
72
- r.data = Marshal.load(Marshal.dump(r.data))
73
- end
74
-
75
- r.stream = Marshal.load(Marshal.dump(r.stream))
76
- r
77
- end
78
-
79
- # Replaces the data and stream with that of other_ref. Preserves compressed
80
- # status.
81
- def replace(other_ref)
82
- @data = other_ref.data
83
- @stream = other_ref.stream
84
- @compressed = other_ref.compressed?
85
- end
86
-
87
- # Marks this and all referenced objects live, recursively.
88
- def mark_live
89
- return if @live
90
- @live = true
91
- referenced_objects.each { |o| o.mark_live }
92
- end
93
-
94
- private
95
-
96
- # All objects referenced by this one. Used for GC.
97
- def referenced_objects(obj=@data)
98
- case obj
99
- when self.class
100
- []
101
- when Hash
102
- obj.values.map{|v| [v] + referenced_objects(v) }
103
- when Array
104
- obj.map{|v| [v] + referenced_objects(v) }
105
- when OutlineRoot, OutlineItem
106
- referenced_objects(obj.to_hash)
107
- else []
108
- end.flatten.grep(self.class)
109
- end
110
-
111
- end
112
-
113
- module_function
114
-
115
- def Reference(*args, &block) #:nodoc:
116
- Reference.new(*args, &block)
117
- end
118
- end
119
- end