///|
fn PdfDocument::pdf_font_table_target_font(
self : PdfDocument,
font_name : String,
page_number : Int,
) -> @syntax.PdfObject raise @core.PdfError {
let font = self.font_from_name(font_name, page_number)
let mut selected = font
match font {
PdfDictionary(entries) =>
for entry in entries {
match self.lookup_direct(pdf_text_base_font_key_name, entry.1) {
Some(PdfNameObject(name)) if pdf_util_string_from_name(name) ==
font_name => selected = entry.1
_ => ()
}
}
_ => ()
}
selected
}
///|
fn pdf_font_table_charset(font : PdfFont) -> Array[@core.PdfName]? {
match font {
PdfFontSimple({ fontdescriptor: Some({ charset: Some(charset), .. }), .. }) =>
Some(charset)
_ => None
}
}
///|
fn pdf_font_table_text_bytes(
font : PdfFont,
code : Int,
) -> @core.PdfBytes raise @core.PdfError {
if font.uses_two_byte_codes() {
Bytes::from_array([@core.pdf_byte_of_int(0), @core.pdf_byte_of_int(code)])
} else {
Bytes::from_array([@core.pdf_byte_of_int(code)])
}
}
///|
fn pdf_font_table_strip_name_slash(name : @core.PdfName) -> String {
let text = pdf_util_string_from_name(name) catch {
_ => @ascii.decode_lossy(name.bytes())
}
if text.has_prefix("/") {
text[1:].to_owned()
} else {
text
}
}
///|
fn pdf_font_table_glyphnames_text(
glyphnames : ArrayView[@core.PdfName],
) -> String {
let mut text = ""
for glyphname in glyphnames {
text = text + pdf_font_table_strip_name_slash(glyphname)
}
text
}
///|
fn pdf_font_table_in_charset(
glyphnames : String,
charset : ArrayView[@core.PdfName],
) -> Bool {
for name in charset {
if pdf_font_table_strip_name_slash(name) == glyphnames {
return true
}
}
false
}
///|
fn pdf_font_table_utf8_text(
codepoints : ArrayView[Int],
) -> String raise @core.PdfError {
let bytes = pdf_utf8_of_codepoints(codepoints)
@utf8.decode(bytes) catch {
_ => ""
}
}
///|
fn pdf_font_table_unicode_fields(
codepoints : ArrayView[Int],
) -> (String, String, String) raise @core.PdfError {
match codepoints {
[codepoint] => {
let data = pdf_unicode_data_lookup(codepoint)
let unicode = match data {
Some(data) => data.code_value
None => ""
}
let unicode_name = match data {
Some(data) => data.character_name
None => ""
}
let is_control = match data {
Some(data) => data.general_category == "Cc"
None => false
}
let utf8 = if is_control {
""
} else {
pdf_font_table_utf8_text(codepoints)
}
(unicode, utf8, unicode_name)
}
_ => ("***multiple", pdf_font_table_utf8_text(codepoints), "***multiple")
}
}
///|
fn pdf_font_table_entry(
font : PdfFont,
extractor : PdfTextExtractor,
code : Int,
) -> @font.PdfFontTableEntry? raise @core.PdfError {
let text = pdf_font_table_text_bytes(font, code)
let glyphnames = extractor.glyphnames_of_text(text)
let glyphnames_text = pdf_font_table_glyphnames_text(glyphnames)
if glyphnames_text == ".notdef" {
None
} else {
match pdf_font_table_charset(font) {
Some(charset) if !pdf_font_table_in_charset(glyphnames_text, charset) =>
None
_ => {
let codepoints = extractor.codepoints_of_text(text)
let (unicode, utf8, unicode_name) = pdf_font_table_unicode_fields(
codepoints,
)
Some({ code, unicode, utf8, unicode_name, glyphnames: glyphnames_text, })
}
}
}
}
///|
/// Return cpdf's font encoding table rows for one named page font.
///
/// This is the in-memory counterpart to cpdf's `print_font_table`. Font names
/// use the same page resource path syntax as `font_from_name`, such as `/F1`.
pub fn PdfDocument::font_table(
self : PdfDocument,
font_name : String,
page_number : Int,
) -> Array[@font.PdfFontTableEntry] raise @core.PdfError {
let font_object = self.pdf_font_table_target_font(font_name, page_number)
let font = self.read_font(font_object)
let extractor = font.text_extractor()
let output : Array[@font.PdfFontTableEntry] = []
for code in 0..<256 {
match pdf_font_table_entry(font, extractor, code) {
Some(entry) => output.push(entry)
None => ()
}
}
output
}
///|
/// Compatibility wrapper for `PdfDocument::font_table`.
pub fn pdf_font_table(
document : PdfDocument,
font_name : String,
page_number : Int,
) -> Array[@font.PdfFontTableEntry] raise @core.PdfError {
document.font_table(font_name, page_number)
}
///|
fn pdf_font_write_table_line(
output : Array[Byte],
position : Int,
entry : @font.PdfFontTableEntry,
) -> Int {
let mut current = pdf_font_write_utf8(
output,
position,
entry.code.to_string(),
)
current = pdf_font_write_utf8(output, current, " = U+")
current = pdf_font_write_utf8(output, current, entry.unicode)
current = pdf_font_write_utf8(output, current, " (")
current = pdf_font_write_utf8(output, current, entry.utf8)
current = pdf_font_write_utf8(output, current, " - ")
current = pdf_font_write_utf8(output, current, entry.unicode_name)
current = pdf_font_write_utf8(output, current, ") = ")
current = pdf_font_write_utf8(output, current, entry.glyphnames)
output[current] = 10
current + 1
}
///|
fn pdf_font_table_line_length(entry : @font.PdfFontTableEntry) -> Int {
pdf_font_utf8_length(entry.code.to_string()) +
pdf_font_utf8_length(entry.unicode) +
pdf_font_utf8_length(entry.utf8) +
pdf_font_utf8_length(entry.unicode_name) +
pdf_font_utf8_length(entry.glyphnames) +
15
}
///|
fn pdf_font_table_text_length(
entries : ArrayView[@font.PdfFontTableEntry],
) -> Int {
let mut length = 0
for entry in entries {
length += pdf_font_table_line_length(entry)
}
length
}
///|
/// Render cpdf's plain-text font encoding table for one named page font.
pub fn PdfDocument::font_table_text(
self : PdfDocument,
font_name : String,
page_number : Int,
) -> @core.PdfBytes raise @core.PdfError {
let entries = self.font_table(font_name, page_number)
let output = Array::make(pdf_font_table_text_length(entries), b'\x00')
let mut position = 0
for entry in entries {
position = pdf_font_write_table_line(output, position, entry)
}
Bytes::from_array(output)
}
///|
/// Compatibility wrapper for `PdfDocument::font_table_text`.
pub fn pdf_font_table_text(
document : PdfDocument,
font_name : String,
page_number : Int,
) -> @core.PdfBytes raise @core.PdfError {
document.font_table_text(font_name, page_number)
}
///|
/// Return the bytes cpdf's `print_font_table` would print.
pub fn PdfDocument::print_font_table(
self : PdfDocument,
font_name : String,
page_number : Int,
) -> @core.PdfBytes raise @core.PdfError {
self.font_table_text(font_name, page_number)
}
///|
/// Compatibility wrapper matching cpdffont's `print_font_table`.
pub fn pdf_print_font_table(
document : PdfDocument,
font_name : String,
page_number : Int,
) -> @core.PdfBytes raise @core.PdfError {
document.print_font_table(font_name, page_number)
}