hexapdf 0.15.6 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +32 -0
- data/lib/hexapdf/cli/command.rb +1 -1
- data/lib/hexapdf/configuration.rb +1 -1
- data/lib/hexapdf/content/canvas.rb +5 -1
- data/lib/hexapdf/content/color_space.rb +167 -1
- data/lib/hexapdf/dictionary_fields.rb +22 -1
- data/lib/hexapdf/parser.rb +10 -1
- data/lib/hexapdf/tokenizer.rb +10 -2
- data/lib/hexapdf/version.rb +1 -1
- data/test/hexapdf/common_tokenizer_tests.rb +15 -0
- data/test/hexapdf/content/test_color_space.rb +13 -1
- data/test/hexapdf/test_dictionary_fields.rb +15 -0
- data/test/hexapdf/test_parser.rb +15 -2
- data/test/hexapdf/test_writer.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b2303787fd50c2407bb99336c3315643c4a9401a84a508462715d18a378788c
|
4
|
+
data.tar.gz: 675bb953973762670c598f93ed15fcaa4387f962c0cbdc9d27060bd06de4f5ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81715891b39fc35606baae317fc44a4be4d7710b2a1488f682425620771c2b563ecdfa8ba8ff0028a5226904d511c79b9507c1fed7170fdfd2c7a29aa4706127
|
7
|
+
data.tar.gz: f24fb2cdd07da0c2afde7511c40880e66fd65d87d2fd6035524202fbf8f1040d1e64576b3b080f6aa0d006d5938fc61c399c062d8687b33b3f3a5e9966b3917d
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,35 @@
|
|
1
|
+
## 0.16.0 - 2021-09-28
|
2
|
+
|
3
|
+
## Added
|
4
|
+
|
5
|
+
* Support for RGB color values of the form "RGB" in addition to "RRGGBB" and for
|
6
|
+
CSS color module level 3 color names
|
7
|
+
* Conversion module for Integer fields to fix certain invalid PDF files
|
8
|
+
|
9
|
+
|
10
|
+
## 0.15.9 - 2021-09-04
|
11
|
+
|
12
|
+
### Fixed
|
13
|
+
|
14
|
+
* Handling of files that contain stream length values that are indirect objects
|
15
|
+
not referring to a number
|
16
|
+
|
17
|
+
|
18
|
+
## 0.15.8 - 2021-08-16
|
19
|
+
|
20
|
+
### Fixed
|
21
|
+
|
22
|
+
* Regression when using `-v` with the hexapdf command line tool
|
23
|
+
|
24
|
+
|
25
|
+
## 0.15.7 - 2021-07-17
|
26
|
+
|
27
|
+
### Fixed
|
28
|
+
|
29
|
+
* Infinite loop while parsing PDF array due to missing closing bracket
|
30
|
+
* Handling of invalid files with missing or corrupted trailer dictionary
|
31
|
+
|
32
|
+
|
1
33
|
## 0.15.6 - 2021-07-16
|
2
34
|
|
3
35
|
### Fixed
|
data/lib/hexapdf/cli/command.rb
CHANGED
@@ -119,7 +119,7 @@ module HexaPDF
|
|
119
119
|
# Writes the document to the given file or does nothing if +out_file+ is +nil+.
|
120
120
|
def write_document(doc, out_file, incremental: false)
|
121
121
|
if out_file
|
122
|
-
doc.validate(auto_correct: true) do |
|
122
|
+
doc.validate(auto_correct: true) do |msg, correctable, object|
|
123
123
|
if command_parser.strict && !correctable
|
124
124
|
raise "Validation error for object (#{object.oid},#{object.gen}): #{msg}"
|
125
125
|
elsif command_parser.verbosity_info?
|
@@ -245,7 +245,7 @@ module HexaPDF
|
|
245
245
|
# Defines a mapping from font names and variants to font files.
|
246
246
|
#
|
247
247
|
# The value needs to be a hash of the form:
|
248
|
-
# {"font_name"
|
248
|
+
# {"font_name" => {variant: file_name, variant2: file_name2, ...}, ...}
|
249
249
|
#
|
250
250
|
# Once a font is registered in this way, the font name together with a variant name can be used
|
251
251
|
# with the HexaPDF::Document::Fonts#add method to load the font.
|
@@ -675,6 +675,10 @@ module HexaPDF
|
|
675
675
|
# * Three numeric arguments specify an RGB color (see Content::ColorSpace::DeviceRGB::Color).
|
676
676
|
# * A string in the format "RRGGBB" where "RR" is the hexadecimal number for the red, "GG"
|
677
677
|
# for the green and "BB" for the blue color value also specifies an RGB color.
|
678
|
+
# * As does a string in the format "RGB" where "RR", "GG" and "BB" would be used as the
|
679
|
+
# hexadecimal numbers for the red, green and blue color values of an RGB color.
|
680
|
+
# * Any other string is treated as a CSS Color Module Level 3 color name, see
|
681
|
+
# https://www.w3.org/TR/css-color-3/#svg-color.
|
678
682
|
# * Four numeric arguments specify a CMYK color (see Content::ColorSpace::DeviceCMYK::Color).
|
679
683
|
# * A color object is used directly (normally used for color spaces other than DeviceRGB,
|
680
684
|
# DeviceCMYK and DeviceGray).
|
@@ -1852,7 +1856,7 @@ module HexaPDF
|
|
1852
1856
|
# on the possible color specifications.
|
1853
1857
|
def color_from_specification(spec)
|
1854
1858
|
if spec.length == 1 && spec[0].kind_of?(String)
|
1855
|
-
|
1859
|
+
ColorSpace.device_color_from_specification(spec)
|
1856
1860
|
elsif spec.length == 1 && spec[0].respond_to?(:color_space)
|
1857
1861
|
spec[0]
|
1858
1862
|
else
|
@@ -96,6 +96,157 @@ module HexaPDF
|
|
96
96
|
# See: PDF1.7 s8.6
|
97
97
|
module ColorSpace
|
98
98
|
|
99
|
+
# Mapping of CSS Color Module Level 3 names to RGB values.
|
100
|
+
CSS_COLOR_NAMES = {
|
101
|
+
"aliceblue" => [240, 248, 255],
|
102
|
+
"antiquewhite" => [250, 235, 215],
|
103
|
+
"aqua" => [0, 255, 255],
|
104
|
+
"aquamarine" => [127, 255, 212],
|
105
|
+
"azure" => [240, 255, 255],
|
106
|
+
"beige" => [245, 245, 220],
|
107
|
+
"bisque" => [255, 228, 196],
|
108
|
+
"black" => [0, 0, 0],
|
109
|
+
"blanchedalmond" => [255, 235, 205],
|
110
|
+
"blue" => [0, 0, 255],
|
111
|
+
"blueviolet" => [138, 43, 226],
|
112
|
+
"brown" => [165, 42, 42],
|
113
|
+
"burlywood" => [222, 184, 135],
|
114
|
+
"cadetblue" => [95, 158, 160],
|
115
|
+
"chartreuse" => [127, 255, 0],
|
116
|
+
"chocolate" => [210, 105, 30],
|
117
|
+
"coral" => [255, 127, 80],
|
118
|
+
"cornflowerblue" => [100, 149, 237],
|
119
|
+
"cornsilk" => [255, 248, 220],
|
120
|
+
"crimson" => [220, 20, 60],
|
121
|
+
"cyan" => [0, 255, 255],
|
122
|
+
"darkblue" => [0, 0, 139],
|
123
|
+
"darkcyan" => [0, 139, 139],
|
124
|
+
"darkgoldenrod" => [184, 134, 11],
|
125
|
+
"darkgray" => [169, 169, 169],
|
126
|
+
"darkgreen" => [0, 100, 0],
|
127
|
+
"darkgrey" => [169, 169, 169],
|
128
|
+
"darkkhaki" => [189, 183, 107],
|
129
|
+
"darkmagenta" => [139, 0, 139],
|
130
|
+
"darkolivegreen" => [85, 107, 47],
|
131
|
+
"darkorange" => [255, 140, 0],
|
132
|
+
"darkorchid" => [153, 50, 204],
|
133
|
+
"darkred" => [139, 0, 0],
|
134
|
+
"darksalmon" => [233, 150, 122],
|
135
|
+
"darkseagreen" => [143, 188, 143],
|
136
|
+
"darkslateblue" => [72, 61, 139],
|
137
|
+
"darkslategray" => [47, 79, 79],
|
138
|
+
"darkslategrey" => [47, 79, 79],
|
139
|
+
"darkturquoise" => [0, 206, 209],
|
140
|
+
"darkviolet" => [148, 0, 211],
|
141
|
+
"deeppink" => [255, 20, 147],
|
142
|
+
"deepskyblue" => [0, 191, 255],
|
143
|
+
"dimgray" => [105, 105, 105],
|
144
|
+
"dimgrey" => [105, 105, 105],
|
145
|
+
"dodgerblue" => [30, 144, 255],
|
146
|
+
"firebrick" => [178, 34, 34],
|
147
|
+
"floralwhite" => [255, 250, 240],
|
148
|
+
"forestgreen" => [34, 139, 34],
|
149
|
+
"fuchsia" => [255, 0, 255],
|
150
|
+
"gainsboro" => [220, 220, 220],
|
151
|
+
"ghostwhite" => [248, 248, 255],
|
152
|
+
"gold" => [255, 215, 0],
|
153
|
+
"goldenrod" => [218, 165, 32],
|
154
|
+
"gray" => [128, 128, 128],
|
155
|
+
"green" => [0, 128, 0],
|
156
|
+
"greenyellow" => [173, 255, 47],
|
157
|
+
"grey" => [128, 128, 128],
|
158
|
+
"honeydew" => [240, 255, 240],
|
159
|
+
"hotpink" => [255, 105, 180],
|
160
|
+
"indianred" => [205, 92, 92],
|
161
|
+
"indigo" => [75, 0, 130],
|
162
|
+
"ivory" => [255, 255, 240],
|
163
|
+
"khaki" => [240, 230, 140],
|
164
|
+
"lavender" => [230, 230, 250],
|
165
|
+
"lavenderblush" => [255, 240, 245],
|
166
|
+
"lawngreen" => [124, 252, 0],
|
167
|
+
"lemonchiffon" => [255, 250, 205],
|
168
|
+
"lightblue" => [173, 216, 230],
|
169
|
+
"lightcoral" => [240, 128, 128],
|
170
|
+
"lightcyan" => [224, 255, 255],
|
171
|
+
"lightgoldenrodyellow" => [250, 250, 210],
|
172
|
+
"lightgray" => [211, 211, 211],
|
173
|
+
"lightgreen" => [144, 238, 144],
|
174
|
+
"lightgrey" => [211, 211, 211],
|
175
|
+
"lightpink" => [255, 182, 193],
|
176
|
+
"lightsalmon" => [255, 160, 122],
|
177
|
+
"lightseagreen" => [32, 178, 170],
|
178
|
+
"lightskyblue" => [135, 206, 250],
|
179
|
+
"lightslategray" => [119, 136, 153],
|
180
|
+
"lightslategrey" => [119, 136, 153],
|
181
|
+
"lightsteelblue" => [176, 196, 222],
|
182
|
+
"lightyellow" => [255, 255, 224],
|
183
|
+
"lime" => [0, 255, 0],
|
184
|
+
"limegreen" => [50, 205, 50],
|
185
|
+
"linen" => [250, 240, 230],
|
186
|
+
"magenta" => [255, 0, 255],
|
187
|
+
"maroon" => [128, 0, 0],
|
188
|
+
"mediumaquamarine" => [102, 205, 170],
|
189
|
+
"mediumblue" => [0, 0, 205],
|
190
|
+
"mediumorchid" => [186, 85, 211],
|
191
|
+
"mediumpurple" => [147, 112, 219],
|
192
|
+
"mediumseagreen" => [60, 179, 113],
|
193
|
+
"mediumslateblue" => [123, 104, 238],
|
194
|
+
"mediumspringgreen" => [0, 250, 154],
|
195
|
+
"mediumturquoise" => [72, 209, 204],
|
196
|
+
"mediumvioletred" => [199, 21, 133],
|
197
|
+
"midnightblue" => [25, 25, 112],
|
198
|
+
"mintcream" => [245, 255, 250],
|
199
|
+
"mistyrose" => [255, 228, 225],
|
200
|
+
"moccasin" => [255, 228, 181],
|
201
|
+
"navajowhite" => [255, 222, 173],
|
202
|
+
"navy" => [0, 0, 128],
|
203
|
+
"oldlace" => [253, 245, 230],
|
204
|
+
"olive" => [128, 128, 0],
|
205
|
+
"olivedrab" => [107, 142, 35],
|
206
|
+
"orange" => [255, 165, 0],
|
207
|
+
"orangered" => [255, 69, 0],
|
208
|
+
"orchid" => [218, 112, 214],
|
209
|
+
"palegoldenrod" => [238, 232, 170],
|
210
|
+
"palegreen" => [152, 251, 152],
|
211
|
+
"paleturquoise" => [175, 238, 238],
|
212
|
+
"palevioletred" => [219, 112, 147],
|
213
|
+
"papayawhip" => [255, 239, 213],
|
214
|
+
"peachpuff" => [255, 218, 185],
|
215
|
+
"peru" => [205, 133, 63],
|
216
|
+
"pink" => [255, 192, 203],
|
217
|
+
"plum" => [221, 160, 221],
|
218
|
+
"powderblue" => [176, 224, 230],
|
219
|
+
"purple" => [128, 0, 128],
|
220
|
+
"red" => [255, 0, 0],
|
221
|
+
"rosybrown" => [188, 143, 143],
|
222
|
+
"royalblue" => [65, 105, 225],
|
223
|
+
"saddlebrown" => [139, 69, 19],
|
224
|
+
"salmon" => [250, 128, 114],
|
225
|
+
"sandybrown" => [244, 164, 96],
|
226
|
+
"seagreen" => [46, 139, 87],
|
227
|
+
"seashell" => [255, 245, 238],
|
228
|
+
"sienna" => [160, 82, 45],
|
229
|
+
"silver" => [192, 192, 192],
|
230
|
+
"skyblue" => [135, 206, 235],
|
231
|
+
"slateblue" => [106, 90, 205],
|
232
|
+
"slategray" => [112, 128, 144],
|
233
|
+
"slategrey" => [112, 128, 144],
|
234
|
+
"snow" => [255, 250, 250],
|
235
|
+
"springgreen" => [0, 255, 127],
|
236
|
+
"steelblue" => [70, 130, 180],
|
237
|
+
"tan" => [210, 180, 140],
|
238
|
+
"teal" => [0, 128, 128],
|
239
|
+
"thistle" => [216, 191, 216],
|
240
|
+
"tomato" => [255, 99, 71],
|
241
|
+
"turquoise" => [64, 224, 208],
|
242
|
+
"violet" => [238, 130, 238],
|
243
|
+
"wheat" => [245, 222, 179],
|
244
|
+
"white" => [255, 255, 255],
|
245
|
+
"whitesmoke" => [245, 245, 245],
|
246
|
+
"yellow" => [255, 255, 0],
|
247
|
+
"yellowgreen" => [154, 205, 50],
|
248
|
+
}.freeze
|
249
|
+
|
99
250
|
# :call-seq:
|
100
251
|
# ColorSpace.device_color_from_specification(gray) => color
|
101
252
|
# ColorSpace.device_color_from_specification(r, g, b) => color
|
@@ -111,6 +262,10 @@ module HexaPDF
|
|
111
262
|
# * Three numeric arguments specify an RGB color (see DeviceRGB::Color).
|
112
263
|
# * A string in the format "RRGGBB" where "RR" is the hexadecimal number for the red, "GG"
|
113
264
|
# for the green and "BB" for the blue color value also specifies an RGB color.
|
265
|
+
# * As does a string in the format "RGB" where "RR", "GG" and "BB" would be used as the
|
266
|
+
# hexadecimal numbers for the red, green and blue color values of an RGB color.
|
267
|
+
# * Any other string is treated as a CSS Color Module Level 3 color name, see
|
268
|
+
# https://www.w3.org/TR/css-color-3/#svg-color.
|
114
269
|
# * Four numeric arguments specify a CMYK color (see DeviceCMYK::Color).
|
115
270
|
# * An array is treated as if its items were specified separately as arguments.
|
116
271
|
#
|
@@ -118,7 +273,18 @@ module HexaPDF
|
|
118
273
|
# values are first normalized - see DeviceGray#color, DeviceRGB#color and DeviceCMYK#color.
|
119
274
|
def self.device_color_from_specification(*spec)
|
120
275
|
spec.flatten!
|
121
|
-
|
276
|
+
first_item = spec[0]
|
277
|
+
if spec.length == 1 && first_item.kind_of?(String)
|
278
|
+
spec = if first_item.match?(/\A\h{6}\z/)
|
279
|
+
first_item.scan(/../).map!(&:hex)
|
280
|
+
elsif first_item.match?(/\A\h{3}\z/)
|
281
|
+
first_item.each_char.map {|x| (x*2).hex}
|
282
|
+
elsif CSS_COLOR_NAMES.key?(first_item)
|
283
|
+
CSS_COLOR_NAMES[first_item]
|
284
|
+
else
|
285
|
+
raise ArgumentError, "Given string is neither a hex color nor a color name"
|
286
|
+
end
|
287
|
+
end
|
122
288
|
GlobalConfiguration.constantize('color_space.map', for_components(spec)).new.color(*spec)
|
123
289
|
end
|
124
290
|
|
@@ -349,9 +349,30 @@ module HexaPDF
|
|
349
349
|
|
350
350
|
end
|
351
351
|
|
352
|
+
# Converter module for fields of type Integer.
|
353
|
+
module IntegerConverter
|
354
|
+
|
355
|
+
# This converter is usable if the +type+ is Integer.
|
356
|
+
def self.usable_for?(type)
|
357
|
+
type == Integer
|
358
|
+
end
|
359
|
+
|
360
|
+
# :nodoc:
|
361
|
+
def self.additional_types
|
362
|
+
end
|
363
|
+
|
364
|
+
# Converts a Float value into an Integer if the float is equal to its integer value. Otherwise
|
365
|
+
# returns +nil+
|
366
|
+
def self.convert(data, _type, _document)
|
367
|
+
return unless data.kind_of?(Float) && data == data.to_i
|
368
|
+
data.to_i
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
372
|
+
|
352
373
|
Field.converters.replace([FileSpecificationConverter, DictionaryConverter, ArrayConverter,
|
353
374
|
StringConverter, PDFByteStringConverter, DateConverter,
|
354
|
-
RectangleConverter])
|
375
|
+
RectangleConverter, IntegerConverter])
|
355
376
|
|
356
377
|
end
|
357
378
|
|
data/lib/hexapdf/parser.rb
CHANGED
@@ -165,7 +165,7 @@ module HexaPDF
|
|
165
165
|
else
|
166
166
|
0
|
167
167
|
end
|
168
|
-
@tokenizer.pos = pos + length
|
168
|
+
@tokenizer.pos = pos + length rescue pos
|
169
169
|
|
170
170
|
tok = @tokenizer.next_token
|
171
171
|
unless tok.kind_of?(Tokenizer::Token) && tok == 'endstream'
|
@@ -447,6 +447,15 @@ module HexaPDF
|
|
447
447
|
|
448
448
|
if !trailer || trailer.empty?
|
449
449
|
_, trailer = load_revision(startxref_offset) rescue nil
|
450
|
+
unless trailer
|
451
|
+
xref.each do |_oid, _gen, xref_entry|
|
452
|
+
obj, * = parse_indirect_object(xref_entry.pos) rescue nil
|
453
|
+
if obj.kind_of?(Hash) && obj[:Type] == :Catalog
|
454
|
+
trailer = {Root: HexaPDF::Reference.new(xref_entry.oid, xref_entry.gen)}
|
455
|
+
break
|
456
|
+
end
|
457
|
+
end
|
458
|
+
end
|
450
459
|
unless trailer
|
451
460
|
@in_reconstruct_revision = false
|
452
461
|
raise_malformed("Could not reconstruct malformed PDF because trailer was not found", pos: 0)
|
data/lib/hexapdf/tokenizer.rb
CHANGED
@@ -55,6 +55,9 @@ module HexaPDF
|
|
55
55
|
|
56
56
|
# This object is returned when there are no more tokens to read.
|
57
57
|
NO_MORE_TOKENS = ::Object.new
|
58
|
+
def NO_MORE_TOKENS.to_s
|
59
|
+
"EOS - no more tokens"
|
60
|
+
end
|
58
61
|
|
59
62
|
# Characters defined as whitespace.
|
60
63
|
#
|
@@ -384,7 +387,11 @@ module HexaPDF
|
|
384
387
|
result = []
|
385
388
|
while true
|
386
389
|
obj = next_object(allow_end_array_token: true)
|
387
|
-
|
390
|
+
if obj.equal?(TOKEN_ARRAY_END)
|
391
|
+
break
|
392
|
+
elsif obj.equal?(NO_MORE_TOKENS)
|
393
|
+
raise HexaPDF::MalformedPDFError.new("Unclosed array found", pos: pos)
|
394
|
+
end
|
388
395
|
result << obj
|
389
396
|
end
|
390
397
|
result
|
@@ -403,7 +410,8 @@ module HexaPDF
|
|
403
410
|
key = next_token
|
404
411
|
break if key.equal?(TOKEN_DICT_END)
|
405
412
|
unless key.kind_of?(Symbol)
|
406
|
-
raise HexaPDF::MalformedPDFError.new("Dictionary keys must be PDF name objects
|
413
|
+
raise HexaPDF::MalformedPDFError.new("Dictionary keys must be PDF name objects, " \
|
414
|
+
"found '#{key}'", pos: pos)
|
407
415
|
end
|
408
416
|
|
409
417
|
val = next_object
|
data/lib/hexapdf/version.rb
CHANGED
@@ -161,6 +161,21 @@ module CommonTokenizerTests
|
|
161
161
|
assert_raises(HexaPDF::MalformedPDFError) { @tokenizer.next_object }
|
162
162
|
end
|
163
163
|
|
164
|
+
it "next_object: fails for an array without closing bracket, encountering EOS" do
|
165
|
+
create_tokenizer("[1 2")
|
166
|
+
exception = assert_raises(HexaPDF::MalformedPDFError) { @tokenizer.next_object }
|
167
|
+
assert_match(/Unclosed array found/, exception.message)
|
168
|
+
end
|
169
|
+
|
170
|
+
it "next_object: fails for a dictionary without closing bracket, encountering EOS" do
|
171
|
+
create_tokenizer("<</Name 5")
|
172
|
+
exception = assert_raises(HexaPDF::MalformedPDFError) { @tokenizer.next_object }
|
173
|
+
assert_match(/must be PDF name objects.*EOS/, exception.message)
|
174
|
+
create_tokenizer("<</Name 5 /Other")
|
175
|
+
exception = assert_raises(HexaPDF::MalformedPDFError) { @tokenizer.next_object }
|
176
|
+
assert_match(/must be PDF name objects.*EOS/, exception.message)
|
177
|
+
end
|
178
|
+
|
164
179
|
it "returns the correct position on operations" do
|
165
180
|
create_tokenizer("hallo du" << " " * 50000 << "hallo du")
|
166
181
|
@tokenizer.next_token
|
@@ -73,10 +73,18 @@ describe HexaPDF::Content::ColorSpace do
|
|
73
73
|
assert_equal([0.2, 1, 0], @class.device_color_from_specification(51, 255, 0).components)
|
74
74
|
end
|
75
75
|
|
76
|
-
it "works for RGB values given as string" do
|
76
|
+
it "works for RGB values given as full hex string" do
|
77
77
|
assert_equal([0.2, 1, 0], @class.device_color_from_specification("33FF00").components)
|
78
78
|
end
|
79
79
|
|
80
|
+
it "works for RGB values given as half hex string" do
|
81
|
+
assert_equal([0.2, 1, 0], @class.device_color_from_specification("3F0").components)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "works for RGB values given as color names" do
|
85
|
+
assert_equal([0, 0, 1], @class.device_color_from_specification("blue").components)
|
86
|
+
end
|
87
|
+
|
80
88
|
it "works for CMYK values" do
|
81
89
|
assert_equal([0.51, 0.9, 1, 0.5],
|
82
90
|
@class.device_color_from_specification(51, 90, 100, 50).components)
|
@@ -85,6 +93,10 @@ describe HexaPDF::Content::ColorSpace do
|
|
85
93
|
it "works when an array is given" do
|
86
94
|
assert_equal([0.2], @class.device_color_from_specification([51]).components)
|
87
95
|
end
|
96
|
+
|
97
|
+
it "raises an error if an invalid color string is given" do
|
98
|
+
assert_raises(ArgumentError) { @class.device_color_from_specification("unknown") }
|
99
|
+
end
|
88
100
|
end
|
89
101
|
|
90
102
|
it "returns a device color object for prenormalized color values" do
|
@@ -242,4 +242,19 @@ describe HexaPDF::DictionaryFields do
|
|
242
242
|
doc.verify
|
243
243
|
end
|
244
244
|
end
|
245
|
+
|
246
|
+
describe "IntegerConverter" do
|
247
|
+
before do
|
248
|
+
@field = self.class::Field.new(Integer)
|
249
|
+
end
|
250
|
+
|
251
|
+
it "no additional field types allowed" do
|
252
|
+
assert_equal([Integer], @field.type)
|
253
|
+
end
|
254
|
+
|
255
|
+
it "allows conversion to an Integer from an equivalent Float value" do
|
256
|
+
refute_same(3, @field.convert(3.1, nil))
|
257
|
+
assert_same(3, @field.convert(3.0, nil))
|
258
|
+
end
|
259
|
+
end
|
245
260
|
end
|
data/test/hexapdf/test_parser.rb
CHANGED
@@ -113,13 +113,21 @@ describe HexaPDF::Parser do
|
|
113
113
|
assert_nil(object)
|
114
114
|
end
|
115
115
|
|
116
|
-
it "recovers from
|
116
|
+
it "recovers from a stream length value that doesn't reflect the correct length" do
|
117
117
|
create_parser("1 0 obj<</Length 4>> stream\n12endstream endobj")
|
118
118
|
obj, _, _, stream = @parser.parse_indirect_object
|
119
119
|
assert_equal(2, obj[:Length])
|
120
120
|
assert_equal('12', TestHelper.collector(stream.fiber))
|
121
121
|
end
|
122
122
|
|
123
|
+
it "recovers from an invalid stream length value" do
|
124
|
+
create_parser("1 0 obj<</Length 2 0 R>> stream\n12endstream endobj")
|
125
|
+
@document.add([5], oid: 2)
|
126
|
+
obj, _, _, stream = @parser.parse_indirect_object
|
127
|
+
assert_equal(2, obj[:Length])
|
128
|
+
assert_equal('12', TestHelper.collector(stream.fiber))
|
129
|
+
end
|
130
|
+
|
123
131
|
it "works even if the keyword endobj is missing or mangled" do
|
124
132
|
create_parser("1 0 obj<</Length 4>>5")
|
125
133
|
object, * = @parser.parse_indirect_object
|
@@ -619,7 +627,12 @@ describe HexaPDF::Parser do
|
|
619
627
|
assert_equal({Size: 1}, @parser.reconstructed_revision.trailer.value)
|
620
628
|
end
|
621
629
|
|
622
|
-
it "
|
630
|
+
it "constructs a trailer with a /Root entry if no valid trailer was found" do
|
631
|
+
create_parser("1 0 obj\n<</Type /Catalog/Pages 2 0 R>>\nendobj\nxref trailer <</Size 1/Prev 5\n%%EOF")
|
632
|
+
assert_equal({Root: HexaPDF::Reference.new(1, 0)}, @parser.reconstructed_revision.trailer.value)
|
633
|
+
end
|
634
|
+
|
635
|
+
it "fails if no valid trailer is found and couldn't be constructed" do
|
623
636
|
create_parser("1 0 obj\n5\nendobj\nquack trailer <</Size 1>>\nstartxref\n22\n%%EOF")
|
624
637
|
assert_raises(HexaPDF::MalformedPDFError) { @parser.reconstructed_revision.trailer }
|
625
638
|
end
|
data/test/hexapdf/test_writer.rb
CHANGED
@@ -40,7 +40,7 @@ describe HexaPDF::Writer do
|
|
40
40
|
219
|
41
41
|
%%EOF
|
42
42
|
3 0 obj
|
43
|
-
<</Producer(HexaPDF version 0.
|
43
|
+
<</Producer(HexaPDF version 0.16.0)>>
|
44
44
|
endobj
|
45
45
|
xref
|
46
46
|
3 1
|
@@ -72,7 +72,7 @@ describe HexaPDF::Writer do
|
|
72
72
|
141
|
73
73
|
%%EOF
|
74
74
|
6 0 obj
|
75
|
-
<</Producer(HexaPDF version 0.
|
75
|
+
<</Producer(HexaPDF version 0.16.0)>>
|
76
76
|
endobj
|
77
77
|
2 0 obj
|
78
78
|
<</Length 10>>stream
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hexapdf
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Leitner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cmdparse
|