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
@@ -300,13 +300,14 @@ module Origami
300
300
  # Encodes data using CCITT-facsimile compression method.
301
301
  #
302
302
  def encode(stream)
303
-
304
- if @params.has_key?(:K) and @params.K != 0
303
+ mode = @params.has_key?(:K) ? @params.K.value : 0
304
+
305
+ unless mode.is_a?(::Integer) and mode <= 0
305
306
  raise NotImplementedError, "CCITT encoding scheme not supported"
306
307
  end
307
308
 
308
309
  columns = @params.has_key?(:Columns) ? @params.Columns.value : (stream.size << 3)
309
- unless columns.is_a?(::Integer) and columns > 0 and columns % 8 == 0
310
+ unless columns.is_a?(::Integer) and columns > 0 #and columns % 8 == 0
310
311
  raise CCITTFaxFilterError, "Invalid value for parameter `Columns'"
311
312
  end
312
313
 
@@ -314,42 +315,24 @@ module Origami
314
315
  raise CCITTFaxFilterError, "Data size is not a multiple of image width"
315
316
  end
316
317
 
317
- white, black = (@params.BlackIs1 == true) ? [0,1] : [1,0]
318
-
318
+ colors = (@params.BlackIs1 == true) ? [0,1] : [1,0]
319
+ white, _black = colors
319
320
  bitr = Utils::BitReader.new(stream)
320
321
  bitw = Utils::BitWriter.new
321
322
 
322
- until bitr.eod?
323
-
324
- bitw.write(*EOL)
325
- scan_len = 0
326
- current_color = white
327
-
328
- # Process each bit in line.
329
- begin
330
- if bitr.read(1) == current_color
331
- scan_len += 1
332
- else
333
- if current_color == white
334
- put_white_bits(bitw, scan_len)
335
- else
336
- put_black_bits(bitw, scan_len)
337
- end
338
-
339
- current_color ^= 1
340
- scan_len = 1
341
- end
342
- end while bitr.pos % columns != 0
343
-
344
- if current_color == white
345
- put_white_bits(bitw, scan_len)
346
- else
347
- put_black_bits(bitw, scan_len)
348
- end
323
+ # Group 4 requires an imaginary white line
324
+ if mode < 0
325
+ prev_line = Utils::BitWriter.new
326
+ write_bit_range(prev_line, white, columns)
327
+ prev_line = Utils::BitReader.new(prev_line.final.to_s)
328
+ end
349
329
 
350
- # Align encoded lign on a 8-bit boundary.
351
- if @params.EncodedByteAlign == true and bitw.pos % 8 != 0
352
- bitw.write(0, 8 - (bitw.pos % 8))
330
+ until bitr.eod?
331
+ case
332
+ when mode == 0
333
+ encode_one_dimensional_line(bitr, bitw, columns, colors)
334
+ when mode < 0
335
+ encode_two_dimensional_line(bitr, bitw, columns, colors, prev_line)
353
336
  end
354
337
  end
355
338
 
@@ -363,21 +346,27 @@ module Origami
363
346
  # Decodes data using CCITT-facsimile compression method.
364
347
  #
365
348
  def decode(stream)
366
- if @params.has_key?(:K) and @params.K != 0
349
+ mode = @params.has_key?(:K) ? @params.K.value : 0
350
+
351
+ unless mode.is_a?(::Integer) and mode <= 0
367
352
  raise NotImplementedError, "CCITT encoding scheme not supported"
368
353
  end
369
354
 
370
355
  columns = @params.has_key?(:Columns) ? @params.Columns.value : 1728
371
- unless columns.is_a?(::Integer) and columns > 0 and columns % 8 == 0
356
+ unless columns.is_a?(::Integer) and columns > 0 #and columns % 8 == 0
372
357
  raise CCITTFaxFilterError, "Invalid value for parameter `Columns'"
373
358
  end
374
359
 
375
- white, black = (@params.BlackIs1 == true) ? [0,1] : [1,0]
376
- aligned = @params.EncodedByteAlign == true
377
- has_eob = @params.EndOfBlock.nil? or @params.EndOfBlock == true
378
- has_eol = @params.EndOfLine == true
360
+ colors = (@params.BlackIs1 == true) ? [0,1] : [1,0]
361
+ white, _black = colors
362
+ params =
363
+ {
364
+ :is_aligned? => (@params.EncodedByteAlign == true),
365
+ :has_eob? => (@params.EndOfBlock.nil? or @params.EndOfBlock == true),
366
+ :has_eol? => (@params.EndOfLine == true)
367
+ }
379
368
 
380
- unless has_eob
369
+ unless params[:has_eob?]
381
370
  unless @params.has_key?(:Rows) and @params.Rows.is_a?(::Integer) and @params.Rows.value > 0
382
371
  raise CCITTFaxFilterError, "Invalid value for parameter `Rows'"
383
372
  end
@@ -388,16 +377,21 @@ module Origami
388
377
  bitr = Utils::BitReader.new(stream)
389
378
  bitw = Utils::BitWriter.new
390
379
 
380
+ # Group 4 requires an imaginary white line
381
+ if mode < 0
382
+ prev_line = Utils::BitWriter.new
383
+ write_bit_range(prev_line, white, columns)
384
+ prev_line = Utils::BitReader.new(prev_line.final.to_s)
385
+ end
386
+
391
387
  until bitr.eod? or rows == 0
392
- current_color = white
393
-
394
388
  # realign the read line on a 8-bit boundary if required
395
- if aligned and bitr.pos % 8 != 0
389
+ if params[:is_aligned?] and bitr.pos % 8 != 0
396
390
  bitr.pos += 8 - (bitr.pos % 8)
397
391
  end
398
392
 
399
393
  # received return-to-control code
400
- if has_eob and bitr.peek(RTC[1]) == RTC[0]
394
+ if params[:has_eob?] and bitr.peek(RTC[1]) == RTC[0]
401
395
  bitr.pos += RTC[1]
402
396
  break
403
397
  end
@@ -407,41 +401,99 @@ module Origami
407
401
  raise InvalidCCITTFaxDataError.new(
408
402
  "No end-of-line pattern found (at bit pos #{bitr.pos}/#{bitr.size}})",
409
403
  bitw.final.to_s
410
- )if has_eol
404
+ ) if params[:has_eol?]
411
405
  else
412
406
  bitr.pos += EOL[1]
413
407
  end
414
408
 
415
- line_length = 0
416
- while line_length < columns
409
+ case
410
+ when mode == 0
411
+ decode_one_dimensional_line(bitr, bitw, columns, colors)
412
+ when mode < 0
413
+ decode_two_dimensional_line(bitr, bitw, columns, colors, prev_line)
414
+ end
415
+
416
+
417
+ rows -= 1 unless params[:has_eob?]
418
+ end
419
+
420
+ bitw.final.to_s
421
+ end
422
+
423
+ private
424
+
425
+ def encode_one_dimensional_line(input, output, columns, colors) #:nodoc:
426
+ output.write(*EOL)
427
+ scan_len = 0
428
+ white, black = colors
429
+ current_color = white
430
+
431
+ # Process each bit in line.
432
+ begin
433
+ if input.read(1) == current_color
434
+ scan_len += 1
435
+ else
417
436
  if current_color == white
418
- bit_length = get_white_bits(bitr)
437
+ put_white_bits(output, scan_len)
419
438
  else
420
- bit_length = get_black_bits(bitr)
439
+ put_black_bits(output, scan_len)
421
440
  end
422
441
 
423
- raise InvalidCCITTFaxDataError.new(
424
- "Unfinished line (at bit pos #{bitr.pos}/#{bitr.size}})",
425
- bitw.final.to_s
426
- ) if bit_length.nil?
427
-
428
- line_length += bit_length
429
- raise InvalidCCITTFaxDataError.new(
430
- "Line is too long (at bit pos #{bitr.pos}/#{bitr.size}})",
431
- bitw.final.to_s
432
- ) if line_length > columns
433
-
434
- write_bit_range(bitw, current_color, bit_length)
435
442
  current_color ^= 1
443
+ scan_len = 1
436
444
  end
445
+ end while input.pos % columns != 0
437
446
 
438
- rows -= 1 unless has_eob
447
+ if current_color == white
448
+ put_white_bits(output, scan_len)
449
+ else
450
+ put_black_bits(output, scan_len)
439
451
  end
440
452
 
441
- bitw.final.to_s
453
+ # Align encoded lign on a 8-bit boundary.
454
+ if @params.EncodedByteAlign == true and output.pos % 8 != 0
455
+ output.write(0, 8 - (output.pos % 8))
456
+ end
442
457
  end
443
458
 
444
- private
459
+ def encode_two_dimensional_line(input, output, columns, colors, prev_line) #:nodoc:
460
+ raise NotImplementedError, "CCITT two-dimensional encoding scheme not supported."
461
+
462
+ white, black = colors
463
+ current_color = white
464
+ end
465
+
466
+ def decode_one_dimensional_line(input, output, columns, colors) #:nodoc:
467
+ white, black = colors
468
+ current_color = white
469
+
470
+ line_length = 0
471
+ while line_length < columns
472
+ if current_color == white
473
+ bit_length = get_white_bits(input)
474
+ else
475
+ bit_length = get_black_bits(input)
476
+ end
477
+
478
+ raise InvalidCCITTFaxDataError.new(
479
+ "Unfinished line (at bit pos #{input.pos}/#{input.size}})",
480
+ output.final.to_s
481
+ ) if bit_length.nil?
482
+
483
+ line_length += bit_length
484
+ raise InvalidCCITTFaxDataError.new(
485
+ "Line is too long (at bit pos #{input.pos}/#{input.size}})",
486
+ output.final.to_s
487
+ ) if line_length > columns
488
+
489
+ write_bit_range(output, current_color, bit_length)
490
+ current_color ^= 1
491
+ end
492
+ end
493
+
494
+ def decode_two_dimensional_line(input, output, columns, colors, prev_line) #:nodoc:
495
+ raise NotImplementedError, "CCITT two-dimensional decoding scheme not supported."
496
+ end
445
497
 
446
498
  def get_white_bits(bitr) #:nodoc:
447
499
  get_color_bits(bitr, WHITE_CONFIGURATION_DECODE_TABLE, WHITE_TERMINAL_DECODE_TABLE)
@@ -83,7 +83,11 @@ module Origami
83
83
  begin
84
84
  uncompressed = zlib_stream.inflate(stream)
85
85
  rescue Zlib::DataError => zlib_except
86
- raise InvalidFlateDataError.new(zlib_except.message, zlib_stream.flush_next_out)
86
+ uncompressed = zlib_stream.flush_next_out
87
+
88
+ unless Origami::OPTIONS[:ignore_zlib_errors]
89
+ raise InvalidFlateDataError.new(zlib_except.message, uncompressed)
90
+ end
87
91
  end
88
92
 
89
93
  if @params.Predictor.is_a?(Integer)
@@ -71,7 +71,7 @@ module Origami
71
71
  while length > 0
72
72
  if length >= 8 - @ptr_bit
73
73
  length -= 8 - @ptr_bit
74
- @last_byte = 0 unless @last_byte
74
+ @last_byte ||= 0
75
75
  @last_byte |= (data >> length) & ((1 << (8 - @ptr_bit)) - 1)
76
76
 
77
77
  data &= (1 << length) - 1
@@ -79,7 +79,7 @@ module Origami
79
79
  @last_byte = nil
80
80
  @ptr_bit = 0
81
81
  else
82
- @last_byte = 0 unless @last_byte
82
+ @last_byte ||= 0
83
83
  @last_byte |= (data & ((1 << length) - 1)) << (8 - @ptr_bit - length)
84
84
  @ptr_bit += length
85
85
 
@@ -130,6 +130,11 @@ module Origami
130
130
  # Internally used by some filters.
131
131
  #
132
132
  class BitReader
133
+ BRUIJIN_TABLE = ::Array.new(32)
134
+ BRUIJIN_TABLE.size.times { |i|
135
+ BRUIJIN_TABLE[((0x77cb531 * (1 << i)) >> 27) & 31] = i
136
+ }
137
+
133
138
  def initialize(data)
134
139
  @data = data
135
140
  reset
@@ -215,6 +220,83 @@ module Origami
215
220
  n
216
221
  end
217
222
 
223
+ #
224
+ # Used for bit scanning.
225
+ # Counts leading zeros. Does not advance read pointer.
226
+ #
227
+ def clz
228
+ count = 0
229
+ if @ptr_bit != 0
230
+ bits = peek(8 - @ptr_bit)
231
+ count = clz32(bits << (32 - (8 - @ptr_bit)))
232
+
233
+ return count if count < (8 - @ptr_bit)
234
+ end
235
+
236
+ delta = 0
237
+ while @data.size > @ptr_byte + delta * 4
238
+ word = @data[@ptr_byte + delta * 4, 4] # next 32 bits
239
+ z = clz32((word << (4 - word.size)).unpack("N")[0])
240
+
241
+ count += z
242
+ delta += 1
243
+
244
+ return count if z < 32 - ((4 - word.size) << 3)
245
+ end
246
+
247
+ count
248
+ end
249
+
250
+ #
251
+ # Used for bit scanning.
252
+ # Count leading ones. Does not advance read pointer.
253
+ #
254
+ def clo
255
+ count = 0
256
+ if @ptr_bit != 0
257
+ bits = peek(8 - @ptr_bit)
258
+ count = clz32(~(bits << (32 - (8 - @ptr_bit))) & 0xff)
259
+
260
+ return count if count < (8 - @ptr_bit)
261
+ end
262
+
263
+ delta = 0
264
+ while @data.size > @ptr_byte + delta * 4
265
+ word = @data[@ptr_byte + delta * 4, 4] # next 32 bits
266
+ z = clz32(~((word << (4 - word.size)).unpack("N")[0]) & 0xffff_ffff)
267
+
268
+ count += z
269
+ delta += 1
270
+
271
+ return count if z < 32 - ((4 - word.size) << 3)
272
+ end
273
+
274
+ count
275
+ end
276
+
277
+ private
278
+
279
+ def bitswap8(i) #:nodoc
280
+ ((i * 0x0202020202) & 0x010884422010) % 1023
281
+ end
282
+
283
+ def bitswap32(i) #:nodoc:
284
+ (bitswap8((i >> 0) & 0xff) << 24) |
285
+ (bitswap8((i >> 8) & 0xff) << 16) |
286
+ (bitswap8((i >> 16) & 0xff) << 8) |
287
+ (bitswap8((i >> 24) & 0xff) << 0)
288
+ end
289
+
290
+ def ctz32(i) #:nodoc:
291
+ if i == 0 then 32
292
+ else
293
+ BRUIJIN_TABLE[(((i & -i) * 0x77cb531) >> 27) & 31]
294
+ end
295
+ end
296
+
297
+ def clz32(i) #:nodoc:
298
+ ctz32 bitswap32 i
299
+ end
218
300
  end
219
301
  end
220
302
 
data/lib/origami/font.rb CHANGED
@@ -25,6 +25,73 @@
25
25
 
26
26
  module Origami
27
27
 
28
+ #
29
+ # Embedded font stream.
30
+ #
31
+ class FontStream < Stream
32
+
33
+ field :Subtype, :Type => Name
34
+ field :Length1, :Type => Integer
35
+ field :Length2, :Type => Integer
36
+ field :Length3, :Type => Integer
37
+
38
+ end
39
+
40
+ #
41
+ # Class representing a font details in a document.
42
+ #
43
+ class FontDescriptor < Dictionary
44
+
45
+ include StandardObject
46
+
47
+ FIXEDPITCH = 1 << 1
48
+ SERIF = 1 << 2
49
+ SYMBOLIC = 1 << 3
50
+ SCRIPT = 1 << 4
51
+ NONSYMBOLIC = 1 << 6
52
+ ITALIC = 1 << 7
53
+ ALLCAP = 1 << 17
54
+ SMALLCAP = 1 << 18
55
+ FORCEBOLD = 1 << 19
56
+
57
+ field :Type, :Type => Name, :Default => :FontDescriptor, :Required => true
58
+ field :FontName, :Type => Name, :Required => true
59
+ field :FontFamily, :Type => ByteString, :Version => "1.5"
60
+ field :FontStretch, :Type => Name, :Default => :Normal, :Version => "1.5"
61
+ field :FontWeight, :Type => Integer, :Default => 400, :Version => "1.5"
62
+ field :Flags, :Type => Integer, :Required => true
63
+ field :FontBBox, :Type => Array
64
+ field :ItalicAngle, :Type => Number, :Required => true
65
+ field :Ascent, :Type => Number
66
+ field :Descent, :Type => Number
67
+ field :Leading, :Type => Number, :Default => 0
68
+ field :CapHeight, :Type => Number
69
+ field :XHeight, :Type => Number, :Default => 0
70
+ field :StemV, :Type => Number
71
+ field :StemH, :Type => Number, :Default => 0
72
+ field :AvgWidth, :Type => Number, :Default => 0
73
+ field :MaxWidth, :Type => Number, :Default => 0
74
+ field :MissingWidth, :Type => Number, :Default => 0
75
+ field :FontFile, :Type => FontStream
76
+ field :FontFile2, :Type => FontStream, :Version => "1.1"
77
+ field :FontFile3, :Type => FontStream, :Version => "1.2"
78
+ field :CharSet, :Type => ByteString, :Version => "1.1"
79
+
80
+ end
81
+
82
+ #
83
+ # Class representing a character encoding in a document.
84
+ #
85
+ class Encoding < Dictionary
86
+
87
+ include StandardObject
88
+
89
+ field :Type, :Type => Name, :Default => :Encoding
90
+ field :BaseEncoding, :Type => Name
91
+ field :Differences, :Type => Array
92
+
93
+ end
94
+
28
95
  #
29
96
  # Class representing a rendering font in a document.
30
97
  #
@@ -33,13 +100,13 @@ module Origami
33
100
  include StandardObject
34
101
 
35
102
  field :Type, :Type => Name, :Default => :Font, :Required => true
36
- field :Subtype, :Type => Name, :Default => :Type1, :Required => true
103
+ field :Subtype, :Type => Name, :Required => true
37
104
  field :Name, :Type => Name
38
105
  field :FirstChar, :Type => Integer
39
106
  field :LastChar, :Type => Integer
40
107
  field :Widths, :Type => Array
41
- field :FontDescriptor, :Type => Dictionary
42
- field :Encoding, :Type => [ Name, Dictionary ], :Default => :MacRomanEncoding
108
+ field :FontDescriptor, :Type => FontDescriptor
109
+ field :Encoding, :Type => [ Name, Encoding ], :Default => :MacRomanEncoding
43
110
  field :ToUnicode, :Type => Stream, :Version => "1.2"
44
111
 
45
112
  # TODO: Type0 and CID Fonts
@@ -49,7 +116,7 @@ module Origami
49
116
  #
50
117
  class Type1 < Font
51
118
 
52
- field :BaseFont, :Type => Name, :Default => :Helvetica, :Required => true
119
+ field :BaseFont, :Type => Name, :Required => true
53
120
  field :Subtype, :Type => Name, :Default => :Type1, :Required => true
54
121
 
55
122
  #
@@ -139,71 +206,4 @@ module Origami
139
206
 
140
207
  end
141
208
 
142
- #
143
- # Embedded font stream.
144
- #
145
- class FontStream < Stream
146
-
147
- field :Subtype, :Type => Name
148
- field :Length1, :Type => Integer
149
- field :Length2, :Type => Integer
150
- field :Length3, :Type => Integer
151
-
152
- end
153
-
154
- #
155
- # Class representing a font details in a document.
156
- #
157
- class FontDescriptor < Dictionary
158
-
159
- include StandardObject
160
-
161
- FIXEDPITCH = 1 << 1
162
- SERIF = 1 << 2
163
- SYMBOLIC = 1 << 3
164
- SCRIPT = 1 << 4
165
- NONSYMBOLIC = 1 << 6
166
- ITALIC = 1 << 7
167
- ALLCAP = 1 << 17
168
- SMALLCAP = 1 << 18
169
- FORCEBOLD = 1 << 19
170
-
171
- field :Type, :Type => Name, :Default => :FontDescriptor, :Required => true
172
- field :FontName, :Type => Name, :Required => true
173
- field :FontFamily, :Type => ByteString, :Version => "1.5"
174
- field :FontStretch, :Type => Name, :Default => :Normal, :Version => "1.5"
175
- field :FontWeight, :Type => Integer, :Default => 400, :Version => "1.5"
176
- field :Flags, :Type => Integer, :Required => true
177
- field :FontBBox, :Type => Array
178
- field :ItalicAngle, :Type => Number, :Required => true
179
- field :Ascent, :Type => Number
180
- field :Descent, :Type => Number
181
- field :Leading, :Type => Number, :Default => 0
182
- field :CapHeight, :Type => Number
183
- field :XHeight, :Type => Number, :Default => 0
184
- field :StemV, :Type => Number
185
- field :StemH, :Type => Number, :Default => 0
186
- field :AvgWidth, :Type => Number, :Default => 0
187
- field :MaxWidth, :Type => Number, :Default => 0
188
- field :MissingWidth, :Type => Number, :Default => 0
189
- field :FontFile, :Type => Stream
190
- field :FontFile2, :Type => Stream, :Version => "1.1"
191
- field :FontFile3, :Type => Stream, :Version => "1.2"
192
- field :CharSet, :Type => ByteString, :Version => "1.1"
193
-
194
- end
195
-
196
- #
197
- # Class representing a character encoding in a document.
198
- #
199
- class Encoding < Dictionary
200
-
201
- include StandardObject
202
-
203
- field :Type, :Type => Name, :Default => :Encoding
204
- field :BaseEncoding, :Type => Name
205
- field :Differences, :Type => Array
206
-
207
- end
208
-
209
209
  end
@@ -41,6 +41,7 @@ module Origami
41
41
 
42
42
  class Tiling < ContentStream
43
43
  include Pattern
44
+ include ResourcesHolder
44
45
 
45
46
  module PaintType
46
47
  COLOURED = 1
@@ -59,7 +60,7 @@ module Origami
59
60
  field :BBox, :Type => Array, :Required => true
60
61
  field :XStep, :Type => Number, :Required => true
61
62
  field :YStep, :Type => Number, :Required => true
62
- field :Resources, :Type => Dictionary, :Required => true
63
+ field :Resources, :Type => Resources, :Required => true
63
64
  field :Matrix, :Type => Array, :Default => [ 1, 0, 0, 1, 0, 0 ]
64
65
 
65
66
  end