///|
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
}
let output : Array[Int] = []
pdf.pdf_page_tree_walk(
pages_node,
node_number,
depth,
(),
(node, number, _) => {
match pdf.lookup_direct(pdf_page_type_key(), node) {
Some(PdfNameObject(name)) if name == pdf_page_type_page() => {
output.push(number)
None
}
_ =>
match pdf.lookup_direct(pdf_page_kids_key(), node) {
Some(PdfArray(kids)) =>
Some((pdf_page_tree_kids_number(node), kids, ()))
_ => {
output.push(number)
None
}
}
}
},
// only kids held by reference that resolve to something
kid => {
match kid {
PdfIndirect(number) => {
let child = pdf.direct(kid)
if child != PdfNull {
Some((child, number))
} else {
None
}
}
_ => None
}
},
)
output
}
///|
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 {
return 0
}
let mut count = 0
self.pdf_page_tree_walk(
node,
-1,
depth,
(),
(node, _, _) => {
match self.lookup_direct(pdf_page_type_key(), node) {
Some(PdfNameObject(name)) if name != pdf_page_type_pages() => {
count += 1
None
}
_ =>
match self.lookup_direct(pdf_page_kids_key(), node) {
Some(PdfArray(kids)) =>
Some((pdf_page_tree_kids_number(node), kids, ()))
_ => raise PageTreeExpected
}
}
},
kid => {
match kid {
PdfIndirect(number) => {
let child = self.lookup_object_or_null(number)
if child == PdfNull {
raise PageTreeExpected
}
Some((child, number))
}
PdfDictionary(_) => Some((kid, -1))
_ => raise PageTreeExpected
}
},
)
count
}
///|
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()
}