hexapdf 0.26.2 → 0.28.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.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +115 -1
  3. data/README.md +1 -1
  4. data/examples/013-text_layouter_shapes.rb +8 -8
  5. data/examples/016-frame_automatic_box_placement.rb +3 -3
  6. data/examples/017-frame_text_flow.rb +3 -3
  7. data/examples/019-acro_form.rb +14 -3
  8. data/examples/020-column_box.rb +3 -3
  9. data/examples/023-images.rb +30 -0
  10. data/lib/hexapdf/cli/info.rb +5 -1
  11. data/lib/hexapdf/cli/inspect.rb +2 -2
  12. data/lib/hexapdf/cli/split.rb +8 -8
  13. data/lib/hexapdf/cli/watermark.rb +2 -2
  14. data/lib/hexapdf/configuration.rb +3 -2
  15. data/lib/hexapdf/content/canvas.rb +8 -3
  16. data/lib/hexapdf/dictionary.rb +4 -17
  17. data/lib/hexapdf/document/destinations.rb +42 -5
  18. data/lib/hexapdf/document/signatures.rb +265 -48
  19. data/lib/hexapdf/document.rb +6 -10
  20. data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
  21. data/lib/hexapdf/importer.rb +35 -27
  22. data/lib/hexapdf/layout/list_box.rb +1 -5
  23. data/lib/hexapdf/object.rb +5 -0
  24. data/lib/hexapdf/parser.rb +14 -0
  25. data/lib/hexapdf/revision.rb +15 -12
  26. data/lib/hexapdf/revisions.rb +7 -1
  27. data/lib/hexapdf/tokenizer.rb +15 -9
  28. data/lib/hexapdf/type/acro_form/appearance_generator.rb +174 -128
  29. data/lib/hexapdf/type/acro_form/button_field.rb +5 -3
  30. data/lib/hexapdf/type/acro_form/choice_field.rb +2 -0
  31. data/lib/hexapdf/type/acro_form/field.rb +11 -5
  32. data/lib/hexapdf/type/acro_form/form.rb +61 -8
  33. data/lib/hexapdf/type/acro_form/signature_field.rb +2 -0
  34. data/lib/hexapdf/type/acro_form/text_field.rb +12 -2
  35. data/lib/hexapdf/type/annotations/widget.rb +3 -0
  36. data/lib/hexapdf/type/catalog.rb +1 -1
  37. data/lib/hexapdf/type/font_true_type.rb +14 -0
  38. data/lib/hexapdf/type/object_stream.rb +2 -2
  39. data/lib/hexapdf/type/outline.rb +19 -1
  40. data/lib/hexapdf/type/outline_item.rb +72 -14
  41. data/lib/hexapdf/type/page.rb +95 -64
  42. data/lib/hexapdf/type/resources.rb +13 -17
  43. data/lib/hexapdf/type/signature/adbe_pkcs7_detached.rb +16 -2
  44. data/lib/hexapdf/type/signature.rb +10 -0
  45. data/lib/hexapdf/version.rb +1 -1
  46. data/lib/hexapdf/writer.rb +5 -3
  47. data/test/hexapdf/content/test_canvas.rb +5 -0
  48. data/test/hexapdf/document/test_destinations.rb +41 -0
  49. data/test/hexapdf/document/test_pages.rb +2 -2
  50. data/test/hexapdf/document/test_signatures.rb +139 -19
  51. data/test/hexapdf/encryption/test_aes.rb +1 -1
  52. data/test/hexapdf/filter/test_predictor.rb +0 -1
  53. data/test/hexapdf/layout/test_box.rb +2 -1
  54. data/test/hexapdf/layout/test_column_box.rb +1 -1
  55. data/test/hexapdf/layout/test_list_box.rb +1 -1
  56. data/test/hexapdf/test_document.rb +2 -8
  57. data/test/hexapdf/test_importer.rb +27 -6
  58. data/test/hexapdf/test_parser.rb +19 -2
  59. data/test/hexapdf/test_revision.rb +15 -14
  60. data/test/hexapdf/test_revisions.rb +63 -12
  61. data/test/hexapdf/test_stream.rb +1 -1
  62. data/test/hexapdf/test_tokenizer.rb +10 -1
  63. data/test/hexapdf/test_writer.rb +11 -3
  64. data/test/hexapdf/type/acro_form/test_appearance_generator.rb +135 -56
  65. data/test/hexapdf/type/acro_form/test_button_field.rb +6 -1
  66. data/test/hexapdf/type/acro_form/test_choice_field.rb +4 -0
  67. data/test/hexapdf/type/acro_form/test_field.rb +4 -4
  68. data/test/hexapdf/type/acro_form/test_form.rb +65 -0
  69. data/test/hexapdf/type/acro_form/test_signature_field.rb +4 -0
  70. data/test/hexapdf/type/acro_form/test_text_field.rb +13 -0
  71. data/test/hexapdf/type/signature/common.rb +54 -0
  72. data/test/hexapdf/type/signature/test_adbe_pkcs7_detached.rb +21 -0
  73. data/test/hexapdf/type/test_catalog.rb +5 -2
  74. data/test/hexapdf/type/test_font_true_type.rb +20 -0
  75. data/test/hexapdf/type/test_object_stream.rb +2 -1
  76. data/test/hexapdf/type/test_outline.rb +4 -1
  77. data/test/hexapdf/type/test_outline_item.rb +62 -1
  78. data/test/hexapdf/type/test_page.rb +103 -45
  79. data/test/hexapdf/type/test_page_tree_node.rb +4 -2
  80. data/test/hexapdf/type/test_resources.rb +0 -5
  81. data/test/hexapdf/type/test_signature.rb +8 -0
  82. data/test/test_helper.rb +1 -1
  83. metadata +61 -4
@@ -94,6 +94,11 @@ describe HexaPDF::Type::Page do
94
94
  @page = @doc.pages.add
95
95
  end
96
96
 
97
+ it "returns the crop box by default" do
98
+ @page[:CropBox] = [0, 0, 100, 200]
99
+ assert_equal([0, 0, 100, 200], @page.box)
100
+ end
101
+
97
102
  it "returns the correct media box" do
98
103
  @page[:MediaBox] = :media
99
104
  assert_equal(:media, @page.box(:media))
@@ -150,15 +155,25 @@ describe HexaPDF::Type::Page do
150
155
  @page = @doc.pages.add
151
156
  end
152
157
 
153
- it "returns :portrait for appropriate media boxes and rotation values" do
154
- @page.box(:media, [0, 0, 100, 300])
158
+ it "uses the crop box by default" do
159
+ @page[:CropBox] = [0, 0, 200, 100]
160
+ assert_equal(:landscape, @page.orientation)
161
+ end
162
+
163
+ it "uses the specified box for determining the orientation" do
164
+ @page[:ArtBox] = [0, 0, 200, 100]
165
+ assert_equal(:landscape, @page.orientation(:art))
166
+ end
167
+
168
+ it "returns :portrait for appropriate boxes and rotation values" do
169
+ @page.box(:crop, [0, 0, 100, 300])
155
170
  assert_equal(:portrait, @page.orientation)
156
171
  @page[:Rotate] = 0
157
172
  assert_equal(:portrait, @page.orientation)
158
173
  @page[:Rotate] = 180
159
174
  assert_equal(:portrait, @page.orientation)
160
175
 
161
- @page.box(:media, [0, 0, 300, 100])
176
+ @page.box(:crop, [0, 0, 300, 100])
162
177
  @page[:Rotate] = 90
163
178
  assert_equal(:portrait, @page.orientation)
164
179
  @page[:Rotate] = 270
@@ -166,14 +181,14 @@ describe HexaPDF::Type::Page do
166
181
  end
167
182
 
168
183
  it "returns :landscape for appropriate media boxes and rotation values" do
169
- @page.box(:media, [0, 0, 300, 100])
184
+ @page.box(:crop, [0, 0, 300, 100])
170
185
  assert_equal(:landscape, @page.orientation)
171
186
  @page[:Rotate] = 0
172
187
  assert_equal(:landscape, @page.orientation)
173
188
  @page[:Rotate] = 180
174
189
  assert_equal(:landscape, @page.orientation)
175
190
 
176
- @page.box(:media, [0, 0, 100, 300])
191
+ @page.box(:crop, [0, 0, 100, 300])
177
192
  @page[:Rotate] = 90
178
193
  assert_equal(:landscape, @page.orientation)
179
194
  @page[:Rotate] = 270
@@ -204,36 +219,72 @@ describe HexaPDF::Type::Page do
204
219
 
205
220
  describe "flatten" do
206
221
  it "adjust all page boxes" do
207
- @page.box(:crop, @page.box)
208
- @page.box(:bleed, @page.box)
209
- @page.box(:trim, @page.box)
210
- @page.box(:art, @page.box)
222
+ @page.box(:crop, [0, 0, 1, 2])
223
+ @page.box(:bleed, [0, 0, 2, 3])
224
+ @page.box(:trim, [0, 0, 3, 4])
225
+ @page.box(:art, [0, 0, 4, 5])
211
226
 
212
227
  @page.rotate(90, flatten: true)
213
- box = [-300, 50, -100, 200]
214
- assert_equal(box, @page.box(:media).value)
215
- assert_equal(box, @page.box(:crop).value)
216
- assert_equal(box, @page.box(:bleed).value)
217
- assert_equal(box, @page.box(:trim).value)
218
- assert_equal(box, @page.box(:art).value)
228
+ assert_equal([-298, 50, -98, 200], @page.box(:media).value)
229
+ assert_equal([0, 0, 2, 1], @page.box(:crop).value)
230
+ assert_equal([-1, 0, 2, 2], @page.box(:bleed).value)
231
+ assert_equal([-2, 0, 2, 3], @page.box(:trim).value)
232
+ assert_equal([-3, 0, 2, 4], @page.box(:art).value)
219
233
  end
220
234
 
221
235
  it "works correctly for 90 degrees" do
222
236
  @page.rotate(90, flatten: true)
223
- assert_equal([-300, 50, -100, 200], @page.box(:media).value)
224
- assert_equal(" q 0 1 -1 0 0 0 cm Q ", @page.contents)
237
+ assert_equal([0, 0, 200, 150], @page.box(:media).value)
238
+ assert_equal(" q 0 1 -1 0 300 -50 cm Q ", @page.contents)
225
239
  end
226
240
 
227
241
  it "works correctly for 180 degrees" do
228
242
  @page.rotate(180, flatten: true)
229
- assert_equal([-200, -300, -50, -100], @page.box(:media).value)
230
- assert_equal(" q -1 0 0 -1 0 0 cm Q ", @page.contents)
243
+ assert_equal([0, 0, 150, 200], @page.box(:media).value)
244
+ assert_equal(" q -1 0 0 -1 200 300 cm Q ", @page.contents)
231
245
  end
232
246
 
233
247
  it "works correctly for 270 degrees" do
234
248
  @page.rotate(270, flatten: true)
235
- assert_equal([100, -200, 300, -50], @page.box(:media).value)
236
- assert_equal(" q 0 -1 1 0 0 0 cm Q ", @page.contents)
249
+ assert_equal([0, 0, 200, 150], @page.box(:media).value)
250
+ assert_equal(" q 0 -1 1 0 -100 200 cm Q ", @page.contents)
251
+ end
252
+
253
+ describe "annotations" do
254
+ before do
255
+ @appearance = @doc.add({Type: :XObject, Subtype: :Form, BBox: [-10, -5, 50, 20]}, stream: "")
256
+ @annot = @doc.add({Type: :Annot, Subtype: :Widget, Rect: [100, 100, 160, 125],
257
+ QuadPoints: [0, 0, 100, 200, 300, 400, 500, 600],
258
+ AP: {N: @appearance}})
259
+ @page[:Annots] = [@annot]
260
+ end
261
+
262
+ it "rotates the /Rect entry" do
263
+ @page.rotate(90, flatten: true)
264
+ assert_equal([175, 50, 200, 110], @annot[:Rect].value)
265
+ end
266
+
267
+ it "rotates all (x,y) pairs in the /QuadPoints entry" do
268
+ @page.rotate(90, flatten: true)
269
+ assert_equal([300, -50, 100, 50, -100, 250, -300, 450],
270
+ @annot[:QuadPoints])
271
+ end
272
+
273
+ it "applies the needed matrix to the annotation's appearance stream's /Matrix entry" do
274
+ @page.rotate(90, flatten: true)
275
+ assert_equal([0, 1, -1, 0, 300, -50], @appearance[:Matrix])
276
+
277
+ @page.rotate(90, flatten: true)
278
+ assert_equal([-1, 0, 0, -1, 200, 300], @appearance[:Matrix])
279
+ end
280
+
281
+ it "modified the /R entry in the appearance characteristics dictionary of a widget annotation" do
282
+ @page.rotate(90, flatten: true)
283
+ assert_equal(90, @annot[:MK][:R])
284
+
285
+ @page.rotate(90, flatten: true)
286
+ assert_equal(180, @annot[:MK][:R])
287
+ end
237
288
  end
238
289
  end
239
290
 
@@ -405,8 +456,8 @@ describe HexaPDF::Type::Page do
405
456
  [:restore_graphics_state]])
406
457
  end
407
458
 
408
- it "works correctly if the page has its origin not at (0,0)" do
409
- @page.box(:media, [-10, -5, 100, 300])
459
+ it "works correctly if the page has its crop box origin not at (0,0)" do
460
+ @page.box(:crop, [-10, -5, 100, 300])
410
461
  @page.canvas(type: :underlay).line_width = 2
411
462
  @page.canvas(type: :page).line_width = 2
412
463
  @page.canvas(type: :overlay).line_width = 2
@@ -427,6 +478,13 @@ describe HexaPDF::Type::Page do
427
478
  [:restore_graphics_state]])
428
479
  end
429
480
 
481
+ it "allows disabling the origin translation" do
482
+ @page.box(:crop, [-10, -5, 100, 300])
483
+ @page.canvas(translate_origin: false).line_width = 2
484
+
485
+ assert_page_operators(@page, [[:set_line_width, [2]]])
486
+ end
487
+
430
488
  it "fails if the page canvas is requested for a page with existing contents" do
431
489
  @page.contents = "q Q"
432
490
  assert_raises(HexaPDF::Error) { @page.canvas }
@@ -473,25 +531,30 @@ describe HexaPDF::Type::Page do
473
531
  @canvas = @page.canvas(type: :overlay)
474
532
  end
475
533
 
476
- it "does nothing if the page doesn't have any annotations" do
534
+ it "does nothing and returns the argument as array if the page doesn't have any annotations" do
535
+ annots = @page[:Annots]
536
+
477
537
  @page.delete(:Annots)
478
538
  result = @page.flatten_annotations
479
539
  assert(result.empty?)
480
540
  assert_operators(@canvas.contents, [])
541
+
542
+ result = @page.flatten_annotations(annots)
543
+ assert_kind_of(Array, result)
544
+ assert_equal([@annot1, @annot2], result)
545
+ assert_operators(@canvas.contents, [])
481
546
  end
482
547
 
483
548
  it "flattens all annotations of the page by default" do
484
549
  result = @page.flatten_annotations
485
550
  assert(result.empty?)
486
551
  assert_operators(@canvas.contents, [[:save_graphics_state],
487
- [:save_graphics_state],
488
552
  [:concatenate_matrix, [1.0, 0, 0, 1.0, 110, 105]],
489
553
  [:paint_xobject, [:XO1]],
490
554
  [:restore_graphics_state],
491
555
  [:save_graphics_state],
492
556
  [:concatenate_matrix, [1.0, 0, 0, 1.0, 20, 15]],
493
557
  [:paint_xobject, [:XO1]],
494
- [:restore_graphics_state],
495
558
  [:restore_graphics_state]])
496
559
  assert(@annot1.null?)
497
560
  assert(@annot2.null?)
@@ -521,10 +584,8 @@ describe HexaPDF::Type::Page do
521
584
  assert(result.empty?)
522
585
  assert(@annot1.null?)
523
586
  assert_operators(@canvas.contents, [[:save_graphics_state],
524
- [:save_graphics_state],
525
587
  [:concatenate_matrix, [1.0, 0, 0, 1.0, 20, 15]],
526
588
  [:paint_xobject, [:XO1]],
527
- [:restore_graphics_state],
528
589
  [:restore_graphics_state]])
529
590
  end
530
591
 
@@ -534,10 +595,8 @@ describe HexaPDF::Type::Page do
534
595
  assert(result.empty?)
535
596
  assert(@annot1.null?)
536
597
  assert_operators(@canvas.contents, [[:save_graphics_state],
537
- [:save_graphics_state],
538
598
  [:concatenate_matrix, [1.0, 0, 0, 1.0, 20, 15]],
539
599
  [:paint_xobject, [:XO1]],
540
- [:restore_graphics_state],
541
600
  [:restore_graphics_state]])
542
601
  end
543
602
 
@@ -547,56 +606,55 @@ describe HexaPDF::Type::Page do
547
606
  assert_equal([@annot1], result)
548
607
  refute(@annot1.empty?)
549
608
  assert_operators(@canvas.contents, [[:save_graphics_state],
550
- [:save_graphics_state],
551
609
  [:concatenate_matrix, [1.0, 0, 0, 1.0, 20, 15]],
552
610
  [:paint_xobject, [:XO1]],
553
- [:restore_graphics_state],
554
611
  [:restore_graphics_state]])
555
612
  end
556
613
 
557
- it "adjusts the position to counter the translation in #canvas based on the page's media box" do
558
- @page[:MediaBox] = [-15, -15, 100, 100]
614
+ it "potentially adjusts the origin so that it is always in (0,0)" do
615
+ @canvas.translate(-15, -15)
559
616
  @page.flatten_annotations
560
- assert_operators(@canvas.contents, [:concatenate_matrix, [1, 0, 0, 1, 15, 15]], range: 1)
617
+ assert_operators(@canvas.contents, [:concatenate_matrix, [1, 0, 0, 1, 15, 15]], range: 2)
561
618
  end
562
619
 
563
620
  it "adjusts the position in case the form /Matrix has an offset" do
564
621
  @appearance[:Matrix] = [1, 0, 0, 1, 15, 15]
565
622
  @page.flatten_annotations
566
- assert_operators(@canvas.contents, [:concatenate_matrix, [1, 0, 0, 1, 95, 90]], range: 2)
623
+ assert_operators(@canvas.contents, [:concatenate_matrix, [1, 0, 0, 1, 95, 90]], range: 1)
567
624
  end
568
625
 
569
626
  it "adjusts the position for an appearance with a 90 degree rotation" do
570
627
  @appearance[:Matrix] = [0, 1, -1, 0, 0, 0]
571
628
  @annot1[:Rect] = [100, 100, 125, 160]
572
629
  @page.flatten_annotations
573
- assert_operators(@canvas.contents, [:concatenate_matrix, [1, 0, 0, 1, 120, 110]], range: 2)
630
+ assert_operators(@canvas.contents, [:concatenate_matrix, [1, 0, 0, 1, 120, 110]], range: 1)
574
631
  end
575
632
 
576
633
  it "adjusts the position for an appearance with a -90 degree rotation" do
577
634
  @appearance[:Matrix] = [0, -1, 1, 0, 0, 0]
578
635
  @annot1[:Rect] = [100, 100, 125, 160]
579
636
  @page.flatten_annotations
580
- assert_operators(@canvas.contents, [:concatenate_matrix, [1, 0, 0, 1, 105, 150]], range: 2)
637
+ assert_operators(@canvas.contents, [:concatenate_matrix, [1, 0, 0, 1, 105, 150]], range: 1)
581
638
  end
582
639
 
583
640
  it "adjusts the position for an appearance with a 180 degree rotation" do
584
641
  @appearance[:Matrix] = [-1, 0, 0, -1, 0, 0]
585
642
  @page.flatten_annotations
586
- assert_operators(@canvas.contents, [:concatenate_matrix, [1, 0, 0, 1, 150, 120]], range: 2)
643
+ assert_operators(@canvas.contents, [:concatenate_matrix, [1, 0, 0, 1, 150, 120]], range: 1)
587
644
  end
588
645
 
589
- it "ignores an appearance with a rotation that is not a mulitple of 90" do
590
- @appearance[:Matrix] = [-1, 0.5, 0.5, -1, 0, 0]
591
- result = @page.flatten_annotations
592
- assert_equal([@annot1, @annot2], result)
593
- assert_operators(@canvas.contents, [[:save_graphics_state], [:restore_graphics_state]])
646
+ it "correctly positions and scales an appearance with a custom rotation" do
647
+ @appearance[:Matrix] = [0.707106, 0.707106, -0.707106, 0.707106, 10, 30]
648
+ @page.flatten_annotations
649
+ assert_operators(@canvas.contents,
650
+ [:concatenate_matrix, [0.998269, 0.0, 0.0, 0.415946, 111.21318, 80.60659]],
651
+ range: 1)
594
652
  end
595
653
 
596
654
  it "scales the appearance to fit into the annotations's rectangle" do
597
655
  @annot1[:Rect] = [100, 100, 130, 150]
598
656
  @page.flatten_annotations
599
- assert_operators(@canvas.contents, [:concatenate_matrix, [0.5, 0, 0, 2, 110, 105]], range: 2)
657
+ assert_operators(@canvas.contents, [:concatenate_matrix, [0.5, 0, 0, 2, 110, 105]], range: 1)
600
658
  end
601
659
  end
602
660
 
@@ -241,11 +241,13 @@ describe HexaPDF::Type::PageTreeNode do
241
241
 
242
242
  it "moves the page to the correct location within the same parent node" do
243
243
  @root.move_page(2, 4)
244
- assert_equal([@pages[0], @pages[1], @pages[3], @pages[4], @pages[2], *@pages[5..-1]], @root.each_page.to_a)
244
+ assert_equal([@pages[0], @pages[1], @pages[3], @pages[4], @pages[2], *@pages[5..-1]],
245
+ @root.each_page.to_a)
245
246
  assert(@root.validate)
246
247
 
247
248
  @root.move_page(4, 3)
248
- assert_equal([@pages[0], @pages[1], @pages[3], @pages[2], @pages[4], *@pages[5..-1]], @root.each_page.to_a)
249
+ assert_equal([@pages[0], @pages[1], @pages[3], @pages[2], @pages[4], *@pages[5..-1]],
250
+ @root.each_page.to_a)
249
251
  assert(@root.validate)
250
252
  end
251
253
 
@@ -189,11 +189,6 @@ describe HexaPDF::Type::Resources do
189
189
  end
190
190
 
191
191
  describe "validation" do
192
- it "assigns the default value if ProcSet is not set" do
193
- @res.validate
194
- assert_equal([:PDF, :Text, :ImageB, :ImageC, :ImageI], @res[:ProcSet].value)
195
- end
196
-
197
192
  it "handles an invalid ProcSet containing a single value instead of an array" do
198
193
  @res[:ProcSet] = :PDF
199
194
  @res.validate
@@ -128,4 +128,12 @@ describe HexaPDF::Type::Signature do
128
128
  assert_kind_of(OpenSSL::X509::Store, store)
129
129
  assert(kwargs[:allow_self_signed])
130
130
  end
131
+
132
+ describe "perform_validation" do
133
+ it "upgrades the version to 2.0 if the /SubFilter needs it" do
134
+ refute(@sig.validate(auto_correct: false))
135
+ assert(@sig.validate(auto_correct: true))
136
+ assert_equal('2.0', @doc.version)
137
+ end
138
+ end
131
139
  end
data/test/test_helper.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  begin
4
4
  require 'simplecov'
5
5
  SimpleCov.start do
6
- minimum_coverage line: 100
6
+ minimum_coverage line: 100 unless ENV['NO_SIMPLECOV']
7
7
  add_filter '/test/'
8
8
  add_filter '/fast_arc4.rb'
9
9
  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.26.2
4
+ version: 0.28.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: 2022-10-21 00:00:00.000000000 Z
11
+ date: 2022-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmdparse
@@ -44,6 +44,20 @@ dependencies:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
46
  version: '0.3'
47
+ - !ruby/object:Gem::Dependency
48
+ name: openssl
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 2.2.1
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 2.2.1
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: kramdown
49
63
  requirement: !ruby/object:Gem::Requirement
@@ -100,6 +114,48 @@ dependencies:
100
114
  - - "~>"
101
115
  - !ruby/object:Gem::Version
102
116
  version: '1.0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: webrick
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ - !ruby/object:Gem::Dependency
132
+ name: rake
133
+ requirement: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ type: :development
139
+ prerelease: false
140
+ version_requirements: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ - !ruby/object:Gem::Dependency
146
+ name: simplecov
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
103
159
  description: |
104
160
  HexaPDF is a pure Ruby library with an accompanying application for working with PDF
105
161
  files.
@@ -234,6 +290,7 @@ files:
234
290
  - examples/020-column_box.rb
235
291
  - examples/021-list_box.rb
236
292
  - examples/022-outline.rb
293
+ - examples/023-images.rb
237
294
  - examples/emoji-smile.png
238
295
  - examples/emoji-wink.png
239
296
  - examples/machupicchu.jpg
@@ -699,14 +756,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
699
756
  requirements:
700
757
  - - ">="
701
758
  - !ruby/object:Gem::Version
702
- version: '2.5'
759
+ version: '2.6'
703
760
  required_rubygems_version: !ruby/object:Gem::Requirement
704
761
  requirements:
705
762
  - - ">="
706
763
  - !ruby/object:Gem::Version
707
764
  version: '0'
708
765
  requirements: []
709
- rubygems_version: 3.2.32
766
+ rubygems_version: 3.4.1
710
767
  signing_key:
711
768
  specification_version: 4
712
769
  summary: HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby