hexapdf 0.32.2 → 0.33.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 +63 -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/lib/hexapdf/cli/command.rb +5 -2
- data/lib/hexapdf/cli/form.rb +5 -5
- data/lib/hexapdf/cli/inspect.rb +3 -3
- data/lib/hexapdf/composer.rb +104 -52
- data/lib/hexapdf/configuration.rb +44 -39
- data/lib/hexapdf/content/canvas.rb +393 -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 +52 -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 +6 -5
- data/lib/hexapdf/dictionary_fields.rb +42 -14
- 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 +2 -2
- 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 +167 -39
- data/lib/hexapdf/document/pages.rb +3 -2
- data/lib/hexapdf/document.rb +89 -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 +1 -1
- 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 +9 -2
- data/lib/hexapdf/layout/box_fitter.rb +2 -2
- data/lib/hexapdf/layout/column_box.rb +18 -4
- data/lib/hexapdf/layout/frame.rb +30 -12
- data/lib/hexapdf/layout/image_box.rb +5 -0
- data/lib/hexapdf/layout/inline_box.rb +1 -0
- data/lib/hexapdf/layout/list_box.rb +17 -1
- data/lib/hexapdf/layout/page_style.rb +4 -4
- data/lib/hexapdf/layout/style.rb +18 -3
- data/lib/hexapdf/layout/table_box.rb +682 -0
- data/lib/hexapdf/layout/text_box.rb +5 -3
- data/lib/hexapdf/layout/text_fragment.rb +1 -1
- data/lib/hexapdf/layout/text_layouter.rb +12 -4
- 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 +4 -2
- 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/uri.rb +1 -1
- data/lib/hexapdf/type/actions.rb +1 -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 +1 -1
- data/lib/hexapdf/type/annotations/widget.rb +2 -2
- data/lib/hexapdf/type/annotations.rb +1 -1
- data/lib/hexapdf/type/catalog.rb +1 -1
- data/lib/hexapdf/type/cid_font.rb +3 -3
- 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 +1 -1
- 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/outline.rb +1 -1
- data/lib/hexapdf/type/outline_item.rb +1 -1
- data/lib/hexapdf/type/page.rb +19 -10
- data/lib/hexapdf/type/page_label.rb +1 -1
- 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/utils/pdf_doc_encoding.rb +1 -1
- 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 +0 -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 +98 -0
- 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 +1 -1
- data/test/hexapdf/layout/test_column_box.rb +65 -21
- data/test/hexapdf/layout/test_frame.rb +14 -14
- data/test/hexapdf/layout/test_image_box.rb +4 -0
- data/test/hexapdf/layout/test_inline_box.rb +5 -0
- data/test/hexapdf/layout/test_list_box.rb +40 -6
- data/test/hexapdf/layout/test_page_style.rb +3 -2
- data/test/hexapdf/layout/test_style.rb +50 -0
- data/test/hexapdf/layout/test_table_box.rb +722 -0
- data/test/hexapdf/layout/test_text_box.rb +18 -0
- data/test/hexapdf/layout/test_text_layouter.rb +4 -0
- data/test/hexapdf/test_dictionary_fields.rb +4 -1
- data/test/hexapdf/test_document.rb +1 -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/test_page.rb +18 -4
- metadata +17 -8
|
@@ -71,21 +71,20 @@ module HexaPDF
|
|
|
71
71
|
#
|
|
72
72
|
# == Box Styles
|
|
73
73
|
#
|
|
74
|
-
# All box creation methods accept
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
# creation process.
|
|
74
|
+
# All box creation methods accept Layout::Style objects or names for style objects (defined via
|
|
75
|
+
# #style). This allows one to predefine certain styles (like first level heading, second level
|
|
76
|
+
# heading, paragraph, ...) and consistently use them throughout the document creation process.
|
|
78
77
|
#
|
|
79
|
-
# One style property,
|
|
78
|
+
# One style property, Layout::Style#font, is handled specially:
|
|
80
79
|
#
|
|
81
80
|
# * If no font is set on a style, the font "Times" is automatically set because otherwise there
|
|
82
81
|
# would be problems with text drawing operations (font is the only style property that has no
|
|
83
82
|
# valid default value).
|
|
84
83
|
#
|
|
85
|
-
# * Standard style objects only allow font wrapper objects to be set via the
|
|
86
|
-
#
|
|
87
|
-
#
|
|
88
|
-
#
|
|
84
|
+
# * Standard style objects only allow font wrapper objects to be set via the Layout::Style#font
|
|
85
|
+
# method. This class makes usage easier by allowing strings or an array [name, options_hash]
|
|
86
|
+
# to be used, like with e.g Content::Canvas#font. So to use Helvetica as font, one could just
|
|
87
|
+
# do:
|
|
89
88
|
#
|
|
90
89
|
# style.font = 'Helvetica'
|
|
91
90
|
#
|
|
@@ -108,11 +107,14 @@ module HexaPDF
|
|
|
108
107
|
# text, formatted_text, image, ...:: Any method accepted by the Layout class without the _box
|
|
109
108
|
# suffix.
|
|
110
109
|
#
|
|
111
|
-
# list, column, ...:: Any name registered
|
|
110
|
+
# list, column, ...:: Any name registered with the configuration option +layout.boxes.map+.
|
|
111
|
+
#
|
|
112
|
+
# The special method #multiple allows adding multiple boxes as a single array to the collected
|
|
113
|
+
# children.
|
|
112
114
|
#
|
|
113
115
|
# Example:
|
|
114
116
|
#
|
|
115
|
-
# document.layout.box(:list) do |list|
|
|
117
|
+
# document.layout.box(:list) do |list| # list is a ChildrenCollector
|
|
116
118
|
# list.text_box("Some text here") # layout method
|
|
117
119
|
# list.image(image_path) # layout method without _box suffix
|
|
118
120
|
# list.column(columns: 3) do |column| # registered box name
|
|
@@ -166,7 +168,7 @@ module HexaPDF
|
|
|
166
168
|
|
|
167
169
|
end
|
|
168
170
|
|
|
169
|
-
# The mapping of style name (a Symbol) to
|
|
171
|
+
# The mapping of style name (a Symbol) to Layout::Style instance.
|
|
170
172
|
attr_reader :styles
|
|
171
173
|
|
|
172
174
|
# Creates a new Layout object for the given PDF document.
|
|
@@ -179,20 +181,20 @@ module HexaPDF
|
|
|
179
181
|
# layout.style(name) -> style
|
|
180
182
|
# layout.style(name, base: :base, **properties) -> style
|
|
181
183
|
#
|
|
182
|
-
# Creates or updates the
|
|
183
|
-
#
|
|
184
|
+
# Creates or updates the Layout::Style object called +name+ with the given property values and
|
|
185
|
+
# returns it.
|
|
186
|
+
#
|
|
187
|
+
# If neither +base+ nor any style properties are specified, the style +name+ is just returned.
|
|
184
188
|
#
|
|
185
189
|
# This method allows convenient access to the stored styles and to update them. Such styles
|
|
186
190
|
# can then be used by name in the various box creation methods, e.g. #text_box or #image_box.
|
|
187
191
|
#
|
|
188
|
-
# If neither +base+ nor any style properties are specified, the style +name+ is just returned.
|
|
189
|
-
#
|
|
190
192
|
# If the style +name+ does not exist yet and the argument +base+ specifies the name of another
|
|
191
193
|
# style, that style is duplicated and used as basis for the style. This also means that the
|
|
192
194
|
# referenced +base+ style needs be defined first!
|
|
193
195
|
#
|
|
194
|
-
# The special name :base should be used for setting the base style which is used
|
|
195
|
-
# specific style is
|
|
196
|
+
# The special name :base should be used for setting the base style which is used for the
|
|
197
|
+
# +base+ argument when no specific style is specified.
|
|
196
198
|
#
|
|
197
199
|
# Note that the style property 'font' is handled specially, see the class documentation for
|
|
198
200
|
# details.
|
|
@@ -269,26 +271,26 @@ module HexaPDF
|
|
|
269
271
|
#
|
|
270
272
|
# +style+, +style_properties+::
|
|
271
273
|
# The box and the text are styled using the given +style+. This can either be a style name
|
|
272
|
-
# set via #style or anything
|
|
274
|
+
# set via #style or anything Layout::Style::create accepts. If any additional
|
|
273
275
|
# +style_properties+ are specified, the style is duplicated and the additional styles are
|
|
274
276
|
# applied.
|
|
275
277
|
#
|
|
276
278
|
# +properties+::
|
|
277
|
-
# This can be used to set custom properties on the created text box. See
|
|
278
|
-
# for details and usage.
|
|
279
|
+
# This can be used to set custom properties on the created text box. See
|
|
280
|
+
# Layout::Box#properties for details and usage.
|
|
279
281
|
#
|
|
280
282
|
# +box_style+::
|
|
281
283
|
# Sometimes it is necessary for the box to have a different style than the text, e.g. when
|
|
282
284
|
# using overlays. In such a case use +box_style+ for specifiying the style of the box (a
|
|
283
|
-
# style name set via #style or anything
|
|
285
|
+
# style name set via #style or anything Layout::Style::create accepts).
|
|
284
286
|
#
|
|
285
287
|
# The +style+ together with the +style_properties+ will be used for the text style.
|
|
286
288
|
#
|
|
287
289
|
# Examples:
|
|
288
290
|
#
|
|
289
|
-
# layout.text_box("Test " * 15)
|
|
291
|
+
# layout.text_box("Test is on " * 15)
|
|
290
292
|
# layout.text_box("Now " * 7, width: 100)
|
|
291
|
-
# layout.text_box("Another test", font_size: 15, fill_color: "
|
|
293
|
+
# layout.text_box("Another test", font_size: 15, fill_color: "hp-blue")
|
|
292
294
|
# layout.text_box("Different box style", fill_color: 'white', box_style: {
|
|
293
295
|
# underlays: [->(c, b) { c.rectangle(0, 0, b.content_width, b.content_height).fill }]
|
|
294
296
|
# })
|
|
@@ -307,7 +309,8 @@ module HexaPDF
|
|
|
307
309
|
# formatted differently.
|
|
308
310
|
#
|
|
309
311
|
# The argument +data+ needs to be an array of String, HexaPDF::Layout::InlineBox and/or Hash
|
|
310
|
-
# objects and is transformed so that it is suitable as argument for the text box
|
|
312
|
+
# objects and is transformed so that it is suitable as argument for the text box
|
|
313
|
+
# initialization method.
|
|
311
314
|
#
|
|
312
315
|
# * A String object is treated like {text: data}.
|
|
313
316
|
#
|
|
@@ -322,9 +325,9 @@ module HexaPDF
|
|
|
322
325
|
# for the text. If this is set and :box is not, the hash will be transformed into a
|
|
323
326
|
# text fragment with an appropriate link overlay.
|
|
324
327
|
#
|
|
325
|
-
# style:: The style to
|
|
326
|
-
#
|
|
327
|
-
#
|
|
328
|
+
# style:: The style to use as base style instead of the style created from the +style+ and
|
|
329
|
+
# +style_properties+ arguments. This can either be a style name set via #style or
|
|
330
|
+
# anything HexaPDF::Layout::Style::create allows.
|
|
328
331
|
#
|
|
329
332
|
# If any style properties are set, the used style is duplicated and the additional
|
|
330
333
|
# properties applied.
|
|
@@ -336,23 +339,42 @@ module HexaPDF
|
|
|
336
339
|
#
|
|
337
340
|
# The value must be one or more (as an array) positional arguments to be used with the
|
|
338
341
|
# #inline_box method. The rest of the hash keys are passed as keyword arguments to
|
|
339
|
-
# #inline_box except for :block
|
|
342
|
+
# #inline_box except for :block which would be passed as the block.
|
|
340
343
|
#
|
|
341
344
|
# See #text_box for details on +width+, +height+, +style+, +style_properties+, +properties+
|
|
342
345
|
# and +box_style+.
|
|
343
346
|
#
|
|
344
347
|
# Examples:
|
|
345
348
|
#
|
|
349
|
+
# # Text without special styling
|
|
346
350
|
# layout.formatted_text_box(["Some string"])
|
|
347
|
-
#
|
|
348
|
-
#
|
|
349
|
-
#
|
|
350
|
-
# layout.formatted_text_box([
|
|
351
|
-
#
|
|
351
|
+
#
|
|
352
|
+
# # A predefined inline box
|
|
353
|
+
# ibox = layout.inline_box(:text, 'Hello')
|
|
354
|
+
# layout.formatted_text_box([ibox])
|
|
355
|
+
#
|
|
356
|
+
# # Text with styling properties
|
|
357
|
+
# layout.formatted_text_box([{text: "string", fill_color: 128}])
|
|
358
|
+
#
|
|
359
|
+
# # Text referencing a base style
|
|
360
|
+
# layout.formatted_text_box([{text: "string", style: :bold}])
|
|
361
|
+
#
|
|
362
|
+
# # Text with a link
|
|
363
|
+
# layout.formatted_text_box([{link: "https://example.com",
|
|
364
|
+
# fill_color: 'blue', text: "Example"}])
|
|
365
|
+
#
|
|
366
|
+
# # Inline boxes created from the given data
|
|
367
|
+
# layout.formatted_text_box([{box: [:text, "string"], valign: :top}])
|
|
352
368
|
# block = lambda {|list| list.text("First item"); list.text("Second item") }
|
|
353
369
|
# layout.formatted_text_box(["Some ", {box: :list, item_spacing: 10, block: block}])
|
|
354
370
|
#
|
|
355
|
-
#
|
|
371
|
+
# # Combining the above variants
|
|
372
|
+
# layout.formatted_text_box(["Hello", {box: [:text, 'World!']}, "Here comes a ",
|
|
373
|
+
# {link: 'https://example.com', text: 'link'}, '!',
|
|
374
|
+
# {text: 'And more!', style: :bold, font_size: 20}])
|
|
375
|
+
#
|
|
376
|
+
# See: #text_box, #inline_box, HexaPDF::Layout::TextBox, HexaPDF::Layout::TextFragment,
|
|
377
|
+
# HexaPDF::Layout::InlineBox
|
|
356
378
|
def formatted_text_box(data, width: 0, height: 0, style: nil, properties: nil, box_style: nil,
|
|
357
379
|
**style_properties)
|
|
358
380
|
style = retrieve_style(style, style_properties)
|
|
@@ -406,25 +428,131 @@ module HexaPDF
|
|
|
406
428
|
properties: properties, style: style)
|
|
407
429
|
end
|
|
408
430
|
|
|
431
|
+
# This helper class is used by Layout#table_box to allow specifying the keyword arguments used
|
|
432
|
+
# when converting cell data to box instances.
|
|
433
|
+
class CellArgumentCollector
|
|
434
|
+
|
|
435
|
+
# Stores a single keyword argument definition for a number of rows/columns.
|
|
436
|
+
ArgumentInfo = Struct.new(:rows, :cols, :args)
|
|
437
|
+
|
|
438
|
+
# Returns all stored ArgumentInfo instances.
|
|
439
|
+
attr_reader :argument_infos
|
|
440
|
+
|
|
441
|
+
# Creates a new instance, providing the number of rows and columns of the table.
|
|
442
|
+
def initialize(number_of_rows, number_of_columns)
|
|
443
|
+
@argument_infos = []
|
|
444
|
+
@number_of_rows = number_of_rows
|
|
445
|
+
@number_of_columns = number_of_columns
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
# Stores the keyword arguments in +args+ for the given 0-based rows and columns which can
|
|
449
|
+
# either be a single number or a range of numbers.
|
|
450
|
+
def []=(rows = 0..-1, cols = 0..-1, args)
|
|
451
|
+
rows = adjust_range(rows.kind_of?(Integer) ? rows..rows : rows, @number_of_rows)
|
|
452
|
+
cols = adjust_range(cols.kind_of?(Integer) ? cols..cols : cols, @number_of_columns)
|
|
453
|
+
@argument_infos << ArgumentInfo.new(rows, cols, args)
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
# Retrieves the merged keyword arguments for the cell in +row+ and +col+.
|
|
457
|
+
#
|
|
458
|
+
# Earlier defined arguments are overridden by later ones.
|
|
459
|
+
def retrieve_arguments_for(row, col)
|
|
460
|
+
@argument_infos.each_with_object({}) do |arg_info, result|
|
|
461
|
+
next unless arg_info.rows.cover?(row) && arg_info.cols.cover?(col)
|
|
462
|
+
result.update(arg_info.args)
|
|
463
|
+
end
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
private
|
|
467
|
+
|
|
468
|
+
# Adjusts the +range+ so that both the begin and the end of the range are zero or positive
|
|
469
|
+
# integers smaller than +max+.
|
|
470
|
+
def adjust_range(range, max)
|
|
471
|
+
(range.begin % max)..(range.end % max)
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
end
|
|
475
|
+
|
|
476
|
+
# Creates a HexaPDF::Layout::TableBox for the given table data.
|
|
477
|
+
#
|
|
478
|
+
# This method is a small wrapper around the actual class and mainly facilitates transforming
|
|
479
|
+
# the contents of the +data+ into the box instances needed by the table box implementation.
|
|
480
|
+
#
|
|
481
|
+
# In addition to everything the table box implementation allows for +data+, it is also
|
|
482
|
+
# possible to specify strings as cell contents. Those strings will be converted to text boxes
|
|
483
|
+
# by using the #text_box method. *Note* that this functionality is *not* available for the
|
|
484
|
+
# header and footer!
|
|
485
|
+
#
|
|
486
|
+
# Additional arguments for the #text_box invocations can be specified using the optional block
|
|
487
|
+
# that yields a CellArgumentCollector instance. This allows customization of the text boxes.
|
|
488
|
+
# By specifying the special key +:cell+ it is also possible to assign style properties to the
|
|
489
|
+
# cells themselves.
|
|
490
|
+
#
|
|
491
|
+
# See HexaPDF::Layout::TableBox::new for details on +column_widths+, +header+, +footer+, and
|
|
492
|
+
# +cell_style+.
|
|
493
|
+
#
|
|
494
|
+
# See #text_box for details on +width+, +height+, +style+, +style_properties+ and
|
|
495
|
+
# +properties+.
|
|
496
|
+
#
|
|
497
|
+
# Examples:
|
|
498
|
+
#
|
|
499
|
+
# layout.table_box([[layout.text('A'), layout.text('B')],
|
|
500
|
+
# [layout.image(image_path), layout.text('D')]]
|
|
501
|
+
# layout.table_box([['A', 'B'], [layout.image(image_path), 'D]]) # same as above
|
|
502
|
+
#
|
|
503
|
+
# layout.table_box([['A', 'B'], ['C', 'D]]) do |args|
|
|
504
|
+
# # assign the predefined style :cell_text to all texts
|
|
505
|
+
# args[] = {style: :cell_text}
|
|
506
|
+
# # row 0 has a grey background and bold text
|
|
507
|
+
# args[0] = {font: ['Helvetica', variant: :bold], cell: {background_color: 'eee'}}
|
|
508
|
+
# # text in last column is right aligned
|
|
509
|
+
# args[0..-1, -1] = {align: :right}
|
|
510
|
+
# end
|
|
511
|
+
#
|
|
512
|
+
# See: HexaPDF::Layout::TableBox
|
|
513
|
+
def table_box(data, column_widths: nil, header: nil, footer: nil, cell_style: nil,
|
|
514
|
+
width: 0, height: 0, style: nil, properties: nil, **style_properties)
|
|
515
|
+
style = retrieve_style(style, style_properties)
|
|
516
|
+
cells = HexaPDF::Layout::TableBox::Cells.new(data, cell_style: cell_style)
|
|
517
|
+
collector = CellArgumentCollector.new(cells.number_of_rows, cells.number_of_columns)
|
|
518
|
+
yield(collector) if block_given?
|
|
519
|
+
cells.style do |cell|
|
|
520
|
+
args = collector.retrieve_arguments_for(cell.row, cell.column)
|
|
521
|
+
cstyle = args.delete(:cell)
|
|
522
|
+
result = case cell.children
|
|
523
|
+
when Array, HexaPDF::Layout::Box
|
|
524
|
+
cell.children
|
|
525
|
+
else
|
|
526
|
+
text_box(cell.children.to_s, **args)
|
|
527
|
+
end
|
|
528
|
+
cell.children = result
|
|
529
|
+
cell.style.update(**cstyle) if cstyle
|
|
530
|
+
end
|
|
531
|
+
box_class_for_name(:table).new(cells: cells, column_widths: column_widths, header: header,
|
|
532
|
+
footer: footer, cell_style: cell_style, width: width,
|
|
533
|
+
height: height, properties: properties, style: style)
|
|
534
|
+
end
|
|
535
|
+
|
|
409
536
|
LOREM_IPSUM = [ # :nodoc:
|
|
410
537
|
"Lorem ipsum dolor sit amet, con\u{00AD}sectetur adipis\u{00AD}cing elit, sed " \
|
|
411
538
|
"do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
|
412
539
|
"Ut enim ad minim veniam, quis nostrud exer\u{00AD}citation ullamco laboris nisi ut " \
|
|
413
|
-
"aliquip ex ea commodo consequat.
|
|
540
|
+
"aliquip ex ea commodo consequat.",
|
|
414
541
|
"Duis aute irure dolor in reprehen\u{00AD}derit in voluptate velit esse cillum dolore " \
|
|
415
|
-
"eu fugiat nulla pariatur.
|
|
542
|
+
"eu fugiat nulla pariatur.",
|
|
416
543
|
"Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt " \
|
|
417
544
|
"mollit anim id est laborum.",
|
|
418
545
|
]
|
|
419
546
|
|
|
420
|
-
# Uses #text_box to create +count+ paragraphs of
|
|
547
|
+
# Uses #text_box to create +count+ paragraphs with +sentences+ number of sentences (1 to 4) of
|
|
548
|
+
# lorem ipsum text.
|
|
421
549
|
#
|
|
422
550
|
# The +text_box_properties+ arguments are passed as is to #text_box.
|
|
423
551
|
def lorem_ipsum_box(sentences: 4, count: 1, **text_box_properties)
|
|
424
552
|
text_box(([LOREM_IPSUM[0, sentences].join(" ")] * count).join("\n\n"), **text_box_properties)
|
|
425
553
|
end
|
|
426
554
|
|
|
427
|
-
BOX_METHOD_NAMES = [:text, :formatted_text, :image, :lorem_ipsum] #:nodoc:
|
|
555
|
+
BOX_METHOD_NAMES = [:text, :formatted_text, :image, :table, :lorem_ipsum] #:nodoc:
|
|
428
556
|
|
|
429
557
|
# Allows creating boxes using more convenient method names:
|
|
430
558
|
#
|
|
@@ -39,7 +39,7 @@ require 'hexapdf/error'
|
|
|
39
39
|
module HexaPDF
|
|
40
40
|
class Document
|
|
41
41
|
|
|
42
|
-
# This class provides methods for managing the pages of a PDF file.
|
|
42
|
+
# This class provides methods for managing the pages and page labels of a PDF file.
|
|
43
43
|
#
|
|
44
44
|
# For page manipulation it uses the methods of HexaPDF::Type::PageTreeNode underneath but
|
|
45
45
|
# provides a more convenient interface.
|
|
@@ -178,7 +178,8 @@ module HexaPDF
|
|
|
178
178
|
@document.catalog.pages.each_page(&block)
|
|
179
179
|
end
|
|
180
180
|
|
|
181
|
-
# Returns the number of pages in the PDF document. May be zero if the document has no pages
|
|
181
|
+
# Returns the number of pages in the PDF document. May be zero if the document has no pages
|
|
182
|
+
# yet.
|
|
182
183
|
def count
|
|
183
184
|
@document.catalog.pages.page_count
|
|
184
185
|
end
|