pdf-core 0.4.0 → 0.10.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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data/lib/pdf/core/annotations.rb +58 -21
- data/lib/pdf/core/byte_string.rb +6 -3
- data/lib/pdf/core/destinations.rb +77 -34
- data/lib/pdf/core/document_state.rb +121 -30
- data/lib/pdf/core/filter_list.rb +47 -6
- data/lib/pdf/core/filters.rb +31 -12
- data/lib/pdf/core/graphics_state.rb +80 -32
- data/lib/pdf/core/literal_string.rb +11 -10
- data/lib/pdf/core/name_tree.rb +118 -54
- data/lib/pdf/core/object_store.rb +82 -37
- data/lib/pdf/core/outline_item.rb +62 -7
- data/lib/pdf/core/outline_root.rb +21 -3
- data/lib/pdf/core/page.rb +232 -77
- data/lib/pdf/core/page_geometry.rb +56 -112
- data/lib/pdf/core/pdf_object.rb +93 -57
- data/lib/pdf/core/reference.rb +70 -30
- data/lib/pdf/core/renderer.rb +149 -68
- data/lib/pdf/core/stream.rb +48 -12
- data/lib/pdf/core/text.rb +300 -106
- data/lib/pdf/core/utils.rb +21 -0
- data/lib/pdf/core.rb +38 -25
- data/pdf-core.gemspec +43 -24
- data.tar.gz.sig +0 -0
- metadata +56 -64
- metadata.gz.sig +2 -0
- data/Gemfile +0 -3
- data/Rakefile +0 -11
- data/spec/filters_spec.rb +0 -34
- data/spec/name_tree_spec.rb +0 -122
- data/spec/object_store_spec.rb +0 -49
- data/spec/pdf_object_spec.rb +0 -172
- data/spec/reference_spec.rb +0 -62
- data/spec/spec_helper.rb +0 -32
- data/spec/stream_spec.rb +0 -59
|
@@ -1,8 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module PDF
|
|
2
4
|
module Core
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
# Outline item.
|
|
6
|
+
#
|
|
7
|
+
# @api private
|
|
8
|
+
# @see # PDF 1.7 spec, section 8.2.2 Document Outline
|
|
9
|
+
class OutlineItem
|
|
10
|
+
# The total number of its open descendants at all lower levels of the
|
|
11
|
+
# outline hierarchy.
|
|
12
|
+
# @return [Integer]
|
|
13
|
+
attr_accessor :count
|
|
14
|
+
|
|
15
|
+
# The first of this item’s immediate children in the outline hierarchy.
|
|
16
|
+
# @return [Reference<PDF::Core::OutlineItem>]
|
|
17
|
+
attr_accessor :first
|
|
18
|
+
|
|
19
|
+
# The last of this item’s immediate children in the outline hierarchy.
|
|
20
|
+
# @return [Reference<PDF::Core::OutlineItem>]
|
|
21
|
+
attr_accessor :last
|
|
22
|
+
|
|
23
|
+
# The next item at this outline level.
|
|
24
|
+
# @return [Reference<PDF::Core::OutlineItem>]
|
|
25
|
+
attr_accessor :next
|
|
26
|
+
|
|
27
|
+
# The previous item at this outline level.
|
|
28
|
+
# @return [Reference<PDF::Core::OutlineItem>]
|
|
29
|
+
attr_accessor :prev
|
|
30
|
+
|
|
31
|
+
# The parent of this item in the outline hierarchy.
|
|
32
|
+
# @return [Reference<[PDF::Core::OutlineItem, PDF::Core::OutlineRoot]>]
|
|
33
|
+
attr_accessor :parent
|
|
34
|
+
|
|
35
|
+
# The text to be displayed on the screen for this item.
|
|
36
|
+
# @return [String]
|
|
37
|
+
attr_accessor :title
|
|
38
|
+
|
|
39
|
+
# The destination to be displayed when this item is activated.
|
|
40
|
+
# @return [String]
|
|
41
|
+
# @return [Symbol]
|
|
42
|
+
# @return [Array]
|
|
43
|
+
# @see Destinations
|
|
44
|
+
attr_accessor :dest
|
|
45
|
+
|
|
46
|
+
# Is this item open or closed.
|
|
47
|
+
# @return [Boolean]
|
|
48
|
+
attr_accessor :closed
|
|
5
49
|
|
|
50
|
+
# @param title [String]
|
|
51
|
+
# @param parent [PDF::Core::OutlineRoot, PDF::Core::OutlineItem]
|
|
52
|
+
# @param options [Hash]
|
|
53
|
+
# @option options :closed [Boolean]
|
|
6
54
|
def initialize(title, parent, options)
|
|
7
55
|
@closed = options[:closed]
|
|
8
56
|
@title = title
|
|
@@ -10,12 +58,19 @@ module PDF
|
|
|
10
58
|
@count = 0
|
|
11
59
|
end
|
|
12
60
|
|
|
61
|
+
# A hash representation of this outline item.
|
|
62
|
+
#
|
|
63
|
+
# @return [Hash]
|
|
13
64
|
def to_hash
|
|
14
|
-
hash = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
65
|
+
hash = {
|
|
66
|
+
Title: title,
|
|
67
|
+
Parent: parent,
|
|
68
|
+
Count: closed ? -count : count,
|
|
69
|
+
}
|
|
70
|
+
[
|
|
71
|
+
{ First: first }, { Last: last }, { Next: defined?(@next) && @next },
|
|
72
|
+
{ Prev: prev }, { Dest: dest },
|
|
73
|
+
].each do |h|
|
|
19
74
|
unless h.values.first.nil?
|
|
20
75
|
hash.merge!(h)
|
|
21
76
|
end
|
|
@@ -1,14 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module PDF
|
|
2
4
|
module Core
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
# Document Outline root.
|
|
6
|
+
#
|
|
7
|
+
# @api private
|
|
8
|
+
# @see # PDF 1.7 spec, section 8.2.2 Document Outline
|
|
9
|
+
class OutlineRoot
|
|
10
|
+
# The total number of open items at all levels of the outline.
|
|
11
|
+
# @return [Integer]
|
|
12
|
+
attr_accessor :count
|
|
13
|
+
|
|
14
|
+
# The first top-level item in the outline.
|
|
15
|
+
# @return [Reference]
|
|
16
|
+
attr_accessor :first
|
|
17
|
+
|
|
18
|
+
# The last top-level item in the outline.
|
|
19
|
+
# @return [Reference]
|
|
20
|
+
attr_accessor :last
|
|
5
21
|
|
|
6
22
|
def initialize
|
|
7
23
|
@count = 0
|
|
8
24
|
end
|
|
9
25
|
|
|
26
|
+
# Hash representation of the outline root
|
|
27
|
+
# @return [Hash]
|
|
10
28
|
def to_hash
|
|
11
|
-
{:
|
|
29
|
+
{ Type: :Outlines, Count: count, First: first, Last: last }
|
|
12
30
|
end
|
|
13
31
|
end
|
|
14
32
|
end
|
data/lib/pdf/core/page.rb
CHANGED
|
@@ -1,38 +1,132 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
# prawn/core/page.rb : Implements low-level representation of a PDF page
|
|
4
|
-
#
|
|
5
|
-
# Copyright February 2010, Gregory Brown. All Rights Reserved.
|
|
6
|
-
#
|
|
7
|
-
# This is free software. Please see the LICENSE and COPYING files for details.
|
|
8
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
9
2
|
|
|
10
3
|
require_relative 'graphics_state'
|
|
11
4
|
|
|
12
5
|
module PDF
|
|
13
6
|
module Core
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
# Low-level representation of a PDF page
|
|
8
|
+
#
|
|
9
|
+
# @api private
|
|
10
|
+
class Page
|
|
11
|
+
# Page art box indents relative to page edges.
|
|
12
|
+
#
|
|
13
|
+
# @return [Hash<[:left, :right, :top, :bottom], Numeric>
|
|
14
|
+
attr_accessor :art_indents
|
|
15
|
+
|
|
16
|
+
# Page bleed box indents.
|
|
17
|
+
#
|
|
18
|
+
# @return [Hash<[:left, :right, :top, :bottom], Numeric>
|
|
19
|
+
attr_accessor :bleeds
|
|
20
|
+
|
|
21
|
+
# Page crop box indents.
|
|
22
|
+
#
|
|
23
|
+
# @return [Hash<[:left, :right, :top, :bottom], Numeric>
|
|
24
|
+
attr_accessor :crops
|
|
25
|
+
|
|
26
|
+
# Page trim box indents.
|
|
27
|
+
#
|
|
28
|
+
# @return [Hash<[:left, :right, :top, :bottom], Numeric>
|
|
29
|
+
attr_accessor :trims
|
|
30
|
+
|
|
31
|
+
# Page margins.
|
|
32
|
+
#
|
|
33
|
+
# @return [Hash<[:left, :right, :top, :bottom], Numeric>
|
|
34
|
+
attr_accessor :margins
|
|
35
|
+
|
|
36
|
+
# Owning document.
|
|
37
|
+
#
|
|
38
|
+
# @return [Prawn::Document]
|
|
39
|
+
attr_accessor :document
|
|
40
|
+
|
|
41
|
+
# Graphic state stack.
|
|
42
|
+
#
|
|
43
|
+
# @return [GraphicStateStack]
|
|
44
|
+
attr_accessor :stack
|
|
17
45
|
|
|
18
|
-
|
|
46
|
+
# Page content stream reference.
|
|
47
|
+
#
|
|
48
|
+
# @return [PDF::Core::Reference<Hash>]
|
|
49
|
+
attr_writer :content
|
|
50
|
+
|
|
51
|
+
# Page dictionary reference.
|
|
52
|
+
#
|
|
53
|
+
# @return [PDF::Core::Reference<Hash>]
|
|
54
|
+
attr_writer :dictionary
|
|
55
|
+
|
|
56
|
+
# A convenince constant of no indents.
|
|
57
|
+
ZERO_INDENTS = {
|
|
58
|
+
left: 0,
|
|
59
|
+
bottom: 0,
|
|
60
|
+
right: 0,
|
|
61
|
+
top: 0,
|
|
62
|
+
}.freeze
|
|
63
|
+
|
|
64
|
+
# @param document [Prawn::Document]
|
|
65
|
+
# @param options [Hash]
|
|
66
|
+
# @option options :margins [Hash{:left, :right, :top, :bottom => Number}, nil]
|
|
67
|
+
# ({ left: 0, right: 0, top: 0, bottom: 0 }) Page margins
|
|
68
|
+
# @option options :crop [Hash{:left, :right, :top, :bottom => Number}, nil] (ZERO_INDENTS)
|
|
69
|
+
# Page crop box
|
|
70
|
+
# @option options :bleed [Hash{:left, :right, :top, :bottom => Number}, nil] (ZERO_INDENTS)
|
|
71
|
+
# Page bleed box
|
|
72
|
+
# @option options :trims [Hash{:left, :right, :top, :bottom => Number}, nil] (ZERO_INDENTS)
|
|
73
|
+
# Page trim box
|
|
74
|
+
# @option options :art_indents [Hash{:left, :right, :top, :bottom => Number}, Numeric>, nil] (ZERO_INDENTS)
|
|
75
|
+
# Page art box indents.
|
|
76
|
+
# @option options :graphic_state [PDF::Core::GraphicState, nil] (nil)
|
|
77
|
+
# Initial graphic state
|
|
78
|
+
# @option options :size [String, Array<Numeric>, nil] ('LETTER')
|
|
79
|
+
# Page size. A string identifies a named page size defined in
|
|
80
|
+
# {PageGeometry}. An array must be a two element array specifying width
|
|
81
|
+
# and height in points.
|
|
82
|
+
# @option options :layout [:portrait, :landscape, nil] (:portrait)
|
|
83
|
+
# Page orientation.
|
|
84
|
+
def initialize(document, options = {})
|
|
19
85
|
@document = document
|
|
20
|
-
@margins
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
86
|
+
@margins = options[:margins] || {
|
|
87
|
+
left: 36,
|
|
88
|
+
right: 36,
|
|
89
|
+
top: 36,
|
|
90
|
+
bottom: 36,
|
|
91
|
+
}
|
|
92
|
+
@crops = options[:crops] || ZERO_INDENTS
|
|
93
|
+
@bleeds = options[:bleeds] || ZERO_INDENTS
|
|
94
|
+
@trims = options[:trims] || ZERO_INDENTS
|
|
95
|
+
@art_indents = options[:art_indents] || ZERO_INDENTS
|
|
24
96
|
@stack = GraphicStateStack.new(options[:graphic_state])
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
97
|
+
@size = options[:size] || 'LETTER'
|
|
98
|
+
@layout = options[:layout] || :portrait
|
|
99
|
+
|
|
100
|
+
@stamp_stream = nil
|
|
101
|
+
@stamp_dictionary = nil
|
|
102
|
+
|
|
103
|
+
@content = document.ref({})
|
|
104
|
+
content << 'q' << "\n"
|
|
105
|
+
@dictionary = document.ref(
|
|
106
|
+
Type: :Page,
|
|
107
|
+
Parent: document.state.store.pages,
|
|
108
|
+
MediaBox: dimensions,
|
|
109
|
+
CropBox: crop_box,
|
|
110
|
+
BleedBox: bleed_box,
|
|
111
|
+
TrimBox: trim_box,
|
|
112
|
+
ArtBox: art_box,
|
|
113
|
+
Contents: content,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
resources[:ProcSet] = %i[PDF Text ImageB ImageC ImageI]
|
|
30
117
|
end
|
|
31
118
|
|
|
119
|
+
# Current graphic state.
|
|
120
|
+
#
|
|
121
|
+
# @return [PDF::Core::GraphicState]
|
|
32
122
|
def graphic_state
|
|
33
123
|
stack.current_state
|
|
34
124
|
end
|
|
35
125
|
|
|
126
|
+
# Page layout.
|
|
127
|
+
#
|
|
128
|
+
# @return [:portrait] if page is talled than wider
|
|
129
|
+
# @return [:landscape] otherwise
|
|
36
130
|
def layout
|
|
37
131
|
return @layout if defined?(@layout) && @layout
|
|
38
132
|
|
|
@@ -44,41 +138,63 @@ module PDF
|
|
|
44
138
|
end
|
|
45
139
|
end
|
|
46
140
|
|
|
141
|
+
# Page size.
|
|
142
|
+
#
|
|
143
|
+
# @return [Array<Numeric>] a two-element array containing width and height
|
|
144
|
+
# of the page.
|
|
47
145
|
def size
|
|
48
|
-
defined?(@size) && @size || dimensions[2,2]
|
|
146
|
+
(defined?(@size) && @size) || dimensions[2, 2]
|
|
49
147
|
end
|
|
50
148
|
|
|
149
|
+
# Are we drawing to a stamp right now?
|
|
150
|
+
#
|
|
151
|
+
# @return [Boolean]
|
|
51
152
|
def in_stamp_stream?
|
|
52
|
-
|
|
153
|
+
!@stamp_stream.nil?
|
|
53
154
|
end
|
|
54
155
|
|
|
156
|
+
# Draw to stamp.
|
|
157
|
+
#
|
|
158
|
+
# @param dictionary [PDF::Core::Reference<Hash>] stamp dictionary
|
|
159
|
+
# @yield outputs to the stamp
|
|
160
|
+
# @return [void]
|
|
55
161
|
def stamp_stream(dictionary)
|
|
56
|
-
@stamp_stream = ""
|
|
57
162
|
@stamp_dictionary = dictionary
|
|
163
|
+
@stamp_stream = @stamp_dictionary.stream
|
|
58
164
|
graphic_stack_size = stack.stack.size
|
|
59
165
|
|
|
60
166
|
document.save_graphics_state
|
|
61
|
-
document.
|
|
167
|
+
document.__send__(:freeze_stamp_graphics)
|
|
62
168
|
yield if block_given?
|
|
63
169
|
|
|
64
170
|
until graphic_stack_size == stack.stack.size
|
|
65
171
|
document.restore_graphics_state
|
|
66
172
|
end
|
|
67
173
|
|
|
68
|
-
@
|
|
69
|
-
|
|
70
|
-
@stamp_stream = nil
|
|
71
|
-
@stamp_dictionary = nil
|
|
174
|
+
@stamp_stream = nil
|
|
175
|
+
@stamp_dictionary = nil
|
|
72
176
|
end
|
|
73
177
|
|
|
178
|
+
# Current content stream. Can be either the page content stream or a stamp
|
|
179
|
+
# content stream.
|
|
180
|
+
#
|
|
181
|
+
# @return [PDF::Core::Reference<Hash>]
|
|
74
182
|
def content
|
|
75
183
|
@stamp_stream || document.state.store[@content]
|
|
76
184
|
end
|
|
77
185
|
|
|
186
|
+
# Current content dictionary. Can be either the page dictionary or a stamp
|
|
187
|
+
# dictionary.
|
|
188
|
+
#
|
|
189
|
+
# @return [PDF::Core::Reference<Hash>]
|
|
78
190
|
def dictionary
|
|
79
|
-
defined?(@stamp_dictionary) && @stamp_dictionary ||
|
|
191
|
+
(defined?(@stamp_dictionary) && @stamp_dictionary) ||
|
|
192
|
+
document.state.store[@dictionary]
|
|
80
193
|
end
|
|
81
194
|
|
|
195
|
+
# Page resources dictionary.
|
|
196
|
+
#
|
|
197
|
+
# @return [Hash]
|
|
82
198
|
def resources
|
|
83
199
|
if dictionary.data[:Resources]
|
|
84
200
|
document.deref(dictionary.data[:Resources])
|
|
@@ -87,6 +203,9 @@ module PDF
|
|
|
87
203
|
end
|
|
88
204
|
end
|
|
89
205
|
|
|
206
|
+
# Fonts dictionary.
|
|
207
|
+
#
|
|
208
|
+
# @return [Hash]
|
|
90
209
|
def fonts
|
|
91
210
|
if resources[:Font]
|
|
92
211
|
document.deref(resources[:Font])
|
|
@@ -95,6 +214,9 @@ module PDF
|
|
|
95
214
|
end
|
|
96
215
|
end
|
|
97
216
|
|
|
217
|
+
# External objects dictionary.
|
|
218
|
+
#
|
|
219
|
+
# @return [Hash]
|
|
98
220
|
def xobjects
|
|
99
221
|
if resources[:XObject]
|
|
100
222
|
document.deref(resources[:XObject])
|
|
@@ -103,6 +225,9 @@ module PDF
|
|
|
103
225
|
end
|
|
104
226
|
end
|
|
105
227
|
|
|
228
|
+
# Graphic state parameter dictionary.
|
|
229
|
+
#
|
|
230
|
+
# @return [Hash]
|
|
106
231
|
def ext_gstates
|
|
107
232
|
if resources[:ExtGState]
|
|
108
233
|
document.deref(resources[:ExtGState])
|
|
@@ -111,67 +236,99 @@ module PDF
|
|
|
111
236
|
end
|
|
112
237
|
end
|
|
113
238
|
|
|
239
|
+
# Finalize page.
|
|
240
|
+
#
|
|
241
|
+
# @return [void]
|
|
114
242
|
def finalize
|
|
115
243
|
if dictionary.data[:Contents].is_a?(Array)
|
|
116
244
|
dictionary.data[:Contents].each do |stream|
|
|
117
245
|
stream.stream.compress! if document.compression_enabled?
|
|
118
246
|
end
|
|
119
|
-
|
|
120
|
-
content.stream.compress!
|
|
247
|
+
elsif document.compression_enabled?
|
|
248
|
+
content.stream.compress!
|
|
121
249
|
end
|
|
122
250
|
end
|
|
123
251
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
252
|
+
# Page dimensions.
|
|
253
|
+
#
|
|
254
|
+
# @return [Array<Numeric>]
|
|
128
255
|
def dimensions
|
|
129
|
-
return inherited_dictionary_value(:MediaBox) if imported_page?
|
|
130
|
-
|
|
131
256
|
coords = PDF::Core::PageGeometry::SIZES[size] || size
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
257
|
+
coords =
|
|
258
|
+
case layout
|
|
259
|
+
when :portrait
|
|
260
|
+
coords
|
|
261
|
+
when :landscape
|
|
262
|
+
coords.reverse
|
|
263
|
+
else
|
|
264
|
+
raise PDF::Core::Errors::InvalidPageLayout,
|
|
265
|
+
'Layout must be either :portrait or :landscape'
|
|
266
|
+
end
|
|
267
|
+
[0, 0].concat(coords)
|
|
141
268
|
end
|
|
142
269
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
270
|
+
# A rectangle, expressed in default user space units, defining the extent
|
|
271
|
+
# of the page's meaningful content (including potential white space) as
|
|
272
|
+
# intended by the page's creator.
|
|
273
|
+
#
|
|
274
|
+
# @return [Array<Numeric>]
|
|
275
|
+
def art_box
|
|
276
|
+
left, bottom, right, top = dimensions
|
|
277
|
+
[
|
|
278
|
+
left + art_indents[:left],
|
|
279
|
+
bottom + art_indents[:bottom],
|
|
280
|
+
right - art_indents[:right],
|
|
281
|
+
top - art_indents[:top],
|
|
282
|
+
]
|
|
155
283
|
end
|
|
156
284
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
285
|
+
# Page bleed box. A rectangle, expressed in default user space units,
|
|
286
|
+
# defining the region to which the contents of the page should be clipped
|
|
287
|
+
# when output in a production environment.
|
|
288
|
+
#
|
|
289
|
+
# @return [Array<Numeric>]
|
|
290
|
+
def bleed_box
|
|
291
|
+
left, bottom, right, top = dimensions
|
|
292
|
+
[
|
|
293
|
+
left + bleeds[:left],
|
|
294
|
+
bottom + bleeds[:bottom],
|
|
295
|
+
right - bleeds[:right],
|
|
296
|
+
top - bleeds[:top],
|
|
297
|
+
]
|
|
298
|
+
end
|
|
164
299
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
300
|
+
# A rectangle, expressed in default user space units, defining the visible
|
|
301
|
+
# region of default user space. When the page is displayed or printed, its
|
|
302
|
+
# contents are to be clipped (cropped) to this rectangle and then imposed
|
|
303
|
+
# on the output medium in some implementation-defined manner.
|
|
304
|
+
#
|
|
305
|
+
# @return [Array<Numeric>]
|
|
306
|
+
def crop_box
|
|
307
|
+
left, bottom, right, top = dimensions
|
|
308
|
+
[
|
|
309
|
+
left + crops[:left],
|
|
310
|
+
bottom + crops[:bottom],
|
|
311
|
+
right - crops[:right],
|
|
312
|
+
top - crops[:top],
|
|
313
|
+
]
|
|
314
|
+
end
|
|
171
315
|
|
|
172
|
-
|
|
316
|
+
# A rectangle, expressed in default user space units, defining the
|
|
317
|
+
# intended dimensions of the finished page after trimming.
|
|
318
|
+
#
|
|
319
|
+
# @return [Array<Numeric>]
|
|
320
|
+
def trim_box
|
|
321
|
+
left, bottom, right, top = dimensions
|
|
322
|
+
[
|
|
323
|
+
left + trims[:left],
|
|
324
|
+
bottom + trims[:bottom],
|
|
325
|
+
right - trims[:right],
|
|
326
|
+
top - trims[:top],
|
|
327
|
+
]
|
|
173
328
|
end
|
|
174
329
|
|
|
330
|
+
private
|
|
331
|
+
|
|
175
332
|
# some entries in the Page dict can be inherited from parent Pages dicts.
|
|
176
333
|
#
|
|
177
334
|
# Starting with the current page dict, this method will walk up the
|
|
@@ -183,12 +340,10 @@ module PDF
|
|
|
183
340
|
def inherited_dictionary_value(key, local_dict = nil)
|
|
184
341
|
local_dict ||= dictionary.data
|
|
185
342
|
|
|
186
|
-
if local_dict.
|
|
343
|
+
if local_dict.key?(key)
|
|
187
344
|
local_dict[key]
|
|
188
|
-
elsif local_dict.
|
|
345
|
+
elsif local_dict.key?(:Parent)
|
|
189
346
|
inherited_dictionary_value(key, local_dict[:Parent].data)
|
|
190
|
-
else
|
|
191
|
-
nil
|
|
192
347
|
end
|
|
193
348
|
end
|
|
194
349
|
end
|