1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use type0::Type0Font;
use crate::{error::PdfResult, objects::Dictionary, pdf_enum, Resolve};
use self::{
descriptor::FontDescriptor,
true_type::TrueTypeFont,
type1::{MmType1Font, Type1Font},
type3::Type3Font,
};
mod cid;
mod cid_font_type0;
mod cid_font_type2;
mod descriptor;
mod embedded;
mod encoding;
mod true_type;
mod type0;
mod type1;
mod type3;
#[derive(Debug)]
pub enum Font {
Type1(Type1Font),
MmType1(MmType1Font),
TrueType(TrueTypeFont),
Type3(Type3Font),
Type0(Type0Font),
}
impl Font {
const TYPE: &'static str = "Font";
pub fn from_dict(mut dict: Dictionary, resolver: &mut dyn Resolve) -> PdfResult<Self> {
dict.expect_type(Self::TYPE, resolver, true)?;
let subtype = FontSubtype::from_str(&dict.expect_name("Subtype", resolver)?)?;
Ok(match subtype {
FontSubtype::Type1 => Self::Type1(Type1Font::from_dict(dict, resolver)?),
FontSubtype::MmType1 => Self::MmType1(MmType1Font::from_dict(dict, resolver)?),
FontSubtype::Type3 => Self::Type3(Type3Font::from_dict(dict, resolver)?),
FontSubtype::TrueType => Self::TrueType(TrueTypeFont::from_dict(dict, resolver)?),
FontSubtype::Type0 => Self::Type0(Type0Font::from_dict(dict, resolver)?),
_ => todo!("unimplemented font subtype: {:?}\n{:#?}", subtype, dict),
})
}
}
#[derive(Debug)]
pub struct BaseFontDict {
/// The name by which this font is referenced in the Font subdictionary
/// of the current resource dictionary.
///
/// This entry is obsolete and should not be used.
name: Option<String>,
/// The first character code defined in the font's Widths array.
///
/// Beginning with PDF 1.5, the special treatment given to the standard 14 fonts
/// is deprecated. Conforming writers should represent all fonts using a complete
/// font descriptor. For backwards capability, conforming readers shall
/// still provide the special treatment identified for the standard 14 fonts.
///
/// Required except for the standard 14 fonts
first_char: u32,
/// The last character code defined in the font's Widths array
last_char: u32,
/// An array of (`last_char` - `first_char` + 1) widths, each element being the
/// glyph width for the character code that equals `first_char` plus the array
/// index. For character codes outside the range `first_char` to `last_char`, the
/// value of MissingWidth from the FontDescriptor entry for this font shall be used.
///
/// The glyph widths shall be measured in units in which 1000 units correspond to 1
/// unit in text space. These widths shall be consistent with the actual widths given
/// in the font program. For more information on glyph widths and other glyph metrics
widths: Vec<f32>,
/// A font descriptor describing the font's metrics other than its glyph widths.
///
/// For the standard 14 fonts, the entries `first_char`, `last_char`, `widths`, and
/// `font_descriptor` shall either all be present or all be absent. Ordinarily, these
/// dictionary keys may be absent; specifying them enables a standard font to be overridden.
font_descriptor: FontDescriptor,
}
impl BaseFontDict {
pub fn from_dict(dict: &mut Dictionary, resolver: &mut dyn Resolve) -> PdfResult<Self> {
let name = dict.get_name("Name", resolver)?;
let first_char = dict.expect_unsigned_integer("FirstChar", resolver)?;
let last_char = dict.expect_unsigned_integer("LastChar", resolver)?;
let widths = dict
.expect_arr("Widths", resolver)?
.into_iter()
.map(|obj| resolver.assert_number(obj))
.collect::<PdfResult<Vec<f32>>>()?;
let font_descriptor =
FontDescriptor::from_dict(dict.expect_dict("FontDescriptor", resolver)?, resolver)?;
Ok(Self {
name,
first_char,
last_char,
widths,
font_descriptor,
})
}
}
pdf_enum!(
#[derive(Debug, Clone, Copy)]
enum FontSubtype {
/// A composite font -- a font composed of glyphs from a descendant CIDFont
Type0 = "Type0",
/// A font that defines glyph shapes using Type 1 font technology
Type1 = "Type1",
/// A multiple master font -- an extension of the Type 1 font that allows
/// the generation of a wide variety of typeface styles from a single font
MmType1 = "MMType1",
/// A font that defines glyphs with streams of PDF graphics operators
Type3 = "Type3",
/// A font based on the TrueType font format
TrueType = "TrueType",
/// A CIDFont whose glyph descriptions are based on Type 1 font technology
CidFontType0 = "CIDFontType0",
/// A CIDFont whose glyph descriptions are based on TrueType font technology
CidFontType2 = "CIDFontType2",
}
);