# -*- encoding: utf-8; frozen_string_literal: true -*-
#
#--
# This file is part of HexaPDF.
#
# HexaPDF - A Versatile PDF Creation and Manipulation Library For Ruby
# Copyright (C) 2014-2019 Thomas Leitner
#
# HexaPDF is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License version 3 as
# published by the Free Software Foundation with the addition of the
# following permission added to Section 15 as permitted in Section 7(a):
# FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
# THOMAS LEITNER, THOMAS LEITNER DISCLAIMS THE WARRANTY OF NON
# INFRINGEMENT OF THIRD PARTY RIGHTS.
#
# HexaPDF is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with HexaPDF. If not, see .
#
# The interactive user interfaces in modified source and object code
# versions of HexaPDF must display Appropriate Legal Notices, as required
# under Section 5 of the GNU Affero General Public License version 3.
#
# In accordance with Section 7(b) of the GNU Affero General Public
# License, a covered work must retain the producer line in every PDF that
# is created or manipulated using HexaPDF.
#
# If the GNU Affero General Public License doesn't fit your need,
# commercial licenses are available at .
#++
require 'hexapdf/stream'
require 'hexapdf/content'
module HexaPDF
module Type
# Represents a form XObject of a PDF document.
#
# See: PDF1.7 s8.10
class Form < Stream
define_type :XObject
define_field :Type, type: Symbol, default: type
define_field :Subtype, type: Symbol, required: true, default: :Form
define_field :FormType, type: Integer, default: 1, allowed_values: 1
define_field :BBox, type: Rectangle, required: true
define_field :Matrix, type: PDFArray, default: [1, 0, 0, 1, 0, 0]
define_field :Resources, type: :XXResources, version: '1.2'
define_field :Group, type: Dictionary, version: '1.4'
define_field :Ref, type: Dictionary, version: '1.4'
define_field :Metadata, type: Stream, version: '1.4'
define_field :PieceInfo, type: Dictionary, version: '1.3'
define_field :LastModified, type: PDFDate, version: '1.3'
define_field :StructParent, type: Integer, version: '1.3'
define_field :StructParents, type: Integer, version: '1.3'
define_field :OPI, type: Dictionary, version: '1.2'
define_field :OC, type: Dictionary, version: '1.5'
# 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).
attr_accessor :source_path
# Returns the rectangle defining the bounding box of the form.
def box
self[:BBox]
end
# Returns the width of the bounding box (see #box).
def width
box.width
end
# Returns the height of the bounding box (see #box).
def height
box.height
end
# Returns the contents of the form XObject.
#
# Note: This is the same as #stream but here for interface compatibility with Page.
def contents
stream
end
# Replaces the contents of the form XObject with the given string.
#
# Note: This is the same as #stream= but here for interface compatibility with Page.
def contents=(data)
self.stream = data
end
# Returns the resource dictionary which is automatically created if it doesn't exist.
def resources
self[:Resources] ||= document.wrap({}, type: :XXResources)
end
# 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
def process_contents(processor, original_resources: nil)
processor.resources = if self[:Resources]
self[:Resources]
elsif original_resources
original_resources
else
document.wrap({}, type: :XXResources)
end
Content::Parser.parse(contents, processor)
end
# 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.
#
# *Note* that a canvas can only be retrieved for initially empty form XObjects!
def canvas
document.cache(@data, :canvas) do
unless stream.empty?
raise HexaPDF::Error, "Cannot create a canvas for a form XObjects with contents"
end
canvas = Content::Canvas.new(self)
self.stream = canvas.stream_data
set_filter(:FlateDecode)
canvas
end
end
end
end
end