hexapdf 0.32.1 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +76 -1
- data/README.md +9 -0
- data/examples/002-graphics.rb +15 -17
- data/examples/003-arcs.rb +9 -9
- data/examples/009-text_layouter_alignment.rb +1 -1
- data/examples/010-text_layouter_inline_boxes.rb +2 -2
- data/examples/011-text_layouter_line_wrapping.rb +1 -1
- data/examples/012-text_layouter_styling.rb +7 -7
- data/examples/013-text_layouter_shapes.rb +1 -1
- data/examples/014-text_in_polygon.rb +1 -1
- data/examples/015-boxes.rb +8 -7
- data/examples/016-frame_automatic_box_placement.rb +2 -2
- data/examples/017-frame_text_flow.rb +2 -1
- data/examples/018-composer.rb +1 -1
- data/examples/020-column_box.rb +2 -1
- data/examples/025-table_box.rb +46 -0
- data/lib/hexapdf/cli/command.rb +5 -2
- data/lib/hexapdf/cli/form.rb +5 -5
- data/lib/hexapdf/cli/inspect.rb +3 -3
- data/lib/hexapdf/cli.rb +4 -0
- data/lib/hexapdf/composer.rb +104 -52
- data/lib/hexapdf/configuration.rb +44 -39
- data/lib/hexapdf/content/canvas.rb +393 -267
- data/lib/hexapdf/content/color_space.rb +72 -25
- data/lib/hexapdf/content/graphic_object/arc.rb +57 -24
- data/lib/hexapdf/content/graphic_object/endpoint_arc.rb +66 -23
- data/lib/hexapdf/content/graphic_object/geom2d.rb +47 -6
- data/lib/hexapdf/content/graphic_object/solid_arc.rb +58 -36
- data/lib/hexapdf/content/graphic_object.rb +6 -7
- data/lib/hexapdf/content/graphics_state.rb +54 -45
- data/lib/hexapdf/content/operator.rb +52 -54
- data/lib/hexapdf/content/parser.rb +2 -2
- data/lib/hexapdf/content/processor.rb +15 -15
- data/lib/hexapdf/content/transformation_matrix.rb +1 -1
- data/lib/hexapdf/content.rb +5 -0
- data/lib/hexapdf/dictionary.rb +6 -5
- data/lib/hexapdf/dictionary_fields.rb +42 -14
- data/lib/hexapdf/digital_signature/cms_handler.rb +2 -2
- data/lib/hexapdf/digital_signature/handler.rb +1 -1
- data/lib/hexapdf/digital_signature/pkcs1_handler.rb +2 -3
- data/lib/hexapdf/digital_signature/signature.rb +6 -6
- data/lib/hexapdf/digital_signature/signatures.rb +13 -12
- data/lib/hexapdf/digital_signature/signing/default_handler.rb +14 -5
- data/lib/hexapdf/digital_signature/signing/signed_data_creator.rb +2 -4
- data/lib/hexapdf/digital_signature/signing/timestamp_handler.rb +4 -4
- data/lib/hexapdf/digital_signature/signing.rb +4 -0
- data/lib/hexapdf/digital_signature/verification_result.rb +2 -2
- data/lib/hexapdf/digital_signature.rb +7 -2
- data/lib/hexapdf/document/destinations.rb +12 -11
- data/lib/hexapdf/document/files.rb +1 -1
- data/lib/hexapdf/document/fonts.rb +1 -1
- data/lib/hexapdf/document/layout.rb +167 -39
- data/lib/hexapdf/document/pages.rb +3 -2
- data/lib/hexapdf/document.rb +89 -55
- data/lib/hexapdf/encryption/aes.rb +5 -5
- data/lib/hexapdf/encryption/arc4.rb +1 -1
- data/lib/hexapdf/encryption/fast_aes.rb +2 -2
- data/lib/hexapdf/encryption/fast_arc4.rb +1 -1
- data/lib/hexapdf/encryption/identity.rb +1 -1
- data/lib/hexapdf/encryption/ruby_aes.rb +1 -1
- data/lib/hexapdf/encryption/ruby_arc4.rb +1 -1
- data/lib/hexapdf/encryption/security_handler.rb +31 -24
- data/lib/hexapdf/encryption/standard_security_handler.rb +45 -36
- data/lib/hexapdf/encryption.rb +7 -2
- data/lib/hexapdf/error.rb +18 -0
- data/lib/hexapdf/filter/ascii85_decode.rb +1 -1
- data/lib/hexapdf/filter/ascii_hex_decode.rb +1 -1
- data/lib/hexapdf/filter/flate_decode.rb +1 -1
- data/lib/hexapdf/filter/lzw_decode.rb +1 -1
- data/lib/hexapdf/filter/pass_through.rb +1 -1
- data/lib/hexapdf/filter/predictor.rb +1 -1
- data/lib/hexapdf/filter/run_length_decode.rb +1 -1
- data/lib/hexapdf/filter.rb +55 -6
- data/lib/hexapdf/font/cmap/parser.rb +2 -2
- data/lib/hexapdf/font/cmap.rb +1 -1
- data/lib/hexapdf/font/encoding/difference_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_expert_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/mac_roman_encoding.rb +2 -2
- data/lib/hexapdf/font/encoding/standard_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/symbol_encoding.rb +1 -1
- data/lib/hexapdf/font/encoding/win_ansi_encoding.rb +3 -3
- data/lib/hexapdf/font/encoding/zapf_dingbats_encoding.rb +1 -1
- data/lib/hexapdf/font/invalid_glyph.rb +3 -0
- data/lib/hexapdf/font/true_type_wrapper.rb +17 -4
- data/lib/hexapdf/font/type1_wrapper.rb +19 -4
- data/lib/hexapdf/font_loader/from_configuration.rb +5 -2
- data/lib/hexapdf/font_loader/from_file.rb +5 -5
- data/lib/hexapdf/font_loader/standard14.rb +3 -3
- data/lib/hexapdf/font_loader.rb +3 -0
- data/lib/hexapdf/image_loader/jpeg.rb +2 -2
- data/lib/hexapdf/image_loader/pdf.rb +1 -1
- data/lib/hexapdf/image_loader/png.rb +2 -2
- data/lib/hexapdf/image_loader.rb +1 -1
- data/lib/hexapdf/importer.rb +13 -0
- data/lib/hexapdf/layout/box.rb +9 -2
- data/lib/hexapdf/layout/box_fitter.rb +2 -2
- data/lib/hexapdf/layout/column_box.rb +18 -4
- data/lib/hexapdf/layout/frame.rb +30 -12
- data/lib/hexapdf/layout/image_box.rb +5 -0
- data/lib/hexapdf/layout/inline_box.rb +1 -0
- data/lib/hexapdf/layout/list_box.rb +17 -1
- data/lib/hexapdf/layout/page_style.rb +4 -4
- data/lib/hexapdf/layout/style.rb +18 -3
- data/lib/hexapdf/layout/table_box.rb +682 -0
- data/lib/hexapdf/layout/text_box.rb +5 -3
- data/lib/hexapdf/layout/text_fragment.rb +1 -1
- data/lib/hexapdf/layout/text_layouter.rb +12 -4
- data/lib/hexapdf/layout.rb +1 -0
- data/lib/hexapdf/name_tree_node.rb +1 -1
- data/lib/hexapdf/number_tree_node.rb +1 -1
- data/lib/hexapdf/object.rb +18 -7
- data/lib/hexapdf/parser.rb +8 -8
- data/lib/hexapdf/pdf_array.rb +1 -1
- data/lib/hexapdf/rectangle.rb +1 -1
- data/lib/hexapdf/reference.rb +1 -1
- data/lib/hexapdf/revision.rb +1 -1
- data/lib/hexapdf/revisions.rb +3 -3
- data/lib/hexapdf/serializer.rb +15 -15
- data/lib/hexapdf/stream.rb +4 -2
- data/lib/hexapdf/tokenizer.rb +14 -14
- data/lib/hexapdf/type/acro_form/appearance_generator.rb +22 -22
- data/lib/hexapdf/type/acro_form/button_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/choice_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/field.rb +2 -2
- data/lib/hexapdf/type/acro_form/form.rb +1 -1
- data/lib/hexapdf/type/acro_form/signature_field.rb +4 -4
- data/lib/hexapdf/type/acro_form/text_field.rb +1 -1
- data/lib/hexapdf/type/acro_form/variable_text_field.rb +1 -1
- data/lib/hexapdf/type/acro_form.rb +1 -1
- data/lib/hexapdf/type/action.rb +1 -1
- data/lib/hexapdf/type/actions/go_to.rb +1 -1
- data/lib/hexapdf/type/actions/go_to_r.rb +1 -1
- data/lib/hexapdf/type/actions/launch.rb +1 -1
- data/lib/hexapdf/type/actions/uri.rb +1 -1
- data/lib/hexapdf/type/actions.rb +1 -1
- data/lib/hexapdf/type/annotation.rb +3 -3
- data/lib/hexapdf/type/annotations/link.rb +1 -1
- data/lib/hexapdf/type/annotations/markup_annotation.rb +1 -1
- data/lib/hexapdf/type/annotations/text.rb +1 -1
- data/lib/hexapdf/type/annotations/widget.rb +2 -2
- data/lib/hexapdf/type/annotations.rb +1 -1
- data/lib/hexapdf/type/catalog.rb +1 -1
- data/lib/hexapdf/type/cid_font.rb +3 -3
- data/lib/hexapdf/type/embedded_file.rb +1 -1
- data/lib/hexapdf/type/file_specification.rb +2 -2
- data/lib/hexapdf/type/font_descriptor.rb +1 -1
- data/lib/hexapdf/type/font_simple.rb +2 -2
- data/lib/hexapdf/type/font_type0.rb +3 -3
- data/lib/hexapdf/type/font_type3.rb +1 -1
- data/lib/hexapdf/type/form.rb +1 -1
- data/lib/hexapdf/type/graphics_state_parameter.rb +1 -1
- data/lib/hexapdf/type/icon_fit.rb +1 -1
- data/lib/hexapdf/type/image.rb +1 -1
- data/lib/hexapdf/type/info.rb +1 -1
- data/lib/hexapdf/type/mark_information.rb +1 -1
- data/lib/hexapdf/type/names.rb +2 -2
- data/lib/hexapdf/type/object_stream.rb +7 -3
- data/lib/hexapdf/type/outline.rb +1 -1
- data/lib/hexapdf/type/outline_item.rb +1 -1
- data/lib/hexapdf/type/page.rb +19 -10
- data/lib/hexapdf/type/page_label.rb +1 -1
- data/lib/hexapdf/type/page_tree_node.rb +1 -1
- data/lib/hexapdf/type/resources.rb +1 -1
- data/lib/hexapdf/type/trailer.rb +2 -2
- data/lib/hexapdf/type/viewer_preferences.rb +1 -1
- data/lib/hexapdf/type/xref_stream.rb +2 -2
- data/lib/hexapdf/utils/pdf_doc_encoding.rb +1 -1
- data/lib/hexapdf/version.rb +1 -1
- data/lib/hexapdf/writer.rb +4 -4
- data/lib/hexapdf/xref_section.rb +2 -2
- data/test/hexapdf/content/graphic_object/test_endpoint_arc.rb +11 -1
- data/test/hexapdf/content/graphic_object/test_geom2d.rb +7 -0
- data/test/hexapdf/content/test_canvas.rb +0 -1
- data/test/hexapdf/digital_signature/test_signatures.rb +22 -0
- data/test/hexapdf/document/test_files.rb +2 -2
- data/test/hexapdf/document/test_layout.rb +98 -0
- data/test/hexapdf/encryption/test_security_handler.rb +12 -11
- data/test/hexapdf/encryption/test_standard_security_handler.rb +35 -23
- data/test/hexapdf/font/test_true_type_wrapper.rb +18 -1
- data/test/hexapdf/font/test_type1_wrapper.rb +15 -1
- data/test/hexapdf/layout/test_box.rb +1 -1
- data/test/hexapdf/layout/test_column_box.rb +65 -21
- data/test/hexapdf/layout/test_frame.rb +14 -14
- data/test/hexapdf/layout/test_image_box.rb +4 -0
- data/test/hexapdf/layout/test_inline_box.rb +5 -0
- data/test/hexapdf/layout/test_list_box.rb +40 -6
- data/test/hexapdf/layout/test_page_style.rb +3 -2
- data/test/hexapdf/layout/test_style.rb +50 -0
- data/test/hexapdf/layout/test_table_box.rb +722 -0
- data/test/hexapdf/layout/test_text_box.rb +18 -0
- data/test/hexapdf/layout/test_text_layouter.rb +4 -0
- data/test/hexapdf/test_dictionary_fields.rb +4 -1
- data/test/hexapdf/test_document.rb +1 -0
- data/test/hexapdf/test_filter.rb +8 -0
- data/test/hexapdf/test_importer.rb +9 -0
- data/test/hexapdf/test_object.rb +16 -5
- data/test/hexapdf/test_parser.rb +1 -1
- data/test/hexapdf/test_stream.rb +7 -0
- data/test/hexapdf/test_writer.rb +3 -3
- data/test/hexapdf/type/acro_form/test_appearance_generator.rb +13 -5
- data/test/hexapdf/type/acro_form/test_form.rb +4 -3
- data/test/hexapdf/type/test_object_stream.rb +9 -3
- data/test/hexapdf/type/test_page.rb +18 -4
- metadata +17 -8
@@ -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.
|
@@ -306,7 +321,7 @@ module HexaPDF
|
|
306
321
|
# canvas.save_graphics_state => canvas
|
307
322
|
# canvas.save_graphics_state { block } => canvas
|
308
323
|
#
|
309
|
-
# Saves the current graphics state and returns self
|
324
|
+
# Saves the current graphics state and returns +self+.
|
310
325
|
#
|
311
326
|
# If invoked without a block a corresponding call to #restore_graphics_state must be done to
|
312
327
|
# ensure proper nesting. Otherwise, i.e. when invoked with a block, the graphics state is
|
@@ -320,7 +335,7 @@ module HexaPDF
|
|
320
335
|
# #>pdf
|
321
336
|
# # With a block
|
322
337
|
# canvas.save_graphics_state do
|
323
|
-
# canvas.stroke_color("
|
338
|
+
# canvas.stroke_color("hp-blue") # After the block the color is reset
|
324
339
|
# canvas.line(20, 20, 70, 180).stroke
|
325
340
|
# end
|
326
341
|
# canvas.line(60, 20, 110, 180).stroke
|
@@ -332,7 +347,7 @@ module HexaPDF
|
|
332
347
|
# restore_graphics_state
|
333
348
|
# canvas.line(140, 20, 190, 180).stroke
|
334
349
|
#
|
335
|
-
# See:
|
350
|
+
# See: PDF2.0 s8.4.2, #restore_graphics_state
|
336
351
|
def save_graphics_state
|
337
352
|
raise_unless_at_page_description_level
|
338
353
|
invoke0(:q)
|
@@ -347,11 +362,20 @@ module HexaPDF
|
|
347
362
|
# :call-seq:
|
348
363
|
# canvas.restore_graphics_state => canvas
|
349
364
|
#
|
350
|
-
# Restores the
|
365
|
+
# Restores the graphics state to the last saved version and returns +self+.
|
351
366
|
#
|
352
367
|
# Must not be invoked more times than #save_graphics_state.
|
353
368
|
#
|
354
|
-
#
|
369
|
+
# Example:
|
370
|
+
#
|
371
|
+
# #>pdf
|
372
|
+
# canvas.save_graphics_state
|
373
|
+
# canvas.circle(100, 100, 50).clip_path.end_path
|
374
|
+
# canvas.fill_color("hp-blue").rectangle(0, 0, 100, 100).fill
|
375
|
+
# canvas.restore_graphics_state
|
376
|
+
# canvas.rectangle(100, 0, 100, 100).fill
|
377
|
+
#
|
378
|
+
# See: PDF2.0 s8.4.2, #save_graphics_state
|
355
379
|
def restore_graphics_state
|
356
380
|
raise_unless_at_page_description_level
|
357
381
|
invoke0(:Q)
|
@@ -363,7 +387,7 @@ module HexaPDF
|
|
363
387
|
# canvas.transform(a, b, c, d, e, f) => canvas
|
364
388
|
# canvas.transform(a, b, c, d, e, f) { block } => canvas
|
365
389
|
#
|
366
|
-
# Transforms the
|
390
|
+
# Transforms the coordinate system by applying the given matrix to the current transformation
|
367
391
|
# matrix and returns self.
|
368
392
|
#
|
369
393
|
# If invoked with a block, the transformation is only active during the block by saving and
|
@@ -375,16 +399,16 @@ module HexaPDF
|
|
375
399
|
# c d 0
|
376
400
|
# e f 1
|
377
401
|
#
|
378
|
-
#
|
402
|
+
# Example:
|
379
403
|
#
|
380
404
|
# #>pdf
|
381
405
|
# canvas.transform(1, 0, 0, 1, 100, 100) do # Translate origin to (100, 100)
|
382
|
-
# canvas.stroke_color("
|
406
|
+
# canvas.stroke_color("hp-blue").
|
383
407
|
# line(0, 0, 100, 50).stroke # Actually from (100, 100) to (200, 150)
|
384
408
|
# end
|
385
409
|
# canvas.line(0, 0, 100, 50).stroke # Really from (0, 0) to (100, 50)
|
386
410
|
#
|
387
|
-
# See:
|
411
|
+
# See: PDF2.0 s8.3, s8.4.4
|
388
412
|
def transform(a, b, c, d, e, f)
|
389
413
|
raise_unless_at_page_description_level
|
390
414
|
save_graphics_state if block_given?
|
@@ -400,30 +424,31 @@ module HexaPDF
|
|
400
424
|
# canvas.rotate(angle, origin: nil) => canvas
|
401
425
|
# canvas.rotate(angle, origin: nil) { block } => canvas
|
402
426
|
#
|
403
|
-
# Rotates the
|
404
|
-
#
|
427
|
+
# Rotates the coordinate system +angle+ degrees around the origin or around the given point
|
428
|
+
# and returns +self+.
|
405
429
|
#
|
406
|
-
# If invoked with a block, the rotation of the
|
407
|
-
# saving and restoring the graphics state.
|
430
|
+
# If invoked with a block, the rotation of the coordinate system is only active during the
|
431
|
+
# block by saving and restoring the graphics state.
|
408
432
|
#
|
409
433
|
# Note that the origin of the coordinate system itself doesn't change even if the +origin+
|
410
434
|
# argument is given!
|
411
435
|
#
|
412
436
|
# origin::
|
413
|
-
# The point around which the
|
437
|
+
# The point around which the coordinate system should be rotated.
|
414
438
|
#
|
415
439
|
# Examples:
|
416
440
|
#
|
417
441
|
# #>pdf-center
|
418
|
-
# canvas.stroke_color("
|
419
|
-
# rectangle(0, 0, 60, 40).stroke
|
442
|
+
# canvas.stroke_color("hp-gray-light").
|
443
|
+
# rectangle(0, 0, 60, 40).stroke # The rectangle that gets rotated
|
444
|
+
#
|
420
445
|
# canvas.rotate(45) do # Positive x-axis pointing to top-right corner
|
421
|
-
# canvas.stroke_color("
|
446
|
+
# canvas.stroke_color("hp-blue").
|
422
447
|
# rectangle(0, 0, 60, 40).stroke
|
423
448
|
# end
|
424
449
|
#
|
425
450
|
# canvas.rotate(-45, origin: [-50, -50]) do # Rotate around (-50,-50)
|
426
|
-
# canvas.stroke_color("
|
451
|
+
# canvas.stroke_color("hp-orange").
|
427
452
|
# rectangle(0, 0, 60, 40).stroke
|
428
453
|
# end
|
429
454
|
#
|
@@ -443,8 +468,8 @@ module HexaPDF
|
|
443
468
|
# canvas.scale(sx, sy = sx, origin: nil) => canvas
|
444
469
|
# canvas.scale(sx, sy = sx, origin: nil) { block } => canvas
|
445
470
|
#
|
446
|
-
# Scales the
|
447
|
-
# direction and returns self
|
471
|
+
# Scales the coordinate system +sx+ units in the horizontal and +sy+ units in the vertical
|
472
|
+
# direction and returns +self+. If the optional +origin+ is specified, scaling is done from
|
448
473
|
# that point.
|
449
474
|
#
|
450
475
|
# If invoked with a block, the scaling is only active during the block by saving and
|
@@ -454,20 +479,21 @@ module HexaPDF
|
|
454
479
|
# argument is given!
|
455
480
|
#
|
456
481
|
# origin::
|
457
|
-
# The point from which the
|
482
|
+
# The point from which the coordinate system should be scaled.
|
458
483
|
#
|
459
484
|
# Examples:
|
460
485
|
#
|
461
486
|
# #>pdf-center
|
462
|
-
# canvas.stroke_color("
|
463
|
-
# rectangle(10, 10, 10, 10).stroke
|
487
|
+
# canvas.stroke_color("hp-gray-light").
|
488
|
+
# rectangle(10, 10, 10, 10).stroke # The rectangle that gets scaled
|
489
|
+
#
|
464
490
|
# canvas.scale(4, 2) do # Scale from origin
|
465
|
-
# canvas.stroke_color("blue").
|
491
|
+
# canvas.stroke_color("hp-blue").
|
466
492
|
# rectangle(10, 10, 10, 10).stroke # Actually (40, 20) to (80, 40)
|
467
493
|
# end
|
468
494
|
#
|
469
495
|
# canvas.scale(-2, 4, origin: [10, 10]) do # Scale from (10, 10)
|
470
|
-
# canvas.stroke_color("
|
496
|
+
# canvas.stroke_color("hp-orange").
|
471
497
|
# rectangle(10, 10, 10, 10).stroke # Actually (10, 10) to (-10, 40)
|
472
498
|
# end
|
473
499
|
#
|
@@ -484,18 +510,19 @@ module HexaPDF
|
|
484
510
|
# canvas.translate(x, y) => canvas
|
485
511
|
# canvas.translate(x, y) { block } => canvas
|
486
512
|
#
|
487
|
-
# Translates the
|
488
|
-
# and returns self
|
513
|
+
# Translates the coordinate system coordinate system origin to the given +x+ and +y+
|
514
|
+
# coordinates and returns +self+.
|
489
515
|
#
|
490
|
-
# If invoked with a block, the translation of the
|
491
|
-
# by saving and restoring the graphics state.
|
516
|
+
# If invoked with a block, the translation of the coordinate system is only active during the
|
517
|
+
# block by saving and restoring the graphics state.
|
492
518
|
#
|
493
519
|
# Examples:
|
494
520
|
#
|
495
521
|
# #>pdf-center
|
496
|
-
# canvas.
|
522
|
+
# canvas.stroke_color("hp-gray-light").
|
523
|
+
# rectangle(0, 0, 40, 20).stroke # Rectangle from (0, 0) to (40, 20)
|
497
524
|
# canvas.translate(50, 50) do # Origin is now at (50, 50)
|
498
|
-
# canvas.stroke_color("
|
525
|
+
# canvas.stroke_color("hp-blue").
|
499
526
|
# rectangle(0, 0, 40, 20).stroke # Actually (50, 50) to (90, 70)
|
500
527
|
# end
|
501
528
|
#
|
@@ -508,7 +535,7 @@ module HexaPDF
|
|
508
535
|
# canvas.skew(a, b, origin: nil) => canvas
|
509
536
|
# canvas.skew(a, b, origin: nil) { block } => canvas
|
510
537
|
#
|
511
|
-
# Skews the the x-axis by +a+ degrees and the y-axis by +b+ degress and returns self
|
538
|
+
# Skews the the x-axis by +a+ degrees and the y-axis by +b+ degress and returns +self+. If the
|
512
539
|
# optional +origin+ is specified, skewing is done from that point.
|
513
540
|
#
|
514
541
|
# If invoked with a block, the skewing is only active during the block by saving and
|
@@ -522,15 +549,16 @@ module HexaPDF
|
|
522
549
|
# Examples:
|
523
550
|
#
|
524
551
|
# #>pdf-center
|
525
|
-
# canvas.stroke_color("
|
526
|
-
# rectangle(10, 10, 40, 20).stroke
|
552
|
+
# canvas.stroke_color("hp-gray-light").
|
553
|
+
# rectangle(10, 10, 40, 20).stroke # The rectangle that gets skewed
|
554
|
+
#
|
527
555
|
# canvas.skew(0, 30) do # Point (10, 10) is now actually (15, 10)
|
528
|
-
# canvas.stroke_color("blue").
|
556
|
+
# canvas.stroke_color("hp-blue").
|
529
557
|
# rectangle(10, 10, 40, 20).stroke # Now a parallelogram
|
530
558
|
# end
|
531
559
|
#
|
532
560
|
# canvas.skew(30, 30, origin: [-50, 50]) do # Skew from (-50, 50)
|
533
|
-
# canvas.stroke_color("
|
561
|
+
# canvas.stroke_color("hp-orange").
|
534
562
|
# rectangle(-50, 50, 20, 20).stroke
|
535
563
|
# end
|
536
564
|
#
|
@@ -553,9 +581,15 @@ module HexaPDF
|
|
553
581
|
#
|
554
582
|
# The line width determines the thickness of a stroked path.
|
555
583
|
#
|
556
|
-
#
|
557
|
-
#
|
558
|
-
#
|
584
|
+
# Note that half the line width lies on either side of the path. For example, if a path from
|
585
|
+
# (0, 0) to (0, 100) is drawn with a line width of 20, the stroked path is actually 20 units
|
586
|
+
# wide, from -10 to 10. And if a rectangle is drawn stroked, but not filled, from (20, 20)
|
587
|
+
# with a width and height of 20 and a line width of 10, the "inside" of the rectangle would
|
588
|
+
# only be from (25, 25) to (35, 35). Also see the examples below.
|
589
|
+
#
|
590
|
+
# Returns the current line width (see GraphicsState#line_width) when no argument is given.
|
591
|
+
# Otherwise sets the line width to the given +width+ and returns +self+. The setter version
|
592
|
+
# can also be called in the line_width= form.
|
559
593
|
#
|
560
594
|
# If the +width+ and a block are provided, the changed line width is only active during the
|
561
595
|
# block by saving and restoring the graphics state.
|
@@ -564,19 +598,22 @@ module HexaPDF
|
|
564
598
|
#
|
565
599
|
# #>pdf
|
566
600
|
# canvas.line_width(10).
|
567
|
-
# line(10,
|
601
|
+
# line(10, 100, 10, 190).stroke
|
568
602
|
# canvas.line_width # => 10
|
569
603
|
# canvas.line_width = 5 # => 5
|
570
|
-
# canvas.line(60,
|
604
|
+
# canvas.line(60, 100, 60, 190).stroke
|
571
605
|
#
|
572
606
|
# canvas.line_width(10) do
|
573
607
|
# canvas.line_width # => 10
|
574
|
-
# canvas.line(110,
|
608
|
+
# canvas.line(110, 100, 110, 190).stroke
|
575
609
|
# end
|
576
610
|
# canvas.line_width # => 5
|
577
|
-
# canvas.line(160,
|
611
|
+
# canvas.line(160, 100, 160, 190).stroke
|
578
612
|
#
|
579
|
-
#
|
613
|
+
# canvas.line_width(10).rectangle(20, 20, 20, 20).stroke # The rectangle
|
614
|
+
# canvas.fill_color("hp-blue").rectangle(25, 25, 10, 10).fill # The inside
|
615
|
+
#
|
616
|
+
# See: PDF2.0 s8.4.3.2
|
580
617
|
def line_width(width = nil, &block)
|
581
618
|
gs_getter_setter(:line_width, :w, width, &block)
|
582
619
|
end
|
@@ -587,7 +624,7 @@ module HexaPDF
|
|
587
624
|
# canvas.line_cap_style(style) => canvas
|
588
625
|
# canvas.line_cap_style(style) { block } => canvas
|
589
626
|
#
|
590
|
-
# The line cap style specifies how the ends of stroked open paths should look like.
|
627
|
+
# The line cap style specifies how the ends of stroked, open paths should look like.
|
591
628
|
#
|
592
629
|
# The +style+ parameter can be one of (also see LineCapStyle):
|
593
630
|
#
|
@@ -598,11 +635,11 @@ module HexaPDF
|
|
598
635
|
# :projecting_square or 2::
|
599
636
|
# The stroke continues half the line width beyond the endpoint of a path.
|
600
637
|
#
|
601
|
-
# Note that the return value is always a normalized line cap style.
|
638
|
+
# Note that the return value is always a normalized line cap style (i.e. a NamedValue).
|
602
639
|
#
|
603
|
-
# Returns the current line cap style (see
|
604
|
-
#
|
605
|
-
#
|
640
|
+
# Returns the current line cap style (see GraphicsState#line_cap_style) when no argument is
|
641
|
+
# given. Otherwise sets the line cap style to the given +style+ and returns +self+. The setter
|
642
|
+
# version can also be called in the line_cap_style= form.
|
606
643
|
#
|
607
644
|
# If the +style+ and a block are provided, the changed line cap style is only active during
|
608
645
|
# the block by saving and restoring the graphics state.
|
@@ -628,7 +665,7 @@ module HexaPDF
|
|
628
665
|
# line(50 + index * 50, 30, 50 + index * 50, 170).stroke
|
629
666
|
# end
|
630
667
|
#
|
631
|
-
# See:
|
668
|
+
# See: PDF2.0 s8.4.3.3, Content::LineCapStyle
|
632
669
|
def line_cap_style(style = nil, &block)
|
633
670
|
gs_getter_setter(:line_cap_style, :J, style && LineCapStyle.normalize(style), &block)
|
634
671
|
end
|
@@ -651,11 +688,11 @@ module HexaPDF
|
|
651
688
|
# The two segments are finished with butt caps and the space between the ends is filled
|
652
689
|
# with a triangle.
|
653
690
|
#
|
654
|
-
# Note that the return value is always a normalized line join style.
|
691
|
+
# Note that the return value is always a normalized line join style (i.e. a NamedValue).
|
655
692
|
#
|
656
|
-
# Returns the current line join style (see
|
657
|
-
#
|
658
|
-
#
|
693
|
+
# Returns the current line join style (see GraphicsState#line_join_style) when no argument is
|
694
|
+
# given. Otherwise sets the line join style to the given +style+ and returns +self+. The
|
695
|
+
# setter version can also be called in the line_join_style= form.
|
659
696
|
#
|
660
697
|
# If the +style+ and a block are provided, the changed line join style is only active during
|
661
698
|
# the block by saving and restoring the graphics state.
|
@@ -681,7 +718,7 @@ module HexaPDF
|
|
681
718
|
# polyline(20 + index * 60, 30, 40 + index * 60, 170, 60 + index * 60, 30).stroke
|
682
719
|
# end
|
683
720
|
#
|
684
|
-
# See:
|
721
|
+
# See: PDF2.0 s8.4.3.4, Content::LineJoinStyle
|
685
722
|
def line_join_style(style = nil, &block)
|
686
723
|
gs_getter_setter(:line_join_style, :j, style && LineJoinStyle.normalize(style), &block)
|
687
724
|
end
|
@@ -696,9 +733,9 @@ module HexaPDF
|
|
696
733
|
# mitered line joins (see #line_join_style). When the limit is exceeded, a bevel join is
|
697
734
|
# used instead of a miter join.
|
698
735
|
#
|
699
|
-
# Returns the current miter limit (see
|
700
|
-
#
|
701
|
-
#
|
736
|
+
# Returns the current miter limit (see GraphicsState#miter_limit) when no argument is given.
|
737
|
+
# Otherwise sets the miter limit to the given +limit+ and returns +self+. The setter version
|
738
|
+
# can also be called in the miter_limit= form.
|
702
739
|
#
|
703
740
|
# If the +limit+ and a block are provided, the changed miter limit is only active during the
|
704
741
|
# block by saving and restoring the graphics state.
|
@@ -722,7 +759,7 @@ module HexaPDF
|
|
722
759
|
# 60 + index * 80, 30).stroke
|
723
760
|
# end
|
724
761
|
#
|
725
|
-
# See:
|
762
|
+
# See: PDF2.0 s8.4.3.5
|
726
763
|
def miter_limit(limit = nil, &block)
|
727
764
|
gs_getter_setter(:miter_limit, :M, limit, &block)
|
728
765
|
end
|
@@ -740,7 +777,7 @@ module HexaPDF
|
|
740
777
|
#
|
741
778
|
# There are multiple ways to set the line dash pattern:
|
742
779
|
#
|
743
|
-
# * By providing a
|
780
|
+
# * By providing a LineDashPattern object
|
744
781
|
# * By providing a single Integer/Float that is used for both dashes and gaps
|
745
782
|
# * By providing an array of Integers/Floats that specify the alternating dashes and gaps
|
746
783
|
#
|
@@ -749,10 +786,10 @@ module HexaPDF
|
|
749
786
|
#
|
750
787
|
# A solid line can be achieved by using 0 for the length or by using an empty array.
|
751
788
|
#
|
752
|
-
# Returns the current line dash pattern (
|
753
|
-
# argument is given. Otherwise sets the line dash
|
754
|
-
# returns self
|
755
|
-
# without the second argument!).
|
789
|
+
# Returns the current line dash pattern (a LineDashPattern object, see
|
790
|
+
# GraphicsState#line_dash_pattern) when no argument is given. Otherwise sets the line dash
|
791
|
+
# pattern using the given arguments and returns +self+. The setter version can also be called
|
792
|
+
# in the line_dash_pattern= form (but only without the second argument!).
|
756
793
|
#
|
757
794
|
# If arguments and a block are provided, the changed line dash pattern is only active during
|
758
795
|
# the block by saving and restoring the graphics state.
|
@@ -778,7 +815,7 @@ module HexaPDF
|
|
778
815
|
# stroke
|
779
816
|
# end
|
780
817
|
#
|
781
|
-
# See:
|
818
|
+
# See: PDF2.0 s8.4.3.5, LineDashPattern
|
782
819
|
def line_dash_pattern(value = nil, phase = 0, &block)
|
783
820
|
gs_getter_setter(:line_dash_pattern, :d, value && LineDashPattern.normalize(value, phase),
|
784
821
|
&block)
|
@@ -799,9 +836,9 @@ module HexaPDF
|
|
799
836
|
# * +:Saturation+
|
800
837
|
# * +:Perceptual+
|
801
838
|
#
|
802
|
-
# Returns the current rendering intent (see
|
803
|
-
#
|
804
|
-
#
|
839
|
+
# Returns the current rendering intent (see GraphicsState#rendering_intent) when no argument
|
840
|
+
# is given. Otherwise sets the rendering intent using the +intent+ argument and returns
|
841
|
+
# +self+. The setter version can also be called in the rendering_intent= form.
|
805
842
|
#
|
806
843
|
# If the +intent+ and a block are provided, the changed rendering intent is only active
|
807
844
|
# during the block by saving and restoring the graphics state.
|
@@ -817,7 +854,7 @@ module HexaPDF
|
|
817
854
|
# end
|
818
855
|
# canvas.rendering_intent # => :Saturation
|
819
856
|
#
|
820
|
-
# See:
|
857
|
+
# See: PDF2.0 s8.6.5.8, RenderingIntent
|
821
858
|
def rendering_intent(intent = nil, &bk)
|
822
859
|
gs_getter_setter(:rendering_intent, :ri, intent && RenderingIntent.normalize(intent), &bk)
|
823
860
|
end
|
@@ -837,23 +874,30 @@ module HexaPDF
|
|
837
874
|
#
|
838
875
|
# There are several ways to define the color that should be used:
|
839
876
|
#
|
840
|
-
# * A single numeric argument specifies a gray color (see
|
841
|
-
#
|
842
|
-
# * Three numeric arguments specify an RGB color (see
|
877
|
+
# * A single numeric argument specifies a gray color (see ColorSpace::DeviceGray::Color).
|
878
|
+
#
|
879
|
+
# * Three numeric arguments specify an RGB color (see ColorSpace::DeviceRGB::Color).
|
880
|
+
#
|
843
881
|
# * A string in the format "RRGGBB" where "RR" is the hexadecimal number for the red, "GG"
|
844
882
|
# for the green and "BB" for the blue color value also specifies an RGB color.
|
883
|
+
#
|
845
884
|
# * As does a string in the format "RGB" where "RR", "GG" and "BB" would be used as the
|
846
885
|
# hexadecimal numbers for the red, green and blue color values of an RGB color.
|
847
|
-
#
|
848
|
-
#
|
849
|
-
#
|
886
|
+
#
|
887
|
+
# * Any other string is treated as a color name. HexaPDF supports CSS Color Module Level 3
|
888
|
+
# color names (see https://www.w3.org/TR/css-color-3/#svg-color) as well as HexaPDF design
|
889
|
+
# colors.
|
890
|
+
#
|
891
|
+
# * Four numeric arguments specify a CMYK color (see ColorSpace::DeviceCMYK::Color).
|
892
|
+
#
|
850
893
|
# * A color object is used directly (normally used for color spaces other than DeviceRGB,
|
851
894
|
# DeviceCMYK and DeviceGray).
|
895
|
+
#
|
852
896
|
# * An array is treated as if its items were specified separately as arguments.
|
853
897
|
#
|
854
|
-
# Returns the current stroke color (see
|
855
|
-
#
|
856
|
-
#
|
898
|
+
# Returns the current stroke color (see GraphicsState#stroke_color) when no argument is given.
|
899
|
+
# Otherwise sets the stroke color using the given arguments and returns +self+. The setter
|
900
|
+
# version can also be called in the stroke_color= form.
|
857
901
|
#
|
858
902
|
# If the arguments and a block are provided, the changed stroke color is only active during
|
859
903
|
# the block by saving and restoring the graphics state.
|
@@ -896,7 +940,7 @@ module HexaPDF
|
|
896
940
|
# canvas.stroke_color # => ColorSpace::DeviceGray.color(0.4)
|
897
941
|
# end
|
898
942
|
#
|
899
|
-
# See:
|
943
|
+
# See: PDF2.0 s8.6, ColorSpace
|
900
944
|
def stroke_color(*color, &block)
|
901
945
|
color_getter_setter(:stroke_color, color, :RG, :G, :K, :CS, :SCN, &block)
|
902
946
|
end
|
@@ -922,10 +966,10 @@ module HexaPDF
|
|
922
966
|
# the fill alpha value applies not just to fill values but to all non-stroking operations
|
923
967
|
# (e.g. images, ...).
|
924
968
|
#
|
925
|
-
# Returns the current fill alpha (see
|
926
|
-
#
|
969
|
+
# Returns the current fill alpha (see GraphicsState#fill_alpha) and stroke alpha (see
|
970
|
+
# GraphicsState#stroke_alpha) values using a hash with the keys +:fill_alpha+ and
|
927
971
|
# +:stroke_alpha+ when no argument is given. Otherwise sets the fill and stroke alpha values
|
928
|
-
# and returns self
|
972
|
+
# and returns +self+. The setter version can also be called in the #opacity= form.
|
929
973
|
#
|
930
974
|
# If the values are set and a block is provided, the changed alpha values are only active
|
931
975
|
# during the block by saving and restoring the graphics state.
|
@@ -944,15 +988,15 @@ module HexaPDF
|
|
944
988
|
# canvas.opacity # => {fill_alpha: 0.4, stroke_alpha: 0.9}
|
945
989
|
#
|
946
990
|
# # visual example
|
947
|
-
# canvas.opacity(fill_alpha: 1, stroke_alpha: 1)
|
948
|
-
#
|
949
|
-
#
|
991
|
+
# canvas.opacity(fill_alpha: 1, stroke_alpha: 1)
|
992
|
+
# canvas.fill_color("hp-gray-light"). # background rectangle on right side
|
993
|
+
# rectangle(100, 0, 100, 200).fill
|
950
994
|
# canvas.opacity(fill_alpha: 0.5, stroke_alpha: 0.8). # foreground rectangle, with a thick
|
951
995
|
# line_width(20). # stroke that also overlays the
|
952
|
-
# fill_color("
|
996
|
+
# fill_color("hp-blue").stroke_color("hp-blue"). # inside of the rectangle, creating
|
953
997
|
# rectangle(20, 20, 160, 160).fill_stroke # multiple shadings due to opacity
|
954
998
|
#
|
955
|
-
# See:
|
999
|
+
# See: PDF2.0 s11.6.4.4
|
956
1000
|
def opacity(fill_alpha: nil, stroke_alpha: nil)
|
957
1001
|
if !fill_alpha.nil? || !stroke_alpha.nil?
|
958
1002
|
raise_unless_at_page_description_level_or_in_text
|
@@ -981,14 +1025,14 @@ module HexaPDF
|
|
981
1025
|
# canvas.move_to(x, y) => canvas
|
982
1026
|
#
|
983
1027
|
# Begins a new subpath (and possibly a new path) by moving the current point to the given
|
984
|
-
# point
|
1028
|
+
# point and returns +self+.
|
985
1029
|
#
|
986
1030
|
# Examples:
|
987
1031
|
#
|
988
1032
|
# canvas.move_to(10, 50)
|
989
1033
|
# canvas.current_point # => [10, 50]
|
990
1034
|
#
|
991
|
-
# See:
|
1035
|
+
# See: PDF2.0 s8.5.2.1, #line_to, #curve_to, #rectangle
|
992
1036
|
def move_to(x, y)
|
993
1037
|
raise_unless_at_page_description_level_or_in_path
|
994
1038
|
invoke2(:m, x, y)
|
@@ -1001,17 +1045,20 @@ module HexaPDF
|
|
1001
1045
|
# canvas.line_to(x, y) => canvas
|
1002
1046
|
#
|
1003
1047
|
# Appends a straight line segment from the current point to the given point (which becomes the
|
1004
|
-
# new current point) to the current subpath
|
1048
|
+
# new current point) to the current subpath and returns +self+.
|
1049
|
+
#
|
1050
|
+
# If there is no current path when the method is invoked, an error is raised since a valid
|
1051
|
+
# current point (#current_point) is needed.
|
1005
1052
|
#
|
1006
1053
|
# Examples:
|
1007
1054
|
#
|
1008
1055
|
# #>pdf-center
|
1009
|
-
# canvas.move_to(10, 50)
|
1010
|
-
#
|
1011
|
-
# canvas.current_point
|
1056
|
+
# canvas.move_to(10, 50)
|
1057
|
+
# canvas.line_to(80, 80)
|
1058
|
+
# canvas.current_point # => [80, 80]
|
1012
1059
|
# canvas.stroke
|
1013
1060
|
#
|
1014
|
-
# See:
|
1061
|
+
# See: PDF2.0 s8.5.2.1, #move_to, #curve_to, #rectangle
|
1015
1062
|
def line_to(x, y)
|
1016
1063
|
raise_unless_in_path
|
1017
1064
|
invoke2(:l, x, y)
|
@@ -1025,8 +1072,11 @@ module HexaPDF
|
|
1025
1072
|
# canvas.curve_to(x, y, p1:) => canvas
|
1026
1073
|
# canvas.curve_to(x, y, p2:) => canvas
|
1027
1074
|
#
|
1028
|
-
# Appends a cubic Bezier curve to the current subpath starting from the current point
|
1029
|
-
# point becomes the new current point.
|
1075
|
+
# Appends a cubic Bezier curve to the current subpath starting from the current point and
|
1076
|
+
# returns +self+. The end point becomes the new current point.
|
1077
|
+
#
|
1078
|
+
# If there is no current path when the method is invoked, an error is raised since a valid
|
1079
|
+
# current point (#current_point) is needed.
|
1030
1080
|
#
|
1031
1081
|
# A Bezier curve consists of the start point, the end point and the two control points +p1+
|
1032
1082
|
# and +p2+. The start point is always the current point and the end point is specified as the
|
@@ -1047,7 +1097,7 @@ module HexaPDF
|
|
1047
1097
|
# canvas.current_point # => [-30, 60]
|
1048
1098
|
# canvas.stroke
|
1049
1099
|
#
|
1050
|
-
# See:
|
1100
|
+
# See: PDF2.0 s8.5.2.2, #move_to, #line_to, #rectangle
|
1051
1101
|
def curve_to(x, y, p1: nil, p2: nil)
|
1052
1102
|
raise_unless_in_path
|
1053
1103
|
if p1 && p2
|
@@ -1069,10 +1119,13 @@ module HexaPDF
|
|
1069
1119
|
#
|
1070
1120
|
# Appends a rectangle to the current path as a complete subpath (drawn in counterclockwise
|
1071
1121
|
# direction), with the bottom left corner specified by +x+ and +y+ and the given +width+ and
|
1072
|
-
# +height+.
|
1122
|
+
# +height+. Returns +self+.
|
1073
1123
|
#
|
1074
1124
|
# If +radius+ is greater than 0, the corners are rounded with the given radius.
|
1075
1125
|
#
|
1126
|
+
# Note that the rectangle degrades to a line if either width or height is zero and to nothing
|
1127
|
+
# if both are zero.
|
1128
|
+
#
|
1076
1129
|
# If there is no current path when the method is invoked, a new path is automatically begun.
|
1077
1130
|
#
|
1078
1131
|
# The current point is set to the bottom left corner if +radius+ is zero, otherwise it is set
|
@@ -1083,10 +1136,10 @@ module HexaPDF
|
|
1083
1136
|
# #>pdf
|
1084
1137
|
# canvas.rectangle(10, 110, 80, 50).stroke
|
1085
1138
|
# canvas.rectangle(110, 110, 80, 50, radius: 10).stroke
|
1086
|
-
# canvas.rectangle(10,
|
1087
|
-
# canvas.rectangle(110,
|
1139
|
+
# canvas.rectangle(10, 90, 80, 0).stroke # Degraded: Just a line
|
1140
|
+
# canvas.rectangle(110, 90, 0, 0).stroke # Degraded: Draws nothing
|
1088
1141
|
#
|
1089
|
-
# See:
|
1142
|
+
# See: PDF2.0 s8.5.2.1, #move_to, #line_to, #curve_to
|
1090
1143
|
def rectangle(x, y, width, height, radius: 0)
|
1091
1144
|
raise_unless_at_page_description_level_or_in_path
|
1092
1145
|
if radius == 0
|
@@ -1103,7 +1156,10 @@ module HexaPDF
|
|
1103
1156
|
# canvas.close_subpath => canvas
|
1104
1157
|
#
|
1105
1158
|
# 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.
|
1159
|
+
# start point of the subpath which also becomes the new current point. Returns +self+.
|
1160
|
+
#
|
1161
|
+
# If there is no current path when the method is invoked, an error is raised since a valid
|
1162
|
+
# current point (#current_point) is needed.
|
1107
1163
|
#
|
1108
1164
|
# Examples:
|
1109
1165
|
#
|
@@ -1114,7 +1170,7 @@ module HexaPDF
|
|
1114
1170
|
# close_subpath. # Draws the line from (60, 60) to (10, 10)
|
1115
1171
|
# stroke
|
1116
1172
|
#
|
1117
|
-
# See:
|
1173
|
+
# See: PDF2.0 s8.5.2.1
|
1118
1174
|
def close_subpath
|
1119
1175
|
raise_unless_in_path
|
1120
1176
|
invoke0(:h)
|
@@ -1126,13 +1182,16 @@ module HexaPDF
|
|
1126
1182
|
# canvas.line(x0, y0, x1, y1) => canvas
|
1127
1183
|
#
|
1128
1184
|
# Moves the current point to (x0, y0) and appends a line to (x1, y1) to the current path.
|
1185
|
+
# Returns +self+.
|
1129
1186
|
#
|
1130
|
-
#
|
1187
|
+
# If there is no current path when the method is invoked, a new path is automatically begun.
|
1131
1188
|
#
|
1132
1189
|
# Examples:
|
1133
1190
|
#
|
1134
1191
|
# #>pdf
|
1135
1192
|
# canvas.line(10, 10, 100, 100).stroke
|
1193
|
+
#
|
1194
|
+
# See: #move_to, #line_to
|
1136
1195
|
def line(x0, y0, x1, y1)
|
1137
1196
|
move_to(x0, y0)
|
1138
1197
|
line_to(x1, y1)
|
@@ -1143,12 +1202,16 @@ module HexaPDF
|
|
1143
1202
|
#
|
1144
1203
|
# Moves the current point to (x0, y0) and appends line segments between all given
|
1145
1204
|
# 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.
|
1205
|
+
# so on. The last point becomes the new current point. Returns +self+.
|
1206
|
+
#
|
1207
|
+
# If there is no current path when the method is invoked, a new path is automatically begun.
|
1147
1208
|
#
|
1148
1209
|
# Examples:
|
1149
1210
|
#
|
1150
1211
|
# #>pdf
|
1151
1212
|
# canvas.polyline(50, 50, 150, 50, 150, 150, 50, 150, 50, 50).stroke
|
1213
|
+
#
|
1214
|
+
# See: #move_to, #line_to, #polygon
|
1152
1215
|
def polyline(*points)
|
1153
1216
|
check_poly_points(points)
|
1154
1217
|
move_to(points[0], points[1])
|
@@ -1163,8 +1226,8 @@ module HexaPDF
|
|
1163
1226
|
# :call-seq:
|
1164
1227
|
# canvas.polygon(x0, y0, x1, y1, x2, y2, ..., radius: 0) => canvas
|
1165
1228
|
#
|
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.
|
1229
|
+
# Appends a polygon consisting of the given points to the path as a complete subpath and
|
1230
|
+
# returns +self+. The point (x0, y0 + radius) becomes the new current point.
|
1168
1231
|
#
|
1169
1232
|
# If +radius+ is greater than 0, the corners are rounded with the given radius.
|
1170
1233
|
#
|
@@ -1174,8 +1237,10 @@ module HexaPDF
|
|
1174
1237
|
#
|
1175
1238
|
# #>pdf
|
1176
1239
|
# canvas.polygon(10, 10, 90, 10, 70, 90, 20, 100).stroke
|
1177
|
-
# canvas.stroke_color("
|
1240
|
+
# canvas.stroke_color("hp-blue").
|
1178
1241
|
# polygon(130, 130, 150, 100, 170, 150, 130, 190, radius: 10).stroke
|
1242
|
+
#
|
1243
|
+
# See: #polyline
|
1179
1244
|
def polygon(*points, radius: 0)
|
1180
1245
|
if radius == 0
|
1181
1246
|
polyline(*points)
|
@@ -1195,16 +1260,19 @@ module HexaPDF
|
|
1195
1260
|
#
|
1196
1261
|
# Appends a circle with center (cx, cy) and the given radius (in degrees) to the path as a
|
1197
1262
|
# complete subpath (drawn in counterclockwise direction). The point (center_x + radius,
|
1198
|
-
# center_y) becomes the new current point.
|
1263
|
+
# center_y) becomes the new current point. Returns +self+.
|
1199
1264
|
#
|
1200
1265
|
# If there is no current path when the method is invoked, a new path is automatically begun.
|
1201
1266
|
#
|
1202
1267
|
# Examples:
|
1203
1268
|
#
|
1204
1269
|
# #>pdf
|
1205
|
-
# canvas.circle(100, 100, 30)
|
1270
|
+
# canvas.circle(100, 100, 30)
|
1271
|
+
# cp = canvas.current_point
|
1272
|
+
# canvas.stroke
|
1273
|
+
# canvas.stroke_color("hp-orange").line(*cp, 180, 100).stroke
|
1206
1274
|
#
|
1207
|
-
# See: #arc (for approximation accuracy)
|
1275
|
+
# See: #arc (for approximation accuracy), #ellipse
|
1208
1276
|
def circle(cx, cy, radius)
|
1209
1277
|
arc(cx, cy, a: radius)
|
1210
1278
|
close_subpath
|
@@ -1215,7 +1283,8 @@ module HexaPDF
|
|
1215
1283
|
#
|
1216
1284
|
# Appends an ellipse with center (cx, cy), semi-major axis +a+, semi-minor axis +b+ and an
|
1217
1285
|
# 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.
|
1286
|
+
# outer-most point on the positive semi-major axis becomes the new current point. Returns
|
1287
|
+
# self.
|
1219
1288
|
#
|
1220
1289
|
# If there is no current path when the method is invoked, a new path is automatically begun.
|
1221
1290
|
#
|
@@ -1225,11 +1294,15 @@ module HexaPDF
|
|
1225
1294
|
# # Ellipse aligned to x-axis and y-axis
|
1226
1295
|
# canvas.ellipse(50, 50, a: 20, b: 10).stroke
|
1227
1296
|
#
|
1228
|
-
# # Inclined ellipse
|
1229
|
-
# canvas.stroke_color("
|
1230
|
-
# ellipse(150, 150, a: 20, b: 10, inclination: 30)
|
1297
|
+
# # Inclined ellipse with line from the end point
|
1298
|
+
# canvas.stroke_color("hp-blue").
|
1299
|
+
# ellipse(150, 150, a: 20, b: 10, inclination: 30)
|
1300
|
+
# cp = canvas.current_point
|
1301
|
+
# x, y = 2 * canvas.current_point[0] - 150, 2 * canvas.current_point[1] - 150
|
1302
|
+
# canvas.stroke.
|
1303
|
+
# stroke_color("hp-orange").line(*cp, x, y).stroke
|
1231
1304
|
#
|
1232
|
-
# See: #arc (for approximation accuracy)
|
1305
|
+
# See: #arc (for approximation accuracy), #circle
|
1233
1306
|
def ellipse(cx, cy, a:, b:, inclination: 0)
|
1234
1307
|
arc(cx, cy, a: a, b: b, inclination: inclination)
|
1235
1308
|
close_subpath
|
@@ -1238,8 +1311,8 @@ module HexaPDF
|
|
1238
1311
|
# :call-seq:
|
1239
1312
|
# canvas.arc(cx, cy, a:, b: a, start_angle: 0, end_angle: 360, clockwise: false, inclination: 0) => canvas
|
1240
1313
|
#
|
1241
|
-
# Appends an elliptical arc to the path
|
1242
|
-
# point.
|
1314
|
+
# Appends an elliptical arc to the path and returns +self+. The endpoint of the arc becomes
|
1315
|
+
# the new current point.
|
1243
1316
|
#
|
1244
1317
|
# +cx+::
|
1245
1318
|
# x-coordinate of the center point of the arc
|
@@ -1271,6 +1344,9 @@ module HexaPDF
|
|
1271
1344
|
#
|
1272
1345
|
# If there is no current path when the method is invoked, a new path is automatically begun.
|
1273
1346
|
#
|
1347
|
+
# This arc does *not* start from the current point (#current_point). If this functionality is
|
1348
|
+
# needed, use #draw together with GraphicObject::EndpointArc.
|
1349
|
+
#
|
1274
1350
|
# Since PDF doesn't have operators for drawing elliptical or circular arcs, they have to be
|
1275
1351
|
# approximated using Bezier curves (see #curve_to). The accuracy of the approximation can be
|
1276
1352
|
# controlled using the configuration option 'graphic_object.arc.max_curves'.
|
@@ -1284,19 +1360,19 @@ module HexaPDF
|
|
1284
1360
|
# canvas.stroke
|
1285
1361
|
#
|
1286
1362
|
# # Circular and elliptical arcs from 30 degrees to 160 degrees
|
1287
|
-
# canvas.stroke_color("
|
1363
|
+
# canvas.stroke_color("hp-blue")
|
1288
1364
|
# canvas.arc(50, 100, a: 10, start_angle: 30, end_angle: 160)
|
1289
1365
|
# canvas.arc(100, 100, a: 10, b: 5, start_angle: 30, end_angle: 160)
|
1290
1366
|
# canvas.stroke
|
1291
1367
|
#
|
1292
1368
|
# # Arcs from 135 degrees to 30 degrees, the first in counterclockwise direction (i.e. the
|
1293
1369
|
# # big arc), the other in clockwise direction (i.e. the small arc)
|
1294
|
-
# canvas.stroke_color("
|
1370
|
+
# canvas.stroke_color("hp-orange")
|
1295
1371
|
# canvas.arc(50, 50, a: 10, start_angle: 135, end_angle: 30)
|
1296
1372
|
# canvas.arc(100, 50, a: 10, start_angle: 135, end_angle: 30, clockwise: true)
|
1297
1373
|
# canvas.stroke
|
1298
1374
|
#
|
1299
|
-
# See:
|
1375
|
+
# See: #arc, #circle, #ellipse, GraphicObject::Arc, GraphicObject::EndpointArc
|
1300
1376
|
def arc(cx, cy, a:, b: a, start_angle: 0, end_angle: 360, clockwise: false, inclination: 0)
|
1301
1377
|
arc = GraphicObject::Arc.configure(cx: cx, cy: cy, a: a, b: b,
|
1302
1378
|
start_angle: start_angle, end_angle: end_angle,
|
@@ -1314,18 +1390,18 @@ module HexaPDF
|
|
1314
1390
|
# :call-seq:
|
1315
1391
|
# canvas.line_with_rounded_corner(x0 = current_point[0], y0 = current_point[1], x1, y1, x2, y2, in_radius:, out_radius: in_radius)
|
1316
1392
|
#
|
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.
|
1393
|
+
# Appends a line with a rounded corner at (x1, y1) from the current point and returns +self+.
|
1394
|
+
# The end point of the rounded corner (i.e. +out_radius+ units from (x1, y1) in the direction
|
1395
|
+
# of (x2, y2)) becomes the current point. In degraded cases the corner point (x1, y1) becomes
|
1396
|
+
# the current point.
|
1321
1397
|
#
|
1322
1398
|
# The corner is specified by (x0, y0) which defaults to the #current_point of the path, (x1,
|
1323
1399
|
# y1) and (x2, y2) - all of which need to be different points. The +in_radius+ specifies the
|
1324
1400
|
# corner radius into the corner and the +out_radius+ the one out of the corner. Degraded
|
1325
1401
|
# cases, like with (x0, y0) == (x1, y1), are handled gracefully.
|
1326
1402
|
#
|
1327
|
-
# There has to be a current path when this method is invoked
|
1328
|
-
#
|
1403
|
+
# There has to be a current path when this method is invoked, otherwise an error is raised.
|
1404
|
+
# For example, the current point could be estabilshed beforehand using #move_to.
|
1329
1405
|
#
|
1330
1406
|
# Examples:
|
1331
1407
|
#
|
@@ -1338,10 +1414,15 @@ module HexaPDF
|
|
1338
1414
|
# canvas.line_with_rounded_corner(180, 120, 150, 100, in_radius: 0, out_radius: 10)
|
1339
1415
|
# canvas.stroke
|
1340
1416
|
#
|
1341
|
-
# # Special effects when (x0, y0) is not the current point, like when the current
|
1342
|
-
# # would be equal to the corner point
|
1417
|
+
# # Special effects when (x0, y0) is not the current point, like when the current
|
1418
|
+
# # point would be equal to the corner point. Rounded rectangle use this method
|
1419
|
+
# # internally, as high-lighted by the blue segment.
|
1343
1420
|
# canvas.rectangle(10, 10, 60, 60, radius: 60).stroke
|
1344
|
-
# canvas.
|
1421
|
+
# canvas.stroke_color("hp-blue").
|
1422
|
+
# move_to(70, 10). # Start point at the end of the lower-left rounded corner
|
1423
|
+
# line_with_rounded_corner(10, 10, 70, 10, 70, 70, in_radius: 60).stroke
|
1424
|
+
# canvas.stroke_color("black").
|
1425
|
+
# rectangle(110, 10, 60, 60, radius: 70).stroke
|
1345
1426
|
def line_with_rounded_corner(x0 = current_point[0], y0 = current_point[1], x1, y1, x2, y2,
|
1346
1427
|
in_radius:, out_radius: in_radius)
|
1347
1428
|
if in_radius == 0 || out_radius == 0
|
@@ -1367,9 +1448,9 @@ module HexaPDF
|
|
1367
1448
|
#
|
1368
1449
|
# Returns the named graphic object, configured with the given options.
|
1369
1450
|
#
|
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.
|
1451
|
+
# If an object responding to :configure is given, it is used. Otherwise the graphic object is
|
1452
|
+
# looked up via the given name in the configuration option 'graphic_object.map'. Either way,
|
1453
|
+
# the graphic object is then configured with the given options if at least one is given.
|
1373
1454
|
#
|
1374
1455
|
# Examples:
|
1375
1456
|
#
|
@@ -1378,7 +1459,7 @@ module HexaPDF
|
|
1378
1459
|
# outer_a: 50, outer_b: 40, end_angle: 135)
|
1379
1460
|
# canvas.draw(obj).stroke
|
1380
1461
|
#
|
1381
|
-
# See:
|
1462
|
+
# See: #draw, GraphicObject
|
1382
1463
|
def graphic_object(obj, **options)
|
1383
1464
|
unless obj.respond_to?(:configure)
|
1384
1465
|
obj = context.document.config.constantize('graphic_object.map', obj)
|
@@ -1404,7 +1485,7 @@ module HexaPDF
|
|
1404
1485
|
# :call-seq:
|
1405
1486
|
# canvas.stroke => canvas
|
1406
1487
|
#
|
1407
|
-
# Strokes the path
|
1488
|
+
# Strokes the path and returns +self+.
|
1408
1489
|
#
|
1409
1490
|
# Examples:
|
1410
1491
|
#
|
@@ -1412,7 +1493,7 @@ module HexaPDF
|
|
1412
1493
|
# canvas.polyline(10, 10, 120, 40, 50, 160)
|
1413
1494
|
# canvas.stroke
|
1414
1495
|
#
|
1415
|
-
# See:
|
1496
|
+
# See: PDF2.0 s8.5.3.1, s8.5.3.2, #close_stroke, #close_fill_stroke
|
1416
1497
|
def stroke
|
1417
1498
|
raise_unless_in_path_or_clipping_path
|
1418
1499
|
invoke0(:S)
|
@@ -1422,7 +1503,7 @@ module HexaPDF
|
|
1422
1503
|
# :call-seq:
|
1423
1504
|
# canvas.close_stroke => canvas
|
1424
1505
|
#
|
1425
|
-
# Closes the last subpath and then strokes the path.
|
1506
|
+
# Closes the last subpath and then strokes the path. Returns +self+.
|
1426
1507
|
#
|
1427
1508
|
# Examples:
|
1428
1509
|
#
|
@@ -1430,7 +1511,7 @@ module HexaPDF
|
|
1430
1511
|
# canvas.polyline(10, 10, 120, 40, 50, 160) # No line from the top to the left
|
1431
1512
|
# canvas.close_stroke
|
1432
1513
|
#
|
1433
|
-
# See:
|
1514
|
+
# See: PDF2.0 s8.5.3.1, s8.5.3.2, #stroke, #close_fill_stroke
|
1434
1515
|
def close_stroke
|
1435
1516
|
raise_unless_in_path_or_clipping_path
|
1436
1517
|
invoke0(:s)
|
@@ -1440,25 +1521,26 @@ module HexaPDF
|
|
1440
1521
|
# :call-seq:
|
1441
1522
|
# canvas.fill(rule = :nonzero) => canvas
|
1442
1523
|
#
|
1443
|
-
# Fills the path using the given rule
|
1524
|
+
# Fills the path using the given rule and returns +self+.
|
1444
1525
|
#
|
1445
1526
|
# The argument +rule+ may either be +:nonzero+ to use the nonzero winding number rule or
|
1446
1527
|
# +: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
|
1528
|
+
# how these rules work are found in the PDF 2.0 spec section 8.5.3.3 or via Internet search.
|
1448
1529
|
#
|
1449
1530
|
# Any open subpaths are implicitly closed before being filled.
|
1450
1531
|
#
|
1451
1532
|
# Examples:
|
1452
1533
|
#
|
1453
1534
|
# #>pdf
|
1454
|
-
# canvas.
|
1455
|
-
#
|
1535
|
+
# canvas.fill_color("hp-blue").
|
1536
|
+
# polyline(20, 10, 90, 60, 10, 60, 80, 10, 50, 90).
|
1537
|
+
# fill
|
1456
1538
|
#
|
1457
|
-
# canvas.fill_color("
|
1458
|
-
#
|
1459
|
-
#
|
1539
|
+
# canvas.fill_color("hp-orange").
|
1540
|
+
# polyline(120, 110, 190, 160, 110, 160, 180, 110, 150, 190).
|
1541
|
+
# fill(:even_odd)
|
1460
1542
|
#
|
1461
|
-
# See:
|
1543
|
+
# See: PDF2.0 s8.5.3.1, s8.5.3.3, #fill_stroke, #close_fill_stroke
|
1462
1544
|
def fill(rule = :nonzero)
|
1463
1545
|
raise_unless_in_path_or_clipping_path
|
1464
1546
|
invoke0(rule == :nonzero ? :f : :'f*')
|
@@ -1468,26 +1550,27 @@ module HexaPDF
|
|
1468
1550
|
# :call-seq:
|
1469
1551
|
# canvas.fill_stroke(rule = :nonzero) => canvas
|
1470
1552
|
#
|
1471
|
-
# Fills and then strokes the path using the given rule.
|
1553
|
+
# Fills and then strokes the path using the given rule. Returns +self+.
|
1472
1554
|
#
|
1473
1555
|
# The argument +rule+ may either be +:nonzero+ to use the nonzero winding number rule or
|
1474
1556
|
# +: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
|
1557
|
+
# how these rules work are found in the PDF 2.0 spec section 8.5.3.3 or via Internet search.
|
1476
1558
|
#
|
1477
|
-
# Note that any open subpaths are *not* closed
|
1559
|
+
# Note that any open subpaths are *not* closed concerning the stroking operation.
|
1478
1560
|
#
|
1479
1561
|
# Examples:
|
1480
1562
|
#
|
1481
1563
|
# #>pdf
|
1482
|
-
# canvas.stroke_color("
|
1483
|
-
# canvas.
|
1484
|
-
#
|
1564
|
+
# canvas.stroke_color("hp-orange").line_width(3)
|
1565
|
+
# canvas.fill_color("hp-blue").
|
1566
|
+
# polyline(20, 10, 90, 60, 10, 60, 80, 10, 50, 90).
|
1567
|
+
# fill_stroke # Note the missing stroke from the top corner
|
1485
1568
|
#
|
1486
|
-
# canvas.fill_color("
|
1487
|
-
#
|
1488
|
-
#
|
1569
|
+
# canvas.fill_color("hp-teal").
|
1570
|
+
# polyline(120, 110, 190, 160, 110, 160, 180, 110, 150, 190).
|
1571
|
+
# fill_stroke(:even_odd) # Note the missing stroke from the top corner
|
1489
1572
|
#
|
1490
|
-
# See:
|
1573
|
+
# See: PDF2.0 s8.5.3.1, s8.5.3.3, #fill, #close_fill_stroke
|
1491
1574
|
def fill_stroke(rule = :nonzero)
|
1492
1575
|
raise_unless_in_path_or_clipping_path
|
1493
1576
|
invoke0(rule == :nonzero ? :B : :'B*')
|
@@ -1497,24 +1580,26 @@ module HexaPDF
|
|
1497
1580
|
# :call-seq:
|
1498
1581
|
# canvas.close_fill_stroke(rule = :nonzero) => canvas
|
1499
1582
|
#
|
1500
|
-
# Closes the last subpath and then fills and strokes the path using the given rule.
|
1583
|
+
# Closes the last subpath and then fills and strokes the path using the given rule. Returns
|
1584
|
+
# +self+.
|
1501
1585
|
#
|
1502
1586
|
# The argument +rule+ may either be +:nonzero+ to use the nonzero winding number rule or
|
1503
1587
|
# +: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
|
1588
|
+
# how these rules work are found in the PDF 2.0 spec section 8.5.3.3 or via Internet search.
|
1505
1589
|
#
|
1506
1590
|
# Examples:
|
1507
1591
|
#
|
1508
1592
|
# #>pdf
|
1509
|
-
# canvas.stroke_color("
|
1510
|
-
# canvas.
|
1511
|
-
#
|
1593
|
+
# canvas.stroke_color("hp-orange").line_width(3)
|
1594
|
+
# canvas.fill_color("hp-blue").
|
1595
|
+
# polyline(20, 10, 90, 60, 10, 60, 80, 10, 50, 90).
|
1596
|
+
# close_fill_stroke
|
1512
1597
|
#
|
1513
|
-
# canvas.fill_color("
|
1514
|
-
#
|
1515
|
-
#
|
1598
|
+
# canvas.fill_color("hp-teal").
|
1599
|
+
# polyline(120, 110, 190, 160, 110, 160, 180, 110, 150, 190).
|
1600
|
+
# close_fill_stroke(:even_odd)
|
1516
1601
|
#
|
1517
|
-
# See:
|
1602
|
+
# See: PDF2.0 s8.5.3, #fill, #fill_stroke
|
1518
1603
|
def close_fill_stroke(rule = :nonzero)
|
1519
1604
|
raise_unless_in_path_or_clipping_path
|
1520
1605
|
invoke0(rule == :nonzero ? :b : :'b*')
|
@@ -1524,17 +1609,17 @@ module HexaPDF
|
|
1524
1609
|
# :call-seq:
|
1525
1610
|
# canvas.end_path => canvas
|
1526
1611
|
#
|
1527
|
-
# Ends the path without stroking or filling it
|
1612
|
+
# Ends the path without stroking or filling it and returns +self+.
|
1528
1613
|
#
|
1529
|
-
# This method is
|
1530
|
-
# clipping.
|
1614
|
+
# This method is usually used in conjunction with the clipping path methods to define the
|
1615
|
+
# clipping path.
|
1531
1616
|
#
|
1532
1617
|
# Examples:
|
1533
1618
|
#
|
1534
1619
|
# canvas.line(10, 10, 100, 100)
|
1535
1620
|
# canvas.end_path # Nothing to see here!
|
1536
1621
|
#
|
1537
|
-
# See:
|
1622
|
+
# See: PDF2.0 s8.5.3.1, #clip_path
|
1538
1623
|
def end_path
|
1539
1624
|
raise_unless_in_path_or_clipping_path
|
1540
1625
|
invoke0(:n)
|
@@ -1544,11 +1629,11 @@ module HexaPDF
|
|
1544
1629
|
# :call-seq:
|
1545
1630
|
# canvas.clip_path(rule = :nonzero) => canvas
|
1546
1631
|
#
|
1547
|
-
# Modifies the clipping path by intersecting it with the current path.
|
1632
|
+
# Modifies the clipping path by intersecting it with the current path. Returns +self+.
|
1548
1633
|
#
|
1549
1634
|
# The argument +rule+ may either be +:nonzero+ to use the nonzero winding number rule or
|
1550
1635
|
# +: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
|
1636
|
+
# path. Details on how these rules work are found in the PDF 2.0 spec section 8.5.3.3 or via
|
1552
1637
|
# Internet search.
|
1553
1638
|
#
|
1554
1639
|
# The initial clipping path includes the entire canvas. Once the clipping path is reduced to a
|
@@ -1566,7 +1651,7 @@ module HexaPDF
|
|
1566
1651
|
# clip_path(:even_odd).end_path
|
1567
1652
|
# canvas.rectangle(0, 0, 200, 200).fill # Fills everything inside the clipping path
|
1568
1653
|
#
|
1569
|
-
# See:
|
1654
|
+
# See: PDF2.0 s8.5.4, #end_path
|
1570
1655
|
def clip_path(rule = :nonzero)
|
1571
1656
|
raise_unless_in_path
|
1572
1657
|
invoke0(rule == :nonzero ? :W : :'W*')
|
@@ -1583,8 +1668,8 @@ module HexaPDF
|
|
1583
1668
|
# position and returns the XObject.
|
1584
1669
|
#
|
1585
1670
|
# 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.
|
1671
|
+
# the configuration option 'image_loader' can be used. PNG (lossless), JPEG (lossy) and PDF
|
1672
|
+
# (vector) images are supported out of the box.
|
1588
1673
|
#
|
1589
1674
|
# If the filename or the IO specifies a PDF file, the first page of this file is used to
|
1590
1675
|
# create a form XObject which is then drawn.
|
@@ -1608,18 +1693,18 @@ module HexaPDF
|
|
1608
1693
|
# #>pdf
|
1609
1694
|
# canvas.xobject(machu_picchu, at: [10, 10], width: 90) # bottom left
|
1610
1695
|
#
|
1611
|
-
# file = File.new(machu_picchu, 'rb')
|
1696
|
+
# file = File.new(machu_picchu, 'rb') # top left
|
1612
1697
|
# canvas.xobject(file, at: [10, 110], height: 50)
|
1613
1698
|
#
|
1614
1699
|
# image = doc.images.add(machu_picchu)
|
1615
1700
|
# canvas.xobject(image, at: [110, 10], width: 50, height: 90) # bottom right
|
1616
1701
|
#
|
1617
1702
|
# form = doc.add({Type: :XObject, Subtype: :Form, BBox: [0, 0, 100, 100]})
|
1618
|
-
# form.canvas.line(10, 10, 90, 90).stroke
|
1703
|
+
# form.canvas.stroke_color("hp-blue").line(10, 10, 90, 90).stroke
|
1619
1704
|
# canvas.line_width = 20
|
1620
1705
|
# canvas.xobject(form, at: [100, 100]) # top right
|
1621
1706
|
#
|
1622
|
-
# See:
|
1707
|
+
# See: PDF2.0 s8.8, s.8.10.1, HexaPDF::Type::Image, HexaPDF::Type::Form, HexaPDF::ImageLoader
|
1623
1708
|
def xobject(obj, at:, width: nil, height: nil)
|
1624
1709
|
unless obj.kind_of?(HexaPDF::Stream)
|
1625
1710
|
obj = context.document.images.add(obj)
|
@@ -1653,14 +1738,18 @@ module HexaPDF
|
|
1653
1738
|
# canvas.character_spacing(amount) => canvas
|
1654
1739
|
# canvas.character_spacing(amount) { block } => canvas
|
1655
1740
|
#
|
1656
|
-
# The character spacing determines how much additional space is added
|
1657
|
-
#
|
1658
|
-
# between two characters, whereas for vertical writing negative values increase the
|
1741
|
+
# The character spacing determines how much additional space is added after each character
|
1742
|
+
# (or, more correctly, after each glyph). For horizontal writing positive values increase the
|
1743
|
+
# distance between two characters, whereas for vertical writing negative values increase the
|
1659
1744
|
# distance.
|
1660
1745
|
#
|
1661
|
-
#
|
1662
|
-
#
|
1663
|
-
#
|
1746
|
+
# Note that the character spacing is applied to all characters that are rendered. This has the
|
1747
|
+
# effect that there is also a space after the last character which might not be wanted in
|
1748
|
+
# certain cases (e.g. when justifying text).
|
1749
|
+
#
|
1750
|
+
# Returns the current character spacing value (see GraphicsState#character_spacing) when no
|
1751
|
+
# argument is given. Otherwise sets the character spacing using the +amount+ argument and
|
1752
|
+
# returns +self+. The setter version can also be called in the character_spacing= form.
|
1664
1753
|
#
|
1665
1754
|
# If the +amount+ and a block are provided, the changed character spacing is only active
|
1666
1755
|
# during the block by saving and restoring the graphics state.
|
@@ -1680,11 +1769,18 @@ module HexaPDF
|
|
1680
1769
|
# # visual example
|
1681
1770
|
# canvas.font("Helvetica", size: 10)
|
1682
1771
|
# canvas.character_spacing = 0 # initial value
|
1683
|
-
# canvas.text("This is an example
|
1684
|
-
#
|
1685
|
-
#
|
1686
|
-
#
|
1687
|
-
#
|
1772
|
+
# canvas.text("This is an example", at: [10, 150])
|
1773
|
+
# # show that the text cursor is directly after the last glyph
|
1774
|
+
# x, y = canvas.text_cursor
|
1775
|
+
# canvas.stroke_color("hp-blue").line(x, y, x, y + 10).stroke
|
1776
|
+
#
|
1777
|
+
# canvas.character_spacing = 5
|
1778
|
+
# canvas.text("This is an example", at: [10, 100])
|
1779
|
+
# # visualize the spacing after the last glyph
|
1780
|
+
# x, y = canvas.text_cursor
|
1781
|
+
# canvas.stroke_color("hp-blue").line(x, y, x, y + 10).stroke
|
1782
|
+
#
|
1783
|
+
# See: PDF2.0 s9.3.2, #word_spacing, #horizontal_scaling
|
1688
1784
|
def character_spacing(amount = nil, &bk)
|
1689
1785
|
gs_getter_setter(:character_spacing, :Tc, amount, &bk)
|
1690
1786
|
end
|
@@ -1703,9 +1799,9 @@ module HexaPDF
|
|
1703
1799
|
# *Important*: In HexaPDF only the standard 14 PDF Type1 fonts support this property! When
|
1704
1800
|
# using any other font, for example a TrueType font, this property has no effect.
|
1705
1801
|
#
|
1706
|
-
# Returns the current word spacing value (see
|
1707
|
-
#
|
1708
|
-
#
|
1802
|
+
# Returns the current word spacing value (see GraphicsState#word_spacing) when no argument is
|
1803
|
+
# given. Otherwise sets the word spacing using the +amount+ argument and returns +self+. The
|
1804
|
+
# setter version can also be called in the word_spacing= form.
|
1709
1805
|
#
|
1710
1806
|
# If the +amount+ and a block are provided, the changed word spacing is only active during
|
1711
1807
|
# the block by saving and restoring the graphics state.
|
@@ -1729,7 +1825,7 @@ module HexaPDF
|
|
1729
1825
|
# canvas.word_spacing = 10
|
1730
1826
|
# canvas.text("This is an example text.", at: [10, 100])
|
1731
1827
|
#
|
1732
|
-
# See:
|
1828
|
+
# See: PDF2.0 s9.3.3, #character_spacing, #horizontal_scaling
|
1733
1829
|
def word_spacing(amount = nil, &bk)
|
1734
1830
|
gs_getter_setter(:word_spacing, :Tw, amount, &bk)
|
1735
1831
|
end
|
@@ -1744,10 +1840,9 @@ module HexaPDF
|
|
1744
1840
|
# compressing them in the horizontal direction. The value is specified as percent of the
|
1745
1841
|
# normal width, so 100 means no scaling.
|
1746
1842
|
#
|
1747
|
-
# Returns the current horizontal scaling value (see
|
1748
|
-
#
|
1749
|
-
#
|
1750
|
-
# form.
|
1843
|
+
# Returns the current horizontal scaling value (see GraphicsState#horizontal_scaling) when no
|
1844
|
+
# argument is given. Otherwise sets the horizontal scaling using the +percent+ argument and
|
1845
|
+
# returns +self+. The setter version can also be called in the horizontal_scaling= form.
|
1751
1846
|
#
|
1752
1847
|
# If the +percent+ and a block are provided, the changed horizontal scaling is only active
|
1753
1848
|
# during the block by saving and restoring the graphics state.
|
@@ -1771,7 +1866,7 @@ module HexaPDF
|
|
1771
1866
|
# canvas.horizontal_scaling = 50
|
1772
1867
|
# canvas.text("This is an example text.", at: [10, 100])
|
1773
1868
|
#
|
1774
|
-
# See:
|
1869
|
+
# See: PDF2.0 s9.3.4, #character_spacing, #word_spacing
|
1775
1870
|
def horizontal_scaling(amount = nil, &bk)
|
1776
1871
|
gs_getter_setter(:horizontal_scaling, :Tz, amount, &bk)
|
1777
1872
|
end
|
@@ -1789,8 +1884,8 @@ module HexaPDF
|
|
1789
1884
|
# There are other PDF content stream operators that would be effected but those are not used
|
1790
1885
|
# by the canvas.
|
1791
1886
|
#
|
1792
|
-
# Returns the current leading value (see
|
1793
|
-
#
|
1887
|
+
# Returns the current leading value (see GraphicsState#leading) when no argument is given.
|
1888
|
+
# Otherwise sets the leading using the +amount+ argument and returns +self+. The setter
|
1794
1889
|
# version can also be called in the leading= form.
|
1795
1890
|
#
|
1796
1891
|
# If the +amount+ and a block are provided, the changed leading is only active during the
|
@@ -1813,7 +1908,7 @@ module HexaPDF
|
|
1813
1908
|
# canvas.leading = 15
|
1814
1909
|
# canvas.text("This is an example text.\nwith a second\nand thrid line", at: [10, 150])
|
1815
1910
|
#
|
1816
|
-
# See:
|
1911
|
+
# See: PDF2.0 s9.3.5, #move_text_cursor
|
1817
1912
|
def leading(amount = nil, &bk)
|
1818
1913
|
gs_getter_setter(:leading, :TL, amount, &bk)
|
1819
1914
|
end
|
@@ -1824,16 +1919,33 @@ module HexaPDF
|
|
1824
1919
|
# canvas.text_rendering_mode(mode) => canvas
|
1825
1920
|
# canvas.text_rendering_mode(mode) { block } => canvas
|
1826
1921
|
#
|
1827
|
-
# The text rendering mode determines if and how glyphs are rendered.
|
1828
|
-
#
|
1829
|
-
#
|
1830
|
-
#
|
1831
|
-
#
|
1832
|
-
#
|
1833
|
-
#
|
1834
|
-
#
|
1835
|
-
#
|
1836
|
-
#
|
1922
|
+
# The text rendering mode determines if and how glyphs are rendered.
|
1923
|
+
#
|
1924
|
+
# The +mode+ parameter can be one of the following (also see TextRenderingMode):
|
1925
|
+
#
|
1926
|
+
# :fill or 0::
|
1927
|
+
# The text is filled (default)
|
1928
|
+
# :stroke or 1::
|
1929
|
+
# The text is stroked.
|
1930
|
+
# :fill_stroke or 2::
|
1931
|
+
# The test is filled, then stroked.
|
1932
|
+
# :invisible or 3::
|
1933
|
+
# The text is neither filled nor stroked.
|
1934
|
+
# :fill_clip or 4::
|
1935
|
+
# The text is filled and added to the clipping path.
|
1936
|
+
# :stroke_clip or 5::
|
1937
|
+
# The text is stroked and added to the clipping path.
|
1938
|
+
# :fill_stroke_clip or 6::
|
1939
|
+
# The text is filled, then stroked and added to the clipping path.
|
1940
|
+
# :clip or 7::
|
1941
|
+
# The text is added to the clipping path.
|
1942
|
+
# either be a valid integer or one of the symbols +:fill+, +:stroke+,
|
1943
|
+
#
|
1944
|
+
# Note that the return value is always a normalized text rendering mode value.
|
1945
|
+
#
|
1946
|
+
# Returns the current text rendering mode value (see GraphicsState#text_rendering_mode) when
|
1947
|
+
# no argument is given. Otherwise sets the text rendering mode using the +mode+ argument and
|
1948
|
+
# returns +self+. The setter version can also be called in the text_rendering_mode= form.
|
1837
1949
|
#
|
1838
1950
|
# If the +mode+ and a block are provided, the changed text rendering mode is only active
|
1839
1951
|
# during the block by saving and restoring the graphics state.
|
@@ -1858,7 +1970,7 @@ module HexaPDF
|
|
1858
1970
|
# canvas.text("#{trm} text.", at: [20, 150 - 30 * index])
|
1859
1971
|
# end
|
1860
1972
|
#
|
1861
|
-
# See:
|
1973
|
+
# See: PDF2.0 s9.3.6, GraphicsState::TextRenderingMode
|
1862
1974
|
def text_rendering_mode(m = nil, &bk)
|
1863
1975
|
gs_getter_setter(:text_rendering_mode, :Tr, m && TextRenderingMode.normalize(m), &bk)
|
1864
1976
|
end
|
@@ -1872,9 +1984,9 @@ module HexaPDF
|
|
1872
1984
|
# The text rise specifies the vertical distance to move the baseline up or down from its
|
1873
1985
|
# default location. Positive values move the baseline up, negative values down.
|
1874
1986
|
#
|
1875
|
-
# Returns the current text rise value (see
|
1876
|
-
#
|
1877
|
-
#
|
1987
|
+
# Returns the current text rise value (see GraphicsState#text_rise) when no argument is given.
|
1988
|
+
# Otherwise sets the text rise using the +amount+ argument and returns +self+. The setter
|
1989
|
+
# version can also be called in the text_rise= form.
|
1878
1990
|
#
|
1879
1991
|
# If the +amount+ and a block are provided, the changed text rise is only active during the
|
1880
1992
|
# block by saving and restoring the graphics state.
|
@@ -1900,7 +2012,7 @@ module HexaPDF
|
|
1900
2012
|
# canvas.text_rise = -10
|
1901
2013
|
# canvas.text("and also down here")
|
1902
2014
|
#
|
1903
|
-
# See:
|
2015
|
+
# See: PDF2.0 s9.3.7
|
1904
2016
|
def text_rise(amount = nil, &bk)
|
1905
2017
|
gs_getter_setter(:text_rise, :Ts, amount, &bk)
|
1906
2018
|
end
|
@@ -1909,7 +2021,7 @@ module HexaPDF
|
|
1909
2021
|
# :call-seq:
|
1910
2022
|
# canvas.begin_text(force_new: false) -> canvas
|
1911
2023
|
#
|
1912
|
-
# Begins a new text object
|
2024
|
+
# Begins a new text object and returns +self+.
|
1913
2025
|
#
|
1914
2026
|
# If +force+ is +true+ and the current graphics object is already a text object, it is ended
|
1915
2027
|
# and a new text object is begun.
|
@@ -1917,7 +2029,7 @@ module HexaPDF
|
|
1917
2029
|
# It is not necessary to invoke this method manually in most cases since it is automatically
|
1918
2030
|
# called when needed by other methods, i.e. the #text method.
|
1919
2031
|
#
|
1920
|
-
# See:
|
2032
|
+
# See: PDF2.0 s9.4.1, #end_text, #text
|
1921
2033
|
def begin_text(force_new: false)
|
1922
2034
|
raise_unless_at_page_description_level_or_in_text
|
1923
2035
|
end_text if force_new
|
@@ -1928,12 +2040,12 @@ module HexaPDF
|
|
1928
2040
|
# :call-seq:
|
1929
2041
|
# canvas.end_text -> canvas
|
1930
2042
|
#
|
1931
|
-
# Ends the current text object
|
2043
|
+
# Ends the current text object and returns +self+.
|
1932
2044
|
#
|
1933
2045
|
# It is not necessary to invoke this method manually in most cases since it is automatically
|
1934
2046
|
# called when needed by other methods, i.e. when creating a new path.
|
1935
2047
|
#
|
1936
|
-
# See:
|
2048
|
+
# See: PDF2.0 s9.4.1, #begin_text
|
1937
2049
|
def end_text
|
1938
2050
|
raise_unless_at_page_description_level_or_in_text
|
1939
2051
|
invoke0(:ET) if graphics_object == :text
|
@@ -1943,7 +2055,12 @@ module HexaPDF
|
|
1943
2055
|
# :call-seq:
|
1944
2056
|
# canvas.text_matrix(a, b, c, d, e, f) => canvas
|
1945
2057
|
#
|
1946
|
-
# Sets the text matrix (and the text line matrix) to the given matrix and returns self
|
2058
|
+
# Sets the text matrix (and the text line matrix) to the given matrix and returns +self+.
|
2059
|
+
#
|
2060
|
+
# The text matrix determines where and how the glyphs are rendered. The most common use is to
|
2061
|
+
# translate the text space origin since the text drawing operations always use the text space
|
2062
|
+
# origin as starting point for drawing the glyphs. This translation operation can more easily
|
2063
|
+
# be specified using #move_text_cursor.
|
1947
2064
|
#
|
1948
2065
|
# The given values are interpreted as a matrix in the following way:
|
1949
2066
|
#
|
@@ -1965,7 +2082,7 @@ module HexaPDF
|
|
1965
2082
|
# canvas.text_matrix(2, 1, 3, 0.5, 50, 50)
|
1966
2083
|
# canvas.text("This is some text")
|
1967
2084
|
#
|
1968
|
-
# See:
|
2085
|
+
# See: PDF2.0 s9.4.2, #move_text_cursor, #text_cursor
|
1969
2086
|
def text_matrix(a, b, c, d, e, f)
|
1970
2087
|
begin_text
|
1971
2088
|
invoke(:Tm, a, b, c, d, e, f)
|
@@ -1975,7 +2092,7 @@ module HexaPDF
|
|
1975
2092
|
# :call-seq:
|
1976
2093
|
# canvas.move_text_cursor(offset: nil, absolute: true) -> canvas
|
1977
2094
|
#
|
1978
|
-
# Moves the text cursor by modifying the text and text line matrices.
|
2095
|
+
# Moves the text cursor by modifying the text and text line matrices. Returns +self+.
|
1979
2096
|
#
|
1980
2097
|
# If +offset+ is not specified, the text cursor is moved to the start of the next text line
|
1981
2098
|
# using #leading as vertical offset.
|
@@ -2010,7 +2127,7 @@ module HexaPDF
|
|
2010
2127
|
# canvas.move_text_cursor
|
2011
2128
|
# canvas.text("Text on next line with leading=30")
|
2012
2129
|
#
|
2013
|
-
# See:
|
2130
|
+
# See: PDF2.0 s9.4.2, #leading, #text_cursor, #text, #show_glyphs
|
2014
2131
|
def move_text_cursor(offset: nil, absolute: true)
|
2015
2132
|
begin_text
|
2016
2133
|
if offset
|
@@ -2028,7 +2145,8 @@ module HexaPDF
|
|
2028
2145
|
# :call-seq:
|
2029
2146
|
# canvas.text_cursor -> [x, y]
|
2030
2147
|
#
|
2031
|
-
# Returns the position of the text cursor, i.e. the origin of
|
2148
|
+
# Returns the position of the text cursor, i.e. the origin of text space. This is where the
|
2149
|
+
# first glyph of the next drawn text will be placed.
|
2032
2150
|
#
|
2033
2151
|
# Note that this method can only be called while the current graphic object is a text object
|
2034
2152
|
# since the text matrix is otherwise undefined.
|
@@ -2038,10 +2156,11 @@ module HexaPDF
|
|
2038
2156
|
# #>pdf
|
2039
2157
|
# canvas.font("Helvetica", size: 10)
|
2040
2158
|
# canvas.text("Some sample text", at: [30, 150])
|
2041
|
-
#
|
2042
|
-
# canvas.
|
2043
|
-
#
|
2044
|
-
#
|
2159
|
+
# tx, ty = canvas.text_cursor # Cursor is directly after the text
|
2160
|
+
# canvas.stroke_color("hp-blue").
|
2161
|
+
# circle(tx, ty, 0.5).
|
2162
|
+
# circle(tx, ty, 5).stroke
|
2163
|
+
# canvas.text("Last cursor: (#{tx.round(2)}, #{ty.round(2)})", at: [30, 100])
|
2045
2164
|
#
|
2046
2165
|
# See: #move_text_cursor
|
2047
2166
|
def text_cursor
|
@@ -2055,7 +2174,7 @@ module HexaPDF
|
|
2055
2174
|
#
|
2056
2175
|
# Specifies the font and optional the font size that should be used when showing text.
|
2057
2176
|
#
|
2058
|
-
# A valid font size
|
2177
|
+
# A valid font size needs to be provided on the first invocation, otherwise an error is raised
|
2059
2178
|
# (this is due to how setting a font works with PDFs).
|
2060
2179
|
#
|
2061
2180
|
# If +size+ is specified, the #font_size method is invoked with it as argument.
|
@@ -2065,8 +2184,9 @@ module HexaPDF
|
|
2065
2184
|
# specifies the font variant to use, with standard values of :none, :italic, :bold and
|
2066
2185
|
# :bold_italic.
|
2067
2186
|
#
|
2068
|
-
# Returns the current font object when no argument is given
|
2069
|
-
# object itself, not the PDF dictionary representing the font
|
2187
|
+
# Returns the current font object when no argument is given, otherwise returns +self+. *Note*
|
2188
|
+
# that this is the font object itself, not the PDF dictionary representing the font that is
|
2189
|
+
# stored in the resources.
|
2070
2190
|
#
|
2071
2191
|
# Examples:
|
2072
2192
|
#
|
@@ -2080,7 +2200,7 @@ module HexaPDF
|
|
2080
2200
|
# canvas.font("Times", variant: :bold_italic, size: 15)
|
2081
2201
|
# canvas.text("Times bold+italic at size 15", at: [10, 100])
|
2082
2202
|
#
|
2083
|
-
# See:
|
2203
|
+
# See: PDF2.0 s9.2.2, #font_size, #text
|
2084
2204
|
def font(name = nil, size: nil, **options)
|
2085
2205
|
if name
|
2086
2206
|
@font = (name.respond_to?(:pdf_object) ? name : context.document.fonts.add(name, **options))
|
@@ -2099,16 +2219,16 @@ module HexaPDF
|
|
2099
2219
|
alias font= font
|
2100
2220
|
|
2101
2221
|
# :call-seq:
|
2102
|
-
# canvas.font_size
|
2103
|
-
# canvas.font_size(size => canvas
|
2222
|
+
# canvas.font_size => font_size
|
2223
|
+
# canvas.font_size(size) => canvas
|
2104
2224
|
#
|
2105
2225
|
# Specifies the font size.
|
2106
2226
|
#
|
2107
2227
|
# Note that an error is raised if no font has been set before via #font (this is due to how
|
2108
2228
|
# setting font and font size works in PDF).
|
2109
2229
|
#
|
2110
|
-
# Returns the current font size when no argument is given
|
2111
|
-
# be called in the font_size= form.
|
2230
|
+
# Returns the current font size when no argument is given, otherwise returns +self+. The
|
2231
|
+
# setter version can also be called in the font_size= form.
|
2112
2232
|
#
|
2113
2233
|
# Examples:
|
2114
2234
|
#
|
@@ -2124,7 +2244,7 @@ module HexaPDF
|
|
2124
2244
|
# canvas.text("Text in size #{size}", at: [15, 180 - index * 20])
|
2125
2245
|
# end
|
2126
2246
|
#
|
2127
|
-
# See:
|
2247
|
+
# See: PDF2.0 s9.2.2, #font, #text
|
2128
2248
|
def font_size(size = nil)
|
2129
2249
|
if size
|
2130
2250
|
unless @font
|
@@ -2142,7 +2262,7 @@ module HexaPDF
|
|
2142
2262
|
# canvas.text(text) -> canvas
|
2143
2263
|
# canvas.text(text, at: [x, y]) -> canvas
|
2144
2264
|
#
|
2145
|
-
# Shows the given text string, either at the current or the provided position.
|
2265
|
+
# Shows the given text string, either at the current or the provided position. Returns +self+.
|
2146
2266
|
#
|
2147
2267
|
# If no position is provided, the text is positioned at the current position of the text
|
2148
2268
|
# cursor (see #text_cursor).
|
@@ -2152,21 +2272,24 @@ module HexaPDF
|
|
2152
2272
|
# equal to the font size will be set..
|
2153
2273
|
#
|
2154
2274
|
# Note that there are no provisions to make sure that all text is visible! So if the text
|
2155
|
-
# string is too long, it
|
2275
|
+
# string is too long, it may be outside the cropped page and be cut off.
|
2156
2276
|
#
|
2157
2277
|
# Examples:
|
2158
2278
|
#
|
2159
2279
|
# #>pdf
|
2160
2280
|
# canvas.font('Times', size: 12)
|
2161
|
-
#
|
2162
|
-
# canvas.text("
|
2281
|
+
# # Sets leading=12 because mulitple lines are drawn
|
2282
|
+
# canvas.text("This is a \n multiline text", at: [15, 150])
|
2283
|
+
# # Starts right after the last text
|
2284
|
+
# canvas.text(". Some more text\nafter the newline.")
|
2163
2285
|
#
|
2164
|
-
# See: #leading,
|
2286
|
+
# See: #leading, #font, #font_size, #show_glyphs,
|
2287
|
+
# http://www.unicode.org/reports/tr18/#Line_Boundaries
|
2165
2288
|
def text(text, at: nil)
|
2166
2289
|
raise_unless_font_set
|
2167
2290
|
move_text_cursor(offset: at) if at
|
2168
|
-
leading(font_size) if leading == 0
|
2169
2291
|
lines = text.split(/\u{D A}|(?!\u{D A})[\u{A}-\u{D}\u{85}\u{2028}\u{2029}]/, -1)
|
2292
|
+
leading(font_size) if leading == 0 && lines.length > 1
|
2170
2293
|
lines.each_with_index do |str, index|
|
2171
2294
|
show_glyphs(@font.decode_utf8(str))
|
2172
2295
|
move_text_cursor unless index == lines.length - 1
|
@@ -2177,7 +2300,7 @@ module HexaPDF
|
|
2177
2300
|
# :call-seq:
|
2178
2301
|
# canvas.show_glyphs(glyphs) -> canvas
|
2179
2302
|
#
|
2180
|
-
# Low-level method for actually showing text on the canvas.
|
2303
|
+
# Low-level method for actually showing text on the canvas. Returns +self+.
|
2181
2304
|
#
|
2182
2305
|
# The argument +glyphs+ needs to be a an array of glyph objects valid for the current font,
|
2183
2306
|
# optionally interspersed with numbers for kerning.
|
@@ -2200,6 +2323,8 @@ module HexaPDF
|
|
2200
2323
|
# canvas.move_text_cursor(offset: [15, 100])
|
2201
2324
|
# canvas.show_glyphs(glyphs)
|
2202
2325
|
# canvas.text(canvas.text_cursor.map(&:to_i).join(", "), at: [15, 80])
|
2326
|
+
#
|
2327
|
+
# See: #text, #text_cursor, #text_matrix, #move_text_cursor, #show_glyphs_only
|
2203
2328
|
def show_glyphs(glyphs)
|
2204
2329
|
return if glyphs.empty?
|
2205
2330
|
raise_unless_font_set
|
@@ -2269,7 +2394,7 @@ module HexaPDF
|
|
2269
2394
|
# :call-seq:
|
2270
2395
|
# canvas.marked_content_point(tag, property_list: nil) -> canvas
|
2271
2396
|
#
|
2272
|
-
# Inserts a marked-content point, optionally associated with a property list.
|
2397
|
+
# Inserts a marked-content point, optionally associated with a property list. Returns +self+.
|
2273
2398
|
#
|
2274
2399
|
# A marked-content point is used to identify a position in the content stream for later use by
|
2275
2400
|
# other applications. The symbol +tag+ is used to uniquely identify the role of the
|
@@ -2284,7 +2409,7 @@ module HexaPDF
|
|
2284
2409
|
# canvas.marked_content_point(:Divider)
|
2285
2410
|
# canvas.marked_content_point(:Divider, property_list: {Key: 'value'})
|
2286
2411
|
#
|
2287
|
-
# See:
|
2412
|
+
# See: PDF2.0 s14.6, #marked_content_sequence, #end_marked_content_sequence
|
2288
2413
|
def marked_content_point(tag, property_list: nil)
|
2289
2414
|
raise_unless_at_page_description_level_or_in_text
|
2290
2415
|
if property_list
|
@@ -2300,7 +2425,8 @@ module HexaPDF
|
|
2300
2425
|
# canvas.marked_content_sequence(tag, property_list: nil) -> canvas
|
2301
2426
|
# canvas.marked_content_sequence(tag, property_list: nil) { block } -> canvas
|
2302
2427
|
#
|
2303
|
-
# Inserts a marked-content sequence, optionally associated with a property list.
|
2428
|
+
# Inserts a marked-content sequence, optionally associated with a property list. Returns
|
2429
|
+
# +self+.
|
2304
2430
|
#
|
2305
2431
|
# A marked-content sequence is used to identify a sequence of complete graphics objects in the
|
2306
2432
|
# content stream for later use by other applications, e.g. for tagged PDF. The symbol +tag+ is
|
@@ -2327,7 +2453,7 @@ module HexaPDF
|
|
2327
2453
|
# # Other instructions
|
2328
2454
|
# end
|
2329
2455
|
#
|
2330
|
-
# See:
|
2456
|
+
# See: PDF2.0 s14.6, #end_marked_content_sequence, #marked_content_point
|
2331
2457
|
def marked_content_sequence(tag, property_list: nil)
|
2332
2458
|
raise_unless_at_page_description_level
|
2333
2459
|
if property_list
|
@@ -2346,22 +2472,22 @@ module HexaPDF
|
|
2346
2472
|
# :call-seq:
|
2347
2473
|
# canvas.end_marked_content_sequence -> canvas
|
2348
2474
|
#
|
2349
|
-
# Ends a marked-content sequence
|
2475
|
+
# Ends a marked-content sequence and returns +self+.
|
2350
2476
|
#
|
2351
2477
|
# See #marked_content_sequence for details.
|
2352
2478
|
#
|
2353
|
-
# See:
|
2479
|
+
# See: PDF2.0 s14.6, #marked_content_sequence, #marked_content_point
|
2354
2480
|
def end_marked_content_sequence
|
2355
2481
|
raise_unless_at_page_description_level
|
2356
2482
|
invoke0(:EMC)
|
2357
2483
|
self
|
2358
2484
|
end
|
2359
2485
|
|
2360
|
-
# Creates a color object from the given color specification. See #stroke_color for
|
2361
|
-
# on the possible color specifications.
|
2486
|
+
# Creates and returns a color object from the given color specification. See #stroke_color for
|
2487
|
+
# details on the possible color specifications.
|
2362
2488
|
#
|
2363
2489
|
# This utility method is meant for use by higher-level methods that need to convert a color
|
2364
|
-
# specification into a color object
|
2490
|
+
# specification into a color object.
|
2365
2491
|
def color_from_specification(spec)
|
2366
2492
|
spec = Array(spec)
|
2367
2493
|
if spec.length == 1 && spec[0].kind_of?(String)
|