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
@@ -0,0 +1,208 @@
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# This file is part of HexaPDF.
|
5
|
+
#
|
6
|
+
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
8
|
+
#
|
9
|
+
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
|
+
# under the terms of the GNU Affero General Public License version 3 as
|
11
|
+
# published by the Free Software Foundation with the addition of the
|
12
|
+
# following permission added to Section 15 as permitted in Section 7(a):
|
13
|
+
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
|
14
|
+
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
|
15
|
+
# INFRINGEMENT OF THIRD PARTY RIGHTS.
|
16
|
+
#
|
17
|
+
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
|
18
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
20
|
+
# License for more details.
|
21
|
+
#
|
22
|
+
# You should have received a copy of the GNU Affero General Public License
|
23
|
+
# along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
|
24
|
+
#
|
25
|
+
# The interactive user interfaces in modified source and object code
|
26
|
+
# versions of HexaPDF must display Appropriate Legal Notices, as required
|
27
|
+
# under Section 5 of the GNU Affero General Public License version 3.
|
28
|
+
#
|
29
|
+
# In accordance with Section 7(b) of the GNU Affero General Public
|
30
|
+
# License, a covered work must retain the producer line in every PDF that
|
31
|
+
# is created or manipulated using HexaPDF.
|
32
|
+
#
|
33
|
+
# If the GNU Affero General Public License doesn't fit your need,
|
34
|
+
# commercial licenses are available at <https://gettalong.at/hexapdf/>.
|
35
|
+
#++
|
36
|
+
|
37
|
+
require 'hexapdf/type/annotations'
|
38
|
+
|
39
|
+
module HexaPDF
|
40
|
+
module Type
|
41
|
+
module Annotations
|
42
|
+
|
43
|
+
# This module provides a convenience method for getting and setting the line ending style for
|
44
|
+
# line and polyline annotations.
|
45
|
+
#
|
46
|
+
# See: PDF2.0 s12.5.6.7
|
47
|
+
module LineEndingStyling
|
48
|
+
|
49
|
+
# Maps HexaPDF names to PDF names.
|
50
|
+
LINE_ENDING_STYLE_MAP = { # :nodoc:
|
51
|
+
Square: :Square, square: :Square,
|
52
|
+
Circle: :Circle, circle: :Circle,
|
53
|
+
Diamond: :Diamond, diamond: :Diamond,
|
54
|
+
OpenArrow: :OpenArrow, open_arrow: :OpenArrow,
|
55
|
+
ClosedArrow: :ClosedArrow, closed_arrow: :ClosedArrow,
|
56
|
+
None: :None, none: :None,
|
57
|
+
Butt: :Butt, butt: :Butt,
|
58
|
+
ROpenArrow: :ROpenArrow, ropen_arrow: :ROpenArrow,
|
59
|
+
RClosedArrow: :RClosedArrow, rclosed_arrow: :RClosedArrow,
|
60
|
+
Slash: :Slash, slash: :Slash,
|
61
|
+
}.freeze
|
62
|
+
LINE_ENDING_STYLE_REVERSE_MAP = LINE_ENDING_STYLE_MAP.invert # :nodoc:
|
63
|
+
|
64
|
+
# Describes the line ending style, i.e. the +start_style+ and the +end_style+.
|
65
|
+
#
|
66
|
+
# See LineEndingStyling#line_ending_style for more information.
|
67
|
+
LineEndingStyle = Struct.new(:start_style, :end_style)
|
68
|
+
|
69
|
+
# :call-seq:
|
70
|
+
# annot.line_ending_style => style
|
71
|
+
# annot.line_ending_style(start_style: :none, end_style: :none) => line
|
72
|
+
#
|
73
|
+
# Returns a LineEndingStyle instance holding the current line ending styles when no argument
|
74
|
+
# is given. Otherwise sets the line ending style of the annotation and returns self.
|
75
|
+
#
|
76
|
+
# When returning the styles, unknown line ending styles are mapped to :none.
|
77
|
+
#
|
78
|
+
# When setting the line ending style, arguments that are not provided will use the currently
|
79
|
+
# defined value or fall back to the default of +:none+.
|
80
|
+
#
|
81
|
+
# Possible line ending styles (the first one is the HexaPDF name, the second the PDF name):
|
82
|
+
#
|
83
|
+
# :square or :Square::
|
84
|
+
# A square filled with the annotation's interior colour, if any.
|
85
|
+
#
|
86
|
+
# #>pdf-small-hide
|
87
|
+
# doc.annotations.
|
88
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
89
|
+
# interior_color("hp-orange").
|
90
|
+
# line_ending_style(end_style: :square).
|
91
|
+
# regenerate_appearance
|
92
|
+
#
|
93
|
+
# :circle or :Circle::
|
94
|
+
# A circle filled with the annotation’s interior colour, if any.
|
95
|
+
#
|
96
|
+
# #>pdf-small-hide
|
97
|
+
# doc.annotations.
|
98
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
99
|
+
# interior_color("hp-orange").
|
100
|
+
# line_ending_style(end_style: :circle).
|
101
|
+
# regenerate_appearance
|
102
|
+
#
|
103
|
+
# :diamond or :Diamond::
|
104
|
+
# A diamond shape filled with the annotation’s interior colour, if any.
|
105
|
+
#
|
106
|
+
# #>pdf-small-hide
|
107
|
+
# doc.annotations.
|
108
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
109
|
+
# interior_color("hp-orange").
|
110
|
+
# line_ending_style(end_style: :diamond).
|
111
|
+
# regenerate_appearance
|
112
|
+
#
|
113
|
+
# :open_arrow or :OpenArrow::
|
114
|
+
# Two short lines meeting in an acute angle to form an open arrowhead.
|
115
|
+
#
|
116
|
+
# #>pdf-small-hide
|
117
|
+
# doc.annotations.
|
118
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
119
|
+
# interior_color("hp-orange").
|
120
|
+
# line_ending_style(end_style: :open_arrow).
|
121
|
+
# regenerate_appearance
|
122
|
+
#
|
123
|
+
# :closed_arrow or :ClosedArrow::
|
124
|
+
# Two short lines meeting in an acute angle as in the +:open_arrow+ style and connected
|
125
|
+
# by a third line to form a triangular closed arrowhead filled with the annotation’s
|
126
|
+
# interior colour, if any.
|
127
|
+
#
|
128
|
+
# #>pdf-small-hide
|
129
|
+
# doc.annotations.
|
130
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
131
|
+
# interior_color("hp-orange").
|
132
|
+
# line_ending_style(end_style: :closed_arrow).
|
133
|
+
# regenerate_appearance
|
134
|
+
#
|
135
|
+
# :none or :None::
|
136
|
+
# No line ending.
|
137
|
+
#
|
138
|
+
# #>pdf-small-hide
|
139
|
+
# doc.annotations.
|
140
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
141
|
+
# interior_color("hp-orange").
|
142
|
+
# line_ending_style(end_style: :none).
|
143
|
+
# regenerate_appearance
|
144
|
+
#
|
145
|
+
# :butt or :Butt::
|
146
|
+
# A short line at the endpoint perpendicular to the line itself.
|
147
|
+
#
|
148
|
+
# #>pdf-small-hide
|
149
|
+
# doc.annotations.
|
150
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
151
|
+
# interior_color("hp-orange").
|
152
|
+
# line_ending_style(end_style: :butt).
|
153
|
+
# regenerate_appearance
|
154
|
+
#
|
155
|
+
# :ropen_arrow or :ROpenArrow::
|
156
|
+
# Two short lines in the reverse direction from +:open_arrow+.
|
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: :ropen_arrow).
|
163
|
+
# regenerate_appearance
|
164
|
+
#
|
165
|
+
# :rclosed_arrow or :RClosedArrow::
|
166
|
+
# A triangular closed arrowhead in the reverse direction from +:closed_arrow+.
|
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: :rclosed_arrow).
|
173
|
+
# regenerate_appearance
|
174
|
+
#
|
175
|
+
# :slash or :Slash::
|
176
|
+
# A short line at the endpoint approximately 30 degrees clockwise from perpendicular to
|
177
|
+
# the line itself.
|
178
|
+
#
|
179
|
+
# #>pdf-small-hide
|
180
|
+
# doc.annotations.
|
181
|
+
# create_line(doc.pages[0], start_point: [20, 20], end_point: [80, 60]).
|
182
|
+
# interior_color("hp-orange").
|
183
|
+
# line_ending_style(end_style: :slash).
|
184
|
+
# regenerate_appearance
|
185
|
+
def line_ending_style(start_style: :UNSET, end_style: :UNSET)
|
186
|
+
if start_style == :UNSET && end_style == :UNSET
|
187
|
+
le = self[:LE]
|
188
|
+
LineEndingStyle.new(LINE_ENDING_STYLE_REVERSE_MAP.fetch(le[0], :none),
|
189
|
+
LINE_ENDING_STYLE_REVERSE_MAP.fetch(le[1], :none))
|
190
|
+
else
|
191
|
+
start_style = self[:LE][0] if start_style == :UNSET
|
192
|
+
end_style = self[:LE][1] if end_style == :UNSET
|
193
|
+
start_style = LINE_ENDING_STYLE_MAP.fetch(start_style) do
|
194
|
+
raise ArgumentError, "Invalid line ending style: #{start_style.inspect}"
|
195
|
+
end
|
196
|
+
end_style = LINE_ENDING_STYLE_MAP.fetch(end_style) do
|
197
|
+
raise ArgumentError, "Invalid line ending style: #{end_style.inspect}"
|
198
|
+
end
|
199
|
+
self[:LE] = [start_style, end_style]
|
200
|
+
self
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -61,7 +61,6 @@ module HexaPDF
|
|
61
61
|
|
62
62
|
define_field :T, type: String, version: '1.1'
|
63
63
|
define_field :Popup, type: :Annot, version: '1.3'
|
64
|
-
define_field :CA, type: Numeric, default: 1.0, version: '1.4'
|
65
64
|
define_field :RC, type: [Stream, String], version: '1.5'
|
66
65
|
define_field :CreationDate, type: PDFDate, version: '1.5'
|
67
66
|
define_field :IRT, type: Dictionary, version: '1.5'
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# This file is part of HexaPDF.
|
5
|
+
#
|
6
|
+
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
8
|
+
#
|
9
|
+
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
|
+
# under the terms of the GNU Affero General Public License version 3 as
|
11
|
+
# published by the Free Software Foundation with the addition of the
|
12
|
+
# following permission added to Section 15 as permitted in Section 7(a):
|
13
|
+
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
|
14
|
+
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
|
15
|
+
# INFRINGEMENT OF THIRD PARTY RIGHTS.
|
16
|
+
#
|
17
|
+
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
|
18
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
20
|
+
# License for more details.
|
21
|
+
#
|
22
|
+
# You should have received a copy of the GNU Affero General Public License
|
23
|
+
# along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
|
24
|
+
#
|
25
|
+
# The interactive user interfaces in modified source and object code
|
26
|
+
# versions of HexaPDF must display Appropriate Legal Notices, as required
|
27
|
+
# under Section 5 of the GNU Affero General Public License version 3.
|
28
|
+
#
|
29
|
+
# In accordance with Section 7(b) of the GNU Affero General Public
|
30
|
+
# License, a covered work must retain the producer line in every PDF that
|
31
|
+
# is created or manipulated using HexaPDF.
|
32
|
+
#
|
33
|
+
# If the GNU Affero General Public License doesn't fit your need,
|
34
|
+
# commercial licenses are available at <https://gettalong.at/hexapdf/>.
|
35
|
+
#++
|
36
|
+
|
37
|
+
require 'hexapdf/type/annotations'
|
38
|
+
|
39
|
+
module HexaPDF
|
40
|
+
module Type
|
41
|
+
module Annotations
|
42
|
+
|
43
|
+
# A polygon annotation displays a closed polygon inside the annotation rectangle.
|
44
|
+
#
|
45
|
+
# Also see PolygonPolyline for more information.
|
46
|
+
#
|
47
|
+
# Example:
|
48
|
+
#
|
49
|
+
# #>pdf-small
|
50
|
+
# doc.annotations.create_polygon(doc.pages[0], 20, 20, 30, 70, 80, 60, 40, 30).
|
51
|
+
# border_style(color: "hp-blue", width: 2, style: [3, 1]).
|
52
|
+
# interior_color("hp-orange").
|
53
|
+
# regenerate_appearance
|
54
|
+
#
|
55
|
+
# See: PDF2.0 s12.5.6.9, HexaPDF::Type::Annotations::PolygonPolyline
|
56
|
+
class Polygon < PolygonPolyline
|
57
|
+
|
58
|
+
define_field :Subtype, type: Symbol, required: true, default: :Polygon
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# This file is part of HexaPDF.
|
5
|
+
#
|
6
|
+
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
8
|
+
#
|
9
|
+
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
|
+
# under the terms of the GNU Affero General Public License version 3 as
|
11
|
+
# published by the Free Software Foundation with the addition of the
|
12
|
+
# following permission added to Section 15 as permitted in Section 7(a):
|
13
|
+
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
|
14
|
+
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
|
15
|
+
# INFRINGEMENT OF THIRD PARTY RIGHTS.
|
16
|
+
#
|
17
|
+
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
|
18
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
20
|
+
# License for more details.
|
21
|
+
#
|
22
|
+
# You should have received a copy of the GNU Affero General Public License
|
23
|
+
# along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
|
24
|
+
#
|
25
|
+
# The interactive user interfaces in modified source and object code
|
26
|
+
# versions of HexaPDF must display Appropriate Legal Notices, as required
|
27
|
+
# under Section 5 of the GNU Affero General Public License version 3.
|
28
|
+
#
|
29
|
+
# In accordance with Section 7(b) of the GNU Affero General Public
|
30
|
+
# License, a covered work must retain the producer line in every PDF that
|
31
|
+
# is created or manipulated using HexaPDF.
|
32
|
+
#
|
33
|
+
# If the GNU Affero General Public License doesn't fit your need,
|
34
|
+
# commercial licenses are available at <https://gettalong.at/hexapdf/>.
|
35
|
+
#++
|
36
|
+
|
37
|
+
require 'hexapdf/type/annotations'
|
38
|
+
|
39
|
+
module HexaPDF
|
40
|
+
module Type
|
41
|
+
module Annotations
|
42
|
+
|
43
|
+
# This is the base class for the polygon and polyline markup annotations which display either
|
44
|
+
# a closed polygon or a polyline inside the annotation rectangle.
|
45
|
+
#
|
46
|
+
# The styling is done through methods included by various modules:
|
47
|
+
#
|
48
|
+
# * Changing the line width, line dash pattern and color is done using the method
|
49
|
+
# BorderStyling#border_style. While that method allows special styling of the line (like
|
50
|
+
# :beveled), only a simple line dash pattern is supported.
|
51
|
+
#
|
52
|
+
# * The border effect can be changed through BorderEffect#border_effect. Note that cloudy
|
53
|
+
# borders are not supported.
|
54
|
+
#
|
55
|
+
# * The interior color can be changed through InteriorColor#interior_color.
|
56
|
+
#
|
57
|
+
# * The line ending style can be changed through LineEndingStyling#line_ending_style.
|
58
|
+
#
|
59
|
+
# See: PDF2.0 s12.5.6.9, HexaPDF::Type::Annotations::Polyline,
|
60
|
+
# HexaPDF::Type::Annotations::Polygon, HexaPDF::Type::MarkupAnnotation
|
61
|
+
class PolygonPolyline < MarkupAnnotation
|
62
|
+
|
63
|
+
include BorderStyling
|
64
|
+
include BorderEffect
|
65
|
+
include InteriorColor
|
66
|
+
include LineEndingStyling
|
67
|
+
|
68
|
+
# Field Subtype is defined in the two subclasses
|
69
|
+
define_field :Vertices, type: PDFArray, required: true
|
70
|
+
define_field :LE, type: PDFArray, default: [:None, :None]
|
71
|
+
define_field :BS, type: :Border
|
72
|
+
define_field :IC, type: PDFArray
|
73
|
+
define_field :BE, type: :XXBorderEffect, version: '1.5'
|
74
|
+
define_field :IT, type: Symbol, version: '1.6',
|
75
|
+
allowed_values: [:PolygonCloud, :PolyLineDimension, :PolygonDimension]
|
76
|
+
define_field :Measure, type: :Measure, version: '1.7'
|
77
|
+
define_field :Path, type: PDFArray, version: '2.0'
|
78
|
+
|
79
|
+
# :call-seq:
|
80
|
+
# annot.vertices => [x0, y0, x1, y1, ...]
|
81
|
+
# annot.vertices(*points) => annot
|
82
|
+
#
|
83
|
+
# Returns the array with the vertices, alternating between horizontal and vertical
|
84
|
+
# coordinates, when no argument is given. Otherwise sets the vertices and returns self.
|
85
|
+
#
|
86
|
+
# This is the only required setting. Note, however, that without setting the appearance
|
87
|
+
# style through convenience methods like #border_style nothing will be shown.
|
88
|
+
#
|
89
|
+
# Example:
|
90
|
+
#
|
91
|
+
# #>pdf-small
|
92
|
+
# doc.annotations.
|
93
|
+
# create_polyline(doc.pages[0], 20, 20, 30, 70, 80, 60, 40, 30).
|
94
|
+
# regenerate_appearance
|
95
|
+
def vertices(*points)
|
96
|
+
if points.empty?
|
97
|
+
self[:Vertices].to_ary
|
98
|
+
elsif points.length % 2 != 0
|
99
|
+
raise ArgumentError, "An even number of arguments must be provided"
|
100
|
+
else
|
101
|
+
self[:Vertices] = points
|
102
|
+
self
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# This file is part of HexaPDF.
|
5
|
+
#
|
6
|
+
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
8
|
+
#
|
9
|
+
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
|
+
# under the terms of the GNU Affero General Public License version 3 as
|
11
|
+
# published by the Free Software Foundation with the addition of the
|
12
|
+
# following permission added to Section 15 as permitted in Section 7(a):
|
13
|
+
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
|
14
|
+
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
|
15
|
+
# INFRINGEMENT OF THIRD PARTY RIGHTS.
|
16
|
+
#
|
17
|
+
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
|
18
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
20
|
+
# License for more details.
|
21
|
+
#
|
22
|
+
# You should have received a copy of the GNU Affero General Public License
|
23
|
+
# along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
|
24
|
+
#
|
25
|
+
# The interactive user interfaces in modified source and object code
|
26
|
+
# versions of HexaPDF must display Appropriate Legal Notices, as required
|
27
|
+
# under Section 5 of the GNU Affero General Public License version 3.
|
28
|
+
#
|
29
|
+
# In accordance with Section 7(b) of the GNU Affero General Public
|
30
|
+
# License, a covered work must retain the producer line in every PDF that
|
31
|
+
# is created or manipulated using HexaPDF.
|
32
|
+
#
|
33
|
+
# If the GNU Affero General Public License doesn't fit your need,
|
34
|
+
# commercial licenses are available at <https://gettalong.at/hexapdf/>.
|
35
|
+
#++
|
36
|
+
|
37
|
+
require 'hexapdf/type/annotations'
|
38
|
+
|
39
|
+
module HexaPDF
|
40
|
+
module Type
|
41
|
+
module Annotations
|
42
|
+
|
43
|
+
# A polyline annotation displays a polyline inside the annotation rectangle.
|
44
|
+
#
|
45
|
+
# Also see PolygonPolyline for more information.
|
46
|
+
#
|
47
|
+
# Example:
|
48
|
+
#
|
49
|
+
# #>pdf-small
|
50
|
+
# doc.annotations.create_polyline(doc.pages[0], 20, 20, 30, 70, 80, 60, 40, 30).
|
51
|
+
# border_style(color: "hp-blue", width: 2, style: [3, 1]).
|
52
|
+
# interior_color("hp-orange").
|
53
|
+
# regenerate_appearance
|
54
|
+
#
|
55
|
+
# See: PDF2.0 s12.5.6.9, HexaPDF::Type::Annotations::PolygonPolyline
|
56
|
+
class Polyline < PolygonPolyline
|
57
|
+
|
58
|
+
define_field :Subtype, type: Symbol, required: true, default: :PolyLine
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -56,6 +56,10 @@ module HexaPDF
|
|
56
56
|
autoload(:SquareCircle, 'hexapdf/type/annotations/square_circle')
|
57
57
|
autoload(:Square, 'hexapdf/type/annotations/square')
|
58
58
|
autoload(:Circle, 'hexapdf/type/annotations/circle')
|
59
|
+
autoload(:LineEndingStyling, 'hexapdf/type/annotations/line_ending_styling')
|
60
|
+
autoload(:PolygonPolyline, 'hexapdf/type/annotations/polygon_polyline')
|
61
|
+
autoload(:Polygon, 'hexapdf/type/annotations/polygon')
|
62
|
+
autoload(:Polyline, 'hexapdf/type/annotations/polyline')
|
59
63
|
|
60
64
|
end
|
61
65
|
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# -*- encoding: utf-8; frozen_string_literal: true -*-
|
2
|
+
#
|
3
|
+
#--
|
4
|
+
# This file is part of HexaPDF.
|
5
|
+
#
|
6
|
+
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
|
7
|
+
# Copyright (C) 2014-2025 Thomas Leitner
|
8
|
+
#
|
9
|
+
# HexaPDF is free software: you can redistribute it and/or modify it
|
10
|
+
# under the terms of the GNU Affero General Public License version 3 as
|
11
|
+
# published by the Free Software Foundation with the addition of the
|
12
|
+
# following permission added to Section 15 as permitted in Section 7(a):
|
13
|
+
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
|
14
|
+
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
|
15
|
+
# INFRINGEMENT OF THIRD PARTY RIGHTS.
|
16
|
+
#
|
17
|
+
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
|
18
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
20
|
+
# License for more details.
|
21
|
+
#
|
22
|
+
# You should have received a copy of the GNU Affero General Public License
|
23
|
+
# along with HexaPDF. If not, see <http://www.gnu.org/licenses/>.
|
24
|
+
#
|
25
|
+
# The interactive user interfaces in modified source and object code
|
26
|
+
# versions of HexaPDF must display Appropriate Legal Notices, as required
|
27
|
+
# under Section 5 of the GNU Affero General Public License version 3.
|
28
|
+
#
|
29
|
+
# In accordance with Section 7(b) of the GNU Affero General Public
|
30
|
+
# License, a covered work must retain the producer line in every PDF that
|
31
|
+
# is created or manipulated using HexaPDF.
|
32
|
+
#
|
33
|
+
# If the GNU Affero General Public License doesn't fit your need,
|
34
|
+
# commercial licenses are available at <https://gettalong.at/hexapdf/>.
|
35
|
+
#++
|
36
|
+
|
37
|
+
require 'hexapdf/dictionary'
|
38
|
+
|
39
|
+
module HexaPDF
|
40
|
+
module Type
|
41
|
+
|
42
|
+
# A Measure dictionary specifies how measurement information should be formatted in textual
|
43
|
+
# form.
|
44
|
+
#
|
45
|
+
# See: PDF2.0 s12.9.1
|
46
|
+
class Measure < Dictionary
|
47
|
+
|
48
|
+
define_type :Measure
|
49
|
+
|
50
|
+
define_field :Type, type: Symbol, default: type
|
51
|
+
define_field :Subtype, type: Symbol, default: :RL,
|
52
|
+
allowed_values: [:RL, :GEO]
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
data/lib/hexapdf/type.rb
CHANGED
@@ -88,6 +88,7 @@ module HexaPDF
|
|
88
88
|
autoload(:Namespace, 'hexapdf/type/namespace')
|
89
89
|
autoload(:MarkedContentReference, 'hexapdf/type/marked_content_reference')
|
90
90
|
autoload(:ObjectReference, 'hexapdf/type/object_reference')
|
91
|
+
autoload(:Measure, 'hexapdf/type/measure')
|
91
92
|
|
92
93
|
end
|
93
94
|
|
data/lib/hexapdf/version.rb
CHANGED
@@ -151,7 +151,6 @@ describe HexaPDF::DigitalSignature::Signing::DefaultHandler do
|
|
151
151
|
@handler.finalize_objects(@field, @obj)
|
152
152
|
ref = @obj[:Reference][0]
|
153
153
|
assert_equal(:DocMDP, ref[:TransformMethod])
|
154
|
-
assert_equal(:SHA256, ref[:DigestMethod])
|
155
154
|
assert_equal(1, ref[:TransformParams][:P])
|
156
155
|
assert_equal(:'1.2', ref[:TransformParams][:V])
|
157
156
|
assert_same(@obj, @doc.catalog[:Perms][:DocMDP])
|
@@ -52,4 +52,24 @@ describe HexaPDF::Document::Annotations do
|
|
52
52
|
assert_equal(annot, @page[:Annots].first)
|
53
53
|
end
|
54
54
|
end
|
55
|
+
|
56
|
+
describe "create_polyline" do
|
57
|
+
it "creates an appropriate polyline annotation object" do
|
58
|
+
annot = @annots.create(:polyline, @page, 10, 10, 20, 15)
|
59
|
+
assert_equal(:Annot, annot[:Type])
|
60
|
+
assert_equal(:PolyLine, annot[:Subtype])
|
61
|
+
assert_equal([10, 10, 20, 15], annot.vertices)
|
62
|
+
assert_equal(annot, @page[:Annots].first)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "create_polygon" do
|
67
|
+
it "creates an appropriate polygon annotation object" do
|
68
|
+
annot = @annots.create(:polygon, @page, 10, 10, 20, 15)
|
69
|
+
assert_equal(:Annot, annot[:Type])
|
70
|
+
assert_equal(:Polygon, annot[:Subtype])
|
71
|
+
assert_equal([10, 10, 20, 15], annot.vertices)
|
72
|
+
assert_equal(annot, @page[:Annots].first)
|
73
|
+
end
|
74
|
+
end
|
55
75
|
end
|
@@ -110,11 +110,12 @@ describe HexaPDF::Document::Layout::CellArgumentCollector do
|
|
110
110
|
assert_equal({key: :value, a: :c, e: :f}, @args.retrieve_arguments_for(5, 6))
|
111
111
|
end
|
112
112
|
|
113
|
-
it "deep merges the :cell keys" do
|
114
|
-
@args[] = {cell: {a: :b, c: :d}}
|
113
|
+
it "deep merges the :cell keys in order of definition" do
|
115
114
|
@args[3..7] = {cell: {a: :y, e: :f}}
|
115
|
+
@args[] = {cell: {a: :b, c: :d}}
|
116
116
|
@args[5, 6] = {cell: {a: :z}}
|
117
117
|
assert_equal({cell: {a: :z, c: :d, e: :f}}, @args.retrieve_arguments_for(5, 6))
|
118
|
+
assert_equal({cell: {a: :b, c: :d}}, @args.retrieve_arguments_for(1, 2))
|
118
119
|
end
|
119
120
|
end
|
120
121
|
end
|
@@ -172,31 +173,36 @@ describe HexaPDF::Document::Layout do
|
|
172
173
|
end
|
173
174
|
end
|
174
175
|
|
175
|
-
describe "
|
176
|
+
describe "resolve_font" do
|
176
177
|
it "resolves a font name to a font wrapper" do
|
177
|
-
style = @layout.
|
178
|
+
style = @layout.style(:other, font: 'Helvetica')
|
179
|
+
@layout.resolve_font(style)
|
178
180
|
assert_kind_of(HexaPDF::Font::Type1Wrapper, style.font)
|
179
181
|
end
|
180
182
|
|
181
183
|
it "uses the font_bold property when resolving a font name to a font wrapper" do
|
182
|
-
style = @layout.
|
184
|
+
style = @layout.style(:other, font: 'Helvetica', font_bold: true)
|
185
|
+
@layout.resolve_font(style)
|
183
186
|
assert_equal('Helvetica-Bold', style.font.wrapped_font.font_name)
|
184
187
|
end
|
185
188
|
|
186
189
|
it "uses the font_italic property when resolving a font name to a font wrapper" do
|
187
|
-
style = @layout.
|
190
|
+
style = @layout.style(:other, font: 'Helvetica', font_italic: true)
|
191
|
+
@layout.resolve_font(style)
|
188
192
|
assert_equal('Helvetica-Oblique', style.font.wrapped_font.font_name)
|
189
193
|
end
|
190
194
|
|
191
195
|
it "sets the :base style's font if no font is set" do
|
192
196
|
@layout.style(:base, font: 'Helvetica')
|
193
|
-
style = @layout.
|
194
|
-
|
197
|
+
style = @layout.style(:other, base: nil, font_italic: true)
|
198
|
+
@layout.resolve_font(style)
|
199
|
+
assert_equal('Helvetica-Oblique', style.font.wrapped_font.font_name)
|
195
200
|
end
|
196
201
|
|
197
202
|
it "sets the font specified in the config option font.default as fallback" do
|
198
|
-
style = @layout.
|
199
|
-
|
203
|
+
style = @layout.style(:other, base: nil, font_italic: true)
|
204
|
+
@layout.resolve_font(style)
|
205
|
+
assert_equal('Times-Italic', style.font.wrapped_font.font_name)
|
200
206
|
end
|
201
207
|
end
|
202
208
|
|
@@ -13,6 +13,17 @@ describe HexaPDF::Document::Metadata do
|
|
13
13
|
|
14
14
|
it "parses the info dictionary on creation" do
|
15
15
|
assert_equal('Title', @metadata.title)
|
16
|
+
|
17
|
+
time = Time.now
|
18
|
+
@doc.trailer.info[:ModDate] = ''
|
19
|
+
assert_nil(HexaPDF::Document::Metadata.new(@doc).modification_date)
|
20
|
+
@doc.trailer.info[:ModDate] = time
|
21
|
+
assert_equal(time, HexaPDF::Document::Metadata.new(@doc).modification_date)
|
22
|
+
@doc.trailer.info[:CreationDate] = ''
|
23
|
+
assert_nil(HexaPDF::Document::Metadata.new(@doc).creation_date)
|
24
|
+
@doc.trailer.info[:CreationDate] = time
|
25
|
+
assert_equal(time, HexaPDF::Document::Metadata.new(@doc).creation_date)
|
26
|
+
|
16
27
|
@doc.trailer.info[:Trapped] = :Unknown
|
17
28
|
assert_nil(HexaPDF::Document::Metadata.new(@doc).trapped)
|
18
29
|
@doc.trailer.info[:Trapped] = :True
|
@@ -213,6 +224,7 @@ describe HexaPDF::Document::Metadata do
|
|
213
224
|
title.language = 'de'
|
214
225
|
@metadata.title(['Title', title])
|
215
226
|
@metadata.author(['Author 1', 'Author 2'])
|
227
|
+
@metadata.creation_date('')
|
216
228
|
@metadata.register_property_type('dc', 'other', 'URI')
|
217
229
|
@metadata.property('dc', 'other', 'https://test.org/example')
|
218
230
|
@metadata.property('pdfaid', 'part', 3)
|
@@ -243,7 +255,7 @@ describe HexaPDF::Document::Metadata do
|
|
243
255
|
</rdf:Description>
|
244
256
|
<rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">
|
245
257
|
<xmp:CreatorTool>Creator</xmp:CreatorTool>
|
246
|
-
<xmp:CreateDate
|
258
|
+
<xmp:CreateDate></xmp:CreateDate>
|
247
259
|
<xmp:ModifyDate>#{@metadata.send(:xmp_date, @time)}</xmp:ModifyDate>
|
248
260
|
</rdf:Description>
|
249
261
|
<rdf:Description rdf:about="" xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/">
|