pdf-reader 2.9.2 → 2.11.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.
- checksums.yaml +4 -4
- data/CHANGELOG +8 -0
- data/Rakefile +1 -1
- data/lib/pdf/reader/buffer.rb +1 -1
- data/lib/pdf/reader/cid_widths.rb +7 -5
- data/lib/pdf/reader/cmap.rb +1 -1
- data/lib/pdf/reader/encoding.rb +4 -4
- data/lib/pdf/reader/error.rb +0 -4
- data/lib/pdf/reader/filter/depredict.rb +2 -2
- data/lib/pdf/reader/font.rb +10 -11
- data/lib/pdf/reader/font_descriptor.rb +3 -1
- data/lib/pdf/reader/form_xobject.rb +4 -1
- data/lib/pdf/reader/glyph_hash.rb +13 -5
- data/lib/pdf/reader/lzw.rb +25 -10
- data/lib/pdf/reader/no_text_filter.rb +14 -0
- data/lib/pdf/reader/object_hash.rb +15 -9
- data/lib/pdf/reader/object_stream.rb +3 -3
- data/lib/pdf/reader/overlapping_runs_filter.rb +1 -1
- data/lib/pdf/reader/page.rb +26 -7
- data/lib/pdf/reader/page_layout.rb +1 -1
- data/lib/pdf/reader/page_state.rb +7 -1
- data/lib/pdf/reader/page_text_receiver.rb +2 -0
- data/lib/pdf/reader/pages_strategy.rb +1 -1
- data/lib/pdf/reader/reference.rb +3 -2
- data/lib/pdf/reader/resources.rb +3 -2
- data/lib/pdf/reader/stream.rb +1 -1
- data/lib/pdf/reader/synchronized_cache.rb +1 -1
- data/lib/pdf/reader/text_run.rb +5 -2
- data/lib/pdf/reader/transformation_matrix.rb +8 -8
- data/lib/pdf/reader/type_check.rb +46 -0
- data/lib/pdf/reader/width_calculator/built_in.rb +4 -3
- data/lib/pdf/reader/width_calculator/composite.rb +6 -2
- data/lib/pdf/reader/width_calculator/true_type.rb +10 -12
- data/lib/pdf/reader/width_calculator/type_one_or_three.rb +6 -5
- data/lib/pdf/reader/width_calculator/type_zero.rb +6 -3
- data/lib/pdf/reader/xref.rb +3 -3
- data/lib/pdf/reader.rb +5 -10
- data/rbi/pdf-reader.rbi +428 -358
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c84983c18d983798ff5f2ede514b540ee55a788229501976474b7341bf57fba
|
4
|
+
data.tar.gz: 79b8f092e72a194110062cf7d7e9425c0a6531e145009c9b7c10c2c072b3d1d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09c97a875bb46389172ed48ae8b2779ba3a8e032852b6a9943f187de13c23649e2398a5374358c62b64cf9e13bbf7f819bb5072d9aaa6882b9b94e96d23f5c13'
|
7
|
+
data.tar.gz: ed92250acee85f4e355785dd043f7774a5883550fe82b01b3cd9e10011f93a1fcdd500108b0e1f4e2af562bddd833c03ca601078b3eba8ee2e9990fd5e76305a
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
v2.11.0 (26th October 2022)
|
2
|
+
- Various bug fixes
|
3
|
+
- Expanded sorbet type annotations
|
4
|
+
|
5
|
+
v2.10.0 (12th May 2022)
|
6
|
+
- Various bug fixes
|
7
|
+
- Expanded sorbet type annotations
|
8
|
+
|
1
9
|
v2.9.2 (20th February 2022)
|
2
10
|
- Fix PDF::Reader::ObjectHash#page_references to return an Array of PDF::Reader::Reference (http://github.com/yob/pdf-reader/pull/444)
|
3
11
|
|
data/Rakefile
CHANGED
@@ -14,7 +14,7 @@ desc "Run cane to check quality metrics"
|
|
14
14
|
Cane::RakeTask.new(:quality) do |cane|
|
15
15
|
cane.abc_max = 20
|
16
16
|
cane.style_measure = 100
|
17
|
-
cane.max_violations =
|
17
|
+
cane.max_violations = 33
|
18
18
|
|
19
19
|
cane.use Morecane::EncodingCheck, :encoding_glob => "{app,lib,spec}/**/*.rb"
|
20
20
|
end
|
data/lib/pdf/reader/buffer.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
# typed:
|
2
|
+
# typed: strict
|
3
3
|
# frozen_string_literal: true
|
4
4
|
|
5
|
-
#
|
6
|
-
|
7
5
|
require 'forwardable'
|
8
6
|
|
9
7
|
class PDF::Reader
|
@@ -33,10 +31,10 @@ class PDF::Reader
|
|
33
31
|
params << array.shift
|
34
32
|
|
35
33
|
if params.size == 2 && params.last.is_a?(Array)
|
36
|
-
widths.merge! parse_first_form(params.first, params.last)
|
34
|
+
widths.merge! parse_first_form(params.first.to_i, Array(params.last))
|
37
35
|
params = []
|
38
36
|
elsif params.size == 3
|
39
|
-
widths.merge! parse_second_form(params[0], params[1], params[2])
|
37
|
+
widths.merge! parse_second_form(params[0].to_i, params[1].to_i, params[2].to_i)
|
40
38
|
params = []
|
41
39
|
end
|
42
40
|
end
|
@@ -54,6 +52,10 @@ class PDF::Reader
|
|
54
52
|
|
55
53
|
# this is the form 10 20 123 where all index between 10 and 20 have width 123
|
56
54
|
def parse_second_form(first, final, width)
|
55
|
+
if first > final
|
56
|
+
raise MalformedPDFError, "CidWidths: #{first} must be less than #{final}"
|
57
|
+
end
|
58
|
+
|
57
59
|
(first..final).inject({}) { |accum, index|
|
58
60
|
accum[index] = width
|
59
61
|
accum
|
data/lib/pdf/reader/cmap.rb
CHANGED
data/lib/pdf/reader/encoding.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
# typed:
|
2
|
+
# typed: strict
|
3
3
|
# frozen_string_literal: true
|
4
4
|
|
5
5
|
################################################################################
|
@@ -76,9 +76,9 @@ class PDF::Reader
|
|
76
76
|
diff.each do |val|
|
77
77
|
if val.kind_of?(Numeric)
|
78
78
|
byte = val.to_i
|
79
|
-
|
79
|
+
elsif codepoint = glyphlist.name_to_unicode(val)
|
80
80
|
@differences[byte] = val
|
81
|
-
@mapping[byte] =
|
81
|
+
@mapping[byte] = codepoint
|
82
82
|
byte += 1
|
83
83
|
end
|
84
84
|
end
|
@@ -167,7 +167,7 @@ class PDF::Reader
|
|
167
167
|
end
|
168
168
|
|
169
169
|
def convert_to_utf8(str)
|
170
|
-
ret = str.unpack(unpack).map! { |c| @mapping[c] || c }.pack("U*")
|
170
|
+
ret = str.unpack(unpack).map! { |c| @mapping[c.to_i] || c }.pack("U*")
|
171
171
|
ret.force_encoding("UTF-8")
|
172
172
|
ret
|
173
173
|
end
|
data/lib/pdf/reader/error.rb
CHANGED
@@ -58,10 +58,6 @@ class PDF::Reader
|
|
58
58
|
def self.validate_not_nil(object, name)
|
59
59
|
raise ArgumentError, "#{object} must not be nil" if object.nil?
|
60
60
|
end
|
61
|
-
################################################################################
|
62
|
-
def self.validate_not_nil_as_malformed(object, name)
|
63
|
-
raise MalformedPDFError, "#{object} must not be nil" if object.nil?
|
64
|
-
end
|
65
61
|
end
|
66
62
|
|
67
63
|
################################################################################
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
# typed:
|
2
|
+
# typed: strict
|
3
3
|
# frozen_string_literal: true
|
4
4
|
|
5
5
|
class PDF::Reader
|
@@ -125,7 +125,7 @@ class PDF::Reader
|
|
125
125
|
row_data[index] = (byte + paeth) % 256
|
126
126
|
end
|
127
127
|
else
|
128
|
-
raise
|
128
|
+
raise MalformedPDFError, "Invalid filter algorithm #{filter}"
|
129
129
|
end
|
130
130
|
|
131
131
|
s = []
|
data/lib/pdf/reader/font.rb
CHANGED
@@ -205,14 +205,17 @@ class PDF::Reader
|
|
205
205
|
end
|
206
206
|
|
207
207
|
def extract_descendants(obj)
|
208
|
-
return unless obj[:DescendantFonts]
|
209
208
|
# per PDF 32000-1:2008 pp. 280 :DescendentFonts is:
|
210
209
|
# A one-element array specifying the CIDFont dictionary that is the
|
211
210
|
# descendant of this Type 0 font.
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
211
|
+
if obj[:DescendantFonts]
|
212
|
+
descendants = @ohash.deref_array(obj[:DescendantFonts])
|
213
|
+
@descendantfonts = descendants.map { |desc|
|
214
|
+
PDF::Reader::Font.new(@ohash, @ohash.deref_hash(desc))
|
215
|
+
}
|
216
|
+
else
|
217
|
+
@descendantfonts = []
|
218
|
+
end
|
216
219
|
end
|
217
220
|
|
218
221
|
def to_utf8_via_cmap(params)
|
@@ -226,9 +229,7 @@ class PDF::Reader
|
|
226
229
|
@tounicode.decode(c) || PDF::Reader::Encoding::UNKNOWN_CHAR
|
227
230
|
}.flatten.pack("U*")
|
228
231
|
when Array
|
229
|
-
params.collect { |param| to_utf8_via_cmap(param) }
|
230
|
-
else
|
231
|
-
params
|
232
|
+
params.collect { |param| to_utf8_via_cmap(param) }.join("")
|
232
233
|
end
|
233
234
|
end
|
234
235
|
|
@@ -243,9 +244,7 @@ class PDF::Reader
|
|
243
244
|
when String
|
244
245
|
encoding.to_utf8(params)
|
245
246
|
when Array
|
246
|
-
params.collect { |param| to_utf8_via_encoding(param) }
|
247
|
-
else
|
248
|
-
params
|
247
|
+
params.collect { |param| to_utf8_via_encoding(param) }.join("")
|
249
248
|
end
|
250
249
|
end
|
251
250
|
|
@@ -45,7 +45,7 @@ module PDF
|
|
45
45
|
def font_objects
|
46
46
|
raw_fonts = @objects.deref_hash(fonts)
|
47
47
|
::Hash[raw_fonts.map { |label, font|
|
48
|
-
[label, PDF::Reader::Font.new(@objects, @objects.deref_hash(font))]
|
48
|
+
[label, PDF::Reader::Font.new(@objects, @objects.deref_hash(font) || {})]
|
49
49
|
}]
|
50
50
|
end
|
51
51
|
|
@@ -55,6 +55,9 @@ module PDF
|
|
55
55
|
# See the comments on PDF::Reader::Page#walk for more detail.
|
56
56
|
#
|
57
57
|
def walk(*receivers)
|
58
|
+
receivers = receivers.map { |receiver|
|
59
|
+
ValidatingReceiver.new(receiver)
|
60
|
+
}
|
58
61
|
content_stream(receivers, raw_content)
|
59
62
|
end
|
60
63
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
# typed:
|
2
|
+
# typed: strict
|
3
3
|
# frozen_string_literal: true
|
4
4
|
|
5
5
|
################################################################################
|
@@ -33,10 +33,18 @@ class PDF::Reader
|
|
33
33
|
#
|
34
34
|
class GlyphHash # :nodoc:
|
35
35
|
def initialize
|
36
|
+
@@by_codepoint_cache ||= nil
|
37
|
+
@@by_name_cache ||= nil
|
38
|
+
|
36
39
|
# only parse the glyph list once, and cache the results (for performance)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
+
if @@by_codepoint_cache != nil && @@by_name_cache != nil
|
41
|
+
@by_name = @@by_name_cache
|
42
|
+
@by_codepoint = @@by_codepoint_cache
|
43
|
+
else
|
44
|
+
by_name, by_codepoint = load_adobe_glyph_mapping
|
45
|
+
@by_name = @@by_name_cache ||= by_name
|
46
|
+
@by_codepoint = @@by_codepoint_cache ||= by_codepoint
|
47
|
+
end
|
40
48
|
end
|
41
49
|
|
42
50
|
# attempt to convert a PDF Name to a unicode codepoint. Returns nil
|
@@ -127,7 +135,7 @@ class PDF::Reader
|
|
127
135
|
end
|
128
136
|
end
|
129
137
|
|
130
|
-
|
138
|
+
return keyed_by_name.freeze, keyed_by_codepoint.freeze
|
131
139
|
end
|
132
140
|
|
133
141
|
end
|
data/lib/pdf/reader/lzw.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
# typed:
|
2
|
+
# typed: strict
|
3
3
|
# frozen_string_literal: true
|
4
4
|
|
5
5
|
module PDF
|
@@ -25,12 +25,14 @@ module PDF
|
|
25
25
|
def initialize(data, bits_in_chunk)
|
26
26
|
@data = data
|
27
27
|
@data.force_encoding("BINARY")
|
28
|
-
|
28
|
+
set_bits_in_chunk(bits_in_chunk)
|
29
29
|
@current_pos = 0
|
30
30
|
@bits_left_in_byte = 8
|
31
31
|
end
|
32
32
|
|
33
33
|
def set_bits_in_chunk(bits_in_chunk)
|
34
|
+
raise MalformedPDFError, "invalid LZW bits" if bits_in_chunk < 9 || bits_in_chunk > 12
|
35
|
+
|
34
36
|
@bits_in_chunk = bits_in_chunk
|
35
37
|
end
|
36
38
|
|
@@ -39,7 +41,7 @@ module PDF
|
|
39
41
|
chunk = -1
|
40
42
|
while bits_left_in_chunk > 0 and @current_pos < @data.size
|
41
43
|
chunk = 0 if chunk < 0
|
42
|
-
codepoint = @data[@current_pos, 1].unpack("C*")[0]
|
44
|
+
codepoint = @data[@current_pos, 1].to_s.unpack("C*")[0].to_i
|
43
45
|
current_byte = codepoint & (2**@bits_left_in_byte - 1) #clear consumed bits
|
44
46
|
dif = bits_left_in_chunk - @bits_left_in_byte
|
45
47
|
if dif > 0 then current_byte <<= dif
|
@@ -61,21 +63,25 @@ module PDF
|
|
61
63
|
CODE_CLEAR_TABLE = 256 #clear table
|
62
64
|
|
63
65
|
# stores de pairs code => string
|
64
|
-
class StringTable
|
66
|
+
class StringTable
|
65
67
|
attr_reader :string_table_pos
|
66
68
|
|
67
69
|
def initialize
|
68
|
-
|
70
|
+
@data = Hash.new
|
69
71
|
@string_table_pos = 258 #initial code
|
70
72
|
end
|
71
73
|
|
72
74
|
#if code less than 258 return fixed string
|
73
75
|
def [](key)
|
74
|
-
if key > 257
|
76
|
+
if key > 257
|
77
|
+
@data[key]
|
78
|
+
else
|
79
|
+
key.chr
|
80
|
+
end
|
75
81
|
end
|
76
82
|
|
77
83
|
def add(string)
|
78
|
-
store(@string_table_pos, string)
|
84
|
+
@data.store(@string_table_pos, string)
|
79
85
|
@string_table_pos += 1
|
80
86
|
end
|
81
87
|
end
|
@@ -83,7 +89,7 @@ module PDF
|
|
83
89
|
# Decompresses a LZW compressed string.
|
84
90
|
#
|
85
91
|
def self.decode(data)
|
86
|
-
stream = BitStream.new
|
92
|
+
stream = BitStream.new(data.to_s, 9) # size of codes between 9 and 12 bits
|
87
93
|
string_table = StringTable.new
|
88
94
|
result = "".dup
|
89
95
|
until (code = stream.read) == CODE_EOD
|
@@ -119,8 +125,17 @@ module PDF
|
|
119
125
|
result
|
120
126
|
end
|
121
127
|
|
122
|
-
def self.create_new_string(string_table,some_code, other_code)
|
123
|
-
|
128
|
+
def self.create_new_string(string_table, some_code, other_code)
|
129
|
+
raise MalformedPDFError, "invalid LZW data" if some_code.nil? || other_code.nil?
|
130
|
+
|
131
|
+
item_one = string_table[some_code]
|
132
|
+
item_two = string_table[other_code]
|
133
|
+
|
134
|
+
if item_one && item_two
|
135
|
+
item_one + item_two.chr
|
136
|
+
else
|
137
|
+
raise MalformedPDFError, "invalid LZW data"
|
138
|
+
end
|
124
139
|
end
|
125
140
|
private_class_method :create_new_string
|
126
141
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# typed: strict
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
class PDF::Reader
|
6
|
+
# There's no point rendering zero-width characters
|
7
|
+
class NoTextFilter
|
8
|
+
|
9
|
+
def self.exclude_empty_strings(runs)
|
10
|
+
runs.reject { |run| run.text.to_s.size == 0 }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -2,6 +2,8 @@
|
|
2
2
|
# typed: true
|
3
3
|
# frozen_string_literal: true
|
4
4
|
|
5
|
+
require 'tempfile'
|
6
|
+
|
5
7
|
class PDF::Reader
|
6
8
|
# Provides low level access to the objects in a PDF file via a hash-like
|
7
9
|
# object.
|
@@ -243,7 +245,7 @@ class PDF::Reader
|
|
243
245
|
|
244
246
|
obj.tap { |obj|
|
245
247
|
if !obj.is_a?(PDF::Reader::Stream)
|
246
|
-
raise MalformedPDFError, "expected object to be
|
248
|
+
raise MalformedPDFError, "expected object to be a Stream or nil"
|
247
249
|
end
|
248
250
|
}
|
249
251
|
end
|
@@ -496,7 +498,9 @@ class PDF::Reader
|
|
496
498
|
def fetch_object_stream(key)
|
497
499
|
if xref[key].is_a?(PDF::Reader::Reference)
|
498
500
|
container_key = xref[key]
|
499
|
-
|
501
|
+
stream = deref_stream(container_key)
|
502
|
+
raise MalformedPDFError, "Object Stream cannot be nil" if stream.nil?
|
503
|
+
object_streams[container_key] ||= PDF::Reader::ObjectStream.new(stream)
|
500
504
|
object_streams[container_key][key.id]
|
501
505
|
end
|
502
506
|
end
|
@@ -564,7 +568,7 @@ class PDF::Reader
|
|
564
568
|
end
|
565
569
|
|
566
570
|
def object_streams
|
567
|
-
@
|
571
|
+
@object_streams ||= {}
|
568
572
|
end
|
569
573
|
|
570
574
|
# returns an array of object references for all pages in this object store. The ordering of
|
@@ -573,7 +577,9 @@ class PDF::Reader
|
|
573
577
|
def get_page_objects(obj)
|
574
578
|
derefed_obj = deref_hash(obj)
|
575
579
|
|
576
|
-
if derefed_obj
|
580
|
+
if derefed_obj.nil?
|
581
|
+
raise MalformedPDFError, "Expected Page or Pages object, got nil"
|
582
|
+
elsif derefed_obj[:Type] == :Page
|
577
583
|
[obj]
|
578
584
|
elsif derefed_obj[:Kids]
|
579
585
|
kids = deref_array(derefed_obj[:Kids]) || []
|
@@ -587,18 +593,18 @@ class PDF::Reader
|
|
587
593
|
|
588
594
|
def read_version
|
589
595
|
@io.seek(0)
|
590
|
-
_m, version = *@io.read(10).match(/PDF-(\d.\d)/)
|
596
|
+
_m, version = *@io.read(10).to_s.match(/PDF-(\d.\d)/)
|
591
597
|
@io.seek(0)
|
592
598
|
version.to_f
|
593
599
|
end
|
594
600
|
|
595
601
|
def extract_io_from(input)
|
596
|
-
if input.
|
602
|
+
if input.is_a?(IO) || input.is_a?(StringIO) || input.is_a?(Tempfile)
|
597
603
|
input
|
598
604
|
elsif File.file?(input.to_s)
|
599
|
-
StringIO.new read_as_binary(input)
|
605
|
+
StringIO.new read_as_binary(input.to_s)
|
600
606
|
else
|
601
|
-
raise ArgumentError, "input must be an IO-like object or a filename"
|
607
|
+
raise ArgumentError, "input must be an IO-like object or a filename (#{input.class})"
|
602
608
|
end
|
603
609
|
end
|
604
610
|
|
@@ -606,7 +612,7 @@ class PDF::Reader
|
|
606
612
|
if File.respond_to?(:binread)
|
607
613
|
File.binread(input.to_s)
|
608
614
|
else
|
609
|
-
File.open(input.to_s,"rb") { |f| f.read }
|
615
|
+
File.open(input.to_s,"rb") { |f| f.read } || ""
|
610
616
|
end
|
611
617
|
end
|
612
618
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
# typed:
|
2
|
+
# typed: strict
|
3
3
|
# frozen_string_literal: true
|
4
4
|
|
5
5
|
class PDF::Reader
|
@@ -24,7 +24,7 @@ class PDF::Reader
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def size
|
27
|
-
@dict[:N]
|
27
|
+
TypeCheck.cast_to_int!(@dict[:N])
|
28
28
|
end
|
29
29
|
|
30
30
|
private
|
@@ -40,7 +40,7 @@ class PDF::Reader
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def first
|
43
|
-
@dict[:First]
|
43
|
+
TypeCheck.cast_to_int!(@dict[:First])
|
44
44
|
end
|
45
45
|
|
46
46
|
def buffer
|
data/lib/pdf/reader/page.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
# typed:
|
2
|
+
# typed: strict
|
3
3
|
# frozen_string_literal: true
|
4
4
|
|
5
5
|
module PDF
|
@@ -43,10 +43,10 @@ module PDF
|
|
43
43
|
#
|
44
44
|
def initialize(objects, pagenum, options = {})
|
45
45
|
@objects, @pagenum = objects, pagenum
|
46
|
-
@page_object = objects.deref_hash(objects.page_references[pagenum - 1])
|
46
|
+
@page_object = objects.deref_hash(objects.page_references[pagenum - 1]) || {}
|
47
47
|
@cache = options[:cache] || {}
|
48
48
|
|
49
|
-
|
49
|
+
if @page_object.empty?
|
50
50
|
raise InvalidPageError, "Invalid page: #{pagenum}"
|
51
51
|
end
|
52
52
|
end
|
@@ -250,8 +250,8 @@ module PDF
|
|
250
250
|
params = []
|
251
251
|
|
252
252
|
while (token = parser.parse_token(PagesStrategy::OPERATORS))
|
253
|
-
if token.kind_of?(Token)
|
254
|
-
callback(receivers,
|
253
|
+
if token.kind_of?(Token) && method_name = PagesStrategy::OPERATORS[token]
|
254
|
+
callback(receivers, method_name, params)
|
255
255
|
params.clear
|
256
256
|
else
|
257
257
|
params << token
|
@@ -263,9 +263,26 @@ module PDF
|
|
263
263
|
|
264
264
|
# calls the name callback method on each receiver object with params as the arguments
|
265
265
|
#
|
266
|
+
# The silly style here is because sorbet won't let me use splat arguments
|
267
|
+
#
|
266
268
|
def callback(receivers, name, params=[])
|
267
269
|
receivers.each do |receiver|
|
268
|
-
|
270
|
+
if receiver.respond_to?(name)
|
271
|
+
case params.size
|
272
|
+
when 0 then receiver.send(name)
|
273
|
+
when 1 then receiver.send(name, params[0])
|
274
|
+
when 2 then receiver.send(name, params[0], params[1])
|
275
|
+
when 3 then receiver.send(name, params[0], params[1], params[2])
|
276
|
+
when 4 then receiver.send(name, params[0], params[1], params[2], params[3])
|
277
|
+
when 5 then receiver.send(name, params[0], params[1], params[2], params[3], params[4])
|
278
|
+
when 6 then receiver.send(name, params[0], params[1], params[2], params[3], params[4], params[5])
|
279
|
+
when 7 then receiver.send(name, params[0], params[1], params[2], params[3], params[4], params[5], params[6])
|
280
|
+
when 8 then receiver.send(name, params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7])
|
281
|
+
when 9 then receiver.send(name, params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8])
|
282
|
+
else
|
283
|
+
receiver.send(name, params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], params[9])
|
284
|
+
end
|
285
|
+
end
|
269
286
|
end
|
270
287
|
end
|
271
288
|
|
@@ -278,7 +295,9 @@ module PDF
|
|
278
295
|
[]
|
279
296
|
else
|
280
297
|
obj = objects.deref_hash(origin)
|
281
|
-
|
298
|
+
if obj.nil?
|
299
|
+
raise MalformedPDFError, "parent mus not be nil"
|
300
|
+
end
|
282
301
|
[ select_inheritable(obj) ] + ancestors(obj[:Parent])
|
283
302
|
end
|
284
303
|
end
|
@@ -16,7 +16,7 @@ class PDF::Reader
|
|
16
16
|
:h_scaling => 1.0,
|
17
17
|
:text_leading => 0,
|
18
18
|
:text_font => nil,
|
19
|
-
:text_font_size =>
|
19
|
+
:text_font_size => 0,
|
20
20
|
:text_mode => 0,
|
21
21
|
:text_rise => 0,
|
22
22
|
:text_knockout => 0
|
@@ -32,6 +32,12 @@ class PDF::Reader
|
|
32
32
|
@cs_stack = [page.color_spaces]
|
33
33
|
@stack = [DEFAULT_GRAPHICS_STATE.dup]
|
34
34
|
state[:ctm] = identity_matrix
|
35
|
+
|
36
|
+
# These are only valid when inside a `BT` block and we re-initialize them on each
|
37
|
+
# `BT`. However, we need the instance variables set so PDFs with the text operators
|
38
|
+
# out order don't trigger NoMethodError when these are nil
|
39
|
+
@text_matrix = identity_matrix
|
40
|
+
@text_line_matrix = identity_matrix
|
35
41
|
end
|
36
42
|
|
37
43
|
#####################################################
|
data/lib/pdf/reader/reference.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
# typed:
|
2
|
+
# typed: strict
|
3
3
|
# frozen_string_literal: true
|
4
4
|
|
5
5
|
################################################################################
|
@@ -31,7 +31,8 @@ class PDF::Reader
|
|
31
31
|
################################################################################
|
32
32
|
# An internal PDF::Reader class that represents an indirect reference to a PDF Object
|
33
33
|
class Reference
|
34
|
-
attr_reader :id
|
34
|
+
attr_reader :id
|
35
|
+
attr_reader :gen
|
35
36
|
################################################################################
|
36
37
|
# Create a new Reference to an object with the specified id and revision number
|
37
38
|
def initialize(id, gen)
|
data/lib/pdf/reader/resources.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
# typed:
|
2
|
+
# typed: strict
|
3
3
|
# frozen_string_literal: true
|
4
4
|
|
5
5
|
module PDF
|
@@ -92,7 +92,8 @@ module PDF
|
|
92
92
|
# of calling it over and over.
|
93
93
|
#
|
94
94
|
def xobjects
|
95
|
-
@objects.deref_hash!(@resources[:XObject]) || {}
|
95
|
+
dict = @objects.deref_hash!(@resources[:XObject]) || {}
|
96
|
+
TypeCheck.cast_to_pdf_dict_with_stream_values!(dict)
|
96
97
|
end
|
97
98
|
|
98
99
|
end
|
data/lib/pdf/reader/stream.rb
CHANGED
@@ -40,7 +40,7 @@ class PDF::Reader
|
|
40
40
|
# Creates a new stream with the specified dictionary and data. The dictionary
|
41
41
|
# should be a standard ruby hash, the data should be a standard ruby string.
|
42
42
|
def initialize(hash, data)
|
43
|
-
@hash = hash
|
43
|
+
@hash = TypeCheck.cast_to_pdf_dict!(hash)
|
44
44
|
@data = data
|
45
45
|
@udata = nil
|
46
46
|
end
|
data/lib/pdf/reader/text_run.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
# typed:
|
2
|
+
# typed: strict
|
3
3
|
# frozen_string_literal: true
|
4
4
|
|
5
5
|
class PDF::Reader
|
@@ -7,7 +7,10 @@ class PDF::Reader
|
|
7
7
|
class TextRun
|
8
8
|
include Comparable
|
9
9
|
|
10
|
-
attr_reader :origin
|
10
|
+
attr_reader :origin
|
11
|
+
attr_reader :width
|
12
|
+
attr_reader :font_size
|
13
|
+
attr_reader :text
|
11
14
|
|
12
15
|
alias :to_s :text
|
13
16
|
|