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
pub mod configuration;
pub mod manager;
pub mod styles;
use std::fs::File;
use std::io::Cursor;
use std::path::{Path, PathBuf};
use freetype::{face, Face, Library};
use printpdf::types::plugins::graphics::two_dimensional::font::IndirectFontRef;
use printpdf::Pt;
use crate::document::Document;
use crate::{Error, Result};
#[derive(Debug)]
pub struct Font {
freetype: Face,
printpdf: IndirectFontRef,
}
impl Font {
pub fn from_file<P: AsRef<Path>>(
path: P,
library: &Library,
document: &mut Document,
) -> Result<Font> {
let file = File::open(path.as_ref())
.map_err(|_| Error::FontNotFound(PathBuf::from(path.as_ref())))?;
Ok(Font {
freetype: library.new_face(path.as_ref(), 0)?,
printpdf: document.inner_mut().add_external_font(file)?,
})
}
pub fn from_bytes(bytes: &[u8], library: &Library, document: &mut Document) -> Result<Font> {
let cursor = Cursor::new(bytes);
Ok(Font {
freetype: library.new_memory_face(bytes.to_vec(), 0)?,
printpdf: document.inner_mut().add_external_font(cursor)?,
})
}
pub fn char_width(&self, c: char, scale: Pt) -> Pt {
let scale = scale.0;
let vert_scale = {
if self
.freetype
.load_char(0x0020, face::LoadFlag::NO_SCALE)
.is_ok()
{
self.freetype.glyph().metrics().vertAdvance
} else {
1000
}
};
let is_ok = self
.freetype
.load_char(c as usize, face::LoadFlag::NO_SCALE)
.is_ok();
let width = if is_ok {
self.freetype.glyph().metrics().horiAdvance
} else {
0
};
Pt(width as f64 / (vert_scale as f64 / scale))
}
pub fn text_width(&self, text: &str, scale: Pt) -> Pt {
let scale = scale.0;
let vert_scale = {
if self
.freetype
.load_char(0x0020, face::LoadFlag::NO_SCALE)
.is_ok()
{
self.freetype.glyph().metrics().vertAdvance
} else {
1000
}
};
let sum_width = text.chars().fold(0, |acc, ch| {
let is_ok = self
.freetype
.load_char(ch as usize, face::LoadFlag::NO_SCALE)
.is_ok();
if is_ok {
acc + self.freetype.glyph().metrics().horiAdvance
} else {
acc
}
});
Pt(sum_width as f64 / (vert_scale as f64 / scale))
}
pub fn printpdf(&self) -> &IndirectFontRef {
&self.printpdf
}
}