alphasights-prawn 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. data/COPYING +340 -0
  2. data/HACKING +50 -0
  3. data/LICENSE +56 -0
  4. data/README +141 -0
  5. data/Rakefile +52 -0
  6. data/data/encodings/win_ansi.txt +29 -0
  7. data/data/fonts/Action Man.dfont +0 -0
  8. data/data/fonts/Activa.ttf +0 -0
  9. data/data/fonts/Chalkboard.ttf +0 -0
  10. data/data/fonts/Courier-Bold.afm +342 -0
  11. data/data/fonts/Courier-BoldOblique.afm +342 -0
  12. data/data/fonts/Courier-Oblique.afm +342 -0
  13. data/data/fonts/Courier.afm +342 -0
  14. data/data/fonts/DejaVuSans.ttf +0 -0
  15. data/data/fonts/Dustismo_Roman.ttf +0 -0
  16. data/data/fonts/Helvetica-Bold.afm +2827 -0
  17. data/data/fonts/Helvetica-BoldOblique.afm +2827 -0
  18. data/data/fonts/Helvetica-Oblique.afm +3051 -0
  19. data/data/fonts/Helvetica.afm +3051 -0
  20. data/data/fonts/MustRead.html +19 -0
  21. data/data/fonts/Symbol.afm +213 -0
  22. data/data/fonts/Times-Bold.afm +2588 -0
  23. data/data/fonts/Times-BoldItalic.afm +2384 -0
  24. data/data/fonts/Times-Italic.afm +2667 -0
  25. data/data/fonts/Times-Roman.afm +2419 -0
  26. data/data/fonts/ZapfDingbats.afm +225 -0
  27. data/data/fonts/comicsans.ttf +0 -0
  28. data/data/fonts/gkai00mp.ttf +0 -0
  29. data/data/images/16bit.alpha +0 -0
  30. data/data/images/16bit.dat +0 -0
  31. data/data/images/16bit.png +0 -0
  32. data/data/images/arrow.png +0 -0
  33. data/data/images/arrow2.png +0 -0
  34. data/data/images/barcode_issue.png +0 -0
  35. data/data/images/dice.alpha +0 -0
  36. data/data/images/dice.dat +0 -0
  37. data/data/images/dice.png +0 -0
  38. data/data/images/dice_interlaced.png +0 -0
  39. data/data/images/fractal.jpg +0 -0
  40. data/data/images/letterhead.jpg +0 -0
  41. data/data/images/page_white_text.alpha +0 -0
  42. data/data/images/page_white_text.dat +0 -0
  43. data/data/images/page_white_text.png +0 -0
  44. data/data/images/pigs.jpg +0 -0
  45. data/data/images/rails.dat +0 -0
  46. data/data/images/rails.png +0 -0
  47. data/data/images/ruport.png +0 -0
  48. data/data/images/ruport_data.dat +0 -0
  49. data/data/images/ruport_transparent.png +0 -0
  50. data/data/images/ruport_type0.png +0 -0
  51. data/data/images/stef.jpg +0 -0
  52. data/data/images/tru256.bmp +0 -0
  53. data/data/images/web-links.dat +1 -0
  54. data/data/images/web-links.png +0 -0
  55. data/data/pdfs/complex_template.pdf +0 -0
  56. data/data/pdfs/contains_ttf_font.pdf +0 -0
  57. data/data/pdfs/encrypted.pdf +0 -0
  58. data/data/pdfs/hexagon.pdf +61 -0
  59. data/data/pdfs/indirect_reference.pdf +86 -0
  60. data/data/pdfs/nested_pages.pdf +118 -0
  61. data/data/pdfs/resources_as_indirect_object.pdf +83 -0
  62. data/data/pdfs/two_hexagons.pdf +90 -0
  63. data/data/pdfs/version_1_6.pdf +61 -0
  64. data/data/shift_jis_text.txt +1 -0
  65. data/examples/bounding_box/bounding_boxes.rb +43 -0
  66. data/examples/bounding_box/indentation.rb +34 -0
  67. data/examples/bounding_box/russian_boxes.rb +36 -0
  68. data/examples/bounding_box/stretched_nesting.rb +67 -0
  69. data/examples/builder/simple.rb +28 -0
  70. data/examples/example_helper.rb +4 -0
  71. data/examples/general/background.rb +23 -0
  72. data/examples/general/canvas.rb +15 -0
  73. data/examples/general/context_sensitive_headers.rb +37 -0
  74. data/examples/general/float.rb +11 -0
  75. data/examples/general/margin.rb +36 -0
  76. data/examples/general/measurement_units.rb +51 -0
  77. data/examples/general/metadata-info.rb +16 -0
  78. data/examples/general/multi_page_layout.rb +18 -0
  79. data/examples/general/outlines.rb +50 -0
  80. data/examples/general/page_geometry.rb +31 -0
  81. data/examples/general/page_numbering.rb +15 -0
  82. data/examples/general/repeaters.rb +47 -0
  83. data/examples/general/stamp.rb +41 -0
  84. data/examples/general/templates.rb +13 -0
  85. data/examples/graphics/basic_images.rb +23 -0
  86. data/examples/graphics/chunkable.rb +38 -0
  87. data/examples/graphics/cmyk.rb +12 -0
  88. data/examples/graphics/curves.rb +11 -0
  89. data/examples/graphics/hexagon.rb +13 -0
  90. data/examples/graphics/image_fit.rb +15 -0
  91. data/examples/graphics/image_flow.rb +37 -0
  92. data/examples/graphics/image_position.rb +17 -0
  93. data/examples/graphics/line.rb +32 -0
  94. data/examples/graphics/png_types.rb +22 -0
  95. data/examples/graphics/polygons.rb +16 -0
  96. data/examples/graphics/remote_images.rb +12 -0
  97. data/examples/graphics/rounded_polygons.rb +19 -0
  98. data/examples/graphics/rounded_rectangle.rb +20 -0
  99. data/examples/graphics/ruport_style_helpers.rb +19 -0
  100. data/examples/graphics/stroke_bounds.rb +20 -0
  101. data/examples/graphics/stroke_cap_and_join.rb +45 -0
  102. data/examples/graphics/stroke_dash.rb +42 -0
  103. data/examples/graphics/transformations.rb +52 -0
  104. data/examples/graphics/transparency.rb +26 -0
  105. data/examples/m17n/chinese_text_wrapping.rb +17 -0
  106. data/examples/m17n/euro.rb +15 -0
  107. data/examples/m17n/sjis.rb +28 -0
  108. data/examples/m17n/utf8.rb +13 -0
  109. data/examples/m17n/win_ansi_charset.rb +54 -0
  110. data/examples/security/hello_foo.rb +8 -0
  111. data/examples/table/bill.rb +53 -0
  112. data/examples/table/cell.rb +12 -0
  113. data/examples/table/checkerboard.rb +22 -0
  114. data/examples/table/header.rb +14 -0
  115. data/examples/table/inline_format_table.rb +12 -0
  116. data/examples/table/multi_page_table.rb +9 -0
  117. data/examples/table/simple_table.rb +24 -0
  118. data/examples/table/subtable.rb +12 -0
  119. data/examples/table/widths.rb +20 -0
  120. data/examples/text/alignment.rb +18 -0
  121. data/examples/text/character_spacing.rb +12 -0
  122. data/examples/text/dfont.rb +48 -0
  123. data/examples/text/family_based_styling.rb +24 -0
  124. data/examples/text/font_calculations.rb +91 -0
  125. data/examples/text/font_size.rb +33 -0
  126. data/examples/text/hyphenation.rb +45 -0
  127. data/examples/text/indent_paragraphs.rb +22 -0
  128. data/examples/text/inline_format.rb +103 -0
  129. data/examples/text/kerning.rb +30 -0
  130. data/examples/text/rotated.rb +98 -0
  131. data/examples/text/shaped_text_box.rb +31 -0
  132. data/examples/text/simple_text.rb +17 -0
  133. data/examples/text/simple_text_ttf.rb +17 -0
  134. data/examples/text/text_box.rb +88 -0
  135. data/examples/text/text_box_returning_excess.rb +51 -0
  136. data/examples/text/text_flow.rb +67 -0
  137. data/lib/prawn.rb +27 -0
  138. data/lib/prawn/canvas.rb +119 -0
  139. data/lib/prawn/chunkable.rb +37 -0
  140. data/lib/prawn/compatibility.rb +51 -0
  141. data/lib/prawn/core.rb +85 -0
  142. data/lib/prawn/core/annotations.rb +61 -0
  143. data/lib/prawn/core/byte_string.rb +9 -0
  144. data/lib/prawn/core/chunk.rb +36 -0
  145. data/lib/prawn/core/destinations.rb +90 -0
  146. data/lib/prawn/core/document_state.rb +78 -0
  147. data/lib/prawn/core/literal_string.rb +16 -0
  148. data/lib/prawn/core/name_tree.rb +165 -0
  149. data/lib/prawn/core/object_store.rb +236 -0
  150. data/lib/prawn/core/page.rb +179 -0
  151. data/lib/prawn/core/pdf_object.rb +108 -0
  152. data/lib/prawn/core/reference.rb +112 -0
  153. data/lib/prawn/core/text.rb +140 -0
  154. data/lib/prawn/core/text/formatted/arranger.rb +266 -0
  155. data/lib/prawn/core/text/formatted/line_wrap.rb +127 -0
  156. data/lib/prawn/core/text/formatted/wrap.rb +112 -0
  157. data/lib/prawn/core/text/line_wrap.rb +209 -0
  158. data/lib/prawn/core/text/wrap.rb +80 -0
  159. data/lib/prawn/document.rb +573 -0
  160. data/lib/prawn/document/bounding_box.rb +425 -0
  161. data/lib/prawn/document/graphics_state.rb +48 -0
  162. data/lib/prawn/document/internals.rb +170 -0
  163. data/lib/prawn/document/page_geometry.rb +136 -0
  164. data/lib/prawn/document/snapshot.rb +87 -0
  165. data/lib/prawn/document_builder.rb +51 -0
  166. data/lib/prawn/document_builder/command.rb +38 -0
  167. data/lib/prawn/document_builder/constructs.rb +2 -0
  168. data/lib/prawn/document_builder/constructs/flowing_text_construct.rb +18 -0
  169. data/lib/prawn/document_builder/constructs/path_construct.rb +9 -0
  170. data/lib/prawn/document_builder/layout.rb +25 -0
  171. data/lib/prawn/document_builder/modifications.rb +2 -0
  172. data/lib/prawn/document_builder/modifications/layout_modification.rb +9 -0
  173. data/lib/prawn/document_builder/modifications/path_modification.rb +9 -0
  174. data/lib/prawn/encoding.rb +121 -0
  175. data/lib/prawn/errors.rb +94 -0
  176. data/lib/prawn/font.rb +341 -0
  177. data/lib/prawn/font/afm.rb +225 -0
  178. data/lib/prawn/font/dfont.rb +42 -0
  179. data/lib/prawn/font/ttf.rb +350 -0
  180. data/lib/prawn/graphics.rb +325 -0
  181. data/lib/prawn/graphics/cap_style.rb +38 -0
  182. data/lib/prawn/graphics/color.rb +205 -0
  183. data/lib/prawn/graphics/dash.rb +71 -0
  184. data/lib/prawn/graphics/join_style.rb +38 -0
  185. data/lib/prawn/graphics/transformation.rb +156 -0
  186. data/lib/prawn/graphics/transparency.rb +99 -0
  187. data/lib/prawn/images.rb +348 -0
  188. data/lib/prawn/images/jpg.rb +46 -0
  189. data/lib/prawn/images/png.rb +226 -0
  190. data/lib/prawn/measurement_extensions.rb +46 -0
  191. data/lib/prawn/measurements.rb +71 -0
  192. data/lib/prawn/outline.rb +278 -0
  193. data/lib/prawn/repeater.rb +129 -0
  194. data/lib/prawn/security.rb +262 -0
  195. data/lib/prawn/security/arcfour.rb +51 -0
  196. data/lib/prawn/stamp.rb +126 -0
  197. data/lib/prawn/table.rb +421 -0
  198. data/lib/prawn/table/accessors.rb +180 -0
  199. data/lib/prawn/table/cell.rb +350 -0
  200. data/lib/prawn/table/cell/in_table.rb +27 -0
  201. data/lib/prawn/table/cell/subtable.rb +65 -0
  202. data/lib/prawn/table/cell/text.rb +125 -0
  203. data/lib/prawn/text.rb +449 -0
  204. data/lib/prawn/text/box.rb +392 -0
  205. data/lib/prawn/text/formatted.rb +4 -0
  206. data/lib/prawn/text/formatted/box.rb +228 -0
  207. data/lib/prawn/text/formatted/fragment.rb +181 -0
  208. data/lib/prawn/text/formatted/parser.rb +213 -0
  209. data/spec/annotations_spec.rb +90 -0
  210. data/spec/bounding_box_spec.rb +190 -0
  211. data/spec/cell_spec.rb +348 -0
  212. data/spec/destinations_spec.rb +15 -0
  213. data/spec/document_spec.rb +473 -0
  214. data/spec/font_spec.rb +324 -0
  215. data/spec/formatted_text_arranger_spec.rb +426 -0
  216. data/spec/formatted_text_box_spec.rb +756 -0
  217. data/spec/formatted_text_fragment_spec.rb +211 -0
  218. data/spec/graphics_spec.rb +446 -0
  219. data/spec/images_spec.rb +96 -0
  220. data/spec/inline_formatted_text_parser_spec.rb +502 -0
  221. data/spec/jpg_spec.rb +25 -0
  222. data/spec/line_wrap_spec.rb +341 -0
  223. data/spec/measurement_units_spec.rb +23 -0
  224. data/spec/name_tree_spec.rb +112 -0
  225. data/spec/object_store_spec.rb +160 -0
  226. data/spec/outline_spec.rb +269 -0
  227. data/spec/pdf_object_spec.rb +170 -0
  228. data/spec/png_spec.rb +237 -0
  229. data/spec/reference_spec.rb +82 -0
  230. data/spec/repeater_spec.rb +96 -0
  231. data/spec/security_spec.rb +120 -0
  232. data/spec/snapshot_spec.rb +138 -0
  233. data/spec/spec_helper.rb +26 -0
  234. data/spec/stamp_spec.rb +108 -0
  235. data/spec/stroke_styles_spec.rb +163 -0
  236. data/spec/table_spec.rb +598 -0
  237. data/spec/template_spec.rb +158 -0
  238. data/spec/text_at_spec.rb +119 -0
  239. data/spec/text_box_spec.rb +742 -0
  240. data/spec/text_spacing_spec.rb +75 -0
  241. data/spec/text_spec.rb +333 -0
  242. data/spec/text_with_inline_formatting_spec.rb +193 -0
  243. data/spec/transparency_spec.rb +89 -0
  244. metadata +331 -0
@@ -0,0 +1,236 @@
1
+ # encoding: utf-8
2
+
3
+ # prawn/core/object_store.rb : Implements PDF object repository for Prawn
4
+ #
5
+ # Copyright August 2009, Brad Ediger. All Rights Reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE and COPYING files for details.
8
+
9
+
10
+ require 'pdf/reader'
11
+
12
+ module Prawn
13
+ module Core
14
+ class ObjectStore #:nodoc:
15
+ include Enumerable
16
+
17
+ attr_reader :min_version
18
+
19
+ BASE_OBJECTS = %w[info pages root]
20
+
21
+ def initialize(opts = {})
22
+ @objects = {}
23
+ @identifiers = []
24
+
25
+ load_file(opts[:template]) if opts[:template]
26
+
27
+ @info ||= ref(opts[:info] || {}).identifier
28
+ @root ||= ref(:Type => :Catalog).identifier
29
+ if pages.nil?
30
+ root.data[:Pages] = ref(:Type => :Pages, :Count => 0, :Kids => [])
31
+ end
32
+ end
33
+
34
+ def ref(data, &block)
35
+ push(size + 1, data, &block)
36
+ end
37
+
38
+ def info
39
+ @objects[@info]
40
+ end
41
+
42
+ def root
43
+ @objects[@root]
44
+ end
45
+
46
+ def pages
47
+ root.data[:Pages]
48
+ end
49
+
50
+ def page_count
51
+ pages.data[:Count]
52
+ end
53
+
54
+ # Adds the given reference to the store and returns the reference object.
55
+ # If the object provided is not a Prawn::Core::Reference, one is created from the
56
+ # arguments provided.
57
+ #
58
+ def push(*args, &block)
59
+ reference = if args.first.is_a?(Prawn::Core::Reference)
60
+ args.first
61
+ else
62
+ Prawn::Core::Reference.new(*args, &block)
63
+ end
64
+
65
+ @objects[reference.identifier] = reference
66
+ @identifiers << reference.identifier
67
+ reference
68
+ end
69
+
70
+ alias_method :<<, :push
71
+
72
+ def each
73
+ @identifiers.each do |id|
74
+ yield @objects[id]
75
+ end
76
+ end
77
+
78
+ def [](id)
79
+ @objects[id]
80
+ end
81
+
82
+ def size
83
+ @identifiers.size
84
+ end
85
+ alias_method :length, :size
86
+
87
+ def compact
88
+ # Clear live markers
89
+ each { |o| o.live = false }
90
+
91
+ # Recursively mark reachable objects live, starting from the roots
92
+ # (the only objects referenced in the trailer)
93
+ root.mark_live
94
+ info.mark_live
95
+
96
+ # Renumber live objects to eliminate gaps (shrink the xref table)
97
+ if @objects.any?{ |_, o| !o.live }
98
+ new_id = 1
99
+ new_objects = {}
100
+ new_identifiers = []
101
+
102
+ each do |obj|
103
+ if obj.live
104
+ obj.identifier = new_id
105
+ new_objects[new_id] = obj
106
+ new_identifiers << new_id
107
+ new_id += 1
108
+ end
109
+ end
110
+
111
+ @objects = new_objects
112
+ @identifiers = new_identifiers
113
+ end
114
+ end
115
+
116
+ # returns the object ID for a particular page in the document. Pages
117
+ # are indexed starting at 1 (not 0!).
118
+ #
119
+ # object_id_for_page(1)
120
+ # => 5
121
+ # object_id_for_page(10)
122
+ # => 87
123
+ # object_id_for_page(-11)
124
+ # => 17
125
+ #
126
+ def object_id_for_page(k)
127
+ k -= 1 if k > 0
128
+ flat_page_ids = get_page_objects(pages).flatten
129
+ flat_page_ids[k]
130
+ end
131
+
132
+ private
133
+
134
+ # returns a nested array of object IDs for all pages in this object store.
135
+ #
136
+ def get_page_objects(obj)
137
+ if obj.data[:Type] == :Page
138
+ obj.identifier
139
+ elsif obj.data[:Type] == :Pages
140
+ obj.data[:Kids].map { |kid| get_page_objects(kid) }
141
+ end
142
+ end
143
+
144
+ # takes a source PDF and uses it as a template for this document.
145
+ #
146
+ def load_file(filename)
147
+ unless File.file?(filename)
148
+ raise ArgumentError, "#{filename} does not exist"
149
+ end
150
+
151
+ unless PDF.const_defined?("Hash")
152
+ raise "PDF::Hash not found. Is PDF::Reader > 0.8?"
153
+ end
154
+
155
+ hash = PDF::Hash.new(filename)
156
+ src_info = hash.trailer[:Info]
157
+ src_root = hash.trailer[:Root]
158
+ @min_version = hash.version.to_f
159
+
160
+ if hash.trailer[:Encrypt]
161
+ msg = "Template file is an encrypted PDF, it can't be used as a template"
162
+ raise Prawn::Errors::TemplateError, msg
163
+ end
164
+
165
+ if src_info
166
+ @info = load_object_graph(hash, src_info).identifier
167
+ end
168
+
169
+ if src_root
170
+ @root = load_object_graph(hash, src_root).identifier
171
+ end
172
+ rescue PDF::Reader::MalformedPDFError, PDF::Reader::InvalidObjectError
173
+ msg = "Error reading template file. If you are sure it's a valid PDF, it may be a bug."
174
+ raise Prawn::Errors::TemplateError, msg
175
+ rescue PDF::Reader::UnsupportedFeatureError
176
+ msg = "Template file contains unsupported PDF features"
177
+ raise Prawn::Errors::TemplateError, msg
178
+ end
179
+
180
+ # recurse down an object graph from a source PDF, importing all the indirect
181
+ # objects we find.
182
+ #
183
+ # hash is the PDF::Hash to extract objects from, object is the object to
184
+ # extract.
185
+ #
186
+ def load_object_graph(hash, object)
187
+ @loaded_objects ||= {}
188
+ case object
189
+ when Hash then
190
+ object.each { |key,value| object[key] = load_object_graph(hash, value) }
191
+ object
192
+ when Array then
193
+ object.map { |item| load_object_graph(hash, item)}
194
+ when PDF::Reader::Reference then
195
+ unless @loaded_objects.has_key?(object.id)
196
+ @loaded_objects[object.id] = ref(nil)
197
+ new_obj = load_object_graph(hash, hash[object])
198
+ if new_obj.kind_of?(PDF::Reader::Stream)
199
+ stream_dict = load_object_graph(hash, new_obj.hash)
200
+ @loaded_objects[object.id].data = stream_dict
201
+ @loaded_objects[object.id] << new_obj.data
202
+ else
203
+ @loaded_objects[object.id].data = new_obj
204
+ end
205
+ end
206
+ @loaded_objects[object.id]
207
+ when PDF::Reader::Stream
208
+ # Stream is a subclass of string, so this is here to prevent the stream
209
+ # being wrapped in a LiteralString
210
+ object
211
+ when String
212
+ is_utf8?(object) ? object : Prawn::Core::ByteString.new(object)
213
+ else
214
+ object
215
+ end
216
+ end
217
+
218
+ ruby_18 do
219
+ def is_utf8?(str)
220
+ begin
221
+ str.unpack("U*")
222
+ true
223
+ rescue
224
+ false
225
+ end
226
+ end
227
+ end
228
+ ruby_19 do
229
+ def is_utf8?(str)
230
+ str.force_encoding("utf-8")
231
+ str.valid_encoding?
232
+ end
233
+ end
234
+ end
235
+ end
236
+ end
@@ -0,0 +1,179 @@
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
+ module Prawn
10
+ module Core
11
+ class Page #:nodoc:
12
+ attr_accessor :document, :content, :dictionary, :margins
13
+
14
+ def initialize(document, options={})
15
+ @document = document
16
+ @margins = options[:margins] || { :left => 36,
17
+ :right => 36,
18
+ :top => 36,
19
+ :bottom => 36 }
20
+
21
+ if options[:object_id]
22
+ init_from_object(options)
23
+ else
24
+ init_new_page(options)
25
+ end
26
+ end
27
+
28
+ def layout
29
+ return @layout if @layout
30
+
31
+ mb = dictionary.data[:MediaBox]
32
+ if mb[3] > mb[2]
33
+ :portrait
34
+ else
35
+ :landscape
36
+ end
37
+ end
38
+
39
+ def size
40
+ @size || dimensions[2,2]
41
+ end
42
+
43
+ def in_stamp_stream?
44
+ !!@stamp_stream
45
+ end
46
+
47
+ def stamp_stream(dictionary)
48
+ @stamp_stream = ""
49
+ @stamp_dictionary = dictionary
50
+
51
+ document.send(:update_colors)
52
+ yield if block_given?
53
+ document.send(:update_colors)
54
+
55
+ @stamp_dictionary.data[:Length] = @stamp_stream.length + 1
56
+ @stamp_dictionary << @stamp_stream
57
+
58
+ @stamp_stream = nil
59
+ @stamp_dictionary = nil
60
+ end
61
+
62
+ def content
63
+ @stamp_stream || document.state.store[@content]
64
+ end
65
+
66
+ # As per the PDF spec, each page can have multiple content streams. This will
67
+ # add a fresh, empty content stream this the page, mainly for use in loading
68
+ # template files.
69
+ #
70
+ def new_content_stream
71
+ return if in_stamp_stream?
72
+
73
+ unless dictionary.data[:Contents].is_a?(Array)
74
+ dictionary.data[:Contents] = [content]
75
+ end
76
+ @content = document.ref(:Length => 0)
77
+ dictionary.data[:Contents] << document.state.store[@content]
78
+ end
79
+
80
+ def dictionary
81
+ @stamp_dictionary || document.state.store[@dictionary]
82
+ end
83
+
84
+ def resources
85
+ if dictionary.data[:Resources]
86
+ document.deref(dictionary.data[:Resources])
87
+ else
88
+ dictionary.data[:Resources] = {}
89
+ end
90
+ end
91
+
92
+ def fonts
93
+ if resources[:Font]
94
+ document.deref(resources[:Font])
95
+ else
96
+ resources[:Font] = {}
97
+ end
98
+ end
99
+
100
+ def xobjects
101
+ if resources[:XObject]
102
+ document.deref(resources[:XObject])
103
+ else
104
+ resources[:XObject] = {}
105
+ end
106
+ end
107
+
108
+ def ext_gstates
109
+ if resources[:ExtGState]
110
+ document.deref(resources[:ExtGState])
111
+ else
112
+ resources[:ExtGState] = {}
113
+ end
114
+ end
115
+
116
+ def finalize
117
+ if dictionary.data[:Contents].is_a?(Array)
118
+ dictionary.data[:Contents].each do |stream|
119
+ stream.compress_stream if document.compression_enabled?
120
+ stream.data[:Length] = stream.stream.size
121
+ end
122
+ else
123
+ content.compress_stream if document.compression_enabled?
124
+ content.data[:Length] = content.stream.size
125
+ end
126
+ end
127
+
128
+ def imported_page?
129
+ @imported_page
130
+ end
131
+
132
+ def dimensions
133
+ return dictionary.data[:MediaBox] if imported_page?
134
+
135
+ coords = Prawn::Document::PageGeometry::SIZES[size] || size
136
+ [0,0] + case(layout)
137
+ when :portrait
138
+ coords
139
+ when :landscape
140
+ coords.reverse
141
+ else
142
+ raise Prawn::Errors::InvalidPageLayout,
143
+ "Layout must be either :portrait or :landscape"
144
+ end
145
+ end
146
+
147
+ private
148
+
149
+ def init_from_object(options)
150
+ @dictionary = options[:object_id].to_i
151
+ unless dictionary.data[:Contents].is_a?(Array) # content only on leafs
152
+ @content = dictionary.data[:Contents].identifier
153
+ end
154
+
155
+ @stamp_stream = nil
156
+ @stamp_dictionary = nil
157
+ @imported_page = true
158
+ end
159
+
160
+ def init_new_page(options)
161
+ @size = options[:size] || "LETTER"
162
+ @layout = options[:layout] || :portrait
163
+
164
+ @content = document.ref(:Length => 0)
165
+ @dictionary = document.ref(:Type => :Page,
166
+ :Parent => document.state.store.pages,
167
+ :MediaBox => dimensions,
168
+ :Contents => content)
169
+
170
+ resources[:ProcSet] = [:PDF, :Text, :ImageB, :ImageC, :ImageI]
171
+
172
+ @stamp_stream = nil
173
+ @stamp_dictionary = nil
174
+ end
175
+
176
+ end
177
+ end
178
+ end
179
+
@@ -0,0 +1,108 @@
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
+ ruby_18 do
17
+ def utf8_to_utf16(str)
18
+ utf16 = "\xFE\xFF"
19
+
20
+ str.unpack("U*").each do |cp|
21
+ if cp < 0x10000 # Basic Multilingual Plane
22
+ utf16 << [cp].pack("n")
23
+ else
24
+ # pull out high/low 10 bits
25
+ hi, lo = (cp - 0x10000).divmod(2**10)
26
+ # encode a surrogate pair
27
+ utf16 << [0xD800 + hi, 0xDC00 + lo].pack("n*")
28
+ end
29
+ end
30
+
31
+ utf16
32
+ end
33
+ 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
+
41
+ # Serializes Ruby objects to their PDF equivalents. Most primitive objects
42
+ # will work as expected, but please note that Name objects are represented
43
+ # by Ruby Symbol objects and Dictionary objects are represented by Ruby hashes
44
+ # (keyed by symbols)
45
+ #
46
+ # Examples:
47
+ #
48
+ # PdfObject(true) #=> "true"
49
+ # PdfObject(false) #=> "false"
50
+ # PdfObject(1.2124) #=> "1.2124"
51
+ # PdfObject("foo bar") #=> "(foo bar)"
52
+ # PdfObject(:Symbol) #=> "/Symbol"
53
+ # PdfObject(["foo",:bar, [1,2]]) #=> "[foo /bar [1 2]]"
54
+ #
55
+ def PdfObject(obj, in_content_stream = false)
56
+ case(obj)
57
+ when NilClass then "null"
58
+ when TrueClass then "true"
59
+ when FalseClass then "false"
60
+ when Numeric then String(obj)
61
+ when Array
62
+ "[" << obj.map { |e| PdfObject(e, in_content_stream) }.join(' ') << "]"
63
+ when Prawn::Core::LiteralString
64
+ obj = obj.gsub(/[\\\n\r\t\b\f\(\)]/n) { |m| "\\#{m}" }
65
+ "(#{obj})"
66
+ when Time
67
+ obj = obj.strftime("D:%Y%m%d%H%M%S%z").chop.chop + "'00'"
68
+ obj = obj.gsub(/[\\\n\r\t\b\f\(\)]/n) { |m| "\\#{m}" }
69
+ "(#{obj})"
70
+ when Prawn::Core::ByteString
71
+ "<" << obj.unpack("H*").first << ">"
72
+ when String
73
+ obj = utf8_to_utf16(obj) unless in_content_stream
74
+ "<" << obj.unpack("H*").first << ">"
75
+ when Symbol
76
+ "/" + obj.to_s.unpack("C*").map { |n|
77
+ if n < 33 || n > 126 || [35,40,41,47,60,62].include?(n)
78
+ "#" + n.to_s(16).upcase
79
+ else
80
+ [n].pack("C*")
81
+ end
82
+ }.join
83
+ when Hash
84
+ output = "<< "
85
+ obj.each do |k,v|
86
+ unless String === k || Symbol === k
87
+ raise Prawn::Errors::FailedObjectConversion,
88
+ "A PDF Dictionary must be keyed by names"
89
+ end
90
+ output << PdfObject(k.to_sym, in_content_stream) << " " <<
91
+ PdfObject(v, in_content_stream) << "\n"
92
+ end
93
+ output << ">>"
94
+ when Prawn::Core::Reference
95
+ obj.to_s
96
+ when Prawn::Core::NameTree::Node
97
+ PdfObject(obj.to_hash)
98
+ when Prawn::Core::NameTree::Value
99
+ PdfObject(obj.name) + " " + PdfObject(obj.value)
100
+ when Prawn::OutlineRoot, Prawn::OutlineItem
101
+ PdfObject(obj.to_hash)
102
+ else
103
+ raise Prawn::Errors::FailedObjectConversion,
104
+ "This object cannot be serialized to PDF (#{obj.inspect})"
105
+ end
106
+ end
107
+ end
108
+ end