hexapdf 0.9.3 → 0.10.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 +35 -0
- data/CONTRIBUTERS +2 -1
- data/VERSION +1 -1
- data/lib/hexapdf/cli/command.rb +9 -5
- data/lib/hexapdf/cli/images.rb +68 -13
- data/lib/hexapdf/cli/inspect.rb +201 -71
- data/lib/hexapdf/content/canvas.rb +1 -1
- data/lib/hexapdf/dictionary.rb +15 -1
- data/lib/hexapdf/dictionary_fields.rb +5 -4
- data/lib/hexapdf/document.rb +15 -6
- data/lib/hexapdf/encryption/security_handler.rb +3 -2
- data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +165 -165
- data/lib/hexapdf/font/true_type_wrapper.rb +2 -2
- data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
- data/lib/hexapdf/image_loader/jpeg.rb +13 -11
- data/lib/hexapdf/reference.rb +5 -0
- data/lib/hexapdf/revision.rb +14 -0
- data/lib/hexapdf/serializer.rb +6 -6
- data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
- data/lib/hexapdf/type/image.rb +3 -1
- data/lib/hexapdf/version.rb +1 -1
- data/lib/hexapdf/xref_section.rb +8 -0
- data/man/man1/hexapdf.1 +88 -20
- data/test/data/images/truecolour-alpha-8bit.png +0 -0
- data/test/data/images/ycck.jpg +0 -0
- data/test/hexapdf/content/test_canvas.rb +2 -2
- data/test/hexapdf/document/test_images.rb +7 -5
- data/test/hexapdf/encryption/test_security_handler.rb +13 -0
- data/test/hexapdf/image_loader/test_jpeg.rb +10 -0
- data/test/hexapdf/image_loader/test_png.rb +3 -2
- data/test/hexapdf/test_dictionary.rb +9 -0
- data/test/hexapdf/test_dictionary_fields.rb +15 -0
- data/test/hexapdf/test_document.rb +5 -2
- data/test/hexapdf/test_reference.rb +4 -0
- data/test/hexapdf/test_revision.rb +12 -0
- data/test/hexapdf/test_writer.rb +5 -5
- data/test/hexapdf/test_xref_section.rb +11 -0
- data/test/hexapdf/type/test_form.rb +1 -1
- data/test/hexapdf/type/test_image.rb +28 -19
- metadata +3 -2
@@ -237,9 +237,9 @@ module HexaPDF
|
|
237
237
|
end
|
238
238
|
|
239
239
|
fd.flag(:fixed_pitch) if @wrapped_font[:post].is_fixed_pitch? ||
|
240
|
-
|
240
|
+
@wrapped_font[:hhea].num_of_long_hor_metrics == 1
|
241
241
|
fd.flag(:italic) if @wrapped_font[:'OS/2'].selection_include?(:italic) ||
|
242
|
-
|
242
|
+
@wrapped_font[:'OS/2'].selection_include?(:oblique)
|
243
243
|
fd.flag(:symbolic)
|
244
244
|
|
245
245
|
cid_font = @document.add(Type: :Font, Subtype: :CIDFontType2,
|
@@ -128,7 +128,7 @@ module HexaPDF
|
|
128
128
|
when :CharacterSet then @metrics.character_set = parse_string
|
129
129
|
when :EncodingScheme then @metrics.encoding_scheme = parse_string
|
130
130
|
when :Weight then @metrics.weight = parse_string
|
131
|
-
when :FontBBox
|
131
|
+
when :FontBBox
|
132
132
|
@metrics.bounding_box = [parse_number, parse_number, parse_number, parse_number]
|
133
133
|
when :CapHeight then @metrics.cap_height = parse_number
|
134
134
|
when :XHeight then @metrics.x_height = parse_number
|
@@ -41,7 +41,7 @@ module HexaPDF
|
|
41
41
|
|
42
42
|
# This module is used for loading images in the JPEG format from files or IO streams.
|
43
43
|
#
|
44
|
-
# See: PDF1.7 s7.4.8, ITU T.81 Annex B
|
44
|
+
# See: PDF1.7 s7.4.8, ITU T.81 Annex B, ITU T.872
|
45
45
|
module JPEG
|
46
46
|
|
47
47
|
# The magic marker that tells us if the file/IO contains an image in JPEG format.
|
@@ -56,13 +56,13 @@ module HexaPDF
|
|
56
56
|
0xC0, 0xC1, 0xC2, 0xC3, 0xC5, 0xC6, 0xC7, 0xC9, 0xCA, 0xCB, 0xCD, 0xCE, 0xCF
|
57
57
|
].freeze
|
58
58
|
|
59
|
-
# Adobe uses the marker 0xEE (APPE) for its purposes. We need to use it for
|
60
|
-
# whether
|
61
|
-
|
62
|
-
|
63
|
-
#
|
64
|
-
#
|
65
|
-
|
59
|
+
# Adobe uses the marker 0xEE (APPE or APP14) for its purposes. We need to use it for
|
60
|
+
# determinig whether we have a CMYK or YCCK image.
|
61
|
+
APP14_MARKER = 0xEE
|
62
|
+
|
63
|
+
# Value of the 12th byte in an APP14 marker specifying that the image uses CMYK color
|
64
|
+
# encoding, with all four colors complemented.
|
65
|
+
APP14_TRANSFORM_CMYK = 0
|
66
66
|
|
67
67
|
# End-of-image marker
|
68
68
|
EOI_MARKER = 0xD9
|
@@ -121,9 +121,11 @@ module HexaPDF
|
|
121
121
|
# but those shouldn't appear here)
|
122
122
|
length = io.read(2).unpack1('n')
|
123
123
|
|
124
|
-
|
125
|
-
|
126
|
-
|
124
|
+
# According to T.872 6.1 and 6.5.3, if this marker is present, we need to use it for
|
125
|
+
# correctly determining whether complemented CMYK or YCCK is used
|
126
|
+
if code1 == APP14_MARKER
|
127
|
+
io.seek(length - 3, IO::SEEK_CUR)
|
128
|
+
invert_colors = true if io.getbyte == APP14_TRANSFORM_CMYK
|
127
129
|
next
|
128
130
|
elsif !SOF_MARKERS.include?(code1)
|
129
131
|
io.seek(length - 2, IO::SEEK_CUR)
|
data/lib/hexapdf/reference.rb
CHANGED
data/lib/hexapdf/revision.rb
CHANGED
@@ -89,6 +89,20 @@ module HexaPDF
|
|
89
89
|
((a = @xref_section.max_oid) < (b = @objects.max_oid) ? b : a) + 1
|
90
90
|
end
|
91
91
|
|
92
|
+
# :call-seq:
|
93
|
+
# revision.xref(ref) -> xref_entry or nil
|
94
|
+
# revision.xref(oid) -> xref_entry or nil
|
95
|
+
#
|
96
|
+
# Returns an XRefSection::Entry structure for the given reference or object number if it is
|
97
|
+
# available, or +nil+ otherwise.
|
98
|
+
def xref(ref)
|
99
|
+
if ref.respond_to?(:oid)
|
100
|
+
@xref_section[ref.oid, ref.gen]
|
101
|
+
else
|
102
|
+
@xref_section[ref, nil]
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
92
106
|
# :call-seq:
|
93
107
|
# revision.object(ref) -> obj or nil
|
94
108
|
# revision.object(oid) -> obj or nil
|
data/lib/hexapdf/serializer.rb
CHANGED
@@ -186,7 +186,7 @@ module HexaPDF
|
|
186
186
|
NAME_CACHE[obj] ||=
|
187
187
|
begin
|
188
188
|
str = obj.to_s.force_encoding(Encoding::BINARY)
|
189
|
-
str.gsub!(NAME_REGEXP
|
189
|
+
str.gsub!(NAME_REGEXP, NAME_SUBSTS)
|
190
190
|
"/#{str}"
|
191
191
|
end
|
192
192
|
end
|
@@ -203,7 +203,7 @@ module HexaPDF
|
|
203
203
|
while index < obj.size
|
204
204
|
tmp = __serialize(obj[index])
|
205
205
|
str << " " unless BYTE_IS_DELIMITER[tmp.getbyte(0)] ||
|
206
|
-
|
206
|
+
BYTE_IS_DELIMITER[str.getbyte(-1)]
|
207
207
|
str << tmp
|
208
208
|
index += 1
|
209
209
|
end
|
@@ -217,10 +217,10 @@ module HexaPDF
|
|
217
217
|
str = +"<<"
|
218
218
|
obj.each do |k, v|
|
219
219
|
next if v.nil? || (v.respond_to?(:null?) && v.null?)
|
220
|
-
str <<
|
220
|
+
str << serialize_symbol(k)
|
221
221
|
tmp = __serialize(v)
|
222
222
|
str << " " unless BYTE_IS_DELIMITER[tmp.getbyte(0)] ||
|
223
|
-
|
223
|
+
BYTE_IS_DELIMITER[str.getbyte(-1)]
|
224
224
|
str << tmp
|
225
225
|
end
|
226
226
|
str << ">>"
|
@@ -311,7 +311,7 @@ module HexaPDF
|
|
311
311
|
|
312
312
|
if @io && fiber.respond_to?(:length) && fiber.length >= 0
|
313
313
|
obj.value[:Length] = fiber.length
|
314
|
-
@io <<
|
314
|
+
@io << serialize_hash(obj.value)
|
315
315
|
@io << "stream\n"
|
316
316
|
while fiber.alive? && (data = fiber.resume)
|
317
317
|
@io << data.freeze
|
@@ -323,7 +323,7 @@ module HexaPDF
|
|
323
323
|
data = Filter.string_from_source(fiber)
|
324
324
|
obj.value[:Length] = data.size
|
325
325
|
|
326
|
-
str =
|
326
|
+
str = serialize_hash(obj.value)
|
327
327
|
str << "stream\n"
|
328
328
|
str << data
|
329
329
|
str << "\nendstream"
|
@@ -47,7 +47,7 @@ module HexaPDF
|
|
47
47
|
class MarkupAnnotation < Annotation
|
48
48
|
|
49
49
|
define_field :T, type: String, version: '1.1'
|
50
|
-
define_field :Popup, type: :
|
50
|
+
define_field :Popup, type: :Annot, version: '1.3'
|
51
51
|
define_field :CA, type: Numeric, default: 1.0, version: '1.4'
|
52
52
|
define_field :RC, type: [Stream, String], version: '1.5'
|
53
53
|
define_field :CreationDate, type: PDFDate, version: '1.5'
|
data/lib/hexapdf/type/image.rb
CHANGED
@@ -253,8 +253,10 @@ module HexaPDF
|
|
253
253
|
if filter == :FlateDecode && self[:DecodeParms] && self[:DecodeParms][:Predictor].to_i >= 10
|
254
254
|
data = stream_source
|
255
255
|
else
|
256
|
+
colors = (color_type == ImageLoader::PNG::INDEXED ? 1 : info.components)
|
256
257
|
flate_decode = config.constantize('filter.map', :FlateDecode)
|
257
|
-
data = flate_decode.encoder(stream_decoder, Predictor: 15,
|
258
|
+
data = flate_decode.encoder(stream_decoder, Predictor: 15,
|
259
|
+
Colors: colors, Columns: info.width,
|
258
260
|
BitsPerComponent: info.bits_per_component)
|
259
261
|
end
|
260
262
|
io << png_chunk('IDAT', Filter.string_from_source(data))
|
data/lib/hexapdf/version.rb
CHANGED
data/lib/hexapdf/xref_section.rb
CHANGED
@@ -82,6 +82,14 @@ module HexaPDF
|
|
82
82
|
def compressed?
|
83
83
|
type == :compressed
|
84
84
|
end
|
85
|
+
|
86
|
+
def to_s
|
87
|
+
case type
|
88
|
+
when :free then "xref #{oid},#{gen} type=free"
|
89
|
+
when :in_use then "xref #{oid},#{gen} type=normal pos=#{pos}"
|
90
|
+
when :compressed then "xref #{oid},#{gen} type=compressed objstm=#{objstm},0 index=#{pos}"
|
91
|
+
end
|
92
|
+
end
|
85
93
|
end
|
86
94
|
|
87
95
|
# Creates an in-use cross-reference entry. See Entry for details on the arguments.
|
data/man/man1/hexapdf.1
CHANGED
@@ -189,7 +189,9 @@ This command prints the application help if no arguments are given\. If one or m
|
|
189
189
|
.SS "images"
|
190
190
|
Synopsis: \fBimages\fP [\fBOPTIONS\fP] \fIPDF\fP
|
191
191
|
.P
|
192
|
-
This command extracts images from the \fIPDF\fP\&\. If the \fB\-\-extract\fP option is not specified, the images are listed with their indices and additional information, sorted by page number\.
|
192
|
+
This command extracts images from the \fIPDF\fP\&\. If the \fB\-\-extract\fP option is not specified, the images are listed with their indices and additional information, sorted by page number\. Note that if an image is used multiple times on a page, only the first occurence of it will be included\.
|
193
|
+
.P
|
194
|
+
The \fB\-\-extract\fP option can then be used to extract one or more images, saving them to files called \fBPREFIX\-N\.EXT\fP where the prefix can be set via \fB\-\-prefix\fP, \fIN\fP is the image index and \fIEXT\fP is either png, jpg or jpx\.
|
193
195
|
.TP
|
194
196
|
\fB\-e\fP [\fIA,B,C,\.\.\.\fP], \fB\-\-extract\fP [\fIA,B,C,\.\.\.\fP]
|
195
197
|
The indices of the images that should be extracted\. Use \fI0\fP or no value to extract all images\.
|
@@ -230,6 +232,15 @@ The number of color components\.
|
|
230
232
|
\fBbpc\fP
|
231
233
|
The number of bits per color component\.
|
232
234
|
.TP
|
235
|
+
\fBx\-ppi\fP
|
236
|
+
The pixels per inch (PPI) of the x\-direction of the image, as found on the page\.
|
237
|
+
.TP
|
238
|
+
\fBy\-ppi\fP
|
239
|
+
The pixels per inch (PPI) of the y\-direction of the image, as found on the page\.
|
240
|
+
.TP
|
241
|
+
\fBsize\fP
|
242
|
+
The file size of the image as stored in the PDF\.
|
243
|
+
.TP
|
233
244
|
\fBtype\fP
|
234
245
|
The image type\. Either jpg (JPEG), jp2 (JPEG2000), ccitt (CCITT Group 3 or 4 Fax), jbig2 (JBIG2) or png (PNG)\.
|
235
246
|
.TP
|
@@ -244,32 +255,87 @@ This command reads the \fIFILE\fP and shows general information about it, like a
|
|
244
255
|
\fB\-p\fP \fIPASSWORD\fP, \fB\-\-password\fP \fIPASSWORD\fP
|
245
256
|
The password to decrypt the PDF \fIFILE\fP\&\. Use \fB\-\fP for \fIPASSWORD\fP for reading it from standard input\.
|
246
257
|
.SS "inspect"
|
247
|
-
Synopsis: \fBinspect\fP [\fBOPTIONS\fP] \fIFILE\fP
|
258
|
+
Synopsis: \fBinspect\fP [\fBOPTIONS\fP] \fIFILE\fP \fI[[CMD [ARGS]]\.\.\.]\fP
|
248
259
|
.P
|
249
260
|
This command is useful when one needs to inspect the internal object structure or a stream of a PDF file\.
|
250
261
|
.P
|
251
|
-
If no
|
262
|
+
If no arguments are given, the interactive mode is started\. This interactive mode allows you to execute inspection commands without re\-parsing the PDF file, leading to better performance for big PDF files\.
|
263
|
+
.P
|
264
|
+
Otherwise the arguments are interpreted as interactive mode commands and executed\. It is possible to specify more than one command in this way by separating them with semicolons, or whitespace in case the number of command arguments is fixed\.
|
252
265
|
.TP
|
253
|
-
\fB\-\-
|
254
|
-
|
266
|
+
\fB\-p\fP \fIPASSWORD\fP, \fB\-\-password\fP \fIPASSWORD\fP
|
267
|
+
The password to decrypt the PDF \fIFILE\fP\&\. Use \fB\-\fP for \fIPASSWORD\fP for reading it from standard input\.
|
268
|
+
.P
|
269
|
+
If an interactive mode command or argument is \fBOID[,GEN]\fP, object and generation numbers are expected\. The generation number defaults to 0 if not given\. PDF objects are always shown in the native PDF syntax\.
|
270
|
+
.P
|
271
|
+
The available commands are:
|
255
272
|
.TP
|
256
|
-
\
|
257
|
-
Print the
|
273
|
+
\fBOID[,GEN] | o[bject] OID[,GEN]\fP
|
274
|
+
Print the given indirect object\.
|
258
275
|
.TP
|
259
|
-
\
|
260
|
-
|
276
|
+
\fBr[ecursive] OID[,GEN]\fP
|
277
|
+
Print the given indirect object recursively\. This means that all references found in the object are resolved and the resulting objects themselves recursively printed\.
|
278
|
+
.RS
|
279
|
+
.P
|
280
|
+
To make it easier to compare such structures between PDF files, the entries of dictionaries are printed in sorted order and the original references are replaced by custom ones\. Once an indirect object is first encountered, it is preceeded by either \fB{obj INDEX}\fP or \fB{obj page PAGEINDEX}\fP where \fBINDEX\fP is an increasing number and \fBPAGEINDEX\fP is the index of the page\. Later references are replaced by \fB{ref INDEX}\fP and \fB{ref page PAGEINDEX}\fP respectively\.
|
281
|
+
.P
|
282
|
+
Here is a simplified example output:
|
283
|
+
.sp
|
284
|
+
.RS 4
|
285
|
+
.EX
|
286
|
+
<<
|
287
|
+
/Info {obj 1} <<
|
288
|
+
/Producer (HexaPDF version 0\.9\.3)
|
289
|
+
>>
|
290
|
+
/Root {obj 2} <<
|
291
|
+
/Pages {obj 3} <<
|
292
|
+
/Count 1
|
293
|
+
/Kids [{obj page 1} <<
|
294
|
+
/MediaBox [0 0 595 842 ]
|
295
|
+
/Parent {ref 3}
|
296
|
+
/Type /Page
|
297
|
+
>> ]
|
298
|
+
/Type /Pages
|
299
|
+
>>
|
300
|
+
/Type /Catalog
|
301
|
+
>>
|
302
|
+
/Size 4
|
303
|
+
>>
|
304
|
+
.EE
|
305
|
+
.RE
|
306
|
+
.P
|
307
|
+
On line 2 the indirect object for the key \fB/Info\fP is shown, preceeded by the custom reference\. On line 8 is an example for a page object with the special reference key\. And on line 10 there is a back reference to the object with index 3 which is started on line 6\.
|
308
|
+
.RE
|
261
309
|
.TP
|
262
|
-
\
|
263
|
-
|
310
|
+
\fBs[tream] OID[,GEN]\fP
|
311
|
+
Print the filtered stream, i\.e\. the stream with all filters applied\. This is useful, for example, to view the contents of content streams\.
|
264
312
|
.TP
|
265
|
-
\
|
266
|
-
|
313
|
+
\fBraw[\-stream] OID[,GEN]\fP
|
314
|
+
Print the raw stream, i\.e\. the stream as it appears in the file\. This is useful, for example, to extract streams into files\.
|
267
315
|
.TP
|
268
|
-
\
|
269
|
-
|
316
|
+
\fBx[ref] OID[,GEN]\fP
|
317
|
+
Print the cross\-reference entry for the given indirect object\.
|
270
318
|
.TP
|
271
|
-
\
|
272
|
-
|
319
|
+
\fBc[atalog]\fP
|
320
|
+
Print the catalog dictionary\.
|
321
|
+
.TP
|
322
|
+
\fBt[railer]\fP
|
323
|
+
Print the trailer dictionary\.
|
324
|
+
.TP
|
325
|
+
\fBp[ages] [RANGE]\fP
|
326
|
+
Print the pages with their object and generation numbers and their associated content streams\. If a range is specified, only those pages are listed\. See the \fBPAGES SPECIFICATION\fP below for details on the allowed format of \fIPAGES\fP\&\.
|
327
|
+
.TP
|
328
|
+
\fBpc | page\-count\fP
|
329
|
+
Print the number of pages\.
|
330
|
+
.TP
|
331
|
+
\fBsearch REGEXP\fP
|
332
|
+
Print all objects matching the pattern\. Each object is preceeded by \fBobj OID GEN\fP and followed by \fBendobj\fP to make it easier to further explore the data\.
|
333
|
+
.TP
|
334
|
+
\fBh[elp]\fP
|
335
|
+
Print the available commands with a short description\.
|
336
|
+
.TP
|
337
|
+
\fBq[uit]Quit\fP
|
338
|
+
Quit the interactive mode\.
|
273
339
|
.SS "merge"
|
274
340
|
Synopsis: \fBmerge\fP [\fBOPTIONS\fP] { \fIINPUT\fP | \fB\-\-empty\fP } [\fIINPUT\fP]\.\.\. \fIOUTPUT\fP
|
275
341
|
.P
|
@@ -426,11 +492,13 @@ Image info and extraction: The first command lists the images of the \fBinput\.p
|
|
426
492
|
.P
|
427
493
|
File information: Show general information about the PDF file, like PDF version, number of pages, creator, creation date and encryption related information\.
|
428
494
|
.SS "inspect"
|
429
|
-
\fBhexapdf inspect input\.pdf\fP
|
430
|
-
.br
|
431
495
|
\fBhexapdf inspect input\.pdf \-o 3\fP
|
432
496
|
.P
|
433
|
-
|
497
|
+
Show the object with the object number 3 of the given PDF file\.
|
498
|
+
.P
|
499
|
+
\fBhexapdf inspect input\.pdf\fP
|
500
|
+
.P
|
501
|
+
Start the interactive inspection mode\.
|
434
502
|
.SS "batch"
|
435
503
|
\fBhexapdf batch \'info {}\' input1\.pdf input2\.pdf input3\.pdf\fP
|
436
504
|
.P
|
Binary file
|
Binary file
|
@@ -777,9 +777,9 @@ describe HexaPDF::Content::Canvas do
|
|
777
777
|
|
778
778
|
describe "xobject" do
|
779
779
|
before do
|
780
|
-
@image = @doc.add(Subtype: :Image, Width: 10, Height: 5)
|
780
|
+
@image = @doc.add(Type: :XObject, Subtype: :Image, Width: 10, Height: 5)
|
781
781
|
@image.source_path = File.join(TEST_DATA_DIR, 'images', 'gray.jpg')
|
782
|
-
@form = @doc.add(Subtype: :Form, BBox: [100, 50, 200, 100])
|
782
|
+
@form = @doc.add(Type: :XObject, Subtype: :Form, BBox: [100, 50, 200, 100])
|
783
783
|
end
|
784
784
|
|
785
785
|
it "can use any xobject specified via a filename" do
|
@@ -16,7 +16,7 @@ describe HexaPDF::Document::Images do
|
|
16
16
|
@loader.define_singleton_method(:handles?) {|*| true }
|
17
17
|
@loader.define_singleton_method(:load) do |doc, s|
|
18
18
|
s = HexaPDF::StreamData.new(s) if s.kind_of?(IO)
|
19
|
-
doc.add({Subtype: :Image}, stream: s)
|
19
|
+
doc.add({Type: :XObject, Subtype: :Image}, stream: s)
|
20
20
|
end
|
21
21
|
@doc.config['image_loader'].unshift(@loader)
|
22
22
|
end
|
@@ -60,10 +60,12 @@ describe HexaPDF::Document::Images do
|
|
60
60
|
it "iterates over all non-mask images" do
|
61
61
|
@doc.add(5)
|
62
62
|
images = []
|
63
|
-
images << @doc.add(Subtype: :Image)
|
64
|
-
images << @doc.add(Subtype: :Image, Mask: [5, 6])
|
65
|
-
images << @doc.add(
|
66
|
-
|
63
|
+
images << @doc.add(Type: :XObject, Subtype: :Image)
|
64
|
+
images << @doc.add(Type: :XObject, Subtype: :Image, Mask: [5, 6])
|
65
|
+
images << @doc.add(Type: :XObject, Subtype: :Image,
|
66
|
+
Mask: @doc.add(Type: :XObject, Subtype: :Image))
|
67
|
+
images << @doc.add(Type: :XObject, Subtype: :Image,
|
68
|
+
SMask: @doc.add(Type: :XObject, Subtype: :Image))
|
67
69
|
assert_equal(images.sort, @doc.images.to_a.sort)
|
68
70
|
end
|
69
71
|
end
|
@@ -298,6 +298,12 @@ describe HexaPDF::Encryption::SecurityHandler do
|
|
298
298
|
assert_equal(@encrypted, @handler.decrypt(@obj)[:Key])
|
299
299
|
end
|
300
300
|
|
301
|
+
it "doesn't decrypt the /Contents of a signature dictionary" do
|
302
|
+
@obj[:Type] = :Sig
|
303
|
+
@obj[:Contents] = "test"
|
304
|
+
assert_equal("test", @handler.decrypt(@obj)[:Contents])
|
305
|
+
end
|
306
|
+
|
301
307
|
it "fails if V < 5 and the object number changes" do
|
302
308
|
@obj.oid = 55
|
303
309
|
@handler.decrypt(@obj)
|
@@ -332,6 +338,13 @@ describe HexaPDF::Encryption::SecurityHandler do
|
|
332
338
|
@stream[:Type] = :XRef
|
333
339
|
assert_equal('string', @handler.encrypt_stream(@stream).resume)
|
334
340
|
end
|
341
|
+
|
342
|
+
it "doesn't encrypt the /Contents key of signature dictionaries" do
|
343
|
+
@obj[:Type] = :Sig
|
344
|
+
@obj[:Contents] = "test"
|
345
|
+
refute_equal('test', @handler.encrypt_string("test", @obj))
|
346
|
+
assert_equal('test', @handler.encrypt_string(@obj[:Contents], @obj))
|
347
|
+
end
|
335
348
|
end
|
336
349
|
|
337
350
|
it "works correctly with different decryption and encryption handlers" do
|
@@ -66,6 +66,16 @@ describe HexaPDF::ImageLoader::JPEG do
|
|
66
66
|
assert_equal(File.binread(jpeg), image.stream)
|
67
67
|
end
|
68
68
|
|
69
|
+
it "works for a YCCK jpeg" do
|
70
|
+
jpeg = @images.grep(/ycck\.jpg/).first
|
71
|
+
image = @loader.load(@doc, jpeg)
|
72
|
+
assert_equal(5, image[:Width])
|
73
|
+
assert_equal(5, image[:Height])
|
74
|
+
assert_equal(:DeviceCMYK, image[:ColorSpace])
|
75
|
+
refute(image.key?(:Decode))
|
76
|
+
assert_equal(File.binread(jpeg), image.stream)
|
77
|
+
end
|
78
|
+
|
69
79
|
it "fails if the JPEG is corrupt" do
|
70
80
|
exp = assert_raises(HexaPDF::Error) do
|
71
81
|
@loader.load(@doc, StringIO.new("some non JPEG data"))
|
@@ -206,8 +206,9 @@ describe HexaPDF::ImageLoader::PNG do
|
|
206
206
|
end
|
207
207
|
|
208
208
|
it "works for a true color 8-bit png with alpha" do
|
209
|
-
|
210
|
-
|
209
|
+
png_data = File.binread(@images.grep(/truecolour-alpha-8bit\.png/).first)
|
210
|
+
png_data[33, 0] = [0, "tRNS", 0].pack('NA4N') # add invalid tRNS chunk
|
211
|
+
image = @loader.load(@doc, StringIO.new(png_data))
|
211
212
|
data = [[12, 92, 146, 80, 136, 175, 167, 193, 213, 97, 175, 101, 38, 113, 50],
|
212
213
|
[12, 92, 146, 81, 137, 176, 168, 194, 214, 97, 175, 101, 38, 113, 49],
|
213
214
|
[12, 92, 146, 81, 137, 176, 169, 195, 214, 96, 175, 101, 37, 113, 49],
|
@@ -230,6 +230,15 @@ describe HexaPDF::Dictionary do
|
|
230
230
|
|
231
231
|
@obj.value[:Inherited] = Class.new(Array).new([5])
|
232
232
|
assert(@obj.validate(auto_correct: false))
|
233
|
+
|
234
|
+
@test_class.define_field(:StringField, type: String)
|
235
|
+
@test_class.define_field(:NameField, type: Symbol)
|
236
|
+
@obj.value[:StringField] = :symbol
|
237
|
+
refute(@obj.validate(auto_correct: false))
|
238
|
+
assert(@obj.validate(auto_correct: true))
|
239
|
+
@obj.value[:NameField] = "string"
|
240
|
+
assert(@obj.validate(auto_correct: true))
|
241
|
+
assert(@obj.validate(auto_correct: true))
|
233
242
|
end
|
234
243
|
|
235
244
|
it "checks whether a field needs to be indirect w/wo auto_correct" do
|