///|
let pdf_metadata_pdfaid_wrong_iso_namespace : String = "http://www.aiim.org/pdfa/ns/id"
///|
let pdf_metadata_pdfaid_wrong_acrobat_namespace : String = "http://www.aiim.org/pdfa/ns/id.html"
///|
fn pdf_metadata_decode_pdf_string(value : BytesView) -> String? {
let text = @utf8.decode(value) catch { _ => return None }
Some(text)
}
///|
fn PdfDocument::pdf_metadata_fallback_pdfx(self : PdfDocument) -> String? {
match self.lookup_direct(pdf_metadata_info(), self.trailer_dict()) {
Some(info) =>
match self.lookup_direct(pdf_metadata_name("/GTS_PDFXVersion"), info) {
Some(PdfString(value)) => pdf_metadata_decode_pdf_string(value)
_ => None
}
None => None
}
}
///|
fn pdf_metadata_reverse_strings(values : ArrayView[String]) -> Array[String] {
let output : Array[String] = []
for offset in 0.. Unit {
match value {
Some(value) if value != "" => values.push(value)
_ => ()
}
}
///|
fn pdf_metadata_namespace_fallback_prefix(xml_uri : String) -> String {
if xml_uri == @metadata.pdf_metadata_adobe_namespace {
"pdf"
} else if xml_uri == @metadata.pdf_metadata_xmp_namespace {
"xmp"
} else if xml_uri == @metadata.pdf_metadata_dc_namespace {
"dc"
} else if xml_uri == @metadata.pdf_metadata_pdfuaid_namespace {
"pdfuaid"
} else if xml_uri == @metadata.pdf_metadata_pdfe_namespace {
"pdfe"
} else if xml_uri == @metadata.pdf_metadata_pdfaid_namespace {
"pdfaid"
} else if xml_uri == @metadata.pdf_metadata_pdfxid_namespace {
"pdfxid"
} else if xml_uri == @metadata.pdf_metadata_pdfvtid_namespace {
"pdfvtid"
} else {
""
}
}
///|
fn pdf_metadata_name_with_slash(name : @core.PdfName) -> String? {
let text = @ascii.decode(name.bytes()) catch { _ => return None }
Some(text)
}
///|
fn pdf_metadata_xmp_info_fields(
key : @core.PdfName,
) -> Array[(String, String)]? {
match pdf_metadata_name_with_slash(key) {
Some("/Title") =>
Some([
(@metadata.pdf_metadata_adobe_namespace, "Title"),
(@metadata.pdf_metadata_dc_namespace, "title"),
])
Some("/Author") =>
Some([
(@metadata.pdf_metadata_adobe_namespace, "Author"),
(@metadata.pdf_metadata_dc_namespace, "creator"),
])
Some("/Subject") =>
Some([
(@metadata.pdf_metadata_adobe_namespace, "Subject"),
(@metadata.pdf_metadata_dc_namespace, "subject"),
])
Some("/Keywords") =>
Some([(@metadata.pdf_metadata_adobe_namespace, "Keywords")])
Some("/Creator") =>
Some([
(@metadata.pdf_metadata_adobe_namespace, "Creator"),
(@metadata.pdf_metadata_xmp_namespace, "CreatorTool"),
])
Some("/Producer") =>
Some([(@metadata.pdf_metadata_adobe_namespace, "Producer")])
Some("/CreationDate") =>
Some([
(@metadata.pdf_metadata_adobe_namespace, "CreationDate"),
(@metadata.pdf_metadata_xmp_namespace, "CreateDate"),
])
Some("/ModDate") =>
Some([
(@metadata.pdf_metadata_adobe_namespace, "ModificationDate"),
(@metadata.pdf_metadata_xmp_namespace, "ModifyDate"),
])
_ => None
}
}
///|
/// Return XMP metadata corresponding to a legacy `/Info` key.
pub fn PdfDocument::xmp_info(self : PdfDocument, key : @core.PdfName) -> String {
let fields = match pdf_metadata_xmp_info_fields(key) {
Some(fields) => fields
None => return ""
}
let metadata = try self.metadata() catch {
_ => return ""
} noraise {
Some(metadata) => metadata
None => return ""
}
for field in fields {
let value = pdf_metadata_get_xmp_data(
metadata,
field.0,
pdf_metadata_namespace_fallback_prefix(field.0),
field.1,
)
match value {
Some(value) if value != "" => break value
_ => ()
}
} nobreak {
""
}
}
///|
/// Return XMP metadata corresponding to a cpdf-style slash-prefixed string key.
pub fn PdfDocument::xmp_info_string(self : PdfDocument, key : String) -> String {
self.xmp_info(pdf_metadata_source_key_name(key))
}
///|
/// Determine PDF/A, PDF/E, PDF/UA, PDF/VT, and PDF/X subformat markers.
///
/// This ports cpdf's in-memory subformat detection. It recognizes simple XMP
/// element and attribute forms and falls back to `/Info /GTS_PDFXVersion`.
pub fn PdfDocument::determine_subformats(
self : PdfDocument,
) -> Array[String] raise @core.PdfError {
let formats : Array[String] = []
match self.metadata() {
None =>
pdf_metadata_push_if_some(formats, self.pdf_metadata_fallback_pdfx())
Some(metadata) => {
pdf_metadata_push_if_some(
formats,
pdf_metadata_get_xmp_data(
metadata, @metadata.pdf_metadata_pdfe_namespace, "pdfe", "ISO_PDFEVersion",
),
)
match
pdf_metadata_get_xmp_data(
metadata, @metadata.pdf_metadata_pdfuaid_namespace, "pdfuaid", "part",
) {
Some(part) if part != "" => formats.push("PDF/UA-" + part)
_ => ()
}
let pdfa_part = match
pdf_metadata_get_xmp_data(
metadata, @metadata.pdf_metadata_pdfaid_namespace, "pdfaid", "part",
) {
Some(part) => Some(part)
None =>
match
pdf_metadata_get_xmp_data(
metadata, pdf_metadata_pdfaid_wrong_acrobat_namespace, "pdfaid", "part",
) {
Some(part) => Some(part)
None =>
pdf_metadata_get_xmp_data(
metadata, pdf_metadata_pdfaid_wrong_iso_namespace, "pdfaid", "part",
)
}
}
match pdfa_part {
Some(part) if part != "" => {
let conformance = match
pdf_metadata_get_xmp_data(
metadata, @metadata.pdf_metadata_pdfaid_namespace, "pdfaid", "conformance",
) {
Some(value) => value.to_lower()
None =>
match
pdf_metadata_get_xmp_data(
metadata, pdf_metadata_pdfaid_wrong_acrobat_namespace, "pdfaid",
"conformance",
) {
Some(value) => value.to_lower()
None =>
match
pdf_metadata_get_xmp_data(
metadata, pdf_metadata_pdfaid_wrong_iso_namespace, "pdfaid",
"conformance",
) {
Some(value) => value.to_lower()
None => ""
}
}
}
formats.push("PDF/A-" + part + conformance)
}
_ => ()
}
match
pdf_metadata_get_xmp_data(
metadata, @metadata.pdf_metadata_pdfxid_namespace, "pdfxid", "GTS_PDFXVersion",
) {
Some(value) if value != "" => formats.push(value)
_ =>
pdf_metadata_push_if_some(formats, self.pdf_metadata_fallback_pdfx())
}
pdf_metadata_push_if_some(
formats,
pdf_metadata_get_xmp_data(
metadata, @metadata.pdf_metadata_pdfvtid_namespace, "pdfvtid", "GTS_PDFVTVersion",
),
)
}
}
pdf_metadata_reverse_strings(formats)
}