summaryrefslogtreecommitdiff
path: root/src/font.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-08-01 00:01:17 +0200
committerLaurenz <laurmaedje@gmail.com>2020-08-01 00:10:54 +0200
commit06dbac6efd98be5a015023c88ed3dbd9a35a4594 (patch)
treebb3c75230098bf71d1ac23bbe7184e4ae7a6cef2 /src/font.rs
parent064954cf9edbb0201b6184e69978f86e93741008 (diff)
Port font handling to fontdock and ttf-parser 🛳
- Use fontdock for indexing fonts and querying - Typst binary now automatically indexes and uses system fonts in addition to a fixed font folder! - Removes subsetting support for now (was half-finished anyways, plan is to use harfbuzz for subsetting in the future) - Adds font width configuration support
Diffstat (limited to 'src/font.rs')
-rw-r--r--src/font.rs69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/font.rs b/src/font.rs
new file mode 100644
index 00000000..81a63445
--- /dev/null
+++ b/src/font.rs
@@ -0,0 +1,69 @@
+//! Font handling.
+
+use std::cell::RefCell;
+use std::ops::Deref;
+use std::rc::Rc;
+use ttf_parser::Face;
+use fontdock::{FontLoader, FontProvider, ContainsChar, FaceFromVec};
+
+/// A referenced-count shared font loader backed by a dynamic provider.
+pub type SharedFontLoader = Rc<RefCell<FontLoader<Box<DynProvider>>>>;
+
+/// The dynamic font provider type backing the font loader.
+pub type DynProvider = dyn FontProvider<Face=OwnedFace>;
+
+/// An owned font face.
+pub struct OwnedFace {
+ data: Vec<u8>,
+ face: Face<'static>,
+}
+
+impl FaceFromVec for OwnedFace {
+ fn from_vec(vec: Vec<u8>, i: u32) -> Option<Self> {
+ // The vec's location is stable in memory since we don't touch it and
+ // it can't be touched from outside this type.
+ let slice: &'static [u8] = unsafe {
+ std::slice::from_raw_parts(vec.as_ptr(), vec.len())
+ };
+
+ Some(OwnedFace {
+ data: vec,
+ face: Face::from_slice(slice, i).ok()?,
+ })
+ }
+}
+
+impl OwnedFace {
+ /// The raw face data.
+ pub fn data(&self) -> &[u8] {
+ &self.data
+ }
+
+ /// Encode the text into glyph ids and encode these into a big-endian byte
+ /// buffer.
+ pub fn encode_text(&self, text: &str) -> Vec<u8> {
+ const BYTES_PER_GLYPH: usize = 2;
+ let mut bytes = Vec::with_capacity(BYTES_PER_GLYPH * text.len());
+ for c in text.chars() {
+ if let Some(glyph) = self.glyph_index(c) {
+ bytes.push((glyph.0 >> 8) as u8);
+ bytes.push((glyph.0 & 0xff) as u8);
+ }
+ }
+ bytes
+ }
+}
+
+impl ContainsChar for OwnedFace {
+ fn contains_char(&self, c: char) -> bool {
+ self.glyph_index(c).is_some()
+ }
+}
+
+impl Deref for OwnedFace {
+ type Target = Face<'static>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.face
+ }
+}