hexapdf 0.9.3 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/CONTRIBUTERS +2 -1
  4. data/VERSION +1 -1
  5. data/lib/hexapdf/cli/command.rb +9 -5
  6. data/lib/hexapdf/cli/images.rb +68 -13
  7. data/lib/hexapdf/cli/inspect.rb +201 -71
  8. data/lib/hexapdf/content/canvas.rb +1 -1
  9. data/lib/hexapdf/dictionary.rb +15 -1
  10. data/lib/hexapdf/dictionary_fields.rb +5 -4
  11. data/lib/hexapdf/document.rb +15 -6
  12. data/lib/hexapdf/encryption/security_handler.rb +3 -2
  13. data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +165 -165
  14. data/lib/hexapdf/font/true_type_wrapper.rb +2 -2
  15. data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
  16. data/lib/hexapdf/image_loader/jpeg.rb +13 -11
  17. data/lib/hexapdf/reference.rb +5 -0
  18. data/lib/hexapdf/revision.rb +14 -0
  19. data/lib/hexapdf/serializer.rb +6 -6
  20. data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
  21. data/lib/hexapdf/type/image.rb +3 -1
  22. data/lib/hexapdf/version.rb +1 -1
  23. data/lib/hexapdf/xref_section.rb +8 -0
  24. data/man/man1/hexapdf.1 +88 -20
  25. data/test/data/images/truecolour-alpha-8bit.png +0 -0
  26. data/test/data/images/ycck.jpg +0 -0
  27. data/test/hexapdf/content/test_canvas.rb +2 -2
  28. data/test/hexapdf/document/test_images.rb +7 -5
  29. data/test/hexapdf/encryption/test_security_handler.rb +13 -0
  30. data/test/hexapdf/image_loader/test_jpeg.rb +10 -0
  31. data/test/hexapdf/image_loader/test_png.rb +3 -2
  32. data/test/hexapdf/test_dictionary.rb +9 -0
  33. data/test/hexapdf/test_dictionary_fields.rb +15 -0
  34. data/test/hexapdf/test_document.rb +5 -2
  35. data/test/hexapdf/test_reference.rb +4 -0
  36. data/test/hexapdf/test_revision.rb +12 -0
  37. data/test/hexapdf/test_writer.rb +5 -5
  38. data/test/hexapdf/test_xref_section.rb +11 -0
  39. data/test/hexapdf/type/test_form.rb +1 -1
  40. data/test/hexapdf/type/test_image.rb +28 -19
  41. 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
- assert_kind_of(@myclass2, @doc.wrap(Subtype: :Global))
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
- assert_kind_of(@myclass2, @doc.wrap({Subtype: :Other}, subtype: :Global))
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))
@@ -40,7 +40,7 @@ describe HexaPDF::Writer do
40
40
  219
41
41
  %%EOF
42
42
  3 0 obj
43
- <</Producer(HexaPDF version 0.9.3)>>
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
- 348
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.9.3)>>
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\xDAcbdlc``b`\xB0\x04\x93\x93\x19\x18\x00\f\x0F\x01[
84
+ x\xDAcbdlg``b`\xB0\x04\x93\x93\x18\x18\x00\f\e\x01[
85
85
  endstream
86
86
  endobj
87
87
  startxref
88
- 447
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
@@ -8,7 +8,7 @@ require 'hexapdf/type/form'
8
8
  describe HexaPDF::Type::Form do
9
9
  before do
10
10
  @doc = HexaPDF::Document.new
11
- @form = @doc.wrap({}, subtype: :Form)
11
+ @form = @doc.wrap({}, type: :XObject, subtype: :Form)
12
12
  end
13
13
 
14
14
  describe "box" do
@@ -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, ColorSpace: :DeviceRGB,
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
- if $?.exitstatus != 0
136
- warn("Skipping PNG output validity check because pngcheck executable is missing")
137
- PNG_CHECK_AVAILABLE = false
138
- else
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
- return unless PNG_CHECK_AVAILABLE
144
- result = `pngcheck -q #{filename}`
145
- assert(result.empty?, "pngcheck error: #{result}")
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
- assert_valid_png(@file.path)
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.9.3
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-06-13 00:00:00.000000000 Z
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