1use crate::MPx;
2use crate::basic::BasicPdfWriter;
3use crate::metric::*;
4use format_bytes::write_bytes as wb;
5
6pub trait Font {
8 fn obj(&self) -> usize;
10
11 fn encode(&self, s: &str, to: &mut Vec<u8>);
13
14 fn width(&self, c: char) -> MPx;
16
17 fn init(&mut self, w: &mut BasicPdfWriter);
19}
20
21pub type FontFamily = [Box<dyn Font>; 4];
23
24pub 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
33pub 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
42pub 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#[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); let (r, _n) = e.encode_from_utf8_to_vec_without_replacement(s, to, false);
102 assert!(r == encoding_rs::EncoderResult::InputEmpty);
103 }
104}
105
106static TIMES: [&str; 4] = [
108 "Times-Roman",
109 "Times-Bold",
110 "Times-Italic",
111 "Times-BoldItalic",
112];
113
114static HELVETICA: [&str; 4] = [
116 "Helvetica",
117 "Helvetica-Bold",
118 "Helvetica-Oblique",
119 "Helvetica-BoldOblique",
120];
121
122static COURIER: [&str; 4] = [
124 "Courier",
125 "Courier-Bold",
126 "Courier-Oblique",
127 "Courier-BoldOblique",
128];