Class: Pdfrb::Document
- Inherits:
-
Object
show all
- Defined in:
- lib/pdfrb/document.rb,
lib/pdfrb/document/form.rb,
lib/pdfrb/document/info.rb,
lib/pdfrb/document/files.rb,
lib/pdfrb/document/fonts.rb,
lib/pdfrb/document/pages.rb,
lib/pdfrb/document/colors.rb,
lib/pdfrb/document/images.rb,
lib/pdfrb/document/layers.rb,
lib/pdfrb/document/stamps.rb,
lib/pdfrb/document/display.rb,
lib/pdfrb/document/outline.rb,
lib/pdfrb/document/metadata.rb,
lib/pdfrb/document/shadings.rb,
lib/pdfrb/document/portfolio.rb,
lib/pdfrb/document/structure.rb,
lib/pdfrb/document/annotations.rb,
lib/pdfrb/document/page_labels.rb,
lib/pdfrb/document/destinations.rb,
lib/pdfrb/document/form_xobject.rb,
lib/pdfrb/document/graphics_state.rb,
lib/pdfrb/document/output_intents.rb,
lib/pdfrb/document/associated_files.rb
Overview
Top-level PDF document facade. Owns:
* The IO it was read from (or nil for in-memory).
* An oid -> Object table for new/modified objects.
* A wrap() pipeline that upgrades raw Hashes to typed
Dictionary subclasses based on /Type or an explicit type.
* On read: an XrefSection + ObjectReader for lazy resolution.
* A revisions stack (TODO 30 — incremental updates).
Defined Under Namespace
Classes: Annotations, AssociatedFiles, Colors, Destinations, Display, Files, Fonts, Form, FormXObject, GraphicsState, Images, Info, Layers, Metadata, Outline, OutlineEntry, OutputIntents, PageLabels, Pages, Portfolio, Shadings, Stamps, Structure
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
-
#add(value, type: nil) ⇒ Object
-
#annotations ⇒ Object
-
#associated_files ⇒ Object
-
#catalog ⇒ Object
-
#colors ⇒ Object
-
#create_form_xobject(name: nil, bbox: nil, matrix: nil) ⇒ Object
-
#destinations ⇒ Object
-
#dispatch_message(message, *args) ⇒ Object
-
#display ⇒ Object
-
#each_indirect_object ⇒ Object
Yield every indirect object in this document: modified/new ones first (they shadow loaded ones), then every loaded entry the xref knows about.
-
#files ⇒ Object
-
#fonts ⇒ Object
-
#forget(oid) ⇒ Object
Drop a modified/new object from the in-memory table so it's no longer emitted by the writer.
-
#form ⇒ Object
-
#graphics_state ⇒ Object
-
#images ⇒ Object
-
#info ⇒ Object
-
#initialize(io: nil, config: {}) ⇒ Document
constructor
A new instance of Document.
-
#layers ⇒ Object
-
#load_xmp_packet ⇒ Object
-
#metadata ⇒ Object
-
#object(reference) ⇒ Object
(also: #dereference)
Resolve a Reference to its Object.
-
#outline ⇒ Object
-
#output_intents ⇒ Object
-
#page_labels ⇒ Object
-
#pages ⇒ Object
---- Facade accessors (Phase 13) ---- Each returns a memoised helper object that knows how to mutate this document.
-
#portfolio ⇒ Object
-
#register_listener(message, &block) ⇒ Object
-
#register_override(obj) ⇒ Object
Replace an indirect object in the @objects table.
-
#shadings ⇒ Object
-
#stamps ⇒ Object
-
#structure ⇒ Object
-
#trailer ⇒ Object
Convenience accessor for the document Catalog dict.
-
#wrap(data, type: nil, oid: 0, gen: 0) ⇒ Object
-
#write(path = nil, io: nil) ⇒ Object
Write this document to path (or any IO via +io:).
-
#xmp ⇒ Object
Constructor Details
#initialize(io: nil, config: {}) ⇒ Document
Returns a new instance of Document.
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
# File 'lib/pdfrb/document.rb', line 35
def initialize(io: nil, config: {})
Pdfrb::Model::Type.eager_load!
@config = Configuration.new(config)
@io = io
@objects = {} @next_oid = 1
@listeners = {} @xref = nil
@object_reader = nil
@version = "1.4"
@empty_trailer = nil
if io
read_from_io(io)
else
seed_empty_structure
end
end
|
Instance Attribute Details
#config ⇒ Object
Returns the value of attribute config.
54
55
56
|
# File 'lib/pdfrb/document.rb', line 54
def config
@config
end
|
#io ⇒ Object
Returns the value of attribute io.
54
55
56
|
# File 'lib/pdfrb/document.rb', line 54
def io
@io
end
|
#next_oid ⇒ Object
Returns the value of attribute next_oid.
54
55
56
|
# File 'lib/pdfrb/document.rb', line 54
def next_oid
@next_oid
end
|
#version ⇒ Object
Returns the value of attribute version.
54
55
56
|
# File 'lib/pdfrb/document.rb', line 54
def version
@version
end
|
#xref ⇒ Object
Returns the value of attribute xref.
54
55
56
|
# File 'lib/pdfrb/document.rb', line 54
def xref
@xref
end
|
Class Method Details
.open(path, **opts) ⇒ Object
56
57
58
59
60
61
62
63
64
|
# File 'lib/pdfrb/document.rb', line 56
def self.open(path, **opts)
if block_given?
File.open(path, "rb") { |f| yield new(io: f, **opts) }
else
bytes = File.binread(path)
require "stringio"
new(io: StringIO.new(bytes), **opts)
end
end
|
Instance Method Details
#add(value, type: nil) ⇒ Object
76
77
78
79
80
81
|
# File 'lib/pdfrb/document.rb', line 76
def add(value, type: nil)
oid = allocate_oid
obj = wrap(value, type: type, oid: oid, gen: 0)
register(obj)
obj
end
|
#annotations ⇒ Object
135
136
137
|
# File 'lib/pdfrb/document.rb', line 135
def annotations
@annotations ||= Document::Annotations.new(self)
end
|
#associated_files ⇒ Object
#catalog ⇒ Object
227
228
229
230
231
232
233
234
|
# File 'lib/pdfrb/document.rb', line 227
def catalog
return @catalog if defined?(@catalog) && @catalog
ref = trailer ? trailer[:Root] : nil
return nil unless ref
@catalog = object(ref)
end
|
#colors ⇒ Object
149
|
# File 'lib/pdfrb/document.rb', line 149
def colors; @colors ||= Document::Colors.new(self); end
|
190
191
192
|
# File 'lib/pdfrb/document.rb', line 190
def create_form_xobject(name: nil, bbox: nil, matrix: nil)
FormXObject.new(self, name: name, bbox: bbox, matrix: matrix)
end
|
#destinations ⇒ Object
131
132
133
|
# File 'lib/pdfrb/document.rb', line 131
def destinations
@destinations ||= Document::Destinations.new(self)
end
|
#dispatch_message(message, *args) ⇒ Object
101
102
103
104
105
|
# File 'lib/pdfrb/document.rb', line 101
def dispatch_message(message, *args)
return unless @listeners.key?(message)
@listeners[message].each { |blk| blk.call(*args) }
end
|
#display ⇒ Object
167
|
# File 'lib/pdfrb/document.rb', line 167
def display; @display ||= Document::Display.new(self); end
|
#each_indirect_object ⇒ Object
Yield every indirect object in this document: modified/new ones
first (they shadow loaded ones), then every loaded entry the
xref knows about.
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
|
# File 'lib/pdfrb/document.rb', line 239
def each_indirect_object
return enum_for(:each_indirect_object) unless block_given?
seen = Set.new
@objects.each_value do |obj|
next unless obj.indirect?
seen << obj.oid
yield obj
end
return if @xref.nil?
@xref.entries.each_key do |oid|
next if seen.include?(oid)
next if oid.zero?
obj = object(Pdfrb::Model::Reference.new(oid, 0))
next if obj.nil? || !obj.indirect?
yield obj
end
end
|
#files ⇒ Object
123
124
125
|
# File 'lib/pdfrb/document.rb', line 123
def files
@files ||= Document::Files.new(self)
end
|
#fonts ⇒ Object
115
116
117
|
# File 'lib/pdfrb/document.rb', line 115
def fonts
@fonts ||= Document::Fonts.new(self)
end
|
#forget(oid) ⇒ Object
Drop a modified/new object from the in-memory table so it's no
longer emitted by the writer. Used by Task::Optimize when a
stream has been deduplicated against a canonical sibling.
Returns the dropped object (or nil if not present).
205
206
207
|
# File 'lib/pdfrb/document.rb', line 205
def forget(oid)
@objects.delete(oid)
end
|
145
|
# File 'lib/pdfrb/document.rb', line 145
def form; @form ||= Document::Form.new(self); end
|
#graphics_state ⇒ Object
151
|
# File 'lib/pdfrb/document.rb', line 151
def graphics_state; @graphics_state ||= Document::GraphicsState.new(self); end
|
#images ⇒ Object
119
120
121
|
# File 'lib/pdfrb/document.rb', line 119
def images
@images ||= Document::Images.new(self)
end
|
#info ⇒ Object
165
|
# File 'lib/pdfrb/document.rb', line 165
def info; @info ||= Document::Info.new(self); end
|
#layers ⇒ Object
153
|
# File 'lib/pdfrb/document.rb', line 153
def layers; @layers ||= Document::Layers.new(self); end
|
#load_xmp_packet ⇒ Object
182
183
184
185
186
|
# File 'lib/pdfrb/document.rb', line 182
def load_xmp_packet
Pdfrb::XMP::Packet.new
rescue LoadError
nil
end
|
127
128
129
|
# File 'lib/pdfrb/document.rb', line 127
def metadata
@metadata ||= Document::Metadata.new(self)
end
|
#object(reference) ⇒ Object
Also known as:
dereference
Resolve a Reference to its Object. New/modified objects take
precedence over xref-loaded ones; otherwise consult the
ObjectReader (which caches per oid).
86
87
88
89
90
91
92
93
94
|
# File 'lib/pdfrb/document.rb', line 86
def object(reference)
return reference unless reference.is_a?(Pdfrb::Model::Reference)
modified = @objects[reference.oid]
return modified if modified
return nil if @object_reader.nil?
@object_reader.load_oid(reference.oid)
end
|
#outline ⇒ Object
139
140
141
|
# File 'lib/pdfrb/document.rb', line 139
def outline
@outline ||= Document::Outline.new(self)
end
|
#output_intents ⇒ Object
159
|
# File 'lib/pdfrb/document.rb', line 159
def output_intents; @output_intents ||= Document::OutputIntents.new(self); end
|
#page_labels ⇒ Object
161
|
# File 'lib/pdfrb/document.rb', line 161
def page_labels; @page_labels ||= Document::PageLabels.new(self); end
|
#pages ⇒ Object
---- Facade accessors (Phase 13) ----
Each returns a memoised helper object that knows how to mutate
this document. Defined under Pdfrb::Document::*.
111
112
113
|
# File 'lib/pdfrb/document.rb', line 111
def pages
@pages ||= Document::Pages.new(self)
end
|
#portfolio ⇒ Object
157
|
# File 'lib/pdfrb/document.rb', line 157
def portfolio; @portfolio ||= Document::Portfolio.new(self); end
|
#register_listener(message, &block) ⇒ Object
97
98
99
|
# File 'lib/pdfrb/document.rb', line 97
def register_listener(message, &block)
(@listeners[message] ||= []) << block
end
|
#register_override(obj) ⇒ Object
Replace an indirect object in the @objects table. Used by the
Importer when promoting a Dictionary stub to a Stream (so cycles
resolve correctly). Idempotent.
197
198
199
|
# File 'lib/pdfrb/document.rb', line 197
def register_override(obj)
@objects[obj.oid] = obj
end
|
#shadings ⇒ Object
147
|
# File 'lib/pdfrb/document.rb', line 147
def shadings; @shadings ||= Document::Shadings.new(self); end
|
#stamps ⇒ Object
163
|
# File 'lib/pdfrb/document.rb', line 163
def stamps; @stamps ||= Document::Stamps.new(self); end
|
#structure ⇒ Object
143
|
# File 'lib/pdfrb/document.rb', line 143
def structure; @structure ||= Document::Structure.new(self); end
|
#trailer ⇒ Object
Convenience accessor for the document Catalog dict. Loads from
trailer's /Root, which itself is loaded lazily from the xref.
221
222
223
224
225
|
# File 'lib/pdfrb/document.rb', line 221
def trailer
return @trailer if defined?(@trailer) && @trailer
@trailer = read_trailer
end
|
#wrap(data, type: nil, oid: 0, gen: 0) ⇒ Object
66
67
68
69
70
71
72
73
74
|
# File 'lib/pdfrb/document.rb', line 66
def wrap(data, type: nil, oid: 0, gen: 0)
target_class = resolve_target_class(data, type)
value = unwrap_value(data)
if target_class <= Pdfrb::Model::Object
target_class.new(value, oid: oid, gen: gen, document: self)
else
target_class.new(value)
end
end
|
#write(path = nil, io: nil) ⇒ Object
Write this document to path (or any IO via +io:).
210
211
212
213
214
215
216
217
|
# File 'lib/pdfrb/document.rb', line 210
def write(path = nil, io: nil)
target = io || (path && File.open(path, "wb"))
raise ArgumentError, "write needs a path or io:" unless target
Pdfrb::Writer.write(self, target)
target.close if path && io.nil? && target.is_a?(IO)
self
end
|
#xmp ⇒ Object
169
170
171
172
173
174
175
176
177
178
179
180
|
# File 'lib/pdfrb/document.rb', line 169
def xmp
return @xmp if @xmp
packet = load_xmp_packet
return nil unless packet
title = metadata[:Title]
packet.title = title if title
author = metadata[:Author]
packet.author = author if author
@xmp = packet
end
|