origami 1.2.5 → 1.2.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/gui/config.rb +0 -4
- data/bin/gui/imgview.rb +2 -2
- data/bin/gui/menu.rb +11 -3
- data/bin/gui/treeview.rb +9 -3
- data/bin/pdfexplode +220 -0
- data/bin/pdfextract +3 -0
- data/lib/origami/acroform.rb +2 -2
- data/lib/origami/actions.rb +62 -35
- data/lib/origami/annotations.rb +3 -2
- data/lib/origami/array.rb +27 -4
- data/lib/origami/boolean.rb +2 -2
- data/lib/origami/catalog.rb +45 -45
- data/lib/origami/dictionary.rb +87 -14
- data/lib/origami/encryption.rb +46 -24
- data/lib/origami/file.rb +1 -2
- data/lib/origami/filters/ccitt.rb +118 -66
- data/lib/origami/filters/flate.rb +5 -1
- data/lib/origami/filters.rb +84 -2
- data/lib/origami/font.rb +71 -71
- data/lib/origami/graphics/patterns.rb +2 -1
- data/lib/origami/graphics/xobject.rb +123 -1
- data/lib/origami/javascript.rb +2 -1
- data/lib/origami/name.rb +2 -2
- data/lib/origami/null.rb +2 -2
- data/lib/origami/numeric.rb +11 -3
- data/lib/origami/object.rb +37 -16
- data/lib/origami/page.rb +135 -71
- data/lib/origami/parser.rb +11 -4
- data/lib/origami/parsers/pdf/linear.rb +1 -0
- data/lib/origami/parsers/pdf.rb +10 -0
- data/lib/origami/pdf.rb +10 -70
- data/lib/origami/reference.rb +4 -5
- data/lib/origami/signature.rb +22 -8
- data/lib/origami/stream.rb +41 -20
- data/lib/origami/string.rb +15 -6
- data/lib/origami/trailer.rb +9 -5
- data/lib/origami.rb +19 -0
- data/samples/actions/loop/loopgoto.rb +1 -1
- data/samples/actions/loop/loopnamed.rb +2 -2
- data/samples/actions/named/named.rb +1 -1
- data/samples/actions/samba/smbrelay.rb +1 -1
- data/samples/actions/triggerevents/trigger.rb +13 -13
- data/samples/actions/webbug/webbug-browser.rb +1 -1
- data/samples/actions/webbug/webbug-js.rb +1 -1
- data/samples/actions/webbug/webbug-reader.rb +1 -1
- data/samples/attachments/attach.rb +2 -2
- data/samples/exploits/cve-2008-2992-utilprintf.rb +1 -1
- data/samples/exploits/cve-2009-0927-geticon.rb +1 -1
- data/samples/exploits/exploit_customdictopen.rb +2 -2
- data/samples/exploits/getannots.rb +1 -1
- data/samples/javascript/js.rb +2 -2
- data/test/ts_pdf.rb +23 -23
- 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 =>
|
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"
|
data/lib/origami/javascript.rb
CHANGED
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
|
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
|
71
|
+
def self.native_type ; Null end
|
72
72
|
|
73
73
|
end
|
74
74
|
|
data/lib/origami/numeric.rb
CHANGED
@@ -92,7 +92,15 @@ module Origami
|
|
92
92
|
super(value.to_s)
|
93
93
|
end
|
94
94
|
|
95
|
-
|
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
|
|
data/lib/origami/object.rb
CHANGED
@@ -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.
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
112
|
-
|
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(
|
121
|
-
|
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
|
-
|
125
|
+
def add_pattern(pattern, name = nil)
|
126
|
+
add_resource(Resources::PATTERN, pattern, name)
|
127
127
|
end
|
128
128
|
|
129
|
-
def
|
130
|
-
|
129
|
+
def add_shading(shading, name = nil)
|
130
|
+
add_resource(Resources::SHADING, shading, name)
|
131
|
+
end
|
131
132
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
self
|
133
|
+
def add_xobject(xobject, name = nil)
|
134
|
+
add_resource(Resources::XOBJECT, xobject, name)
|
136
135
|
end
|
137
136
|
|
138
|
-
def
|
139
|
-
|
137
|
+
def add_font(font, name = nil)
|
138
|
+
add_resource(Resources::FONT, font, name)
|
139
|
+
end
|
140
140
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
self
|
141
|
+
def add_properties(properties, name = nil)
|
142
|
+
add_resource(Resources::PROPERTIES, properties, name)
|
145
143
|
end
|
146
144
|
|
147
|
-
def
|
148
|
-
|
145
|
+
def add_resource(type, rsrc, name = nil)
|
146
|
+
return existing if not name and existing = ls_resources(type).key(rsrc)
|
149
147
|
|
150
|
-
|
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.
|
160
|
-
|
161
|
-
|
162
|
-
|
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
|
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
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
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
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
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
|
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 =>
|
363
|
-
field :MediaBox, :Type => Array, :Default =>
|
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 => [
|
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
|
+
|
data/lib/origami/parser.rb
CHANGED
@@ -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.
|
186
|
-
" (" + obj.
|
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
|