///|
fn pdf_chop_name(text : String) -> PdfName {
pdf_name_of_bytes(@ascii.encode(text))
}
///|
let pdf_chop_cropbox_key_name : PdfName = pdf_chop_name("/CropBox")
///|
fn pdf_chop_cropbox_key() -> PdfName {
pdf_chop_cropbox_key_name
}
///|
let pdf_chop_bleedbox_key_name : PdfName = pdf_chop_name("/BleedBox")
///|
fn pdf_chop_bleedbox_key() -> PdfName {
pdf_chop_bleedbox_key_name
}
///|
let pdf_chop_trimbox_key_name : PdfName = pdf_chop_name("/TrimBox")
///|
fn pdf_chop_trimbox_key() -> PdfName {
pdf_chop_trimbox_key_name
}
///|
let pdf_chop_artbox_key_name : PdfName = pdf_chop_name("/ArtBox")
///|
fn pdf_chop_artbox_key() -> PdfName {
pdf_chop_artbox_key_name
}
///|
let pdf_chop_annots_key_name : PdfName = pdf_chop_name("/Annots")
///|
fn pdf_chop_annots_key() -> PdfName {
pdf_chop_annots_key_name
}
///|
fn pdf_chop_rectangle_object(
min_x : Double,
min_y : Double,
max_x : Double,
max_y : Double,
) -> PdfObject {
PdfArray([PdfReal(min_x), PdfReal(min_y), PdfReal(max_x), PdfReal(max_y)])
}
///|
fn pdf_chop_box(
document : PdfDocument,
page : PdfPage,
) -> PdfRectangle raise PdfError {
match document.lookup_direct(pdf_chop_cropbox_key(), page.rest) {
Some(cropbox) => document.parse_rectangle(cropbox)
None => document.parse_rectangle(page.mediabox)
}
}
///|
fn pdf_chop_erase_boxes(rest : PdfObject) -> PdfObject raise PdfError {
rest
.remove_dict_entry(pdf_chop_cropbox_key())
.remove_dict_entry(pdf_chop_bleedbox_key())
.remove_dict_entry(pdf_chop_trimbox_key())
.remove_dict_entry(pdf_chop_artbox_key())
.remove_dict_entry(pdf_chop_annots_key())
}
///|
fn pdf_chop_page_with_box(
page : PdfPage,
min_x : Double,
min_y : Double,
max_x : Double,
max_y : Double,
) -> PdfPage raise PdfError {
{
..page,
mediabox: pdf_chop_rectangle_object(min_x, min_y, max_x, max_y),
rest: pdf_chop_erase_boxes(page.rest),
}
}
///|
fn pdf_chop_index_order(count : Int, reverse : Bool) -> Array[Int] {
[
for index in 0.. if reverse { count - index - 1 } else { index }
]
}
///|
fn pdf_chop_grid_pages(
page : PdfPage,
bounds : PdfRectangle,
x : Int,
y : Int,
columns : Bool,
btt : Bool,
rtl : Bool,
) -> Array[PdfPage] raise PdfError {
let width = (bounds.max_x - bounds.min_x) / x.to_double()
let height = (bounds.max_y - bounds.min_y) / y.to_double()
let pages : Array[PdfPage] = []
let x_order = pdf_chop_index_order(x, rtl)
let y_order = pdf_chop_index_order(y, !btt)
if columns {
for tx in x_order {
for ty in y_order {
let min_x = bounds.min_x + width * tx.to_double()
let min_y = bounds.min_y + height * ty.to_double()
pages.push(
pdf_chop_page_with_box(
page,
min_x,
min_y,
min_x + width,
min_y + height,
),
)
}
}
} else {
for ty in y_order {
for tx in x_order {
let min_x = bounds.min_x + width * tx.to_double()
let min_y = bounds.min_y + height * ty.to_double()
pages.push(
pdf_chop_page_with_box(
page,
min_x,
min_y,
min_x + width,
min_y + height,
),
)
}
}
}
pages
}
///|
fn pdf_chop_pair_pages(
first : PdfPage,
second : PdfPage,
columns : Bool,
) -> Array[PdfPage] {
if columns {
[second, first]
} else {
[first, second]
}
}
///|
fn pdf_chop_page_boxes(
document : PdfDocument,
page : PdfPage,
line : Double,
x : Int,
y : Int,
columns : Bool,
btt : Bool,
rtl : Bool,
) -> Array[PdfPage] raise PdfError {
let bounds = pdf_chop_box(document, page)
if x == 0 {
let top = pdf_chop_page_with_box(
page,
bounds.min_x,
line,
bounds.max_x,
bounds.max_y,
)
let bottom = pdf_chop_page_with_box(
page,
bounds.min_x,
bounds.min_y,
bounds.max_x,
line,
)
pdf_chop_pair_pages(top, bottom, columns)
} else if y == 0 {
let left = pdf_chop_page_with_box(
page,
bounds.min_x,
bounds.min_y,
line,
bounds.max_y,
)
let right = pdf_chop_page_with_box(
page,
line,
bounds.min_y,
bounds.max_x,
bounds.max_y,
)
pdf_chop_pair_pages(left, right, columns)
} else {
pdf_chop_grid_pages(page, bounds, x, y, columns, btt, rtl)
}
}
///|
fn pdf_chop_contains_page(
page_numbers : ArrayView[Int],
page_number : Int,
) -> Bool {
for selected in page_numbers {
if selected == page_number {
break true
}
} nobreak {
false
}
}
///|
fn pdf_chop_validate_page_numbers(
page_numbers : ArrayView[Int],
end_page : Int,
context : String,
) -> Unit raise PdfError {
for page_number in page_numbers {
if page_number < 1 || page_number > end_page {
raise BadPageSpecification(
context + ": range contains pages not present in pdf",
)
}
}
}
///|
fn pdf_chop_validate_grid(x : Int, y : Int) -> Unit raise PdfError {
if x <= 0 || y <= 0 {
raise BadNumberArgument("chop: x and y must be positive")
}
}
///|
fn pdf_chop_change_table(
original_count : Int,
page_numbers : ArrayView[Int],
pieces_per_selected_page : Int,
) -> Array[(Int, Int)] {
let changes : Array[(Int, Int)] = []
let mut next_page = 1
for old_page in 1..<=original_count {
if pdf_chop_contains_page(page_numbers, old_page) {
for new_page in next_page..<(next_page + pieces_per_selected_page) {
changes.push((old_page, new_page))
}
next_page += pieces_per_selected_page
} else {
changes.push((old_page, next_page))
next_page += 1
}
}
changes
}
///|
fn PdfDocument::pdf_chop_inner(
self : PdfDocument,
line : Double,
x : Int,
y : Int,
columns : Bool,
btt : Bool,
rtl : Bool,
page_numbers : ArrayView[Int],
context : String,
) -> PdfDocument raise PdfError {
let end_page = self.endpage()
pdf_chop_validate_page_numbers(page_numbers, end_page, context)
let pages = self.pages_of_pagetree()
let output : Array[PdfPage] = []
for index in 0.. PdfDocument raise PdfError {
pdf_chop_validate_grid(x, y)
self.pdf_chop_inner(0.0, x, y, columns, btt, rtl, page_numbers, "chop")
}
///|
/// Chop selected pages horizontally or vertically at `line`.
pub fn PdfDocument::chop_hv(
self : PdfDocument,
is_h : Bool,
line : Double,
columns : Bool,
page_numbers : ArrayView[Int],
) -> PdfDocument raise PdfError {
self.pdf_chop_inner(
line,
if is_h {
0
} else {
1
},
if is_h {
1
} else {
0
},
columns,
false,
false,
page_numbers,
if is_h {
"chop_h"
} else {
"chop_v"
},
)
}
///|
/// Compatibility wrapper for `PdfDocument::chop`.
pub fn pdf_chop(
document : PdfDocument,
x : Int,
y : Int,
columns : Bool,
btt : Bool,
rtl : Bool,
page_numbers : ArrayView[Int],
) -> PdfDocument raise PdfError {
document.chop(x, y, columns, btt, rtl, page_numbers)
}
///|
/// Compatibility wrapper for `PdfDocument::chop_hv`.
pub fn pdf_chop_hv(
document : PdfDocument,
is_h : Bool,
line : Double,
columns : Bool,
page_numbers : ArrayView[Int],
) -> PdfDocument raise PdfError {
document.chop_hv(is_h, line, columns, page_numbers)
}