diff options
| author | Laurenz <laurmaedje@gmail.com> | 2020-09-30 13:18:42 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2020-09-30 13:18:42 +0200 |
| commit | 7143e10afccc7beef22646f6c7355075f97afb2c (patch) | |
| tree | 6713e1c732fb47ec3ef439f0b90df489398df201 /src | |
| parent | ee11f871756b1a17cf34b3ed5549eaddddc70f5e (diff) | |
Streamline font handling a bit 📜
Diffstat (limited to 'src')
| -rw-r--r-- | src/export/pdf.rs | 14 | ||||
| -rw-r--r-- | src/font.rs | 41 | ||||
| -rw-r--r-- | src/layout/text.rs | 13 | ||||
| -rw-r--r-- | src/layout/tree.rs | 2 |
4 files changed, 37 insertions, 33 deletions
diff --git a/src/export/pdf.rs b/src/export/pdf.rs index c4c12713..b87b3181 100644 --- a/src/export/pdf.rs +++ b/src/export/pdf.rs @@ -13,10 +13,10 @@ use tide::font::{ use tide::{PdfWriter, Rect, Ref, Trailer, Version}; use ttf_parser::{name_id, GlyphId}; +use crate::font::FontLoader; use crate::layout::elements::LayoutElement; use crate::layout::BoxLayout; use crate::length::Length; -use crate::SharedFontLoader; /// Export a list of layouts into a _PDF_ document. /// @@ -28,7 +28,7 @@ use crate::SharedFontLoader; /// bytes written. pub fn export<W: Write>( layout: &[BoxLayout], - loader: &SharedFontLoader, + loader: &FontLoader, target: W, ) -> io::Result<usize> { PdfExporter::new(layout, loader, target)?.write() @@ -37,7 +37,7 @@ pub fn export<W: Write>( struct PdfExporter<'a, W: Write> { writer: PdfWriter<W>, layouts: &'a [BoxLayout], - loader: &'a SharedFontLoader, + loader: &'a FontLoader, /// We need to know exactly which indirect reference id will be used for /// which objects up-front to correctly declare the document catalogue, page /// tree and so on. These offsets are computed in the beginning and stored @@ -61,7 +61,7 @@ const NUM_OBJECTS_PER_FONT: u32 = 5; impl<'a, W: Write> PdfExporter<'a, W> { fn new( layouts: &'a [BoxLayout], - loader: &'a SharedFontLoader, + loader: &'a FontLoader, target: W, ) -> io::Result<Self> { let (to_pdf, to_fontdock) = remap_fonts(layouts); @@ -168,8 +168,8 @@ impl<'a, W: Write> PdfExporter<'a, W> { let mut id = self.offsets.fonts.0; for &face_id in &self.to_layout { - let loader = self.loader.borrow(); - let face = loader.get_loaded(face_id); + let owned_face = self.loader.get_loaded(face_id); + let face = owned_face.get(); let name = face .names() @@ -269,7 +269,7 @@ impl<'a, W: Write> PdfExporter<'a, W> { .write_obj(id + 3, &CMap::new("Custom", system_info, mapping))?; // Write the face's bytes. - self.writer.write_obj(id + 4, &FontStream::new(face.data()))?; + self.writer.write_obj(id + 4, &FontStream::new(owned_face.data()))?; id += NUM_OBJECTS_PER_FONT; } diff --git a/src/font.rs b/src/font.rs index 1e34ac05..539f3188 100644 --- a/src/font.rs +++ b/src/font.rs @@ -1,25 +1,34 @@ //! Font handling. use std::cell::RefCell; -use std::ops::Deref; use std::rc::Rc; -use fontdock::{ContainsChar, FaceFromVec, FontLoader, FontProvider}; +use fontdock::{ContainsChar, FaceFromVec, FontProvider}; use ttf_parser::Face; -/// A referenced-count shared font loader backed by a dynamic provider. -pub type SharedFontLoader = Rc<RefCell<FontLoader<Box<DynProvider>>>>; +/// A reference-counted shared font loader backed by a dynamic font provider. +pub type SharedFontLoader = Rc<RefCell<FontLoader>>; -/// The dynamic font provider type backing the font loader. +/// A font loader backed by a dynamic provider. +pub type FontLoader = fontdock::FontLoader<Box<DynProvider>>; + +/// The dynamic font provider backing the font loader. pub type DynProvider = dyn FontProvider<Face = OwnedFace>; /// An owned font face. pub struct OwnedFace { - data: Vec<u8>, + data: Box<[u8]>, face: Face<'static>, } impl OwnedFace { + /// Get a reference to the underlying face. + pub fn get<'a>(&'a self) -> &'a Face<'a> { + // We can't implement Deref because that would leak the internal 'static + // lifetime. + &self.face + } + /// The raw face data. pub fn data(&self) -> &[u8] { &self.data @@ -28,13 +37,15 @@ impl OwnedFace { 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 data = vec.into_boxed_slice(); + + // SAFETY: The slices'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()) }; + unsafe { std::slice::from_raw_parts(data.as_ptr(), data.len()) }; Some(Self { - data: vec, + data, face: Face::from_slice(slice, i).ok()?, }) } @@ -42,14 +53,6 @@ impl FaceFromVec for OwnedFace { 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 + self.get().glyph_index(c).is_some() } } diff --git a/src/layout/text.rs b/src/layout/text.rs index 971d6be6..7dd557c9 100644 --- a/src/layout/text.rs +++ b/src/layout/text.rs @@ -9,7 +9,7 @@ use ttf_parser::GlyphId; use super::elements::{LayoutElement, Shaped}; use super::*; -use crate::font::SharedFontLoader; +use crate::font::FontLoader; use crate::geom::Size; use crate::style::TextStyle; @@ -30,11 +30,11 @@ struct TextLayouter<'a> { } /// The context for text layouting. -#[derive(Debug, Copy, Clone)] +#[derive(Debug)] pub struct TextContext<'a> { /// The font loader to retrieve fonts from when typesetting text with /// `layout_text`. - pub loader: &'a SharedFontLoader, + pub loader: &'a mut FontLoader, /// The style for text: Font selection with classes, weights and variants, /// font sizes, spacing and so on. pub style: &'a TextStyle, @@ -50,12 +50,12 @@ pub struct TextContext<'a> { impl<'a> TextLayouter<'a> { fn new(text: &'a str, ctx: TextContext<'a>) -> Self { Self { - ctx, text, shaped: Shaped::new(FaceId::MAX, ctx.style.font_size()), elements: LayoutElements::new(), start: 0.0, width: 0.0, + ctx, } } @@ -116,7 +116,6 @@ impl<'a> TextLayouter<'a> { } async fn select_font(&mut self, c: char) -> Option<(FaceId, GlyphId, f64)> { - let mut loader = self.ctx.loader.borrow_mut(); let mut variant = self.ctx.style.variant; if self.ctx.style.bolder { @@ -137,7 +136,9 @@ impl<'a> TextLayouter<'a> { c, }; - if let Some((id, face)) = loader.query(query).await { + if let Some((id, owned_face)) = self.ctx.loader.query(query).await { + let face = owned_face.get(); + // Determine the width of the char. let units_per_em = face.units_per_em().unwrap_or(1000) as f64; let ratio = 1.0 / units_per_em; diff --git a/src/layout/tree.rs b/src/layout/tree.rs index b6f9ab47..19bff091 100644 --- a/src/layout/tree.rs +++ b/src/layout/tree.rs @@ -107,7 +107,7 @@ impl<'a> TreeLayouter<'a> { async fn layout_text(&mut self, text: &str) { self.layouter.add( layout_text(text, TextContext { - loader: &self.ctx.loader, + loader: &mut self.ctx.loader.borrow_mut(), style: &self.style.text, dir: self.ctx.axes.primary, align: self.ctx.align, |
