origami 1.2.5 → 1.2.6

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 (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