hexapdf 0.32.1 → 0.33.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +76 -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/cli.rb +4 -0
- 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 +8 -8
- 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 +7 -3
- 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_parser.rb +1 -1
- 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_object_stream.rb +9 -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
|