Class: HexaPDF::Type::PageTreeNode

Inherits:
Dictionary show all
Defined in:
lib/hexapdf/type/page_tree_node.rb

Overview

Represents a node in the page tree of the PDF’s document.

The page tree is a tree structure containing page tree nodes for the root and intermediate nodes and page objects for the leaf nodes (see Page). The root node of the page tree is linked via the /Pages entry in the Catalog.

All operations except #add_page on the page tree are rather expensive because page tree nodes and page objects can be mixed. This means that for finding a page at a specific index we have to go through all objects that come before it.

Page indices are zero-based, not one-based. Therefore the first page has an index of 0!

Since the page tree needs a certain structure it is not advised to directly modify page tree nodes. The validation feature can correct most problems but until the page tree is in order the methods may not work correctly!

Newly created pages use the ‘page.default_media_box’ configuration option for the /MediaBox value. If an inherited /Resources dictionary does not exist, an empty one is created for the page.

See: PDF1.7 s7.7.3.2, Page

Constant Summary

Constants included from DictionaryFields

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

Constants inherited from Object

Object::NOT_DUPLICATABLE_CLASSES

Instance Attribute Summary

Attributes inherited from Object

#data, #document, #must_be_indirect

Instance Method Summary collapse

Methods inherited from Dictionary

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

Methods inherited from Object

#<=>, #==, #deep_copy, deep_copy, #document?, #eql?, #gen, #gen=, #hash, #indirect?, #initialize, #inspect, #null?, #oid, #oid=, #type, #validate, #value, #value=

Constructor Details

This class inherits a constructor from HexaPDF::Object

Instance Method Details

#add_page(page = nil) ⇒ Object

Adds the page or a new empty page at the end and returns it.



150
151
152
# File 'lib/hexapdf/type/page_tree_node.rb', line 150

def add_page(page = nil)
  insert_page(-1, page)
end

#delete_page(index) ⇒ Object

Deletes the page at the position specified by the zero-based index and returns it. If an invalid index is specified, nil is returned.

Negative indices count backwards from the end, i.e. -1 is the last page.

Must be called on the root of the page tree, otherwise the /Count entries are not correctly updated!



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/hexapdf/type/page_tree_node.rb', line 161

def delete_page(index)
  index = self[:Count] + index if index < 0
  return nil if index < 0 || index >= self[:Count]

  page = nil
  self[:Count] -= 1
  self[:Kids].each_with_index do |kid, kid_index|
    kid = document.deref(kid)
    if kid.type == :Page && index == 0
      page = self[:Kids].delete_at(kid_index)
      document.delete(page)
      break
    elsif kid.type == :Page
      index -= 1
    elsif index < kid[:Count]
      page = kid.delete_page(index)
      if kid[:Count] == 0
        self[:Kids].delete_at(kid_index)
        document.delete(kid)
      elsif kid[:Count] == 1
        self[:Kids][kid_index] = kid[:Kids][0]
        kid[:Kids][0][:Parent] = self
        document.delete(kid)
      end
      break
    else
      index -= kid[:Count]
    end
  end

  page
end

#each_page(&block) ⇒ Object

:call-seq:

pages.each_page {|page| block }   -> pages
pages.each_page                   -> Enumerator

Iterates over all pages that are beneath this page tree node, from the first to the last page.



200
201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/hexapdf/type/page_tree_node.rb', line 200

def each_page(&block)
  return to_enum(__method__) unless block_given?

  self[:Kids].each do |kid|
    kid = document.deref(kid)
    if kid.type == :Page
      yield(kid)
    else
      kid.each_page(&block)
    end
  end

  self
end

#insert_page(index, page = nil) ⇒ Object

Inserts the page or a new empty page at the zero-based index and returns it.

Negative indices count backwards from the end, i.e. -1 is the last page. When using negative indices, the page will be inserted after that element. So using an index of -1 will insert the page after the last page.

Must be called on the root of the page tree, otherwise the /Count entries are not correctly updated!



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/hexapdf/type/page_tree_node.rb', line 118

def insert_page(index, page = nil)
  page ||= new_page
  index = self[:Count] + index + 1 if index < 0

  if index >= self[:Count]
    self[:Kids] << page
    page[:Parent] = self
    page[:Resources] ||= {}
  else
    self[:Kids].each_with_index do |kid, kid_index|
      kid = document.deref(kid)
      if index == 0
        self[:Kids].insert(kid_index, page)
        page[:Parent] = self
        break
      elsif kid.type == :Page
        index -= 1
      elsif index <= kid[:Count]
        kid.insert_page(index, page)
        break
      else
        index -= kid[:Count]
      end
    end
  end

  self[:Count] += 1

  page
end

#must_be_indirect?Boolean

Returns true since page tree objects must always be indirect.

Returns:



75
76
77
# File 'lib/hexapdf/type/page_tree_node.rb', line 75

def must_be_indirect?
  true
end

#page(index) ⇒ Object

Returns the page for the zero-based index or nil if no such page exists.

Negative indices count backwards from the end, i.e. -1 is the last page.



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/hexapdf/type/page_tree_node.rb', line 90

def page(index)
  index = self[:Count] + index if index < 0
  return nil if index < 0 || index >= self[:Count]

  self[:Kids].each do |kid|
    kid = document.deref(kid)
    if kid.type == :Page
      if index == 0
        return kid
      else
        index -= 1
      end
    elsif index < kid[:Count]
      return kid.page(index)
    else
      index -= kid[:Count]
    end
  end
end

#page_countObject

Returns the number of pages under this page tree.

Note: If this methods is not called on the root object of the page tree, the returned number is not the total number of pages in the document!



83
84
85
# File 'lib/hexapdf/type/page_tree_node.rb', line 83

def page_count
  self[:Count]
end