origami 1.2.5 → 1.2.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/bin/gui/config.rb +0 -4
  3. data/bin/gui/imgview.rb +2 -2
  4. data/bin/gui/menu.rb +11 -3
  5. data/bin/gui/treeview.rb +9 -3
  6. data/bin/pdfexplode +220 -0
  7. data/bin/pdfextract +3 -0
  8. data/lib/origami/acroform.rb +2 -2
  9. data/lib/origami/actions.rb +62 -35
  10. data/lib/origami/annotations.rb +3 -2
  11. data/lib/origami/array.rb +27 -4
  12. data/lib/origami/boolean.rb +2 -2
  13. data/lib/origami/catalog.rb +45 -45
  14. data/lib/origami/dictionary.rb +87 -14
  15. data/lib/origami/encryption.rb +46 -24
  16. data/lib/origami/file.rb +1 -2
  17. data/lib/origami/filters/ccitt.rb +118 -66
  18. data/lib/origami/filters/flate.rb +5 -1
  19. data/lib/origami/filters.rb +84 -2
  20. data/lib/origami/font.rb +71 -71
  21. data/lib/origami/graphics/patterns.rb +2 -1
  22. data/lib/origami/graphics/xobject.rb +123 -1
  23. data/lib/origami/javascript.rb +2 -1
  24. data/lib/origami/name.rb +2 -2
  25. data/lib/origami/null.rb +2 -2
  26. data/lib/origami/numeric.rb +11 -3
  27. data/lib/origami/object.rb +37 -16
  28. data/lib/origami/page.rb +135 -71
  29. data/lib/origami/parser.rb +11 -4
  30. data/lib/origami/parsers/pdf/linear.rb +1 -0
  31. data/lib/origami/parsers/pdf.rb +10 -0
  32. data/lib/origami/pdf.rb +10 -70
  33. data/lib/origami/reference.rb +4 -5
  34. data/lib/origami/signature.rb +22 -8
  35. data/lib/origami/stream.rb +41 -20
  36. data/lib/origami/string.rb +15 -6
  37. data/lib/origami/trailer.rb +9 -5
  38. data/lib/origami.rb +19 -0
  39. data/samples/actions/loop/loopgoto.rb +1 -1
  40. data/samples/actions/loop/loopnamed.rb +2 -2
  41. data/samples/actions/named/named.rb +1 -1
  42. data/samples/actions/samba/smbrelay.rb +1 -1
  43. data/samples/actions/triggerevents/trigger.rb +13 -13
  44. data/samples/actions/webbug/webbug-browser.rb +1 -1
  45. data/samples/actions/webbug/webbug-js.rb +1 -1
  46. data/samples/actions/webbug/webbug-reader.rb +1 -1
  47. data/samples/attachments/attach.rb +2 -2
  48. data/samples/exploits/cve-2008-2992-utilprintf.rb +1 -1
  49. data/samples/exploits/cve-2009-0927-geticon.rb +1 -1
  50. data/samples/exploits/exploit_customdictopen.rb +2 -2
  51. data/samples/exploits/getannots.rb +1 -1
  52. data/samples/javascript/js.rb +2 -2
  53. data/test/ts_pdf.rb +23 -23
  54. metadata +71 -86
@@ -441,6 +441,127 @@ module Origami
441
441
 
442
442
  end #class ContentStream
443
443
 
444
+ class Page < Dictionary
445
+
446
+ def render(engine) #:nodoc:
447
+ contents = self.Contents
448
+ contents = [ contents ] unless contents.is_a? Array
449
+
450
+ contents.each do |stream|
451
+ stream = stream.cast_to(ContentStream) unless stream.is_a? ContentStream
452
+
453
+ stream.render(engine)
454
+ end
455
+ end
456
+
457
+ # TODO :nodoc:
458
+ def draw_image
459
+ raise NotImplementedError
460
+ end
461
+
462
+ # See ContentStream#draw_line.
463
+ def draw_line(from, to, attr = {})
464
+ last_content_stream.draw_line(from, to, attr); self
465
+ end
466
+
467
+ # See ContentStream#draw_polygon.
468
+ def draw_polygon(coords = [], attr = {})
469
+ last_content_stream.draw_polygon(coords, attr); self
470
+ end
471
+
472
+ # See ContentStream#draw_rectangle.
473
+ def draw_rectangle(x, y, width, height, attr = {})
474
+ last_content_stream.draw_rectangle(x, y, width, height, attr); self
475
+ end
476
+
477
+ # See ContentStream#write.
478
+ def write(text, attr = {})
479
+ last_content_stream.write(text, attr); self
480
+ end
481
+
482
+ # TODO :nodoc:
483
+ def paint_shading(shade)
484
+ raise NotImplementedError
485
+ end
486
+
487
+ # TODO :nodoc:
488
+ def set_text_font(font, size)
489
+ raise NotImplementedError
490
+ end
491
+
492
+ # See ContentStream#set_text_pos.
493
+ def set_text_pos(tx, ty)
494
+ last_content_stream.set_text_pos(tx, ty); self
495
+ end
496
+
497
+ # See ContentStream#set_text_leading.
498
+ def set_text_leading(leading)
499
+ last_content_stream.set_text_leading(leading); self
500
+ end
501
+
502
+ # See ContentStream#set_text_rendering.
503
+ def set_text_rendering(rendering)
504
+ last_content_stream.set_text_rendering(rendering); self
505
+ end
506
+
507
+ # See ContentStream#set_text_rise.
508
+ def set_text_rise(rise)
509
+ last_content_stream.set_text_rise(rise); self
510
+ end
511
+
512
+ # See ContentStream#set_text_scale.
513
+ def set_text_scale(scaling)
514
+ last_content_stream.set_text_scale(scaling); self
515
+ end
516
+
517
+ # See ContentStream#set_text_word_spacing.
518
+ def set_text_word_spacing(word_spacing)
519
+ last_content_stream.set_text_word_spacing(word_spacing); self
520
+ end
521
+
522
+ # See ContentStream#set_text_char_spacing.
523
+ def set_text_char_spacing(char_spacing)
524
+ last_content_stream.set_text_char_spacing(char_spacing); self
525
+ end
526
+
527
+ # See ContentStream#set_fill_color.
528
+ def set_fill_color(color)
529
+ last_content_stream.set_fill_color(color); self
530
+ end
531
+
532
+ # See ContentStream#set_stroke_color.
533
+ def set_stroke_color(color)
534
+ last_content_stream.set_stroke_color(color); self
535
+ end
536
+
537
+ # See ContentStream#set_dash_pattern.
538
+ def set_dash_pattern(pattern)
539
+ last_content_stream.set_dash_pattern(pattern); self
540
+ end
541
+
542
+ # See ContentStream#set_line_width.
543
+ def set_line_width(width)
544
+ last_content_stream.set_line_width(width); self
545
+ end
546
+
547
+ # See ContentStream#set_line_cap.
548
+ def set_line_cap(cap)
549
+ last_content_stream.set_line_cap(cap); self
550
+ end
551
+
552
+ # See ContentStream#set_line_join.
553
+ def set_line_join(join)
554
+ last_content_stream.set_line_join(join); self
555
+ end
556
+
557
+ private
558
+
559
+ def last_content_stream #:nodoc:
560
+ contents = (self.Contents ||= ContentStream.new)
561
+ contents.is_a?(Array) ? contents.last : contents
562
+ end
563
+ end # class Page
564
+
444
565
  module Graphics
445
566
 
446
567
  module XObject
@@ -451,12 +572,13 @@ module Origami
451
572
 
452
573
  class FormXObject < ContentStream
453
574
  include XObject
575
+ include ResourcesHolder
454
576
 
455
577
  field :Subtype, :Type => Name, :Default => :Form, :Required => true
456
578
  field :FormType, :Type => Integer, :Default => 1
457
579
  field :BBox, :Type => Array, :Required => true
458
580
  field :Matrix, :Type => Array, :Default => [1, 0, 0, 1, 0, 0]
459
- field :Resources, :Type => Dictionary, :Version => "1.2"
581
+ field :Resources, :Type => Resources, :Version => "1.2"
460
582
  field :Group, :Type => Dictionary, :Version => "1.4"
461
583
  field :Ref, :Type => Dictionary, :Version => "1.4"
462
584
  field :Metadata, :Type => Stream, :Version => "1.4"
@@ -273,7 +273,8 @@ module Origami
273
273
  def modDate; @doc.mod_date.to_s end
274
274
  end
275
275
 
276
- def initialize(engine, pdf)
276
+ def initialize(*args)
277
+ engine, pdf = args # XXX: Bypass therubyracer bug #238. Temporary.
277
278
  super(engine)
278
279
 
279
280
  @pdf = pdf
data/lib/origami/name.rb CHANGED
@@ -107,7 +107,7 @@ module Origami
107
107
  super(TOKENS.first + Name.expand(@value))
108
108
  end
109
109
 
110
- def self.parse(stream) #:nodoc:
110
+ def self.parse(stream, parser = nil) #:nodoc:
111
111
 
112
112
  offset = stream.pos
113
113
 
@@ -163,7 +163,7 @@ module Origami
163
163
  end
164
164
  end
165
165
 
166
- def real_type ; Name end
166
+ def self.native_type ; Name end
167
167
 
168
168
  end
169
169
 
data/lib/origami/null.rb CHANGED
@@ -43,7 +43,7 @@ module Origami
43
43
  super
44
44
  end
45
45
 
46
- def self.parse(stream) #:nodoc:
46
+ def self.parse(stream, parser = nil) #:nodoc:
47
47
 
48
48
  offset = stream.pos
49
49
 
@@ -68,7 +68,7 @@ module Origami
68
68
  super(TOKENS.first)
69
69
  end
70
70
 
71
- def real_type ; Null end
71
+ def self.native_type ; Null end
72
72
 
73
73
  end
74
74
 
@@ -92,7 +92,15 @@ module Origami
92
92
  super(value.to_s)
93
93
  end
94
94
 
95
- def real_type ; Number end
95
+ module ClassMethods #:nodoc:all
96
+ def native_type; Number end
97
+ end
98
+
99
+ def self.included(receiver) #:nodoc:
100
+ receiver.extend(ClassMethods)
101
+ end
102
+
103
+ def self.native_type; Number end #:nodoc:
96
104
  end
97
105
 
98
106
  #
@@ -121,7 +129,7 @@ module Origami
121
129
  super(i)
122
130
  end
123
131
 
124
- def self.parse(stream) #:nodoc:
132
+ def self.parse(stream, parser = nil) #:nodoc:
125
133
 
126
134
  offset = stream.pos
127
135
 
@@ -169,7 +177,7 @@ module Origami
169
177
  super(f)
170
178
  end
171
179
 
172
- def self.parse(stream) #:nodoc:
180
+ def self.parse(stream, parser = nil) #:nodoc:
173
181
 
174
182
  offset = stream.pos
175
183
 
@@ -39,14 +39,6 @@ class Array #:nodoc:
39
39
  def to_o
40
40
  Origami::Array.new(self)
41
41
  end
42
-
43
- def shuffle
44
- sort_by { rand }
45
- end
46
-
47
- def shuffle!
48
- self.replace shuffle
49
- end
50
42
  end
51
43
 
52
44
  class Float #:nodoc:
@@ -110,7 +102,7 @@ module Origami
110
102
  #
111
103
  module StandardObject #:nodoc:
112
104
 
113
- DEFAULT_ATTRIBUTES = { :Type => Object, :Version => "1.1" } #:nodoc:
105
+ DEFAULT_ATTRIBUTES = { :Type => Object, :Version => "1.2" } #:nodoc:
114
106
 
115
107
  def self.included(receiver) #:nodoc:
116
108
  receiver.instance_variable_set(:@fields, Hash.new(DEFAULT_ATTRIBUTES))
@@ -126,8 +118,11 @@ module Origami
126
118
  def fields
127
119
  @fields
128
120
  end
129
-
121
+
130
122
  def field(name, attributes)
123
+ if attributes[:Required] == true and attributes.has_key?(:Default) and attributes[:Type] == Name
124
+ self.add_type_info(self, name, attributes[:Default])
125
+ end
131
126
 
132
127
  if not @fields.has_key?(name)
133
128
  @fields[name] = attributes
@@ -160,6 +155,11 @@ module Origami
160
155
  fields
161
156
  end
162
157
 
158
+ def hint_type(name)
159
+ if @fields.has_key?(name)
160
+ @fields[name][:Type]
161
+ end
162
+ end
163
163
  end
164
164
 
165
165
  def pre_build #:nodoc:
@@ -168,7 +168,7 @@ module Origami
168
168
  do_type_check if Origami::OPTIONS[:enable_type_checking] == true
169
169
 
170
170
  super
171
- end
171
+ end
172
172
 
173
173
  #
174
174
  # Check if an attribute is set in the current Object.
@@ -218,7 +218,7 @@ module Origami
218
218
 
219
219
  if not self[field].nil? and not attributes[:Type].nil?
220
220
  types = attributes[:Type].is_a?(::Array) ? attributes[:Type] : [ attributes[:Type] ]
221
- if not self[field].is_a?(Reference) and types.all? {|type| not self[field].is_a?(type)}
221
+ if not self[field].is_a?(Reference) and types.all? {|type| not self[field].is_a?(type.native_type)}
222
222
  puts "Warning: in object #{self.class}, field `#{field.to_s}' has unexpected type #{self[field].class}"
223
223
  end
224
224
  end
@@ -289,6 +289,7 @@ module Origami
289
289
  @no = @generation = 0
290
290
  @pdf = nil
291
291
  end
292
+
292
293
  @indirect = bool
293
294
  self
294
295
  end
@@ -329,6 +330,8 @@ module Origami
329
330
  def copy
330
331
  saved_pdf = @pdf
331
332
  saved_parent = @parent
333
+
334
+ saved_xref_cache = @xref_cache
332
335
  @pdf = @parent = nil # do not process parent object and document in the copy
333
336
 
334
337
  # Perform the recursive copy (quite dirty).
@@ -337,7 +340,8 @@ module Origami
337
340
  # restore saved values
338
341
  @pdf = saved_pdf
339
342
  @parent = saved_parent
340
- copyobj.set_pdf(saved_pdf)
343
+
344
+ copyobj.set_pdf(saved_pdf) if copyobj.is_indirect?
341
345
  copyobj.parent = parent
342
346
 
343
347
  copyobj
@@ -403,6 +407,7 @@ module Origami
403
407
  exported_obj.no = exported_obj.generation = 0
404
408
  exported_obj.set_pdf(nil) if exported_obj.is_indirect?
405
409
  exported_obj.parent = nil
410
+ exported_obj.xref_cache.clear
406
411
 
407
412
  exported_obj
408
413
  end
@@ -539,7 +544,7 @@ module Origami
539
544
  nil
540
545
  end
541
546
 
542
- def parse(stream) #:nodoc:
547
+ def parse(stream, parser = nil) #:nodoc:
543
548
  offset = stream.pos
544
549
 
545
550
  #
@@ -562,7 +567,7 @@ module Origami
562
567
  end
563
568
 
564
569
  begin
565
- newObj = type.parse(stream)
570
+ newObj = type.parse(stream, parser)
566
571
  rescue Exception => e
567
572
  raise InvalidObjectError,
568
573
  "Failed to parse object (no:#{no},gen:#{gen})\n\t -> [#{e.class}] #{e.message}"
@@ -602,7 +607,23 @@ module Origami
602
607
  def type
603
608
  self.class.to_s.split("::").last.to_sym
604
609
  end
605
- alias real_type type
610
+
611
+ def self.native_type; Origami::Object end #:nodoc:
612
+
613
+ #
614
+ # Returns the native PDF type of this Object.
615
+ #
616
+ def native_type
617
+ self.class.native_type
618
+ end
619
+
620
+ def cast_to(type) #:nodoc:
621
+ if type.native_type != self.native_type
622
+ raise TypeError, "Incompatible cast from #{self.class} to #{type}"
623
+ end
624
+
625
+ self
626
+ end
606
627
 
607
628
  #
608
629
  # Outputs this object into PDF code.
data/lib/origami/page.rb CHANGED
@@ -27,6 +27,9 @@ module Origami
27
27
 
28
28
  class PDF
29
29
 
30
+ #
31
+ # Appends a page or list of pages to the end of the page tree.
32
+ #
30
33
  def append_page(page = Page.new, *more)
31
34
  raise InvalidPDFError, "Invalid page tree" if not self.Catalog or not self.Catalog.Pages or not self.Catalog.Pages.is_a?(PageTreeNode)
32
35
 
@@ -52,6 +55,9 @@ module Origami
52
55
  self
53
56
  end
54
57
 
58
+ #
59
+ # Inserts a page at position _index_ into the document.
60
+ #
55
61
  def insert_page(index, page)
56
62
  raise InvalidPDFError, "Invalid page tree" if not self.Catalog or not self.Catalog.Pages or not self.Catalog.Pages.is_a?(PageTreeNode)
57
63
 
@@ -108,69 +114,105 @@ module Origami
108
114
 
109
115
  module ResourcesHolder
110
116
 
111
- def add_extgstate(name, extgstate)
112
- target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new)
113
-
114
- target.ExtGState ||= {}
115
- target.ExtGState[name] = extgstate
116
-
117
- self
117
+ def add_extgstate(extgstate, name = nil)
118
+ add_resource(Resources::EXTGSTATE, extgstate, name)
118
119
  end
119
120
 
120
- def add_colorspace(name, colorspace)
121
- target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new)
122
-
123
- csdir = target[:ColorSpace] ||= {}
124
- (csdir.is_a?(Reference) ? csdir.solve : csdir)[name] = colorspace
121
+ def add_colorspace(colorspace, name = nil)
122
+ add_resource(Resources::COLORSPACE, colorspace, name)
123
+ end
125
124
 
126
- self
125
+ def add_pattern(pattern, name = nil)
126
+ add_resource(Resources::PATTERN, pattern, name)
127
127
  end
128
128
 
129
- def add_pattern(name, pattern)
130
- target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new)
129
+ def add_shading(shading, name = nil)
130
+ add_resource(Resources::SHADING, shading, name)
131
+ end
131
132
 
132
- target.Pattern ||= {}
133
- target.Pattern[name] = pattern
134
-
135
- self
133
+ def add_xobject(xobject, name = nil)
134
+ add_resource(Resources::XOBJECT, xobject, name)
136
135
  end
137
136
 
138
- def add_shading(name, shading)
139
- target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new)
137
+ def add_font(font, name = nil)
138
+ add_resource(Resources::FONT, font, name)
139
+ end
140
140
 
141
- target.Shading ||= {}
142
- target.Shading[name] = shading
143
-
144
- self
141
+ def add_properties(properties, name = nil)
142
+ add_resource(Resources::PROPERTIES, properties, name)
145
143
  end
146
144
 
147
- def add_xobject(name, xobject)
148
- target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new)
145
+ def add_resource(type, rsrc, name = nil)
146
+ return existing if not name and existing = ls_resources(type).key(rsrc)
149
147
 
150
- target.XObject ||= {}
151
- target.XObject[name] = xobject
152
-
153
- self
154
- end
155
-
156
- def add_font(name, font)
148
+ name = new_id(type) unless name
157
149
  target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new)
158
150
 
159
- target.Font ||= {}
160
- target.Font[name] = font
161
-
162
- self
151
+ rsrc_dict = target.send(type) || (target[type] = Dictionary.new)
152
+ rsrc_dict[name] = rsrc
153
+
154
+ name
163
155
  end
164
156
 
165
- def add_properties(name, properties)
157
+ def ls_resources(type)
166
158
  target = self.is_a?(Resources) ? self : (self.Resources ||= Resources.new)
159
+
160
+ rsrc = {}
161
+ (target.send(type) || {}).each_pair do |name, obj|
162
+ rsrc[name.value] = obj.solve
163
+ end
167
164
 
168
- target.Properties ||= {}
169
- target.Properties[name] = properties
170
-
171
- self
165
+ rsrc
166
+ end
167
+
168
+ def extgstates; ls_resources(Resources::EXTGSTATE) end
169
+ def colorspaces; ls_resources(Resources::COLORSPACE) end
170
+ def patterns; ls_resources(Resources::PATTERN) end
171
+ def shadings; ls_resources(Resources::SHADING) end
172
+ def xobjects; ls_resources(Resources::XOBJECT) end
173
+ def fonts; ls_resources(Resources::FONT) end
174
+ def properties; ls_resources(Resources::PROPERTIES) end
175
+ def resources;
176
+ self.extgstates.
177
+ merge self.colorspaces.
178
+ merge self.patterns.
179
+ merge self.shadings.
180
+ merge self.xobjects.
181
+ merge self.fonts.
182
+ merge self.properties
183
+ end
184
+
185
+ private
186
+
187
+ def new_id(type, prefix = nil) #:nodoc:
188
+ prefix ||=
189
+ {
190
+ Resources::EXTGSTATE => 'ExtG',
191
+ Resources::COLORSPACE => 'CS',
192
+ Resources::PATTERN => 'P',
193
+ Resources::SHADING => 'Sh',
194
+ Resources::XOBJECT => 'Im',
195
+ Resources::FONT => 'F',
196
+ Resources::PROPERTIES => 'Pr'
197
+ }[type]
198
+
199
+ rsrc = ls_resources(type)
200
+ n = '1'
201
+
202
+ while rsrc.include? (prefix + n).to_sym
203
+ n.next!
204
+ end
205
+
206
+ (prefix + n).to_sym
172
207
  end
173
-
208
+
209
+ def new_extgstate_id; new_id(Resources::EXTGSTATE) end
210
+ def new_colorspace_id; new_id(Resources::COLORSPACE) end
211
+ def new_pattern_id; new_id(Resources::PATTERN) end
212
+ def new_shading_id; new_id(Resources::SHADING) end
213
+ def new_xobject_id; new_id(Resources::XOBJECT) end
214
+ def new_font_id; new_name(Resources::FONT) end
215
+ def new_properties_id; new_name(Resources::PROPERTIES) end
174
216
  end
175
217
 
176
218
  #
@@ -181,22 +223,25 @@ module Origami
181
223
  include StandardObject
182
224
  include ResourcesHolder
183
225
 
184
- field :ExtGState, :Type => Dictionary
185
- field :ColorSpace, :Type => Dictionary
186
- field :Pattern, :Type => Dictionary
187
- field :Shading, :Type => Dictionary, :Version => "1.3"
188
- field :XObject, :Type => Dictionary
189
- field :Font, :Type => Dictionary
226
+ EXTGSTATE = :ExtGState
227
+ COLORSPACE = :ColorSpace
228
+ PATTERN = :Pattern
229
+ SHADING = :Shading
230
+ XOBJECT = :XObject
231
+ FONT = :Font
232
+ PROPERTIES = :Properties
233
+
234
+ field EXTGSTATE, :Type => Dictionary
235
+ field COLORSPACE, :Type => Dictionary
236
+ field PATTERN, :Type => Dictionary
237
+ field SHADING, :Type => Dictionary, :Version => "1.3"
238
+ field XOBJECT, :Type => Dictionary
239
+ field FONT, :Type => Dictionary
190
240
  field :ProcSet, :Type => Array
191
- field :Properties, :Type => Dictionary, :Version => "1.2"
241
+ field PROPERTIES, :Type => Dictionary, :Version => "1.2"
192
242
 
193
243
  def pre_build
194
- unless self.Font
195
- fnt = Font::Type1::Standard::Helvetica.new.pre_build
196
- fnt.Name = :F1
197
-
198
- add_font(fnt.Name, fnt)
199
- end
244
+ add_font(Font::Type1::Standard::Helvetica.new.pre_build) unless self.Font
200
245
 
201
246
  super
202
247
  end
@@ -347,6 +392,9 @@ module Origami
347
392
  end
348
393
  end
349
394
  end
395
+
396
+ # Forward declaration.
397
+ class ContentStream < Stream; end
350
398
 
351
399
  #
352
400
  # Class representing a Page in the PDF document.
@@ -355,18 +403,44 @@ module Origami
355
403
 
356
404
  include StandardObject
357
405
  include ResourcesHolder
406
+
407
+ module Format
408
+ A0 = Rectangle[:width => 2384, :height => 3370]
409
+ A1 = Rectangle[:width => 1684, :height => 2384]
410
+ A2 = Rectangle[:width => 1191, :height => 1684]
411
+ A3 = Rectangle[:width => 842, :height => 1191]
412
+ A4 = Rectangle[:width => 595, :height => 842]
413
+ A5 = Rectangle[:width => 420, :height => 595]
414
+ A6 = Rectangle[:width => 298, :height => 420]
415
+ A7 = Rectangle[:width => 210, :height => 298]
416
+ A8 = Rectangle[:width => 147, :height => 210]
417
+ A9 = Rectangle[:width => 105, :height => 147]
418
+ A10 = Rectangle[:width => 74, :height => 105]
419
+
420
+ B0 = Rectangle[:width => 2836, :height => 4008]
421
+ B1 = Rectangle[:width => 2004, :height => 2835]
422
+ B2 = Rectangle[:width => 1417, :height => 2004]
423
+ B3 = Rectangle[:width => 1001, :height => 1417]
424
+ B4 = Rectangle[:width => 709, :height => 1001]
425
+ B5 = Rectangle[:width => 499, :height => 709]
426
+ B6 = Rectangle[:width => 354, :height => 499]
427
+ B7 = Rectangle[:width => 249, :height => 354]
428
+ B8 = Rectangle[:width => 176, :height => 249]
429
+ B9 = Rectangle[:width => 125, :height => 176]
430
+ B10 = Rectangle[:width => 88, :height => 125]
431
+ end
358
432
 
359
433
  field :Type, :Type => Name, :Default => :Page, :Required => true
360
434
  field :Parent, :Type => Dictionary, :Required => true
361
435
  field :LastModified, :Type => String, :Version => "1.3"
362
- field :Resources, :Type => Dictionary, :Required => true
363
- field :MediaBox, :Type => Array, :Default => Rectangle[ :llx => 0, :lly => 0, :urx => 795, :ury => 842 ], :Required => true
436
+ field :Resources, :Type => Resources, :Required => true
437
+ field :MediaBox, :Type => Array, :Default => Format::A4, :Required => true
364
438
  field :CropBox, :Type => Array
365
439
  field :BleedBox, :Type => Array, :Version => "1.3"
366
440
  field :TrimBox, :Type => Array, :Version => "1.3"
367
441
  field :ArtBox, :Type => Array, :Version => "1.3"
368
442
  field :BoxColorInfo, :Type => Dictionary, :Version => "1.4"
369
- field :Contents, :Type => [ Stream, Array ]
443
+ field :Contents, :Type => [ ContentStream, Array ]
370
444
  field :Rotate, :Type => Integer, :Default => 0
371
445
  field :Group, :Type => Dictionary, :Version => "1.4"
372
446
  field :Thumb, :Type => Stream
@@ -393,17 +467,6 @@ module Origami
393
467
  set_indirect(true)
394
468
  end
395
469
 
396
- def render(engine) #:nodoc:
397
- contents = self.Contents
398
- return unless contents.is_a? Stream
399
-
400
- unless contents.is_a? ContentStream
401
- contents = ContentStream.new(contents.data)
402
- end
403
-
404
- contents.render(engine)
405
- end
406
-
407
470
  def pre_build
408
471
  self.Resources = Resources.new.pre_build unless self.has_key?(:Resources)
409
472
 
@@ -594,3 +657,4 @@ module Origami
594
657
  end
595
658
 
596
659
  end
660
+
@@ -134,6 +134,9 @@ module Origami
134
134
  attr_accessor :options
135
135
 
136
136
  def initialize(options = {}) #:nodoc:
137
+
138
+ # Type information for indirect objects.
139
+ @deferred_casts = {}
137
140
 
138
141
  #Default options values
139
142
  @options =
@@ -178,12 +181,12 @@ module Origami
178
181
  @data.pos = pos
179
182
 
180
183
  begin
181
- obj = Object.parse(@data)
184
+ obj = Object.parse(@data, self)
182
185
  return if obj.nil?
183
186
 
184
187
  trace "Read #{obj.type} object#{
185
- if obj.type != obj.real_type
186
- " (" + obj.real_type.to_s.split('::').last + ")"
188
+ if obj.class != obj.native_type
189
+ " (" + obj.native_type.to_s.split('::').last + ")"
187
190
  end
188
191
  }, #{obj.reference}"
189
192
 
@@ -237,7 +240,7 @@ module Origami
237
240
 
238
241
  begin
239
242
  info "...Parsing trailer..."
240
- trailer = Trailer.parse(@data)
243
+ trailer = Trailer.parse(@data, self)
241
244
 
242
245
  @options[:callback].call(trailer)
243
246
  trailer
@@ -252,6 +255,10 @@ module Origami
252
255
  end
253
256
  end
254
257
 
258
+ def defer_type_cast(reference, type) #:nodoc:
259
+ @deferred_casts[reference] = type
260
+ end
261
+
255
262
  def target_filename
256
263
  @filename
257
264
  end