#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct TrueTypeFontId(pub usize);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum FontRef {
Builtin(BuiltinFont),
TrueType(TrueTypeFontId),
}
impl From<BuiltinFont> for FontRef {
fn from(font: BuiltinFont) -> Self {
FontRef::Builtin(font)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
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 => "F1",
BuiltinFont::HelveticaBold => "F2",
BuiltinFont::HelveticaOblique => "F3",
BuiltinFont::HelveticaBoldOblique => "F4",
BuiltinFont::TimesRoman => "F5",
BuiltinFont::TimesBold => "F6",
BuiltinFont::TimesItalic => "F7",
BuiltinFont::TimesBoldItalic => "F8",
BuiltinFont::Courier => "F9",
BuiltinFont::CourierBold => "F10",
BuiltinFont::CourierOblique => "F11",
BuiltinFont::CourierBoldOblique => "F12",
BuiltinFont::Symbol => "F13",
BuiltinFont::ZapfDingbats => "F14",
}
}
pub fn pdf_base_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 from_name(name: &str) -> Option<BuiltinFont> {
match name {
"Helvetica" => Some(BuiltinFont::Helvetica),
"Helvetica-Bold" => Some(BuiltinFont::HelveticaBold),
"Helvetica-Oblique" => Some(BuiltinFont::HelveticaOblique),
"Helvetica-BoldOblique" => Some(BuiltinFont::HelveticaBoldOblique),
"Times-Roman" => Some(BuiltinFont::TimesRoman),
"Times-Bold" => Some(BuiltinFont::TimesBold),
"Times-Italic" => Some(BuiltinFont::TimesItalic),
"Times-BoldItalic" => Some(BuiltinFont::TimesBoldItalic),
"Courier" => Some(BuiltinFont::Courier),
"Courier-Bold" => Some(BuiltinFont::CourierBold),
"Courier-Oblique" => Some(BuiltinFont::CourierOblique),
"Courier-BoldOblique" => Some(BuiltinFont::CourierBoldOblique),
"Symbol" => Some(BuiltinFont::Symbol),
"ZapfDingbats" => Some(BuiltinFont::ZapfDingbats),
_ => None,
}
}
}
const HELVETICA_WIDTHS: [u16; 95] = [
278, 278, 355, 556, 556, 889, 667, 191, 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, 333, 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, ];
const HELVETICA_BOLD_WIDTHS: [u16; 95] = [
278, 333, 474, 556, 556, 889, 722, 238, 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, 333, 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, ];
const TIMES_ROMAN_WIDTHS: [u16; 95] = [
250, 333, 408, 500, 500, 833, 778, 180, 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, ];
const TIMES_BOLD_WIDTHS: [u16; 95] = [
250, 333, 555, 500, 500, 1000, 833, 278, 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, ];
const TIMES_ITALIC_WIDTHS: [u16; 95] = [
250, 333, 420, 500, 500, 833, 778, 214, 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, ];
const TIMES_BOLD_ITALIC_WIDTHS: [u16; 95] = [
250, 389, 555, 500, 500, 833, 778, 278, 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, 556, 556, 389, 389, 278, 556, 444, 667, 500, 444, 389, 348, 220, 348, 570, ];
const COURIER_WIDTH: u16 = 600;
const DEFAULT_WIDTH: u16 = 278;
pub struct FontMetrics;
impl FontMetrics {
pub fn char_width(font: BuiltinFont, ch: char) -> u16 {
match font {
BuiltinFont::Courier
| BuiltinFont::CourierBold
| BuiltinFont::CourierOblique
| BuiltinFont::CourierBoldOblique => {
return COURIER_WIDTH;
}
BuiltinFont::Symbol | BuiltinFont::ZapfDingbats => {
return DEFAULT_WIDTH;
}
_ => {}
}
let code = ch as u32;
if code < 32 || code > 126 {
return DEFAULT_WIDTH;
}
let index = (code - 32) as usize;
match font {
BuiltinFont::Helvetica | BuiltinFont::HelveticaOblique => HELVETICA_WIDTHS[index],
BuiltinFont::HelveticaBold | BuiltinFont::HelveticaBoldOblique => {
HELVETICA_BOLD_WIDTHS[index]
}
BuiltinFont::TimesRoman => TIMES_ROMAN_WIDTHS[index],
BuiltinFont::TimesBold => TIMES_BOLD_WIDTHS[index],
BuiltinFont::TimesItalic => TIMES_ITALIC_WIDTHS[index],
BuiltinFont::TimesBoldItalic => TIMES_BOLD_ITALIC_WIDTHS[index],
_ => DEFAULT_WIDTH,
}
}
pub fn measure_text(text: &str, font: BuiltinFont, font_size: f64) -> f64 {
let total: u32 = text
.chars()
.map(|ch| Self::char_width(font, ch) as u32)
.sum();
total as f64 * font_size / 1000.0
}
pub fn line_height(_font: BuiltinFont, font_size: f64) -> f64 {
font_size * 1.2
}
}