podoff 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +6 -0
- data/lib/podoff.rb +118 -109
- data/spec/document_spec.rb +52 -10
- data/spec/spec_helper.rb +1 -0
- data/spec/stream_spec.rb +42 -6
- data/todo.txt +1 -1
- metadata +2 -2
data/CHANGELOG.txt
CHANGED
data/lib/podoff.rb
CHANGED
@@ -23,13 +23,14 @@
|
|
23
23
|
# Made in Japan.
|
24
24
|
#++
|
25
25
|
|
26
|
+
require 'zlib'
|
26
27
|
require 'strscan'
|
27
28
|
require 'stringio'
|
28
29
|
|
29
30
|
|
30
31
|
module Podoff
|
31
32
|
|
32
|
-
VERSION = '1.1.
|
33
|
+
VERSION = '1.1.1'
|
33
34
|
|
34
35
|
def self.load(path, encoding='iso-8859-1')
|
35
36
|
|
@@ -53,7 +54,7 @@ module Podoff
|
|
53
54
|
Podoff::Document.new(s)
|
54
55
|
end
|
55
56
|
|
56
|
-
attr_reader :
|
57
|
+
attr_reader :scanner
|
57
58
|
attr_reader :version
|
58
59
|
attr_reader :xref
|
59
60
|
attr_reader :objs
|
@@ -67,7 +68,7 @@ module Podoff
|
|
67
68
|
fail ArgumentError.new('not a PDF file') \
|
68
69
|
unless s.match(/\A%PDF-\d+\.\d+\s/)
|
69
70
|
|
70
|
-
@
|
71
|
+
@scanner = ::StringScanner.new(s)
|
71
72
|
@version = nil
|
72
73
|
@xref = nil
|
73
74
|
@objs = {}
|
@@ -76,15 +77,14 @@ module Podoff
|
|
76
77
|
|
77
78
|
@additions = {}
|
78
79
|
|
79
|
-
|
80
|
-
@version = sca.scan(/%PDF-\d+\.\d+/)
|
80
|
+
@version = @scanner.scan(/%PDF-\d+\.\d+/)
|
81
81
|
|
82
82
|
loop do
|
83
83
|
|
84
|
-
i =
|
84
|
+
i = @scanner.skip_until(
|
85
85
|
/(startxref\s+\d+|\d+\s+\d+\s+obj|\/Root\s+\d+\s+\d+\s+R)/)
|
86
86
|
|
87
|
-
m =
|
87
|
+
m = @scanner.matched
|
88
88
|
break unless m
|
89
89
|
|
90
90
|
if m[0] == 's'
|
@@ -92,22 +92,27 @@ module Podoff
|
|
92
92
|
elsif m[0] == '/'
|
93
93
|
@root = extract_ref(m)
|
94
94
|
else
|
95
|
-
obj = Podoff::Obj.extract(self
|
95
|
+
obj = Podoff::Obj.extract(self)
|
96
96
|
@objs[obj.ref] = obj
|
97
97
|
@obj_counters[obj.ref] = (@obj_counters[obj.ref] || 0) + 1
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
101
|
if @root == nil
|
102
|
-
|
102
|
+
@scanner.pos = 0
|
103
103
|
loop do
|
104
|
-
i =
|
105
|
-
break unless
|
106
|
-
@root = extract_ref(
|
104
|
+
i = @scanner.skip_until(/\/Root\s+\d+\s+\d+\s+R/)
|
105
|
+
break unless @scanner.matched
|
106
|
+
@root = extract_ref(@scanner.matched)
|
107
107
|
end
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
111
|
+
def source
|
112
|
+
|
113
|
+
@scanner.string
|
114
|
+
end
|
115
|
+
|
111
116
|
def extract_ref(s)
|
112
117
|
|
113
118
|
s.gsub(/\s+/, ' ').gsub(/[^0-9 ]+/, '').strip
|
@@ -124,7 +129,7 @@ module Podoff
|
|
124
129
|
|
125
130
|
self.class.allocate.instance_eval do
|
126
131
|
|
127
|
-
@
|
132
|
+
@scanner = ::StringScanner.new(o.source)
|
128
133
|
@xref = o.xref
|
129
134
|
|
130
135
|
@objs = o.objs.inject({}) { |h, (k, v)| h[k] = v.dup(self); h }
|
@@ -182,35 +187,32 @@ module Podoff
|
|
182
187
|
|
183
188
|
name = name[1..-1] if name[0] == '/'
|
184
189
|
|
185
|
-
|
190
|
+
r = new_ref
|
191
|
+
s = "#{r} obj <</Type /Font /Subtype /Type1 /BaseFont /#{name}>> endobj"
|
186
192
|
|
187
|
-
add(
|
188
|
-
Obj.create(
|
189
|
-
self,
|
190
|
-
ref,
|
191
|
-
[
|
192
|
-
"#{ref} obj",
|
193
|
-
"<< /Type /Font /Subtype /Type1 /BaseFont /#{name} >>",
|
194
|
-
"endobj"
|
195
|
-
].join(' ')))
|
193
|
+
add(Obj.new(self, r, source: s))
|
196
194
|
end
|
197
195
|
|
198
|
-
def add_stream(
|
196
|
+
def add_stream(src=nil, &block)
|
199
197
|
|
200
198
|
ref = new_ref
|
201
199
|
|
202
|
-
|
200
|
+
src =
|
201
|
+
src &&
|
202
|
+
[
|
203
|
+
"#{ref} obj",
|
204
|
+
"<< /Length #{src.size} >>\nstream\n#{src}\nendstream",
|
205
|
+
"endobj"
|
206
|
+
].join("\n")
|
203
207
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
"endobj"
|
209
|
-
].join("\n") if s.is_a?(String)
|
208
|
+
str =
|
209
|
+
src ?
|
210
|
+
nil :
|
211
|
+
make_stream(&block)
|
210
212
|
|
211
|
-
|
213
|
+
obj = add(Obj.new(self, ref, source: src, stream: str))
|
212
214
|
|
213
|
-
|
215
|
+
str || obj
|
214
216
|
end
|
215
217
|
|
216
218
|
def re_add(obj_or_ref)
|
@@ -231,7 +233,7 @@ module Podoff
|
|
231
233
|
else path
|
232
234
|
end
|
233
235
|
|
234
|
-
f.write(
|
236
|
+
f.write(source)
|
235
237
|
|
236
238
|
if @additions.any?
|
237
239
|
|
@@ -239,27 +241,14 @@ module Podoff
|
|
239
241
|
|
240
242
|
@additions.values.each do |o|
|
241
243
|
f.write("\n")
|
242
|
-
pointers[o.ref] = f.pos + 1
|
243
|
-
|
244
|
-
f.write(o.source)
|
245
|
-
else # Stream
|
246
|
-
s = o.source.to_s
|
247
|
-
f.write("#{o.ref} obj\n<< /Length #{s.length} >>\n")
|
248
|
-
f.write("stream\n#{s}\nendstream\nendobj")
|
249
|
-
end
|
244
|
+
pointers[o.ref.split(' ').first.to_i] = f.pos + 1
|
245
|
+
f.write(o.to_s)
|
250
246
|
end
|
251
247
|
f.write("\n\n")
|
252
248
|
|
253
249
|
xref = f.pos + 1
|
254
250
|
|
255
|
-
f
|
256
|
-
f.write("0 1\n")
|
257
|
-
f.write("0000000000 65535 f\n")
|
258
|
-
|
259
|
-
pointers.each do |k, v|
|
260
|
-
f.write("#{k.split(' ').first} 1\n")
|
261
|
-
f.write(sprintf("%010d 00000 n\n", v))
|
262
|
-
end
|
251
|
+
write_xref(f, pointers)
|
263
252
|
|
264
253
|
f.write("trailer\n")
|
265
254
|
f.write("<<\n")
|
@@ -289,42 +278,17 @@ module Podoff
|
|
289
278
|
f.write(v)
|
290
279
|
f.write("\n")
|
291
280
|
|
292
|
-
|
281
|
+
pointers = {}
|
293
282
|
|
294
283
|
objs.keys.sort.each do |k|
|
295
|
-
|
284
|
+
pointers[k.split(' ').first.to_i] = f.pos + 1
|
296
285
|
f.write(objs[k].source)
|
297
286
|
f.write("\n")
|
298
287
|
end
|
299
288
|
|
300
289
|
xref = f.pos + 1
|
301
|
-
max = objs.keys.inject(-1) { |i, k| [ i, k.split(' ')[0].to_i ].max }
|
302
|
-
|
303
|
-
#f.write("xref\n0 #{max}\n0000000000 65535 f\n")
|
304
|
-
f.write("xref\n0 1\n0000000000 65535 f\n")
|
305
|
-
|
306
|
-
partitions = [ [] ]
|
307
|
-
#
|
308
|
-
(1..max).each do |i|
|
309
|
-
k = "#{i} 0"
|
310
|
-
last = partitions.last
|
311
|
-
if ptrs.has_key?(k)
|
312
|
-
last << i
|
313
|
-
else
|
314
|
-
partitions << [] unless last == []
|
315
|
-
end
|
316
|
-
end
|
317
|
-
#
|
318
|
-
partitions.each do |part|
|
319
290
|
|
320
|
-
|
321
|
-
|
322
|
-
part.each do |i|
|
323
|
-
k = "#{i} 0"
|
324
|
-
#f.write(sprintf("%010d 00000 n %% %s\n", ptrs[k], k))
|
325
|
-
f.write(sprintf("%010d 00000 n\n", ptrs[k]))
|
326
|
-
end
|
327
|
-
end
|
291
|
+
write_xref(f, pointers)
|
328
292
|
|
329
293
|
f.write("trailer\n")
|
330
294
|
f.write("<<\n")
|
@@ -339,7 +303,27 @@ module Podoff
|
|
339
303
|
f.is_a?(StringIO) ? f.string : nil
|
340
304
|
end
|
341
305
|
|
342
|
-
|
306
|
+
protected
|
307
|
+
|
308
|
+
def write_xref(f, pointers)
|
309
|
+
|
310
|
+
f.write("xref\n")
|
311
|
+
f.write("0 1\n")
|
312
|
+
f.write("0000000000 65535 f\n")
|
313
|
+
|
314
|
+
pointers
|
315
|
+
.keys
|
316
|
+
.sort
|
317
|
+
.inject([ [] ]) { |ps, k|
|
318
|
+
ps << [] if ps.last != [] && k > ps.last.last + 1
|
319
|
+
ps.last << k
|
320
|
+
ps
|
321
|
+
}
|
322
|
+
.each { |part|
|
323
|
+
f.write("#{part.first} #{part.size}\n")
|
324
|
+
part.each { |k| f.write(sprintf("%010d 00000 n\n", pointers[k])) }
|
325
|
+
}
|
326
|
+
end
|
343
327
|
|
344
328
|
def make_stream(&block)
|
345
329
|
|
@@ -355,7 +339,9 @@ module Podoff
|
|
355
339
|
ATTRIBUTES =
|
356
340
|
{ type: 'Type', contents: 'Contents', pagenum: 'pdftk_PageNum' }
|
357
341
|
|
358
|
-
def self.extract(doc
|
342
|
+
def self.extract(doc)
|
343
|
+
|
344
|
+
sca = doc.scanner
|
359
345
|
|
360
346
|
re = sca.matched[0..-4].strip
|
361
347
|
st = sca.pos - sca.matched.length
|
@@ -363,50 +349,48 @@ module Podoff
|
|
363
349
|
i = sca.skip_until(/endobj/); return nil unless i
|
364
350
|
en = sca.pos - 1
|
365
351
|
|
366
|
-
|
367
|
-
ATTRIBUTES.each do |k, v|
|
368
|
-
sca.pos = st
|
369
|
-
i = sca.skip_until(/\/#{v}\b/); next unless i
|
370
|
-
next if sca.pos > en
|
371
|
-
atts[k] = sca.scan(/ *\/?[^\n\r\/>]+/).strip
|
372
|
-
end
|
373
|
-
|
374
|
-
sca.pos = en
|
375
|
-
|
376
|
-
Podoff::Obj.new(doc, re, st, en, atts)
|
352
|
+
Podoff::Obj.new(doc, re, start_index: st, end_index: en)
|
377
353
|
end
|
378
354
|
|
379
355
|
attr_reader :document
|
380
356
|
attr_reader :ref
|
381
357
|
attr_reader :start_index, :end_index
|
358
|
+
attr_reader :stream
|
382
359
|
attr_reader :attributes
|
383
360
|
|
384
|
-
def initialize(doc, ref,
|
361
|
+
def initialize(doc, ref, opts={})
|
385
362
|
|
386
363
|
@document = doc
|
387
364
|
@ref = ref
|
388
|
-
@start_index = st
|
389
|
-
@end_index = en
|
390
|
-
@attributes = atts
|
391
|
-
@source = source
|
392
365
|
|
393
|
-
|
394
|
-
@
|
395
|
-
|
366
|
+
@start_index = opts[:start_index]
|
367
|
+
@end_index = opts[:end_index]
|
368
|
+
@attributes = nil
|
369
|
+
@source = opts[:source]
|
396
370
|
|
397
|
-
|
371
|
+
@stream = opts[:stream]
|
372
|
+
@stream.obj = self if @stream
|
398
373
|
|
399
|
-
|
374
|
+
recompute_attributes
|
375
|
+
#@source.obj = self if @source.is_a?(Podoff::Stream)
|
376
|
+
|
377
|
+
@document.scanner.pos = @end_index if @document.scanner && @end_index
|
400
378
|
end
|
401
379
|
|
402
|
-
def
|
380
|
+
def dup(new_doc)
|
403
381
|
|
404
|
-
self.new(
|
382
|
+
self.class.new(
|
383
|
+
new_doc, ref,
|
384
|
+
start_index: start_index, end_index: end_index)
|
405
385
|
end
|
406
386
|
|
387
|
+
#def self.create(doc, ref, source)
|
388
|
+
# self.new(doc, ref, nil, nil, nil, source)
|
389
|
+
#end
|
390
|
+
|
407
391
|
def replicate
|
408
392
|
|
409
|
-
self.class.
|
393
|
+
self.class.new(document, ref, source: source.dup)
|
410
394
|
end
|
411
395
|
|
412
396
|
def to_a
|
@@ -416,7 +400,7 @@ module Podoff
|
|
416
400
|
|
417
401
|
def source
|
418
402
|
|
419
|
-
@source || @document.source[@start_index..@end_index]
|
403
|
+
@source || (@start_index && @document.source[@start_index..@end_index])
|
420
404
|
end
|
421
405
|
|
422
406
|
def replica?
|
@@ -463,14 +447,29 @@ module Podoff
|
|
463
447
|
end
|
464
448
|
alias :insert_content :insert_contents
|
465
449
|
|
450
|
+
def to_s
|
451
|
+
|
452
|
+
source || stream.to_s
|
453
|
+
end
|
454
|
+
|
466
455
|
protected
|
467
456
|
|
468
457
|
def recompute_attributes
|
469
458
|
|
459
|
+
st, en, sca =
|
460
|
+
if @start_index
|
461
|
+
[ @start_index, @end_index, @document.scanner ]
|
462
|
+
elsif @source
|
463
|
+
[ 0, @source.length, ::StringScanner.new(@source) ]
|
464
|
+
end
|
465
|
+
|
466
|
+
return unless sca
|
467
|
+
|
470
468
|
@attributes =
|
471
469
|
ATTRIBUTES.inject({}) do |h, (k, v)|
|
472
|
-
|
473
|
-
|
470
|
+
sca.pos = st
|
471
|
+
i = sca.skip_until(/\/#{v}\b/)
|
472
|
+
h[k] = sca.scan(/ *\/?[^\n\r\/>]+/).strip if i && sca.pos < en
|
474
473
|
h
|
475
474
|
end
|
476
475
|
end
|
@@ -504,8 +503,9 @@ module Podoff
|
|
504
503
|
|
505
504
|
attr_accessor :obj
|
506
505
|
|
507
|
-
def initialize
|
506
|
+
def initialize(obj=nil)
|
508
507
|
|
508
|
+
@obj = obj
|
509
509
|
@font = nil
|
510
510
|
@content = StringIO.new
|
511
511
|
end
|
@@ -535,7 +535,16 @@ module Podoff
|
|
535
535
|
|
536
536
|
def to_s
|
537
537
|
|
538
|
-
@content.string
|
538
|
+
s = @content.string
|
539
|
+
f = ''
|
540
|
+
if s.length > 98
|
541
|
+
f = ' /Filter /FlateDecode'
|
542
|
+
s = Zlib::Deflate.deflate(s)
|
543
|
+
end
|
544
|
+
|
545
|
+
"#{obj.ref} obj\n" +
|
546
|
+
"<</Length #{s.size}#{f}>>\nstream\n#{s}\nendstream\n" +
|
547
|
+
"endobj"
|
539
548
|
end
|
540
549
|
|
541
550
|
protected
|
data/spec/document_spec.rb
CHANGED
@@ -97,6 +97,15 @@ describe Podoff::Document do
|
|
97
97
|
|
98
98
|
expect(d.root).to eq('65 0')
|
99
99
|
end
|
100
|
+
|
101
|
+
it 'sports objs with properly recomputed attributes' do
|
102
|
+
|
103
|
+
pa = @d.page(1)
|
104
|
+
|
105
|
+
d = @d.dup
|
106
|
+
|
107
|
+
expect(d.objs[pa.ref].attributes).to eq(pa.attributes)
|
108
|
+
end
|
100
109
|
end
|
101
110
|
|
102
111
|
context 'additions' do
|
@@ -120,13 +129,12 @@ describe Podoff::Document do
|
|
120
129
|
expect(fo.ref).to eq('7 0')
|
121
130
|
|
122
131
|
expect(fo.source).to eq(
|
123
|
-
'7 0 obj '
|
124
|
-
'<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >> endobj')
|
132
|
+
'7 0 obj <</Type /Font /Subtype /Type1 /BaseFont /Helvetica>> endobj')
|
125
133
|
|
126
134
|
s = @d.write(:string)
|
127
135
|
d = Podoff.parse(s)
|
128
136
|
|
129
|
-
expect(d.xref).to eq(
|
137
|
+
expect(d.xref).to eq(680)
|
130
138
|
end
|
131
139
|
|
132
140
|
it 'doesn\'t mind a slash in front of the font name' do
|
@@ -141,8 +149,7 @@ describe Podoff::Document do
|
|
141
149
|
expect(fo.ref).to eq('7 0')
|
142
150
|
|
143
151
|
expect(fo.source).to eq(
|
144
|
-
'7 0 obj '
|
145
|
-
'<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >> endobj')
|
152
|
+
'7 0 obj <</Type /Font /Subtype /Type1 /BaseFont /Helvetica>> endobj')
|
146
153
|
end
|
147
154
|
end
|
148
155
|
|
@@ -185,15 +192,20 @@ endobj
|
|
185
192
|
expect(st.obj.document).to eq(@d)
|
186
193
|
expect(st.obj.ref).to eq('7 0')
|
187
194
|
|
188
|
-
expect(st.
|
195
|
+
expect(st.to_s).to eq(%{
|
196
|
+
7 0 obj
|
197
|
+
<</Length 97>>
|
198
|
+
stream
|
189
199
|
BT /Helvetica 35 Tf 10 20 Td (thirty here) Tj ET
|
190
200
|
BT /Helvetica 35 Tf 40 50 Td (sixty there) Tj ET
|
201
|
+
endstream
|
202
|
+
endobj
|
191
203
|
}.strip)
|
192
204
|
|
193
205
|
d = Podoff.parse(@d.write(:string))
|
194
206
|
|
195
|
-
expect(d.source.index('
|
196
|
-
expect(d.xref).to eq(
|
207
|
+
expect(d.source.index('<</Length 97>>')).to eq(618)
|
208
|
+
expect(d.xref).to eq(757)
|
197
209
|
end
|
198
210
|
|
199
211
|
it 'returns the open stream when no arg given' do
|
@@ -273,9 +285,9 @@ BT /Helvetica 35 Tf 40 50 Td (sixty there) Tj ET
|
|
273
285
|
s = d.write(:string)
|
274
286
|
|
275
287
|
expect(
|
276
|
-
|
288
|
+
s.index(%{
|
277
289
|
7 0 obj
|
278
|
-
|
290
|
+
<</Length 37>>
|
279
291
|
stream
|
280
292
|
BT 10 20 Td (hello open stream) Tj ET
|
281
293
|
endstream
|
@@ -283,6 +295,36 @@ endobj
|
|
283
295
|
}.strip)
|
284
296
|
).to eq(722)
|
285
297
|
end
|
298
|
+
|
299
|
+
it 'writes a proper xref table' do
|
300
|
+
|
301
|
+
d = Podoff.load('pdfs/t0.pdf')
|
302
|
+
|
303
|
+
pa = d.re_add(d.page(1))
|
304
|
+
st = d.add_stream
|
305
|
+
st.bt(10, 20, 'hello open stream')
|
306
|
+
pa.insert_contents(st)
|
307
|
+
|
308
|
+
s = d.write(:string)
|
309
|
+
|
310
|
+
expect(s[808..-1].strip).to eq(%{
|
311
|
+
xref
|
312
|
+
0 1
|
313
|
+
0000000000 65535 f
|
314
|
+
3 1
|
315
|
+
0000000611 00000 n
|
316
|
+
7 1
|
317
|
+
0000000723 00000 n
|
318
|
+
trailer
|
319
|
+
<<
|
320
|
+
/Prev 414
|
321
|
+
/Size 7
|
322
|
+
/Root 1 0 R
|
323
|
+
>>
|
324
|
+
startxref 809
|
325
|
+
%%EOF
|
326
|
+
}.strip)
|
327
|
+
end
|
286
328
|
end
|
287
329
|
|
288
330
|
describe '#rewrite' do
|
data/spec/spec_helper.rb
CHANGED
data/spec/stream_spec.rb
CHANGED
@@ -14,7 +14,7 @@ describe Podoff::Stream do
|
|
14
14
|
|
15
15
|
it 'sets the current font' do
|
16
16
|
|
17
|
-
st = Podoff::Stream.new
|
17
|
+
st = Podoff::Stream.new(OpenStruct.new(ref: '1 0'))
|
18
18
|
|
19
19
|
st.tf('/Helvetica', 35)
|
20
20
|
st.bt(10, 20, 'helvetic')
|
@@ -22,8 +22,13 @@ describe Podoff::Stream do
|
|
22
22
|
st.bt(10, 50, 'zapfesque')
|
23
23
|
|
24
24
|
expect(st.to_s).to eq(%{
|
25
|
+
1 0 obj
|
26
|
+
<</Length 95>>
|
27
|
+
stream
|
25
28
|
BT /Helvetica 35 Tf 10 20 Td (helvetic) Tj ET
|
26
29
|
BT /ZapfDingbats 21 Tf 10 50 Td (zapfesque) Tj ET
|
30
|
+
endstream
|
31
|
+
endobj
|
27
32
|
}.strip)
|
28
33
|
end
|
29
34
|
end
|
@@ -32,18 +37,32 @@ BT /ZapfDingbats 21 Tf 10 50 Td (zapfesque) Tj ET
|
|
32
37
|
|
33
38
|
it 'works' do
|
34
39
|
|
35
|
-
st = Podoff::Stream.new
|
40
|
+
st = Podoff::Stream.new(OpenStruct.new(ref: '1 0'))
|
36
41
|
st.bt(10, 20, 'hello world')
|
37
42
|
|
38
|
-
expect(st.to_s).to eq(
|
43
|
+
expect(st.to_s).to eq(%{
|
44
|
+
1 0 obj
|
45
|
+
<</Length 31>>
|
46
|
+
stream
|
47
|
+
BT 10 20 Td (hello world) Tj ET
|
48
|
+
endstream
|
49
|
+
endobj
|
50
|
+
}.strip)
|
39
51
|
end
|
40
52
|
|
41
53
|
it 'escapes the text' do
|
42
54
|
|
43
|
-
st = Podoff::Stream.new
|
55
|
+
st = Podoff::Stream.new(OpenStruct.new(ref: '1 0'))
|
44
56
|
st.bt(10, 20, 'hello()world')
|
45
57
|
|
46
|
-
expect(st.to_s).to eq(
|
58
|
+
expect(st.to_s).to eq(%{
|
59
|
+
1 0 obj
|
60
|
+
<</Length 34>>
|
61
|
+
stream
|
62
|
+
BT 10 20 Td (hello\\(\\)world) Tj ET
|
63
|
+
endstream
|
64
|
+
endobj
|
65
|
+
}.strip)
|
47
66
|
end
|
48
67
|
end
|
49
68
|
|
@@ -51,17 +70,34 @@ BT /ZapfDingbats 21 Tf 10 50 Td (zapfesque) Tj ET
|
|
51
70
|
|
52
71
|
it 'injects text into the stream' do
|
53
72
|
|
54
|
-
st = Podoff::Stream.new
|
73
|
+
st = Podoff::Stream.new(OpenStruct.new(ref: '1 0'))
|
55
74
|
st.bt(10, 20, 'abc')
|
56
75
|
st.write("\nBT 25 35 Td (ABC) Tj ET")
|
57
76
|
st.bt(30, 40, 'def')
|
58
77
|
|
59
78
|
expect(st.to_s).to eq(%{
|
79
|
+
1 0 obj
|
80
|
+
<</Length 71>>
|
81
|
+
stream
|
60
82
|
BT 10 20 Td (abc) Tj ET
|
61
83
|
BT 25 35 Td (ABC) Tj ET
|
62
84
|
BT 30 40 Td (def) Tj ET
|
85
|
+
endstream
|
86
|
+
endobj
|
63
87
|
}.strip)
|
64
88
|
end
|
65
89
|
end
|
90
|
+
|
91
|
+
describe '#to_s' do
|
92
|
+
|
93
|
+
it 'applies /Filter /FlateDecode if stream.size > 98' do
|
94
|
+
|
95
|
+
st = Podoff::Stream.new(OpenStruct.new(ref: '1 0'))
|
96
|
+
st.write("BT /Helvetica 35 Tf 123 456 Td (Hello Nada) Tj ET\n" * 4)
|
97
|
+
|
98
|
+
expect(st.to_s).to match(
|
99
|
+
/^1 0 obj\n<<\/Length 60 \/Filter \/FlateDecode>>/)
|
100
|
+
end
|
101
|
+
end
|
66
102
|
end
|
67
103
|
|
data/todo.txt
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: podoff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-10-
|
12
|
+
date: 2015-10-25 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|