#[derive(Debug, Clone, Copy, PartialEq)]
pub enum BuiltinFont {
Helvetica,
HelveticaBold,
HelveticaOblique,
HelveticaBoldOblique,
TimesRoman,
TimesBold,
TimesItalic,
TimesBoldItalic,
Courier,
CourierBold,
CourierOblique,
CourierBoldOblique,
Symbol,
ZapfDingbats,
}
impl BuiltinFont {
pub fn pdf_name(&self) -> &'static str {
match self {
BuiltinFont::Helvetica => "Helvetica",
BuiltinFont::HelveticaBold => "Helvetica-Bold",
BuiltinFont::HelveticaOblique => "Helvetica-Oblique",
BuiltinFont::HelveticaBoldOblique => "Helvetica-BoldOblique",
BuiltinFont::TimesRoman => "Times-Roman",
BuiltinFont::TimesBold => "Times-Bold",
BuiltinFont::TimesItalic => "Times-Italic",
BuiltinFont::TimesBoldItalic => "Times-BoldItalic",
BuiltinFont::Courier => "Courier",
BuiltinFont::CourierBold => "Courier-Bold",
BuiltinFont::CourierOblique => "Courier-Oblique",
BuiltinFont::CourierBoldOblique => "Courier-BoldOblique",
BuiltinFont::Symbol => "Symbol",
BuiltinFont::ZapfDingbats => "ZapfDingbats",
}
}
pub fn char_width(&self, c: char) -> f64 {
let code = c as u32;
let idx = if code > 0xFF {
let replacement = match c {
'\u{2014}' => '-', '\u{2013}' => '-', '\u{2018}' | '\u{2019}' => '\'',
'\u{201C}' | '\u{201D}' => '"',
'\u{2026}' => '.', _ => '?',
} as usize;
replacement
} else {
code as usize
};
let widths = self.widths();
widths.get(idx).copied().unwrap_or(500) as f64
}
pub fn string_width(&self, text: &str, size: f64) -> f64 {
let total: f64 = text.chars().flat_map(|c| {
if c as u32 > 0xFF {
let s: &[char] = match c {
'\u{2014}' => &['-', '-'], '\u{2026}' => &['.', '.', '.'], _ => &['?'],
};
s.iter().map(|&ch| self.char_width(ch)).collect::<Vec<_>>()
} else {
vec![self.char_width(c)]
}
}).sum();
total * size / 1000.0
}
fn widths(&self) -> &'static [u16] {
match self {
BuiltinFont::Helvetica | BuiltinFont::HelveticaOblique => HELVETICA_WIDTHS,
BuiltinFont::HelveticaBold | BuiltinFont::HelveticaBoldOblique => HELVETICA_BOLD_WIDTHS,
BuiltinFont::TimesRoman => TIMES_ROMAN_WIDTHS,
BuiltinFont::TimesBold => TIMES_BOLD_WIDTHS,
BuiltinFont::TimesItalic => TIMES_ITALIC_WIDTHS,
BuiltinFont::TimesBoldItalic => TIMES_BOLD_ITALIC_WIDTHS,
BuiltinFont::Courier
| BuiltinFont::CourierBold
| BuiltinFont::CourierOblique
| BuiltinFont::CourierBoldOblique => COURIER_WIDTHS,
_ => HELVETICA_WIDTHS,
}
}
pub fn is_monospace(&self) -> bool {
matches!(
self,
BuiltinFont::Courier
| BuiltinFont::CourierBold
| BuiltinFont::CourierOblique
| BuiltinFont::CourierBoldOblique
)
}
}
static HELVETICA_WIDTHS: &[u16] = &[
278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, 278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, 278,278,355,556,556,889,667,222,333,333,389,584,278,333,278,278, 556,556,556,556,556,556,556,556,556,556,278,278,584,584,584,556, 1015,667,667,722,722,667,611,778,722,278,500,667,556,833,722,778, 667,778,722,667,611,722,667,944,667,667,611,278,278,278,469,556, 222,556,556,500,556,556,278,556,556,222,222,500,222,833,556,556, 556,556,333,500,278,556,500,722,500,500,500,334,260,334,584,278, 278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, 278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, 278,333,556,556,556,556,260,556,333,737,370,556,584,333,737,333, 400,584,333,333,333,556,537,278,333,333,365,556,834,834,834,611, 667,667,667,667,667,667,1000,722,667,667,667,667,278,278,278,278, 722,722,778,778,778,778,778,584,778,722,722,722,722,667,667,611, 556,556,556,556,556,556,889,500,556,556,556,556,278,278,278,278, 556,556,556,556,556,556,556,584,611,556,556,556,556,500,556,500, ];
static HELVETICA_BOLD_WIDTHS: &[u16] = &[
278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
278,333,474,556,556,889,722,278,333,333,389,584,278,333,278,278,
556,556,556,556,556,556,556,556,556,556,333,333,584,584,584,611,
975,722,722,722,722,667,611,778,722,278,556,722,611,833,722,778,
667,778,722,667,611,722,667,944,667,667,611,333,278,333,584,556,
278,556,611,556,611,556,333,611,611,278,278,556,278,889,611,611,
611,611,389,556,333,611,556,778,556,556,500,389,280,389,584,278,
278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,
278,333,556,556,556,556,280,556,333,737,370,556,584,333,737,333,
400,584,333,333,333,611,556,278,333,333,365,556,834,834,834,611,
722,722,722,722,722,722,1000,722,667,667,667,667,278,278,278,278,
722,722,778,778,778,778,778,584,778,722,722,722,722,667,667,611,
556,556,556,556,556,556,889,556,556,556,556,556,278,278,278,278,
611,611,611,611,611,611,611,584,611,611,611,611,611,556,611,556,
];
static TIMES_ROMAN_WIDTHS: &[u16] = &[
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,333,408,500,500,833,778,333,333,333,500,564,250,333,250,278,
500,500,500,500,500,500,500,500,500,500,278,278,564,564,564,444,
921,722,667,667,722,611,556,722,722,333,389,722,611,889,722,722,
556,722,667,556,611,722,722,944,722,722,611,333,278,333,469,500,
333,444,500,444,500,444,333,500,500,278,278,500,278,778,500,500,
500,500,333,389,278,500,500,722,500,500,444,480,200,480,541,250,
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,333,500,500,500,500,200,500,333,760,276,500,564,333,760,333,
400,564,300,300,333,500,453,250,333,300,310,500,750,750,750,444,
722,722,722,722,722,722,889,667,611,611,611,611,333,333,333,333,
722,722,722,722,722,722,722,564,722,722,722,722,722,722,556,500,
444,444,444,444,444,444,667,444,444,444,444,444,278,278,278,278,
500,500,500,500,500,500,500,564,500,500,500,500,500,500,500,500,
];
static TIMES_BOLD_WIDTHS: &[u16] = &[
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,333,555,500,500,1000,833,333,333,333,500,570,250,333,250,278,
500,500,500,500,500,500,500,500,500,500,333,333,570,570,570,500,
930,722,667,722,722,667,611,778,778,389,500,778,667,944,722,778,
611,778,722,556,667,722,722,1000,722,722,667,333,278,333,581,500,
333,500,556,444,556,444,333,500,556,278,333,556,278,833,556,500,
556,556,444,389,333,556,500,722,500,500,444,394,220,394,520,250,
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,333,500,500,500,500,220,500,333,747,300,500,570,333,747,333,
400,570,300,300,333,556,540,250,333,300,330,500,750,750,750,500,
722,722,722,722,722,722,1000,722,667,667,667,667,389,389,389,389,
722,722,778,778,778,778,778,570,778,722,722,722,722,722,556,500,
500,500,500,500,500,500,722,444,444,444,444,444,278,278,278,278,
500,556,500,500,500,500,500,570,500,556,556,556,556,500,556,500,
];
static TIMES_ITALIC_WIDTHS: &[u16] = &[
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,333,420,500,500,833,778,333,333,333,500,675,250,333,250,278,
500,500,500,500,500,500,500,500,500,500,333,333,675,675,675,500,
920,611,611,667,722,611,611,722,722,333,444,667,556,833,667,722,
611,722,611,500,556,722,611,833,611,556,556,389,278,389,422,500,
333,500,500,444,500,444,278,500,500,278,278,444,278,722,500,500,
500,500,389,389,278,500,444,667,444,444,389,400,275,400,541,250,
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,389,500,500,500,500,275,500,333,760,276,500,675,333,760,333,
400,675,300,300,333,500,523,250,333,300,310,500,750,750,750,500,
611,611,611,611,611,611,889,667,611,611,611,611,333,333,333,333,
722,667,722,722,722,722,722,675,722,722,722,722,722,556,611,500,
500,500,500,500,500,500,667,444,444,444,444,444,278,278,278,278,
500,500,500,500,500,500,500,675,500,500,500,500,500,444,500,444,
];
static TIMES_BOLD_ITALIC_WIDTHS: &[u16] = &[
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,389,555,500,500,833,778,333,333,333,500,570,250,333,250,278,
500,500,500,500,500,500,500,500,500,500,333,333,570,570,570,500,
832,667,667,667,722,667,667,722,778,389,500,667,611,889,722,722,
611,722,667,556,611,722,667,889,667,611,611,333,278,333,570,500,
333,500,500,444,500,444,333,500,556,278,278,500,278,778,556,500,
500,500,389,389,278,556,444,667,500,444,389,348,220,348,570,250,
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,250,
250,389,500,500,500,500,220,500,333,747,266,500,606,333,747,333,
400,570,300,300,333,576,500,250,333,300,300,500,750,750,750,500,
667,667,667,667,667,667,944,667,667,667,667,667,389,389,389,389,
722,722,722,722,722,722,722,570,722,722,722,722,722,611,611,500,
500,500,500,500,500,500,722,444,444,444,444,444,278,278,278,278,
500,556,500,500,500,500,500,570,500,556,556,556,556,444,500,444,
];
static COURIER_WIDTHS: &[u16] = &[600; 256];