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
data/lib/hexapdf/composer.rb
CHANGED
|
@@ -51,17 +51,18 @@ module HexaPDF
|
|
|
51
51
|
# On creation a HexaPDF::Document object is created as well the first page and an accompanying
|
|
52
52
|
# HexaPDF::Layout::Frame object. The frame is used by the various methods for general document
|
|
53
53
|
# layout tasks, like positioning of text, images, and so on. By default, it covers the whole page
|
|
54
|
-
# except the margin area. How the frame gets created can be customized by
|
|
55
|
-
# #
|
|
54
|
+
# except the margin area. How the frame gets created can be customized by defining a custom page
|
|
55
|
+
# style, see #page_style. Use the +skip_page_creation+ argument to avoid the initial page
|
|
56
|
+
# creation when creating a Composer instance.
|
|
56
57
|
#
|
|
57
58
|
# Once the Composer object is created, its methods can be used to draw text, images, ... on the
|
|
58
|
-
# page. Behind the scenes HexaPDF::Layout::Box (and subclass) objects are created
|
|
59
|
-
# page via the frame.
|
|
59
|
+
# page. Behind the scenes HexaPDF::Layout::Box (and subclass) objects are created using the
|
|
60
|
+
# HexaPDF::Document::Layout methods and drawn on the page via the frame.
|
|
60
61
|
#
|
|
61
62
|
# If the frame of a page is full and a box doesn't fit anymore, a new page is automatically
|
|
62
63
|
# created. The box is either split into two boxes where one fits on the first page and the other
|
|
63
64
|
# on the new page, or it is drawn completely on the new page. A new page can also be created by
|
|
64
|
-
# calling the #new_page method.
|
|
65
|
+
# calling the #new_page method, optionally providing a page style.
|
|
65
66
|
#
|
|
66
67
|
# The #x and #y methods provide the point where the next box would be drawn if it fits the
|
|
67
68
|
# available space. This information can be used, for example, for custom drawing operations
|
|
@@ -75,30 +76,36 @@ module HexaPDF
|
|
|
75
76
|
#
|
|
76
77
|
# == Example
|
|
77
78
|
#
|
|
78
|
-
#
|
|
79
|
-
#
|
|
79
|
+
# #>pdf-full
|
|
80
|
+
# HexaPDF::Composer.create('out.pdf', page_size: :A6, margin: 36) do |pdf|
|
|
81
|
+
# pdf.style(:base, font_size: 20, align: :center)
|
|
80
82
|
# pdf.text("Hello World", valign: :center)
|
|
81
83
|
# end
|
|
84
|
+
#
|
|
85
|
+
# See: HexaPDF::Document::Layout, HexaPDF::Layout::Frame, HexaPDF::Layout::Box
|
|
82
86
|
class Composer
|
|
83
87
|
|
|
84
|
-
# Creates a new PDF document and writes it to +output+. The +options+
|
|
88
|
+
# Creates a new PDF document and writes it to +output+. The argument +options+ and +block+ are
|
|
89
|
+
# passed to ::new.
|
|
85
90
|
#
|
|
86
91
|
# Example:
|
|
87
92
|
#
|
|
88
|
-
# HexaPDF::Composer.create('
|
|
93
|
+
# HexaPDF::Composer.create('out.pdf', margin: 36) do |pdf|
|
|
89
94
|
# ...
|
|
90
95
|
# end
|
|
91
96
|
def self.create(output, **options, &block)
|
|
92
97
|
new(**options, &block).write(output)
|
|
93
98
|
end
|
|
94
99
|
|
|
95
|
-
# The PDF document that is created.
|
|
100
|
+
# The PDF document (HexaPDF::Document) that is created.
|
|
96
101
|
attr_reader :document
|
|
97
102
|
|
|
98
103
|
# The current page (a HexaPDF::Type::Page object).
|
|
99
104
|
attr_reader :page
|
|
100
105
|
|
|
101
|
-
# The Content::Canvas of the current page.
|
|
106
|
+
# The canvas instance (a Content::Canvas object) of the current page.
|
|
107
|
+
#
|
|
108
|
+
# Can be used to perform arbitrary drawing operations.
|
|
102
109
|
attr_reader :canvas
|
|
103
110
|
|
|
104
111
|
# The HexaPDF::Layout::Frame for automatic box placement.
|
|
@@ -107,43 +114,53 @@ module HexaPDF
|
|
|
107
114
|
# Creates a new Composer object and optionally yields it to the given block.
|
|
108
115
|
#
|
|
109
116
|
# skip_page_creation::
|
|
110
|
-
# If this argument is +
|
|
111
|
-
# and +margin+ are used to create a page style with the name :default
|
|
112
|
-
# created
|
|
117
|
+
# If this argument is +false+ (the default), the arguments +page_size+, +page_orientation+
|
|
118
|
+
# and +margin+ are used to create a page style with the name :default. Additionally, an
|
|
119
|
+
# initial page/frame is created using this page style.
|
|
113
120
|
#
|
|
114
|
-
# Otherwise, i.e. when this argument is +
|
|
115
|
-
# created. This
|
|
121
|
+
# Otherwise, i.e. when this argument is +true+, no initial page or default page style is
|
|
122
|
+
# created. This is useful when the first page needs a custom page style. The #page_style
|
|
123
|
+
# method needs to be used to define a page style which is then used with the #new_page
|
|
124
|
+
# method to create the initial page/frame.
|
|
116
125
|
#
|
|
117
126
|
# page_size::
|
|
118
127
|
# Can be any valid predefined page size (see Type::Page::PAPER_SIZE) or an array [llx, lly,
|
|
119
128
|
# urx, ury] specifying a custom page size.
|
|
120
129
|
#
|
|
130
|
+
# Only used if +skip_page_creation+ is +false+.
|
|
131
|
+
#
|
|
121
132
|
# page_orientation::
|
|
122
|
-
# Specifies the orientation of the page, either +:portrait+ or +:landscape
|
|
123
|
-
#
|
|
133
|
+
# Specifies the orientation of the page, either +:portrait+ or +:landscape+, if +page_size+
|
|
134
|
+
# is one of the predefined page sizes.
|
|
135
|
+
#
|
|
136
|
+
# Only used if +skip_page_creation+ is +false+.
|
|
124
137
|
#
|
|
125
138
|
# margin::
|
|
126
139
|
# The margin to use. See HexaPDF::Layout::Style::Quad#set for possible values.
|
|
127
140
|
#
|
|
141
|
+
# Only used if +skip_page_creation+ is +false+.
|
|
142
|
+
#
|
|
128
143
|
# Example:
|
|
129
144
|
#
|
|
130
|
-
#
|
|
145
|
+
# # Uses the default values
|
|
146
|
+
# composer = HexaPDF::Composer.new
|
|
131
147
|
#
|
|
132
148
|
# HexaPDF::Composer.new(page_size: :Letter, margin: 72) do |composer|
|
|
133
149
|
# #...
|
|
134
150
|
# end
|
|
135
151
|
#
|
|
136
152
|
# HexaPDF::Composer.new(skip_page_creation: true) do |composer|
|
|
137
|
-
#
|
|
138
|
-
#
|
|
139
|
-
#
|
|
153
|
+
# composer.page_style(:default) do |canvas, style|
|
|
154
|
+
# style.frame = style.create_frame(canvas.context, 36)
|
|
155
|
+
# end
|
|
156
|
+
# composer.new_page
|
|
140
157
|
# # ...
|
|
141
158
|
# end
|
|
142
159
|
def initialize(skip_page_creation: false, page_size: :A4, page_orientation: :portrait,
|
|
143
160
|
margin: 36) #:yields: composer
|
|
144
161
|
@document = HexaPDF::Document.new
|
|
145
162
|
@page_styles = {}
|
|
146
|
-
@
|
|
163
|
+
@next_page_style = :default
|
|
147
164
|
unless skip_page_creation
|
|
148
165
|
page_style(:default, page_size: page_size, orientation: page_orientation) do |canvas, style|
|
|
149
166
|
style.frame = style.create_frame(canvas.context, margin)
|
|
@@ -155,41 +172,61 @@ module HexaPDF
|
|
|
155
172
|
|
|
156
173
|
# Creates a new page, making it the current one.
|
|
157
174
|
#
|
|
158
|
-
# The page style to use for the new page can be set via the +style+ argument.
|
|
159
|
-
# the currently set page style is used
|
|
175
|
+
# The page style (see #page_style) to use for the new page can be set via the +style+ argument.
|
|
176
|
+
# If not provided, the currently set page style is used (:default is the initial value for
|
|
177
|
+
# @next_page_style).
|
|
160
178
|
#
|
|
161
|
-
# The
|
|
162
|
-
# If this information is not provided
|
|
179
|
+
# The applied page style determines the page style that should be used for the following new
|
|
180
|
+
# pages (see Layout::PageStyle#next_style). If this information is not provided by the applied
|
|
181
|
+
# page style, that page style is used again.
|
|
163
182
|
#
|
|
164
183
|
# Examples:
|
|
165
184
|
#
|
|
166
|
-
#
|
|
185
|
+
# # Define two page styles
|
|
186
|
+
# composer.page_style(:cover, page_size: :A4, next_style: :content)
|
|
167
187
|
# composer.page_style(:content, page_size: :A4)
|
|
188
|
+
#
|
|
168
189
|
# composer.new_page(:cover) # uses the :cover style, set next style to :content
|
|
169
190
|
# composer.new_page # uses the :content style, next style again :content
|
|
170
|
-
def new_page(style = @
|
|
191
|
+
def new_page(style = @next_page_style)
|
|
171
192
|
page_style = @page_styles.fetch(style) do |key|
|
|
172
193
|
raise ArgumentError, "Page style #{key} has not been defined"
|
|
173
194
|
end
|
|
174
195
|
@page = @document.pages.add(page_style.create_page(@document))
|
|
175
196
|
@canvas = @page.canvas
|
|
176
197
|
@frame = page_style.frame
|
|
177
|
-
@
|
|
198
|
+
@next_page_style = page_style.next_style || style
|
|
178
199
|
end
|
|
179
200
|
|
|
180
|
-
# The x-position
|
|
201
|
+
# The x-position inside the current frame where the next box (provided it fits) will be placed.
|
|
202
|
+
#
|
|
203
|
+
# Example:
|
|
204
|
+
#
|
|
205
|
+
# #>pdf-composer
|
|
206
|
+
# composer.text("Hello", position: :float)
|
|
207
|
+
# composer.canvas.stroke_color("hp-blue").
|
|
208
|
+
# circle(composer.x, composer.y, 0.5).fill.
|
|
209
|
+
# circle(composer.x, composer.y, 5).stroke
|
|
181
210
|
def x
|
|
182
211
|
@frame.x
|
|
183
212
|
end
|
|
184
213
|
|
|
185
|
-
# The y-position
|
|
214
|
+
# The y-position inside the current frame.where the next box (provided it fits) will be placed.
|
|
215
|
+
#
|
|
216
|
+
# Example:
|
|
217
|
+
#
|
|
218
|
+
# #>pdf-composer
|
|
219
|
+
# composer.text("Hello", position: :float)
|
|
220
|
+
# composer.canvas.stroke_color("hp-blue").
|
|
221
|
+
# circle(composer.x, composer.y, 0.5).fill.
|
|
222
|
+
# circle(composer.x, composer.y, 5).stroke
|
|
186
223
|
def y
|
|
187
224
|
@frame.y
|
|
188
225
|
end
|
|
189
226
|
|
|
190
|
-
# Writes the PDF document to the given output.
|
|
227
|
+
# Writes the created PDF document to the given output.
|
|
191
228
|
#
|
|
192
|
-
# See Document#write for details.
|
|
229
|
+
# See HexaPDF::Document#write for details.
|
|
193
230
|
def write(output, optimize: true, **options)
|
|
194
231
|
@document.write(output, optimize: optimize, **options)
|
|
195
232
|
end
|
|
@@ -201,6 +238,8 @@ module HexaPDF
|
|
|
201
238
|
# Creates or updates the HexaPDF::Layout::Style object called +name+ with the given property
|
|
202
239
|
# values and returns it.
|
|
203
240
|
#
|
|
241
|
+
# If neither +base+ nor any style properties are specified, the style +name+ is just returned.
|
|
242
|
+
#
|
|
204
243
|
# See HexaPDF::Document::Layout#style for details; this method is just a thin wrapper around
|
|
205
244
|
# that method.
|
|
206
245
|
#
|
|
@@ -225,15 +264,15 @@ module HexaPDF
|
|
|
225
264
|
# +nil+ is returned.
|
|
226
265
|
#
|
|
227
266
|
# If one or more page style attributes are given, a new HexaPDF::Layout::PageStyle object with
|
|
228
|
-
# those attribute values is created, stored under +name+ and returned.
|
|
229
|
-
# it is used to define the page template.
|
|
267
|
+
# those attribute values is created, stored under +name+ and returned. Additionally, if a block
|
|
268
|
+
# is provided, it is used to define the page template.
|
|
230
269
|
#
|
|
231
270
|
# Example:
|
|
232
271
|
#
|
|
233
272
|
# composer.page_style(:default)
|
|
234
273
|
# composer.page_style(:cover, page_size: :A4) do |canvas, style|
|
|
235
274
|
# page_box = canvas.context.box
|
|
236
|
-
# canvas.fill_color("
|
|
275
|
+
# canvas.fill_color("green") do
|
|
237
276
|
# canvas.rectangle(0, 0, page_box.width, page_box.height).
|
|
238
277
|
# fill
|
|
239
278
|
# end
|
|
@@ -251,9 +290,9 @@ module HexaPDF
|
|
|
251
290
|
|
|
252
291
|
# Draws the given text at the current position into the current frame.
|
|
253
292
|
#
|
|
254
|
-
# The text will be positioned at the current position if possible. Otherwise the
|
|
255
|
-
# position is used. If the text doesn't fit onto the current page or only partially,
|
|
256
|
-
# are created automatically.
|
|
293
|
+
# The text will be positioned at the current position (see #x and #y) if possible. Otherwise the
|
|
294
|
+
# next best position is used. If the text doesn't fit onto the current page or only partially,
|
|
295
|
+
# one or more new pages are created automatically.
|
|
257
296
|
#
|
|
258
297
|
# This method is of the two main methods for creating text boxes, the other being
|
|
259
298
|
# #formatted_text. It uses HexaPDF::Document::Layout#text_box behind the scenes to create the
|
|
@@ -264,18 +303,21 @@ module HexaPDF
|
|
|
264
303
|
# Examples:
|
|
265
304
|
#
|
|
266
305
|
# #>pdf-composer
|
|
267
|
-
# composer.text("Test " * 15)
|
|
306
|
+
# composer.text("Test it now " * 15)
|
|
268
307
|
# composer.text("Now " * 7, width: 100)
|
|
269
|
-
# composer.text("Another test", font_size: 15, fill_color: "
|
|
308
|
+
# composer.text("Another test", font_size: 15, fill_color: "hp-blue")
|
|
270
309
|
# composer.text("Different box style", fill_color: 'white', box_style: {
|
|
271
310
|
# underlays: [->(c, b) { c.rectangle(0, 0, b.content_width, b.content_height).fill }]
|
|
272
311
|
# })
|
|
312
|
+
#
|
|
313
|
+
# See: #formatted_text, HexaPDF::Layout::TextBox, HexaPDF::Layout::TextFragment
|
|
273
314
|
def text(str, width: 0, height: 0, style: nil, box_style: nil, **style_properties)
|
|
274
315
|
draw_box(@document.layout.text_box(str, width: width, height: height, style: style,
|
|
275
316
|
box_style: box_style, **style_properties))
|
|
276
317
|
end
|
|
277
318
|
|
|
278
|
-
# Draws text like #text but allows parts of the text to be formatted differently
|
|
319
|
+
# Draws text like #text but allows parts of the text to be formatted differently and
|
|
320
|
+
# interspersing with inline boxes.
|
|
279
321
|
#
|
|
280
322
|
# It uses HexaPDF::Document::Layout#formatted_text_box behind the scenes to create the
|
|
281
323
|
# HexaPDF::Layout::TextBox that does the actual work. See that method for details on the
|
|
@@ -285,10 +327,13 @@ module HexaPDF
|
|
|
285
327
|
#
|
|
286
328
|
# #>pdf-composer
|
|
287
329
|
# composer.formatted_text(["Some string"])
|
|
288
|
-
# composer.formatted_text(["Some ", {text: "string", fill_color:
|
|
330
|
+
# composer.formatted_text(["Some ", {text: "string", fill_color: "hp-orange"}])
|
|
289
331
|
# composer.formatted_text(["Some ", {link: "https://example.com",
|
|
290
|
-
# fill_color: 'blue', text: "Example"}])
|
|
332
|
+
# fill_color: 'hp-blue', text: "Example"}])
|
|
291
333
|
# composer.formatted_text(["Some ", {text: "string", style: {font_size: 20}}])
|
|
334
|
+
# block = lambda {|list| list.text("First item"); list.text("Second item") }
|
|
335
|
+
# composer.formatted_text(["Some ", {box: :list, width: 50,
|
|
336
|
+
# valign: :bottom, block: block}])
|
|
292
337
|
#
|
|
293
338
|
# See: #text, HexaPDF::Layout::TextBox, HexaPDF::Layout::TextFragment
|
|
294
339
|
def formatted_text(data, width: 0, height: 0, style: nil, box_style: nil, **style_properties)
|
|
@@ -296,7 +341,7 @@ module HexaPDF
|
|
|
296
341
|
box_style: box_style, **style_properties))
|
|
297
342
|
end
|
|
298
343
|
|
|
299
|
-
# Draws the given image at the current position.
|
|
344
|
+
# Draws the given image at the current position (see #x and #y).
|
|
300
345
|
#
|
|
301
346
|
# It uses HexaPDF::Document::Layout#image_box behind the scenes to create the
|
|
302
347
|
# HexaPDF::Layout::ImageBox that does the actual work. See that method for details on the
|
|
@@ -314,7 +359,7 @@ module HexaPDF
|
|
|
314
359
|
style: style, **style_properties))
|
|
315
360
|
end
|
|
316
361
|
|
|
317
|
-
# Draws the named box at the current position.
|
|
362
|
+
# Draws the named box at the current position (see #x and #y).
|
|
318
363
|
#
|
|
319
364
|
# It uses HexaPDF::Document::Layout#box behind the scenes to create the named box. See that
|
|
320
365
|
# method for details on the arguments.
|
|
@@ -331,11 +376,19 @@ module HexaPDF
|
|
|
331
376
|
|
|
332
377
|
# Draws any custom box that can be created using HexaPDF::Document::Layout.
|
|
333
378
|
#
|
|
379
|
+
# This includes all named boxes defined in the 'layout.boxes.map' configuration option.
|
|
380
|
+
#
|
|
334
381
|
# Examples:
|
|
335
382
|
#
|
|
336
383
|
# #>pdf-composer
|
|
337
|
-
# composer.lorem_ipsum
|
|
338
|
-
# composer.
|
|
384
|
+
# composer.lorem_ipsum(sentences: 1, margin: [0, 0, 5])
|
|
385
|
+
# composer.list(item_spacing: 2) do |list|
|
|
386
|
+
# composer.document.config['layout.boxes.map'].each do |name, klass|
|
|
387
|
+
# list.formatted_text([{text: name.to_s, fill_color: "hp-blue-dark"}, "\n#{klass}"])
|
|
388
|
+
# end
|
|
389
|
+
# end
|
|
390
|
+
#
|
|
391
|
+
# See: HexaPDF::Document::Layout#box
|
|
339
392
|
def method_missing(name, *args, **kwargs, &block)
|
|
340
393
|
if @document.layout.box_creation_method?(name)
|
|
341
394
|
draw_box(@document.layout.send(name, *args, **kwargs, &block))
|
|
@@ -344,8 +397,7 @@ module HexaPDF
|
|
|
344
397
|
end
|
|
345
398
|
end
|
|
346
399
|
|
|
347
|
-
# :nodoc:
|
|
348
|
-
def respond_to_missing?(name, _private)
|
|
400
|
+
def respond_to_missing?(name, _private) # :nodoc:
|
|
349
401
|
@document.layout.box_creation_method?(name) || super
|
|
350
402
|
end
|
|
351
403
|
|
|
@@ -393,7 +445,7 @@ module HexaPDF
|
|
|
393
445
|
#
|
|
394
446
|
# #>pdf-composer
|
|
395
447
|
# stamp = composer.create_stamp(50, 50) do |canvas|
|
|
396
|
-
# canvas.fill_color("
|
|
448
|
+
# canvas.fill_color("hp-blue").line_width(5).
|
|
397
449
|
# rectangle(10, 10, 30, 30).fill_stroke
|
|
398
450
|
# end
|
|
399
451
|
# composer.image(stamp, width: 20, height: 20)
|
|
@@ -44,12 +44,12 @@ module HexaPDF
|
|
|
44
44
|
# == Overview
|
|
45
45
|
#
|
|
46
46
|
# HexaPDF allows detailed control over many aspects of PDF manipulation. If there is a need to
|
|
47
|
-
# use a certain default value somewhere, it is defined as configuration
|
|
47
|
+
# use a certain default value somewhere, it is defined as a configuration option so that it can
|
|
48
48
|
# easily be changed.
|
|
49
49
|
#
|
|
50
50
|
# Some options are defined as global options because they are needed on the class level - see
|
|
51
|
-
# HexaPDF::GlobalConfiguration[index.html#GlobalConfiguration]. Other options can be configured
|
|
52
|
-
# individual documents as they allow to fine-tune some behavior - see
|
|
51
|
+
# HexaPDF::GlobalConfiguration[index.html#GlobalConfiguration]. Other options can be configured
|
|
52
|
+
# for individual documents as they allow to fine-tune some behavior - see
|
|
53
53
|
# HexaPDF::DefaultDocumentConfiguration[index.html#DefaultDocumentConfiguration].
|
|
54
54
|
#
|
|
55
55
|
# A configuration option name is dot-separted to provide a hierarchy of option names. For
|
|
@@ -155,9 +155,6 @@ module HexaPDF
|
|
|
155
155
|
# A boolean specifying whether an AcroForm field's appearances should automatically be
|
|
156
156
|
# generated if they are missing.
|
|
157
157
|
#
|
|
158
|
-
# acro_form.text_field.default_width::
|
|
159
|
-
# A number specifying the default width of AcroForm text fields which should be auto-sized.
|
|
160
|
-
#
|
|
161
158
|
# acro_form.default_font_size::
|
|
162
159
|
# A number specifying the default font size of AcroForm text fields which should be auto-sized.
|
|
163
160
|
#
|
|
@@ -248,7 +245,7 @@ module HexaPDF
|
|
|
248
245
|
#
|
|
249
246
|
# The most often used filters are implemented and readily available.
|
|
250
247
|
#
|
|
251
|
-
# See
|
|
248
|
+
# See PDF2.0 s7.4.1, ADB sH.3 3.3
|
|
252
249
|
#
|
|
253
250
|
# font.map::
|
|
254
251
|
# Defines a mapping from font names and variants to font files.
|
|
@@ -278,7 +275,14 @@ module HexaPDF
|
|
|
278
275
|
# was called, you can use +font_wrapper.pdf_object.document+.
|
|
279
276
|
#
|
|
280
277
|
# The default implementation returns an object of class HexaPDF::Font::InvalidGlyph which, when
|
|
281
|
-
# not removed before encoding, will raise
|
|
278
|
+
# not removed before encoding, will raise a HexaPDF::MissingGlyphError.
|
|
279
|
+
#
|
|
280
|
+
# If a replacement glyph should be displayed instead of an error, the following provides a good
|
|
281
|
+
# starting implementation:
|
|
282
|
+
#
|
|
283
|
+
# doc.config['font.on_missing_glyph'] = lambda do |character, font_wrapper|
|
|
284
|
+
# font_wrapper.custom_glyph(font_wrapper.font_type == :Type1 ? :question : 0, character)
|
|
285
|
+
# end
|
|
282
286
|
#
|
|
283
287
|
# font.on_missing_unicode_mapping::
|
|
284
288
|
# Callback hook when a character code point cannot be converted to a Unicode character.
|
|
@@ -298,11 +302,6 @@ module HexaPDF
|
|
|
298
302
|
#
|
|
299
303
|
# See the HexaPDF::FontLoader module for information on how to implement a font loader object.
|
|
300
304
|
#
|
|
301
|
-
# graphic_object.map::
|
|
302
|
-
# A mapping from graphic object names to graphic object factories.
|
|
303
|
-
#
|
|
304
|
-
# See HexaPDF::Content::GraphicObject for more information.
|
|
305
|
-
#
|
|
306
305
|
# graphic_object.arc.max_curves::
|
|
307
306
|
# The maximum number of curves used for approximating a complete ellipse using Bezier curves.
|
|
308
307
|
#
|
|
@@ -310,6 +309,11 @@ module HexaPDF
|
|
|
310
309
|
# to compute. It should not be set to values lower than 4, otherwise the approximation of a
|
|
311
310
|
# complete ellipse is visibly false.
|
|
312
311
|
#
|
|
312
|
+
# graphic_object.map::
|
|
313
|
+
# A mapping from graphic object names to graphic object factories.
|
|
314
|
+
#
|
|
315
|
+
# See HexaPDF::Content::GraphicObject for more information.
|
|
316
|
+
#
|
|
313
317
|
# image_loader::
|
|
314
318
|
# An array with image loader implementations. When an image should be loaded, the array is
|
|
315
319
|
# iterated in sequence to find a suitable image loader.
|
|
@@ -381,14 +385,6 @@ module HexaPDF
|
|
|
381
385
|
#
|
|
382
386
|
# Defaults to +true+.
|
|
383
387
|
#
|
|
384
|
-
# sorted_tree.max_leaf_node_size::
|
|
385
|
-
# The maximum number of nodes that should be in a leaf node of a node tree.
|
|
386
|
-
#
|
|
387
|
-
# style.layers_map::
|
|
388
|
-
# A mapping from style layer names to layer objects.
|
|
389
|
-
#
|
|
390
|
-
# See HexaPDF::Layout::Style::Layers for more information.
|
|
391
|
-
#
|
|
392
388
|
# signature.signing_handler::
|
|
393
389
|
# A mapping from a Symbol to a signing handler class (see
|
|
394
390
|
# HexaPDF::Document::Signatures::DefaultHandler). If the value is a String, it should contain
|
|
@@ -403,6 +399,14 @@ module HexaPDF
|
|
|
403
399
|
# filter value of a signature dictionary is ignored since we only support the standard
|
|
404
400
|
# signature algorithms.
|
|
405
401
|
#
|
|
402
|
+
# sorted_tree.max_leaf_node_size::
|
|
403
|
+
# The maximum number of nodes that should be in a leaf node of a node tree.
|
|
404
|
+
#
|
|
405
|
+
# style.layers_map::
|
|
406
|
+
# A mapping from style layer names to layer objects.
|
|
407
|
+
#
|
|
408
|
+
# See HexaPDF::Layout::Style::Layers for more information.
|
|
409
|
+
#
|
|
406
410
|
# task.map::
|
|
407
411
|
# A mapping from task names to callable task objects. See HexaPDF::Task for more information.
|
|
408
412
|
DefaultDocumentConfiguration =
|
|
@@ -459,13 +463,13 @@ module HexaPDF
|
|
|
459
463
|
'HexaPDF::FontLoader::FromConfiguration',
|
|
460
464
|
'HexaPDF::FontLoader::FromFile',
|
|
461
465
|
],
|
|
466
|
+
'graphic_object.arc.max_curves' => 6,
|
|
462
467
|
'graphic_object.map' => {
|
|
463
468
|
arc: 'HexaPDF::Content::GraphicObject::Arc',
|
|
464
469
|
endpoint_arc: 'HexaPDF::Content::GraphicObject::EndpointArc',
|
|
465
470
|
solid_arc: 'HexaPDF::Content::GraphicObject::SolidArc',
|
|
466
471
|
geom2d: 'HexaPDF::Content::GraphicObject::Geom2D',
|
|
467
472
|
},
|
|
468
|
-
'graphic_object.arc.max_curves' => 6,
|
|
469
473
|
'image_loader' => [
|
|
470
474
|
'HexaPDF::ImageLoader::JPEG',
|
|
471
475
|
'HexaPDF::ImageLoader::PNG',
|
|
@@ -479,15 +483,12 @@ module HexaPDF
|
|
|
479
483
|
image: 'HexaPDF::Layout::ImageBox',
|
|
480
484
|
column: 'HexaPDF::Layout::ColumnBox',
|
|
481
485
|
list: 'HexaPDF::Layout::ListBox',
|
|
486
|
+
table: 'HexaPDF::Layout::TableBox',
|
|
482
487
|
},
|
|
483
488
|
'page.default_media_box' => :A4,
|
|
484
489
|
'page.default_media_orientation' => :portrait,
|
|
485
490
|
'parser.on_correctable_error' => proc { false },
|
|
486
491
|
'parser.try_xref_reconstruction' => true,
|
|
487
|
-
'sorted_tree.max_leaf_node_size' => 64,
|
|
488
|
-
'style.layers_map' => {
|
|
489
|
-
link: 'HexaPDF::Layout::Style::LinkLayer',
|
|
490
|
-
},
|
|
491
492
|
'signature.signing_handler' => {
|
|
492
493
|
default: 'HexaPDF::DigitalSignature::Signing::DefaultHandler',
|
|
493
494
|
timestamp: 'HexaPDF::DigitalSignature::Signing::TimestampHandler',
|
|
@@ -498,6 +499,10 @@ module HexaPDF
|
|
|
498
499
|
'ETSI.CAdES.detached': 'HexaPDF::DigitalSignature::CMSHandler',
|
|
499
500
|
'ETSI.RFC3161': 'HexaPDF::DigitalSignature::CMSHandler',
|
|
500
501
|
},
|
|
502
|
+
'sorted_tree.max_leaf_node_size' => 64,
|
|
503
|
+
'style.layers_map' => {
|
|
504
|
+
link: 'HexaPDF::Layout::Style::LinkLayer',
|
|
505
|
+
},
|
|
501
506
|
'task.map' => {
|
|
502
507
|
optimize: 'HexaPDF::Task::Optimize',
|
|
503
508
|
dereference: 'HexaPDF::Task::Dereference',
|
|
@@ -512,12 +517,19 @@ module HexaPDF
|
|
|
512
517
|
#
|
|
513
518
|
# Classes for the most often used color space families are implemented and readily available.
|
|
514
519
|
#
|
|
515
|
-
# See
|
|
520
|
+
# See PDF2.0 s8.6
|
|
516
521
|
#
|
|
517
522
|
# filter.flate.compression::
|
|
518
523
|
# Specifies the compression level that should be used with the FlateDecode filter. The level
|
|
519
524
|
# can range from 0 (no compression), 1 (best speed) to 9 (best compression, default).
|
|
520
525
|
#
|
|
526
|
+
# filter.flate.memory::
|
|
527
|
+
# Specifies the memory level that should be used with the FlateDecode filter. The level can
|
|
528
|
+
# range from 1 (minimum memory usage; slow, reduces compression) to 9 (maximum memory usage).
|
|
529
|
+
#
|
|
530
|
+
# The HexaPDF default value of 6 has been found in tests to be nearly equivalent to the Zlib
|
|
531
|
+
# default of 8 in terms of speed and compression level but uses less memory.
|
|
532
|
+
#
|
|
521
533
|
# filter.flate.on_error::
|
|
522
534
|
# Callback hook when a potentially recoverable Zlib error occurs in the FlateDecode filter.
|
|
523
535
|
#
|
|
@@ -527,13 +539,6 @@ module HexaPDF
|
|
|
527
539
|
#
|
|
528
540
|
# The default implementation prevents errors from being raised.
|
|
529
541
|
#
|
|
530
|
-
# filter.flate.memory::
|
|
531
|
-
# Specifies the memory level that should be used with the FlateDecode filter. The level can
|
|
532
|
-
# range from 1 (minimum memory usage; slow, reduces compression) to 9 (maximum memory usage).
|
|
533
|
-
#
|
|
534
|
-
# The HexaPDF default value of 6 has been found in tests to be nearly equivalent to the Zlib
|
|
535
|
-
# default of 8 in terms of speed and compression level but uses less memory.
|
|
536
|
-
#
|
|
537
542
|
# filter.predictor.strict::
|
|
538
543
|
# Specifies whether the predictor algorithm used by LZWDecode and FlateDecode should operate in
|
|
539
544
|
# strict mode, i.e. adhering to the PDF specification without correcting for common deficiences
|
|
@@ -555,15 +560,15 @@ module HexaPDF
|
|
|
555
560
|
# This mapping is used to provide automatic wrapping of objects in the HexaPDF::Document#wrap
|
|
556
561
|
# method.
|
|
557
562
|
GlobalConfiguration =
|
|
558
|
-
Configuration.new('
|
|
559
|
-
'filter.flate.on_error' => proc { false },
|
|
560
|
-
'filter.flate.memory' => 6,
|
|
561
|
-
'filter.predictor.strict' => false,
|
|
562
|
-
'color_space.map' => {
|
|
563
|
+
Configuration.new('color_space.map' => {
|
|
563
564
|
DeviceRGB: 'HexaPDF::Content::ColorSpace::DeviceRGB',
|
|
564
565
|
DeviceCMYK: 'HexaPDF::Content::ColorSpace::DeviceCMYK',
|
|
565
566
|
DeviceGray: 'HexaPDF::Content::ColorSpace::DeviceGray',
|
|
566
567
|
},
|
|
568
|
+
'filter.flate.compression' => 9,
|
|
569
|
+
'filter.flate.memory' => 6,
|
|
570
|
+
'filter.flate.on_error' => proc { false },
|
|
571
|
+
'filter.predictor.strict' => false,
|
|
567
572
|
'object.type_map' => {
|
|
568
573
|
XRef: 'HexaPDF::Type::XRefStream',
|
|
569
574
|
ObjStm: 'HexaPDF::Type::ObjectStream',
|