hexapdf 0.21.1 → 0.24.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 +137 -0
- data/LICENSE +1 -1
- data/Rakefile +1 -1
- data/examples/016-frame_automatic_box_placement.rb +7 -2
- data/examples/017-frame_text_flow.rb +10 -18
- data/examples/020-column_box.rb +20 -37
- data/examples/021-list_box.rb +26 -0
- data/lib/hexapdf/cli/batch.rb +1 -1
- data/lib/hexapdf/cli/command.rb +1 -1
- data/lib/hexapdf/cli/files.rb +1 -1
- data/lib/hexapdf/cli/fonts.rb +1 -1
- data/lib/hexapdf/cli/form.rb +31 -4
- data/lib/hexapdf/cli/image2pdf.rb +1 -1
- data/lib/hexapdf/cli/images.rb +1 -1
- data/lib/hexapdf/cli/info.rb +2 -2
- data/lib/hexapdf/cli/inspect.rb +19 -6
- data/lib/hexapdf/cli/merge.rb +1 -1
- data/lib/hexapdf/cli/modify.rb +24 -4
- data/lib/hexapdf/cli/optimize.rb +1 -1
- data/lib/hexapdf/cli/split.rb +1 -1
- data/lib/hexapdf/cli/watermark.rb +1 -1
- data/lib/hexapdf/cli.rb +1 -1
- data/lib/hexapdf/composer.rb +66 -125
- data/lib/hexapdf/configuration.rb +17 -1
- data/lib/hexapdf/content/canvas.rb +1 -1
- data/lib/hexapdf/content/color_space.rb +1 -1
- data/lib/hexapdf/content/graphic_object/arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object/geom2d.rb +2 -1
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +1 -1
- data/lib/hexapdf/content/graphic_object.rb +1 -1
- data/lib/hexapdf/content/graphics_state.rb +1 -1
- data/lib/hexapdf/content/operator.rb +1 -1
- data/lib/hexapdf/content/parser.rb +1 -1
- data/lib/hexapdf/content/processor.rb +1 -1
- data/lib/hexapdf/content/transformation_matrix.rb +1 -1
- data/lib/hexapdf/content.rb +1 -1
- data/lib/hexapdf/data_dir.rb +1 -1
- data/lib/hexapdf/dictionary.rb +1 -1
- data/lib/hexapdf/dictionary_fields.rb +2 -2
- data/lib/hexapdf/document/destinations.rb +396 -0
- data/lib/hexapdf/document/files.rb +1 -1
- data/lib/hexapdf/document/fonts.rb +1 -1
- data/lib/hexapdf/document/images.rb +1 -1
- data/lib/hexapdf/document/layout.rb +397 -0
- data/lib/hexapdf/document/pages.rb +17 -1
- data/lib/hexapdf/document/signatures.rb +5 -4
- data/lib/hexapdf/document.rb +46 -90
- data/lib/hexapdf/encryption/aes.rb +1 -1
- data/lib/hexapdf/encryption/arc4.rb +1 -1
- data/lib/hexapdf/encryption/fast_aes.rb +1 -1
- data/lib/hexapdf/encryption/fast_arc4.rb +30 -21
- 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 +1 -1
- data/lib/hexapdf/encryption/standard_security_handler.rb +1 -1
- data/lib/hexapdf/encryption.rb +1 -1
- data/lib/hexapdf/error.rb +1 -1
- data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
- data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
- data/lib/hexapdf/filter/crypt.rb +1 -1
- data/lib/hexapdf/filter/encryption.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 +1 -1
- data/lib/hexapdf/font/cmap/parser.rb +1 -1
- data/lib/hexapdf/font/cmap/writer.rb +1 -1
- data/lib/hexapdf/font/cmap.rb +1 -1
- data/lib/hexapdf/font/encoding/base.rb +1 -1
- data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/glyph_list.rb +2 -2
- data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +1 -1
- 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 +1 -1
- data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding.rb +1 -1
- data/lib/hexapdf/font/invalid_glyph.rb +1 -1
- data/lib/hexapdf/font/true_type/builder.rb +1 -1
- data/lib/hexapdf/font/true_type/font.rb +1 -1
- data/lib/hexapdf/font/true_type/optimizer.rb +1 -1
- data/lib/hexapdf/font/true_type/subsetter.rb +1 -1
- data/lib/hexapdf/font/true_type/table/cmap.rb +1 -1
- data/lib/hexapdf/font/true_type/table/cmap_subtable.rb +1 -1
- data/lib/hexapdf/font/true_type/table/directory.rb +1 -1
- data/lib/hexapdf/font/true_type/table/glyf.rb +1 -1
- data/lib/hexapdf/font/true_type/table/head.rb +1 -1
- data/lib/hexapdf/font/true_type/table/hhea.rb +1 -1
- data/lib/hexapdf/font/true_type/table/hmtx.rb +1 -1
- data/lib/hexapdf/font/true_type/table/kern.rb +1 -1
- data/lib/hexapdf/font/true_type/table/loca.rb +1 -1
- data/lib/hexapdf/font/true_type/table/maxp.rb +1 -1
- data/lib/hexapdf/font/true_type/table/name.rb +1 -1
- data/lib/hexapdf/font/true_type/table/os2.rb +1 -1
- data/lib/hexapdf/font/true_type/table/post.rb +1 -1
- data/lib/hexapdf/font/true_type/table.rb +1 -1
- data/lib/hexapdf/font/true_type.rb +1 -1
- data/lib/hexapdf/font/true_type_wrapper.rb +1 -1
- data/lib/hexapdf/font/type1/afm_parser.rb +1 -1
- data/lib/hexapdf/font/type1/character_metrics.rb +1 -1
- data/lib/hexapdf/font/type1/font.rb +1 -1
- data/lib/hexapdf/font/type1/font_metrics.rb +1 -1
- data/lib/hexapdf/font/type1/pfb_parser.rb +1 -1
- data/lib/hexapdf/font/type1.rb +1 -1
- data/lib/hexapdf/font/type1_wrapper.rb +1 -1
- data/lib/hexapdf/font_loader/from_configuration.rb +1 -1
- data/lib/hexapdf/font_loader/from_file.rb +1 -1
- data/lib/hexapdf/font_loader/standard14.rb +1 -1
- data/lib/hexapdf/font_loader.rb +1 -1
- data/lib/hexapdf/image_loader/jpeg.rb +1 -1
- data/lib/hexapdf/image_loader/pdf.rb +1 -1
- data/lib/hexapdf/image_loader/png.rb +1 -1
- data/lib/hexapdf/image_loader.rb +1 -1
- data/lib/hexapdf/importer.rb +1 -1
- data/lib/hexapdf/layout/box.rb +121 -22
- data/lib/hexapdf/layout/box_fitter.rb +136 -0
- data/lib/hexapdf/layout/column_box.rb +168 -89
- data/lib/hexapdf/layout/frame.rb +155 -140
- data/lib/hexapdf/layout/image_box.rb +19 -4
- data/lib/hexapdf/layout/inline_box.rb +1 -1
- data/lib/hexapdf/layout/line.rb +1 -1
- data/lib/hexapdf/layout/list_box.rb +355 -0
- data/lib/hexapdf/layout/numeric_refinements.rb +1 -1
- data/lib/hexapdf/layout/style.rb +285 -8
- data/lib/hexapdf/layout/text_box.rb +30 -11
- data/lib/hexapdf/layout/text_fragment.rb +3 -2
- data/lib/hexapdf/layout/text_layouter.rb +23 -3
- data/lib/hexapdf/layout/text_shaper.rb +1 -1
- data/lib/hexapdf/layout/width_from_polygon.rb +12 -7
- data/lib/hexapdf/layout.rb +4 -1
- data/lib/hexapdf/name_tree_node.rb +1 -1
- data/lib/hexapdf/number_tree_node.rb +1 -1
- data/lib/hexapdf/object.rb +1 -1
- data/lib/hexapdf/parser.rb +1 -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 +9 -2
- data/lib/hexapdf/revisions.rb +152 -51
- data/lib/hexapdf/serializer.rb +1 -1
- data/lib/hexapdf/stream.rb +1 -1
- data/lib/hexapdf/task/dereference.rb +1 -1
- data/lib/hexapdf/task/optimize.rb +22 -12
- data/lib/hexapdf/task.rb +1 -1
- data/lib/hexapdf/tokenizer.rb +1 -1
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +1 -1
- 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 +1 -1
- data/lib/hexapdf/type/acro_form/form.rb +12 -6
- data/lib/hexapdf/type/acro_form/signature_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/text_field.rb +9 -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 +1 -1
- 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 +1 -1
- data/lib/hexapdf/type/annotations.rb +1 -1
- data/lib/hexapdf/type/catalog.rb +10 -2
- data/lib/hexapdf/type/cid_font.rb +1 -1
- data/lib/hexapdf/type/embedded_file.rb +1 -1
- data/lib/hexapdf/type/file_specification.rb +1 -1
- data/lib/hexapdf/type/font.rb +1 -1
- data/lib/hexapdf/type/font_descriptor.rb +1 -1
- data/lib/hexapdf/type/font_simple.rb +1 -1
- data/lib/hexapdf/type/font_true_type.rb +1 -1
- data/lib/hexapdf/type/font_type0.rb +1 -1
- data/lib/hexapdf/type/font_type1.rb +1 -1
- 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 +48 -4
- data/lib/hexapdf/type/info.rb +1 -1
- data/lib/hexapdf/type/names.rb +14 -1
- data/lib/hexapdf/type/object_stream.rb +1 -1
- data/lib/hexapdf/type/page.rb +1 -1
- data/lib/hexapdf/type/page_tree_node.rb +19 -2
- data/lib/hexapdf/type/resources.rb +1 -1
- data/lib/hexapdf/type/signature/adbe_pkcs7_detached.rb +1 -1
- data/lib/hexapdf/type/signature/adbe_x509_rsa_sha1.rb +1 -1
- data/lib/hexapdf/type/signature/handler.rb +1 -1
- data/lib/hexapdf/type/signature/verification_result.rb +1 -1
- data/lib/hexapdf/type/signature.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 +3 -2
- data/lib/hexapdf/type.rb +1 -1
- data/lib/hexapdf/utils/bit_field.rb +1 -1
- data/lib/hexapdf/utils/bit_stream.rb +1 -1
- data/lib/hexapdf/utils/graphics_helpers.rb +1 -1
- data/lib/hexapdf/utils/lru_cache.rb +1 -1
- data/lib/hexapdf/utils/math_helpers.rb +1 -1
- data/lib/hexapdf/utils/object_hash.rb +1 -1
- data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
- data/lib/hexapdf/utils/sorted_tree_node.rb +4 -2
- data/lib/hexapdf/version.rb +2 -2
- data/lib/hexapdf/writer.rb +23 -8
- data/lib/hexapdf/xref_section.rb +1 -1
- data/lib/hexapdf.rb +1 -1
- data/test/hexapdf/content/graphic_object/test_geom2d.rb +1 -1
- data/test/hexapdf/document/test_destinations.rb +338 -0
- data/test/hexapdf/document/test_images.rb +1 -1
- data/test/hexapdf/document/test_layout.rb +264 -0
- data/test/hexapdf/document/test_pages.rb +9 -0
- data/test/hexapdf/document/test_signatures.rb +10 -3
- data/test/hexapdf/encryption/test_security_handler.rb +3 -3
- data/test/hexapdf/font/encoding/test_glyph_list.rb +4 -0
- data/test/hexapdf/layout/test_box.rb +53 -3
- data/test/hexapdf/layout/test_box_fitter.rb +62 -0
- data/test/hexapdf/layout/test_column_box.rb +159 -0
- data/test/hexapdf/layout/test_frame.rb +114 -39
- data/test/hexapdf/layout/test_image_box.rb +1 -1
- data/test/hexapdf/layout/test_list_box.rb +249 -0
- data/test/hexapdf/layout/test_text_box.rb +33 -2
- data/test/hexapdf/layout/test_text_fragment.rb +1 -1
- data/test/hexapdf/layout/test_text_layouter.rb +49 -17
- data/test/hexapdf/layout/test_width_from_polygon.rb +13 -0
- data/test/hexapdf/task/test_optimize.rb +17 -4
- data/test/hexapdf/test_composer.rb +35 -1
- data/test/hexapdf/test_dictionary_fields.rb +10 -10
- data/test/hexapdf/test_document.rb +33 -136
- data/test/hexapdf/test_filter.rb +1 -1
- data/test/hexapdf/test_parser.rb +1 -3
- data/test/hexapdf/test_revision.rb +14 -0
- data/test/hexapdf/test_revisions.rb +137 -29
- data/test/hexapdf/test_serializer.rb +1 -5
- data/test/hexapdf/test_writer.rb +99 -15
- data/test/hexapdf/type/acro_form/test_form.rb +2 -1
- data/test/hexapdf/type/acro_form/test_text_field.rb +17 -0
- data/test/hexapdf/type/test_catalog.rb +8 -0
- data/test/hexapdf/type/test_image.rb +45 -9
- data/test/hexapdf/type/test_names.rb +20 -0
- data/test/hexapdf/type/test_page_tree_node.rb +21 -1
- data/test/hexapdf/type/test_trailer.rb +3 -3
- data/test/hexapdf/type/test_xref_stream.rb +2 -1
- data/test/hexapdf/utils/test_sorted_tree_node.rb +11 -1
- data/test/test_helper.rb +5 -1
- metadata +29 -3
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2022 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2022 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
data/lib/hexapdf/font/type1.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2022 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2022 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2022 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2022 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2022 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
data/lib/hexapdf/font_loader.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2022 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2022 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2022 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2022 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
data/lib/hexapdf/image_loader.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2022 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
data/lib/hexapdf/importer.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2022 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
data/lib/hexapdf/layout/box.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# This file is part of HexaPDF.
|
5
5
|
#
|
6
6
|
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
-
# Copyright (C) 2014-
|
7
|
+
# Copyright (C) 2014-2022 Thomas Leitner
|
8
8
|
#
|
9
9
|
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
10
|
# under the terms of the GNU Affero General Public License version 3 as
|
@@ -40,6 +40,8 @@ module HexaPDF
|
|
40
40
|
|
41
41
|
# The base class for all layout boxes.
|
42
42
|
#
|
43
|
+
# == Box Model
|
44
|
+
#
|
43
45
|
# HexaPDF uses the following box model:
|
44
46
|
#
|
45
47
|
# * Each box can specify a width and height. Padding and border are inside, the margin outside
|
@@ -49,12 +51,35 @@ module HexaPDF
|
|
49
51
|
# the content box without padding and the border.
|
50
52
|
#
|
51
53
|
# * If width or height is set to zero, they are determined automatically during layouting.
|
54
|
+
#
|
55
|
+
#
|
56
|
+
# == Subclasses
|
57
|
+
#
|
58
|
+
# Each subclass should only take keyword arguments on initialization so that the boxes can be
|
59
|
+
# instantiated from the common convenience method HexaPDF::Document::Layout#box. To use this
|
60
|
+
# facility subclasses need to be registered with the configuration option 'layout.boxes.map'.
|
61
|
+
#
|
62
|
+
# The methods #fit, #split or #split_content, and #draw or #draw_content need to be customized
|
63
|
+
# according to the subclass's use case.
|
64
|
+
#
|
65
|
+
# #fit:: This method should return +true+ if fitting was successful. Additionally, the
|
66
|
+
# @fit_successful instance variable needs to be set to the fit result as it is used in
|
67
|
+
# #split.
|
68
|
+
#
|
69
|
+
# #split:: This method splits the content so that the available space is used as good as
|
70
|
+
# possible. The default implementation should be fine for most use-cases, so only
|
71
|
+
# #split_content needs to be implemented. The method #create_split_box should be used
|
72
|
+
# for getting a basic cloned box.
|
73
|
+
#
|
74
|
+
# #draw:: This method draws the content and the default implementation already handles things
|
75
|
+
# like drawing the border and background. Therefore it's best to implement #draw_content
|
76
|
+
# which should just draw the content.
|
52
77
|
class Box
|
53
78
|
|
54
79
|
# Creates a new Box object, using the provided block as drawing block (see ::new).
|
55
80
|
#
|
56
81
|
# If +content_box+ is +true+, the width and height are taken to mean the content width and
|
57
|
-
# height and the style's padding and border are
|
82
|
+
# height and the style's padding and border are added to them appropriately.
|
58
83
|
#
|
59
84
|
# The +style+ argument defines the Style object (see Style::create for details) for the box.
|
60
85
|
# Any additional keyword arguments have to be style properties and are applied to the style
|
@@ -102,6 +127,18 @@ module HexaPDF
|
|
102
127
|
@height = @initial_height = height
|
103
128
|
@style = Style.create(style)
|
104
129
|
@draw_block = block
|
130
|
+
@fit_successful = false
|
131
|
+
@split_box = false
|
132
|
+
end
|
133
|
+
|
134
|
+
# Returns +true+ if this is a split box, i.e. the rest of another box after it was split.
|
135
|
+
def split_box?
|
136
|
+
@split_box
|
137
|
+
end
|
138
|
+
|
139
|
+
# Returns +false+ since a basic box doesn't support the 'position' style property value :flow.
|
140
|
+
def supports_position_flow?
|
141
|
+
false
|
105
142
|
end
|
106
143
|
|
107
144
|
# The width of the content box, i.e. without padding and/or borders.
|
@@ -123,16 +160,16 @@ module HexaPDF
|
|
123
160
|
def fit(available_width, available_height, _frame)
|
124
161
|
@width = (@initial_width > 0 ? @initial_width : available_width)
|
125
162
|
@height = (@initial_height > 0 ? @initial_height : available_height)
|
126
|
-
@width <= available_width && @height <= available_height
|
163
|
+
@fit_successful = (@width <= available_width && @height <= available_height)
|
127
164
|
end
|
128
165
|
|
129
166
|
# Tries to split the box into two, the first of which needs to fit into the available space,
|
130
167
|
# and returns the parts as array.
|
131
168
|
#
|
132
|
-
#
|
133
|
-
# a part of the box may still fit. Note that #fit
|
134
|
-
#
|
135
|
-
# the available space, +nil+ should be returned as the first array element.
|
169
|
+
# If the first item in the result array is not +nil+, it needs to be this box and it means
|
170
|
+
# that even when #fit fails, a part of the box may still fit. Note that #fit should not be
|
171
|
+
# called before #draw on the first box since it is already fitted. If not even a part of this
|
172
|
+
# box fits into the available space, +nil+ should be returned as the first array element.
|
136
173
|
#
|
137
174
|
# Possible return values:
|
138
175
|
#
|
@@ -140,15 +177,24 @@ module HexaPDF
|
|
140
177
|
# [nil, self]:: The box can't be split or no part of the box fits into the available space.
|
141
178
|
# [self, new_box]:: A part of the box fits and a new box is returned for the rest.
|
142
179
|
#
|
143
|
-
# This default implementation provides
|
144
|
-
|
145
|
-
|
180
|
+
# This default implementation provides the basic functionality based on the #fit result that
|
181
|
+
# should be sufficient for most subclasses; only #split_content needs to be implemented if
|
182
|
+
# necessary.
|
183
|
+
def split(available_width, available_height, frame)
|
184
|
+
if @fit_successful
|
185
|
+
[self, nil]
|
186
|
+
elsif (style.position != :flow && (@width > available_width || @height > available_height)) ||
|
187
|
+
content_height == 0 || content_width == 0
|
188
|
+
[nil, self]
|
189
|
+
else
|
190
|
+
split_content(available_width, available_height, frame)
|
191
|
+
end
|
146
192
|
end
|
147
193
|
|
148
194
|
# Draws the content of the box onto the canvas at the position (x, y).
|
149
195
|
#
|
150
196
|
# The coordinate system is translated so that the origin is at the bottom left corner of the
|
151
|
-
# **content box** during the drawing operations.
|
197
|
+
# **content box** during the drawing operations when +@draw_block+ is used.
|
152
198
|
#
|
153
199
|
# The block specified when creating the box is invoked with the canvas and the box as
|
154
200
|
# arguments. Subclasses can specify an on-demand drawing method by setting the +@draw_block+
|
@@ -165,11 +211,7 @@ module HexaPDF
|
|
165
211
|
style.underlays.draw(canvas, x, y, self) if style.underlays?
|
166
212
|
style.border.draw(canvas, x, y, width, height) if style.border?
|
167
213
|
|
168
|
-
|
169
|
-
cy = y
|
170
|
-
(cx += style.padding.left; cy += style.padding.bottom) if style.padding?
|
171
|
-
(cx += style.border.width.left; cy += style.border.width.bottom) if style.border?
|
172
|
-
draw_content(canvas, cx, cy)
|
214
|
+
draw_content(canvas, x + reserved_width_left, y + reserved_height_bottom)
|
173
215
|
|
174
216
|
style.overlays.draw(canvas, x, y, self) if style.overlays?
|
175
217
|
end
|
@@ -187,17 +229,47 @@ module HexaPDF
|
|
187
229
|
|
188
230
|
# Returns the width that is reserved by the padding and border style properties.
|
189
231
|
def reserved_width
|
190
|
-
|
191
|
-
result += style.padding.left + style.padding.right if style.padding?
|
192
|
-
result += style.border.width.left + style.border.width.right if style.border?
|
193
|
-
result
|
232
|
+
reserved_width_left + reserved_width_right
|
194
233
|
end
|
195
234
|
|
196
235
|
# Returns the height that is reserved by the padding and border style properties.
|
197
236
|
def reserved_height
|
237
|
+
reserved_height_top + reserved_height_bottom
|
238
|
+
end
|
239
|
+
|
240
|
+
# Returns the width that is reserved by the padding and the border style properties on the
|
241
|
+
# left side of the box.
|
242
|
+
def reserved_width_left
|
198
243
|
result = 0
|
199
|
-
result += style.padding.
|
200
|
-
result += style.border.width.
|
244
|
+
result += style.padding.left if style.padding?
|
245
|
+
result += style.border.width.left if style.border?
|
246
|
+
result
|
247
|
+
end
|
248
|
+
|
249
|
+
# Returns the width that is reserved by the padding and the border style properties on the
|
250
|
+
# right side of the box.
|
251
|
+
def reserved_width_right
|
252
|
+
result = 0
|
253
|
+
result += style.padding.right if style.padding?
|
254
|
+
result += style.border.width.right if style.border?
|
255
|
+
result
|
256
|
+
end
|
257
|
+
|
258
|
+
# Returns the height that is reserved by the padding and the border style properties on the
|
259
|
+
# top side of the box.
|
260
|
+
def reserved_height_top
|
261
|
+
result = 0
|
262
|
+
result += style.padding.top if style.padding?
|
263
|
+
result += style.border.width.top if style.border?
|
264
|
+
result
|
265
|
+
end
|
266
|
+
|
267
|
+
# Returns the height that is reserved by the padding and the border style properties on the
|
268
|
+
# bottom side of the box.
|
269
|
+
def reserved_height_bottom
|
270
|
+
result = 0
|
271
|
+
result += style.padding.bottom if style.padding?
|
272
|
+
result += style.border.width.bottom if style.border?
|
201
273
|
result
|
202
274
|
end
|
203
275
|
|
@@ -209,6 +281,33 @@ module HexaPDF
|
|
209
281
|
end
|
210
282
|
end
|
211
283
|
|
284
|
+
# Splits the content of the box.
|
285
|
+
#
|
286
|
+
# This is just a stub implementation, returning [nil, self] since we can't know how to split
|
287
|
+
# the content when it didn't fit.
|
288
|
+
#
|
289
|
+
# Subclasses that support splitting content need to provide an appropriate implementation and
|
290
|
+
# use #create_split_box to create a cloned box to supply as the second argument.
|
291
|
+
def split_content(_available_width, _available_height, _frame)
|
292
|
+
[nil, self]
|
293
|
+
end
|
294
|
+
|
295
|
+
# Creates a new box based on this one and resets the data back to their original values.
|
296
|
+
#
|
297
|
+
# The variable +@split_box+ is set to +split_box_value+ (defaults to +true+) to make the new
|
298
|
+
# box aware that it is a split box. If needed, subclasses can set the variable to other truthy
|
299
|
+
# values to convey more meaning.
|
300
|
+
#
|
301
|
+
# This method should be used by subclasses to create their split box.
|
302
|
+
def create_split_box(split_box_value: true)
|
303
|
+
box = clone
|
304
|
+
box.instance_variable_set(:@width, @initial_width)
|
305
|
+
box.instance_variable_set(:@height, @initial_height)
|
306
|
+
box.instance_variable_set(:@fit_successful, nil)
|
307
|
+
box.instance_variable_set(:@split_box, split_box_value)
|
308
|
+
box
|
309
|
+
end
|
310
|
+
|
212
311
|
end
|
213
312
|
|
214
313
|
end
|
@@ -0,0 +1,136 @@
|
|
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-2022 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
|
+
module HexaPDF
|
38
|
+
module Layout
|
39
|
+
|
40
|
+
# A BoxFitter instance contains an array of Frame objects and allows placing boxes one after the
|
41
|
+
# other in them. Such functionality is useful, for example, for boxes that provide multiple
|
42
|
+
# frames for content.
|
43
|
+
#
|
44
|
+
# == Usage
|
45
|
+
#
|
46
|
+
# * First one needs to add the frame objects via #<< or provide them on initialization.
|
47
|
+
#
|
48
|
+
# * Then use the #fit method to fit boxes one after the other. No drawing is done.
|
49
|
+
#
|
50
|
+
# * Once all boxes have been fitted, the #fit_results, #remaining_boxes and #fit_successful?
|
51
|
+
# methods can be used to get the result:
|
52
|
+
#
|
53
|
+
# - If there are no remaining boxes, all boxes were successfully fitted into the frames.
|
54
|
+
# - If there are remaining boxes but no fit results, the first box could not be fitted.
|
55
|
+
# - If there are remaining boxes and fit results, some boxes were able to fit.
|
56
|
+
class BoxFitter
|
57
|
+
|
58
|
+
# The array of frames inside of which the boxes should be laid out.
|
59
|
+
#
|
60
|
+
# Use #<< to add additional frames.
|
61
|
+
attr_reader :frames
|
62
|
+
|
63
|
+
# The Frame::FitResult objects for the successfully fitted objects in the order the boxes were
|
64
|
+
# fitted.
|
65
|
+
attr_reader :fit_results
|
66
|
+
|
67
|
+
# The boxes that could not be fitted into the frames.
|
68
|
+
attr_reader :remaining_boxes
|
69
|
+
|
70
|
+
# Creates a new BoxFitter object for the given +frames+.
|
71
|
+
def initialize(frames = [])
|
72
|
+
@frames = []
|
73
|
+
@content_heights = []
|
74
|
+
@initial_frame_y = []
|
75
|
+
@frame_index = 0
|
76
|
+
@fit_results = []
|
77
|
+
@remaining_boxes = []
|
78
|
+
|
79
|
+
frames.each {|frame| self << frame }
|
80
|
+
end
|
81
|
+
|
82
|
+
# Add the given frame to the list of frames.
|
83
|
+
def <<(frame)
|
84
|
+
@frames << frame
|
85
|
+
@initial_frame_y << frame.y
|
86
|
+
@content_heights << 0
|
87
|
+
end
|
88
|
+
|
89
|
+
# Fits the given box at the current location.
|
90
|
+
def fit(box)
|
91
|
+
unless @remaining_boxes.empty?
|
92
|
+
@remaining_boxes << box
|
93
|
+
return
|
94
|
+
end
|
95
|
+
|
96
|
+
while (current_frame = @frames[@frame_index])
|
97
|
+
result = current_frame.fit(box)
|
98
|
+
if result.success?
|
99
|
+
current_frame.remove_area(result.mask)
|
100
|
+
@content_heights[@frame_index] = [@content_heights[@frame_index],
|
101
|
+
@initial_frame_y[@frame_index] - result.mask[0].y].max
|
102
|
+
@fit_results << result
|
103
|
+
box = nil
|
104
|
+
break
|
105
|
+
elsif current_frame.full?
|
106
|
+
@frame_index += 1
|
107
|
+
else
|
108
|
+
draw_box, box = current_frame.split(result)
|
109
|
+
if draw_box
|
110
|
+
current_frame.remove_area(result.mask)
|
111
|
+
@content_heights[@frame_index] = [@content_heights[@frame_index],
|
112
|
+
@initial_frame_y[@frame_index] - result.mask[0].y].max
|
113
|
+
@fit_results << result
|
114
|
+
elsif !current_frame.find_next_region
|
115
|
+
@frame_index += 1
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
@remaining_boxes << box if box
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns an array with the heights of the content of each frame.
|
124
|
+
def content_heights
|
125
|
+
@content_heights
|
126
|
+
end
|
127
|
+
|
128
|
+
# Returns +true+ if all boxes were successfully fitted.
|
129
|
+
def fit_successful?
|
130
|
+
@remaining_boxes.empty?
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|