Class: HexaPDF::Type::Form

Inherits:
Stream show all
Defined in:
lib/hexapdf/type/form.rb

Overview

Represents a form XObject of a PDF document.

See: PDF2.0 s8.10

Defined Under Namespace

Classes: Group, Reference

Constant Summary

Constants included from DictionaryFields

DictionaryFields::Boolean, DictionaryFields::PDFByteString, DictionaryFields::PDFDate

Instance Attribute Summary collapse

Attributes inherited from Object

#data, #document, #must_be_indirect

Instance Method Summary collapse

Methods inherited from Stream

#must_be_indirect?, #raw_stream, #set_filter, #stream, #stream=, #stream_decoder, #stream_encoder, #stream_source

Methods inherited from Dictionary

#[], #[]=, define_field, define_type, #delete, #each, each_field, #empty?, field, #key?, #to_h, type, #type

Methods inherited from Object

#<=>, #==, #cache, #cached?, #clear_cache, deep_copy, #deep_copy, #document?, #eql?, field, #gen, #gen=, #hash, #indirect?, #initialize, #inspect, make_direct, #must_be_indirect?, #null?, #oid, #oid=, #type, #validate, #value, #value=

Constructor Details

This class inherits a constructor from HexaPDF::Object

Instance Attribute Details

#source_pathObject

Returns the path to the PDF file that was used when creating the form object.

This value is only set when the form object was created by using the image loading facility (i.e. when treating a single page PDF file as image) and not when the form object was created in any other way (i.e. manually created or already part of a loaded PDF file).



98
99
100
# File 'lib/hexapdf/type/form.rb', line 98

def source_path
  @source_path
end

Instance Method Details

#boxObject

Returns the rectangle defining the bounding box of the form.



101
102
103
# File 'lib/hexapdf/type/form.rb', line 101

def box
  self[:BBox]
end

#canvasObject

Returns the canvas for the form XObject.

The canvas object is cached once it is created so that its graphics state is correctly retained without the need for parsing its contents.

If the bounding box of the form XObject doesn’t have its origin at (0, 0), the canvas origin is translated into the bottom left corner so that this detail doesn’t matter when using the canvas. This means that the canvas’ origin is always at the bottom left corner of the bounding box.

Note that a canvas can only be retrieved for initially empty form XObjects!



167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/hexapdf/type/form.rb', line 167

def canvas
  cache(:canvas) do
    unless stream.empty?
      raise HexaPDF::Error, "Cannot create a canvas for a form XObjects with contents"
    end

    canvas = Content::Canvas.new(self)
    if box.left != 0 || box.bottom != 0
      canvas.save_graphics_state.translate(box.left, box.bottom)
    end
    self.stream = canvas.stream_data
    set_filter(:FlateDecode)
    canvas
  end
end

#contentsObject

Returns the contents of the form XObject.

Note: This is the same as #stream but here for interface compatibility with Page.



118
119
120
# File 'lib/hexapdf/type/form.rb', line 118

def contents
  stream
end

#contents=(data) ⇒ Object

Replaces the contents of the form XObject with the given string.

This also clears the cache to avoid returning invalid objects.

Note: This is the same as #stream= but here for interface compatibility with Page.



127
128
129
130
# File 'lib/hexapdf/type/form.rb', line 127

def contents=(data)
  self.stream = data
  clear_cache
end

#heightObject

Returns the height of the bounding box (see #box).



111
112
113
# File 'lib/hexapdf/type/form.rb', line 111

def height
  box.height
end

#process_contents(processor, original_resources: nil) ⇒ Object

Processes the content stream of the form XObject with the given processor object.

The original_resources argument has to be set to a page’s resources if this form XObject is processed as part of this page.

See: HexaPDF::Content::Processor



144
145
146
147
148
149
150
151
152
153
154
# File 'lib/hexapdf/type/form.rb', line 144

def process_contents(processor, original_resources: nil)
  form = referenced_content || self
  processor.resources = if form[:Resources]
                          form[:Resources]
                        elsif original_resources
                          original_resources
                        else
                          document.wrap({}, type: :XXResources)
                        end
  Content::Parser.parse(form.contents, processor)
end

#reference_xobject?Boolean

Returns true if the Form XObject is a reference XObject.

Returns:



184
185
186
# File 'lib/hexapdf/type/form.rb', line 184

def reference_xobject?
  !self[:Ref].nil?
end

#referenced_contentObject

Returns the referenced page as Form XObject, if this Form XObject is a Reference XObject and the referenced page is found. Otherwise returns nil.



190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/hexapdf/type/form.rb', line 190

def referenced_content
  return unless (ref = self[:Ref])

  doc = if ref[:F].embedded_file?
          HexaPDF::Document.new(io: StringIO.new(ref[:F].embedded_file_stream.stream))
        elsif File.exist?(ref[:F].path)
          HexaPDF::Document.open(ref[:F].path)
        end
  return unless doc

  page = ref[:Page]
  if page.kind_of?(Integer)
    page = doc.pages[page]
  else
    labels = []
    doc.pages.each_labelling_range do |first_index, count, label|
      count.times {|i| labels << label.construct_label(i) }
    end
    index = labels.index(page)
    page = index && doc.pages[index]
  end
  return unless page

  # See PDF2.0 s8.10.4.3
  print_annots = page.each_annotation.select {|annot| annot.flagged?(:print) }
  page.flatten_annotations(print_annots) unless print_annots.empty?

  obj = page.to_form_xobject
  obj[:BBox] = self[:BBox].dup
  obj[:Matrix] = self[:Matrix].dup
  obj
rescue
  nil
end

#resourcesObject

Returns the resource dictionary which is automatically created if it doesn’t exist.



133
134
135
136
# File 'lib/hexapdf/type/form.rb', line 133

def resources
  self[:Resources] ||= document.wrap({ProcSet: [:PDF, :Text, :ImageB, :ImageC, :ImageI]},
                                     type: :XXResources)
end

#widthObject

Returns the width of the bounding box (see #box).



106
107
108
# File 'lib/hexapdf/type/form.rb', line 106

def width
  box.width
end