hexapdf 1.3.0 → 1.4.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 +45 -0
- data/lib/hexapdf/cli/form.rb +9 -4
- data/lib/hexapdf/configuration.rb +10 -0
- data/lib/hexapdf/dictionary_fields.rb +1 -1
- data/lib/hexapdf/digital_signature/signing/default_handler.rb +1 -2
- data/lib/hexapdf/document/annotations.rb +47 -0
- data/lib/hexapdf/document/layout.rb +73 -33
- data/lib/hexapdf/document/metadata.rb +10 -3
- data/lib/hexapdf/document.rb +9 -0
- data/lib/hexapdf/encryption/standard_security_handler.rb +7 -2
- data/lib/hexapdf/layout/box.rb +5 -0
- data/lib/hexapdf/layout/container_box.rb +63 -28
- data/lib/hexapdf/layout/style.rb +28 -13
- data/lib/hexapdf/layout/table_box.rb +20 -2
- data/lib/hexapdf/type/annotations/appearance_generator.rb +94 -16
- data/lib/hexapdf/type/annotations/interior_color.rb +1 -1
- data/lib/hexapdf/type/annotations/line.rb +1 -157
- data/lib/hexapdf/type/annotations/line_ending_styling.rb +208 -0
- data/lib/hexapdf/type/annotations/markup_annotation.rb +0 -1
- data/lib/hexapdf/type/annotations/polygon.rb +64 -0
- data/lib/hexapdf/type/annotations/polygon_polyline.rb +109 -0
- data/lib/hexapdf/type/annotations/polyline.rb +64 -0
- data/lib/hexapdf/type/annotations.rb +4 -0
- data/lib/hexapdf/type/measure.rb +57 -0
- data/lib/hexapdf/type.rb +1 -0
- data/lib/hexapdf/version.rb +1 -1
- data/test/hexapdf/digital_signature/signing/test_default_handler.rb +0 -1
- data/test/hexapdf/document/test_annotations.rb +20 -0
- data/test/hexapdf/document/test_layout.rb +16 -10
- data/test/hexapdf/document/test_metadata.rb +13 -1
- data/test/hexapdf/encryption/test_standard_security_handler.rb +2 -1
- data/test/hexapdf/layout/test_box.rb +8 -0
- data/test/hexapdf/layout/test_container_box.rb +34 -6
- data/test/hexapdf/layout/test_page_style.rb +1 -1
- data/test/hexapdf/layout/test_style.rb +20 -1
- data/test/hexapdf/layout/test_table_box.rb +14 -1
- data/test/hexapdf/test_dictionary_fields.rb +1 -0
- data/test/hexapdf/type/annotations/test_appearance_generator.rb +126 -0
- data/test/hexapdf/type/annotations/test_line.rb +0 -25
- data/test/hexapdf/type/annotations/test_line_ending_styling.rb +42 -0
- data/test/hexapdf/type/annotations/test_polygon_polyline.rb +29 -0
- metadata +9 -2
data/lib/hexapdf/layout/style.rb
CHANGED
@@ -150,14 +150,15 @@ module HexaPDF
|
|
150
150
|
end
|
151
151
|
|
152
152
|
# :call-seq:
|
153
|
-
# quad.set(value)
|
154
|
-
# quad.set(array)
|
155
|
-
# quad.set(quad
|
153
|
+
# quad.set(value) -> quad
|
154
|
+
# quad.set(array) -> quad
|
155
|
+
# quad.set(hash) -> quad
|
156
|
+
# quad.set(quad) -> quad
|
156
157
|
#
|
157
|
-
# Sets all values of the quad.
|
158
|
+
# Sets all values of the quad and returns it.
|
158
159
|
#
|
159
|
-
# * If a single value is provided that is neither a Quad nor an array, it is
|
160
|
-
# an array with one value was given.
|
160
|
+
# * If a single value is provided that is neither a Quad nor an array nor a hash, it is
|
161
|
+
# handled as if an array with one value was given.
|
161
162
|
#
|
162
163
|
# * If a Quad is provided, its values are used.
|
163
164
|
#
|
@@ -170,6 +171,9 @@ module HexaPDF
|
|
170
171
|
# third value.
|
171
172
|
# * Four or more values: Top is set to the first, right to the second, bottom to the third
|
172
173
|
# and left to the fourth value.
|
174
|
+
#
|
175
|
+
# * If a hash is provided, the keys +:top+, +:bottom+, +:left+ and +:right+ are used to set
|
176
|
+
# the respective value. All unspecified keys that have not been set before are set to 0.
|
173
177
|
def set(obj)
|
174
178
|
case obj
|
175
179
|
when Quad
|
@@ -182,9 +186,15 @@ module HexaPDF
|
|
182
186
|
@bottom = obj[2] || obj[0]
|
183
187
|
@left = obj[3] || obj[1] || obj[0]
|
184
188
|
@right = obj[1] || obj[0]
|
189
|
+
when Hash
|
190
|
+
@top = obj[:top] || @top || 0
|
191
|
+
@bottom = obj[:bottom] || @bottom || 0
|
192
|
+
@left = obj[:left] || @left || 0
|
193
|
+
@right = obj[:right] || @right || 0
|
185
194
|
else
|
186
195
|
@top = @bottom = @left = @right = obj
|
187
196
|
end
|
197
|
+
self
|
188
198
|
end
|
189
199
|
|
190
200
|
# Returns +true+ if the quad effectively contains only one value.
|
@@ -398,6 +408,9 @@ module HexaPDF
|
|
398
408
|
# bottom-left corner of the box during the drawing operations.
|
399
409
|
class Layers
|
400
410
|
|
411
|
+
# The array holding all raw layer definitions.
|
412
|
+
attr_reader :layers
|
413
|
+
|
401
414
|
# Creates a new Layers object popuplated with the given +layers+.
|
402
415
|
def initialize(layers = nil)
|
403
416
|
@layers = []
|
@@ -1527,10 +1540,10 @@ module HexaPDF
|
|
1527
1540
|
[:text_rendering_mode, "Content::TextRenderingMode::FILL",
|
1528
1541
|
{setter: "Content::TextRenderingMode.normalize(value)"}],
|
1529
1542
|
[:subscript, false,
|
1530
|
-
{setter: "value; superscript(false) if superscript",
|
1543
|
+
{setter: "value; superscript(false) if value && superscript? && superscript",
|
1531
1544
|
valid_values: [true, false]}],
|
1532
1545
|
[:superscript, false,
|
1533
|
-
{setter: "value; subscript(false) if subscript",
|
1546
|
+
{setter: "value; subscript(false) if value && subscript? && subscript",
|
1534
1547
|
valid_values: [true, false]}],
|
1535
1548
|
[:underline, false, {valid_values: [true, false]}],
|
1536
1549
|
[:strikeout, false, {valid_values: [true, false]}],
|
@@ -1557,8 +1570,10 @@ module HexaPDF
|
|
1557
1570
|
[:fill_horizontal, nil],
|
1558
1571
|
[:background_color, nil],
|
1559
1572
|
[:background_alpha, 1],
|
1560
|
-
[:padding, "Quad.new(0)",
|
1561
|
-
|
1573
|
+
[:padding, "Quad.new(0)",
|
1574
|
+
{setter: "value.kind_of?(Hash) && @name ? @name.set(value) : Quad.new(value)"}],
|
1575
|
+
[:margin, "Quad.new(0)",
|
1576
|
+
{setter: "value.kind_of?(Hash) && @name ? @name.set(value) : Quad.new(value)"}],
|
1562
1577
|
[:border, "Border.new", {setter: "Border.new(**value)"}],
|
1563
1578
|
[:overlays, "Layers.new", {setter: "Layers.new(value)"}],
|
1564
1579
|
[:underlays, "Layers.new", {setter: "Layers.new(value)"}],
|
@@ -1641,9 +1656,9 @@ module HexaPDF
|
|
1641
1656
|
|
1642
1657
|
# The calculated text rise, taking superscript and subscript into account.
|
1643
1658
|
def calculated_text_rise
|
1644
|
-
if superscript
|
1659
|
+
if superscript? && superscript
|
1645
1660
|
text_rise + font_size * 0.33
|
1646
|
-
elsif subscript
|
1661
|
+
elsif subscript? && subscript
|
1647
1662
|
text_rise - font_size * 0.20
|
1648
1663
|
else
|
1649
1664
|
text_rise
|
@@ -1652,7 +1667,7 @@ module HexaPDF
|
|
1652
1667
|
|
1653
1668
|
# The calculated font size, taking superscript and subscript into account.
|
1654
1669
|
def calculated_font_size
|
1655
|
-
(superscript || subscript ? 0.583 : 1) * font_size
|
1670
|
+
((superscript? && superscript) || (subscript? && subscript) ? 0.583 : 1) * font_size
|
1656
1671
|
end
|
1657
1672
|
|
1658
1673
|
# Returns the correct offset from the baseline for the underline.
|
@@ -126,6 +126,15 @@ module HexaPDF
|
|
126
126
|
# [layout.text('E'), layout.text('F')]]
|
127
127
|
# composer.column(height: 90) {|col| col.table(cells, header: header, footer: footer) }
|
128
128
|
#
|
129
|
+
# While the width of a cell is determined by the #column_widths array, the height is
|
130
|
+
# automatically determined during fitting of the content. However, it is also possible to use a
|
131
|
+
# fixed height (only if the actual content is smaller or equal than it):
|
132
|
+
#
|
133
|
+
# #>pdf-composer
|
134
|
+
# cells = [[{content: layout.text('A'), height: 5}, layout.text('B')],
|
135
|
+
# [{content: layout.text('C'), height: 40}, layout.text('D')]]
|
136
|
+
# composer.table(cells)
|
137
|
+
#
|
129
138
|
# The cells can be styled using a callable object for more complex styling:
|
130
139
|
#
|
131
140
|
# #>pdf-composer
|
@@ -191,13 +200,14 @@ module HexaPDF
|
|
191
200
|
attr_accessor :children
|
192
201
|
|
193
202
|
# Creates a new Cell instance.
|
194
|
-
def initialize(row:, column:, children: nil, row_span: nil, col_span: nil, **kwargs)
|
203
|
+
def initialize(row:, column:, children: nil, min_height: nil, row_span: nil, col_span: nil, **kwargs)
|
195
204
|
super(**kwargs, width: 0, height: 0)
|
196
205
|
@children = children
|
197
206
|
@row = row
|
198
207
|
@column = column
|
199
208
|
@row_span = row_span || 1
|
200
209
|
@col_span = col_span || 1
|
210
|
+
@min_height = min_height
|
201
211
|
style.border.width.set(1) unless style.border?
|
202
212
|
style.border.draw_on_bounds = true
|
203
213
|
style.padding.set(5) unless style.padding?
|
@@ -257,6 +267,11 @@ module HexaPDF
|
|
257
267
|
@fit_results = []
|
258
268
|
fit_result.success!
|
259
269
|
end
|
270
|
+
|
271
|
+
if @min_height && @height < @min_height
|
272
|
+
@height = @preferred_height = @min_height
|
273
|
+
fit_result.failure! if available_height < @height
|
274
|
+
end
|
260
275
|
end
|
261
276
|
|
262
277
|
# Draws the content of the cell.
|
@@ -298,6 +313,8 @@ module HexaPDF
|
|
298
313
|
#
|
299
314
|
# +:col_span+:: An integer specifying the number of columsn this cell should span.
|
300
315
|
#
|
316
|
+
# +:min_height+:: A number specifying the minimum height of the table cell.
|
317
|
+
#
|
301
318
|
# +:properties+:: A hash of properties (see Box#properties) to be set on the cell itself.
|
302
319
|
#
|
303
320
|
# All other key-value pairs are taken to be cell styling information (like
|
@@ -513,11 +530,12 @@ module HexaPDF
|
|
513
530
|
children = content.delete(:content)
|
514
531
|
row_span = content.delete(:row_span)
|
515
532
|
col_span = content.delete(:col_span)
|
533
|
+
min_height = content.delete(:min_height)
|
516
534
|
properties = content.delete(:properties)
|
517
535
|
style = content
|
518
536
|
end
|
519
537
|
cell = Cell.new(children: children, row: row_index, column: col_index,
|
520
|
-
row_span: row_span, col_span: col_span)
|
538
|
+
row_span: row_span, col_span: col_span, min_height: min_height)
|
521
539
|
cell_style_block&.call(cell)
|
522
540
|
cell.style.update(**style) if style
|
523
541
|
cell.properties.update(properties) if properties
|
@@ -75,6 +75,8 @@ module HexaPDF
|
|
75
75
|
when :Line then create_line_appearance
|
76
76
|
when :Square then create_square_circle_appearance(:square)
|
77
77
|
when :Circle then create_square_circle_appearance(:circle)
|
78
|
+
when :Polygon then create_polygon_polyline_appearance(:polygon)
|
79
|
+
when :PolyLine then create_polygon_polyline_appearance(:polyline)
|
78
80
|
else
|
79
81
|
raise HexaPDF::Error, "Appearance regeneration for #{@annot[:Subtype]} not yet supported"
|
80
82
|
end
|
@@ -143,18 +145,8 @@ module HexaPDF
|
|
143
145
|
# the caption when calculating the bounding box.
|
144
146
|
#
|
145
147
|
# The result could still be improved by tailoring to the specific line ending style.
|
146
|
-
|
147
|
-
|
148
|
-
when :square, :circle, :diamond, :slash, :open_arrow, :closed_arrow
|
149
|
-
3 * style.width
|
150
|
-
when :ropen_arrow, :rclosed_arrow
|
151
|
-
10 * style.width
|
152
|
-
else
|
153
|
-
0
|
154
|
-
end
|
155
|
-
end
|
156
|
-
dstart = calculate_le_padding.call(line_ending_style.start_style)
|
157
|
-
dend = calculate_le_padding.call(line_ending_style.end_style)
|
148
|
+
dstart = calculate_line_ending_padding(line_ending_style.start_style, style.width)
|
149
|
+
dend = calculate_line_ending_padding(line_ending_style.end_style, style.width)
|
158
150
|
if captioned
|
159
151
|
cap_ulx = x0 + cos_angle * cap_x - sin_angle * cap_y
|
160
152
|
cap_uly = y0 + sin_angle * cap_x + cos_angle * cap_y
|
@@ -299,6 +291,90 @@ module HexaPDF
|
|
299
291
|
end
|
300
292
|
end
|
301
293
|
|
294
|
+
# Creates the appropriate appearance for a polygon or polyline annotation depending on the
|
295
|
+
# given +type+ (which can either be +:polygon+ or +:polyline+).
|
296
|
+
#
|
297
|
+
# The cloudy border effect is not supported.
|
298
|
+
#
|
299
|
+
# See: HexaPDF::Type::Annotations::Polygon, HexaPDF::Type::Annotations::Polyline
|
300
|
+
def create_polygon_polyline_appearance(type)
|
301
|
+
# Prepare the annotation
|
302
|
+
form = (@annot[:AP] ||= {})[:N] ||=
|
303
|
+
@document.add({Type: :XObject, Subtype: :Form, BBox: [0, 0, 0, 0]})
|
304
|
+
form.contents = ""
|
305
|
+
@annot.flag(:print)
|
306
|
+
@annot.unflag(:hidden)
|
307
|
+
|
308
|
+
# Get all needed values from the annotation
|
309
|
+
vertices = @annot.vertices
|
310
|
+
border_style = @annot.border_style
|
311
|
+
line_ending_style = @annot.line_ending_style
|
312
|
+
opacity = @annot.opacity
|
313
|
+
interior_color = @annot.interior_color
|
314
|
+
|
315
|
+
# Calculate the annotation's rectangle as well as the form bounding box
|
316
|
+
padding_start = calculate_line_ending_padding(line_ending_style.start_style, border_style.width)
|
317
|
+
padding_end = calculate_line_ending_padding(line_ending_style.end_style, border_style.width)
|
318
|
+
x_coords, y_coords = vertices.partition.with_index {|_, index| index.even? }
|
319
|
+
min_x, max_x = (x_coords + [x_coords[0] + padding_start, x_coords[0] - padding_start,
|
320
|
+
x_coords[-1] + padding_end, x_coords[-1] - padding_end]).minmax
|
321
|
+
min_y, max_y = (y_coords + [y_coords[0] + padding_start, y_coords[0] - padding_start,
|
322
|
+
y_coords[-1] + padding_end, y_coords[-1] - padding_end]).minmax
|
323
|
+
|
324
|
+
padding = 4 * border_style.width
|
325
|
+
rect = [min_x - padding, min_y - padding, max_x + padding, max_y + padding]
|
326
|
+
@annot[:Rect] = rect
|
327
|
+
form[:BBox] = rect.dup
|
328
|
+
|
329
|
+
return if vertices.length < 4
|
330
|
+
|
331
|
+
# Set the appropriate graphics state
|
332
|
+
canvas = form.canvas(translate: false)
|
333
|
+
canvas.opacity(**opacity.to_h)
|
334
|
+
canvas.stroke_color(border_style.color) if border_style.color
|
335
|
+
canvas.fill_color(interior_color) if interior_color
|
336
|
+
canvas.line_width(border_style.width)
|
337
|
+
canvas.line_dash_pattern(border_style.style) if border_style.style.kind_of?(Array)
|
338
|
+
|
339
|
+
stroke_op = (border_style.color ? :stroke : :end_path)
|
340
|
+
fill_op = (border_style.color && interior_color ? :fill_stroke :
|
341
|
+
(border_style.color ? :stroke : (interior_color ? :fill : :end_path)))
|
342
|
+
|
343
|
+
# Draw the polygon/polyline
|
344
|
+
canvas.send(type, *vertices)
|
345
|
+
canvas.send(type == :polygon ? fill_op : stroke_op)
|
346
|
+
|
347
|
+
return unless type == :polyline
|
348
|
+
|
349
|
+
# Draw line endings
|
350
|
+
angle_start = Math.atan2(y_coords[1] - y_coords[0], x_coords[1] - x_coords[0])
|
351
|
+
angle_end = Math.atan2(y_coords[-2] - y_coords[-1], x_coords[-2] - x_coords[-1])
|
352
|
+
if line_ending_style.start_style != :none
|
353
|
+
do_fill = draw_line_ending(canvas, line_ending_style.start_style,
|
354
|
+
x_coords[0], y_coords[0], border_style.width, angle_start)
|
355
|
+
canvas.send(do_fill ? fill_op : stroke_op)
|
356
|
+
end
|
357
|
+
if line_ending_style.end_style != :none
|
358
|
+
do_fill = draw_line_ending(canvas, line_ending_style.end_style,
|
359
|
+
x_coords[-1], y_coords[-1], border_style.width, angle_end)
|
360
|
+
canvas.send(do_fill ? fill_op : stroke_op)
|
361
|
+
end
|
362
|
+
|
363
|
+
end
|
364
|
+
|
365
|
+
# Calculates the padding needed around the line endings based on the line ending +style+ and
|
366
|
+
# the +border_width+.
|
367
|
+
def calculate_line_ending_padding(style, border_width)
|
368
|
+
case style
|
369
|
+
when :square, :circle, :diamond, :slash, :open_arrow, :closed_arrow
|
370
|
+
3 * border_width
|
371
|
+
when :ropen_arrow, :rclosed_arrow
|
372
|
+
10 * border_width
|
373
|
+
else
|
374
|
+
0
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
302
378
|
# Draws the line ending style +type+ at the position (+x+, +y+) and returns +true+ if the
|
303
379
|
# shape needs to be filled.
|
304
380
|
#
|
@@ -319,11 +395,13 @@ module HexaPDF
|
|
319
395
|
canvas.polygon(x + lw3, y, x, y + lw3, x - lw3, y, x, y - lw3)
|
320
396
|
true
|
321
397
|
when :open_arrow, :closed_arrow, :ropen_arrow, :rclosed_arrow
|
322
|
-
|
323
|
-
|
398
|
+
arrow_cos_up = Math.cos(angle + Math::PI / 6)
|
399
|
+
arrow_sin_up = Math.sin(angle + Math::PI / 6)
|
400
|
+
arrow_cos_down = Math.cos(angle - Math::PI / 6)
|
401
|
+
arrow_sin_down = Math.sin(angle - Math::PI / 6)
|
324
402
|
dir = (type == :ropen_arrow || type == :rclosed_arrow ? -1 : 1)
|
325
|
-
canvas.polyline(x + dir *
|
326
|
-
x + dir *
|
403
|
+
canvas.polyline(x + dir * arrow_cos_up * 3 * lw3, y + arrow_sin_up * 3 * lw3, x, y,
|
404
|
+
x + dir * arrow_cos_down * 3 * lw3, y + arrow_sin_down * 3 * lw3)
|
327
405
|
if type == :closed_arrow || type == :rclosed_arrow
|
328
406
|
canvas.close_subpath
|
329
407
|
true
|
@@ -61,7 +61,7 @@ module HexaPDF
|
|
61
61
|
# the allowed arguments.
|
62
62
|
#
|
63
63
|
# If the special value +:transparent+ is used when setting the color, no color is
|
64
|
-
# used for filling
|
64
|
+
# used for filling.
|
65
65
|
def interior_color(*color)
|
66
66
|
if color.empty?
|
67
67
|
color = self[:IC]
|
@@ -71,6 +71,7 @@ module HexaPDF
|
|
71
71
|
|
72
72
|
include BorderStyling
|
73
73
|
include InteriorColor
|
74
|
+
include LineEndingStyling
|
74
75
|
|
75
76
|
define_field :Subtype, type: Symbol, required: true, default: :Line
|
76
77
|
define_field :L, type: PDFArray, required: true
|
@@ -116,163 +117,6 @@ module HexaPDF
|
|
116
117
|
end
|
117
118
|
end
|
118
119
|
|
119
|
-
# Maps HexaPDF names to PDF names.
|
120
|
-
LINE_ENDING_STYLE_MAP = { # :nodoc:
|
121
|
-
Square: :Square, square: :Square,
|
122
|
-
Circle: :Circle, circle: :Circle,
|
123
|
-
Diamond: :Diamond, diamond: :Diamond,
|
124
|
-
OpenArrow: :OpenArrow, open_arrow: :OpenArrow,
|
125
|
-
ClosedArrow: :ClosedArrow, closed_arrow: :ClosedArrow,
|
126
|
-
None: :None, none: :None,
|
127
|
-
Butt: :Butt, butt: :Butt,
|
128
|
-
ROpenArrow: :ROpenArrow, ropen_arrow: :ROpenArrow,
|
129
|
-
RClosedArrow: :RClosedArrow, rclosed_arrow: :RClosedArrow,
|
130
|
-
Slash: :Slash, slash: :Slash,
|
131
|
-
}.freeze
|
132
|
-
LINE_ENDING_STYLE_REVERSE_MAP = LINE_ENDING_STYLE_MAP.invert # :nodoc:
|
133
|
-
|
134
|
-
|
135
|
-
# Describes the line ending style for a line annotation, i.e. the +start_style+ and the
|
136
|
-
# +end_style+.
|
137
|
-
#
|
138
|
-
# See Line#line_ending_style for more information.
|
139
|
-
LineEndingStyle = Struct.new(:start_style, :end_style)
|
140
|
-
|
141
|
-
# :call-seq:
|
142
|
-
# line.line_ending_style => style
|
143
|
-
# line.line_ending_style(start_style: :none, end_style: :none) => line
|
144
|
-
#
|
145
|
-
# Returns a LineEndingStyle instance holding the current line ending styles when no argument
|
146
|
-
# is given. Otherwise sets the line ending style of the line and returns self.
|
147
|
-
#
|
148
|
-
# When returning the styles, unknown line ending styles are mapped to :none.
|
149
|
-
#
|
150
|
-
# When setting the line ending style, arguments that are not provided will use the currently
|
151
|
-
# defined value or fall back to the default of +:none+.
|
152
|
-
#
|
153
|
-
# Possible line ending styles (the first one is the HexaPDF name, the second the PDF name):
|
154
|
-
#
|
155
|
-
# :square or :Square::
|
156
|
-
# A square filled with the annotation's interior colour, if any.
|
157
|
-
#
|
158
|
-
# #>pdf-small-hide
|
159
|
-
# doc.annotations.
|
160
|
-
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
161
|
-
# interior_color("hp-orange").
|
162
|
-
# line_ending_style(end_style: :square).
|
163
|
-
# regenerate_appearance
|
164
|
-
#
|
165
|
-
# :circle or :Circle::
|
166
|
-
# A circle filled with the annotation’s interior colour, if any.
|
167
|
-
#
|
168
|
-
# #>pdf-small-hide
|
169
|
-
# doc.annotations.
|
170
|
-
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
171
|
-
# interior_color("hp-orange").
|
172
|
-
# line_ending_style(end_style: :circle).
|
173
|
-
# regenerate_appearance
|
174
|
-
#
|
175
|
-
# :diamond or :Diamond::
|
176
|
-
# A diamond shape filled with the annotation’s interior colour, if any.
|
177
|
-
#
|
178
|
-
# #>pdf-small-hide
|
179
|
-
# doc.annotations.
|
180
|
-
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
181
|
-
# interior_color("hp-orange").
|
182
|
-
# line_ending_style(end_style: :diamond).
|
183
|
-
# regenerate_appearance
|
184
|
-
#
|
185
|
-
# :open_arrow or :OpenArrow::
|
186
|
-
# Two short lines meeting in an acute angle to form an open arrowhead.
|
187
|
-
#
|
188
|
-
# #>pdf-small-hide
|
189
|
-
# doc.annotations.
|
190
|
-
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
191
|
-
# interior_color("hp-orange").
|
192
|
-
# line_ending_style(end_style: :open_arrow).
|
193
|
-
# regenerate_appearance
|
194
|
-
#
|
195
|
-
# :closed_arrow or :ClosedArrow::
|
196
|
-
# Two short lines meeting in an acute angle as in the +:open_arrow+ style and connected
|
197
|
-
# by a third line to form a triangular closed arrowhead filled with the annotation’s
|
198
|
-
# interior colour, if any.
|
199
|
-
#
|
200
|
-
# #>pdf-small-hide
|
201
|
-
# doc.annotations.
|
202
|
-
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
203
|
-
# interior_color("hp-orange").
|
204
|
-
# line_ending_style(end_style: :closed_arrow).
|
205
|
-
# regenerate_appearance
|
206
|
-
#
|
207
|
-
# :none or :None::
|
208
|
-
# No line ending.
|
209
|
-
#
|
210
|
-
# #>pdf-small-hide
|
211
|
-
# doc.annotations.
|
212
|
-
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
213
|
-
# interior_color("hp-orange").
|
214
|
-
# line_ending_style(end_style: :none).
|
215
|
-
# regenerate_appearance
|
216
|
-
#
|
217
|
-
# :butt or :Butt::
|
218
|
-
# A short line at the endpoint perpendicular to the line itself.
|
219
|
-
#
|
220
|
-
# #>pdf-small-hide
|
221
|
-
# doc.annotations.
|
222
|
-
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
223
|
-
# interior_color("hp-orange").
|
224
|
-
# line_ending_style(end_style: :butt).
|
225
|
-
# regenerate_appearance
|
226
|
-
#
|
227
|
-
# :ropen_arrow or :ROpenArrow::
|
228
|
-
# Two short lines in the reverse direction from +:open_arrow+.
|
229
|
-
#
|
230
|
-
# #>pdf-small-hide
|
231
|
-
# doc.annotations.
|
232
|
-
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
233
|
-
# interior_color("hp-orange").
|
234
|
-
# line_ending_style(end_style: :ropen_arrow).
|
235
|
-
# regenerate_appearance
|
236
|
-
#
|
237
|
-
# :rclosed_arrow or :RClosedArrow::
|
238
|
-
# A triangular closed arrowhead in the reverse direction from +:closed_arrow+.
|
239
|
-
#
|
240
|
-
# #>pdf-small-hide
|
241
|
-
# doc.annotations.
|
242
|
-
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
243
|
-
# interior_color("hp-orange").
|
244
|
-
# line_ending_style(end_style: :rclosed_arrow).
|
245
|
-
# regenerate_appearance
|
246
|
-
#
|
247
|
-
# :slash or :Slash::
|
248
|
-
# A short line at the endpoint approximately 30 degrees clockwise from perpendicular to
|
249
|
-
# the line itself.
|
250
|
-
#
|
251
|
-
# #>pdf-small-hide
|
252
|
-
# doc.annotations.
|
253
|
-
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
254
|
-
# interior_color("hp-orange").
|
255
|
-
# line_ending_style(end_style: :slash).
|
256
|
-
# regenerate_appearance
|
257
|
-
def line_ending_style(start_style: :UNSET, end_style: :UNSET)
|
258
|
-
if start_style == :UNSET && end_style == :UNSET
|
259
|
-
le = self[:LE]
|
260
|
-
LineEndingStyle.new(LINE_ENDING_STYLE_REVERSE_MAP.fetch(le[0], :none),
|
261
|
-
LINE_ENDING_STYLE_REVERSE_MAP.fetch(le[1], :none))
|
262
|
-
else
|
263
|
-
start_style = self[:LE][0] if start_style == :UNSET
|
264
|
-
end_style = self[:LE][1] if end_style == :UNSET
|
265
|
-
start_style = LINE_ENDING_STYLE_MAP.fetch(start_style) do
|
266
|
-
raise ArgumentError, "Invalid line ending style: #{start_style.inspect}"
|
267
|
-
end
|
268
|
-
end_style = LINE_ENDING_STYLE_MAP.fetch(end_style) do
|
269
|
-
raise ArgumentError, "Invalid line ending style: #{end_style.inspect}"
|
270
|
-
end
|
271
|
-
self[:LE] = [start_style, end_style]
|
272
|
-
self
|
273
|
-
end
|
274
|
-
end
|
275
|
-
|
276
120
|
# :call-seq:
|
277
121
|
# line.leader_line_length => leader_line_length
|
278
122
|
# line.leader_line_length(length) => line
|