///|
fn check_object_contains_renumbering(
changes : Map[Int, Int],
obj : PdfObject,
) -> Bool {
match obj {
Indirect(i) => changes.get(i) is Some(_)
Array(values) =>
values.any(v => check_object_contains_renumbering(changes, v))
Dictionary(entries) =>
entries.any(pair => check_object_contains_renumbering(changes, pair.1))
Stream(r) => {
let (dict, _) = r.val
check_object_contains_renumbering(changes, dict)
}
_ => false
}
}
///|
/// Calculate the change table required to renumber objects 1..n.
pub fn Pdf::changes(self : Pdf) -> Map[Int, Int] {
let keys = self.objnumbers()
let table : Map[Int, Int] = Map::new(capacity=keys.length())
let mut num = 1
for key in keys {
table.set(key, num)
num = num + 1
}
table
}
///|
/// Renumber a PDF's objects using a change table.
pub fn Pdf::renumber(
self : Pdf,
change_table : Map[Int, Int],
preserve_order? : Bool = false,
) -> Pdf {
let root = match change_table.get(self.root) {
Some(value) => value
None => self.root
}
let trailerdict = if check_object_contains_renumbering(
change_table,
self.trailerdict,
) {
self.renumber_object_parsed(change_table, self.trailerdict, preserve_order~)
} else {
self.trailerdict
}
let entries = self.objects.objects.to_array()
entries.sort_by((a, b) => a.0 - b.0)
let objects : PdfObjMap = Map::new(capacity=entries.length())
let mut max_obj_num = 0
for entry in entries {
let old_num = entry.0
let new_num = match change_table.get(old_num) {
Some(value) => value
None => old_num
}
let obj = self.lookup_obj(old_num)
let updated = if check_object_contains_renumbering(change_table, obj) {
self.renumber_object_parsed(change_table, obj, preserve_order~)
} else {
obj
}
objects.set(new_num, ({ val: ObjectData::Parsed(updated) }, 0))
if new_num > max_obj_num {
max_obj_num = new_num
}
}
let object_stream_ids = Map::new(
capacity=self.objects.object_stream_ids.length(),
)
for key, value in self.objects.object_stream_ids {
match change_table.get(key) {
Some(new_key) => object_stream_ids.set(new_key, value)
None => ()
}
}
{
major: self.major,
minor: self.minor,
root,
objects: {
max_obj_num,
parse: self.objects.parse,
objects,
object_stream_ids,
},
trailerdict,
was_linearized: self.was_linearized,
saved_encryption: self.saved_encryption,
}
}
///|
/// Renumber a list of PDFs so their object numbers are mutually exclusive.
pub fn renumber_pdfs(pdfs : Array[Pdf]) -> Array[Pdf] {
let out = Array::new(capacity=pdfs.length())
let mut base = 1
for pdf in pdfs {
let keys = pdf.objnumbers()
let changes : Map[Int, Int] = Map::new(capacity=keys.length())
let mut i = 0
for key in keys {
changes.set(key, base + i)
i = i + 1
}
base = base + keys.length()
out.push(pdf.renumber(changes))
}
out
}