pdf-core 0.8.1 → 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 +51 -13
- data/lib/pdf/core/byte_string.rb +3 -2
- data/lib/pdf/core/destinations.rb +64 -24
- data/lib/pdf/core/document_state.rb +100 -17
- data/lib/pdf/core/filter_list.rb +44 -5
- data/lib/pdf/core/filters.rb +26 -7
- data/lib/pdf/core/graphics_state.rb +74 -30
- data/lib/pdf/core/literal_string.rb +9 -10
- data/lib/pdf/core/name_tree.rb +76 -16
- data/lib/pdf/core/object_store.rb +69 -19
- data/lib/pdf/core/outline_item.rb +53 -5
- data/lib/pdf/core/outline_root.rb +18 -2
- data/lib/pdf/core/page.rb +158 -32
- data/lib/pdf/core/page_geometry.rb +4 -58
- data/lib/pdf/core/pdf_object.rb +62 -37
- data/lib/pdf/core/reference.rb +58 -15
- data/lib/pdf/core/renderer.rb +116 -47
- data/lib/pdf/core/stream.rb +43 -7
- data/lib/pdf/core/text.rb +255 -106
- data/lib/pdf/core/utils.rb +10 -1
- data/lib/pdf/core.rb +26 -16
- data/pdf-core.gemspec +31 -27
- data.tar.gz.sig +0 -0
- metadata +36 -101
- metadata.gz.sig +2 -1
- data/Gemfile +0 -5
- data/Rakefile +0 -17
data/lib/pdf/core/text.rb
CHANGED
@@ -8,28 +8,46 @@
|
|
8
8
|
|
9
9
|
module PDF
|
10
10
|
module Core
|
11
|
-
|
11
|
+
# Low-level text rendering.
|
12
|
+
module Text
|
13
|
+
# Valid options of text drawing.
|
12
14
|
# These should be used as a base. Extensions may build on this list
|
13
|
-
#
|
14
15
|
VALID_OPTIONS = %i[kerning size style].freeze
|
16
|
+
|
17
|
+
# text rendering modes
|
15
18
|
MODES = {
|
16
19
|
fill: 0,
|
17
20
|
stroke: 1,
|
18
21
|
fill_stroke: 2,
|
19
22
|
invisible: 3,
|
20
|
-
fill_clip: 4,
|
23
|
+
fill_clip: 4,
|
24
|
+
stroke_clip: 5,
|
21
25
|
fill_stroke_clip: 6,
|
22
|
-
clip: 7
|
26
|
+
clip: 7,
|
23
27
|
}.freeze
|
24
28
|
|
29
|
+
# Sygnals that a font doesn't have a name.
|
30
|
+
class BadFontFamily < StandardError
|
31
|
+
def initialize(message = 'Bad font family')
|
32
|
+
super
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# @deprecated
|
25
37
|
attr_reader :skip_encoding
|
26
38
|
|
27
39
|
# Low level call to set the current font style and extract text options
|
28
40
|
# from an options hash. Should be called from within a save_font block
|
29
41
|
#
|
42
|
+
# @param options [Hash]
|
43
|
+
# @option options :style [Symbol, String]
|
44
|
+
# @option options :kerning [Boolean]
|
45
|
+
# @option options :size [Numeric]
|
46
|
+
# @return [void]
|
30
47
|
def process_text_options(options)
|
31
48
|
if options[:style]
|
32
|
-
raise
|
49
|
+
raise BadFontFamily unless font.family
|
50
|
+
|
33
51
|
font(font.family, style: options[:style])
|
34
52
|
end
|
35
53
|
|
@@ -43,10 +61,12 @@ module PDF
|
|
43
61
|
|
44
62
|
# Retrieve the current default kerning setting.
|
45
63
|
#
|
46
|
-
# Defaults to true
|
64
|
+
# Defaults to `true`.
|
47
65
|
#
|
66
|
+
# @return [Boolean]
|
48
67
|
def default_kerning?
|
49
68
|
return true unless defined?(@default_kerning)
|
69
|
+
|
50
70
|
@default_kerning
|
51
71
|
end
|
52
72
|
|
@@ -54,12 +74,15 @@ module PDF
|
|
54
74
|
# be overridden using the :kerning text option when drawing text or a text
|
55
75
|
# box.
|
56
76
|
#
|
77
|
+
# @example
|
57
78
|
# pdf.default_kerning = false
|
58
|
-
# pdf.text('hello world')
|
59
|
-
# pdf.text('hello world', :
|
79
|
+
# pdf.text('hello world') # text is not kerned
|
80
|
+
# pdf.text('hello world', kerning: true) # text is kerned
|
60
81
|
#
|
61
|
-
|
62
|
-
|
82
|
+
# @param value [Boolean]
|
83
|
+
# @return [void]
|
84
|
+
def default_kerning(value)
|
85
|
+
@default_kerning = value
|
63
86
|
end
|
64
87
|
|
65
88
|
alias default_kerning= default_kerning
|
@@ -70,15 +93,18 @@ module PDF
|
|
70
93
|
# overridden using the :leading text option when drawing text or a text
|
71
94
|
# box.
|
72
95
|
#
|
96
|
+
# @example
|
73
97
|
# pdf.default_leading = 7
|
74
|
-
# pdf.text('hello world')
|
75
|
-
# pdf.text('hello world', :
|
98
|
+
# pdf.text('hello world') # a leading of 7 is used
|
99
|
+
# pdf.text('hello world', leading: 0) # a leading of 0 is used
|
76
100
|
#
|
77
|
-
# Defaults to 0
|
101
|
+
# Defaults to 0.
|
78
102
|
#
|
103
|
+
# @param number [Numeric]
|
104
|
+
# @return [Numeric]
|
79
105
|
def default_leading(number = nil)
|
80
106
|
if number.nil?
|
81
|
-
defined?(@default_leading) && @default_leading || 0
|
107
|
+
(defined?(@default_leading) && @default_leading) || 0
|
82
108
|
else
|
83
109
|
@default_leading = number
|
84
110
|
end
|
@@ -92,23 +118,27 @@ module PDF
|
|
92
118
|
# overridden using the :direction text option when drawing text or a text
|
93
119
|
# box.
|
94
120
|
#
|
121
|
+
# @example
|
95
122
|
# pdf.text_direction = :rtl
|
96
|
-
# pdf.text('hello world')
|
97
|
-
# pdf.text('hello world', :
|
123
|
+
# pdf.text('hello world') # prints 'dlrow olleh'
|
124
|
+
# pdf.text('hello world', direction: :ltr) # prints 'hello world'
|
98
125
|
#
|
99
126
|
# Valid directions are:
|
100
127
|
#
|
101
|
-
# *
|
102
|
-
# *
|
128
|
+
# * `:ltr` -- left-to-right (default)
|
129
|
+
# * `:rtl` -- right-to-left
|
103
130
|
#
|
104
131
|
# Side effects:
|
105
132
|
#
|
106
|
-
# * When printing left-to-right, the default text alignment is
|
107
|
-
# * When printing right-to-left, the default text alignment is
|
133
|
+
# * When printing left-to-right, the default text alignment is `:left`
|
134
|
+
# * When printing right-to-left, the default text alignment is `:right`
|
108
135
|
#
|
136
|
+
# @param direction [:ltr, :rtl]
|
137
|
+
# @return [:ltr]
|
138
|
+
# @return [:rtl]
|
109
139
|
def text_direction(direction = nil)
|
110
140
|
if direction.nil?
|
111
|
-
defined?(@text_direction) && @text_direction || :ltr
|
141
|
+
(defined?(@text_direction) && @text_direction) || :ltr
|
112
142
|
else
|
113
143
|
@text_direction = direction
|
114
144
|
end
|
@@ -124,33 +154,36 @@ module PDF
|
|
124
154
|
# rendered using the first font that includes the glyph, starting with the
|
125
155
|
# current font and then moving through :fallback_fonts from left to right.
|
126
156
|
#
|
127
|
-
# Call with an empty array to turn off fallback fonts
|
128
|
-
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
# }
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
# }
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
#
|
144
|
-
#
|
157
|
+
# Call with an empty array to turn off fallback fonts.
|
158
|
+
#
|
159
|
+
# @example
|
160
|
+
# file = "#{Prawn::DATADIR}/fonts/gkai00mp.ttf"
|
161
|
+
# font_families['Kai'] = {
|
162
|
+
# normal: { file: file, font: 'Kai' }
|
163
|
+
# }
|
164
|
+
# file = "#{Prawn::DATADIR}/fonts/Action Man.dfont"
|
165
|
+
# font_families['Action Man'] = {
|
166
|
+
# normal: { file: file, font: 'ActionMan' },
|
167
|
+
# }
|
168
|
+
# fallback_fonts ['Times-Roman', 'Kai']
|
169
|
+
# font 'Action Man'
|
170
|
+
# text 'hello ƒ 你好'
|
171
|
+
# # hello prints in Action Man
|
172
|
+
# # ƒ prints in Times-Roman
|
173
|
+
# # 你好 prints in Kai
|
174
|
+
#
|
175
|
+
# fallback_fonts [] # clears document-wide fallback fonts
|
145
176
|
#
|
146
177
|
# Side effects:
|
147
178
|
#
|
148
179
|
# * Increased overhead when fallback fonts are declared as each glyph is
|
149
180
|
# checked to see whether it exists in the current font
|
150
181
|
#
|
182
|
+
# @param fallback_fonts [Array<String>]
|
183
|
+
# @return [Array<String>]
|
151
184
|
def fallback_fonts(fallback_fonts = nil)
|
152
185
|
if fallback_fonts.nil?
|
153
|
-
defined?(@fallback_fonts) && @fallback_fonts || []
|
186
|
+
(defined?(@fallback_fonts) && @fallback_fonts) || []
|
154
187
|
else
|
155
188
|
@fallback_fonts = fallback_fonts
|
156
189
|
end
|
@@ -163,140 +196,256 @@ module PDF
|
|
163
196
|
# Call with a symbol and block to temporarily change the current
|
164
197
|
# text rendering mode.
|
165
198
|
#
|
199
|
+
# Valid modes are:
|
200
|
+
#
|
201
|
+
# * `:fill` - fill text (default)
|
202
|
+
# * `:stroke` - stroke text
|
203
|
+
# * `:fill_stroke` - fill, then stroke text
|
204
|
+
# * `:invisible` - invisible text
|
205
|
+
# * `:fill_clip` - fill text then add to path for clipping
|
206
|
+
# * `:stroke_clip` - stroke text then add to path for clipping
|
207
|
+
# * `:fill_stroke_clip` - fill then stroke text, then add to path for
|
208
|
+
# clipping
|
209
|
+
# * `:clip` - add text to path for clipping
|
210
|
+
#
|
211
|
+
# @example
|
166
212
|
# pdf.text_rendering_mode(:stroke) do
|
167
213
|
# pdf.text('Outlined Text')
|
168
214
|
# end
|
169
215
|
#
|
170
|
-
#
|
171
|
-
#
|
172
|
-
#
|
173
|
-
#
|
174
|
-
|
175
|
-
# * :invisible - invisible text
|
176
|
-
# * :fill_clip - fill text then add to path for clipping
|
177
|
-
# * :stroke_clip - stroke text then add to path for clipping
|
178
|
-
# * :fill_stroke_clip - fill then stroke text, then add to path for
|
179
|
-
# clipping
|
180
|
-
# * :clip - add text to path for clipping
|
181
|
-
def text_rendering_mode(mode = nil)
|
216
|
+
# @param mode [Symbol]
|
217
|
+
# @yield Temporariliy set text rendering mode
|
218
|
+
# @return [Symbol] if called withouth mode
|
219
|
+
# @return [void] otherwise
|
220
|
+
def text_rendering_mode(mode = nil, &block)
|
182
221
|
if mode.nil?
|
183
|
-
return defined?(@text_rendering_mode) && @text_rendering_mode || :fill
|
222
|
+
return (defined?(@text_rendering_mode) && @text_rendering_mode) || :fill
|
184
223
|
end
|
224
|
+
|
185
225
|
unless MODES.key?(mode)
|
186
226
|
raise ArgumentError,
|
187
227
|
"mode must be between one of #{MODES.keys.join(', ')} (#{mode})"
|
188
228
|
end
|
189
|
-
original_mode = text_rendering_mode
|
190
229
|
|
191
|
-
if
|
230
|
+
if text_rendering_mode == mode
|
192
231
|
yield
|
193
232
|
else
|
194
|
-
|
195
|
-
add_content "\n#{MODES[mode]} Tr"
|
196
|
-
yield
|
197
|
-
add_content "\n#{MODES[original_mode]} Tr"
|
198
|
-
@text_rendering_mode = original_mode
|
233
|
+
wrap_and_restore_text_rendering_mode(mode, &block)
|
199
234
|
end
|
200
235
|
end
|
201
236
|
|
237
|
+
# Forget previously set text rendering mode.
|
238
|
+
#
|
239
|
+
# @return [void]
|
202
240
|
def forget_text_rendering_mode!
|
203
241
|
@text_rendering_mode = :unknown
|
204
242
|
end
|
205
243
|
|
206
244
|
# Increases or decreases the space between characters.
|
207
245
|
# For horizontal text, a positive value will increase the space.
|
208
|
-
# For
|
246
|
+
# For vertical text, a positive value will decrease the space.
|
209
247
|
#
|
210
|
-
|
248
|
+
# Call with no arguments to retrieve current character spacing.
|
249
|
+
#
|
250
|
+
# @param amount [Numeric]
|
251
|
+
# @yield Temporarily set character spacing
|
252
|
+
# @return [Numeric] if called without amount
|
253
|
+
# @return [void] otherwise
|
254
|
+
def character_spacing(amount = nil, &block)
|
211
255
|
if amount.nil?
|
212
|
-
return defined?(@character_spacing) && @character_spacing || 0
|
256
|
+
return (defined?(@character_spacing) && @character_spacing) || 0
|
213
257
|
end
|
214
|
-
|
215
|
-
if
|
258
|
+
|
259
|
+
if character_spacing == amount
|
216
260
|
yield
|
217
261
|
else
|
218
|
-
|
219
|
-
add_content "\n#{PDF::Core.real(amount)} Tc"
|
220
|
-
yield
|
221
|
-
add_content "\n#{PDF::Core.real(original_character_spacing)} Tc"
|
222
|
-
@character_spacing = original_character_spacing
|
262
|
+
wrap_and_restore_character_spacing(amount, &block)
|
223
263
|
end
|
224
264
|
end
|
225
265
|
|
226
266
|
# Increases or decreases the space between words.
|
227
267
|
# For horizontal text, a positive value will increase the space.
|
228
|
-
# For
|
268
|
+
# For vertical text, a positive value will decrease the space.
|
269
|
+
#
|
270
|
+
# Call with no arguments to retrieve current word spacing.
|
229
271
|
#
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
272
|
+
# @param amount [Numeric]
|
273
|
+
# @yield Temporarily set word spacing
|
274
|
+
# @return [Numeric] if called without amount
|
275
|
+
# @return [void] otherwise
|
276
|
+
def word_spacing(amount = nil, &block)
|
277
|
+
return (defined?(@word_spacing) && @word_spacing) || 0 if amount.nil?
|
278
|
+
|
279
|
+
if word_spacing == amount
|
234
280
|
yield
|
235
281
|
else
|
236
|
-
|
237
|
-
add_content "\n#{PDF::Core.real(amount)} Tw"
|
238
|
-
yield
|
239
|
-
add_content "\n#{PDF::Core.real(original_word_spacing)} Tw"
|
240
|
-
|
241
|
-
@word_spacing = original_word_spacing
|
282
|
+
wrap_and_restore_word_spacing(amount, &block)
|
242
283
|
end
|
243
284
|
end
|
244
285
|
|
245
|
-
# Set the horizontal scaling.
|
246
|
-
#
|
247
|
-
|
286
|
+
# Set the horizontal scaling.
|
287
|
+
#
|
288
|
+
# @param amount [Numeric] the percentage of the normal width.
|
289
|
+
# @yield Temporarili set text scaling
|
290
|
+
# @return [Numeric] if called with no arguments
|
291
|
+
# @return [void] otherwise
|
292
|
+
def horizontal_text_scaling(amount = nil, &block)
|
248
293
|
if amount.nil?
|
249
|
-
return defined?(@horizontal_text_scaling) &&
|
250
|
-
@horizontal_text_scaling || 100
|
294
|
+
return (defined?(@horizontal_text_scaling) && @horizontal_text_scaling) || 100
|
251
295
|
end
|
252
296
|
|
253
|
-
|
254
|
-
if original_horizontal_text_scaling == amount
|
297
|
+
if horizontal_text_scaling == amount
|
255
298
|
yield
|
256
299
|
else
|
257
|
-
|
258
|
-
|
300
|
+
wrap_and_restore_horizontal_text_scaling(amount, &block)
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
# Move the baseline up or down from its default location.
|
305
|
+
# Positive values move the baseline up, negative values move it down, and
|
306
|
+
# a zero value resets the baseline to its default location.
|
307
|
+
#
|
308
|
+
# @param amount [Numeric]
|
309
|
+
# @yield Temporarily set text rise
|
310
|
+
# @return [Numeric] if called with no arguments
|
311
|
+
# @return [void] otherwise
|
312
|
+
def rise(amount = nil, &block)
|
313
|
+
if amount.nil?
|
314
|
+
return (defined?(@rise) && @rise) || 0
|
315
|
+
end
|
316
|
+
|
317
|
+
if rise == amount
|
259
318
|
yield
|
260
|
-
|
261
|
-
|
319
|
+
else
|
320
|
+
wrap_and_restore_rise(amount, &block)
|
262
321
|
end
|
263
322
|
end
|
264
323
|
|
265
|
-
#
|
324
|
+
# Add a text object to content stream.
|
325
|
+
#
|
326
|
+
# @param text [String]
|
327
|
+
# @param x [Numeric] horizontal position of the text origin on the page
|
328
|
+
# @param y [Numeric] vertical position of the text origin on the page
|
329
|
+
# @param options [Hash]
|
330
|
+
# @option options :rotate [Numeric] text rotation angle in degrees
|
331
|
+
# @option options :kerning [Boolean]
|
266
332
|
def add_text_content(text, x, y, options)
|
267
333
|
chunks = font.encode_text(text, options)
|
268
334
|
|
269
|
-
add_content
|
335
|
+
add_content("\nBT")
|
270
336
|
|
271
337
|
if options[:rotate]
|
272
|
-
rad = options[:rotate]
|
338
|
+
rad = Float(options[:rotate]) * Math::PI / 180
|
273
339
|
array = [
|
274
340
|
Math.cos(rad),
|
275
341
|
Math.sin(rad),
|
276
342
|
-Math.sin(rad),
|
277
343
|
Math.cos(rad),
|
278
|
-
x, y
|
344
|
+
x, y,
|
279
345
|
]
|
280
|
-
add_content
|
346
|
+
add_content("#{PDF::Core.real_params(array)} Tm")
|
281
347
|
else
|
282
|
-
add_content
|
348
|
+
add_content("#{PDF::Core.real(x)} #{PDF::Core.real(y)} Td")
|
283
349
|
end
|
284
350
|
|
285
351
|
chunks.each do |(subset, string)|
|
286
352
|
font.add_to_current_page(subset)
|
287
|
-
add_content
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
353
|
+
add_content(
|
354
|
+
[
|
355
|
+
PDF::Core.pdf_object(font.identifier_for(subset), true),
|
356
|
+
PDF::Core.pdf_object(font_size, true),
|
357
|
+
'Tf',
|
358
|
+
].join(' '),
|
359
|
+
)
|
292
360
|
|
293
361
|
operation = options[:kerning] && string.is_a?(Array) ? 'TJ' : 'Tj'
|
294
|
-
add_content
|
362
|
+
add_content("#{PDF::Core.pdf_object(string, true)} #{operation}")
|
363
|
+
end
|
364
|
+
|
365
|
+
add_content("ET\n")
|
366
|
+
end
|
367
|
+
|
368
|
+
private
|
369
|
+
|
370
|
+
def wrap_and_restore_text_rendering_mode(block_value)
|
371
|
+
original_value = text_rendering_mode
|
372
|
+
@text_rendering_mode = block_value
|
373
|
+
update_text_rendering_mode_state
|
374
|
+
begin
|
375
|
+
yield
|
376
|
+
ensure
|
377
|
+
@text_rendering_mode = original_value
|
378
|
+
update_text_rendering_mode_state
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
def update_text_rendering_mode_state
|
383
|
+
add_content("\n#{MODES[text_rendering_mode]} Tr")
|
384
|
+
end
|
385
|
+
|
386
|
+
def wrap_and_restore_character_spacing(block_value)
|
387
|
+
original_value = character_spacing
|
388
|
+
@character_spacing = block_value
|
389
|
+
update_character_spacing_state
|
390
|
+
begin
|
391
|
+
yield
|
392
|
+
ensure
|
393
|
+
@character_spacing = original_value
|
394
|
+
update_character_spacing_state
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
def update_character_spacing_state
|
399
|
+
add_content("\n#{PDF::Core.real(character_spacing)} Tc")
|
400
|
+
end
|
401
|
+
|
402
|
+
def wrap_and_restore_word_spacing(block_value)
|
403
|
+
original_value = word_spacing
|
404
|
+
@word_spacing = block_value
|
405
|
+
update_word_spacing_state
|
406
|
+
begin
|
407
|
+
yield
|
408
|
+
ensure
|
409
|
+
@word_spacing = original_value
|
410
|
+
update_word_spacing_state
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
def update_word_spacing_state
|
415
|
+
add_content("\n#{PDF::Core.real(word_spacing)} Tw")
|
416
|
+
end
|
417
|
+
|
418
|
+
def wrap_and_restore_horizontal_text_scaling(block_value)
|
419
|
+
original_value = horizontal_text_scaling
|
420
|
+
@horizontal_text_scaling = block_value
|
421
|
+
update_horizontal_text_scaling_state
|
422
|
+
begin
|
423
|
+
yield
|
424
|
+
ensure
|
425
|
+
@horizontal_text_scaling = original_value
|
426
|
+
update_horizontal_text_scaling_state
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
def update_horizontal_text_scaling_state
|
431
|
+
add_content("\n#{PDF::Core.real(horizontal_text_scaling)} Tz")
|
432
|
+
end
|
433
|
+
|
434
|
+
def wrap_and_restore_rise(block_value)
|
435
|
+
original_value = rise
|
436
|
+
@rise = block_value
|
437
|
+
update_rise_state
|
438
|
+
begin
|
439
|
+
yield
|
440
|
+
ensure
|
441
|
+
@rise = original_value
|
442
|
+
update_rise_state
|
295
443
|
end
|
444
|
+
end
|
296
445
|
|
297
|
-
|
446
|
+
def update_rise_state
|
447
|
+
add_content("\n#{PDF::Core.real(rise)} Ts")
|
298
448
|
end
|
299
|
-
# rubocop: enable Naming/UncommunicativeMethodParamName
|
300
449
|
end
|
301
450
|
end
|
302
451
|
end
|
data/lib/pdf/core/utils.rb
CHANGED
@@ -2,11 +2,20 @@
|
|
2
2
|
|
3
3
|
module PDF
|
4
4
|
module Core
|
5
|
+
# Utility methods
|
5
6
|
module Utils
|
7
|
+
module_function
|
8
|
+
|
9
|
+
# Deep clone an object.
|
10
|
+
# It uses marshal-demarshal trick. Since it's supposed to be use only on
|
11
|
+
# objects that can be serialized into PDF it shouldn't have any issues
|
12
|
+
# with objects that can not be marshaled.
|
13
|
+
#
|
14
|
+
# @param object [any]
|
15
|
+
# @return [any]
|
6
16
|
def deep_clone(object)
|
7
17
|
Marshal.load(Marshal.dump(object))
|
8
18
|
end
|
9
|
-
module_function :deep_clone
|
10
19
|
end
|
11
20
|
end
|
12
21
|
end
|
data/lib/pdf/core.rb
CHANGED
@@ -1,5 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Top level Module
|
4
|
+
module PDF
|
5
|
+
# PDF::Core is concerned with low-level PDF functions such as serialization,
|
6
|
+
# content streams and such.
|
7
|
+
#
|
8
|
+
# It's extracted from Prawn but at the moment is not entirely independent.
|
9
|
+
module Core
|
10
|
+
# PDF::Core-specific errors
|
11
|
+
module Errors
|
12
|
+
# This error indicates failure of {PDF::Core.pdf_object}
|
13
|
+
class FailedObjectConversion < StandardError
|
14
|
+
end
|
15
|
+
|
16
|
+
# This error occurs when a graphic state is being restored but the graphic
|
17
|
+
# state stack is empty.
|
18
|
+
class EmptyGraphicStateStack < StandardError
|
19
|
+
end
|
20
|
+
|
21
|
+
# This error is raised when page layout is set to anything other than
|
22
|
+
# `:portrait` or `:landscape`
|
23
|
+
class InvalidPageLayout < StandardError
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
3
29
|
require_relative 'core/pdf_object'
|
4
30
|
require_relative 'core/annotations'
|
5
31
|
require_relative 'core/byte_string'
|
@@ -19,19 +45,3 @@ require_relative 'core/outline_root'
|
|
19
45
|
require_relative 'core/outline_item'
|
20
46
|
require_relative 'core/renderer'
|
21
47
|
require_relative 'core/text'
|
22
|
-
|
23
|
-
module PDF
|
24
|
-
module Core
|
25
|
-
module Errors
|
26
|
-
# This error is raised when pdf_object() fails
|
27
|
-
FailedObjectConversion = Class.new(StandardError)
|
28
|
-
|
29
|
-
# This error is raise when trying to restore a graphic state that
|
30
|
-
EmptyGraphicStateStack = Class.new(StandardError)
|
31
|
-
|
32
|
-
# This error is raised when Document#page_layout is set to anything
|
33
|
-
# other than :portrait or :landscape
|
34
|
-
InvalidPageLayout = Class.new(StandardError)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
data/pdf-core.gemspec
CHANGED
@@ -2,43 +2,47 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = 'pdf-core'
|
5
|
-
spec.version = '0.
|
5
|
+
spec.version = '0.10.0'
|
6
6
|
spec.platform = Gem::Platform::RUBY
|
7
|
-
spec.summary = '
|
8
|
-
spec.
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
spec.summary = 'Low level PDF generator.'
|
8
|
+
spec.description = 'PDF::Core is used by Prawn to render PDF documents. It provides low-level format support.'
|
9
|
+
spec.files =
|
10
|
+
Dir.glob('lib/**/**/*') +
|
11
|
+
%w[COPYING GPLv2 GPLv3 LICENSE] +
|
12
|
+
['pdf-core.gemspec']
|
12
13
|
spec.require_path = 'lib'
|
13
|
-
spec.required_ruby_version = '>= 2.
|
14
|
+
spec.required_ruby_version = '>= 2.7'
|
14
15
|
spec.required_rubygems_version = '>= 1.3.6'
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
17
|
+
if File.basename($PROGRAM_NAME) == 'gem' && ARGV.include?('build')
|
18
|
+
signing_key = File.expand_path('~/.gem/gem-private_key.pem')
|
19
|
+
if File.exist?(signing_key)
|
20
|
+
spec.cert_chain = ['certs/pointlessone.pem']
|
21
|
+
spec.signing_key = signing_key
|
22
|
+
else
|
23
|
+
warn 'WARNING: Signing key is missing. The gem is not signed and its authenticity can not be verified.'
|
24
|
+
end
|
19
25
|
end
|
20
26
|
|
21
|
-
# spec.extra_rdoc_files = %w{README.md LICENSE COPYING GPLv2 GPLv3}
|
22
|
-
# spec.rdoc_options << '--title' << 'Prawn Documentation' <<
|
23
|
-
# '--main' << 'README.md' << '-q'
|
24
27
|
spec.authors = [
|
25
|
-
'Gregory Brown', 'Brad Ediger', 'Daniel Nelson',
|
26
|
-
'James Healy'
|
28
|
+
'Alexander Mankuta', 'Gregory Brown', 'Brad Ediger', 'Daniel Nelson',
|
29
|
+
'Jonathan Greenberg', 'James Healy',
|
27
30
|
]
|
28
31
|
spec.email = [
|
29
|
-
'gregory.t.brown@gmail.com', 'brad@bradediger.com',
|
30
|
-
'greenberg@entryway.net', 'jimmy@deefa.com'
|
32
|
+
'alex@pointless.one', 'gregory.t.brown@gmail.com', 'brad@bradediger.com',
|
33
|
+
'dnelson@bluejade.com', 'greenberg@entryway.net', 'jimmy@deefa.com',
|
31
34
|
]
|
32
|
-
spec.
|
33
|
-
spec.
|
34
|
-
spec.
|
35
|
+
spec.licenses = %w[Nonstandard GPL-2.0-only GPL-3.0-only]
|
36
|
+
spec.homepage = 'http://prawnpdf.org/'
|
37
|
+
spec.metadata = {
|
38
|
+
'rubygems_mfa_required' => 'true',
|
39
|
+
'homepage_uri' => spec.homepage,
|
40
|
+
'changelog_uri' => "https://github.com/prawnpdf/pdf-core/blob/#{spec.version}/CHANGELOG.md",
|
41
|
+
'source_code_uri' => 'https://github.com/prawnpdf/pdf-core',
|
42
|
+
'documentation_uri' => "https://prawnpdf.org/docs/pdf-core/#{spec.version}/",
|
43
|
+
'bug_tracker_uri' => 'https://github.com/prawnpdf/pdf-core/issues',
|
44
|
+
}
|
35
45
|
spec.add_development_dependency('pdf-inspector', '~> 1.1.0')
|
36
46
|
spec.add_development_dependency('pdf-reader', '~>1.2')
|
37
|
-
spec.add_development_dependency('
|
38
|
-
spec.add_development_dependency('rspec')
|
39
|
-
spec.add_development_dependency('rubocop', '~> 0.55')
|
40
|
-
spec.add_development_dependency('rubocop-rspec', '~> 1.25')
|
41
|
-
spec.add_development_dependency('simplecov')
|
42
|
-
spec.homepage = 'http://prawn.majesticseacreature.com'
|
43
|
-
spec.description = 'PDF::Core is used by Prawn to render PDF documents'
|
47
|
+
spec.add_development_dependency('prawn-dev', '~> 0.4.0')
|
44
48
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|