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
data/lib/hexapdf/tokenizer.rb
CHANGED
|
@@ -42,7 +42,7 @@ module HexaPDF
|
|
|
42
42
|
|
|
43
43
|
# Tokenizes the content of an IO object following the PDF rules.
|
|
44
44
|
#
|
|
45
|
-
# See:
|
|
45
|
+
# See: PDF2.0 s7.2
|
|
46
46
|
class Tokenizer
|
|
47
47
|
|
|
48
48
|
# Represents a keyword in a PDF file.
|
|
@@ -61,12 +61,12 @@ module HexaPDF
|
|
|
61
61
|
|
|
62
62
|
# Characters defined as whitespace.
|
|
63
63
|
#
|
|
64
|
-
# See:
|
|
64
|
+
# See: PDF2.0 s7.2.2
|
|
65
65
|
WHITESPACE = " \n\r\0\t\f"
|
|
66
66
|
|
|
67
67
|
# Characters defined as delimiters.
|
|
68
68
|
#
|
|
69
|
-
# See:
|
|
69
|
+
# See: PDF2.0 s7.2.2
|
|
70
70
|
DELIMITER = "()<>{}/[]%"
|
|
71
71
|
|
|
72
72
|
WHITESPACE_MULTI_RE = /[#{WHITESPACE}]+/ # :nodoc:
|
|
@@ -171,7 +171,7 @@ module HexaPDF
|
|
|
171
171
|
# If the +allow_end_array_token+ argument is +true+, the ']' token is permitted to facilitate
|
|
172
172
|
# the use of this method during array parsing.
|
|
173
173
|
#
|
|
174
|
-
# See:
|
|
174
|
+
# See: PDF2.0 s7.3
|
|
175
175
|
def next_object(allow_end_array_token: false, allow_keyword: false)
|
|
176
176
|
token = next_token
|
|
177
177
|
|
|
@@ -231,7 +231,7 @@ module HexaPDF
|
|
|
231
231
|
# If a problem is detected, yields to caller where the argument +recoverable+ is truthy if the
|
|
232
232
|
# problem is recoverable.
|
|
233
233
|
#
|
|
234
|
-
# See:
|
|
234
|
+
# See: PDF2.0 7.5.4
|
|
235
235
|
def next_xref_entry #:yield: recoverable
|
|
236
236
|
prepare_string_scanner(20)
|
|
237
237
|
if !@ss.skip(/(\d{10}) (\d{5}) ([nf])(?: \r| \n|\r\n|(\r\r|\r|\n))/) || @ss[4]
|
|
@@ -242,7 +242,7 @@ module HexaPDF
|
|
|
242
242
|
|
|
243
243
|
# Skips all whitespace at the current position.
|
|
244
244
|
#
|
|
245
|
-
# See:
|
|
245
|
+
# See: PDF2.0 s7.2.2
|
|
246
246
|
def skip_whitespace
|
|
247
247
|
prepare_string_scanner
|
|
248
248
|
prepare_string_scanner while @ss.skip(WHITESPACE_MULTI_RE)
|
|
@@ -268,7 +268,7 @@ module HexaPDF
|
|
|
268
268
|
|
|
269
269
|
# Parses the keyword at the current position.
|
|
270
270
|
#
|
|
271
|
-
# See:
|
|
271
|
+
# See: PDF2.0 s7.2
|
|
272
272
|
def parse_keyword
|
|
273
273
|
str = scan_until(WHITESPACE_OR_DELIMITER_RE) || @ss.scan(/.*/)
|
|
274
274
|
TOKEN_CACHE[str]
|
|
@@ -278,12 +278,12 @@ module HexaPDF
|
|
|
278
278
|
|
|
279
279
|
# Parses the number (integer or real) at the current position.
|
|
280
280
|
#
|
|
281
|
-
# See:
|
|
281
|
+
# See: PDF2.0 s7.3.3
|
|
282
282
|
def parse_number
|
|
283
283
|
val = scan_until(WHITESPACE_OR_DELIMITER_RE) || @ss.scan(/.*/)
|
|
284
284
|
if val.match?(/\A[+-]?\d++(?!\.)\z/)
|
|
285
285
|
tmp = val.to_i
|
|
286
|
-
# Handle object references, see
|
|
286
|
+
# Handle object references, see PDF2.0 s7.3.10
|
|
287
287
|
prepare_string_scanner(10)
|
|
288
288
|
if @ss.scan(REFERENCE_RE)
|
|
289
289
|
tmp = if tmp > 0
|
|
@@ -315,7 +315,7 @@ module HexaPDF
|
|
|
315
315
|
|
|
316
316
|
# Parses the literal string at the current position.
|
|
317
317
|
#
|
|
318
|
-
# See:
|
|
318
|
+
# See: PDF2.0 s7.3.4.2
|
|
319
319
|
def parse_literal_string
|
|
320
320
|
@ss.pos += 1
|
|
321
321
|
str = "".b
|
|
@@ -358,7 +358,7 @@ module HexaPDF
|
|
|
358
358
|
|
|
359
359
|
# Parses the hex string at the current position.
|
|
360
360
|
#
|
|
361
|
-
# See:
|
|
361
|
+
# See: PDF2.0 s7.3.4.3
|
|
362
362
|
def parse_hex_string
|
|
363
363
|
@ss.pos += 1
|
|
364
364
|
data = scan_until(/(?=>)/)
|
|
@@ -373,7 +373,7 @@ module HexaPDF
|
|
|
373
373
|
|
|
374
374
|
# Parses the name at the current position.
|
|
375
375
|
#
|
|
376
|
-
# See:
|
|
376
|
+
# See: PDF2.0 s7.3.5
|
|
377
377
|
def parse_name
|
|
378
378
|
@ss.pos += 1
|
|
379
379
|
str = scan_until(WHITESPACE_OR_DELIMITER_RE) || @ss.scan(/.*/)
|
|
@@ -389,7 +389,7 @@ module HexaPDF
|
|
|
389
389
|
#
|
|
390
390
|
# It is assumed that the initial '[' has already been scanned.
|
|
391
391
|
#
|
|
392
|
-
# See:
|
|
392
|
+
# See: PDF2.0 s7.3.6
|
|
393
393
|
def parse_array
|
|
394
394
|
result = []
|
|
395
395
|
while true
|
|
@@ -408,7 +408,7 @@ module HexaPDF
|
|
|
408
408
|
#
|
|
409
409
|
# It is assumed that the initial '<<' has already been scanned.
|
|
410
410
|
#
|
|
411
|
-
# See:
|
|
411
|
+
# See: PDF2.0 s7.3.7
|
|
412
412
|
def parse_dictionary
|
|
413
413
|
result = {}
|
|
414
414
|
while true
|
|
@@ -61,7 +61,7 @@ module HexaPDF
|
|
|
61
61
|
# By subclassing and overriding the necessary methods it is possible to define custom
|
|
62
62
|
# appearances.
|
|
63
63
|
#
|
|
64
|
-
# See:
|
|
64
|
+
# See: PDF2.0 s12.5.5, s12.7
|
|
65
65
|
class AppearanceGenerator
|
|
66
66
|
|
|
67
67
|
# Creates a new instance for the given +widget+.
|
|
@@ -200,7 +200,7 @@ module HexaPDF
|
|
|
200
200
|
def create_text_appearances
|
|
201
201
|
default_resources = @document.acro_form.default_resources
|
|
202
202
|
font, font_size, font_color = retrieve_font_information(default_resources)
|
|
203
|
-
style = HexaPDF::Layout::Style.new(font: font, fill_color: font_color)
|
|
203
|
+
style = HexaPDF::Layout::Style.new(font: font, font_size: font_size, fill_color: font_color)
|
|
204
204
|
border_style = @widget.border_style
|
|
205
205
|
padding = [1, border_style.width].max
|
|
206
206
|
|
|
@@ -226,8 +226,6 @@ module HexaPDF
|
|
|
226
226
|
|
|
227
227
|
canvas = form.canvas
|
|
228
228
|
apply_background_and_border(border_style, canvas)
|
|
229
|
-
style.font_size = calculate_font_size(font, font_size, height, border_style)
|
|
230
|
-
style.clear_cache
|
|
231
229
|
|
|
232
230
|
canvas.marked_content_sequence(:Tx) do
|
|
233
231
|
if @field.field_value || @field.concrete_field_type == :list_box
|
|
@@ -362,6 +360,7 @@ module HexaPDF
|
|
|
362
360
|
def draw_single_line_text(canvas, width, height, style, padding)
|
|
363
361
|
value, text_color = apply_javascript_formatting(@field.field_value)
|
|
364
362
|
style.fill_color = text_color if text_color
|
|
363
|
+
calculate_and_apply_font_size(value, style, width, height, padding)
|
|
365
364
|
fragment = HexaPDF::Layout::TextFragment.create(value, style)
|
|
366
365
|
|
|
367
366
|
if @field.concrete_field_type == :comb_text_field
|
|
@@ -431,6 +430,11 @@ module HexaPDF
|
|
|
431
430
|
|
|
432
431
|
# Draws the visible option items of the list box in the widget's rectangle.
|
|
433
432
|
def draw_list_box(canvas, width, height, style, padding)
|
|
433
|
+
if style.font_size == 0
|
|
434
|
+
style.font_size = 12 # Seems to be Adobe's default
|
|
435
|
+
style.clear_cache
|
|
436
|
+
end
|
|
437
|
+
|
|
434
438
|
option_items = @field.option_items
|
|
435
439
|
top_index = @field.list_box_top_index
|
|
436
440
|
items = [Layout::TextFragment.create(option_items[top_index..-1].join("\n"), style)]
|
|
@@ -475,24 +479,20 @@ module HexaPDF
|
|
|
475
479
|
[font, font_size, font_color]
|
|
476
480
|
end
|
|
477
481
|
|
|
478
|
-
# Calculates the font size for text fields based on the font
|
|
479
|
-
# appearance string, the annotation rectangle's height and
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
end
|
|
493
|
-
else
|
|
494
|
-
font_size
|
|
495
|
-
end
|
|
482
|
+
# Calculates the font size for single line text fields using auto-sizing, based on the font
|
|
483
|
+
# and font size of the default appearance string, the annotation rectangle's height and
|
|
484
|
+
# width and the given padding. The font size is then applied to the provided style object.
|
|
485
|
+
def calculate_and_apply_font_size(value, style, width, height, padding)
|
|
486
|
+
return if style.font_size != 0
|
|
487
|
+
|
|
488
|
+
font = style.font
|
|
489
|
+
unit_font_size = (font.wrapped_font.bounding_box[3] - font.wrapped_font.bounding_box[1]) *
|
|
490
|
+
font.scaling_factor / 1000.0
|
|
491
|
+
# The constant factor was found empirically by checking what Adobe Reader etc. do
|
|
492
|
+
style.font_size = (height - 2 * padding) / unit_font_size * 0.85
|
|
493
|
+
fragment = HexaPDF::Layout::TextFragment.create(value, style)
|
|
494
|
+
style.font_size = [style.font_size, style.font_size * (width - 4 * padding) / fragment.width].min
|
|
495
|
+
style.clear_cache
|
|
496
496
|
end
|
|
497
497
|
|
|
498
498
|
# Handles Javascript formatting routines for single-line text fields.
|
|
@@ -81,7 +81,7 @@ module HexaPDF
|
|
|
81
81
|
# :radios_in_unison:: A group of radio buttons with the same value for the on state will turn
|
|
82
82
|
# on or off in unison.
|
|
83
83
|
#
|
|
84
|
-
# See:
|
|
84
|
+
# See: PDF2.0 s12.7.4.2
|
|
85
85
|
class ButtonField < Field
|
|
86
86
|
|
|
87
87
|
define_type :XXAcroFormField
|
|
@@ -86,7 +86,7 @@ module HexaPDF
|
|
|
86
86
|
# to combination of the superclass value of the constant and the mapping of flag names to bit
|
|
87
87
|
# indices.
|
|
88
88
|
#
|
|
89
|
-
# See:
|
|
89
|
+
# See: PDF2.0 s12.7.4.1
|
|
90
90
|
class Field < Dictionary
|
|
91
91
|
|
|
92
92
|
# Provides a #value method for hash that returns self so that a Hash can be used
|
|
@@ -367,7 +367,7 @@ module HexaPDF
|
|
|
367
367
|
document.pages.each do |page|
|
|
368
368
|
if page.key?(:Annots) && (index = page[:Annots].index(self))
|
|
369
369
|
page[:Annots][index] = widget
|
|
370
|
-
break # Each annotation dictionary may only appear on one page, see
|
|
370
|
+
break # Each annotation dictionary may only appear on one page, see PDF2.0 12.5.2
|
|
371
371
|
end
|
|
372
372
|
end
|
|
373
373
|
widget
|
|
@@ -68,7 +68,7 @@ module HexaPDF
|
|
|
68
68
|
# HexaPDF uses the configuration option +acro_form.create_appearance_streams+ to determine
|
|
69
69
|
# whether appearances should automatically be generated.
|
|
70
70
|
#
|
|
71
|
-
# See:
|
|
71
|
+
# See: PDF2.0 s12.7.3, Field, HexaPDF::Type::Annotations::Widget
|
|
72
72
|
class Form < Dictionary
|
|
73
73
|
|
|
74
74
|
extend Utils::BitField
|
|
@@ -49,13 +49,13 @@ module HexaPDF
|
|
|
49
49
|
# If the signature should not be visible, the associated widget annotation should have zero
|
|
50
50
|
# width and height; and/or the 'hidden' or 'no_view' flags of the annotation should be set.
|
|
51
51
|
#
|
|
52
|
-
# See:
|
|
52
|
+
# See: PDF2.0 s12.7.5.5
|
|
53
53
|
class SignatureField < Field
|
|
54
54
|
|
|
55
55
|
# A signature field lock dictionary specifies a set of form fields that should be locked
|
|
56
56
|
# once the associated signature field is signed.
|
|
57
57
|
#
|
|
58
|
-
# See:
|
|
58
|
+
# See: PDF2.0 s12.7.5.5
|
|
59
59
|
class LockDictionary < Dictionary
|
|
60
60
|
|
|
61
61
|
define_type :SigFieldLock
|
|
@@ -86,7 +86,7 @@ module HexaPDF
|
|
|
86
86
|
# The available flags are: filter, sub_filter, v, reasons, legal_attestation, add_rev_info
|
|
87
87
|
# and digest_method.
|
|
88
88
|
#
|
|
89
|
-
# See:
|
|
89
|
+
# See: PDF2.0 s12.7.5.5
|
|
90
90
|
class SeedValueDictionary < Dictionary
|
|
91
91
|
|
|
92
92
|
extend Utils::BitField
|
|
@@ -145,7 +145,7 @@ module HexaPDF
|
|
|
145
145
|
#
|
|
146
146
|
# The available flags are: subject, issuer, oid, subject_dn, reserved, key_usage and url.
|
|
147
147
|
#
|
|
148
|
-
# See:
|
|
148
|
+
# See: PDF2.0 s12.7.5.5
|
|
149
149
|
class CertificateSeedValueDictionary < Dictionary
|
|
150
150
|
|
|
151
151
|
extend Utils::BitField
|
data/lib/hexapdf/type/action.rb
CHANGED
|
@@ -44,7 +44,7 @@ module HexaPDF
|
|
|
44
44
|
# Action dictionaries are used, for example, by annotations or outline items to specify the
|
|
45
45
|
# action that should be performed. Each action class should be defined under the Actions module.
|
|
46
46
|
#
|
|
47
|
-
# See:
|
|
47
|
+
# See: PDF2.0 s12.6
|
|
48
48
|
class Action < Dictionary
|
|
49
49
|
|
|
50
50
|
define_type :Action
|
|
@@ -42,7 +42,7 @@ module HexaPDF
|
|
|
42
42
|
|
|
43
43
|
# A Launch action dictionary launches an application, opens a document or prints a document.
|
|
44
44
|
#
|
|
45
|
-
# See:
|
|
45
|
+
# See: PDF2.0 s12.6.4.6
|
|
46
46
|
class Launch < Action
|
|
47
47
|
|
|
48
48
|
# The type used for the /Win field of a Launch action dictionary.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
|
2
|
+
#
|
|
3
|
+
#--
|
|
4
|
+
# This file is part of HexaPDF.
|
|
5
|
+
#
|
|
6
|
+
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
|
7
|
+
# Copyright (C) 2014-2023 Thomas Leitner
|
|
8
|
+
#
|
|
9
|
+
# HexaPDF is free software: you can redistribute it and/or modify it
|
|
10
|
+
# under the terms of the GNU Affero General Public License version 3 as
|
|
11
|
+
# published by the Free Software Foundation with the addition of the
|
|
12
|
+
# following permission added to Section 15 as permitted in Section 7(a):
|
|
13
|
+
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
|
|
14
|
+
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
|
|
15
|
+
# INFRINGEMENT OF THIRD PARTY RIGHTS.
|
|
16
|
+
#
|
|
17
|
+
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
|
|
18
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
|
20
|
+
# License for more details.
|
|
21
|
+
#
|
|
22
|
+
# You should have received a copy of the GNU Affero General Public License
|
|
23
|
+
# along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
|
|
24
|
+
#
|
|
25
|
+
# The interactive user interfaces in modified source and object code
|
|
26
|
+
# versions of HexaPDF must display Appropriate Legal Notices, as required
|
|
27
|
+
# under Section 5 of the GNU Affero General Public License version 3.
|
|
28
|
+
#
|
|
29
|
+
# In accordance with Section 7(b) of the GNU Affero General Public
|
|
30
|
+
# License, a covered work must retain the producer line in every PDF that
|
|
31
|
+
# is created or manipulated using HexaPDF.
|
|
32
|
+
#
|
|
33
|
+
# If the GNU Affero General Public License doesn't fit your need,
|
|
34
|
+
# commercial licenses are available at <https://gettalong.at/hexapdf/>.
|
|
35
|
+
#++
|
|
36
|
+
|
|
37
|
+
require 'hexapdf/type/action'
|
|
38
|
+
|
|
39
|
+
module HexaPDF
|
|
40
|
+
module Type
|
|
41
|
+
module Actions
|
|
42
|
+
|
|
43
|
+
# A Set-OCG-state action changes the state of one or more optional content groups.
|
|
44
|
+
#
|
|
45
|
+
# See: PDF2.0 s12.6.4.13, HexaPDF::Type::OptionalContentGroup
|
|
46
|
+
class SetOCGState < Action
|
|
47
|
+
|
|
48
|
+
define_field :S, type: Symbol, required: true, default: :SetOCGState
|
|
49
|
+
define_field :State, type: PDFArray, required: true, default: []
|
|
50
|
+
define_field :PreserveRB, type: Boolean, default: true
|
|
51
|
+
|
|
52
|
+
STATE_TYPE_MAPPING = {on: :ON, ON: :ON, off: :OFF, OFF: :OFF, # :nodoc:
|
|
53
|
+
toggle: :Toggle, Toggle: :Toggle}
|
|
54
|
+
|
|
55
|
+
# Adds a state changing sequence to the /State array.
|
|
56
|
+
#
|
|
57
|
+
# The +type+ argument specifies how the state of the given optional content groups should be
|
|
58
|
+
# changed.
|
|
59
|
+
#
|
|
60
|
+
# +type+:: The type of sequence to add, either :on/:ON (for turning the OCGs on) , :off/:OFF
|
|
61
|
+
# (for turning the OCGs off), or :toggle/:Toggle (for toggling the state of the
|
|
62
|
+
# OCGs).
|
|
63
|
+
#
|
|
64
|
+
# +ocgs+:: A single optional content group or an array of optional content groups to which
|
|
65
|
+
# the state change defined with +type+ should be applied. The OCGs can be specified
|
|
66
|
+
# via their dictionary or by name which uses the first found OCG with that name.
|
|
67
|
+
def add_state_change(type, ocgs)
|
|
68
|
+
type = STATE_TYPE_MAPPING.fetch(type) do
|
|
69
|
+
raise ArgumentError, "Invalid type #{type} specified, should be one of :on, :off or :toggle"
|
|
70
|
+
end
|
|
71
|
+
state = self[:State]
|
|
72
|
+
state << type
|
|
73
|
+
Array(ocgs).each do |ocg|
|
|
74
|
+
if (ocg_name = ocg).kind_of?(String)
|
|
75
|
+
ocg = document.optional_content.ocg(ocg_name, create: false)
|
|
76
|
+
raise HexaPDF::Error, "Invalid OCG named '#{ocg_name}' specified" unless ocg
|
|
77
|
+
end
|
|
78
|
+
state << ocg
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
data/lib/hexapdf/type/actions.rb
CHANGED
|
@@ -41,13 +41,14 @@ module HexaPDF
|
|
|
41
41
|
|
|
42
42
|
# Namespace module for all PDF action dictionary types.
|
|
43
43
|
#
|
|
44
|
-
# See:
|
|
44
|
+
# See: PDF2.0 s12.6.4, Action
|
|
45
45
|
module Actions
|
|
46
46
|
|
|
47
47
|
autoload(:GoTo, 'hexapdf/type/actions/go_to')
|
|
48
48
|
autoload(:GoToR, 'hexapdf/type/actions/go_to_r')
|
|
49
49
|
autoload(:Launch, 'hexapdf/type/actions/launch')
|
|
50
50
|
autoload(:URI, 'hexapdf/type/actions/uri')
|
|
51
|
+
autoload(:SetOCGState, 'hexapdf/type/actions/set_ocg_state')
|
|
51
52
|
|
|
52
53
|
end
|
|
53
54
|
|
|
@@ -43,7 +43,7 @@ module HexaPDF
|
|
|
43
43
|
# Annotations are used to associate objects like notes, sounds or movies with a location on a
|
|
44
44
|
# PDF page or allow the user to interact with a PDF document using a keyboard or mouse.
|
|
45
45
|
#
|
|
46
|
-
# See:
|
|
46
|
+
# See: PDF2.0 s12.5
|
|
47
47
|
class Annotation < Dictionary
|
|
48
48
|
|
|
49
49
|
# The appearance dictionary references appearance streams for various use cases.
|
|
@@ -52,7 +52,7 @@ module HexaPDF
|
|
|
52
52
|
# latter is used when the appearance depends on the state of the annotation, e.g. a check box
|
|
53
53
|
# widget that can be checked or unchecked.
|
|
54
54
|
#
|
|
55
|
-
# See:
|
|
55
|
+
# See: PDF2.0 s12.5.5
|
|
56
56
|
class AppearanceDictionary < Dictionary
|
|
57
57
|
|
|
58
58
|
define_type :XXAppearanceDictionary
|
|
@@ -101,7 +101,7 @@ module HexaPDF
|
|
|
101
101
|
|
|
102
102
|
# Border style dictionary used by various annotation types.
|
|
103
103
|
#
|
|
104
|
-
# See:
|
|
104
|
+
# See: PDF2.0 s12.5.4
|
|
105
105
|
class Border < Dictionary
|
|
106
106
|
|
|
107
107
|
define_type :Border
|
|
@@ -43,7 +43,7 @@ module HexaPDF
|
|
|
43
43
|
# Link annotations represent a link to a destination elsewhere in the PDF document or an
|
|
44
44
|
# action to be performed.
|
|
45
45
|
#
|
|
46
|
-
# See:
|
|
46
|
+
# See: PDF2.0 s12.5.6.5, HexaPDF::Type::Annotation
|
|
47
47
|
class Link < Annotation
|
|
48
48
|
|
|
49
49
|
define_field :Subtype, type: Symbol, required: true, default: :Link
|
|
@@ -43,7 +43,7 @@ module HexaPDF
|
|
|
43
43
|
# Markup annotations are used to "mark up" a PDF document, most of the available PDF
|
|
44
44
|
# annotations are actually markup annotations.
|
|
45
45
|
#
|
|
46
|
-
# See:
|
|
46
|
+
# See: PDF2.0 s12.5.6.2, HexaPDF::Type::Annotation
|
|
47
47
|
class MarkupAnnotation < Annotation
|
|
48
48
|
|
|
49
49
|
define_field :T, type: String, version: '1.1'
|
|
@@ -43,7 +43,7 @@ module HexaPDF
|
|
|
43
43
|
# Text annotations are "sticky notes" attached to a point in a PDF document. They act as if
|
|
44
44
|
# the NoZoom and NoRotate flags were always set.
|
|
45
45
|
#
|
|
46
|
-
# See:
|
|
46
|
+
# See: PDF2.0 s12.5.6.4, HexaPDF::Type::MarkupAnnotation
|
|
47
47
|
class Text < MarkupAnnotation
|
|
48
48
|
|
|
49
49
|
define_field :Subtype, type: Symbol, required: true, default: :Text
|
|
@@ -55,8 +55,7 @@ module HexaPDF
|
|
|
55
55
|
|
|
56
56
|
private
|
|
57
57
|
|
|
58
|
-
# :nodoc:
|
|
59
|
-
STATE_TO_STATE_MODEL = {
|
|
58
|
+
STATE_TO_STATE_MODEL = { # :nodoc:
|
|
60
59
|
"Marked" => "Marked", "Unmarked" => "Marked",
|
|
61
60
|
"Accepted" => "Review", "Rejected" => "Review", "Cancelled" => "Review",
|
|
62
61
|
"Completed" => "Review", "None" => "Review"
|
|
@@ -45,7 +45,7 @@ module HexaPDF
|
|
|
45
45
|
# Widget annotations are used by interactive forms to represent the appearance of fields and
|
|
46
46
|
# to manage user interactions.
|
|
47
47
|
#
|
|
48
|
-
# See:
|
|
48
|
+
# See: PDF2.0 s12.5.6.19, HexaPDF::Type::Annotation
|
|
49
49
|
class Widget < Annotation
|
|
50
50
|
|
|
51
51
|
# The dictionary used by the /MK key of the widget annotation.
|
|
@@ -264,7 +264,7 @@ module HexaPDF
|
|
|
264
264
|
# the /DA key on the widget (although /DA is not defined for widget, this is how Acrobat
|
|
265
265
|
# does it).
|
|
266
266
|
#
|
|
267
|
-
# See:
|
|
267
|
+
# See: PDF2.0 s12.5.6.19 and s12.7.4.3
|
|
268
268
|
def marker_style(style: nil, size: nil, color: nil)
|
|
269
269
|
field = form_field
|
|
270
270
|
if style || size || color
|
|
@@ -41,7 +41,7 @@ module HexaPDF
|
|
|
41
41
|
|
|
42
42
|
# Namespace module for all PDF annotation dictionary types.
|
|
43
43
|
#
|
|
44
|
-
# See:
|
|
44
|
+
# See: PDF2.0 s12.5.6, Annotation
|
|
45
45
|
module Annotations
|
|
46
46
|
|
|
47
47
|
autoload(:MarkupAnnotation, 'hexapdf/type/annotations/markup_annotation')
|
data/lib/hexapdf/type/catalog.rb
CHANGED
|
@@ -46,7 +46,7 @@ module HexaPDF
|
|
|
46
46
|
#
|
|
47
47
|
# The catalog dictionary is linked via the /Root entry from the Trailer.
|
|
48
48
|
#
|
|
49
|
-
# See:
|
|
49
|
+
# See: PDF2.0 s7.7.2, Trailer
|
|
50
50
|
class Catalog < Dictionary
|
|
51
51
|
|
|
52
52
|
define_type :Catalog
|
|
@@ -78,7 +78,7 @@ module HexaPDF
|
|
|
78
78
|
define_field :SpiderInfo, type: Dictionary, version: '1.3'
|
|
79
79
|
define_field :OutputIntents, type: PDFArray, version: '1.4'
|
|
80
80
|
define_field :PieceInfo, type: Dictionary, version: '1.4'
|
|
81
|
-
define_field :OCProperties, type:
|
|
81
|
+
define_field :OCProperties, type: :XXOCProperties, version: '1.5'
|
|
82
82
|
define_field :Perms, type: Dictionary, version: '1.5'
|
|
83
83
|
define_field :Legal, type: Dictionary, version: '1.5'
|
|
84
84
|
define_field :Requirements, type: PDFArray, version: '1.7'
|
|
@@ -112,6 +112,15 @@ module HexaPDF
|
|
|
112
112
|
self[:Outlines] ||= document.add({}, type: :Outlines)
|
|
113
113
|
end
|
|
114
114
|
|
|
115
|
+
# Returns the optional content properties dictionary, creating it if needed.
|
|
116
|
+
#
|
|
117
|
+
# This is the main entry point for working with optional content, a.k.a. layers.
|
|
118
|
+
#
|
|
119
|
+
# See: OptionalContentProperties
|
|
120
|
+
def optional_content
|
|
121
|
+
self[:OCProperties] ||= document.add({OCGs: [], D: {Creator: 'HexaPDF'}}, type: :XXOCProperties)
|
|
122
|
+
end
|
|
123
|
+
|
|
115
124
|
# Returns the main AcroForm object.
|
|
116
125
|
#
|
|
117
126
|
# * If an AcroForm object exists, the +create+ argument is not used.
|
|
@@ -42,13 +42,27 @@ module HexaPDF
|
|
|
42
42
|
# Represents a generic CIDFont which can only be used as a descendant font of a composite PDF
|
|
43
43
|
# font.
|
|
44
44
|
#
|
|
45
|
-
# See:
|
|
45
|
+
# See: PDF2.0 s9.7.4
|
|
46
46
|
class CIDFont < Font
|
|
47
47
|
|
|
48
|
+
# Describes the CIDSystemInfo dictionary specifying the character collection assumed by the
|
|
49
|
+
# CIDFont.
|
|
50
|
+
#
|
|
51
|
+
# See: PDF2.0 s9.7.3
|
|
52
|
+
class CIDSystemInfo < Dictionary
|
|
53
|
+
|
|
54
|
+
define_type :XXCIDSystemInfo
|
|
55
|
+
|
|
56
|
+
define_field :Registry, type: String, required: true
|
|
57
|
+
define_field :Ordering, type: String, required: true
|
|
58
|
+
define_field :Supplement, type: Integer, required: true
|
|
59
|
+
|
|
60
|
+
end
|
|
61
|
+
|
|
48
62
|
DEFAULT_WIDTH = 1000 # :nodoc:
|
|
49
63
|
|
|
50
64
|
define_field :BaseFont, type: Symbol, required: true
|
|
51
|
-
define_field :CIDSystemInfo, type:
|
|
65
|
+
define_field :CIDSystemInfo, type: :XXCIDSystemInfo, required: true
|
|
52
66
|
define_field :FontDescriptor, type: :FontDescriptor, indirect: true, required: true
|
|
53
67
|
define_field :DW, type: Integer, default: DEFAULT_WIDTH
|
|
54
68
|
define_field :W, type: PDFArray
|
|
@@ -66,7 +80,7 @@ module HexaPDF
|
|
|
66
80
|
# Sets the /W and /DW keys using the given array of [CID, width] pairs and an optional default
|
|
67
81
|
# width.
|
|
68
82
|
#
|
|
69
|
-
# See:
|
|
83
|
+
# See: PDF2.0 s9.7.4.3
|
|
70
84
|
def set_widths(widths, default_width: DEFAULT_WIDTH)
|
|
71
85
|
if widths.empty?
|
|
72
86
|
(default_width == DEFAULT_WIDTH ? delete(:DW) : self[:DW] = default_width)
|
|
@@ -93,7 +107,7 @@ module HexaPDF
|
|
|
93
107
|
#
|
|
94
108
|
# Note that the hash is cached internally when accessed the first time.
|
|
95
109
|
#
|
|
96
|
-
# See:
|
|
110
|
+
# See: PDF2.0 s9.7.4.3
|
|
97
111
|
def widths
|
|
98
112
|
cache(:widths) do
|
|
99
113
|
result = {}
|
|
@@ -46,7 +46,7 @@ module HexaPDF
|
|
|
46
46
|
# Type::FileSpecification dictionary or with the document as a whole through the /EmbeddedFiles
|
|
47
47
|
# entry in the document catalog's /Names dictionary.
|
|
48
48
|
#
|
|
49
|
-
# See:
|
|
49
|
+
# See: PDF2.0 s7.11.4, FileSpecification
|
|
50
50
|
class EmbeddedFile < Stream
|
|
51
51
|
|
|
52
52
|
# The type used for the /Mac field of an EmbeddedFile::Parameters dictionary.
|