///|
fn pdf_page_reference_numbers_inner(
pdf : PdfDocument,
pages_node : @syntax.PdfObject,
node_number : Int,
depth : Int,
) -> Array[Int] raise @core.PdfError {
if depth > 10000 {
raise PageTreeExpected
}
match pdf.lookup_direct(pdf_page_type_key(), pages_node) {
Some(PdfNameObject(name)) if name == pdf_page_type_page() => [node_number]
_ =>
match pdf.lookup_direct(pdf_page_kids_key(), pages_node) {
Some(PdfArray(kids)) => {
let output : Array[Int] = []
for kid in kids {
match kid {
PdfIndirect(number) => {
let child = pdf.direct(kid)
if child != PdfNull {
for
page_number in pdf_page_reference_numbers_inner(
pdf,
child,
number,
depth + 1,
) {
output.push(page_number)
}
}
}
_ => ()
}
}
output
}
_ => [node_number]
}
}
}
///|
fn PdfDocument::pdf_pages_of_pagetree_quick_node(
self : PdfDocument,
node : @syntax.PdfObject,
depth : Int,
) -> Int raise @core.PdfError {
if depth > 10000 {
raise PageTreeExpected
}
if node == PdfNull {
0
} else {
match self.lookup_direct(pdf_page_type_key(), node) {
Some(PdfNameObject(name)) if name != pdf_page_type_pages() => 1
_ =>
match self.lookup_direct(pdf_page_kids_key(), node) {
Some(PdfArray(kids)) => {
let mut count = 0
for kid in kids {
match kid {
PdfIndirect(number) => {
let child = self.lookup_object_or_null(number)
if child == PdfNull {
raise PageTreeExpected
}
count += self.pdf_pages_of_pagetree_quick_node(
child,
depth + 1,
)
}
PdfDictionary(_) =>
count += self.pdf_pages_of_pagetree_quick_node(kid, depth + 1)
_ => raise PageTreeExpected
}
}
count
}
_ => raise PageTreeExpected
}
}
}
}
///|
fn pdf_page_root_pages_node(
pdf : PdfDocument,
) -> @syntax.PdfObject raise @core.PdfError {
let root = match pdf.pdf_page_active_catalog() {
Some((catalog, _)) => catalog
None => raise RootExpected
}
match pdf.lookup_direct(pdf_page_pages_key(), root) {
Some(pages) => pages
None => raise PageTreeExpected
}
}
///|
/// Return page object numbers in page-tree order.
pub fn PdfDocument::page_reference_numbers(
self : PdfDocument,
) -> Array[Int] raise @core.PdfError {
pdf_page_reference_numbers_inner(self, pdf_page_root_pages_node(self), -1, 0)
}
///|
/// Compatibility wrapper for `PdfDocument::page_reference_numbers`.
pub fn pdf_page_reference_numbers(
document : PdfDocument,
) -> Array[Int] raise @core.PdfError {
document.page_reference_numbers()
}
///|
/// Count pages by walking the page tree without materializing `@page.PdfPage` records.
pub fn PdfDocument::pages_of_pagetree_quick(
self : PdfDocument,
) -> Int raise @core.PdfError {
self.pdf_pages_of_pagetree_quick_node(pdf_page_root_pages_node(self), 0)
}
///|
/// Return the object number for a 1-based page number.
///
/// Out-of-range page numbers return `None`.
pub fn PdfDocument::page_object_number(
self : PdfDocument,
page_number : Int,
) -> Int? raise @core.PdfError {
let references = self.page_reference_numbers()
if page_number < 1 || page_number > references.length() {
None
} else {
Some(references[page_number - 1])
}
}
///|
/// Compatibility wrapper for `PdfDocument::page_object_number`.
pub fn pdf_page_object_number(
document : PdfDocument,
page_number : Int,
) -> Int? raise @core.PdfError {
document.page_object_number(page_number)
}
///|
/// Resolve a destination target to a 1-based page number.
pub fn PdfDocument::page_number_of_target(
self : PdfDocument,
destination : @destination.PdfDestination,
) -> Int raise @core.PdfError {
self.pdf_destination_page_number(destination, self.page_reference_numbers())
}
///|
/// Compatibility wrapper for `PdfDocument::page_number_of_target`.
pub fn pdf_pagenumber_of_target(
document : PdfDocument,
destination : @destination.PdfDestination,
) -> Int raise @core.PdfError {
document.page_number_of_target(destination)
}
///|
/// Build a fit destination for a 1-based page number.
///
/// Out-of-range page numbers return `DestNull`.
pub fn PdfDocument::target_of_page_number(
self : PdfDocument,
page_number : Int,
) -> @destination.PdfDestination raise @core.PdfError {
match self.page_object_number(page_number) {
Some(object_number) => DestFit(TargetPageObject(object_number))
None => DestNull
}
}
///|
/// Compatibility wrapper for `PdfDocument::target_of_page_number`.
pub fn pdf_target_of_pagenumber(
document : PdfDocument,
page_number : Int,
) -> @destination.PdfDestination raise @core.PdfError {
document.target_of_page_number(page_number)
}
///|
/// Return the number of pages by walking the page tree.
pub fn PdfDocument::endpage(self : PdfDocument) -> Int raise @core.PdfError {
self.pages_of_pagetree_quick()
}
///|
/// Compatibility wrapper for `PdfDocument::endpage`.
pub fn pdf_endpage(document : PdfDocument) -> Int raise @core.PdfError {
document.endpage()
}
///|
/// Return the root page-tree `/Count` value without validating child pages.
///
/// Missing or malformed counts return `0`.
pub fn PdfDocument::endpage_fast(
self : PdfDocument,
) -> Int raise @core.PdfError {
match
self.lookup_direct(pdf_page_count_key(), pdf_page_root_pages_node(self)) {
Some(PdfInteger(count)) => count
_ => 0
}
}
///|
/// Compatibility wrapper for `PdfDocument::endpage_fast`.
pub fn pdf_endpage_fast(document : PdfDocument) -> Int raise @core.PdfError {
document.endpage_fast()
}