hexapdf 0.33.0 → 0.34.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 (69) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -1
  3. data/examples/026-optional_content.rb +55 -0
  4. data/examples/027-composer_optional_content.rb +83 -0
  5. data/lib/hexapdf/cli/command.rb +7 -1
  6. data/lib/hexapdf/cli/fonts.rb +1 -1
  7. data/lib/hexapdf/cli/inspect.rb +2 -4
  8. data/lib/hexapdf/composer.rb +2 -1
  9. data/lib/hexapdf/configuration.rb +21 -1
  10. data/lib/hexapdf/content/canvas.rb +52 -0
  11. data/lib/hexapdf/content/operator.rb +2 -0
  12. data/lib/hexapdf/dictionary.rb +1 -0
  13. data/lib/hexapdf/dictionary_fields.rb +1 -2
  14. data/lib/hexapdf/digital_signature/verification_result.rb +1 -2
  15. data/lib/hexapdf/document/layout.rb +3 -0
  16. data/lib/hexapdf/document/pages.rb +1 -1
  17. data/lib/hexapdf/document.rb +7 -0
  18. data/lib/hexapdf/encryption/ruby_aes.rb +10 -20
  19. data/lib/hexapdf/layout/box.rb +23 -3
  20. data/lib/hexapdf/layout/column_box.rb +2 -1
  21. data/lib/hexapdf/layout/frame.rb +23 -6
  22. data/lib/hexapdf/layout/inline_box.rb +20 -9
  23. data/lib/hexapdf/layout/list_box.rb +34 -20
  24. data/lib/hexapdf/layout/page_style.rb +2 -1
  25. data/lib/hexapdf/layout/style.rb +46 -6
  26. data/lib/hexapdf/layout/table_box.rb +9 -7
  27. data/lib/hexapdf/layout/text_box.rb +9 -2
  28. data/lib/hexapdf/layout/text_fragment.rb +28 -2
  29. data/lib/hexapdf/layout/text_layouter.rb +21 -5
  30. data/lib/hexapdf/stream.rb +1 -2
  31. data/lib/hexapdf/type/actions/set_ocg_state.rb +86 -0
  32. data/lib/hexapdf/type/actions.rb +1 -0
  33. data/lib/hexapdf/type/annotations/text.rb +1 -2
  34. data/lib/hexapdf/type/catalog.rb +10 -1
  35. data/lib/hexapdf/type/cid_font.rb +15 -1
  36. data/lib/hexapdf/type/form.rb +75 -5
  37. data/lib/hexapdf/type/optional_content_configuration.rb +170 -0
  38. data/lib/hexapdf/type/optional_content_group.rb +370 -0
  39. data/lib/hexapdf/type/optional_content_membership.rb +63 -0
  40. data/lib/hexapdf/type/optional_content_properties.rb +158 -0
  41. data/lib/hexapdf/type/page.rb +27 -11
  42. data/lib/hexapdf/type/page_label.rb +4 -8
  43. data/lib/hexapdf/type.rb +4 -0
  44. data/lib/hexapdf/utils/pdf_doc_encoding.rb +0 -1
  45. data/lib/hexapdf/version.rb +1 -1
  46. data/test/hexapdf/content/test_canvas.rb +49 -0
  47. data/test/hexapdf/document/test_layout.rb +7 -2
  48. data/test/hexapdf/document/test_pages.rb +6 -6
  49. data/test/hexapdf/layout/test_box.rb +13 -4
  50. data/test/hexapdf/layout/test_frame.rb +13 -1
  51. data/test/hexapdf/layout/test_inline_box.rb +17 -8
  52. data/test/hexapdf/layout/test_list_box.rb +48 -31
  53. data/test/hexapdf/layout/test_style.rb +10 -0
  54. data/test/hexapdf/layout/test_table_box.rb +32 -26
  55. data/test/hexapdf/layout/test_text_box.rb +8 -0
  56. data/test/hexapdf/layout/test_text_fragment.rb +33 -0
  57. data/test/hexapdf/layout/test_text_layouter.rb +32 -5
  58. data/test/hexapdf/test_composer.rb +10 -0
  59. data/test/hexapdf/test_dictionary.rb +10 -0
  60. data/test/hexapdf/test_document.rb +4 -0
  61. data/test/hexapdf/test_writer.rb +3 -3
  62. data/test/hexapdf/type/actions/test_set_ocg_state.rb +40 -0
  63. data/test/hexapdf/type/test_catalog.rb +11 -0
  64. data/test/hexapdf/type/test_form.rb +119 -0
  65. data/test/hexapdf/type/test_optional_content_configuration.rb +112 -0
  66. data/test/hexapdf/type/test_optional_content_group.rb +158 -0
  67. data/test/hexapdf/type/test_optional_content_properties.rb +109 -0
  68. data/test/hexapdf/type/test_page.rb +2 -2
  69. metadata +14 -3
@@ -0,0 +1,112 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/type/optional_content_configuration'
5
+ require 'hexapdf/document'
6
+
7
+ describe HexaPDF::Type::OptionalContentConfiguration do
8
+ before do
9
+ @doc = HexaPDF::Document.new
10
+ @oc_config = @doc.optional_content.default_configuration
11
+ @ocg = @doc.optional_content.ocg('Test')
12
+ end
13
+
14
+ describe "ocg_state" do
15
+ it "defaults to the base state if nothing specific is set" do
16
+ assert_equal(:on, @oc_config.ocg_state(@ocg))
17
+ @oc_config[:BaseState] = :OFF
18
+ assert_equal(:off, @oc_config.ocg_state(@ocg))
19
+ @oc_config[:BaseState] = :Unchanged
20
+ assert_nil(@oc_config.ocg_state(@ocg))
21
+ end
22
+
23
+ it "returns :on if the OCG is in the /ON key" do
24
+ @oc_config[:ON] = [@ocg]
25
+ [:ON, :OFF, :Unchanged].each do |base_state|
26
+ @oc_config[:BaseState] = base_state
27
+ assert_equal(:on, @oc_config.ocg_state(@ocg))
28
+ end
29
+ end
30
+
31
+ it "returns :off if the OCG is in the /OFF key" do
32
+ @oc_config[:OFF] = [@ocg]
33
+ [:ON, :OFF, :Unchanged].each do |base_state|
34
+ @oc_config[:BaseState] = base_state
35
+ assert_equal(:off, @oc_config.ocg_state(@ocg))
36
+ end
37
+ end
38
+
39
+ it "adds the OCG to the respective dictionary key if a state is given" do
40
+ [[:ON, :OFF], [:OFF, :ON]].each do |state, other_state|
41
+ @oc_config[other_state] = [@ocg]
42
+ @oc_config.ocg_state(@ocg, state.downcase)
43
+ assert_equal([], @oc_config[other_state].value)
44
+ assert_equal([@ocg], @oc_config[state].value)
45
+ @oc_config.ocg_state(@ocg, state)
46
+ assert_equal([@ocg], @oc_config[state].value)
47
+ end
48
+ end
49
+
50
+ it "fails if an invalid state is given" do
51
+ assert_raises(ArgumentError) { @oc_config.ocg_state(@ocg, :unknwo) }
52
+ end
53
+ end
54
+
55
+ it "returns whether a given ocg is on" do
56
+ assert(@oc_config.ocg_on?(@ocg))
57
+ @oc_config[:OFF] = [@ocg]
58
+ refute(@oc_config.ocg_on?(@ocg))
59
+ end
60
+
61
+ describe "add_ocg_to_ui" do
62
+ it "adds the ocg to the top level" do
63
+ @oc_config.add_ocg_to_ui(@ocg)
64
+ @oc_config.add_ocg_to_ui(@ocg)
65
+ assert_equal([@ocg, @ocg], @oc_config[:Order].value)
66
+ end
67
+
68
+ it "adds the ocg under an existing label" do
69
+ @oc_config[:Order] = [:ocg1, ['Test'], :ocg2]
70
+ @oc_config.add_ocg_to_ui(@ocg, path: 'Test')
71
+ @oc_config.add_ocg_to_ui(@ocg, path: 'Test')
72
+ assert_equal([:ocg1, ['Test', @ocg, @ocg], :ocg2], @oc_config[:Order].value)
73
+ end
74
+
75
+ it "adds the ocg under a new label" do
76
+ @oc_config[:Order] = []
77
+ @oc_config.add_ocg_to_ui(@ocg, path: 'Test')
78
+ @oc_config.add_ocg_to_ui(@ocg, path: 'Test')
79
+ @oc_config.add_ocg_to_ui(@ocg, path: 'Test2')
80
+ assert_equal([['Test', @ocg, @ocg], ['Test2', @ocg]], @oc_config[:Order].value)
81
+ end
82
+
83
+ it "adds the ocg under an existing ocg" do
84
+ @oc_config[:Order] = [:ocg1, :ocg2]
85
+ @oc_config.add_ocg_to_ui(@ocg, path: :ocg2)
86
+ @oc_config.add_ocg_to_ui(@ocg, path: :ocg2)
87
+ assert_equal([:ocg1, :ocg2, [@ocg, @ocg]], @oc_config[:Order].value)
88
+ end
89
+
90
+ it "adds the ocg under a new ocg" do
91
+ @oc_config[:Order] = []
92
+ @oc_config.add_ocg_to_ui(@ocg, path: :ocg1)
93
+ @oc_config.add_ocg_to_ui(@ocg, path: :ocg1)
94
+ @oc_config.add_ocg_to_ui(@ocg, path: :ocg2)
95
+ assert_equal([:ocg1, [@ocg, @ocg], :ocg2, [@ocg]], @oc_config[:Order].value)
96
+ end
97
+
98
+ it "adds the ocg under an existing multi-level path" do
99
+ @oc_config[:Order] = [:ocg1, ['Test', :ocg2, [:ocg4, ['Test2', :ocg5]]], :ocg3]
100
+ @oc_config.add_ocg_to_ui(@ocg, path: ['Test', :ocg2, 'Test2'])
101
+ assert_equal([:ocg1, ['Test', :ocg2, [:ocg4, ['Test2', :ocg5, @ocg]]], :ocg3],
102
+ @oc_config[:Order].value)
103
+ end
104
+
105
+ it "adds the ocg under a new multi-level path" do
106
+ @oc_config[:Order] = [:ocg1, ['Test', :ocg2]]
107
+ @oc_config.add_ocg_to_ui(@ocg, path: ['Test2', :ocg3, 'Test3'])
108
+ assert_equal([:ocg1, ['Test', :ocg2], ['Test2', :ocg3, [['Test3', @ocg]]]],
109
+ @oc_config[:Order].value)
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,158 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/type/optional_content_group'
5
+ require 'hexapdf/document'
6
+
7
+ describe HexaPDF::Type::OptionalContentGroup do
8
+ before do
9
+ @doc = HexaPDF::Document.new
10
+ @ocg = @doc.add({Type: :OCG, Name: 'OCG'})
11
+ end
12
+
13
+ it "resolves all referenced type classes" do
14
+ hash = {
15
+ Usage: {
16
+ CreatorInfo: {},
17
+ Language: {},
18
+ Export: {},
19
+ Zoom: {},
20
+ Print: {},
21
+ View: {},
22
+ User: {},
23
+ PageElement: {}
24
+ }
25
+ }
26
+ ocg = @doc.add(hash, type: :OCG)
27
+ assert_kind_of(HexaPDF::Type::OptionalContentGroup, ocg)
28
+ ocu = ocg[:Usage]
29
+ assert_kind_of(HexaPDF::Type::OptionalContentGroup::OptionalContentUsage, ocu)
30
+ assert_kind_of(HexaPDF::Type::OptionalContentGroup::OptionalContentUsage::CreatorInfo,
31
+ ocu[:CreatorInfo])
32
+ assert_kind_of(HexaPDF::Type::OptionalContentGroup::OptionalContentUsage::Language,
33
+ ocu[:Language])
34
+ assert_kind_of(HexaPDF::Type::OptionalContentGroup::OptionalContentUsage::Export,
35
+ ocu[:Export])
36
+ assert_kind_of(HexaPDF::Type::OptionalContentGroup::OptionalContentUsage::Zoom,
37
+ ocu[:Zoom])
38
+ assert_kind_of(HexaPDF::Type::OptionalContentGroup::OptionalContentUsage::Print,
39
+ ocu[:Print])
40
+ assert_kind_of(HexaPDF::Type::OptionalContentGroup::OptionalContentUsage::View,
41
+ ocu[:View])
42
+ assert_kind_of(HexaPDF::Type::OptionalContentGroup::OptionalContentUsage::User,
43
+ ocu[:User])
44
+ assert_kind_of(HexaPDF::Type::OptionalContentGroup::OptionalContentUsage::PageElement,
45
+ ocu[:PageElement])
46
+ end
47
+
48
+ it "must always be an indirect object" do
49
+ assert(@ocg.must_be_indirect?)
50
+ end
51
+
52
+ it "returns the name" do
53
+ assert_equal('OCG', @ocg.name)
54
+ @ocg.name('Other')
55
+ assert_equal('Other', @ocg.name)
56
+ end
57
+
58
+ describe "intent" do
59
+ it "can be ask whether the intent is :View" do
60
+ assert(@ocg.intent_view?)
61
+ @ocg[:Intent] = :Design
62
+ refute(@ocg.intent_view?)
63
+ end
64
+
65
+ it "can be ask whether the intent is :Design" do
66
+ refute(@ocg.intent_design?)
67
+ @ocg[:Intent] = :Design
68
+ assert(@ocg.intent_design?)
69
+ end
70
+
71
+ it "can apply one or more intents" do
72
+ @ocg.apply_intent(:View)
73
+ @ocg.apply_intent(:Design)
74
+ assert(@ocg.intent_view?)
75
+ assert(@ocg.intent_design?)
76
+ end
77
+ end
78
+
79
+ describe "managing the OCG's default configuration" do
80
+ it "can be asked whether it is on by default" do
81
+ assert(@ocg.on?)
82
+ @doc.optional_content.default_configuration[:OFF] = [@ocg]
83
+ refute(@ocg.on?)
84
+ end
85
+
86
+ it "can set its default state to on" do
87
+ @doc.optional_content.default_configuration[:OFF] = [@ocg]
88
+ @ocg.on!
89
+ assert(@ocg.on?)
90
+ end
91
+
92
+ it "can set its default state to off" do
93
+ @ocg.off!
94
+ refute(@ocg.on?)
95
+ end
96
+
97
+ it "can add itself to the UI" do
98
+ @ocg.add_to_ui(path: 'Test')
99
+ assert_equal([['Test', @ocg]], @doc.optional_content.default_configuration[:Order].value)
100
+ end
101
+ end
102
+
103
+ it "can set and return the creator info usage entry" do
104
+ refute(@ocg.creator_info)
105
+ dict = @ocg.creator_info("HexaPDF", :Technical)
106
+ assert_equal({Creator: "HexaPDF", Subtype: :Technical}, dict.value)
107
+ assert_raises(ArgumentError) { @ocg.creator_info("HexaPDF") }
108
+ end
109
+
110
+ it "can set and return the language usage entry" do
111
+ refute(@ocg.language)
112
+ dict = @ocg.language('de')
113
+ assert_equal({Lang: "de", Preferred: :OFF}, dict.value)
114
+ @ocg.language('de', preferred: true)
115
+ assert_equal({Lang: "de", Preferred: :ON}, @ocg.language.value)
116
+ end
117
+
118
+ it "can set and return the export state usage entry" do
119
+ refute(@ocg.export_state)
120
+ assert(@ocg.export_state(true))
121
+ assert(@ocg.export_state)
122
+ end
123
+
124
+ it "can set and return the view state usage entry" do
125
+ refute(@ocg.view_state)
126
+ assert(@ocg.view_state(true))
127
+ assert(@ocg.view_state)
128
+ end
129
+
130
+ it "can set and return the print state usage entry" do
131
+ refute(@ocg.print_state)
132
+ dict = @ocg.print_state(true)
133
+ assert_equal({PrintState: :ON, Subtype: nil}, dict.value)
134
+ @ocg.print_state(true, subtype: :Watermark)
135
+ assert_equal({PrintState: :ON, Subtype: :Watermark}, @ocg.print_state.value)
136
+ end
137
+
138
+ it "can set and return the zoom usage entry" do
139
+ refute(@ocg.zoom)
140
+ dict = @ocg.zoom(min: 2.0)
141
+ assert_equal({min: 2.0, max: nil}, dict.value)
142
+ assert_equal({min: nil, max: 3.0}, @ocg.zoom(max: 3.0).value)
143
+ assert_equal({min: 1.0, max: 3.0}, @ocg.zoom(min: 1.0, max: 3.0).value)
144
+ end
145
+
146
+ it "can set and return the intended user usage entry" do
147
+ refute(@ocg.intended_user)
148
+ dict = @ocg.intended_user(:Ind, 'Me')
149
+ assert_equal({Type: :Ind, Name: "Me"}, dict.value)
150
+ end
151
+
152
+ it "can set and return the page element usage entry" do
153
+ refute(@ocg.page_element)
154
+ assert_equal(:HF, @ocg.page_element(:HF))
155
+ @ocg.page_element(:L)
156
+ assert_equal(:L, @ocg.page_element)
157
+ end
158
+ end
@@ -0,0 +1,109 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require 'test_helper'
4
+ require 'hexapdf/type/optional_content_properties'
5
+ require 'hexapdf/document'
6
+
7
+ describe HexaPDF::Type::OptionalContentProperties do
8
+ before do
9
+ @doc = HexaPDF::Document.new
10
+ @oc = @doc.optional_content
11
+ end
12
+
13
+ describe "add_ocg" do
14
+ it "adds a given OCG object" do
15
+ ocg = @doc.add({Type: :OCG, Name: 'test'})
16
+ assert_same(ocg, @oc.add_ocg(ocg))
17
+ assert_equal([ocg], @oc[:OCGs])
18
+ end
19
+
20
+ it "doesn't add an OCG if it has been added before" do
21
+ ocg = @doc.add({Type: :OCG, Name: 'test'})
22
+ @oc.add_ocg(ocg)
23
+ @oc.add_ocg(ocg)
24
+ assert_equal([ocg], @oc[:OCGs])
25
+ end
26
+
27
+ it "creates a new OCG object with the given name and adds it" do
28
+ ocg = @oc.add_ocg('Test')
29
+ assert_equal([ocg], @oc[:OCGs])
30
+ end
31
+ end
32
+
33
+ describe "ocg" do
34
+ it "returns the first OCG with the given name, regardless of the create argument" do
35
+ ocg1 = @oc.add_ocg('Test')
36
+ _ocg2 = @oc.add_ocg('Test')
37
+ assert_same(ocg1, @oc.ocg('Test', create: false))
38
+ assert_same(ocg1, @oc.ocg('Test', create: true))
39
+ end
40
+
41
+ it "returns nil if no OCG with the given name exists and create is false" do
42
+ assert_nil(@oc.ocg('Other', create: false))
43
+ @oc.add_ocg('Test')
44
+ assert_nil(@oc.ocg('Other', create: false))
45
+ end
46
+
47
+ it "creates an OCG with the given name if none is found and create is true" do
48
+ ocg = @oc.ocg('Test')
49
+ assert_same(ocg, @oc.ocg('Test'))
50
+ assert_equal([ocg], @oc[:OCGs])
51
+ end
52
+ end
53
+
54
+ describe "ocgs" do
55
+ it "returns the list of the known optional content groups, with duplicates removed" do
56
+ ocg1 = @oc.add_ocg(@oc.add_ocg('Test'))
57
+ @oc[:OCGs] << nil
58
+ ocg2 = @oc.add_ocg('Test')
59
+ ocg3 = @oc.add_ocg('Other')
60
+ assert_equal([ocg1, ocg2, ocg3], @oc.ocgs)
61
+ end
62
+ end
63
+
64
+ describe "create_ocmd" do
65
+ it "creates the optional content membership dictionary for the given OCGs" do
66
+ ocmd = @oc.create_ocmd(@oc.ocg('Test'))
67
+ assert_equal({Type: :OCMD, OCGs: [@oc.ocg('Test')], P: :AnyOn}, ocmd.value)
68
+
69
+ ocmd = @oc.create_ocmd([@oc.ocg('Test'), @oc.ocg('Test2')], policy: :any_off)
70
+ assert_equal({Type: :OCMD, OCGs: [@oc.ocg('Test'), @oc.ocg('Test2')], P: :AnyOff}, ocmd.value)
71
+ end
72
+
73
+ it "fails if the policy is invalid" do
74
+ error = assert_raises(ArgumentError) { @oc.create_ocmd(:ocg, policy: :unknown) }
75
+ assert_match(/Invalid OCMD.*unknown/, error.message)
76
+ end
77
+ end
78
+
79
+ describe "default_configuration" do
80
+ it "returns an existing dictionary" do
81
+ dict = @oc.default_configuration
82
+ assert_same(@oc[:D], dict)
83
+ assert_kind_of(HexaPDF::Type::OptionalContentConfiguration, dict)
84
+ end
85
+
86
+ it "sets and returns a default configuration dictionary if none is set" do
87
+ @oc.delete(:D)
88
+ assert_equal({Creator: 'HexaPDF'}, @oc.default_configuration.value)
89
+ end
90
+
91
+ it "sets the default configuration dictionary to the given value" do
92
+ d_before = @oc[:D]
93
+ d_new = @oc.default_configuration(Creator: 'Test')
94
+ refute_same(d_before, d_new)
95
+ assert_same(@oc[:D], d_new)
96
+ assert_equal({Creator: 'Test'}, d_new.value)
97
+ end
98
+ end
99
+
100
+ describe "perform_validation" do
101
+ it "creates the /D entry if it is not set" do
102
+ @oc.delete(:D)
103
+ refute(@oc.validate(auto_correct: false))
104
+ refute(@oc.key?(:D))
105
+ assert(@oc.validate(auto_correct: true))
106
+ assert_equal({Creator: 'HexaPDF'}, @oc[:D].value)
107
+ end
108
+ end
109
+ end
@@ -706,14 +706,14 @@ describe HexaPDF::Type::Page do
706
706
  @appearance[:Matrix] = [0.707106, 0.707106, -0.707106, 0.707106, 10, 30]
707
707
  @page.flatten_annotations
708
708
  assert_operators(@canvas.contents,
709
- [:concatenate_matrix, [0.998269, 0.0, 0.0, 0.415946, 111.21318, 80.60659]],
709
+ [:concatenate_matrix, [0.998269, 0.0, 0.0, 0.415946, 111.193776, 91.933396]],
710
710
  range: 1)
711
711
  end
712
712
 
713
713
  it "scales the appearance to fit into the annotations's rectangle" do
714
714
  @annot1[:Rect] = [100, 100, 130, 150]
715
715
  @page.flatten_annotations
716
- assert_operators(@canvas.contents, [:concatenate_matrix, [0.5, 0, 0, 2, 110, 105]], range: 1)
716
+ assert_operators(@canvas.contents, [:concatenate_matrix, [0.5, 0, 0, 2, 105, 110]], range: 1)
717
717
  end
718
718
  end
719
719
 
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.33.0
4
+ version: 0.34.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: 2023-08-02 00:00:00.000000000 Z
11
+ date: 2023-10-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cmdparse
@@ -299,6 +299,8 @@ files:
299
299
  - examples/023-images.rb
300
300
  - examples/024-digital-signatures.rb
301
301
  - examples/025-table_box.rb
302
+ - examples/026-optional_content.rb
303
+ - examples/027-composer_optional_content.rb
302
304
  - examples/emoji-smile.png
303
305
  - examples/emoji-wink.png
304
306
  - examples/machupicchu.jpg
@@ -474,6 +476,7 @@ files:
474
476
  - lib/hexapdf/type/actions/go_to.rb
475
477
  - lib/hexapdf/type/actions/go_to_r.rb
476
478
  - lib/hexapdf/type/actions/launch.rb
479
+ - lib/hexapdf/type/actions/set_ocg_state.rb
477
480
  - lib/hexapdf/type/actions/uri.rb
478
481
  - lib/hexapdf/type/annotation.rb
479
482
  - lib/hexapdf/type/annotations.rb
@@ -500,6 +503,10 @@ files:
500
503
  - lib/hexapdf/type/mark_information.rb
501
504
  - lib/hexapdf/type/names.rb
502
505
  - lib/hexapdf/type/object_stream.rb
506
+ - lib/hexapdf/type/optional_content_configuration.rb
507
+ - lib/hexapdf/type/optional_content_group.rb
508
+ - lib/hexapdf/type/optional_content_membership.rb
509
+ - lib/hexapdf/type/optional_content_properties.rb
503
510
  - lib/hexapdf/type/outline.rb
504
511
  - lib/hexapdf/type/outline_item.rb
505
512
  - lib/hexapdf/type/page.rb
@@ -728,6 +735,7 @@ files:
728
735
  - test/hexapdf/type/acro_form/test_text_field.rb
729
736
  - test/hexapdf/type/acro_form/test_variable_text_field.rb
730
737
  - test/hexapdf/type/actions/test_launch.rb
738
+ - test/hexapdf/type/actions/test_set_ocg_state.rb
731
739
  - test/hexapdf/type/actions/test_uri.rb
732
740
  - test/hexapdf/type/annotations/test_markup_annotation.rb
733
741
  - test/hexapdf/type/annotations/test_text.rb
@@ -748,6 +756,9 @@ files:
748
756
  - test/hexapdf/type/test_info.rb
749
757
  - test/hexapdf/type/test_names.rb
750
758
  - test/hexapdf/type/test_object_stream.rb
759
+ - test/hexapdf/type/test_optional_content_configuration.rb
760
+ - test/hexapdf/type/test_optional_content_group.rb
761
+ - test/hexapdf/type/test_optional_content_properties.rb
751
762
  - test/hexapdf/type/test_outline.rb
752
763
  - test/hexapdf/type/test_outline_item.rb
753
764
  - test/hexapdf/type/test_page.rb
@@ -784,7 +795,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
784
795
  - !ruby/object:Gem::Version
785
796
  version: '0'
786
797
  requirements: []
787
- rubygems_version: 3.5.0.dev
798
+ rubygems_version: 3.4.10
788
799
  signing_key:
789
800
  specification_version: 4
790
801
  summary: HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby