Skip to main content

pdf_min/
font.rs

1use crate::MPx;
2use crate::basic::BasicPdfWriter;
3use crate::metric::*;
4use format_bytes::write_bytes as wb;
5
6/// Font
7pub trait Font {
8    /// Get the PDF object number.
9    fn obj(&self) -> usize;
10
11    /// Encode string.
12    fn encode(&self, s: &str, to: &mut Vec<u8>);
13
14    /// Get char width
15    fn width(&self, c: char) -> MPx;
16
17    /// Initialise the font by writing defition to w.
18    fn init(&mut self, w: &mut BasicPdfWriter);
19}
20
21/// Font family - normal, bold, italic, bold italic
22pub type FontFamily = [Box<dyn Font>; 4];
23
24/// Helvetica standard font family
25pub fn helvetica() -> FontFamily {
26    let a = StandardFont::make(&HELVETICA0[..], HELVETICA[0]);
27    let b = StandardFont::make(&HELVETICA1[..], HELVETICA[1]);
28    let c = StandardFont::make(&HELVETICA2[..], HELVETICA[2]);
29    let d = StandardFont::make(&HELVETICA3[..], HELVETICA[3]);
30    [a, b, c, d]
31}
32
33/// Times standard font family
34pub fn times() -> FontFamily {
35    let a = StandardFont::make(&TIMES0[..], TIMES[0]);
36    let b = StandardFont::make(&TIMES1[..], TIMES[1]);
37    let c = StandardFont::make(&TIMES2[..], TIMES[2]);
38    let d = StandardFont::make(&TIMES3[..], TIMES[3]);
39    [a, b, c, d]
40}
41
42/// Courier standard font family
43pub fn courier() -> FontFamily {
44    let a = StandardFont::make(&COURIER0[..], COURIER[0]);
45    let b = StandardFont::make(&COURIER1[..], COURIER[1]);
46    let c = StandardFont::make(&COURIER2[..], COURIER[2]);
47    let d = StandardFont::make(&COURIER3[..], COURIER[3]);
48    [a, b, c, d]
49}
50
51/// Standard Font
52#[derive(Default)]
53pub struct StandardFont {
54    obj: usize,
55    size_data: &'static [u16],
56    name: &'static str,
57}
58
59impl StandardFont {
60    fn make(size_data: &'static [u16], name: &'static str) -> Box<dyn Font> {
61        Box::new(Self {
62            obj: 0,
63            size_data,
64            name,
65        })
66    }
67}
68
69impl Font for StandardFont {
70    fn obj(&self) -> usize {
71        self.obj
72    }
73
74    fn width(&self, c: char) -> MPx {
75        let mut c = c as usize;
76        if c < 32 || c - 32 >= self.size_data.len() {
77            c = 32;
78        }
79        self.size_data[c - 32] as MPx
80    }
81
82    fn init(&mut self, w: &mut BasicPdfWriter) {
83        if self.obj == 0 {
84            self.obj = w.begin();
85            let _ = wb!(
86                &mut w.b,
87                b"<</Type/Font/Subtype/Type1/Name/F{}/BaseFont/{}/Encoding/WinAnsiEncoding>>",
88                self.obj,
89                self.name.as_bytes()
90            );
91            w.end();
92        }
93    }
94
95    fn encode(&self, s: &str, to: &mut Vec<u8>) {
96        let mut e = encoding_rs::WINDOWS_1252.new_encoder();
97        let x = e
98            .max_buffer_length_from_utf8_without_replacement(s.len())
99            .unwrap();
100        to.reserve(x); // Weird that this is necessary.
101        let (r, _n) = e.encode_from_utf8_to_vec_without_replacement(s, to, false);
102        assert!(r == encoding_rs::EncoderResult::InputEmpty);
103    }
104}
105
106/// Names of standard Times font.
107static TIMES: [&str; 4] = [
108    "Times-Roman",
109    "Times-Bold",
110    "Times-Italic",
111    "Times-BoldItalic",
112];
113
114/// Names of standard Helvetica font.
115static HELVETICA: [&str; 4] = [
116    "Helvetica",
117    "Helvetica-Bold",
118    "Helvetica-Oblique",
119    "Helvetica-BoldOblique",
120];
121
122/// Names of standard Courier font.
123static COURIER: [&str; 4] = [
124    "Courier",
125    "Courier-Bold",
126    "Courier-Oblique",
127    "Courier-BoldOblique",
128];