pdf-core 0.8.1 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|