///|
fn PdfDocument::pdf_text_cid_string_entry(
self : PdfDocument,
dictionary : @syntax.PdfObject,
key : @core.PdfName,
error : @core.PdfError,
) -> @core.PdfBytes raise @core.PdfError {
match self.lookup_direct(key, dictionary) {
Some(PdfString(bytes)) => bytes
_ => raise error
}
}
///|
/// Read a CID-system-info dictionary.
///
/// Registry and ordering are returned as byte strings, matching PDF string
/// semantics. Missing or malformed required fields raise `@core.PdfError`.
pub fn PdfDocument::read_cid_system_info(
self : PdfDocument,
dictionary : @syntax.PdfObject,
) -> PdfCIDSystemInfo raise @core.PdfError {
{
registry: self.pdf_text_cid_string_entry(
dictionary,
pdf_text_registry_key_name,
CIDRegistryExpected,
),
ordering: self.pdf_text_cid_string_entry(
dictionary,
pdf_text_ordering_key_name,
CIDOrderingExpected,
),
supplement: match
self.lookup_direct(pdf_text_supplement_key_name, dictionary) {
Some(PdfInteger(value)) => value
_ => raise CIDSupplementExpected
},
}
}
///|
fn PdfDocument::pdf_text_cid_number(
self : PdfDocument,
value : @syntax.PdfObject,
error : @core.PdfError,
) -> Double raise @core.PdfError {
self.get_number(value) catch {
_ => raise error
}
}
///|
fn PdfDocument::pdf_text_read_cid_widths(
self : PdfDocument,
values : ArrayView[@syntax.PdfObject],
) -> Array[(Int, Double)] raise @core.PdfError {
let output : Array[(Int, Double)] = Array(capacity=values.length())
let mut index = 0
while index < values.length() {
match self.direct(values[index]) {
PdfInteger(first_code) => {
guard index + 1 < values.length() else { raise CIDWidthsExpected }
match self.direct(values[index + 1]) {
PdfArray(widths) => {
for offset in 0.. {
guard index + 2 < values.length() && last_code >= first_code else {
raise CIDWidthsExpected
}
let width = self.pdf_text_cid_number(
values[index + 2],
CIDWidthsExpected,
)
for code in first_code..<=last_code {
output.push((code, width))
}
index += 3
}
_ => raise CIDWidthsExpected
}
}
_ => raise CIDWidthsExpected
}
}
output
}
///|
fn PdfDocument::pdf_text_read_cid_widths2(
self : PdfDocument,
values : ArrayView[@syntax.PdfObject],
) -> Array[(Int, PdfCIDVerticalWidth)] raise @core.PdfError {
let output : Array[(Int, PdfCIDVerticalWidth)] = Array(
capacity=values.length(),
)
let mut index = 0
while index < values.length() {
match self.direct(values[index]) {
PdfInteger(first_code) => {
guard index + 1 < values.length() else { raise CIDWidths2Expected }
match self.direct(values[index + 1]) {
PdfArray(widths) => {
guard widths.length() % 3 == 0 else { raise CIDWidths2Expected }
let mut code = first_code
let mut width_index = 0
while width_index < widths.length() {
output.push(
(
code,
{
width: self.pdf_text_cid_number(
widths[width_index],
CIDWidths2Expected,
),
vx: self.pdf_text_cid_number(
widths[width_index + 1],
CIDWidths2Expected,
),
vy: self.pdf_text_cid_number(
widths[width_index + 2],
CIDWidths2Expected,
),
},
),
)
code += 1
width_index += 3
}
index += 2
}
PdfInteger(last_code) => {
guard index + 4 < values.length() && last_code >= first_code else {
raise CIDWidths2Expected
}
let width = PdfCIDVerticalWidth::{
width: self.pdf_text_cid_number(
values[index + 2],
CIDWidths2Expected,
),
vx: self.pdf_text_cid_number(
values[index + 3],
CIDWidths2Expected,
),
vy: self.pdf_text_cid_number(
values[index + 4],
CIDWidths2Expected,
),
}
for code in first_code..<=last_code {
output.push((code, width))
}
index += 5
}
_ => raise CIDWidths2Expected
}
}
_ => raise CIDWidths2Expected
}
}
output
}
///|
fn PdfDocument::pdf_text_cid_widths(
self : PdfDocument,
dictionary : @syntax.PdfObject,
) -> Array[(Int, Double)] raise @core.PdfError {
match self.lookup_direct(pdf_text_w_key_name, dictionary) {
Some(PdfArray(values)) => self.pdf_text_read_cid_widths(values)
_ => []
}
}
///|
fn PdfDocument::pdf_text_cid_widths2(
self : PdfDocument,
dictionary : @syntax.PdfObject,
) -> Array[(Int, PdfCIDVerticalWidth)] raise @core.PdfError {
match self.lookup_direct(pdf_text_w2_key_name, dictionary) {
Some(PdfArray(values)) => self.pdf_text_read_cid_widths2(values)
_ => []
}
}
///|
fn PdfDocument::pdf_text_cid_default_width(
self : PdfDocument,
dictionary : @syntax.PdfObject,
) -> Double raise @core.PdfError {
match self.lookup_direct(pdf_text_dw_key_name, dictionary) {
Some(value) => self.pdf_text_cid_number(value, CIDWidthsExpected)
None => 1000.0
}
}
///|
fn PdfDocument::pdf_text_cid_default_width2(
self : PdfDocument,
dictionary : @syntax.PdfObject,
) -> Array[Double] raise @core.PdfError {
match self.lookup_direct(pdf_text_dw2_key_name, dictionary) {
Some(PdfArray(values)) => {
let output : Array[Double] = Array(capacity=values.length())
for value in values {
output.push(self.pdf_text_cid_number(value, CIDWidths2Expected))
}
output
}
_ => [880.0, -1000.0]
}
}
///|
fn PdfDocument::pdf_text_read_descendant(
self : PdfDocument,
dictionary : @syntax.PdfObject,
) -> PdfCompositeCIDFont raise @core.PdfError {
let cid_system_info = match
self.lookup_direct(pdf_text_cid_system_info_key_name, dictionary) {
Some(system_info) => self.read_cid_system_info(system_info)
None => raise CIDSystemInfoExpected
}
let cid_basefont = match
self.lookup_direct(pdf_text_base_font_key_name, dictionary) {
Some(PdfNameObject(name)) => name
_ => raise CIDBaseFontExpected
}
let cid_fontdescriptor = match self.read_font_descriptor(dictionary) {
Some(fontdescriptor) => fontdescriptor
None => raise CIDFontDescriptorExpected
}
{
cid_system_info,
cid_basefont,
cid_fontdescriptor,
cid_widths: self.pdf_text_cid_widths(dictionary),
cid_widths2: self.pdf_text_cid_widths2(dictionary),
cid_default_width: self.pdf_text_cid_default_width(dictionary),
cid_default_width2: self.pdf_text_cid_default_width2(dictionary),
}
}
///|
fn PdfDocument::pdf_text_read_cmap_encoding(
self : PdfDocument,
font : @syntax.PdfObject,
) -> PdfCMapEncoding raise @core.PdfError {
match self.lookup_direct(pdf_text_encoding_key_name, font) {
Some(PdfNameObject(name)) => PdfPredefinedCMap(name)
Some(PdfStreamObject(_)) =>
match pdf_text_find_immediate_indirect(font, pdf_text_encoding_key_name) {
Some(number) =>
try self.parse_cmap(PdfIndirect(number)) catch {
_ => PdfCMap(number)
} noraise {
parsed => PdfExternalCMap(number, parsed)
}
None => raise CMapEncodingExpected
}
_ => raise CMapEncodingExpected
}
}
///|
/// Parse a Type 0 font dictionary into a CID-keyed font.
///
/// This reads the descendant CIDFont, width data, descriptor, base font, and
/// CMap encoding. External CMap streams are parsed when possible while still
/// preserving the referenced stream object number.
pub fn PdfDocument::read_cidkeyed_font(
self : PdfDocument,
font : @syntax.PdfObject,
) -> PdfCIDKeyedFont raise @core.PdfError {
let basefont = match self.lookup_direct(pdf_text_base_font_key_name, font) {
Some(PdfNameObject(name)) => name
_ => raise BaseFontExpected
}
let composite = match
self.lookup_direct(pdf_text_descendant_fonts_key_name, font) {
Some(PdfArray([descendant])) =>
self.pdf_text_read_descendant(self.direct(descendant))
_ => raise DescendantFontExpected
}
{ basefont, composite, encoding: self.pdf_text_read_cmap_encoding(font), }
}