hexapdf 0.32.2 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +104 -1
- data/README.md +9 -0
- data/examples/002-graphics.rb +15 -17
- data/examples/003-arcs.rb +9 -9
- data/examples/009-text_layouter_alignment.rb +1 -1
- data/examples/010-text_layouter_inline_boxes.rb +2 -2
- data/examples/011-text_layouter_line_wrapping.rb +1 -1
- data/examples/012-text_layouter_styling.rb +7 -7
- data/examples/013-text_layouter_shapes.rb +1 -1
- data/examples/014-text_in_polygon.rb +1 -1
- data/examples/015-boxes.rb +8 -7
- data/examples/016-frame_automatic_box_placement.rb +2 -2
- data/examples/017-frame_text_flow.rb +2 -1
- data/examples/018-composer.rb +1 -1
- data/examples/020-column_box.rb +2 -1
- data/examples/025-table_box.rb +46 -0
- data/examples/026-optional_content.rb +55 -0
- data/examples/027-composer_optional_content.rb +83 -0
- data/lib/hexapdf/cli/command.rb +12 -3
- data/lib/hexapdf/cli/fonts.rb +1 -1
- data/lib/hexapdf/cli/form.rb +5 -5
- data/lib/hexapdf/cli/inspect.rb +5 -7
- data/lib/hexapdf/composer.rb +106 -53
- data/lib/hexapdf/configuration.rb +65 -40
- data/lib/hexapdf/content/canvas.rb +445 -267
- data/lib/hexapdf/content/color_space.rb +72 -25
- data/lib/hexapdf/content/graphic_object/arc.rb +57 -24
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +66 -23
- data/lib/hexapdf/content/graphic_object/geom2d.rb +47 -6
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +58 -36
- data/lib/hexapdf/content/graphic_object.rb +6 -7
- data/lib/hexapdf/content/graphics_state.rb +54 -45
- data/lib/hexapdf/content/operator.rb +54 -54
- data/lib/hexapdf/content/parser.rb +2 -2
- data/lib/hexapdf/content/processor.rb +15 -15
- data/lib/hexapdf/content/transformation_matrix.rb +1 -1
- data/lib/hexapdf/content.rb +5 -0
- data/lib/hexapdf/dictionary.rb +7 -5
- data/lib/hexapdf/dictionary_fields.rb +43 -16
- data/lib/hexapdf/digital_signature/cms_handler.rb +2 -2
- data/lib/hexapdf/digital_signature/handler.rb +1 -1
- data/lib/hexapdf/digital_signature/pkcs1_handler.rb +2 -3
- data/lib/hexapdf/digital_signature/signature.rb +6 -6
- data/lib/hexapdf/digital_signature/signatures.rb +13 -12
- data/lib/hexapdf/digital_signature/signing/default_handler.rb +14 -5
- data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +2 -4
- data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +4 -4
- data/lib/hexapdf/digital_signature/signing.rb +4 -0
- data/lib/hexapdf/digital_signature/verification_result.rb +3 -4
- data/lib/hexapdf/digital_signature.rb +7 -2
- data/lib/hexapdf/document/destinations.rb +12 -11
- data/lib/hexapdf/document/files.rb +1 -1
- data/lib/hexapdf/document/fonts.rb +1 -1
- data/lib/hexapdf/document/layout.rb +170 -39
- data/lib/hexapdf/document/pages.rb +4 -3
- data/lib/hexapdf/document.rb +96 -55
- data/lib/hexapdf/encryption/aes.rb +5 -5
- data/lib/hexapdf/encryption/arc4.rb +1 -1
- data/lib/hexapdf/encryption/fast_aes.rb +2 -2
- data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
- data/lib/hexapdf/encryption/identity.rb +1 -1
- data/lib/hexapdf/encryption/ruby_aes.rb +11 -21
- data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
- data/lib/hexapdf/encryption/security_handler.rb +31 -24
- data/lib/hexapdf/encryption/standard_security_handler.rb +45 -36
- data/lib/hexapdf/encryption.rb +7 -2
- data/lib/hexapdf/error.rb +18 -0
- data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
- data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
- data/lib/hexapdf/filter/flate_decode.rb +1 -1
- data/lib/hexapdf/filter/lzw_decode.rb +1 -1
- data/lib/hexapdf/filter/pass_through.rb +1 -1
- data/lib/hexapdf/filter/predictor.rb +1 -1
- data/lib/hexapdf/filter/run_length_decode.rb +1 -1
- data/lib/hexapdf/filter.rb +55 -6
- data/lib/hexapdf/font/cmap/parser.rb +2 -2
- data/lib/hexapdf/font/cmap.rb +1 -1
- data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +2 -2
- data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +3 -3
- data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
- data/lib/hexapdf/font/invalid_glyph.rb +3 -0
- data/lib/hexapdf/font/true_type_wrapper.rb +17 -4
- data/lib/hexapdf/font/type1_wrapper.rb +19 -4
- data/lib/hexapdf/font_loader/from_configuration.rb +5 -2
- data/lib/hexapdf/font_loader/from_file.rb +5 -5
- data/lib/hexapdf/font_loader/standard14.rb +3 -3
- data/lib/hexapdf/font_loader.rb +3 -0
- data/lib/hexapdf/image_loader/jpeg.rb +2 -2
- data/lib/hexapdf/image_loader/pdf.rb +1 -1
- data/lib/hexapdf/image_loader/png.rb +2 -2
- data/lib/hexapdf/image_loader.rb +1 -1
- data/lib/hexapdf/importer.rb +13 -0
- data/lib/hexapdf/layout/box.rb +32 -5
- data/lib/hexapdf/layout/box_fitter.rb +2 -2
- data/lib/hexapdf/layout/column_box.rb +20 -5
- data/lib/hexapdf/layout/frame.rb +53 -18
- data/lib/hexapdf/layout/image_box.rb +5 -0
- data/lib/hexapdf/layout/inline_box.rb +21 -9
- data/lib/hexapdf/layout/list_box.rb +50 -20
- data/lib/hexapdf/layout/page_style.rb +6 -5
- data/lib/hexapdf/layout/style.rb +64 -9
- data/lib/hexapdf/layout/table_box.rb +684 -0
- data/lib/hexapdf/layout/text_box.rb +12 -3
- data/lib/hexapdf/layout/text_fragment.rb +29 -3
- data/lib/hexapdf/layout/text_layouter.rb +32 -8
- data/lib/hexapdf/layout.rb +1 -0
- data/lib/hexapdf/name_tree_node.rb +1 -1
- data/lib/hexapdf/number_tree_node.rb +1 -1
- data/lib/hexapdf/object.rb +18 -7
- data/lib/hexapdf/parser.rb +7 -7
- data/lib/hexapdf/pdf_array.rb +1 -1
- data/lib/hexapdf/rectangle.rb +1 -1
- data/lib/hexapdf/reference.rb +1 -1
- data/lib/hexapdf/revision.rb +1 -1
- data/lib/hexapdf/revisions.rb +3 -3
- data/lib/hexapdf/serializer.rb +15 -15
- data/lib/hexapdf/stream.rb +5 -4
- data/lib/hexapdf/tokenizer.rb +14 -14
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +22 -22
- data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/field.rb +2 -2
- data/lib/hexapdf/type/acro_form/form.rb +1 -1
- data/lib/hexapdf/type/acro_form/signature_field.rb +4 -4
- data/lib/hexapdf/type/acro_form/text_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/variable_text_field.rb +1 -1
- data/lib/hexapdf/type/acro_form.rb +1 -1
- data/lib/hexapdf/type/action.rb +1 -1
- data/lib/hexapdf/type/actions/go_to.rb +1 -1
- data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
- data/lib/hexapdf/type/actions/launch.rb +1 -1
- data/lib/hexapdf/type/actions/set_ocg_state.rb +86 -0
- data/lib/hexapdf/type/actions/uri.rb +1 -1
- data/lib/hexapdf/type/actions.rb +2 -1
- data/lib/hexapdf/type/annotation.rb +3 -3
- data/lib/hexapdf/type/annotations/link.rb +1 -1
- data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
- data/lib/hexapdf/type/annotations/text.rb +2 -3
- data/lib/hexapdf/type/annotations/widget.rb +2 -2
- data/lib/hexapdf/type/annotations.rb +1 -1
- data/lib/hexapdf/type/catalog.rb +11 -2
- data/lib/hexapdf/type/cid_font.rb +18 -4
- data/lib/hexapdf/type/embedded_file.rb +1 -1
- data/lib/hexapdf/type/file_specification.rb +2 -2
- data/lib/hexapdf/type/font_descriptor.rb +1 -1
- data/lib/hexapdf/type/font_simple.rb +2 -2
- data/lib/hexapdf/type/font_type0.rb +3 -3
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/form.rb +76 -6
- data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
- data/lib/hexapdf/type/icon_fit.rb +1 -1
- data/lib/hexapdf/type/image.rb +1 -1
- data/lib/hexapdf/type/info.rb +1 -1
- data/lib/hexapdf/type/mark_information.rb +1 -1
- data/lib/hexapdf/type/names.rb +2 -2
- data/lib/hexapdf/type/object_stream.rb +2 -1
- data/lib/hexapdf/type/optional_content_configuration.rb +170 -0
- data/lib/hexapdf/type/optional_content_group.rb +370 -0
- data/lib/hexapdf/type/optional_content_membership.rb +63 -0
- data/lib/hexapdf/type/optional_content_properties.rb +158 -0
- data/lib/hexapdf/type/outline.rb +1 -1
- data/lib/hexapdf/type/outline_item.rb +1 -1
- data/lib/hexapdf/type/page.rb +46 -21
- data/lib/hexapdf/type/page_label.rb +5 -9
- data/lib/hexapdf/type/page_tree_node.rb +1 -1
- data/lib/hexapdf/type/resources.rb +1 -1
- data/lib/hexapdf/type/trailer.rb +2 -2
- data/lib/hexapdf/type/viewer_preferences.rb +1 -1
- data/lib/hexapdf/type/xref_stream.rb +2 -2
- data/lib/hexapdf/type.rb +4 -0
- data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -2
- data/lib/hexapdf/version.rb +1 -1
- data/lib/hexapdf/writer.rb +4 -4
- data/lib/hexapdf/xref_section.rb +2 -2
- data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +11 -1
- data/test/hexapdf/content/graphic_object/test_geom2d.rb +7 -0
- data/test/hexapdf/content/test_canvas.rb +49 -1
- data/test/hexapdf/digital_signature/test_signatures.rb +22 -0
- data/test/hexapdf/document/test_files.rb +2 -2
- data/test/hexapdf/document/test_layout.rb +105 -2
- data/test/hexapdf/document/test_pages.rb +6 -6
- data/test/hexapdf/encryption/test_security_handler.rb +12 -11
- data/test/hexapdf/encryption/test_standard_security_handler.rb +35 -23
- data/test/hexapdf/font/test_true_type_wrapper.rb +18 -1
- data/test/hexapdf/font/test_type1_wrapper.rb +15 -1
- data/test/hexapdf/layout/test_box.rb +14 -5
- data/test/hexapdf/layout/test_column_box.rb +65 -21
- data/test/hexapdf/layout/test_frame.rb +27 -15
- data/test/hexapdf/layout/test_image_box.rb +4 -0
- data/test/hexapdf/layout/test_inline_box.rb +17 -3
- data/test/hexapdf/layout/test_list_box.rb +84 -33
- data/test/hexapdf/layout/test_page_style.rb +3 -2
- data/test/hexapdf/layout/test_style.rb +60 -0
- data/test/hexapdf/layout/test_table_box.rb +728 -0
- data/test/hexapdf/layout/test_text_box.rb +26 -0
- data/test/hexapdf/layout/test_text_fragment.rb +33 -0
- data/test/hexapdf/layout/test_text_layouter.rb +36 -5
- data/test/hexapdf/test_composer.rb +10 -0
- data/test/hexapdf/test_dictionary.rb +10 -0
- data/test/hexapdf/test_dictionary_fields.rb +4 -1
- data/test/hexapdf/test_document.rb +5 -0
- data/test/hexapdf/test_filter.rb +8 -0
- data/test/hexapdf/test_importer.rb +9 -0
- data/test/hexapdf/test_object.rb +16 -5
- data/test/hexapdf/test_stream.rb +7 -0
- data/test/hexapdf/test_writer.rb +3 -3
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +13 -5
- data/test/hexapdf/type/acro_form/test_form.rb +4 -3
- data/test/hexapdf/type/actions/test_set_ocg_state.rb +40 -0
- data/test/hexapdf/type/test_catalog.rb +11 -0
- data/test/hexapdf/type/test_form.rb +119 -0
- data/test/hexapdf/type/test_optional_content_configuration.rb +112 -0
- data/test/hexapdf/type/test_optional_content_group.rb +158 -0
- data/test/hexapdf/type/test_optional_content_properties.rb +109 -0
- data/test/hexapdf/type/test_page.rb +20 -6
- metadata +28 -8
|
@@ -63,7 +63,7 @@ module HexaPDF
|
|
|
63
63
|
# The PDF operators themselves are implemented as classes, see Operator. The canvas class uses
|
|
64
64
|
# the Operator::BaseOperator#invoke and Operator::BaseOperator#serialize methods for applying
|
|
65
65
|
# changes and serialization, with one exception: color setters don't invoke the corresponding
|
|
66
|
-
# operator implementation but directly
|
|
66
|
+
# operator implementation but work directly on the graphics state.
|
|
67
67
|
#
|
|
68
68
|
# === General Graphics State Manipulation Methods
|
|
69
69
|
#
|
|
@@ -161,7 +161,7 @@ module HexaPDF
|
|
|
161
161
|
# showing operators, and such groups of operators are allowed to be used only in certain
|
|
162
162
|
# graphics objects or the page description level.
|
|
163
163
|
#
|
|
164
|
-
# Have a look at the PDF specification (
|
|
164
|
+
# Have a look at the PDF specification (PDF2.0 s8.2) for more details.
|
|
165
165
|
#
|
|
166
166
|
# HexaPDF tries to ensure the proper use of the operators and graphics objects and if it
|
|
167
167
|
# cannot do it, an error is raised. So if you don't modify a content stream directly but via
|
|
@@ -169,15 +169,20 @@ module HexaPDF
|
|
|
169
169
|
#
|
|
170
170
|
# === Graphics State
|
|
171
171
|
#
|
|
172
|
-
# Some operators modify the so called graphics state (see
|
|
173
|
-
#
|
|
174
|
-
#
|
|
172
|
+
# Some operators modify the so called graphics state (see GraphicsState). The graphics state is
|
|
173
|
+
# a collection of settings that is used during processing or creating a content stream. For
|
|
174
|
+
# example, the path painting operators don't have operands to specify the line width or the
|
|
175
175
|
# stroke color but take this information from the graphics state.
|
|
176
176
|
#
|
|
177
177
|
# One important thing about the graphics state is that it is only possible to restore a prior
|
|
178
178
|
# state using the save and restore methods. It is not possible to reset the graphics state
|
|
179
179
|
# while creating the content stream!
|
|
180
180
|
#
|
|
181
|
+
# This means, for example, if you use a clipping path (see #clip_path) you should first save the
|
|
182
|
+
# graphics state (#save_graphics_state) and then restore it afterwards
|
|
183
|
+
# (#restore_graphics_state). Otherwise all following operations will be clipped to the clipping
|
|
184
|
+
# path.
|
|
185
|
+
#
|
|
181
186
|
# === Paths
|
|
182
187
|
#
|
|
183
188
|
# A PDF path object consists of one or more subpaths. Each subpath can be a rectangle or can
|
|
@@ -200,7 +205,7 @@ module HexaPDF
|
|
|
200
205
|
# In addition filling may be done using either the nonzero winding number rule or the even-odd
|
|
201
206
|
# rule.
|
|
202
207
|
#
|
|
203
|
-
# See:
|
|
208
|
+
# See: PDF2.0 s8, s9
|
|
204
209
|
class Canvas
|
|
205
210
|
|
|
206
211
|
include HexaPDF::Utils::MathHelpers
|
|
@@ -208,12 +213,20 @@ module HexaPDF
|
|
|
208
213
|
|
|
209
214
|
# The context for which the canvas was created (a HexaPDF::Type::Page or HexaPDF::Type::Form
|
|
210
215
|
# object).
|
|
216
|
+
#
|
|
217
|
+
# The context object is used for two things:
|
|
218
|
+
#
|
|
219
|
+
# * To store the resources (#resources) that are needed by the canvas (e.g. font references).
|
|
220
|
+
#
|
|
221
|
+
# * To access the HexaPDF::Document object to which this canvas and the context object
|
|
222
|
+
# belongs. This is used internally but it is also useful in other situations since some
|
|
223
|
+
# parts of HexaPDF only yield a canvas object, and not also the underlying document object.
|
|
211
224
|
attr_reader :context
|
|
212
225
|
|
|
213
226
|
# The serialized contents produced by the various canvas operations up to this point.
|
|
214
227
|
#
|
|
215
228
|
# Note that the returned string may not be a completely valid PDF content stream since a
|
|
216
|
-
# graphic object may be open or the graphics state not completely restored.
|
|
229
|
+
# graphic object may be open or the graphics state may not be completely restored.
|
|
217
230
|
#
|
|
218
231
|
# See: #stream_data
|
|
219
232
|
attr_reader :contents
|
|
@@ -228,7 +241,7 @@ module HexaPDF
|
|
|
228
241
|
# canvas!
|
|
229
242
|
attr_reader :stream_data
|
|
230
243
|
|
|
231
|
-
# The
|
|
244
|
+
# The GraphicsState object containing the current graphics state.
|
|
232
245
|
#
|
|
233
246
|
# The graphics state must not be changed directly, only by using the provided methods. If it
|
|
234
247
|
# is changed directly, the output will not be correct.
|
|
@@ -236,7 +249,7 @@ module HexaPDF
|
|
|
236
249
|
|
|
237
250
|
# The current graphics object.
|
|
238
251
|
#
|
|
239
|
-
# The graphics object should not be changed directly
|
|
252
|
+
# The graphics object should not be changed directly! It is automatically updated by the
|
|
240
253
|
# invoked methods.
|
|
241
254
|
#
|
|
242
255
|
# This attribute can have the following values:
|
|
@@ -246,13 +259,13 @@ module HexaPDF
|
|
|
246
259
|
# :clipping_path:: The current graphics object is a clipping path.
|
|
247
260
|
# :text:: The current graphics object is a text object.
|
|
248
261
|
#
|
|
249
|
-
# See:
|
|
262
|
+
# See: PDF2.0 s8.2
|
|
250
263
|
attr_accessor :graphics_object
|
|
251
264
|
|
|
252
265
|
# The current point [x, y] of the path.
|
|
253
266
|
#
|
|
254
|
-
# This attribute holds the current point which is only valid if the current graphics
|
|
255
|
-
# is :path.
|
|
267
|
+
# This attribute holds the current point which is only valid if the current graphics object
|
|
268
|
+
# (see #graphic_object) is :path.
|
|
256
269
|
#
|
|
257
270
|
# When the current point changes, the array is modified in place instead of creating a new
|
|
258
271
|
# array!
|
|
@@ -260,7 +273,8 @@ module HexaPDF
|
|
|
260
273
|
|
|
261
274
|
# The operator name/implementation map used when invoking or serializing an operator.
|
|
262
275
|
#
|
|
263
|
-
# Defaults to
|
|
276
|
+
# Defaults to Operator::DEFAULT_OPERATORS, i.e. the standard implementation provided by
|
|
277
|
+
# HexaPDF.
|
|
264
278
|
attr_reader :operators
|
|
265
279
|
|
|
266
280
|
# Creates a new Canvas object for the given context object (either a HexaPDF::Type::Page or a
|
|
@@ -285,7 +299,7 @@ module HexaPDF
|
|
|
285
299
|
@current_point = [0, 0]
|
|
286
300
|
@start_point = [0, 0]
|
|
287
301
|
@contents = ''.b
|
|
288
|
-
|
|
302
|
+
source = HexaPDF::Filter.source_from_proc do
|
|
289
303
|
case graphics_object
|
|
290
304
|
when :path, :clipping_path then end_path
|
|
291
305
|
when :text then end_text
|
|
@@ -293,6 +307,7 @@ module HexaPDF
|
|
|
293
307
|
restore_graphics_state while graphics_state.saved_states?
|
|
294
308
|
@contents
|
|
295
309
|
end
|
|
310
|
+
@stream_data = HexaPDF::StreamData.new(source)
|
|
296
311
|
end
|
|
297
312
|
|
|
298
313
|
# Returns the resource dictionary of the context object.
|
|
@@ -302,11 +317,19 @@ module HexaPDF
|
|
|
302
317
|
@context.resources
|
|
303
318
|
end
|
|
304
319
|
|
|
320
|
+
# Returns the position (x,y) transformed by the current transformation matrix.
|
|
321
|
+
#
|
|
322
|
+
# The resulting position should be interpreted in terms of the coordinate system of the
|
|
323
|
+
# context object (e.g. the page or Form XObject).
|
|
324
|
+
def pos(x, y)
|
|
325
|
+
graphics_state.ctm.evaluate(x, y)
|
|
326
|
+
end
|
|
327
|
+
|
|
305
328
|
# :call-seq:
|
|
306
329
|
# canvas.save_graphics_state => canvas
|
|
307
330
|
# canvas.save_graphics_state { block } => canvas
|
|
308
331
|
#
|
|
309
|
-
# Saves the current graphics state and returns self
|
|
332
|
+
# Saves the current graphics state and returns +self+.
|
|
310
333
|
#
|
|
311
334
|
# If invoked without a block a corresponding call to #restore_graphics_state must be done to
|
|
312
335
|
# ensure proper nesting. Otherwise, i.e. when invoked with a block, the graphics state is
|
|
@@ -320,7 +343,7 @@ module HexaPDF
|
|
|
320
343
|
# #>pdf
|
|
321
344
|
# # With a block
|
|
322
345
|
# canvas.save_graphics_state do
|
|
323
|
-
# canvas.stroke_color("
|
|
346
|
+
# canvas.stroke_color("hp-blue") # After the block the color is reset
|
|
324
347
|
# canvas.line(20, 20, 70, 180).stroke
|
|
325
348
|
# end
|
|
326
349
|
# canvas.line(60, 20, 110, 180).stroke
|
|
@@ -332,7 +355,7 @@ module HexaPDF
|
|
|
332
355
|
# restore_graphics_state
|
|
333
356
|
# canvas.line(140, 20, 190, 180).stroke
|
|
334
357
|
#
|
|
335
|
-
# See:
|
|
358
|
+
# See: PDF2.0 s8.4.2, #restore_graphics_state
|
|
336
359
|
def save_graphics_state
|
|
337
360
|
raise_unless_at_page_description_level
|
|
338
361
|
invoke0(:q)
|
|
@@ -347,11 +370,20 @@ module HexaPDF
|
|
|
347
370
|
# :call-seq:
|
|
348
371
|
# canvas.restore_graphics_state => canvas
|
|
349
372
|
#
|
|
350
|
-
# Restores the
|
|
373
|
+
# Restores the graphics state to the last saved version and returns +self+.
|
|
351
374
|
#
|
|
352
375
|
# Must not be invoked more times than #save_graphics_state.
|
|
353
376
|
#
|
|
354
|
-
#
|
|
377
|
+
# Example:
|
|
378
|
+
#
|
|
379
|
+
# #>pdf
|
|
380
|
+
# canvas.save_graphics_state
|
|
381
|
+
# canvas.circle(100, 100, 50).clip_path.end_path
|
|
382
|
+
# canvas.fill_color("hp-blue").rectangle(0, 0, 100, 100).fill
|
|
383
|
+
# canvas.restore_graphics_state
|
|
384
|
+
# canvas.rectangle(100, 0, 100, 100).fill
|
|
385
|
+
#
|
|
386
|
+
# See: PDF2.0 s8.4.2, #save_graphics_state
|
|
355
387
|
def restore_graphics_state
|
|
356
388
|
raise_unless_at_page_description_level
|
|
357
389
|
invoke0(:Q)
|
|
@@ -363,7 +395,7 @@ module HexaPDF
|
|
|
363
395
|
# canvas.transform(a, b, c, d, e, f) => canvas
|
|
364
396
|
# canvas.transform(a, b, c, d, e, f) { block } => canvas
|
|
365
397
|
#
|
|
366
|
-
# Transforms the
|
|
398
|
+
# Transforms the coordinate system by applying the given matrix to the current transformation
|
|
367
399
|
# matrix and returns self.
|
|
368
400
|
#
|
|
369
401
|
# If invoked with a block, the transformation is only active during the block by saving and
|
|
@@ -375,16 +407,16 @@ module HexaPDF
|
|
|
375
407
|
# c d 0
|
|
376
408
|
# e f 1
|
|
377
409
|
#
|
|
378
|
-
#
|
|
410
|
+
# Example:
|
|
379
411
|
#
|
|
380
412
|
# #>pdf
|
|
381
413
|
# canvas.transform(1, 0, 0, 1, 100, 100) do # Translate origin to (100, 100)
|
|
382
|
-
# canvas.stroke_color("
|
|
414
|
+
# canvas.stroke_color("hp-blue").
|
|
383
415
|
# line(0, 0, 100, 50).stroke # Actually from (100, 100) to (200, 150)
|
|
384
416
|
# end
|
|
385
417
|
# canvas.line(0, 0, 100, 50).stroke # Really from (0, 0) to (100, 50)
|
|
386
418
|
#
|
|
387
|
-
# See:
|
|
419
|
+
# See: PDF2.0 s8.3, s8.4.4
|
|
388
420
|
def transform(a, b, c, d, e, f)
|
|
389
421
|
raise_unless_at_page_description_level
|
|
390
422
|
save_graphics_state if block_given?
|
|
@@ -400,30 +432,31 @@ module HexaPDF
|
|
|
400
432
|
# canvas.rotate(angle, origin: nil) => canvas
|
|
401
433
|
# canvas.rotate(angle, origin: nil) { block } => canvas
|
|
402
434
|
#
|
|
403
|
-
# Rotates the
|
|
404
|
-
#
|
|
435
|
+
# Rotates the coordinate system +angle+ degrees around the origin or around the given point
|
|
436
|
+
# and returns +self+.
|
|
405
437
|
#
|
|
406
|
-
# If invoked with a block, the rotation of the
|
|
407
|
-
# saving and restoring the graphics state.
|
|
438
|
+
# If invoked with a block, the rotation of the coordinate system is only active during the
|
|
439
|
+
# block by saving and restoring the graphics state.
|
|
408
440
|
#
|
|
409
441
|
# Note that the origin of the coordinate system itself doesn't change even if the +origin+
|
|
410
442
|
# argument is given!
|
|
411
443
|
#
|
|
412
444
|
# origin::
|
|
413
|
-
# The point around which the
|
|
445
|
+
# The point around which the coordinate system should be rotated.
|
|
414
446
|
#
|
|
415
447
|
# Examples:
|
|
416
448
|
#
|
|
417
449
|
# #>pdf-center
|
|
418
|
-
# canvas.stroke_color("
|
|
419
|
-
# rectangle(0, 0, 60, 40).stroke
|
|
450
|
+
# canvas.stroke_color("hp-gray-light").
|
|
451
|
+
# rectangle(0, 0, 60, 40).stroke # The rectangle that gets rotated
|
|
452
|
+
#
|
|
420
453
|
# canvas.rotate(45) do # Positive x-axis pointing to top-right corner
|
|
421
|
-
# canvas.stroke_color("
|
|
454
|
+
# canvas.stroke_color("hp-blue").
|
|
422
455
|
# rectangle(0, 0, 60, 40).stroke
|
|
423
456
|
# end
|
|
424
457
|
#
|
|
425
458
|
# canvas.rotate(-45, origin: [-50, -50]) do # Rotate around (-50,-50)
|
|
426
|
-
# canvas.stroke_color("
|
|
459
|
+
# canvas.stroke_color("hp-orange").
|
|
427
460
|
# rectangle(0, 0, 60, 40).stroke
|
|
428
461
|
# end
|
|
429
462
|
#
|
|
@@ -443,8 +476,8 @@ module HexaPDF
|
|
|
443
476
|
# canvas.scale(sx, sy = sx, origin: nil) => canvas
|
|
444
477
|
# canvas.scale(sx, sy = sx, origin: nil) { block } => canvas
|
|
445
478
|
#
|
|
446
|
-
# Scales the
|
|
447
|
-
# direction and returns self
|
|
479
|
+
# Scales the coordinate system +sx+ units in the horizontal and +sy+ units in the vertical
|
|
480
|
+
# direction and returns +self+. If the optional +origin+ is specified, scaling is done from
|
|
448
481
|
# that point.
|
|
449
482
|
#
|
|
450
483
|
# If invoked with a block, the scaling is only active during the block by saving and
|
|
@@ -454,20 +487,21 @@ module HexaPDF
|
|
|
454
487
|
# argument is given!
|
|
455
488
|
#
|
|
456
489
|
# origin::
|
|
457
|
-
# The point from which the
|
|
490
|
+
# The point from which the coordinate system should be scaled.
|
|
458
491
|
#
|
|
459
492
|
# Examples:
|
|
460
493
|
#
|
|
461
494
|
# #>pdf-center
|
|
462
|
-
# canvas.stroke_color("
|
|
463
|
-
# rectangle(10, 10, 10, 10).stroke
|
|
495
|
+
# canvas.stroke_color("hp-gray-light").
|
|
496
|
+
# rectangle(10, 10, 10, 10).stroke # The rectangle that gets scaled
|
|
497
|
+
#
|
|
464
498
|
# canvas.scale(4, 2) do # Scale from origin
|
|
465
|
-
# canvas.stroke_color("blue").
|
|
499
|
+
# canvas.stroke_color("hp-blue").
|
|
466
500
|
# rectangle(10, 10, 10, 10).stroke # Actually (40, 20) to (80, 40)
|
|
467
501
|
# end
|
|
468
502
|
#
|
|
469
503
|
# canvas.scale(-2, 4, origin: [10, 10]) do # Scale from (10, 10)
|
|
470
|
-
# canvas.stroke_color("
|
|
504
|
+
# canvas.stroke_color("hp-orange").
|
|
471
505
|
# rectangle(10, 10, 10, 10).stroke # Actually (10, 10) to (-10, 40)
|
|
472
506
|
# end
|
|
473
507
|
#
|
|
@@ -484,18 +518,19 @@ module HexaPDF
|
|
|
484
518
|
# canvas.translate(x, y) => canvas
|
|
485
519
|
# canvas.translate(x, y) { block } => canvas
|
|
486
520
|
#
|
|
487
|
-
# Translates the
|
|
488
|
-
# and returns self
|
|
521
|
+
# Translates the coordinate system coordinate system origin to the given +x+ and +y+
|
|
522
|
+
# coordinates and returns +self+.
|
|
489
523
|
#
|
|
490
|
-
# If invoked with a block, the translation of the
|
|
491
|
-
# by saving and restoring the graphics state.
|
|
524
|
+
# If invoked with a block, the translation of the coordinate system is only active during the
|
|
525
|
+
# block by saving and restoring the graphics state.
|
|
492
526
|
#
|
|
493
527
|
# Examples:
|
|
494
528
|
#
|
|
495
529
|
# #>pdf-center
|
|
496
|
-
# canvas.
|
|
530
|
+
# canvas.stroke_color("hp-gray-light").
|
|
531
|
+
# rectangle(0, 0, 40, 20).stroke # Rectangle from (0, 0) to (40, 20)
|
|
497
532
|
# canvas.translate(50, 50) do # Origin is now at (50, 50)
|
|
498
|
-
# canvas.stroke_color("
|
|
533
|
+
# canvas.stroke_color("hp-blue").
|
|
499
534
|
# rectangle(0, 0, 40, 20).stroke # Actually (50, 50) to (90, 70)
|
|
500
535
|
# end
|
|
501
536
|
#
|
|
@@ -508,7 +543,7 @@ module HexaPDF
|
|
|
508
543
|
# canvas.skew(a, b, origin: nil) => canvas
|
|
509
544
|
# canvas.skew(a, b, origin: nil) { block } => canvas
|
|
510
545
|
#
|
|
511
|
-
# Skews the the x-axis by +a+ degrees and the y-axis by +b+ degress and returns self
|
|
546
|
+
# Skews the the x-axis by +a+ degrees and the y-axis by +b+ degress and returns +self+. If the
|
|
512
547
|
# optional +origin+ is specified, skewing is done from that point.
|
|
513
548
|
#
|
|
514
549
|
# If invoked with a block, the skewing is only active during the block by saving and
|
|
@@ -522,15 +557,16 @@ module HexaPDF
|
|
|
522
557
|
# Examples:
|
|
523
558
|
#
|
|
524
559
|
# #>pdf-center
|
|
525
|
-
# canvas.stroke_color("
|
|
526
|
-
# rectangle(10, 10, 40, 20).stroke
|
|
560
|
+
# canvas.stroke_color("hp-gray-light").
|
|
561
|
+
# rectangle(10, 10, 40, 20).stroke # The rectangle that gets skewed
|
|
562
|
+
#
|
|
527
563
|
# canvas.skew(0, 30) do # Point (10, 10) is now actually (15, 10)
|
|
528
|
-
# canvas.stroke_color("blue").
|
|
564
|
+
# canvas.stroke_color("hp-blue").
|
|
529
565
|
# rectangle(10, 10, 40, 20).stroke # Now a parallelogram
|
|
530
566
|
# end
|
|
531
567
|
#
|
|
532
568
|
# canvas.skew(30, 30, origin: [-50, 50]) do # Skew from (-50, 50)
|
|
533
|
-
# canvas.stroke_color("
|
|
569
|
+
# canvas.stroke_color("hp-orange").
|
|
534
570
|
# rectangle(-50, 50, 20, 20).stroke
|
|
535
571
|
# end
|
|
536
572
|
#
|
|
@@ -553,9 +589,15 @@ module HexaPDF
|
|
|
553
589
|
#
|
|
554
590
|
# The line width determines the thickness of a stroked path.
|
|
555
591
|
#
|
|
556
|
-
#
|
|
557
|
-
#
|
|
558
|
-
#
|
|
592
|
+
# Note that half the line width lies on either side of the path. For example, if a path from
|
|
593
|
+
# (0, 0) to (0, 100) is drawn with a line width of 20, the stroked path is actually 20 units
|
|
594
|
+
# wide, from -10 to 10. And if a rectangle is drawn stroked, but not filled, from (20, 20)
|
|
595
|
+
# with a width and height of 20 and a line width of 10, the "inside" of the rectangle would
|
|
596
|
+
# only be from (25, 25) to (35, 35). Also see the examples below.
|
|
597
|
+
#
|
|
598
|
+
# Returns the current line width (see GraphicsState#line_width) when no argument is given.
|
|
599
|
+
# Otherwise sets the line width to the given +width+ and returns +self+. The setter version
|
|
600
|
+
# can also be called in the line_width= form.
|
|
559
601
|
#
|
|
560
602
|
# If the +width+ and a block are provided, the changed line width is only active during the
|
|
561
603
|
# block by saving and restoring the graphics state.
|
|
@@ -564,19 +606,22 @@ module HexaPDF
|
|
|
564
606
|
#
|
|
565
607
|
# #>pdf
|
|
566
608
|
# canvas.line_width(10).
|
|
567
|
-
# line(10,
|
|
609
|
+
# line(10, 100, 10, 190).stroke
|
|
568
610
|
# canvas.line_width # => 10
|
|
569
611
|
# canvas.line_width = 5 # => 5
|
|
570
|
-
# canvas.line(60,
|
|
612
|
+
# canvas.line(60, 100, 60, 190).stroke
|
|
571
613
|
#
|
|
572
614
|
# canvas.line_width(10) do
|
|
573
615
|
# canvas.line_width # => 10
|
|
574
|
-
# canvas.line(110,
|
|
616
|
+
# canvas.line(110, 100, 110, 190).stroke
|
|
575
617
|
# end
|
|
576
618
|
# canvas.line_width # => 5
|
|
577
|
-
# canvas.line(160,
|
|
619
|
+
# canvas.line(160, 100, 160, 190).stroke
|
|
578
620
|
#
|
|
579
|
-
#
|
|
621
|
+
# canvas.line_width(10).rectangle(20, 20, 20, 20).stroke # The rectangle
|
|
622
|
+
# canvas.fill_color("hp-blue").rectangle(25, 25, 10, 10).fill # The inside
|
|
623
|
+
#
|
|
624
|
+
# See: PDF2.0 s8.4.3.2
|
|
580
625
|
def line_width(width = nil, &block)
|
|
581
626
|
gs_getter_setter(:line_width, :w, width, &block)
|
|
582
627
|
end
|
|
@@ -587,7 +632,7 @@ module HexaPDF
|
|
|
587
632
|
# canvas.line_cap_style(style) => canvas
|
|
588
633
|
# canvas.line_cap_style(style) { block } => canvas
|
|
589
634
|
#
|
|
590
|
-
# The line cap style specifies how the ends of stroked open paths should look like.
|
|
635
|
+
# The line cap style specifies how the ends of stroked, open paths should look like.
|
|
591
636
|
#
|
|
592
637
|
# The +style+ parameter can be one of (also see LineCapStyle):
|
|
593
638
|
#
|
|
@@ -598,11 +643,11 @@ module HexaPDF
|
|
|
598
643
|
# :projecting_square or 2::
|
|
599
644
|
# The stroke continues half the line width beyond the endpoint of a path.
|
|
600
645
|
#
|
|
601
|
-
# Note that the return value is always a normalized line cap style.
|
|
646
|
+
# Note that the return value is always a normalized line cap style (i.e. a NamedValue).
|
|
602
647
|
#
|
|
603
|
-
# Returns the current line cap style (see
|
|
604
|
-
#
|
|
605
|
-
#
|
|
648
|
+
# Returns the current line cap style (see GraphicsState#line_cap_style) when no argument is
|
|
649
|
+
# given. Otherwise sets the line cap style to the given +style+ and returns +self+. The setter
|
|
650
|
+
# version can also be called in the line_cap_style= form.
|
|
606
651
|
#
|
|
607
652
|
# If the +style+ and a block are provided, the changed line cap style is only active during
|
|
608
653
|
# the block by saving and restoring the graphics state.
|
|
@@ -628,7 +673,7 @@ module HexaPDF
|
|
|
628
673
|
# line(50 + index * 50, 30, 50 + index * 50, 170).stroke
|
|
629
674
|
# end
|
|
630
675
|
#
|
|
631
|
-
# See:
|
|
676
|
+
# See: PDF2.0 s8.4.3.3, Content::LineCapStyle
|
|
632
677
|
def line_cap_style(style = nil, &block)
|
|
633
678
|
gs_getter_setter(:line_cap_style, :J, style && LineCapStyle.normalize(style), &block)
|
|
634
679
|
end
|
|
@@ -651,11 +696,11 @@ module HexaPDF
|
|
|
651
696
|
# The two segments are finished with butt caps and the space between the ends is filled
|
|
652
697
|
# with a triangle.
|
|
653
698
|
#
|
|
654
|
-
# Note that the return value is always a normalized line join style.
|
|
699
|
+
# Note that the return value is always a normalized line join style (i.e. a NamedValue).
|
|
655
700
|
#
|
|
656
|
-
# Returns the current line join style (see
|
|
657
|
-
#
|
|
658
|
-
#
|
|
701
|
+
# Returns the current line join style (see GraphicsState#line_join_style) when no argument is
|
|
702
|
+
# given. Otherwise sets the line join style to the given +style+ and returns +self+. The
|
|
703
|
+
# setter version can also be called in the line_join_style= form.
|
|
659
704
|
#
|
|
660
705
|
# If the +style+ and a block are provided, the changed line join style is only active during
|
|
661
706
|
# the block by saving and restoring the graphics state.
|
|
@@ -681,7 +726,7 @@ module HexaPDF
|
|
|
681
726
|
# polyline(20 + index * 60, 30, 40 + index * 60, 170, 60 + index * 60, 30).stroke
|
|
682
727
|
# end
|
|
683
728
|
#
|
|
684
|
-
# See:
|
|
729
|
+
# See: PDF2.0 s8.4.3.4, Content::LineJoinStyle
|
|
685
730
|
def line_join_style(style = nil, &block)
|
|
686
731
|
gs_getter_setter(:line_join_style, :j, style && LineJoinStyle.normalize(style), &block)
|
|
687
732
|
end
|
|
@@ -696,9 +741,9 @@ module HexaPDF
|
|
|
696
741
|
# mitered line joins (see #line_join_style). When the limit is exceeded, a bevel join is
|
|
697
742
|
# used instead of a miter join.
|
|
698
743
|
#
|
|
699
|
-
# Returns the current miter limit (see
|
|
700
|
-
#
|
|
701
|
-
#
|
|
744
|
+
# Returns the current miter limit (see GraphicsState#miter_limit) when no argument is given.
|
|
745
|
+
# Otherwise sets the miter limit to the given +limit+ and returns +self+. The setter version
|
|
746
|
+
# can also be called in the miter_limit= form.
|
|
702
747
|
#
|
|
703
748
|
# If the +limit+ and a block are provided, the changed miter limit is only active during the
|
|
704
749
|
# block by saving and restoring the graphics state.
|
|
@@ -722,7 +767,7 @@ module HexaPDF
|
|
|
722
767
|
# 60 + index * 80, 30).stroke
|
|
723
768
|
# end
|
|
724
769
|
#
|
|
725
|
-
# See:
|
|
770
|
+
# See: PDF2.0 s8.4.3.5
|
|
726
771
|
def miter_limit(limit = nil, &block)
|
|
727
772
|
gs_getter_setter(:miter_limit, :M, limit, &block)
|
|
728
773
|
end
|
|
@@ -740,7 +785,7 @@ module HexaPDF
|
|
|
740
785
|
#
|
|
741
786
|
# There are multiple ways to set the line dash pattern:
|
|
742
787
|
#
|
|
743
|
-
# * By providing a
|
|
788
|
+
# * By providing a LineDashPattern object
|
|
744
789
|
# * By providing a single Integer/Float that is used for both dashes and gaps
|
|
745
790
|
# * By providing an array of Integers/Floats that specify the alternating dashes and gaps
|
|
746
791
|
#
|
|
@@ -749,10 +794,10 @@ module HexaPDF
|
|
|
749
794
|
#
|
|
750
795
|
# A solid line can be achieved by using 0 for the length or by using an empty array.
|
|
751
796
|
#
|
|
752
|
-
# Returns the current line dash pattern (
|
|
753
|
-
# argument is given. Otherwise sets the line dash
|
|
754
|
-
# returns self
|
|
755
|
-
# without the second argument!).
|
|
797
|
+
# Returns the current line dash pattern (a LineDashPattern object, see
|
|
798
|
+
# GraphicsState#line_dash_pattern) when no argument is given. Otherwise sets the line dash
|
|
799
|
+
# pattern using the given arguments and returns +self+. The setter version can also be called
|
|
800
|
+
# in the line_dash_pattern= form (but only without the second argument!).
|
|
756
801
|
#
|
|
757
802
|
# If arguments and a block are provided, the changed line dash pattern is only active during
|
|
758
803
|
# the block by saving and restoring the graphics state.
|
|
@@ -778,7 +823,7 @@ module HexaPDF
|
|
|
778
823
|
# stroke
|
|
779
824
|
# end
|
|
780
825
|
#
|
|
781
|
-
# See:
|
|
826
|
+
# See: PDF2.0 s8.4.3.5, LineDashPattern
|
|
782
827
|
def line_dash_pattern(value = nil, phase = 0, &block)
|
|
783
828
|
gs_getter_setter(:line_dash_pattern, :d, value && LineDashPattern.normalize(value, phase),
|
|
784
829
|
&block)
|
|
@@ -799,9 +844,9 @@ module HexaPDF
|
|
|
799
844
|
# * +:Saturation+
|
|
800
845
|
# * +:Perceptual+
|
|
801
846
|
#
|
|
802
|
-
# Returns the current rendering intent (see
|
|
803
|
-
#
|
|
804
|
-
#
|
|
847
|
+
# Returns the current rendering intent (see GraphicsState#rendering_intent) when no argument
|
|
848
|
+
# is given. Otherwise sets the rendering intent using the +intent+ argument and returns
|
|
849
|
+
# +self+. The setter version can also be called in the rendering_intent= form.
|
|
805
850
|
#
|
|
806
851
|
# If the +intent+ and a block are provided, the changed rendering intent is only active
|
|
807
852
|
# during the block by saving and restoring the graphics state.
|
|
@@ -817,7 +862,7 @@ module HexaPDF
|
|
|
817
862
|
# end
|
|
818
863
|
# canvas.rendering_intent # => :Saturation
|
|
819
864
|
#
|
|
820
|
-
# See:
|
|
865
|
+
# See: PDF2.0 s8.6.5.8, RenderingIntent
|
|
821
866
|
def rendering_intent(intent = nil, &bk)
|
|
822
867
|
gs_getter_setter(:rendering_intent, :ri, intent && RenderingIntent.normalize(intent), &bk)
|
|
823
868
|
end
|
|
@@ -837,23 +882,30 @@ module HexaPDF
|
|
|
837
882
|
#
|
|
838
883
|
# There are several ways to define the color that should be used:
|
|
839
884
|
#
|
|
840
|
-
# * A single numeric argument specifies a gray color (see
|
|
841
|
-
#
|
|
842
|
-
# * Three numeric arguments specify an RGB color (see
|
|
885
|
+
# * A single numeric argument specifies a gray color (see ColorSpace::DeviceGray::Color).
|
|
886
|
+
#
|
|
887
|
+
# * Three numeric arguments specify an RGB color (see ColorSpace::DeviceRGB::Color).
|
|
888
|
+
#
|
|
843
889
|
# * A string in the format "RRGGBB" where "RR" is the hexadecimal number for the red, "GG"
|
|
844
890
|
# for the green and "BB" for the blue color value also specifies an RGB color.
|
|
891
|
+
#
|
|
845
892
|
# * As does a string in the format "RGB" where "RR", "GG" and "BB" would be used as the
|
|
846
893
|
# hexadecimal numbers for the red, green and blue color values of an RGB color.
|
|
847
|
-
#
|
|
848
|
-
#
|
|
849
|
-
#
|
|
894
|
+
#
|
|
895
|
+
# * Any other string is treated as a color name. HexaPDF supports CSS Color Module Level 3
|
|
896
|
+
# color names (see https://www.w3.org/TR/css-color-3/#svg-color) as well as HexaPDF design
|
|
897
|
+
# colors.
|
|
898
|
+
#
|
|
899
|
+
# * Four numeric arguments specify a CMYK color (see ColorSpace::DeviceCMYK::Color).
|
|
900
|
+
#
|
|
850
901
|
# * A color object is used directly (normally used for color spaces other than DeviceRGB,
|
|
851
902
|
# DeviceCMYK and DeviceGray).
|
|
903
|
+
#
|
|
852
904
|
# * An array is treated as if its items were specified separately as arguments.
|
|
853
905
|
#
|
|
854
|
-
# Returns the current stroke color (see
|
|
855
|
-
#
|
|
856
|
-
#
|
|
906
|
+
# Returns the current stroke color (see GraphicsState#stroke_color) when no argument is given.
|
|
907
|
+
# Otherwise sets the stroke color using the given arguments and returns +self+. The setter
|
|
908
|
+
# version can also be called in the stroke_color= form.
|
|
857
909
|
#
|
|
858
910
|
# If the arguments and a block are provided, the changed stroke color is only active during
|
|
859
911
|
# the block by saving and restoring the graphics state.
|
|
@@ -896,7 +948,7 @@ module HexaPDF
|
|
|
896
948
|
# canvas.stroke_color # => ColorSpace::DeviceGray.color(0.4)
|
|
897
949
|
# end
|
|
898
950
|
#
|
|
899
|
-
# See:
|
|
951
|
+
# See: PDF2.0 s8.6, ColorSpace
|
|
900
952
|
def stroke_color(*color, &block)
|
|
901
953
|
color_getter_setter(:stroke_color, color, :RG, :G, :K, :CS, :SCN, &block)
|
|
902
954
|
end
|
|
@@ -922,10 +974,10 @@ module HexaPDF
|
|
|
922
974
|
# the fill alpha value applies not just to fill values but to all non-stroking operations
|
|
923
975
|
# (e.g. images, ...).
|
|
924
976
|
#
|
|
925
|
-
# Returns the current fill alpha (see
|
|
926
|
-
#
|
|
977
|
+
# Returns the current fill alpha (see GraphicsState#fill_alpha) and stroke alpha (see
|
|
978
|
+
# GraphicsState#stroke_alpha) values using a hash with the keys +:fill_alpha+ and
|
|
927
979
|
# +:stroke_alpha+ when no argument is given. Otherwise sets the fill and stroke alpha values
|
|
928
|
-
# and returns self
|
|
980
|
+
# and returns +self+. The setter version can also be called in the #opacity= form.
|
|
929
981
|
#
|
|
930
982
|
# If the values are set and a block is provided, the changed alpha values are only active
|
|
931
983
|
# during the block by saving and restoring the graphics state.
|
|
@@ -944,15 +996,15 @@ module HexaPDF
|
|
|
944
996
|
# canvas.opacity # => {fill_alpha: 0.4, stroke_alpha: 0.9}
|
|
945
997
|
#
|
|
946
998
|
# # visual example
|
|
947
|
-
# canvas.opacity(fill_alpha: 1, stroke_alpha: 1)
|
|
948
|
-
#
|
|
949
|
-
#
|
|
999
|
+
# canvas.opacity(fill_alpha: 1, stroke_alpha: 1)
|
|
1000
|
+
# canvas.fill_color("hp-gray-light"). # background rectangle on right side
|
|
1001
|
+
# rectangle(100, 0, 100, 200).fill
|
|
950
1002
|
# canvas.opacity(fill_alpha: 0.5, stroke_alpha: 0.8). # foreground rectangle, with a thick
|
|
951
1003
|
# line_width(20). # stroke that also overlays the
|
|
952
|
-
# fill_color("
|
|
1004
|
+
# fill_color("hp-blue").stroke_color("hp-blue"). # inside of the rectangle, creating
|
|
953
1005
|
# rectangle(20, 20, 160, 160).fill_stroke # multiple shadings due to opacity
|
|
954
1006
|
#
|
|
955
|
-
# See:
|
|
1007
|
+
# See: PDF2.0 s11.6.4.4
|
|
956
1008
|
def opacity(fill_alpha: nil, stroke_alpha: nil)
|
|
957
1009
|
if !fill_alpha.nil? || !stroke_alpha.nil?
|
|
958
1010
|
raise_unless_at_page_description_level_or_in_text
|
|
@@ -981,14 +1033,14 @@ module HexaPDF
|
|
|
981
1033
|
# canvas.move_to(x, y) => canvas
|
|
982
1034
|
#
|
|
983
1035
|
# Begins a new subpath (and possibly a new path) by moving the current point to the given
|
|
984
|
-
# point
|
|
1036
|
+
# point and returns +self+.
|
|
985
1037
|
#
|
|
986
1038
|
# Examples:
|
|
987
1039
|
#
|
|
988
1040
|
# canvas.move_to(10, 50)
|
|
989
1041
|
# canvas.current_point # => [10, 50]
|
|
990
1042
|
#
|
|
991
|
-
# See:
|
|
1043
|
+
# See: PDF2.0 s8.5.2.1, #line_to, #curve_to, #rectangle
|
|
992
1044
|
def move_to(x, y)
|
|
993
1045
|
raise_unless_at_page_description_level_or_in_path
|
|
994
1046
|
invoke2(:m, x, y)
|
|
@@ -1001,17 +1053,20 @@ module HexaPDF
|
|
|
1001
1053
|
# canvas.line_to(x, y) => canvas
|
|
1002
1054
|
#
|
|
1003
1055
|
# Appends a straight line segment from the current point to the given point (which becomes the
|
|
1004
|
-
# new current point) to the current subpath
|
|
1056
|
+
# new current point) to the current subpath and returns +self+.
|
|
1057
|
+
#
|
|
1058
|
+
# If there is no current path when the method is invoked, an error is raised since a valid
|
|
1059
|
+
# current point (#current_point) is needed.
|
|
1005
1060
|
#
|
|
1006
1061
|
# Examples:
|
|
1007
1062
|
#
|
|
1008
1063
|
# #>pdf-center
|
|
1009
|
-
# canvas.move_to(10, 50)
|
|
1010
|
-
#
|
|
1011
|
-
# canvas.current_point
|
|
1064
|
+
# canvas.move_to(10, 50)
|
|
1065
|
+
# canvas.line_to(80, 80)
|
|
1066
|
+
# canvas.current_point # => [80, 80]
|
|
1012
1067
|
# canvas.stroke
|
|
1013
1068
|
#
|
|
1014
|
-
# See:
|
|
1069
|
+
# See: PDF2.0 s8.5.2.1, #move_to, #curve_to, #rectangle
|
|
1015
1070
|
def line_to(x, y)
|
|
1016
1071
|
raise_unless_in_path
|
|
1017
1072
|
invoke2(:l, x, y)
|
|
@@ -1025,8 +1080,11 @@ module HexaPDF
|
|
|
1025
1080
|
# canvas.curve_to(x, y, p1:) => canvas
|
|
1026
1081
|
# canvas.curve_to(x, y, p2:) => canvas
|
|
1027
1082
|
#
|
|
1028
|
-
# Appends a cubic Bezier curve to the current subpath starting from the current point
|
|
1029
|
-
# point becomes the new current point.
|
|
1083
|
+
# Appends a cubic Bezier curve to the current subpath starting from the current point and
|
|
1084
|
+
# returns +self+. The end point becomes the new current point.
|
|
1085
|
+
#
|
|
1086
|
+
# If there is no current path when the method is invoked, an error is raised since a valid
|
|
1087
|
+
# current point (#current_point) is needed.
|
|
1030
1088
|
#
|
|
1031
1089
|
# A Bezier curve consists of the start point, the end point and the two control points +p1+
|
|
1032
1090
|
# and +p2+. The start point is always the current point and the end point is specified as the
|
|
@@ -1047,7 +1105,7 @@ module HexaPDF
|
|
|
1047
1105
|
# canvas.current_point # => [-30, 60]
|
|
1048
1106
|
# canvas.stroke
|
|
1049
1107
|
#
|
|
1050
|
-
# See:
|
|
1108
|
+
# See: PDF2.0 s8.5.2.2, #move_to, #line_to, #rectangle
|
|
1051
1109
|
def curve_to(x, y, p1: nil, p2: nil)
|
|
1052
1110
|
raise_unless_in_path
|
|
1053
1111
|
if p1 && p2
|
|
@@ -1069,10 +1127,13 @@ module HexaPDF
|
|
|
1069
1127
|
#
|
|
1070
1128
|
# Appends a rectangle to the current path as a complete subpath (drawn in counterclockwise
|
|
1071
1129
|
# direction), with the bottom left corner specified by +x+ and +y+ and the given +width+ and
|
|
1072
|
-
# +height+.
|
|
1130
|
+
# +height+. Returns +self+.
|
|
1073
1131
|
#
|
|
1074
1132
|
# If +radius+ is greater than 0, the corners are rounded with the given radius.
|
|
1075
1133
|
#
|
|
1134
|
+
# Note that the rectangle degrades to a line if either width or height is zero and to nothing
|
|
1135
|
+
# if both are zero.
|
|
1136
|
+
#
|
|
1076
1137
|
# If there is no current path when the method is invoked, a new path is automatically begun.
|
|
1077
1138
|
#
|
|
1078
1139
|
# The current point is set to the bottom left corner if +radius+ is zero, otherwise it is set
|
|
@@ -1083,10 +1144,10 @@ module HexaPDF
|
|
|
1083
1144
|
# #>pdf
|
|
1084
1145
|
# canvas.rectangle(10, 110, 80, 50).stroke
|
|
1085
1146
|
# canvas.rectangle(110, 110, 80, 50, radius: 10).stroke
|
|
1086
|
-
# canvas.rectangle(10,
|
|
1087
|
-
# canvas.rectangle(110,
|
|
1147
|
+
# canvas.rectangle(10, 90, 80, 0).stroke # Degraded: Just a line
|
|
1148
|
+
# canvas.rectangle(110, 90, 0, 0).stroke # Degraded: Draws nothing
|
|
1088
1149
|
#
|
|
1089
|
-
# See:
|
|
1150
|
+
# See: PDF2.0 s8.5.2.1, #move_to, #line_to, #curve_to
|
|
1090
1151
|
def rectangle(x, y, width, height, radius: 0)
|
|
1091
1152
|
raise_unless_at_page_description_level_or_in_path
|
|
1092
1153
|
if radius == 0
|
|
@@ -1103,7 +1164,10 @@ module HexaPDF
|
|
|
1103
1164
|
# canvas.close_subpath => canvas
|
|
1104
1165
|
#
|
|
1105
1166
|
# Closes the current subpath by appending a straight line from the current point to the
|
|
1106
|
-
# start point of the subpath which also becomes the new current point.
|
|
1167
|
+
# start point of the subpath which also becomes the new current point. Returns +self+.
|
|
1168
|
+
#
|
|
1169
|
+
# If there is no current path when the method is invoked, an error is raised since a valid
|
|
1170
|
+
# current point (#current_point) is needed.
|
|
1107
1171
|
#
|
|
1108
1172
|
# Examples:
|
|
1109
1173
|
#
|
|
@@ -1114,7 +1178,7 @@ module HexaPDF
|
|
|
1114
1178
|
# close_subpath. # Draws the line from (60, 60) to (10, 10)
|
|
1115
1179
|
# stroke
|
|
1116
1180
|
#
|
|
1117
|
-
# See:
|
|
1181
|
+
# See: PDF2.0 s8.5.2.1
|
|
1118
1182
|
def close_subpath
|
|
1119
1183
|
raise_unless_in_path
|
|
1120
1184
|
invoke0(:h)
|
|
@@ -1126,13 +1190,16 @@ module HexaPDF
|
|
|
1126
1190
|
# canvas.line(x0, y0, x1, y1) => canvas
|
|
1127
1191
|
#
|
|
1128
1192
|
# Moves the current point to (x0, y0) and appends a line to (x1, y1) to the current path.
|
|
1193
|
+
# Returns +self+.
|
|
1129
1194
|
#
|
|
1130
|
-
#
|
|
1195
|
+
# If there is no current path when the method is invoked, a new path is automatically begun.
|
|
1131
1196
|
#
|
|
1132
1197
|
# Examples:
|
|
1133
1198
|
#
|
|
1134
1199
|
# #>pdf
|
|
1135
1200
|
# canvas.line(10, 10, 100, 100).stroke
|
|
1201
|
+
#
|
|
1202
|
+
# See: #move_to, #line_to
|
|
1136
1203
|
def line(x0, y0, x1, y1)
|
|
1137
1204
|
move_to(x0, y0)
|
|
1138
1205
|
line_to(x1, y1)
|
|
@@ -1143,12 +1210,16 @@ module HexaPDF
|
|
|
1143
1210
|
#
|
|
1144
1211
|
# Moves the current point to (x0, y0) and appends line segments between all given
|
|
1145
1212
|
# consecutive points, i.e. between (x0, y0) and (x1, y1), between (x1, y1) and (x2, y2) and
|
|
1146
|
-
# so on. The last point becomes the new current point.
|
|
1213
|
+
# so on. The last point becomes the new current point. Returns +self+.
|
|
1214
|
+
#
|
|
1215
|
+
# If there is no current path when the method is invoked, a new path is automatically begun.
|
|
1147
1216
|
#
|
|
1148
1217
|
# Examples:
|
|
1149
1218
|
#
|
|
1150
1219
|
# #>pdf
|
|
1151
1220
|
# canvas.polyline(50, 50, 150, 50, 150, 150, 50, 150, 50, 50).stroke
|
|
1221
|
+
#
|
|
1222
|
+
# See: #move_to, #line_to, #polygon
|
|
1152
1223
|
def polyline(*points)
|
|
1153
1224
|
check_poly_points(points)
|
|
1154
1225
|
move_to(points[0], points[1])
|
|
@@ -1163,8 +1234,8 @@ module HexaPDF
|
|
|
1163
1234
|
# :call-seq:
|
|
1164
1235
|
# canvas.polygon(x0, y0, x1, y1, x2, y2, ..., radius: 0) => canvas
|
|
1165
1236
|
#
|
|
1166
|
-
# Appends a polygon consisting of the given points to the path as a complete subpath
|
|
1167
|
-
# point (x0, y0 + radius) becomes the new current point.
|
|
1237
|
+
# Appends a polygon consisting of the given points to the path as a complete subpath and
|
|
1238
|
+
# returns +self+. The point (x0, y0 + radius) becomes the new current point.
|
|
1168
1239
|
#
|
|
1169
1240
|
# If +radius+ is greater than 0, the corners are rounded with the given radius.
|
|
1170
1241
|
#
|
|
@@ -1174,8 +1245,10 @@ module HexaPDF
|
|
|
1174
1245
|
#
|
|
1175
1246
|
# #>pdf
|
|
1176
1247
|
# canvas.polygon(10, 10, 90, 10, 70, 90, 20, 100).stroke
|
|
1177
|
-
# canvas.stroke_color("
|
|
1248
|
+
# canvas.stroke_color("hp-blue").
|
|
1178
1249
|
# polygon(130, 130, 150, 100, 170, 150, 130, 190, radius: 10).stroke
|
|
1250
|
+
#
|
|
1251
|
+
# See: #polyline
|
|
1179
1252
|
def polygon(*points, radius: 0)
|
|
1180
1253
|
if radius == 0
|
|
1181
1254
|
polyline(*points)
|
|
@@ -1195,16 +1268,19 @@ module HexaPDF
|
|
|
1195
1268
|
#
|
|
1196
1269
|
# Appends a circle with center (cx, cy) and the given radius (in degrees) to the path as a
|
|
1197
1270
|
# complete subpath (drawn in counterclockwise direction). The point (center_x + radius,
|
|
1198
|
-
# center_y) becomes the new current point.
|
|
1271
|
+
# center_y) becomes the new current point. Returns +self+.
|
|
1199
1272
|
#
|
|
1200
1273
|
# If there is no current path when the method is invoked, a new path is automatically begun.
|
|
1201
1274
|
#
|
|
1202
1275
|
# Examples:
|
|
1203
1276
|
#
|
|
1204
1277
|
# #>pdf
|
|
1205
|
-
# canvas.circle(100, 100, 30)
|
|
1278
|
+
# canvas.circle(100, 100, 30)
|
|
1279
|
+
# cp = canvas.current_point
|
|
1280
|
+
# canvas.stroke
|
|
1281
|
+
# canvas.stroke_color("hp-orange").line(*cp, 180, 100).stroke
|
|
1206
1282
|
#
|
|
1207
|
-
# See: #arc (for approximation accuracy)
|
|
1283
|
+
# See: #arc (for approximation accuracy), #ellipse
|
|
1208
1284
|
def circle(cx, cy, radius)
|
|
1209
1285
|
arc(cx, cy, a: radius)
|
|
1210
1286
|
close_subpath
|
|
@@ -1215,7 +1291,8 @@ module HexaPDF
|
|
|
1215
1291
|
#
|
|
1216
1292
|
# Appends an ellipse with center (cx, cy), semi-major axis +a+, semi-minor axis +b+ and an
|
|
1217
1293
|
# inclination from the x-axis of +inclination+ degrees to the path as a complete subpath. The
|
|
1218
|
-
# outer-most point on the semi-major axis becomes the new current point.
|
|
1294
|
+
# outer-most point on the positive semi-major axis becomes the new current point. Returns
|
|
1295
|
+
# self.
|
|
1219
1296
|
#
|
|
1220
1297
|
# If there is no current path when the method is invoked, a new path is automatically begun.
|
|
1221
1298
|
#
|
|
@@ -1225,11 +1302,15 @@ module HexaPDF
|
|
|
1225
1302
|
# # Ellipse aligned to x-axis and y-axis
|
|
1226
1303
|
# canvas.ellipse(50, 50, a: 20, b: 10).stroke
|
|
1227
1304
|
#
|
|
1228
|
-
# # Inclined ellipse
|
|
1229
|
-
# canvas.stroke_color("
|
|
1230
|
-
# ellipse(150, 150, a: 20, b: 10, inclination: 30)
|
|
1305
|
+
# # Inclined ellipse with line from the end point
|
|
1306
|
+
# canvas.stroke_color("hp-blue").
|
|
1307
|
+
# ellipse(150, 150, a: 20, b: 10, inclination: 30)
|
|
1308
|
+
# cp = canvas.current_point
|
|
1309
|
+
# x, y = 2 * canvas.current_point[0] - 150, 2 * canvas.current_point[1] - 150
|
|
1310
|
+
# canvas.stroke.
|
|
1311
|
+
# stroke_color("hp-orange").line(*cp, x, y).stroke
|
|
1231
1312
|
#
|
|
1232
|
-
# See: #arc (for approximation accuracy)
|
|
1313
|
+
# See: #arc (for approximation accuracy), #circle
|
|
1233
1314
|
def ellipse(cx, cy, a:, b:, inclination: 0)
|
|
1234
1315
|
arc(cx, cy, a: a, b: b, inclination: inclination)
|
|
1235
1316
|
close_subpath
|
|
@@ -1238,8 +1319,8 @@ module HexaPDF
|
|
|
1238
1319
|
# :call-seq:
|
|
1239
1320
|
# canvas.arc(cx, cy, a:, b: a, start_angle: 0, end_angle: 360, clockwise: false, inclination: 0) => canvas
|
|
1240
1321
|
#
|
|
1241
|
-
# Appends an elliptical arc to the path
|
|
1242
|
-
# point.
|
|
1322
|
+
# Appends an elliptical arc to the path and returns +self+. The endpoint of the arc becomes
|
|
1323
|
+
# the new current point.
|
|
1243
1324
|
#
|
|
1244
1325
|
# +cx+::
|
|
1245
1326
|
# x-coordinate of the center point of the arc
|
|
@@ -1271,6 +1352,9 @@ module HexaPDF
|
|
|
1271
1352
|
#
|
|
1272
1353
|
# If there is no current path when the method is invoked, a new path is automatically begun.
|
|
1273
1354
|
#
|
|
1355
|
+
# This arc does *not* start from the current point (#current_point). If this functionality is
|
|
1356
|
+
# needed, use #draw together with GraphicObject::EndpointArc.
|
|
1357
|
+
#
|
|
1274
1358
|
# Since PDF doesn't have operators for drawing elliptical or circular arcs, they have to be
|
|
1275
1359
|
# approximated using Bezier curves (see #curve_to). The accuracy of the approximation can be
|
|
1276
1360
|
# controlled using the configuration option 'graphic_object.arc.max_curves'.
|
|
@@ -1284,19 +1368,19 @@ module HexaPDF
|
|
|
1284
1368
|
# canvas.stroke
|
|
1285
1369
|
#
|
|
1286
1370
|
# # Circular and elliptical arcs from 30 degrees to 160 degrees
|
|
1287
|
-
# canvas.stroke_color("
|
|
1371
|
+
# canvas.stroke_color("hp-blue")
|
|
1288
1372
|
# canvas.arc(50, 100, a: 10, start_angle: 30, end_angle: 160)
|
|
1289
1373
|
# canvas.arc(100, 100, a: 10, b: 5, start_angle: 30, end_angle: 160)
|
|
1290
1374
|
# canvas.stroke
|
|
1291
1375
|
#
|
|
1292
1376
|
# # Arcs from 135 degrees to 30 degrees, the first in counterclockwise direction (i.e. the
|
|
1293
1377
|
# # big arc), the other in clockwise direction (i.e. the small arc)
|
|
1294
|
-
# canvas.stroke_color("
|
|
1378
|
+
# canvas.stroke_color("hp-orange")
|
|
1295
1379
|
# canvas.arc(50, 50, a: 10, start_angle: 135, end_angle: 30)
|
|
1296
1380
|
# canvas.arc(100, 50, a: 10, start_angle: 135, end_angle: 30, clockwise: true)
|
|
1297
1381
|
# canvas.stroke
|
|
1298
1382
|
#
|
|
1299
|
-
# See:
|
|
1383
|
+
# See: #arc, #circle, #ellipse, GraphicObject::Arc, GraphicObject::EndpointArc
|
|
1300
1384
|
def arc(cx, cy, a:, b: a, start_angle: 0, end_angle: 360, clockwise: false, inclination: 0)
|
|
1301
1385
|
arc = GraphicObject::Arc.configure(cx: cx, cy: cy, a: a, b: b,
|
|
1302
1386
|
start_angle: start_angle, end_angle: end_angle,
|
|
@@ -1314,18 +1398,18 @@ module HexaPDF
|
|
|
1314
1398
|
# :call-seq:
|
|
1315
1399
|
# canvas.line_with_rounded_corner(x0 = current_point[0], y0 = current_point[1], x1, y1, x2, y2, in_radius:, out_radius: in_radius)
|
|
1316
1400
|
#
|
|
1317
|
-
# Appends a line with a rounded corner at (x1, y1) from the current point
|
|
1318
|
-
# the rounded corner (i.e. +out_radius+ units from (x1, y1) in the direction
|
|
1319
|
-
# becomes the current point. In degraded cases the corner point (x1, y1) becomes
|
|
1320
|
-
# point.
|
|
1401
|
+
# Appends a line with a rounded corner at (x1, y1) from the current point and returns +self+.
|
|
1402
|
+
# The end point of the rounded corner (i.e. +out_radius+ units from (x1, y1) in the direction
|
|
1403
|
+
# of (x2, y2)) becomes the current point. In degraded cases the corner point (x1, y1) becomes
|
|
1404
|
+
# the current point.
|
|
1321
1405
|
#
|
|
1322
1406
|
# The corner is specified by (x0, y0) which defaults to the #current_point of the path, (x1,
|
|
1323
1407
|
# y1) and (x2, y2) - all of which need to be different points. The +in_radius+ specifies the
|
|
1324
1408
|
# corner radius into the corner and the +out_radius+ the one out of the corner. Degraded
|
|
1325
1409
|
# cases, like with (x0, y0) == (x1, y1), are handled gracefully.
|
|
1326
1410
|
#
|
|
1327
|
-
# There has to be a current path when this method is invoked
|
|
1328
|
-
#
|
|
1411
|
+
# There has to be a current path when this method is invoked, otherwise an error is raised.
|
|
1412
|
+
# For example, the current point could be estabilshed beforehand using #move_to.
|
|
1329
1413
|
#
|
|
1330
1414
|
# Examples:
|
|
1331
1415
|
#
|
|
@@ -1338,10 +1422,15 @@ module HexaPDF
|
|
|
1338
1422
|
# canvas.line_with_rounded_corner(180, 120, 150, 100, in_radius: 0, out_radius: 10)
|
|
1339
1423
|
# canvas.stroke
|
|
1340
1424
|
#
|
|
1341
|
-
# # Special effects when (x0, y0) is not the current point, like when the current
|
|
1342
|
-
# # would be equal to the corner point
|
|
1425
|
+
# # Special effects when (x0, y0) is not the current point, like when the current
|
|
1426
|
+
# # point would be equal to the corner point. Rounded rectangle use this method
|
|
1427
|
+
# # internally, as high-lighted by the blue segment.
|
|
1343
1428
|
# canvas.rectangle(10, 10, 60, 60, radius: 60).stroke
|
|
1344
|
-
# canvas.
|
|
1429
|
+
# canvas.stroke_color("hp-blue").
|
|
1430
|
+
# move_to(70, 10). # Start point at the end of the lower-left rounded corner
|
|
1431
|
+
# line_with_rounded_corner(10, 10, 70, 10, 70, 70, in_radius: 60).stroke
|
|
1432
|
+
# canvas.stroke_color("black").
|
|
1433
|
+
# rectangle(110, 10, 60, 60, radius: 70).stroke
|
|
1345
1434
|
def line_with_rounded_corner(x0 = current_point[0], y0 = current_point[1], x1, y1, x2, y2,
|
|
1346
1435
|
in_radius:, out_radius: in_radius)
|
|
1347
1436
|
if in_radius == 0 || out_radius == 0
|
|
@@ -1367,9 +1456,9 @@ module HexaPDF
|
|
|
1367
1456
|
#
|
|
1368
1457
|
# Returns the named graphic object, configured with the given options.
|
|
1369
1458
|
#
|
|
1370
|
-
# If an object responding to :configure is given, it is used. Otherwise the graphic object
|
|
1371
|
-
#
|
|
1372
|
-
# graphic object is configured with the given options if at least one is given.
|
|
1459
|
+
# If an object responding to :configure is given, it is used. Otherwise the graphic object is
|
|
1460
|
+
# looked up via the given name in the configuration option 'graphic_object.map'. Either way,
|
|
1461
|
+
# the graphic object is then configured with the given options if at least one is given.
|
|
1373
1462
|
#
|
|
1374
1463
|
# Examples:
|
|
1375
1464
|
#
|
|
@@ -1378,7 +1467,7 @@ module HexaPDF
|
|
|
1378
1467
|
# outer_a: 50, outer_b: 40, end_angle: 135)
|
|
1379
1468
|
# canvas.draw(obj).stroke
|
|
1380
1469
|
#
|
|
1381
|
-
# See:
|
|
1470
|
+
# See: #draw, GraphicObject
|
|
1382
1471
|
def graphic_object(obj, **options)
|
|
1383
1472
|
unless obj.respond_to?(:configure)
|
|
1384
1473
|
obj = context.document.config.constantize('graphic_object.map', obj)
|
|
@@ -1404,7 +1493,7 @@ module HexaPDF
|
|
|
1404
1493
|
# :call-seq:
|
|
1405
1494
|
# canvas.stroke => canvas
|
|
1406
1495
|
#
|
|
1407
|
-
# Strokes the path
|
|
1496
|
+
# Strokes the path and returns +self+.
|
|
1408
1497
|
#
|
|
1409
1498
|
# Examples:
|
|
1410
1499
|
#
|
|
@@ -1412,7 +1501,7 @@ module HexaPDF
|
|
|
1412
1501
|
# canvas.polyline(10, 10, 120, 40, 50, 160)
|
|
1413
1502
|
# canvas.stroke
|
|
1414
1503
|
#
|
|
1415
|
-
# See:
|
|
1504
|
+
# See: PDF2.0 s8.5.3.1, s8.5.3.2, #close_stroke, #close_fill_stroke
|
|
1416
1505
|
def stroke
|
|
1417
1506
|
raise_unless_in_path_or_clipping_path
|
|
1418
1507
|
invoke0(:S)
|
|
@@ -1422,7 +1511,7 @@ module HexaPDF
|
|
|
1422
1511
|
# :call-seq:
|
|
1423
1512
|
# canvas.close_stroke => canvas
|
|
1424
1513
|
#
|
|
1425
|
-
# Closes the last subpath and then strokes the path.
|
|
1514
|
+
# Closes the last subpath and then strokes the path. Returns +self+.
|
|
1426
1515
|
#
|
|
1427
1516
|
# Examples:
|
|
1428
1517
|
#
|
|
@@ -1430,7 +1519,7 @@ module HexaPDF
|
|
|
1430
1519
|
# canvas.polyline(10, 10, 120, 40, 50, 160) # No line from the top to the left
|
|
1431
1520
|
# canvas.close_stroke
|
|
1432
1521
|
#
|
|
1433
|
-
# See:
|
|
1522
|
+
# See: PDF2.0 s8.5.3.1, s8.5.3.2, #stroke, #close_fill_stroke
|
|
1434
1523
|
def close_stroke
|
|
1435
1524
|
raise_unless_in_path_or_clipping_path
|
|
1436
1525
|
invoke0(:s)
|
|
@@ -1440,25 +1529,26 @@ module HexaPDF
|
|
|
1440
1529
|
# :call-seq:
|
|
1441
1530
|
# canvas.fill(rule = :nonzero) => canvas
|
|
1442
1531
|
#
|
|
1443
|
-
# Fills the path using the given rule
|
|
1532
|
+
# Fills the path using the given rule and returns +self+.
|
|
1444
1533
|
#
|
|
1445
1534
|
# The argument +rule+ may either be +:nonzero+ to use the nonzero winding number rule or
|
|
1446
1535
|
# +:even_odd+ to use the even-odd rule for determining which regions to fill in. Details on
|
|
1447
|
-
# how these rules work are found in the PDF
|
|
1536
|
+
# how these rules work are found in the PDF 2.0 spec section 8.5.3.3 or via Internet search.
|
|
1448
1537
|
#
|
|
1449
1538
|
# Any open subpaths are implicitly closed before being filled.
|
|
1450
1539
|
#
|
|
1451
1540
|
# Examples:
|
|
1452
1541
|
#
|
|
1453
1542
|
# #>pdf
|
|
1454
|
-
# canvas.
|
|
1455
|
-
#
|
|
1543
|
+
# canvas.fill_color("hp-blue").
|
|
1544
|
+
# polyline(20, 10, 90, 60, 10, 60, 80, 10, 50, 90).
|
|
1545
|
+
# fill
|
|
1456
1546
|
#
|
|
1457
|
-
# canvas.fill_color("
|
|
1458
|
-
#
|
|
1459
|
-
#
|
|
1547
|
+
# canvas.fill_color("hp-orange").
|
|
1548
|
+
# polyline(120, 110, 190, 160, 110, 160, 180, 110, 150, 190).
|
|
1549
|
+
# fill(:even_odd)
|
|
1460
1550
|
#
|
|
1461
|
-
# See:
|
|
1551
|
+
# See: PDF2.0 s8.5.3.1, s8.5.3.3, #fill_stroke, #close_fill_stroke
|
|
1462
1552
|
def fill(rule = :nonzero)
|
|
1463
1553
|
raise_unless_in_path_or_clipping_path
|
|
1464
1554
|
invoke0(rule == :nonzero ? :f : :'f*')
|
|
@@ -1468,26 +1558,27 @@ module HexaPDF
|
|
|
1468
1558
|
# :call-seq:
|
|
1469
1559
|
# canvas.fill_stroke(rule = :nonzero) => canvas
|
|
1470
1560
|
#
|
|
1471
|
-
# Fills and then strokes the path using the given rule.
|
|
1561
|
+
# Fills and then strokes the path using the given rule. Returns +self+.
|
|
1472
1562
|
#
|
|
1473
1563
|
# The argument +rule+ may either be +:nonzero+ to use the nonzero winding number rule or
|
|
1474
1564
|
# +:even_odd+ to use the even-odd rule for determining which regions to fill in. Details on
|
|
1475
|
-
# how these rules work are found in the PDF
|
|
1565
|
+
# how these rules work are found in the PDF 2.0 spec section 8.5.3.3 or via Internet search.
|
|
1476
1566
|
#
|
|
1477
|
-
# Note that any open subpaths are *not* closed
|
|
1567
|
+
# Note that any open subpaths are *not* closed concerning the stroking operation.
|
|
1478
1568
|
#
|
|
1479
1569
|
# Examples:
|
|
1480
1570
|
#
|
|
1481
1571
|
# #>pdf
|
|
1482
|
-
# canvas.stroke_color("
|
|
1483
|
-
# canvas.
|
|
1484
|
-
#
|
|
1572
|
+
# canvas.stroke_color("hp-orange").line_width(3)
|
|
1573
|
+
# canvas.fill_color("hp-blue").
|
|
1574
|
+
# polyline(20, 10, 90, 60, 10, 60, 80, 10, 50, 90).
|
|
1575
|
+
# fill_stroke # Note the missing stroke from the top corner
|
|
1485
1576
|
#
|
|
1486
|
-
# canvas.fill_color("
|
|
1487
|
-
#
|
|
1488
|
-
#
|
|
1577
|
+
# canvas.fill_color("hp-teal").
|
|
1578
|
+
# polyline(120, 110, 190, 160, 110, 160, 180, 110, 150, 190).
|
|
1579
|
+
# fill_stroke(:even_odd) # Note the missing stroke from the top corner
|
|
1489
1580
|
#
|
|
1490
|
-
# See:
|
|
1581
|
+
# See: PDF2.0 s8.5.3.1, s8.5.3.3, #fill, #close_fill_stroke
|
|
1491
1582
|
def fill_stroke(rule = :nonzero)
|
|
1492
1583
|
raise_unless_in_path_or_clipping_path
|
|
1493
1584
|
invoke0(rule == :nonzero ? :B : :'B*')
|
|
@@ -1497,24 +1588,26 @@ module HexaPDF
|
|
|
1497
1588
|
# :call-seq:
|
|
1498
1589
|
# canvas.close_fill_stroke(rule = :nonzero) => canvas
|
|
1499
1590
|
#
|
|
1500
|
-
# Closes the last subpath and then fills and strokes the path using the given rule.
|
|
1591
|
+
# Closes the last subpath and then fills and strokes the path using the given rule. Returns
|
|
1592
|
+
# +self+.
|
|
1501
1593
|
#
|
|
1502
1594
|
# The argument +rule+ may either be +:nonzero+ to use the nonzero winding number rule or
|
|
1503
1595
|
# +:even_odd+ to use the even-odd rule for determining which regions to fill in. Details on
|
|
1504
|
-
# how these rules work are found in the PDF
|
|
1596
|
+
# how these rules work are found in the PDF 2.0 spec section 8.5.3.3 or via Internet search.
|
|
1505
1597
|
#
|
|
1506
1598
|
# Examples:
|
|
1507
1599
|
#
|
|
1508
1600
|
# #>pdf
|
|
1509
|
-
# canvas.stroke_color("
|
|
1510
|
-
# canvas.
|
|
1511
|
-
#
|
|
1601
|
+
# canvas.stroke_color("hp-orange").line_width(3)
|
|
1602
|
+
# canvas.fill_color("hp-blue").
|
|
1603
|
+
# polyline(20, 10, 90, 60, 10, 60, 80, 10, 50, 90).
|
|
1604
|
+
# close_fill_stroke
|
|
1512
1605
|
#
|
|
1513
|
-
# canvas.fill_color("
|
|
1514
|
-
#
|
|
1515
|
-
#
|
|
1606
|
+
# canvas.fill_color("hp-teal").
|
|
1607
|
+
# polyline(120, 110, 190, 160, 110, 160, 180, 110, 150, 190).
|
|
1608
|
+
# close_fill_stroke(:even_odd)
|
|
1516
1609
|
#
|
|
1517
|
-
# See:
|
|
1610
|
+
# See: PDF2.0 s8.5.3, #fill, #fill_stroke
|
|
1518
1611
|
def close_fill_stroke(rule = :nonzero)
|
|
1519
1612
|
raise_unless_in_path_or_clipping_path
|
|
1520
1613
|
invoke0(rule == :nonzero ? :b : :'b*')
|
|
@@ -1524,17 +1617,17 @@ module HexaPDF
|
|
|
1524
1617
|
# :call-seq:
|
|
1525
1618
|
# canvas.end_path => canvas
|
|
1526
1619
|
#
|
|
1527
|
-
# Ends the path without stroking or filling it
|
|
1620
|
+
# Ends the path without stroking or filling it and returns +self+.
|
|
1528
1621
|
#
|
|
1529
|
-
# This method is
|
|
1530
|
-
# clipping.
|
|
1622
|
+
# This method is usually used in conjunction with the clipping path methods to define the
|
|
1623
|
+
# clipping path.
|
|
1531
1624
|
#
|
|
1532
1625
|
# Examples:
|
|
1533
1626
|
#
|
|
1534
1627
|
# canvas.line(10, 10, 100, 100)
|
|
1535
1628
|
# canvas.end_path # Nothing to see here!
|
|
1536
1629
|
#
|
|
1537
|
-
# See:
|
|
1630
|
+
# See: PDF2.0 s8.5.3.1, #clip_path
|
|
1538
1631
|
def end_path
|
|
1539
1632
|
raise_unless_in_path_or_clipping_path
|
|
1540
1633
|
invoke0(:n)
|
|
@@ -1544,11 +1637,11 @@ module HexaPDF
|
|
|
1544
1637
|
# :call-seq:
|
|
1545
1638
|
# canvas.clip_path(rule = :nonzero) => canvas
|
|
1546
1639
|
#
|
|
1547
|
-
# Modifies the clipping path by intersecting it with the current path.
|
|
1640
|
+
# Modifies the clipping path by intersecting it with the current path. Returns +self+.
|
|
1548
1641
|
#
|
|
1549
1642
|
# The argument +rule+ may either be +:nonzero+ to use the nonzero winding number rule or
|
|
1550
1643
|
# +:even_odd+ to use the even-odd rule for determining which regions lie inside the clipping
|
|
1551
|
-
# path. Details on how these rules work are found in the PDF
|
|
1644
|
+
# path. Details on how these rules work are found in the PDF 2.0 spec section 8.5.3.3 or via
|
|
1552
1645
|
# Internet search.
|
|
1553
1646
|
#
|
|
1554
1647
|
# The initial clipping path includes the entire canvas. Once the clipping path is reduced to a
|
|
@@ -1566,7 +1659,7 @@ module HexaPDF
|
|
|
1566
1659
|
# clip_path(:even_odd).end_path
|
|
1567
1660
|
# canvas.rectangle(0, 0, 200, 200).fill # Fills everything inside the clipping path
|
|
1568
1661
|
#
|
|
1569
|
-
# See:
|
|
1662
|
+
# See: PDF2.0 s8.5.4, #end_path
|
|
1570
1663
|
def clip_path(rule = :nonzero)
|
|
1571
1664
|
raise_unless_in_path
|
|
1572
1665
|
invoke0(rule == :nonzero ? :W : :'W*')
|
|
@@ -1583,8 +1676,8 @@ module HexaPDF
|
|
|
1583
1676
|
# position and returns the XObject.
|
|
1584
1677
|
#
|
|
1585
1678
|
# Any image format for which a HexaPDF::ImageLoader object is available and registered with
|
|
1586
|
-
# the configuration option 'image_loader' can be used. PNG
|
|
1587
|
-
# of the box.
|
|
1679
|
+
# the configuration option 'image_loader' can be used. PNG (lossless), JPEG (lossy) and PDF
|
|
1680
|
+
# (vector) images are supported out of the box.
|
|
1588
1681
|
#
|
|
1589
1682
|
# If the filename or the IO specifies a PDF file, the first page of this file is used to
|
|
1590
1683
|
# create a form XObject which is then drawn.
|
|
@@ -1608,18 +1701,18 @@ module HexaPDF
|
|
|
1608
1701
|
# #>pdf
|
|
1609
1702
|
# canvas.xobject(machu_picchu, at: [10, 10], width: 90) # bottom left
|
|
1610
1703
|
#
|
|
1611
|
-
# file = File.new(machu_picchu, 'rb')
|
|
1704
|
+
# file = File.new(machu_picchu, 'rb') # top left
|
|
1612
1705
|
# canvas.xobject(file, at: [10, 110], height: 50)
|
|
1613
1706
|
#
|
|
1614
1707
|
# image = doc.images.add(machu_picchu)
|
|
1615
1708
|
# canvas.xobject(image, at: [110, 10], width: 50, height: 90) # bottom right
|
|
1616
1709
|
#
|
|
1617
1710
|
# form = doc.add({Type: :XObject, Subtype: :Form, BBox: [0, 0, 100, 100]})
|
|
1618
|
-
# form.canvas.line(10, 10, 90, 90).stroke
|
|
1711
|
+
# form.canvas.stroke_color("hp-blue").line(10, 10, 90, 90).stroke
|
|
1619
1712
|
# canvas.line_width = 20
|
|
1620
1713
|
# canvas.xobject(form, at: [100, 100]) # top right
|
|
1621
1714
|
#
|
|
1622
|
-
# See:
|
|
1715
|
+
# See: PDF2.0 s8.8, s.8.10.1, HexaPDF::Type::Image, HexaPDF::Type::Form, HexaPDF::ImageLoader
|
|
1623
1716
|
def xobject(obj, at:, width: nil, height: nil)
|
|
1624
1717
|
unless obj.kind_of?(HexaPDF::Stream)
|
|
1625
1718
|
obj = context.document.images.add(obj)
|
|
@@ -1653,14 +1746,18 @@ module HexaPDF
|
|
|
1653
1746
|
# canvas.character_spacing(amount) => canvas
|
|
1654
1747
|
# canvas.character_spacing(amount) { block } => canvas
|
|
1655
1748
|
#
|
|
1656
|
-
# The character spacing determines how much additional space is added
|
|
1657
|
-
#
|
|
1658
|
-
# between two characters, whereas for vertical writing negative values increase the
|
|
1749
|
+
# The character spacing determines how much additional space is added after each character
|
|
1750
|
+
# (or, more correctly, after each glyph). For horizontal writing positive values increase the
|
|
1751
|
+
# distance between two characters, whereas for vertical writing negative values increase the
|
|
1659
1752
|
# distance.
|
|
1660
1753
|
#
|
|
1661
|
-
#
|
|
1662
|
-
#
|
|
1663
|
-
#
|
|
1754
|
+
# Note that the character spacing is applied to all characters that are rendered. This has the
|
|
1755
|
+
# effect that there is also a space after the last character which might not be wanted in
|
|
1756
|
+
# certain cases (e.g. when justifying text).
|
|
1757
|
+
#
|
|
1758
|
+
# Returns the current character spacing value (see GraphicsState#character_spacing) when no
|
|
1759
|
+
# argument is given. Otherwise sets the character spacing using the +amount+ argument and
|
|
1760
|
+
# returns +self+. The setter version can also be called in the character_spacing= form.
|
|
1664
1761
|
#
|
|
1665
1762
|
# If the +amount+ and a block are provided, the changed character spacing is only active
|
|
1666
1763
|
# during the block by saving and restoring the graphics state.
|
|
@@ -1680,11 +1777,18 @@ module HexaPDF
|
|
|
1680
1777
|
# # visual example
|
|
1681
1778
|
# canvas.font("Helvetica", size: 10)
|
|
1682
1779
|
# canvas.character_spacing = 0 # initial value
|
|
1683
|
-
# canvas.text("This is an example
|
|
1684
|
-
#
|
|
1685
|
-
#
|
|
1686
|
-
#
|
|
1687
|
-
#
|
|
1780
|
+
# canvas.text("This is an example", at: [10, 150])
|
|
1781
|
+
# # show that the text cursor is directly after the last glyph
|
|
1782
|
+
# x, y = canvas.text_cursor
|
|
1783
|
+
# canvas.stroke_color("hp-blue").line(x, y, x, y + 10).stroke
|
|
1784
|
+
#
|
|
1785
|
+
# canvas.character_spacing = 5
|
|
1786
|
+
# canvas.text("This is an example", at: [10, 100])
|
|
1787
|
+
# # visualize the spacing after the last glyph
|
|
1788
|
+
# x, y = canvas.text_cursor
|
|
1789
|
+
# canvas.stroke_color("hp-blue").line(x, y, x, y + 10).stroke
|
|
1790
|
+
#
|
|
1791
|
+
# See: PDF2.0 s9.3.2, #word_spacing, #horizontal_scaling
|
|
1688
1792
|
def character_spacing(amount = nil, &bk)
|
|
1689
1793
|
gs_getter_setter(:character_spacing, :Tc, amount, &bk)
|
|
1690
1794
|
end
|
|
@@ -1703,9 +1807,9 @@ module HexaPDF
|
|
|
1703
1807
|
# *Important*: In HexaPDF only the standard 14 PDF Type1 fonts support this property! When
|
|
1704
1808
|
# using any other font, for example a TrueType font, this property has no effect.
|
|
1705
1809
|
#
|
|
1706
|
-
# Returns the current word spacing value (see
|
|
1707
|
-
#
|
|
1708
|
-
#
|
|
1810
|
+
# Returns the current word spacing value (see GraphicsState#word_spacing) when no argument is
|
|
1811
|
+
# given. Otherwise sets the word spacing using the +amount+ argument and returns +self+. The
|
|
1812
|
+
# setter version can also be called in the word_spacing= form.
|
|
1709
1813
|
#
|
|
1710
1814
|
# If the +amount+ and a block are provided, the changed word spacing is only active during
|
|
1711
1815
|
# the block by saving and restoring the graphics state.
|
|
@@ -1729,7 +1833,7 @@ module HexaPDF
|
|
|
1729
1833
|
# canvas.word_spacing = 10
|
|
1730
1834
|
# canvas.text("This is an example text.", at: [10, 100])
|
|
1731
1835
|
#
|
|
1732
|
-
# See:
|
|
1836
|
+
# See: PDF2.0 s9.3.3, #character_spacing, #horizontal_scaling
|
|
1733
1837
|
def word_spacing(amount = nil, &bk)
|
|
1734
1838
|
gs_getter_setter(:word_spacing, :Tw, amount, &bk)
|
|
1735
1839
|
end
|
|
@@ -1744,10 +1848,9 @@ module HexaPDF
|
|
|
1744
1848
|
# compressing them in the horizontal direction. The value is specified as percent of the
|
|
1745
1849
|
# normal width, so 100 means no scaling.
|
|
1746
1850
|
#
|
|
1747
|
-
# Returns the current horizontal scaling value (see
|
|
1748
|
-
#
|
|
1749
|
-
#
|
|
1750
|
-
# form.
|
|
1851
|
+
# Returns the current horizontal scaling value (see GraphicsState#horizontal_scaling) when no
|
|
1852
|
+
# argument is given. Otherwise sets the horizontal scaling using the +percent+ argument and
|
|
1853
|
+
# returns +self+. The setter version can also be called in the horizontal_scaling= form.
|
|
1751
1854
|
#
|
|
1752
1855
|
# If the +percent+ and a block are provided, the changed horizontal scaling is only active
|
|
1753
1856
|
# during the block by saving and restoring the graphics state.
|
|
@@ -1771,7 +1874,7 @@ module HexaPDF
|
|
|
1771
1874
|
# canvas.horizontal_scaling = 50
|
|
1772
1875
|
# canvas.text("This is an example text.", at: [10, 100])
|
|
1773
1876
|
#
|
|
1774
|
-
# See:
|
|
1877
|
+
# See: PDF2.0 s9.3.4, #character_spacing, #word_spacing
|
|
1775
1878
|
def horizontal_scaling(amount = nil, &bk)
|
|
1776
1879
|
gs_getter_setter(:horizontal_scaling, :Tz, amount, &bk)
|
|
1777
1880
|
end
|
|
@@ -1789,8 +1892,8 @@ module HexaPDF
|
|
|
1789
1892
|
# There are other PDF content stream operators that would be effected but those are not used
|
|
1790
1893
|
# by the canvas.
|
|
1791
1894
|
#
|
|
1792
|
-
# Returns the current leading value (see
|
|
1793
|
-
#
|
|
1895
|
+
# Returns the current leading value (see GraphicsState#leading) when no argument is given.
|
|
1896
|
+
# Otherwise sets the leading using the +amount+ argument and returns +self+. The setter
|
|
1794
1897
|
# version can also be called in the leading= form.
|
|
1795
1898
|
#
|
|
1796
1899
|
# If the +amount+ and a block are provided, the changed leading is only active during the
|
|
@@ -1813,7 +1916,7 @@ module HexaPDF
|
|
|
1813
1916
|
# canvas.leading = 15
|
|
1814
1917
|
# canvas.text("This is an example text.\nwith a second\nand thrid line", at: [10, 150])
|
|
1815
1918
|
#
|
|
1816
|
-
# See:
|
|
1919
|
+
# See: PDF2.0 s9.3.5, #move_text_cursor
|
|
1817
1920
|
def leading(amount = nil, &bk)
|
|
1818
1921
|
gs_getter_setter(:leading, :TL, amount, &bk)
|
|
1819
1922
|
end
|
|
@@ -1824,16 +1927,33 @@ module HexaPDF
|
|
|
1824
1927
|
# canvas.text_rendering_mode(mode) => canvas
|
|
1825
1928
|
# canvas.text_rendering_mode(mode) { block } => canvas
|
|
1826
1929
|
#
|
|
1827
|
-
# The text rendering mode determines if and how glyphs are rendered.
|
|
1828
|
-
#
|
|
1829
|
-
#
|
|
1830
|
-
#
|
|
1831
|
-
#
|
|
1832
|
-
#
|
|
1833
|
-
#
|
|
1834
|
-
#
|
|
1835
|
-
#
|
|
1836
|
-
#
|
|
1930
|
+
# The text rendering mode determines if and how glyphs are rendered.
|
|
1931
|
+
#
|
|
1932
|
+
# The +mode+ parameter can be one of the following (also see TextRenderingMode):
|
|
1933
|
+
#
|
|
1934
|
+
# :fill or 0::
|
|
1935
|
+
# The text is filled (default)
|
|
1936
|
+
# :stroke or 1::
|
|
1937
|
+
# The text is stroked.
|
|
1938
|
+
# :fill_stroke or 2::
|
|
1939
|
+
# The test is filled, then stroked.
|
|
1940
|
+
# :invisible or 3::
|
|
1941
|
+
# The text is neither filled nor stroked.
|
|
1942
|
+
# :fill_clip or 4::
|
|
1943
|
+
# The text is filled and added to the clipping path.
|
|
1944
|
+
# :stroke_clip or 5::
|
|
1945
|
+
# The text is stroked and added to the clipping path.
|
|
1946
|
+
# :fill_stroke_clip or 6::
|
|
1947
|
+
# The text is filled, then stroked and added to the clipping path.
|
|
1948
|
+
# :clip or 7::
|
|
1949
|
+
# The text is added to the clipping path.
|
|
1950
|
+
# either be a valid integer or one of the symbols +:fill+, +:stroke+,
|
|
1951
|
+
#
|
|
1952
|
+
# Note that the return value is always a normalized text rendering mode value.
|
|
1953
|
+
#
|
|
1954
|
+
# Returns the current text rendering mode value (see GraphicsState#text_rendering_mode) when
|
|
1955
|
+
# no argument is given. Otherwise sets the text rendering mode using the +mode+ argument and
|
|
1956
|
+
# returns +self+. The setter version can also be called in the text_rendering_mode= form.
|
|
1837
1957
|
#
|
|
1838
1958
|
# If the +mode+ and a block are provided, the changed text rendering mode is only active
|
|
1839
1959
|
# during the block by saving and restoring the graphics state.
|
|
@@ -1858,7 +1978,7 @@ module HexaPDF
|
|
|
1858
1978
|
# canvas.text("#{trm} text.", at: [20, 150 - 30 * index])
|
|
1859
1979
|
# end
|
|
1860
1980
|
#
|
|
1861
|
-
# See:
|
|
1981
|
+
# See: PDF2.0 s9.3.6, GraphicsState::TextRenderingMode
|
|
1862
1982
|
def text_rendering_mode(m = nil, &bk)
|
|
1863
1983
|
gs_getter_setter(:text_rendering_mode, :Tr, m && TextRenderingMode.normalize(m), &bk)
|
|
1864
1984
|
end
|
|
@@ -1872,9 +1992,9 @@ module HexaPDF
|
|
|
1872
1992
|
# The text rise specifies the vertical distance to move the baseline up or down from its
|
|
1873
1993
|
# default location. Positive values move the baseline up, negative values down.
|
|
1874
1994
|
#
|
|
1875
|
-
# Returns the current text rise value (see
|
|
1876
|
-
#
|
|
1877
|
-
#
|
|
1995
|
+
# Returns the current text rise value (see GraphicsState#text_rise) when no argument is given.
|
|
1996
|
+
# Otherwise sets the text rise using the +amount+ argument and returns +self+. The setter
|
|
1997
|
+
# version can also be called in the text_rise= form.
|
|
1878
1998
|
#
|
|
1879
1999
|
# If the +amount+ and a block are provided, the changed text rise is only active during the
|
|
1880
2000
|
# block by saving and restoring the graphics state.
|
|
@@ -1900,7 +2020,7 @@ module HexaPDF
|
|
|
1900
2020
|
# canvas.text_rise = -10
|
|
1901
2021
|
# canvas.text("and also down here")
|
|
1902
2022
|
#
|
|
1903
|
-
# See:
|
|
2023
|
+
# See: PDF2.0 s9.3.7
|
|
1904
2024
|
def text_rise(amount = nil, &bk)
|
|
1905
2025
|
gs_getter_setter(:text_rise, :Ts, amount, &bk)
|
|
1906
2026
|
end
|
|
@@ -1909,7 +2029,7 @@ module HexaPDF
|
|
|
1909
2029
|
# :call-seq:
|
|
1910
2030
|
# canvas.begin_text(force_new: false) -> canvas
|
|
1911
2031
|
#
|
|
1912
|
-
# Begins a new text object
|
|
2032
|
+
# Begins a new text object and returns +self+.
|
|
1913
2033
|
#
|
|
1914
2034
|
# If +force+ is +true+ and the current graphics object is already a text object, it is ended
|
|
1915
2035
|
# and a new text object is begun.
|
|
@@ -1917,7 +2037,7 @@ module HexaPDF
|
|
|
1917
2037
|
# It is not necessary to invoke this method manually in most cases since it is automatically
|
|
1918
2038
|
# called when needed by other methods, i.e. the #text method.
|
|
1919
2039
|
#
|
|
1920
|
-
# See:
|
|
2040
|
+
# See: PDF2.0 s9.4.1, #end_text, #text
|
|
1921
2041
|
def begin_text(force_new: false)
|
|
1922
2042
|
raise_unless_at_page_description_level_or_in_text
|
|
1923
2043
|
end_text if force_new
|
|
@@ -1928,12 +2048,12 @@ module HexaPDF
|
|
|
1928
2048
|
# :call-seq:
|
|
1929
2049
|
# canvas.end_text -> canvas
|
|
1930
2050
|
#
|
|
1931
|
-
# Ends the current text object
|
|
2051
|
+
# Ends the current text object and returns +self+.
|
|
1932
2052
|
#
|
|
1933
2053
|
# It is not necessary to invoke this method manually in most cases since it is automatically
|
|
1934
2054
|
# called when needed by other methods, i.e. when creating a new path.
|
|
1935
2055
|
#
|
|
1936
|
-
# See:
|
|
2056
|
+
# See: PDF2.0 s9.4.1, #begin_text
|
|
1937
2057
|
def end_text
|
|
1938
2058
|
raise_unless_at_page_description_level_or_in_text
|
|
1939
2059
|
invoke0(:ET) if graphics_object == :text
|
|
@@ -1943,7 +2063,12 @@ module HexaPDF
|
|
|
1943
2063
|
# :call-seq:
|
|
1944
2064
|
# canvas.text_matrix(a, b, c, d, e, f) => canvas
|
|
1945
2065
|
#
|
|
1946
|
-
# Sets the text matrix (and the text line matrix) to the given matrix and returns self
|
|
2066
|
+
# Sets the text matrix (and the text line matrix) to the given matrix and returns +self+.
|
|
2067
|
+
#
|
|
2068
|
+
# The text matrix determines where and how the glyphs are rendered. The most common use is to
|
|
2069
|
+
# translate the text space origin since the text drawing operations always use the text space
|
|
2070
|
+
# origin as starting point for drawing the glyphs. This translation operation can more easily
|
|
2071
|
+
# be specified using #move_text_cursor.
|
|
1947
2072
|
#
|
|
1948
2073
|
# The given values are interpreted as a matrix in the following way:
|
|
1949
2074
|
#
|
|
@@ -1965,7 +2090,7 @@ module HexaPDF
|
|
|
1965
2090
|
# canvas.text_matrix(2, 1, 3, 0.5, 50, 50)
|
|
1966
2091
|
# canvas.text("This is some text")
|
|
1967
2092
|
#
|
|
1968
|
-
# See:
|
|
2093
|
+
# See: PDF2.0 s9.4.2, #move_text_cursor, #text_cursor
|
|
1969
2094
|
def text_matrix(a, b, c, d, e, f)
|
|
1970
2095
|
begin_text
|
|
1971
2096
|
invoke(:Tm, a, b, c, d, e, f)
|
|
@@ -1975,7 +2100,7 @@ module HexaPDF
|
|
|
1975
2100
|
# :call-seq:
|
|
1976
2101
|
# canvas.move_text_cursor(offset: nil, absolute: true) -> canvas
|
|
1977
2102
|
#
|
|
1978
|
-
# Moves the text cursor by modifying the text and text line matrices.
|
|
2103
|
+
# Moves the text cursor by modifying the text and text line matrices. Returns +self+.
|
|
1979
2104
|
#
|
|
1980
2105
|
# If +offset+ is not specified, the text cursor is moved to the start of the next text line
|
|
1981
2106
|
# using #leading as vertical offset.
|
|
@@ -2010,7 +2135,7 @@ module HexaPDF
|
|
|
2010
2135
|
# canvas.move_text_cursor
|
|
2011
2136
|
# canvas.text("Text on next line with leading=30")
|
|
2012
2137
|
#
|
|
2013
|
-
# See:
|
|
2138
|
+
# See: PDF2.0 s9.4.2, #leading, #text_cursor, #text, #show_glyphs
|
|
2014
2139
|
def move_text_cursor(offset: nil, absolute: true)
|
|
2015
2140
|
begin_text
|
|
2016
2141
|
if offset
|
|
@@ -2028,7 +2153,8 @@ module HexaPDF
|
|
|
2028
2153
|
# :call-seq:
|
|
2029
2154
|
# canvas.text_cursor -> [x, y]
|
|
2030
2155
|
#
|
|
2031
|
-
# Returns the position of the text cursor, i.e. the origin of
|
|
2156
|
+
# Returns the position of the text cursor, i.e. the origin of text space. This is where the
|
|
2157
|
+
# first glyph of the next drawn text will be placed.
|
|
2032
2158
|
#
|
|
2033
2159
|
# Note that this method can only be called while the current graphic object is a text object
|
|
2034
2160
|
# since the text matrix is otherwise undefined.
|
|
@@ -2038,10 +2164,11 @@ module HexaPDF
|
|
|
2038
2164
|
# #>pdf
|
|
2039
2165
|
# canvas.font("Helvetica", size: 10)
|
|
2040
2166
|
# canvas.text("Some sample text", at: [30, 150])
|
|
2041
|
-
#
|
|
2042
|
-
# canvas.
|
|
2043
|
-
#
|
|
2044
|
-
#
|
|
2167
|
+
# tx, ty = canvas.text_cursor # Cursor is directly after the text
|
|
2168
|
+
# canvas.stroke_color("hp-blue").
|
|
2169
|
+
# circle(tx, ty, 0.5).
|
|
2170
|
+
# circle(tx, ty, 5).stroke
|
|
2171
|
+
# canvas.text("Last cursor: (#{tx.round(2)}, #{ty.round(2)})", at: [30, 100])
|
|
2045
2172
|
#
|
|
2046
2173
|
# See: #move_text_cursor
|
|
2047
2174
|
def text_cursor
|
|
@@ -2055,7 +2182,7 @@ module HexaPDF
|
|
|
2055
2182
|
#
|
|
2056
2183
|
# Specifies the font and optional the font size that should be used when showing text.
|
|
2057
2184
|
#
|
|
2058
|
-
# A valid font size
|
|
2185
|
+
# A valid font size needs to be provided on the first invocation, otherwise an error is raised
|
|
2059
2186
|
# (this is due to how setting a font works with PDFs).
|
|
2060
2187
|
#
|
|
2061
2188
|
# If +size+ is specified, the #font_size method is invoked with it as argument.
|
|
@@ -2065,8 +2192,9 @@ module HexaPDF
|
|
|
2065
2192
|
# specifies the font variant to use, with standard values of :none, :italic, :bold and
|
|
2066
2193
|
# :bold_italic.
|
|
2067
2194
|
#
|
|
2068
|
-
# Returns the current font object when no argument is given
|
|
2069
|
-
# object itself, not the PDF dictionary representing the font
|
|
2195
|
+
# Returns the current font object when no argument is given, otherwise returns +self+. *Note*
|
|
2196
|
+
# that this is the font object itself, not the PDF dictionary representing the font that is
|
|
2197
|
+
# stored in the resources.
|
|
2070
2198
|
#
|
|
2071
2199
|
# Examples:
|
|
2072
2200
|
#
|
|
@@ -2080,7 +2208,7 @@ module HexaPDF
|
|
|
2080
2208
|
# canvas.font("Times", variant: :bold_italic, size: 15)
|
|
2081
2209
|
# canvas.text("Times bold+italic at size 15", at: [10, 100])
|
|
2082
2210
|
#
|
|
2083
|
-
# See:
|
|
2211
|
+
# See: PDF2.0 s9.2.2, #font_size, #text
|
|
2084
2212
|
def font(name = nil, size: nil, **options)
|
|
2085
2213
|
if name
|
|
2086
2214
|
@font = (name.respond_to?(:pdf_object) ? name : context.document.fonts.add(name, **options))
|
|
@@ -2099,16 +2227,16 @@ module HexaPDF
|
|
|
2099
2227
|
alias font= font
|
|
2100
2228
|
|
|
2101
2229
|
# :call-seq:
|
|
2102
|
-
# canvas.font_size
|
|
2103
|
-
# canvas.font_size(size => canvas
|
|
2230
|
+
# canvas.font_size => font_size
|
|
2231
|
+
# canvas.font_size(size) => canvas
|
|
2104
2232
|
#
|
|
2105
2233
|
# Specifies the font size.
|
|
2106
2234
|
#
|
|
2107
2235
|
# Note that an error is raised if no font has been set before via #font (this is due to how
|
|
2108
2236
|
# setting font and font size works in PDF).
|
|
2109
2237
|
#
|
|
2110
|
-
# Returns the current font size when no argument is given
|
|
2111
|
-
# be called in the font_size= form.
|
|
2238
|
+
# Returns the current font size when no argument is given, otherwise returns +self+. The
|
|
2239
|
+
# setter version can also be called in the font_size= form.
|
|
2112
2240
|
#
|
|
2113
2241
|
# Examples:
|
|
2114
2242
|
#
|
|
@@ -2124,7 +2252,7 @@ module HexaPDF
|
|
|
2124
2252
|
# canvas.text("Text in size #{size}", at: [15, 180 - index * 20])
|
|
2125
2253
|
# end
|
|
2126
2254
|
#
|
|
2127
|
-
# See:
|
|
2255
|
+
# See: PDF2.0 s9.2.2, #font, #text
|
|
2128
2256
|
def font_size(size = nil)
|
|
2129
2257
|
if size
|
|
2130
2258
|
unless @font
|
|
@@ -2142,7 +2270,7 @@ module HexaPDF
|
|
|
2142
2270
|
# canvas.text(text) -> canvas
|
|
2143
2271
|
# canvas.text(text, at: [x, y]) -> canvas
|
|
2144
2272
|
#
|
|
2145
|
-
# Shows the given text string, either at the current or the provided position.
|
|
2273
|
+
# Shows the given text string, either at the current or the provided position. Returns +self+.
|
|
2146
2274
|
#
|
|
2147
2275
|
# If no position is provided, the text is positioned at the current position of the text
|
|
2148
2276
|
# cursor (see #text_cursor).
|
|
@@ -2152,21 +2280,24 @@ module HexaPDF
|
|
|
2152
2280
|
# equal to the font size will be set..
|
|
2153
2281
|
#
|
|
2154
2282
|
# Note that there are no provisions to make sure that all text is visible! So if the text
|
|
2155
|
-
# string is too long, it
|
|
2283
|
+
# string is too long, it may be outside the cropped page and be cut off.
|
|
2156
2284
|
#
|
|
2157
2285
|
# Examples:
|
|
2158
2286
|
#
|
|
2159
2287
|
# #>pdf
|
|
2160
2288
|
# canvas.font('Times', size: 12)
|
|
2161
|
-
#
|
|
2162
|
-
# canvas.text("
|
|
2289
|
+
# # Sets leading=12 because mulitple lines are drawn
|
|
2290
|
+
# canvas.text("This is a \n multiline text", at: [15, 150])
|
|
2291
|
+
# # Starts right after the last text
|
|
2292
|
+
# canvas.text(". Some more text\nafter the newline.")
|
|
2163
2293
|
#
|
|
2164
|
-
# See: #leading,
|
|
2294
|
+
# See: #leading, #font, #font_size, #show_glyphs,
|
|
2295
|
+
# http://www.unicode.org/reports/tr18/#Line_Boundaries
|
|
2165
2296
|
def text(text, at: nil)
|
|
2166
2297
|
raise_unless_font_set
|
|
2167
2298
|
move_text_cursor(offset: at) if at
|
|
2168
|
-
leading(font_size) if leading == 0
|
|
2169
2299
|
lines = text.split(/\u{D A}|(?!\u{D A})[\u{A}-\u{D}\u{85}\u{2028}\u{2029}]/, -1)
|
|
2300
|
+
leading(font_size) if leading == 0 && lines.length > 1
|
|
2170
2301
|
lines.each_with_index do |str, index|
|
|
2171
2302
|
show_glyphs(@font.decode_utf8(str))
|
|
2172
2303
|
move_text_cursor unless index == lines.length - 1
|
|
@@ -2177,7 +2308,7 @@ module HexaPDF
|
|
|
2177
2308
|
# :call-seq:
|
|
2178
2309
|
# canvas.show_glyphs(glyphs) -> canvas
|
|
2179
2310
|
#
|
|
2180
|
-
# Low-level method for actually showing text on the canvas.
|
|
2311
|
+
# Low-level method for actually showing text on the canvas. Returns +self+.
|
|
2181
2312
|
#
|
|
2182
2313
|
# The argument +glyphs+ needs to be a an array of glyph objects valid for the current font,
|
|
2183
2314
|
# optionally interspersed with numbers for kerning.
|
|
@@ -2200,6 +2331,8 @@ module HexaPDF
|
|
|
2200
2331
|
# canvas.move_text_cursor(offset: [15, 100])
|
|
2201
2332
|
# canvas.show_glyphs(glyphs)
|
|
2202
2333
|
# canvas.text(canvas.text_cursor.map(&:to_i).join(", "), at: [15, 80])
|
|
2334
|
+
#
|
|
2335
|
+
# See: #text, #text_cursor, #text_matrix, #move_text_cursor, #show_glyphs_only
|
|
2203
2336
|
def show_glyphs(glyphs)
|
|
2204
2337
|
return if glyphs.empty?
|
|
2205
2338
|
raise_unless_font_set
|
|
@@ -2269,7 +2402,7 @@ module HexaPDF
|
|
|
2269
2402
|
# :call-seq:
|
|
2270
2403
|
# canvas.marked_content_point(tag, property_list: nil) -> canvas
|
|
2271
2404
|
#
|
|
2272
|
-
# Inserts a marked-content point, optionally associated with a property list.
|
|
2405
|
+
# Inserts a marked-content point, optionally associated with a property list. Returns +self+.
|
|
2273
2406
|
#
|
|
2274
2407
|
# A marked-content point is used to identify a position in the content stream for later use by
|
|
2275
2408
|
# other applications. The symbol +tag+ is used to uniquely identify the role of the
|
|
@@ -2284,7 +2417,7 @@ module HexaPDF
|
|
|
2284
2417
|
# canvas.marked_content_point(:Divider)
|
|
2285
2418
|
# canvas.marked_content_point(:Divider, property_list: {Key: 'value'})
|
|
2286
2419
|
#
|
|
2287
|
-
# See:
|
|
2420
|
+
# See: PDF2.0 s14.6, #marked_content_sequence, #end_marked_content_sequence
|
|
2288
2421
|
def marked_content_point(tag, property_list: nil)
|
|
2289
2422
|
raise_unless_at_page_description_level_or_in_text
|
|
2290
2423
|
if property_list
|
|
@@ -2300,7 +2433,8 @@ module HexaPDF
|
|
|
2300
2433
|
# canvas.marked_content_sequence(tag, property_list: nil) -> canvas
|
|
2301
2434
|
# canvas.marked_content_sequence(tag, property_list: nil) { block } -> canvas
|
|
2302
2435
|
#
|
|
2303
|
-
# Inserts a marked-content sequence, optionally associated with a property list.
|
|
2436
|
+
# Inserts a marked-content sequence, optionally associated with a property list. Returns
|
|
2437
|
+
# +self+.
|
|
2304
2438
|
#
|
|
2305
2439
|
# A marked-content sequence is used to identify a sequence of complete graphics objects in the
|
|
2306
2440
|
# content stream for later use by other applications, e.g. for tagged PDF. The symbol +tag+ is
|
|
@@ -2327,7 +2461,7 @@ module HexaPDF
|
|
|
2327
2461
|
# # Other instructions
|
|
2328
2462
|
# end
|
|
2329
2463
|
#
|
|
2330
|
-
# See:
|
|
2464
|
+
# See: PDF2.0 s14.6, #end_marked_content_sequence, #marked_content_point
|
|
2331
2465
|
def marked_content_sequence(tag, property_list: nil)
|
|
2332
2466
|
raise_unless_at_page_description_level
|
|
2333
2467
|
if property_list
|
|
@@ -2346,22 +2480,66 @@ module HexaPDF
|
|
|
2346
2480
|
# :call-seq:
|
|
2347
2481
|
# canvas.end_marked_content_sequence -> canvas
|
|
2348
2482
|
#
|
|
2349
|
-
# Ends a marked-content sequence
|
|
2483
|
+
# Ends a marked-content sequence and returns +self+.
|
|
2350
2484
|
#
|
|
2351
2485
|
# See #marked_content_sequence for details.
|
|
2352
2486
|
#
|
|
2353
|
-
# See:
|
|
2487
|
+
# See: PDF2.0 s14.6, #marked_content_sequence, #marked_content_point
|
|
2354
2488
|
def end_marked_content_sequence
|
|
2355
2489
|
raise_unless_at_page_description_level
|
|
2356
2490
|
invoke0(:EMC)
|
|
2357
2491
|
self
|
|
2358
2492
|
end
|
|
2359
2493
|
|
|
2360
|
-
#
|
|
2361
|
-
#
|
|
2494
|
+
# :call-seq:
|
|
2495
|
+
# canvas.optional_content(ocg, &block) -> canvas
|
|
2496
|
+
# canvas.optional_content(name, use_existing_ocg: true, &block) -> canvas
|
|
2497
|
+
#
|
|
2498
|
+
# Inserts an optional content sequence. Returns +self+.
|
|
2499
|
+
#
|
|
2500
|
+
# An optional content sequence marks part of the content stream as belonging to the given
|
|
2501
|
+
# optional content group. See HexaPDF::Type::OptionalContentProperties for details.
|
|
2502
|
+
#
|
|
2503
|
+
# If the first argument is already an optional content group dictionary, it is used.
|
|
2504
|
+
# Otherwise, the first argument needs to be the name of the optional content group. In that
|
|
2505
|
+
# case, the +use_existing_ocg+ specifies whether the first found optional content group with
|
|
2506
|
+
# that name should be used or whether a new OCG should always be created.
|
|
2507
|
+
#
|
|
2508
|
+
# If invoked without a block, a corresponding call to #end_optional_content must be done.
|
|
2509
|
+
# Otherwise the optional content sequence automatically ends when the block is finished.
|
|
2510
|
+
#
|
|
2511
|
+
# Examples:
|
|
2512
|
+
#
|
|
2513
|
+
# canvas.optional_content('Hints')
|
|
2514
|
+
# # Other instructions
|
|
2515
|
+
# canvas.end_optional_content
|
|
2516
|
+
#
|
|
2517
|
+
# canvas.optional_content('Hints', use_existing_ocg: false) do
|
|
2518
|
+
# # Other instructions
|
|
2519
|
+
# end
|
|
2520
|
+
#
|
|
2521
|
+
# See: PDF2.0 s8.11, #end_optional_content, HexaPDF::Type::OptionalContentProperties
|
|
2522
|
+
def optional_content(ocg, use_existing_ocg: true, &block)
|
|
2523
|
+
ocg = if ocg.kind_of?(HexaPDF::Dictionary) || !use_existing_ocg
|
|
2524
|
+
context.document.optional_content.add_ocg(ocg)
|
|
2525
|
+
else
|
|
2526
|
+
context.document.optional_content.ocg(ocg, create: true)
|
|
2527
|
+
end
|
|
2528
|
+
marked_content_sequence(:OC, property_list: ocg, &block)
|
|
2529
|
+
end
|
|
2530
|
+
|
|
2531
|
+
# Ends an optional content sequence and returns +self+.
|
|
2532
|
+
#
|
|
2533
|
+
# See #optional_content for details.
|
|
2534
|
+
#
|
|
2535
|
+
# See: PDF2.0 s8.11
|
|
2536
|
+
alias :end_optional_content :end_marked_content_sequence
|
|
2537
|
+
|
|
2538
|
+
# Creates and returns a color object from the given color specification. See #stroke_color for
|
|
2539
|
+
# details on the possible color specifications.
|
|
2362
2540
|
#
|
|
2363
2541
|
# This utility method is meant for use by higher-level methods that need to convert a color
|
|
2364
|
-
# specification into a color object
|
|
2542
|
+
# specification into a color object.
|
|
2365
2543
|
def color_from_specification(spec)
|
|
2366
2544
|
spec = Array(spec)
|
|
2367
2545
|
if spec.length == 1 && spec[0].kind_of?(String)
|