hexapdf 0.32.2 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +104 -1
- data/README.md +9 -0
- data/examples/002-graphics.rb +15 -17
- data/examples/003-arcs.rb +9 -9
- data/examples/009-text_layouter_alignment.rb +1 -1
- data/examples/010-text_layouter_inline_boxes.rb +2 -2
- data/examples/011-text_layouter_line_wrapping.rb +1 -1
- data/examples/012-text_layouter_styling.rb +7 -7
- data/examples/013-text_layouter_shapes.rb +1 -1
- data/examples/014-text_in_polygon.rb +1 -1
- data/examples/015-boxes.rb +8 -7
- data/examples/016-frame_automatic_box_placement.rb +2 -2
- data/examples/017-frame_text_flow.rb +2 -1
- data/examples/018-composer.rb +1 -1
- data/examples/020-column_box.rb +2 -1
- data/examples/025-table_box.rb +46 -0
- data/examples/026-optional_content.rb +55 -0
- data/examples/027-composer_optional_content.rb +83 -0
- data/lib/hexapdf/cli/command.rb +12 -3
- data/lib/hexapdf/cli/fonts.rb +1 -1
- data/lib/hexapdf/cli/form.rb +5 -5
- data/lib/hexapdf/cli/inspect.rb +5 -7
- data/lib/hexapdf/composer.rb +106 -53
- data/lib/hexapdf/configuration.rb +65 -40
- data/lib/hexapdf/content/canvas.rb +445 -267
- data/lib/hexapdf/content/color_space.rb +72 -25
- data/lib/hexapdf/content/graphic_object/arc.rb +57 -24
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +66 -23
- data/lib/hexapdf/content/graphic_object/geom2d.rb +47 -6
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +58 -36
- data/lib/hexapdf/content/graphic_object.rb +6 -7
- data/lib/hexapdf/content/graphics_state.rb +54 -45
- data/lib/hexapdf/content/operator.rb +54 -54
- data/lib/hexapdf/content/parser.rb +2 -2
- data/lib/hexapdf/content/processor.rb +15 -15
- data/lib/hexapdf/content/transformation_matrix.rb +1 -1
- data/lib/hexapdf/content.rb +5 -0
- data/lib/hexapdf/dictionary.rb +7 -5
- data/lib/hexapdf/dictionary_fields.rb +43 -16
- data/lib/hexapdf/digital_signature/cms_handler.rb +2 -2
- data/lib/hexapdf/digital_signature/handler.rb +1 -1
- data/lib/hexapdf/digital_signature/pkcs1_handler.rb +2 -3
- data/lib/hexapdf/digital_signature/signature.rb +6 -6
- data/lib/hexapdf/digital_signature/signatures.rb +13 -12
- data/lib/hexapdf/digital_signature/signing/default_handler.rb +14 -5
- data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +2 -4
- data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +4 -4
- data/lib/hexapdf/digital_signature/signing.rb +4 -0
- data/lib/hexapdf/digital_signature/verification_result.rb +3 -4
- data/lib/hexapdf/digital_signature.rb +7 -2
- data/lib/hexapdf/document/destinations.rb +12 -11
- data/lib/hexapdf/document/files.rb +1 -1
- data/lib/hexapdf/document/fonts.rb +1 -1
- data/lib/hexapdf/document/layout.rb +170 -39
- data/lib/hexapdf/document/pages.rb +4 -3
- data/lib/hexapdf/document.rb +96 -55
- data/lib/hexapdf/encryption/aes.rb +5 -5
- data/lib/hexapdf/encryption/arc4.rb +1 -1
- data/lib/hexapdf/encryption/fast_aes.rb +2 -2
- data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
- data/lib/hexapdf/encryption/identity.rb +1 -1
- data/lib/hexapdf/encryption/ruby_aes.rb +11 -21
- data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
- data/lib/hexapdf/encryption/security_handler.rb +31 -24
- data/lib/hexapdf/encryption/standard_security_handler.rb +45 -36
- data/lib/hexapdf/encryption.rb +7 -2
- data/lib/hexapdf/error.rb +18 -0
- data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
- data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
- data/lib/hexapdf/filter/flate_decode.rb +1 -1
- data/lib/hexapdf/filter/lzw_decode.rb +1 -1
- data/lib/hexapdf/filter/pass_through.rb +1 -1
- data/lib/hexapdf/filter/predictor.rb +1 -1
- data/lib/hexapdf/filter/run_length_decode.rb +1 -1
- data/lib/hexapdf/filter.rb +55 -6
- data/lib/hexapdf/font/cmap/parser.rb +2 -2
- data/lib/hexapdf/font/cmap.rb +1 -1
- data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +2 -2
- data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +3 -3
- data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
- data/lib/hexapdf/font/invalid_glyph.rb +3 -0
- data/lib/hexapdf/font/true_type_wrapper.rb +17 -4
- data/lib/hexapdf/font/type1_wrapper.rb +19 -4
- data/lib/hexapdf/font_loader/from_configuration.rb +5 -2
- data/lib/hexapdf/font_loader/from_file.rb +5 -5
- data/lib/hexapdf/font_loader/standard14.rb +3 -3
- data/lib/hexapdf/font_loader.rb +3 -0
- data/lib/hexapdf/image_loader/jpeg.rb +2 -2
- data/lib/hexapdf/image_loader/pdf.rb +1 -1
- data/lib/hexapdf/image_loader/png.rb +2 -2
- data/lib/hexapdf/image_loader.rb +1 -1
- data/lib/hexapdf/importer.rb +13 -0
- data/lib/hexapdf/layout/box.rb +32 -5
- data/lib/hexapdf/layout/box_fitter.rb +2 -2
- data/lib/hexapdf/layout/column_box.rb +20 -5
- data/lib/hexapdf/layout/frame.rb +53 -18
- data/lib/hexapdf/layout/image_box.rb +5 -0
- data/lib/hexapdf/layout/inline_box.rb +21 -9
- data/lib/hexapdf/layout/list_box.rb +50 -20
- data/lib/hexapdf/layout/page_style.rb +6 -5
- data/lib/hexapdf/layout/style.rb +64 -9
- data/lib/hexapdf/layout/table_box.rb +684 -0
- data/lib/hexapdf/layout/text_box.rb +12 -3
- data/lib/hexapdf/layout/text_fragment.rb +29 -3
- data/lib/hexapdf/layout/text_layouter.rb +32 -8
- data/lib/hexapdf/layout.rb +1 -0
- data/lib/hexapdf/name_tree_node.rb +1 -1
- data/lib/hexapdf/number_tree_node.rb +1 -1
- data/lib/hexapdf/object.rb +18 -7
- data/lib/hexapdf/parser.rb +7 -7
- data/lib/hexapdf/pdf_array.rb +1 -1
- data/lib/hexapdf/rectangle.rb +1 -1
- data/lib/hexapdf/reference.rb +1 -1
- data/lib/hexapdf/revision.rb +1 -1
- data/lib/hexapdf/revisions.rb +3 -3
- data/lib/hexapdf/serializer.rb +15 -15
- data/lib/hexapdf/stream.rb +5 -4
- data/lib/hexapdf/tokenizer.rb +14 -14
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +22 -22
- data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/field.rb +2 -2
- data/lib/hexapdf/type/acro_form/form.rb +1 -1
- data/lib/hexapdf/type/acro_form/signature_field.rb +4 -4
- data/lib/hexapdf/type/acro_form/text_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/variable_text_field.rb +1 -1
- data/lib/hexapdf/type/acro_form.rb +1 -1
- data/lib/hexapdf/type/action.rb +1 -1
- data/lib/hexapdf/type/actions/go_to.rb +1 -1
- data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
- data/lib/hexapdf/type/actions/launch.rb +1 -1
- data/lib/hexapdf/type/actions/set_ocg_state.rb +86 -0
- data/lib/hexapdf/type/actions/uri.rb +1 -1
- data/lib/hexapdf/type/actions.rb +2 -1
- data/lib/hexapdf/type/annotation.rb +3 -3
- data/lib/hexapdf/type/annotations/link.rb +1 -1
- data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
- data/lib/hexapdf/type/annotations/text.rb +2 -3
- data/lib/hexapdf/type/annotations/widget.rb +2 -2
- data/lib/hexapdf/type/annotations.rb +1 -1
- data/lib/hexapdf/type/catalog.rb +11 -2
- data/lib/hexapdf/type/cid_font.rb +18 -4
- data/lib/hexapdf/type/embedded_file.rb +1 -1
- data/lib/hexapdf/type/file_specification.rb +2 -2
- data/lib/hexapdf/type/font_descriptor.rb +1 -1
- data/lib/hexapdf/type/font_simple.rb +2 -2
- data/lib/hexapdf/type/font_type0.rb +3 -3
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/form.rb +76 -6
- data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
- data/lib/hexapdf/type/icon_fit.rb +1 -1
- data/lib/hexapdf/type/image.rb +1 -1
- data/lib/hexapdf/type/info.rb +1 -1
- data/lib/hexapdf/type/mark_information.rb +1 -1
- data/lib/hexapdf/type/names.rb +2 -2
- data/lib/hexapdf/type/object_stream.rb +2 -1
- data/lib/hexapdf/type/optional_content_configuration.rb +170 -0
- data/lib/hexapdf/type/optional_content_group.rb +370 -0
- data/lib/hexapdf/type/optional_content_membership.rb +63 -0
- data/lib/hexapdf/type/optional_content_properties.rb +158 -0
- data/lib/hexapdf/type/outline.rb +1 -1
- data/lib/hexapdf/type/outline_item.rb +1 -1
- data/lib/hexapdf/type/page.rb +46 -21
- data/lib/hexapdf/type/page_label.rb +5 -9
- data/lib/hexapdf/type/page_tree_node.rb +1 -1
- data/lib/hexapdf/type/resources.rb +1 -1
- data/lib/hexapdf/type/trailer.rb +2 -2
- data/lib/hexapdf/type/viewer_preferences.rb +1 -1
- data/lib/hexapdf/type/xref_stream.rb +2 -2
- data/lib/hexapdf/type.rb +4 -0
- data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -2
- data/lib/hexapdf/version.rb +1 -1
- data/lib/hexapdf/writer.rb +4 -4
- data/lib/hexapdf/xref_section.rb +2 -2
- data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +11 -1
- data/test/hexapdf/content/graphic_object/test_geom2d.rb +7 -0
- data/test/hexapdf/content/test_canvas.rb +49 -1
- data/test/hexapdf/digital_signature/test_signatures.rb +22 -0
- data/test/hexapdf/document/test_files.rb +2 -2
- data/test/hexapdf/document/test_layout.rb +105 -2
- data/test/hexapdf/document/test_pages.rb +6 -6
- data/test/hexapdf/encryption/test_security_handler.rb +12 -11
- data/test/hexapdf/encryption/test_standard_security_handler.rb +35 -23
- data/test/hexapdf/font/test_true_type_wrapper.rb +18 -1
- data/test/hexapdf/font/test_type1_wrapper.rb +15 -1
- data/test/hexapdf/layout/test_box.rb +14 -5
- data/test/hexapdf/layout/test_column_box.rb +65 -21
- data/test/hexapdf/layout/test_frame.rb +27 -15
- data/test/hexapdf/layout/test_image_box.rb +4 -0
- data/test/hexapdf/layout/test_inline_box.rb +17 -3
- data/test/hexapdf/layout/test_list_box.rb +84 -33
- data/test/hexapdf/layout/test_page_style.rb +3 -2
- data/test/hexapdf/layout/test_style.rb +60 -0
- data/test/hexapdf/layout/test_table_box.rb +728 -0
- data/test/hexapdf/layout/test_text_box.rb +26 -0
- data/test/hexapdf/layout/test_text_fragment.rb +33 -0
- data/test/hexapdf/layout/test_text_layouter.rb +36 -5
- data/test/hexapdf/test_composer.rb +10 -0
- data/test/hexapdf/test_dictionary.rb +10 -0
- data/test/hexapdf/test_dictionary_fields.rb +4 -1
- data/test/hexapdf/test_document.rb +5 -0
- data/test/hexapdf/test_filter.rb +8 -0
- data/test/hexapdf/test_importer.rb +9 -0
- data/test/hexapdf/test_object.rb +16 -5
- data/test/hexapdf/test_stream.rb +7 -0
- data/test/hexapdf/test_writer.rb +3 -3
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +13 -5
- data/test/hexapdf/type/acro_form/test_form.rb +4 -3
- data/test/hexapdf/type/actions/test_set_ocg_state.rb +40 -0
- data/test/hexapdf/type/test_catalog.rb +11 -0
- data/test/hexapdf/type/test_form.rb +119 -0
- data/test/hexapdf/type/test_optional_content_configuration.rb +112 -0
- data/test/hexapdf/type/test_optional_content_group.rb +158 -0
- data/test/hexapdf/type/test_optional_content_properties.rb +109 -0
- data/test/hexapdf/type/test_page.rb +20 -6
- metadata +28 -8
|
@@ -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
|
|
@@ -557,7 +557,7 @@ describe HexaPDF::Type::Page do
|
|
|
557
557
|
@page = @doc.pages.add
|
|
558
558
|
@appearance = @doc.add({Type: :XObject, Subtype: :Form, BBox: [-10, -5, 50, 20]}, stream: "")
|
|
559
559
|
@annot1 = @doc.add({Type: :Annot, Subtype: :Text, Rect: [100, 100, 160, 125], AP: {N: @appearance}})
|
|
560
|
-
@annot2 = @doc.add({Rect: [10, 10, 70, 35], AP: {N: @appearance}})
|
|
560
|
+
@annot2 = @doc.add({Type: :Annot, Subtype: :Text, Rect: [10, 10, 70, 35], AP: {N: @appearance}})
|
|
561
561
|
@page[:Annots] = [@annot1, @annot2]
|
|
562
562
|
@canvas = @page.canvas(type: :overlay)
|
|
563
563
|
end
|
|
@@ -591,6 +591,18 @@ describe HexaPDF::Type::Page do
|
|
|
591
591
|
assert(@annot2.null?)
|
|
592
592
|
end
|
|
593
593
|
|
|
594
|
+
it "gracefully handles invalid /Annot key values" do
|
|
595
|
+
@page[:Annots] << nil << @doc.add({}, stream: '')
|
|
596
|
+
result = @page.flatten_annotations
|
|
597
|
+
assert(result.empty?)
|
|
598
|
+
assert(@annot1.null?)
|
|
599
|
+
assert(@annot2.null?)
|
|
600
|
+
|
|
601
|
+
@page[:Annots] = @doc.add({}, stream: '')
|
|
602
|
+
result = @page.flatten_annotations
|
|
603
|
+
assert(result.empty?)
|
|
604
|
+
end
|
|
605
|
+
|
|
594
606
|
it "only deletes the widget annotation of a form field even if it is embedded in the field object" do
|
|
595
607
|
form = @doc.acro_form(create: true)
|
|
596
608
|
field = form.create_text_field('test')
|
|
@@ -631,7 +643,7 @@ describe HexaPDF::Type::Page do
|
|
|
631
643
|
[:restore_graphics_state]])
|
|
632
644
|
end
|
|
633
645
|
|
|
634
|
-
it "ignores annotations without
|
|
646
|
+
it "ignores annotations without appearance stream" do
|
|
635
647
|
@annot1.delete(:AP)
|
|
636
648
|
result = @page.flatten_annotations
|
|
637
649
|
assert_equal([@annot1], result)
|
|
@@ -694,24 +706,26 @@ describe HexaPDF::Type::Page do
|
|
|
694
706
|
@appearance[:Matrix] = [0.707106, 0.707106, -0.707106, 0.707106, 10, 30]
|
|
695
707
|
@page.flatten_annotations
|
|
696
708
|
assert_operators(@canvas.contents,
|
|
697
|
-
[:concatenate_matrix, [0.998269, 0.0, 0.0, 0.415946, 111.
|
|
709
|
+
[:concatenate_matrix, [0.998269, 0.0, 0.0, 0.415946, 111.193776, 91.933396]],
|
|
698
710
|
range: 1)
|
|
699
711
|
end
|
|
700
712
|
|
|
701
713
|
it "scales the appearance to fit into the annotations's rectangle" do
|
|
702
714
|
@annot1[:Rect] = [100, 100, 130, 150]
|
|
703
715
|
@page.flatten_annotations
|
|
704
|
-
assert_operators(@canvas.contents, [:concatenate_matrix, [0.5, 0, 0, 2,
|
|
716
|
+
assert_operators(@canvas.contents, [:concatenate_matrix, [0.5, 0, 0, 2, 105, 110]], range: 1)
|
|
705
717
|
end
|
|
706
718
|
end
|
|
707
719
|
|
|
708
720
|
it "yields each annotation" do
|
|
709
721
|
page = @doc.pages.add
|
|
710
722
|
annot1 = @doc.add({Type: :Annot, Subtype: :Text, Rect: [100, 100, 160, 125]})
|
|
711
|
-
annot2 = @doc.add({Rect: [10, 10, 70, 35]})
|
|
712
|
-
|
|
723
|
+
annot2 = @doc.add({Subtype: :Unknown, Rect: [10, 10, 70, 35]})
|
|
724
|
+
not_an_annot = @doc.add({}, stream: '')
|
|
725
|
+
page[:Annots] = [not_an_annot, annot1, nil, annot2]
|
|
713
726
|
|
|
714
727
|
annotations = page.each_annotation.to_a
|
|
728
|
+
assert_equal(2, annotations.size)
|
|
715
729
|
assert_equal([100, 100, 160, 125], annotations[0][:Rect])
|
|
716
730
|
assert_equal(:Annot, annotations[0].type)
|
|
717
731
|
assert_equal(:Annot, annotations[1].type)
|
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.34.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Thomas Leitner
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-
|
|
11
|
+
date: 2023-10-22 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: cmdparse
|
|
@@ -36,14 +36,20 @@ dependencies:
|
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '0.
|
|
39
|
+
version: '0.4'
|
|
40
|
+
- - ">="
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: 0.4.1
|
|
40
43
|
type: :runtime
|
|
41
44
|
prerelease: false
|
|
42
45
|
version_requirements: !ruby/object:Gem::Requirement
|
|
43
46
|
requirements:
|
|
44
47
|
- - "~>"
|
|
45
48
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '0.
|
|
49
|
+
version: '0.4'
|
|
50
|
+
- - ">="
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: 0.4.1
|
|
47
53
|
- !ruby/object:Gem::Dependency
|
|
48
54
|
name: openssl
|
|
49
55
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -292,6 +298,9 @@ files:
|
|
|
292
298
|
- examples/022-outline.rb
|
|
293
299
|
- examples/023-images.rb
|
|
294
300
|
- examples/024-digital-signatures.rb
|
|
301
|
+
- examples/025-table_box.rb
|
|
302
|
+
- examples/026-optional_content.rb
|
|
303
|
+
- examples/027-composer_optional_content.rb
|
|
295
304
|
- examples/emoji-smile.png
|
|
296
305
|
- examples/emoji-wink.png
|
|
297
306
|
- examples/machupicchu.jpg
|
|
@@ -430,6 +439,7 @@ files:
|
|
|
430
439
|
- lib/hexapdf/layout/numeric_refinements.rb
|
|
431
440
|
- lib/hexapdf/layout/page_style.rb
|
|
432
441
|
- lib/hexapdf/layout/style.rb
|
|
442
|
+
- lib/hexapdf/layout/table_box.rb
|
|
433
443
|
- lib/hexapdf/layout/text_box.rb
|
|
434
444
|
- lib/hexapdf/layout/text_fragment.rb
|
|
435
445
|
- lib/hexapdf/layout/text_layouter.rb
|
|
@@ -466,6 +476,7 @@ files:
|
|
|
466
476
|
- lib/hexapdf/type/actions/go_to.rb
|
|
467
477
|
- lib/hexapdf/type/actions/go_to_r.rb
|
|
468
478
|
- lib/hexapdf/type/actions/launch.rb
|
|
479
|
+
- lib/hexapdf/type/actions/set_ocg_state.rb
|
|
469
480
|
- lib/hexapdf/type/actions/uri.rb
|
|
470
481
|
- lib/hexapdf/type/annotation.rb
|
|
471
482
|
- lib/hexapdf/type/annotations.rb
|
|
@@ -492,6 +503,10 @@ files:
|
|
|
492
503
|
- lib/hexapdf/type/mark_information.rb
|
|
493
504
|
- lib/hexapdf/type/names.rb
|
|
494
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
|
|
495
510
|
- lib/hexapdf/type/outline.rb
|
|
496
511
|
- lib/hexapdf/type/outline_item.rb
|
|
497
512
|
- lib/hexapdf/type/page.rb
|
|
@@ -682,6 +697,7 @@ files:
|
|
|
682
697
|
- test/hexapdf/layout/test_list_box.rb
|
|
683
698
|
- test/hexapdf/layout/test_page_style.rb
|
|
684
699
|
- test/hexapdf/layout/test_style.rb
|
|
700
|
+
- test/hexapdf/layout/test_table_box.rb
|
|
685
701
|
- test/hexapdf/layout/test_text_box.rb
|
|
686
702
|
- test/hexapdf/layout/test_text_fragment.rb
|
|
687
703
|
- test/hexapdf/layout/test_text_layouter.rb
|
|
@@ -719,6 +735,7 @@ files:
|
|
|
719
735
|
- test/hexapdf/type/acro_form/test_text_field.rb
|
|
720
736
|
- test/hexapdf/type/acro_form/test_variable_text_field.rb
|
|
721
737
|
- test/hexapdf/type/actions/test_launch.rb
|
|
738
|
+
- test/hexapdf/type/actions/test_set_ocg_state.rb
|
|
722
739
|
- test/hexapdf/type/actions/test_uri.rb
|
|
723
740
|
- test/hexapdf/type/annotations/test_markup_annotation.rb
|
|
724
741
|
- test/hexapdf/type/annotations/test_text.rb
|
|
@@ -739,6 +756,9 @@ files:
|
|
|
739
756
|
- test/hexapdf/type/test_info.rb
|
|
740
757
|
- test/hexapdf/type/test_names.rb
|
|
741
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
|
|
742
762
|
- test/hexapdf/type/test_outline.rb
|
|
743
763
|
- test/hexapdf/type/test_outline_item.rb
|
|
744
764
|
- test/hexapdf/type/test_page.rb
|
|
@@ -760,7 +780,7 @@ licenses:
|
|
|
760
780
|
- AGPL-3.0
|
|
761
781
|
- Nonstandard
|
|
762
782
|
metadata: {}
|
|
763
|
-
post_install_message:
|
|
783
|
+
post_install_message:
|
|
764
784
|
rdoc_options: []
|
|
765
785
|
require_paths:
|
|
766
786
|
- lib
|
|
@@ -775,8 +795,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
775
795
|
- !ruby/object:Gem::Version
|
|
776
796
|
version: '0'
|
|
777
797
|
requirements: []
|
|
778
|
-
rubygems_version: 3.4.
|
|
779
|
-
signing_key:
|
|
798
|
+
rubygems_version: 3.4.10
|
|
799
|
+
signing_key:
|
|
780
800
|
specification_version: 4
|
|
781
801
|
summary: HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
782
802
|
test_files: []
|