Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/pdf/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require_relative 'core/annotations'
require_relative 'core/byte_string'
require_relative 'core/destinations'
require_relative 'core/embedded_files'
require_relative 'core/filters'
require_relative 'core/stream'
require_relative 'core/reference'
Expand Down
42 changes: 42 additions & 0 deletions lib/pdf/core/embedded_files.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true

module PDF
module Core
module EmbeddedFiles #:nodoc:
# The maximum number of children to fit into a single node in the
# EmbeddedFiles tree.
NAME_TREE_CHILDREN_LIMIT = 20 #:nodoc:

# The EmbeddedFiles name tree in the Name dictionary (see
# Prawn::Document::Internal#names). This name tree is used to store named
# embedded files (PDF spec 3.10.3). (For more on name trees, see section
# 3.8.4 in the PDF spec.)
#
def embedded_files
bump_min_version

names.data[:EmbeddedFiles] ||= ref!(
PDF::Core::NameTree::Node.new(self, NAME_TREE_CHILDREN_LIMIT)
)
end

# Adds a new embedded file to the EmbeddedFiles name tree
# (see #embedded_files). The +reference+ parameter will be converted into
# a PDF::Core::Reference if it is not already one.
#
def add_embedded_file(name, reference)
reference = ref!(reference) unless reference.is_a?(PDF::Core::Reference)
embedded_files.data.add(name, reference)
end

# Friendly method alias to attach file specifications in the catalog
alias attach_file add_embedded_file

private

def bump_min_version
renderer.min_version(1.4)
end
end
end
end
60 changes: 60 additions & 0 deletions spec/pdf/core/embedded_files_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# frozen_string_literal: true

require 'spec_helper'

class EmbeddedFiles
include PDF::Core::EmbeddedFiles

class InnerRenderer; def min_version(value); end; end

attr_reader :renderer

def initialize
@size = 0
@root = ref!(Type: :Catalog)
@renderer = InnerRenderer.new
end

def names
@root.data[:Names] ||= ref!(Type: :Names)
end

def ref!(data)
@size += 1

PDF::Core::Reference.new(@size, data)
end
end

RSpec.describe EmbeddedFiles do
it 'has an empty catalog object' do
t = described_class.new
pdf_object = "2 0 obj\n<< /Type /Names\n>>\nendobj\n"
expect(t.names.object).to eq pdf_object
end

it 'has an embedded files object with no names' do
t = described_class.new
pdf_object = "3 0 obj\n<< /Names []\n>>\nendobj\n"
expect(t.embedded_files.object).to eq pdf_object
end

it 'has a catalog object with an embedded files reference' do
t = described_class.new
t.embedded_files

pdf_object = "2 0 obj\n<< /Type /Names\n/EmbeddedFiles 3 0 R\n>>\nendobj\n"
expect(t.names.object).to eq pdf_object
end

it 'has an embedded files object with one name reference' do
t = described_class.new
file_name = PDF::Core::LiteralString.new('my_file')

t.add_embedded_file(file_name, t.ref!(Type: :Filespec))

pdf_object = "4 0 obj\n<< /Names [(my_file) 2 0 R]\n>>\nendobj\n"
expect(t.embedded_files.data.size).to eq 1
expect(t.embedded_files.object).to eq pdf_object
end
end