///|
fn pdf_merge_append_ascii_suffix(
name : @core.PdfBytes,
suffix : String,
) -> @core.PdfBytes {
let suffix_bytes = @ascii.encode(suffix)
let output = Array::make(name.length() + suffix_bytes.length(), b'\x00')
let mut position = 0
for byte in name {
output[position] = byte
position += 1
}
for byte in suffix_bytes {
output[position] = byte
position += 1
}
Bytes::from_array(output)
}
///|
fn pdf_merge_append_name_suffix(
name : @core.PdfName,
suffix : String,
) -> @core.PdfName {
@core.pdf_name_of_bytes(pdf_merge_append_ascii_suffix(name.bytes(), suffix))
}
///|
priv struct PdfMergeDestinationNameMap {
values : @hashmap.HashMap[Bytes, @core.PdfBytes]
}
///|
fn pdf_merge_destination_name_map(
changes : ArrayView[(@core.PdfBytes, @core.PdfBytes)],
) -> PdfMergeDestinationNameMap {
let values : @hashmap.HashMap[Bytes, @core.PdfBytes] = HashMap([])
for change in changes {
let (old_name, new_name) = change
if !values.contains(old_name) {
values[old_name] = new_name
}
}
{ values, }
}
///|
fn PdfMergeDestinationNameMap::changed(
self : PdfMergeDestinationNameMap,
name : @core.PdfBytes,
) -> @core.PdfBytes {
match self.values.get(name) {
Some(new_name) => new_name
None => name
}
}
///|
priv struct PdfMergeDestinationNameLookup {
local_names : PdfMergeDestinationNameMap
global_names : PdfMergeDestinationNameMap
}
///|
fn pdf_merge_destination_name_lookup(
changes : ArrayView[(@core.PdfBytes, @core.PdfBytes)],
all_changes : ArrayView[(@core.PdfBytes, @core.PdfBytes)],
) -> PdfMergeDestinationNameLookup {
{
local_names: pdf_merge_destination_name_map(changes),
global_names: pdf_merge_destination_name_map(all_changes),
}
}
///|
fn PdfMergeDestinationNameLookup::changed(
self : PdfMergeDestinationNameLookup,
name : @core.PdfBytes,
) -> @core.PdfBytes {
let changed = self.local_names.changed(name)
if changed == name {
self.global_names.changed(name)
} else {
changed
}
}
///|
priv struct PdfMergeCatalogDestinationNameMap {
values : @hashmap.HashMap[Bytes, @core.PdfName]
}
///|
fn pdf_merge_catalog_destination_name_map(
changes : ArrayView[(@core.PdfName, @core.PdfName)],
) -> PdfMergeCatalogDestinationNameMap {
let values : @hashmap.HashMap[Bytes, @core.PdfName] = HashMap([])
for change in changes {
let (old_name, new_name) = change
let key = old_name.bytes()
if !values.contains(key) {
values[key] = new_name
}
}
{ values, }
}
///|
fn PdfMergeCatalogDestinationNameMap::changed(
self : PdfMergeCatalogDestinationNameMap,
name : @core.PdfName,
) -> @core.PdfName {
match self.values.get(name.bytes()) {
Some(new_name) => new_name
None => name
}
}
///|
priv struct PdfMergeCatalogDestinationNameLookup {
local_names : PdfMergeCatalogDestinationNameMap
global_names : PdfMergeCatalogDestinationNameMap
}
///|
fn pdf_merge_catalog_destination_name_lookup(
changes : ArrayView[(@core.PdfName, @core.PdfName)],
all_changes : ArrayView[(@core.PdfName, @core.PdfName)],
) -> PdfMergeCatalogDestinationNameLookup {
{
local_names: pdf_merge_catalog_destination_name_map(changes),
global_names: pdf_merge_catalog_destination_name_map(all_changes),
}
}
///|
fn PdfMergeCatalogDestinationNameLookup::changed(
self : PdfMergeCatalogDestinationNameLookup,
name : @core.PdfName,
) -> @core.PdfName {
let changed = self.local_names.changed(name)
if changed == name {
self.global_names.changed(name)
} else {
changed
}
}
///|
fn pdf_merge_destination_name_changes_are_unique(
changes_by_document : ArrayView[Array[(@core.PdfBytes, @core.PdfBytes)]],
) -> Bool {
let seen = pdf_merge_bytes_set()
for changes in changes_by_document {
for change in changes {
let (_, new_name) = change
if seen.contains(new_name) {
return false
}
seen.add(new_name)
}
}
true
}
///|
fn pdf_merge_catalog_destination_name_changes_are_unique(
changes_by_document : ArrayView[Array[(@core.PdfName, @core.PdfName)]],
) -> Bool {
let seen = pdf_merge_name_set()
for changes in changes_by_document {
for change in changes {
let (_, new_name) = change
if seen.contains(new_name) {
return false
}
seen.add(new_name)
}
}
true
}
///|
fn pdf_merge_destination_name_lists(
documents : ArrayView[PdfDocument],
) -> Array[Array[@core.PdfBytes]] raise @core.PdfError {
let output : Array[Array[@core.PdfBytes]] = []
for document in documents {
output.push(
[
for entry in document.pdf_merge_name_tree_entries(pdf_merge_dests_key()) => {
entry.0
}
],
)
}
output
}
///|
fn PdfDocument::pdf_merge_catalog_destination_name_entries(
self : PdfDocument,
) -> Array[@core.PdfName] raise @core.PdfError {
match self.pdf_merge_catalog_entry(pdf_merge_dests_key()) {
Some(PdfDictionary(entries)) => [ for entry in entries => entry.0 ]
_ => []
}
}
///|
fn pdf_merge_catalog_destination_name_lists(
documents : ArrayView[PdfDocument],
) -> Array[Array[@core.PdfName]] raise @core.PdfError {
let output : Array[Array[@core.PdfName]] = []
for document in documents {
output.push(document.pdf_merge_catalog_destination_name_entries())
}
output
}
///|
fn pdf_merge_destination_name_changes(
documents : ArrayView[PdfDocument],
) -> Array[Array[(@core.PdfBytes, @core.PdfBytes)]] raise @core.PdfError {
let names_by_document = pdf_merge_destination_name_lists(documents)
let identity : Array[Array[(@core.PdfBytes, @core.PdfBytes)]] = [
for names in names_by_document => [ for name in names => (name, name) ]
]
if pdf_merge_destination_name_changes_are_unique(identity) {
[
for _ in names_by_document => []
]
} else {
let mut suffix_start = 0
let mut changes : Array[Array[(@core.PdfBytes, @core.PdfBytes)]] = identity
while !pdf_merge_destination_name_changes_are_unique(changes) {
changes = []
for i in 0.. Array[Array[(@core.PdfName, @core.PdfName)]] raise @core.PdfError {
let names_by_document = pdf_merge_catalog_destination_name_lists(documents)
let identity : Array[Array[(@core.PdfName, @core.PdfName)]] = [
for names in names_by_document => [ for name in names => (name, name) ]
]
if pdf_merge_catalog_destination_name_changes_are_unique(identity) {
[
for _ in names_by_document => []
]
} else {
let mut suffix_start = 0
let mut changes : Array[Array[(@core.PdfName, @core.PdfName)]] = identity
while !pdf_merge_catalog_destination_name_changes_are_unique(changes) {
changes = []
for i in 0.. Array[(@core.PdfBytes, @core.PdfBytes)] {
let output : Array[(@core.PdfBytes, @core.PdfBytes)] = []
for document_changes in changes {
for change in document_changes {
output.push(change)
}
}
output
}
///|
fn pdf_merge_all_catalog_destination_name_changes(
changes : ArrayView[Array[(@core.PdfName, @core.PdfName)]],
) -> Array[(@core.PdfName, @core.PdfName)] {
let output : Array[(@core.PdfName, @core.PdfName)] = []
for document_changes in changes {
for change in document_changes {
output.push(change)
}
}
output
}