hexapdf 0.9.3 → 0.10.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.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
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'test_helper'
|
4
4
|
require 'hexapdf/dictionary_fields'
|
5
5
|
require 'hexapdf/dictionary'
|
6
|
+
require 'hexapdf/stream'
|
6
7
|
require 'hexapdf/type'
|
7
8
|
|
8
9
|
describe HexaPDF::DictionaryFields do
|
@@ -74,6 +75,20 @@ describe HexaPDF::DictionaryFields do
|
|
74
75
|
@doc.verify
|
75
76
|
end
|
76
77
|
|
78
|
+
it "allows conversion from an HexaPDF::Dictionary to a Stream if stream data is set" do
|
79
|
+
@field = self.class::Field.new(HexaPDF::Stream)
|
80
|
+
@doc.expect(:wrap, :data, [HexaPDF::Dictionary, Hash])
|
81
|
+
data = HexaPDF::PDFData.new({}, 0, 0, "")
|
82
|
+
@field.convert(HexaPDF::Dictionary.new(data), @doc)
|
83
|
+
@doc.verify
|
84
|
+
end
|
85
|
+
|
86
|
+
it "doesn't allow conversion to a Stream subclass from Hash or Dictionary" do
|
87
|
+
@field = self.class::Field.new(HexaPDF::Stream)
|
88
|
+
refute(@field.convert({}, @doc))
|
89
|
+
refute(@field.convert(HexaPDF::Dictionary.new(Test: :value), @doc))
|
90
|
+
end
|
91
|
+
|
77
92
|
it "doesn't allow conversion from nil" do
|
78
93
|
refute(@field.convert(nil, @doc))
|
79
94
|
end
|
@@ -267,6 +267,7 @@ describe HexaPDF::Document do
|
|
267
267
|
@myclass = Class.new(HexaPDF::Dictionary)
|
268
268
|
@myclass.define_type(:MyClass)
|
269
269
|
@myclass2 = Class.new(HexaPDF::Dictionary)
|
270
|
+
@myclass2.define_field(:Test, type: String, required: true)
|
270
271
|
HexaPDF::GlobalConfiguration['object.type_map'][:MyClass] = @myclass
|
271
272
|
HexaPDF::GlobalConfiguration['object.subtype_map'][nil][:Global] = @myclass2
|
272
273
|
HexaPDF::GlobalConfiguration['object.subtype_map'][:MyClass] = {TheSecond: @myclass2}
|
@@ -328,14 +329,16 @@ describe HexaPDF::Document do
|
|
328
329
|
it "uses the type/subtype information in the hash that should be wrapped" do
|
329
330
|
assert_kind_of(@myclass, @doc.wrap(Type: :MyClass))
|
330
331
|
refute_kind_of(@myclass2, @doc.wrap(Subtype: :TheSecond))
|
331
|
-
|
332
|
+
refute_kind_of(@myclass2, @doc.wrap(Subtype: :Global))
|
333
|
+
assert_kind_of(@myclass2, @doc.wrap(Subtype: :Global, Test: "true"))
|
332
334
|
assert_kind_of(@myclass2, @doc.wrap(Type: :MyClass, S: :TheSecond))
|
333
335
|
assert_kind_of(@myclass, @doc.wrap(Type: :MyClass, Subtype: :TheThird))
|
334
336
|
end
|
335
337
|
|
336
338
|
it "respects the given type/subtype arguments" do
|
337
339
|
assert_kind_of(@myclass, @doc.wrap({Type: :Other}, type: :MyClass))
|
338
|
-
|
340
|
+
refute_kind_of(@myclass2, @doc.wrap({Subtype: :Other}, subtype: :Global))
|
341
|
+
assert_kind_of(@myclass2, @doc.wrap({Subtype: :Other, Test: "true"}, subtype: :Global))
|
339
342
|
assert_kind_of(@myclass2, @doc.wrap({Type: :Other, Subtype: :Other},
|
340
343
|
type: :MyClass, subtype: :TheSecond))
|
341
344
|
assert_kind_of(@myclass2, @doc.wrap({Subtype: :TheSecond}, type: @myclass))
|
@@ -40,6 +40,10 @@ describe HexaPDF::Reference do
|
|
40
40
|
refute(h.key?(HexaPDF::Reference.new(5, 8)))
|
41
41
|
end
|
42
42
|
|
43
|
+
it "shows the PDF serialization as string representation " do
|
44
|
+
assert_equal("5 7 R", HexaPDF::Reference.new(5, 7).to_s)
|
45
|
+
end
|
46
|
+
|
43
47
|
it "shows oid and gen on inspection" do
|
44
48
|
assert_match(/\[5, 7\]/, HexaPDF::Reference.new(5, 7).inspect)
|
45
49
|
end
|
@@ -63,6 +63,18 @@ describe HexaPDF::Revision do
|
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
|
+
describe "xref" do
|
67
|
+
it "returns the xref structure" do
|
68
|
+
assert_equal(@xref_section[2, 0], @rev.xref(HexaPDF::Reference.new(2, 0)))
|
69
|
+
assert_equal(@xref_section[2, 0], @rev.xref(2))
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns nil if no xref entry is found" do
|
73
|
+
assert_nil(@rev.xref(@ref))
|
74
|
+
assert_nil(@rev.xref(1))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
66
78
|
describe "object" do
|
67
79
|
it "returns nil if no object is found" do
|
68
80
|
assert_nil(@rev.object(@ref))
|
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.10.0)>>
|
44
44
|
endobj
|
45
45
|
xref
|
46
46
|
3 1
|
@@ -48,7 +48,7 @@ describe HexaPDF::Writer do
|
|
48
48
|
trailer
|
49
49
|
<</Prev 219/Size 4/Root<</Type/Catalog>>/Info 3 0 R>>
|
50
50
|
startxref
|
51
|
-
|
51
|
+
349
|
52
52
|
%%EOF
|
53
53
|
EOF
|
54
54
|
|
@@ -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.10.0)>>
|
76
76
|
endobj
|
77
77
|
2 0 obj
|
78
78
|
<</Length 10>>stream
|
@@ -81,11 +81,11 @@ describe HexaPDF::Writer do
|
|
81
81
|
endobj
|
82
82
|
4 0 obj
|
83
83
|
<</Size 7/Prev 141/Root<</Type/Catalog>>/Info 6 0 R/Type/XRef/W[1 2 2]/Index[2 1 4 1 6 1]/Filter/FlateDecode/DecodeParms<</Columns 5/Predictor 12>>/Length 22>>stream
|
84
|
-
x\
|
84
|
+
x\xDAcbdlg``b`\xB0\x04\x93\x93\x18\x18\x00\f\e\x01[
|
85
85
|
endstream
|
86
86
|
endobj
|
87
87
|
startxref
|
88
|
-
|
88
|
+
448
|
89
89
|
%%EOF
|
90
90
|
EOF
|
91
91
|
end
|
@@ -3,6 +3,17 @@
|
|
3
3
|
require 'test_helper'
|
4
4
|
require 'hexapdf/xref_section'
|
5
5
|
|
6
|
+
describe HexaPDF::XRefSection::Entry do
|
7
|
+
it "can describe itself" do
|
8
|
+
free = HexaPDF::XRefSection::Entry.new(:free, 1, 2)
|
9
|
+
normal = HexaPDF::XRefSection::Entry.new(:in_use, 1, 2, 10)
|
10
|
+
compressed = HexaPDF::XRefSection::Entry.new(:compressed, 1, 0, 2, 10)
|
11
|
+
assert_match(/1,2 type=free/, free.to_s)
|
12
|
+
assert_match(/1,2 type=normal/, normal.to_s)
|
13
|
+
assert_match(/1,0 type=compressed/, compressed.to_s)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
6
17
|
describe HexaPDF::XRefSection do
|
7
18
|
before do
|
8
19
|
@xref_section = HexaPDF::XRefSection.new
|
@@ -12,19 +12,19 @@ describe HexaPDF::Type::Image do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "returns the width of the image" do
|
15
|
-
@image = @doc.wrap(Subtype: :Image, Width: 10)
|
15
|
+
@image = @doc.wrap(Type: :XObject, Subtype: :Image, Width: 10)
|
16
16
|
assert_equal(10, @image.width)
|
17
17
|
end
|
18
18
|
|
19
19
|
it "returns the height of the image" do
|
20
|
-
@image = @doc.wrap(Subtype: :Image, Height: 10)
|
20
|
+
@image = @doc.wrap(Type: :XObject, Subtype: :Image, Height: 10)
|
21
21
|
assert_equal(10, @image.height)
|
22
22
|
end
|
23
23
|
|
24
24
|
describe "info" do
|
25
25
|
before do
|
26
|
-
@image = @doc.wrap(Subtype: :Image, Width: 10, Height: 5,
|
27
|
-
BitsPerComponent: 4)
|
26
|
+
@image = @doc.wrap(Type: :XObject, Subtype: :Image, Width: 10, Height: 5,
|
27
|
+
ColorSpace: :DeviceRGB, BitsPerComponent: 4)
|
28
28
|
end
|
29
29
|
|
30
30
|
it "uses the Width, Height and BitsPerComponent values" do
|
@@ -131,18 +131,24 @@ describe HexaPDF::Type::Image do
|
|
131
131
|
@file.unlink
|
132
132
|
end
|
133
133
|
|
134
|
-
`pngcheck 2>&1`
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
PNG_CHECK_AVAILABLE = true
|
140
|
-
end
|
134
|
+
`which pngcheck 2>&1`
|
135
|
+
PNG_CHECK_AVAILABLE = $?.exitstatus == 0
|
136
|
+
|
137
|
+
`which pngtopnm 2>&1`
|
138
|
+
PNG_COMPARE_AVAILABLE = $?.exitstatus == 0
|
141
139
|
|
142
|
-
def assert_valid_png(filename)
|
143
|
-
|
144
|
-
|
145
|
-
|
140
|
+
def assert_valid_png(filename, original = nil)
|
141
|
+
if PNG_CHECK_AVAILABLE
|
142
|
+
result = `pngcheck -q #{filename}`
|
143
|
+
assert(result.empty?, "pngcheck error: #{result}")
|
144
|
+
else
|
145
|
+
skip("Skipping PNG output validity check because pngcheck executable is missing")
|
146
|
+
end
|
147
|
+
if PNG_COMPARE_AVAILABLE
|
148
|
+
assert_equal(`pngtopnm #{original}`, `pngtopnm #{filename}`) if original
|
149
|
+
else
|
150
|
+
skip("Skipping PNG output comparison check because pngtopnm executable is missing")
|
151
|
+
end
|
146
152
|
end
|
147
153
|
|
148
154
|
it "can write to an IO" do
|
@@ -179,8 +185,11 @@ describe HexaPDF::Type::Image do
|
|
179
185
|
it "writes #{File.basename(png_file)} correctly as PNG file" do
|
180
186
|
image = @doc.images.add(png_file)
|
181
187
|
image.write(@file.path)
|
188
|
+
assert_valid_png(@file.path, png_file)
|
182
189
|
|
183
|
-
|
190
|
+
image.delete(:DecodeParms) # force re-encoding of stream
|
191
|
+
image.write(@file.path)
|
192
|
+
assert_valid_png(@file.path, png_file)
|
184
193
|
|
185
194
|
new_image = @doc.images.add(@file.path)
|
186
195
|
|
@@ -208,7 +217,7 @@ describe HexaPDF::Type::Image do
|
|
208
217
|
end
|
209
218
|
|
210
219
|
it "works for greyscale indexed images" do
|
211
|
-
image = @doc.add(Subtype: :Image, Width: 2, Height: 2, BitsPerComponent: 2,
|
220
|
+
image = @doc.add(Type: :XObject, Subtype: :Image, Width: 2, Height: 2, BitsPerComponent: 2,
|
212
221
|
ColorSpace: [:Indexed, :DeviceGray, 3, "\x00\x40\x80\xFF".b])
|
213
222
|
image.stream = HexaPDF::StreamData.new(filter: :ASCIIHexDecode) { "10 B0".b }
|
214
223
|
image.write(@file.path)
|
@@ -227,13 +236,13 @@ describe HexaPDF::Type::Image do
|
|
227
236
|
end
|
228
237
|
|
229
238
|
it "fails if an unsupported colorspace is used" do
|
230
|
-
image = @doc.add(Subtype: :Image, Width: 1, Height: 1, BitsPerComponent: 8,
|
239
|
+
image = @doc.add(Type: :XObject, Subtype: :Image, Width: 1, Height: 1, BitsPerComponent: 8,
|
231
240
|
ColorSpace: :ICCBased)
|
232
241
|
assert_raises(HexaPDF::Error) { image.write(@file) }
|
233
242
|
end
|
234
243
|
|
235
244
|
it "fails if an indexed image with an unsupported colorspace is used" do
|
236
|
-
image = @doc.add(Subtype: :Image, Width: 1, Height: 1, BitsPerComponent: 8,
|
245
|
+
image = @doc.add(Type: :XObject, Subtype: :Image, Width: 1, Height: 1, BitsPerComponent: 8,
|
237
246
|
ColorSpace: [:Indexed, :ICCBased, 0, "0"])
|
238
247
|
assert_raises(HexaPDF::Error) { image.write(@file) }
|
239
248
|
end
|
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.10.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: 2019-
|
11
|
+
date: 2019-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cmdparse
|
@@ -436,6 +436,7 @@ files:
|
|
436
436
|
- test/data/images/truecolour-alpha-8bit.png
|
437
437
|
- test/data/images/truecolour-gama-chrm-8bit.png
|
438
438
|
- test/data/images/truecolour-srgb-8bit.png
|
439
|
+
- test/data/images/ycck.jpg
|
439
440
|
- test/data/minimal.pdf
|
440
441
|
- test/data/standard-security-handler/README
|
441
442
|
- test/data/standard-security-handler/bothpwd-aes-128bit-V4.pdf
|