origami-docspring 2.2.0 → 2.3.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 +18 -0
- data/examples/attachments/attachment.rb +7 -8
- data/examples/attachments/nested_document.rb +6 -5
- data/examples/encryption/encryption.rb +5 -4
- data/examples/events/events.rb +7 -6
- data/examples/flash/flash.rb +10 -9
- data/examples/forms/javascript.rb +14 -13
- data/examples/forms/xfa.rb +67 -66
- data/examples/javascript/hello_world.rb +6 -5
- data/examples/javascript/js_emulation.rb +26 -26
- data/examples/loop/goto.rb +12 -11
- data/examples/loop/named.rb +17 -16
- data/examples/signature/signature.rb +11 -11
- data/examples/uri/javascript.rb +25 -24
- data/examples/uri/open-uri.rb +5 -4
- data/examples/uri/submitform.rb +11 -10
- data/lib/origami/3d.rb +330 -334
- data/lib/origami/acroform.rb +267 -268
- data/lib/origami/actions.rb +266 -278
- data/lib/origami/annotations.rb +659 -670
- data/lib/origami/array.rb +192 -196
- data/lib/origami/boolean.rb +66 -70
- data/lib/origami/catalog.rb +360 -363
- data/lib/origami/collections.rb +132 -133
- data/lib/origami/compound.rb +125 -129
- data/lib/origami/destinations.rb +226 -237
- data/lib/origami/dictionary.rb +155 -154
- data/lib/origami/encryption.rb +967 -923
- data/lib/origami/extensions/fdf.rb +270 -275
- data/lib/origami/extensions/ppklite.rb +323 -328
- data/lib/origami/filespec.rb +170 -173
- data/lib/origami/filters/ascii.rb +162 -167
- data/lib/origami/filters/ccitt/tables.rb +248 -252
- data/lib/origami/filters/ccitt.rb +309 -312
- data/lib/origami/filters/crypt.rb +31 -34
- data/lib/origami/filters/dct.rb +47 -50
- data/lib/origami/filters/flate.rb +57 -60
- data/lib/origami/filters/jbig2.rb +50 -53
- data/lib/origami/filters/jpx.rb +40 -43
- data/lib/origami/filters/lzw.rb +151 -155
- data/lib/origami/filters/predictors.rb +250 -255
- data/lib/origami/filters/runlength.rb +111 -115
- data/lib/origami/filters.rb +319 -325
- data/lib/origami/font.rb +173 -177
- data/lib/origami/functions.rb +62 -66
- data/lib/origami/graphics/colors.rb +203 -208
- data/lib/origami/graphics/instruction.rb +79 -81
- data/lib/origami/graphics/path.rb +141 -144
- data/lib/origami/graphics/patterns.rb +156 -160
- data/lib/origami/graphics/render.rb +51 -47
- data/lib/origami/graphics/state.rb +144 -142
- data/lib/origami/graphics/text.rb +185 -188
- data/lib/origami/graphics/xobject.rb +818 -804
- data/lib/origami/graphics.rb +25 -26
- data/lib/origami/header.rb +63 -65
- data/lib/origami/javascript.rb +718 -651
- data/lib/origami/linearization.rb +284 -285
- data/lib/origami/metadata.rb +156 -135
- data/lib/origami/name.rb +98 -100
- data/lib/origami/null.rb +49 -51
- data/lib/origami/numeric.rb +133 -135
- data/lib/origami/obfuscation.rb +180 -182
- data/lib/origami/object.rb +634 -631
- data/lib/origami/optionalcontent.rb +147 -149
- data/lib/origami/outline.rb +46 -48
- data/lib/origami/outputintents.rb +76 -77
- data/lib/origami/page.rb +637 -596
- data/lib/origami/parser.rb +214 -221
- data/lib/origami/parsers/fdf.rb +44 -45
- data/lib/origami/parsers/pdf/lazy.rb +147 -154
- data/lib/origami/parsers/pdf/linear.rb +104 -109
- data/lib/origami/parsers/pdf.rb +109 -107
- data/lib/origami/parsers/ppklite.rb +44 -46
- data/lib/origami/pdf.rb +886 -896
- data/lib/origami/reference.rb +116 -120
- data/lib/origami/signature.rb +617 -625
- data/lib/origami/stream.rb +560 -558
- data/lib/origami/string.rb +366 -368
- data/lib/origami/template/patterns.rb +50 -52
- data/lib/origami/template/widgets.rb +111 -114
- data/lib/origami/trailer.rb +153 -157
- data/lib/origami/tree.rb +55 -57
- data/lib/origami/version.rb +19 -19
- data/lib/origami/webcapture.rb +87 -90
- data/lib/origami/xfa/config.rb +409 -414
- data/lib/origami/xfa/connectionset.rb +113 -117
- data/lib/origami/xfa/datasets.rb +38 -42
- data/lib/origami/xfa/localeset.rb +33 -37
- data/lib/origami/xfa/package.rb +49 -52
- data/lib/origami/xfa/pdf.rb +54 -59
- data/lib/origami/xfa/signature.rb +33 -37
- data/lib/origami/xfa/sourceset.rb +34 -38
- data/lib/origami/xfa/stylesheet.rb +35 -39
- data/lib/origami/xfa/template.rb +1630 -1634
- data/lib/origami/xfa/xdc.rb +33 -37
- data/lib/origami/xfa/xfa.rb +132 -123
- data/lib/origami/xfa/xfdf.rb +34 -38
- data/lib/origami/xfa/xmpmeta.rb +34 -38
- data/lib/origami/xfa.rb +50 -53
- data/lib/origami/xreftable.rb +462 -462
- data/lib/origami.rb +37 -38
- data/test/test_actions.rb +22 -20
- data/test/test_annotations.rb +54 -52
- data/test/test_forms.rb +23 -21
- data/test/test_native_types.rb +82 -78
- data/test/test_object_tree.rb +25 -24
- data/test/test_pages.rb +43 -41
- data/test/test_pdf.rb +2 -0
- data/test/test_pdf_attachment.rb +23 -21
- data/test/test_pdf_create.rb +16 -15
- data/test/test_pdf_encrypt.rb +69 -66
- data/test/test_pdf_parse.rb +131 -129
- data/test/test_pdf_parse_lazy.rb +53 -53
- data/test/test_pdf_sign.rb +67 -67
- data/test/test_streams.rb +145 -143
- data/test/test_xrefs.rb +46 -45
- metadata +64 -8
@@ -1,22 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This file is part of Origami, PDF manipulation framework for Ruby
|
5
|
+
# Copyright (C) 2016 Guillaume Delugré.
|
6
|
+
#
|
7
|
+
# Origami is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU Lesser General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# Origami is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU Lesser General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU Lesser General Public License
|
18
|
+
# along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
#
|
20
20
|
|
21
21
|
require 'origami/object'
|
22
22
|
require 'origami/name'
|
@@ -32,316 +32,311 @@ require 'origami/xreftable'
|
|
32
32
|
require 'origami/parsers/fdf'
|
33
33
|
|
34
34
|
module Origami
|
35
|
+
#
|
36
|
+
# Class representing an AcroForm Forms Data Format file.
|
37
|
+
#
|
38
|
+
class FDF
|
39
|
+
def self.read(path, options = {})
|
40
|
+
path = File.expand_path(path) if path.is_a?(::String)
|
41
|
+
|
42
|
+
FDF::Parser.new(options).parse(path)
|
43
|
+
end
|
44
|
+
|
45
|
+
class Header
|
46
|
+
MAGIC = /%FDF-(?<major>\d)\.(?<minor>\d)/
|
35
47
|
|
36
|
-
|
37
|
-
# Class representing an AcroForm Forms Data Format file.
|
38
|
-
#
|
39
|
-
class FDF
|
48
|
+
attr_accessor :major_version, :minor_version
|
40
49
|
|
41
|
-
|
42
|
-
|
50
|
+
#
|
51
|
+
# Creates a file header, with the given major and minor versions.
|
52
|
+
# _major_version_:: Major version.
|
53
|
+
# _minor_version_:: Minor version.
|
54
|
+
#
|
55
|
+
def initialize(major_version = 1, minor_version = 2)
|
56
|
+
@major_version, @minor_version = major_version, minor_version
|
57
|
+
end
|
43
58
|
|
44
|
-
|
59
|
+
def self.parse(stream) # :nodoc:
|
60
|
+
scanner = Parser.init_scanner(stream)
|
61
|
+
|
62
|
+
if !scanner.scan(MAGIC).nil?
|
63
|
+
maj = scanner['major'].to_i
|
64
|
+
min = scanner['minor'].to_i
|
65
|
+
else
|
66
|
+
raise InvalidHeader, "Invalid header format"
|
45
67
|
end
|
46
68
|
|
47
|
-
|
48
|
-
MAGIC = /%FDF-(?<major>\d)\.(?<minor>\d)/
|
69
|
+
scanner.skip(REGEXP_WHITESPACES)
|
49
70
|
|
50
|
-
|
71
|
+
FDF::Header.new(maj, min)
|
72
|
+
end
|
51
73
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
# _minor_version_:: Minor version.
|
56
|
-
#
|
57
|
-
def initialize(major_version = 1, minor_version = 2)
|
58
|
-
@major_version, @minor_version = major_version, minor_version
|
59
|
-
end
|
74
|
+
def to_s(eol: $/)
|
75
|
+
"%FDF-#{@major_version}.#{@minor_version}".b + eol
|
76
|
+
end
|
60
77
|
|
61
|
-
|
62
|
-
|
78
|
+
def to_sym # :nodoc:
|
79
|
+
:"#{@major_version}.#{@minor_version}"
|
80
|
+
end
|
63
81
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
raise InvalidHeader, "Invalid header format"
|
69
|
-
end
|
82
|
+
def to_f # :nodoc:
|
83
|
+
to_sym.to_s.to_f
|
84
|
+
end
|
85
|
+
end
|
70
86
|
|
71
|
-
|
87
|
+
class Revision # :nodoc;
|
88
|
+
attr_accessor :document
|
89
|
+
attr_accessor :body, :xreftable
|
90
|
+
attr_reader :trailer
|
91
|
+
|
92
|
+
def initialize(fdf)
|
93
|
+
@document = fdf
|
94
|
+
@body = {}
|
95
|
+
@xreftable = nil
|
96
|
+
@trailer = nil
|
97
|
+
end
|
98
|
+
|
99
|
+
def trailer=(trl)
|
100
|
+
trl.document = @document
|
101
|
+
@trailer = trl
|
102
|
+
end
|
103
|
+
|
104
|
+
def each_object(&b)
|
105
|
+
@body.each_value(&b)
|
106
|
+
end
|
107
|
+
|
108
|
+
def objects
|
109
|
+
@body.values
|
110
|
+
end
|
111
|
+
end
|
72
112
|
|
73
|
-
|
74
|
-
|
113
|
+
class JavaScript < Dictionary
|
114
|
+
include StandardObject
|
75
115
|
|
76
|
-
|
77
|
-
|
78
|
-
|
116
|
+
field :Before, Type: [String, Stream]
|
117
|
+
field :After, Type: [String, Stream]
|
118
|
+
field :AfterPermsReady, Type: [String, Stream]
|
119
|
+
field :Doc, Type: Array.of(Name, String)
|
120
|
+
end
|
79
121
|
|
80
|
-
|
81
|
-
|
82
|
-
end
|
122
|
+
class IconFit < Dictionary
|
123
|
+
include StandardObject
|
83
124
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
125
|
+
ALWAYS_SCALE = :A
|
126
|
+
SCALE_WHEN_BIGGER = :B
|
127
|
+
SCALE_WHEN_SMALLER = :S
|
128
|
+
NEVER_SCALE = :N
|
88
129
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
def initialize(fdf)
|
95
|
-
@document = fdf
|
96
|
-
@body = {}
|
97
|
-
@xreftable = nil
|
98
|
-
@trailer = nil
|
99
|
-
end
|
100
|
-
|
101
|
-
def trailer=(trl)
|
102
|
-
trl.document = @document
|
103
|
-
@trailer = trl
|
104
|
-
end
|
105
|
-
|
106
|
-
def each_object(&b)
|
107
|
-
@body.each_value(&b)
|
108
|
-
end
|
109
|
-
|
110
|
-
def objects
|
111
|
-
@body.values
|
112
|
-
end
|
113
|
-
end
|
130
|
+
field :SW, Type: Name
|
131
|
+
field :S, Type: Name
|
132
|
+
field :A, Type: Array.of(Number, length: 2)
|
133
|
+
field :FB, Type: Boolean
|
134
|
+
end
|
114
135
|
|
115
|
-
|
116
|
-
|
136
|
+
class NamedPageReference < Dictionary
|
137
|
+
include StandardObject
|
117
138
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
field :Doc, :Type => Array.of(Name, String)
|
122
|
-
end
|
123
|
-
|
124
|
-
class IconFit < Dictionary
|
125
|
-
include StandardObject
|
126
|
-
|
127
|
-
ALWAYS_SCALE = :A
|
128
|
-
SCALE_WHEN_BIGGER = :B
|
129
|
-
SCALE_WHEN_SMALLER = :S
|
130
|
-
NEVER_SCALE = :N
|
131
|
-
|
132
|
-
field :SW, :Type => Name
|
133
|
-
field :S, :Type => Name
|
134
|
-
field :A, :Type => Array.of(Number, length: 2)
|
135
|
-
field :FB, :Type => Boolean
|
136
|
-
end
|
137
|
-
|
138
|
-
class NamedPageReference < Dictionary
|
139
|
-
include StandardObject
|
139
|
+
field :Name, Type: String, Required: true
|
140
|
+
field :F, Type: FileSpec
|
141
|
+
end
|
140
142
|
|
141
|
-
|
142
|
-
|
143
|
-
|
143
|
+
class Field < Dictionary
|
144
|
+
include StandardObject
|
145
|
+
|
146
|
+
field :Kids, Type: Array.of(Field)
|
147
|
+
field :T, Type: String, Required: true
|
148
|
+
field :V, Type: Dictionary
|
149
|
+
field :Ff, Type: Integer
|
150
|
+
field :SetFf, Type: Integer
|
151
|
+
field :ClrFf, Type: Integer
|
152
|
+
field :F, Type: Integer
|
153
|
+
field :SetF, Type: Integer
|
154
|
+
field :ClrF, Type: Integer
|
155
|
+
field :AP, Type: Annotation::AppearanceDictionary
|
156
|
+
field :APRef, Type: Dictionary
|
157
|
+
field :IF, Type: IconFit
|
158
|
+
field :Opt, Type: Array.of([String, Array.of(String, String)])
|
159
|
+
field :A, Type: Action
|
160
|
+
field :AA, Type: Annotation::AdditionalActions
|
161
|
+
field :RV, Type: [String, Stream]
|
162
|
+
end
|
144
163
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
field :Kids, :Type => Array.of(Field)
|
149
|
-
field :T, :Type => String, :Required => true
|
150
|
-
field :V, :Type => Dictionary
|
151
|
-
field :Ff, :Type => Integer
|
152
|
-
field :SetFf, :Type => Integer
|
153
|
-
field :ClrFf, :Type => Integer
|
154
|
-
field :F, :Type => Integer
|
155
|
-
field :SetF, :Type => Integer
|
156
|
-
field :ClrF, :Type => Integer
|
157
|
-
field :AP, :Type => Annotation::AppearanceDictionary
|
158
|
-
field :APRef, :Type => Dictionary
|
159
|
-
field :IF, :Type => IconFit
|
160
|
-
field :Opt, :Type => Array.of([String, Array.of(String, String)])
|
161
|
-
field :A, :Type => Action
|
162
|
-
field :AA, :Type => Annotation::AdditionalActions
|
163
|
-
field :RV, :Type => [ String, Stream ]
|
164
|
-
end
|
165
|
-
|
166
|
-
class Template < Dictionary
|
167
|
-
include StandardObject
|
164
|
+
class Template < Dictionary
|
165
|
+
include StandardObject
|
168
166
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
class Page < Dictionary
|
175
|
-
include StandardObject
|
167
|
+
field :TRef, Type: NamedPageReference, Required: true
|
168
|
+
field :Fields, Type: Array.of(Field)
|
169
|
+
field :Rename, Type: Boolean
|
170
|
+
end
|
176
171
|
|
177
|
-
|
178
|
-
|
179
|
-
end
|
172
|
+
class Page < Dictionary
|
173
|
+
include StandardObject
|
180
174
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
class Dictionary < Origami::Dictionary
|
186
|
-
include StandardObject
|
187
|
-
|
188
|
-
field :F, :Type => FileSpec
|
189
|
-
field :ID, :Type => Array.of(String, length: 2)
|
190
|
-
field :Fields, :Type => Array.of(FDF::Field)
|
191
|
-
field :Status, :Type => String
|
192
|
-
field :Pages, :Type => Array.of(FDF::Page)
|
193
|
-
field :Encoding, :Type => Name
|
194
|
-
field :Annots, :Type => Array.of(FDF::Annotation)
|
195
|
-
field :Differences, :Type => Stream
|
196
|
-
field :Target, :Type => String
|
197
|
-
field :EmbeddedFDFs, :Type => Array.of(FileSpec)
|
198
|
-
field :JavaScript, :Type => JavaScript
|
199
|
-
end
|
200
|
-
|
201
|
-
class Catalog < Dictionary
|
202
|
-
include StandardObject
|
175
|
+
field :Templates, Type: Array.of(Template), Required: true
|
176
|
+
field :Info, Type: Dictionary
|
177
|
+
end
|
203
178
|
|
204
|
-
|
205
|
-
|
206
|
-
|
179
|
+
class Annotation < Origami::Annotation
|
180
|
+
field :Page, Type: Integer, Required: true
|
181
|
+
end
|
207
182
|
|
208
|
-
|
183
|
+
class Dictionary < Origami::Dictionary
|
184
|
+
include StandardObject
|
185
|
+
|
186
|
+
field :F, Type: FileSpec
|
187
|
+
field :ID, Type: Array.of(String, length: 2)
|
188
|
+
field :Fields, Type: Array.of(FDF::Field)
|
189
|
+
field :Status, Type: String
|
190
|
+
field :Pages, Type: Array.of(FDF::Page)
|
191
|
+
field :Encoding, Type: Name
|
192
|
+
field :Annots, Type: Array.of(FDF::Annotation)
|
193
|
+
field :Differences, Type: Stream
|
194
|
+
field :Target, Type: String
|
195
|
+
field :EmbeddedFDFs, Type: Array.of(FileSpec)
|
196
|
+
field :JavaScript, Type: JavaScript
|
197
|
+
end
|
209
198
|
|
210
|
-
|
211
|
-
|
212
|
-
@revisions = [ Revision.new(self) ]
|
213
|
-
@revisions.first.trailer = Trailer.new
|
214
|
-
@parser = parser
|
199
|
+
class Catalog < Dictionary
|
200
|
+
include StandardObject
|
215
201
|
|
216
|
-
|
217
|
-
|
202
|
+
field :Version, Type: Name
|
203
|
+
field :FDF, Type: FDF::Dictionary, Required: true
|
204
|
+
end
|
218
205
|
|
219
|
-
|
220
|
-
object.set_indirect(true)
|
221
|
-
object.set_document(self)
|
206
|
+
attr_accessor :header, :revisions
|
222
207
|
|
223
|
-
|
224
|
-
|
225
|
-
|
208
|
+
def initialize(parser = nil) # :nodoc:
|
209
|
+
@header = FDF::Header.new
|
210
|
+
@revisions = [Revision.new(self)]
|
211
|
+
@revisions.first.trailer = Trailer.new
|
212
|
+
@parser = parser
|
226
213
|
|
227
|
-
|
228
|
-
|
229
|
-
end
|
214
|
+
init if parser.nil?
|
215
|
+
end
|
230
216
|
|
231
|
-
|
217
|
+
def <<(object)
|
218
|
+
object.set_indirect(true)
|
219
|
+
object.set_document(self)
|
232
220
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
def get_object(no, generation = 0) #:nodoc:
|
238
|
-
case no
|
239
|
-
when Reference
|
240
|
-
target = no
|
241
|
-
when ::Integer
|
242
|
-
target = Reference.new(no, generation)
|
243
|
-
when Origami::Object
|
244
|
-
return no
|
245
|
-
end
|
246
|
-
|
247
|
-
@revisions.first.body[target]
|
248
|
-
end
|
221
|
+
if object.no.zero?
|
222
|
+
maxno = 1
|
223
|
+
maxno = maxno.succ while get_object(maxno)
|
249
224
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
alias root_objects indirect_objects
|
254
|
-
|
255
|
-
def cast_object(reference, type) #:nodoc:
|
256
|
-
@revisions.each do |rev|
|
257
|
-
if rev.body.include?(reference) and type < rev.body[reference].class
|
258
|
-
rev.body[reference] = rev.body[reference].cast_to(type, @parser)
|
259
|
-
|
260
|
-
rev.body[reference]
|
261
|
-
else
|
262
|
-
nil
|
263
|
-
end
|
264
|
-
end
|
265
|
-
end
|
225
|
+
object.generation = 0
|
226
|
+
object.no = maxno
|
227
|
+
end
|
266
228
|
|
267
|
-
|
268
|
-
|
229
|
+
@revisions.first.body[object.reference] = object
|
230
|
+
|
231
|
+
object.reference
|
232
|
+
end
|
233
|
+
alias_method :insert, :<<
|
234
|
+
|
235
|
+
def get_object(no, generation = 0) # :nodoc:
|
236
|
+
case no
|
237
|
+
when Reference
|
238
|
+
target = no
|
239
|
+
when ::Integer
|
240
|
+
target = Reference.new(no, generation)
|
241
|
+
when Origami::Object
|
242
|
+
return no
|
243
|
+
end
|
244
|
+
|
245
|
+
@revisions.first.body[target]
|
246
|
+
end
|
247
|
+
|
248
|
+
def indirect_objects
|
249
|
+
@revisions.inject([]) do |set, rev| set.concat(rev.objects) end
|
250
|
+
end
|
251
|
+
alias_method :root_objects, :indirect_objects
|
252
|
+
|
253
|
+
def cast_object(reference, type) # :nodoc:
|
254
|
+
@revisions.each do |rev|
|
255
|
+
if rev.body.include?(reference) && (type < rev.body[reference].class)
|
256
|
+
rev.body[reference] = rev.body[reference].cast_to(type, @parser)
|
257
|
+
|
258
|
+
rev.body[reference]
|
269
259
|
end
|
260
|
+
end
|
261
|
+
end
|
270
262
|
|
271
|
-
|
272
|
-
|
273
|
-
|
263
|
+
def Catalog
|
264
|
+
get_object(@revisions.first.trailer.Root)
|
265
|
+
end
|
274
266
|
|
275
|
-
|
267
|
+
def save(path)
|
268
|
+
bin = "".b
|
269
|
+
bin << @header.to_s
|
276
270
|
|
277
|
-
|
278
|
-
xrefsection = XRef::Section.new
|
271
|
+
lastno, brange = 0, 0
|
279
272
|
|
280
|
-
|
281
|
-
|
282
|
-
xrefsection << XRef::Subsection.new(brange, xrefs)
|
283
|
-
brange = obj.no
|
284
|
-
xrefs.clear
|
285
|
-
end
|
273
|
+
xrefs = [XRef.new(0, XRef::FIRSTFREE, XRef::FREE)]
|
274
|
+
xrefsection = XRef::Section.new
|
286
275
|
|
287
|
-
|
288
|
-
|
276
|
+
@revisions.first.body.values.sort.each { |obj|
|
277
|
+
if (obj.no - lastno).abs > 1
|
278
|
+
xrefsection << XRef::Subsection.new(brange, xrefs)
|
279
|
+
brange = obj.no
|
280
|
+
xrefs.clear
|
281
|
+
end
|
289
282
|
|
290
|
-
|
283
|
+
xrefs << XRef.new(bin.size, obj.generation, XRef::USED)
|
284
|
+
lastno = obj.no
|
291
285
|
|
292
|
-
|
286
|
+
obj.pre_build
|
293
287
|
|
294
|
-
|
295
|
-
}
|
288
|
+
bin << obj.to_s
|
296
289
|
|
297
|
-
|
290
|
+
obj.post_build
|
291
|
+
}
|
298
292
|
|
299
|
-
|
300
|
-
@trailer ||= Trailer.new
|
301
|
-
@trailer.Size = @revisions.first.body.size + 1
|
302
|
-
@trailer.startxref = bin.size
|
293
|
+
xrefsection << XRef::Subsection.new(brange, xrefs)
|
303
294
|
|
304
|
-
|
305
|
-
|
295
|
+
@xreftable = xrefsection
|
296
|
+
@trailer ||= Trailer.new
|
297
|
+
@trailer.Size = @revisions.first.body.size + 1
|
298
|
+
@trailer.startxref = bin.size
|
306
299
|
|
307
|
-
|
308
|
-
|
309
|
-
else
|
310
|
-
path = File.expand_path(path)
|
311
|
-
io = File.open(path, "wb", encoding: 'binary')
|
312
|
-
close = true
|
313
|
-
end
|
300
|
+
bin << @xreftable.to_s
|
301
|
+
bin << @trailer.to_s
|
314
302
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
303
|
+
if path.respond_to?(:write)
|
304
|
+
io = path
|
305
|
+
else
|
306
|
+
path = File.expand_path(path)
|
307
|
+
io = File.open(path, "wb", encoding: 'binary')
|
308
|
+
close = true
|
309
|
+
end
|
320
310
|
|
321
|
-
|
322
|
-
|
311
|
+
begin
|
312
|
+
io.write(bin)
|
313
|
+
ensure
|
314
|
+
io.close if close
|
315
|
+
end
|
323
316
|
|
324
|
-
|
317
|
+
self
|
318
|
+
end
|
325
319
|
|
326
|
-
|
327
|
-
catalog = Catalog.new(:FDF => FDF::Dictionary.new)
|
320
|
+
private
|
328
321
|
|
329
|
-
|
330
|
-
|
322
|
+
def init
|
323
|
+
catalog = Catalog.new(FDF: FDF::Dictionary.new)
|
331
324
|
|
332
|
-
|
333
|
-
|
334
|
-
objectoffset = bodyoffset
|
325
|
+
@revisions.first.trailer.Root = insert(catalog)
|
326
|
+
end
|
335
327
|
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
objectoffset += object.to_s.size
|
340
|
-
end
|
341
|
-
}
|
328
|
+
def get_object_offset(no, generation) # :nodoc:
|
329
|
+
bodyoffset = @header.to_s.size
|
330
|
+
objectoffset = bodyoffset
|
342
331
|
|
343
|
-
|
332
|
+
@revisions.first.body.values.each { |object|
|
333
|
+
if (object.no == no) && (object.generation == generation) then return objectoffset
|
334
|
+
else
|
335
|
+
objectoffset += object.to_s.size
|
344
336
|
end
|
345
|
-
|
337
|
+
}
|
338
|
+
|
339
|
+
nil
|
346
340
|
end
|
341
|
+
end
|
347
342
|
end
|