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 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
use crate::preparse::{FaceSubtables, PreParsedSubtables};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, vec::Vec};
use core::{fmt, marker::PhantomPinned, mem, pin::Pin, slice};
/// An owned version of font [`Face`](struct.Face.html).
pub struct OwnedFace(Pin<Box<SelfRefVecFace>>);
impl OwnedFace {
/// Creates an `OwnedFace` from owned data.
///
/// You can set index for font collections. For simple ttf fonts set index to 0.
///
/// # Example
/// ```
/// # use owned_ttf_parser::OwnedFace;
/// # let owned_font_data = include_bytes!("../fonts/font.ttf").to_vec();
/// let owned_face = OwnedFace::from_vec(owned_font_data, 0).unwrap();
/// ```
// Note: not `try_from_vec` to better mimic `ttf_parser::Face::from_data`.
pub fn from_vec(data: Vec<u8>, index: u32) -> Result<Self, ttf_parser::FaceParsingError> {
let inner = SelfRefVecFace::try_from_vec(data, index)?;
Ok(Self(inner))
}
pub(crate) fn pre_parse_subtables(self) -> PreParsedSubtables<'static, Self> {
// build subtables referencing fake static data
let subtables = FaceSubtables::from(match self.0.face.as_ref() {
Some(f) => f,
None => unsafe { core::hint::unreachable_unchecked() },
});
// bundle everything together so self-reference lifetimes hold
PreParsedSubtables {
face: self,
subtables,
}
}
/// Extracts a slice containing the data passed into [`OwnedFace::from_vec`].
///
/// # Example
/// ```
/// # use owned_ttf_parser::OwnedFace;
/// # let owned_font_data = include_bytes!("../fonts/font.ttf").to_vec();
/// let data_clone = owned_font_data.clone();
/// let owned_face = OwnedFace::from_vec(owned_font_data, 0).unwrap();
/// assert_eq!(owned_face.as_slice(), data_clone);
/// ```
pub fn as_slice(&self) -> &[u8] {
&self.0.data
}
/// Unwraps the data passed into [`OwnedFace::from_vec`].
///
/// # Example
/// ```
/// # use owned_ttf_parser::OwnedFace;
/// # let owned_font_data = include_bytes!("../fonts/font.ttf").to_vec();
/// let data_clone = owned_font_data.clone();
/// let owned_face = OwnedFace::from_vec(owned_font_data, 0).unwrap();
/// assert_eq!(owned_face.into_vec(), data_clone);
/// ```
pub fn into_vec(self) -> Vec<u8> {
self.0.into_vec()
}
}
impl fmt::Debug for OwnedFace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "OwnedFace()")
}
}
impl crate::convert::AsFaceRef for OwnedFace {
#[inline]
fn as_face_ref(&self) -> &ttf_parser::Face<'_> {
self.0.inner_ref()
}
}
impl crate::convert::AsFaceRef for &OwnedFace {
#[inline]
fn as_face_ref(&self) -> &ttf_parser::Face<'_> {
self.0.inner_ref()
}
}
impl crate::convert::FaceMut for OwnedFace {
fn set_variation(&mut self, axis: ttf_parser::Tag, value: f32) -> Option<()> {
unsafe {
let mut_ref = Pin::as_mut(&mut self.0);
let mut_inner = mut_ref.get_unchecked_mut();
match mut_inner.face.as_mut() {
Some(face) => face.set_variation(axis, value),
None => None,
}
}
}
}
impl crate::convert::FaceMut for &mut OwnedFace {
#[inline]
fn set_variation(&mut self, axis: ttf_parser::Tag, value: f32) -> Option<()> {
(*self).set_variation(axis, value)
}
}
// Face data in a `Vec` with a self-referencing `Face`.
struct SelfRefVecFace {
data: Vec<u8>,
face: Option<ttf_parser::Face<'static>>,
_pin: PhantomPinned,
}
impl SelfRefVecFace {
/// Creates an underlying face object from owned data.
fn try_from_vec(
data: Vec<u8>,
index: u32,
) -> Result<Pin<Box<Self>>, ttf_parser::FaceParsingError> {
let face = Self {
data,
face: None,
_pin: PhantomPinned,
};
let mut b = Box::pin(face);
unsafe {
// 'static lifetime is a lie, this data is owned, it has pseudo-self lifetime.
let slice: &'static [u8] = slice::from_raw_parts(b.data.as_ptr(), b.data.len());
let mut_ref: Pin<&mut Self> = Pin::as_mut(&mut b);
let mut_inner = mut_ref.get_unchecked_mut();
mut_inner.face = Some(ttf_parser::Face::parse(slice, index)?);
}
Ok(b)
}
// Must not leak the fake 'static lifetime that we lied about earlier to the
// compiler. Since the lifetime 'a will not outlive our owned data it's
// safe to provide Face<'a>
#[inline]
#[allow(clippy::needless_lifetimes)] // explicit is nice as it's important 'static isn't leaked
fn inner_ref<'a>(self: &'a Pin<Box<Self>>) -> &'a ttf_parser::Face<'a> {
// Safety: if you have a ref `face` is always Some
unsafe { self.face.as_ref().unwrap_unchecked() }
}
fn into_vec(self: Pin<Box<Self>>) -> Vec<u8> {
// Safety: safe as `face` is dropped.
let mut me = unsafe { Pin::into_inner_unchecked(self) };
me.face.take(); // ensure dropped before taking `data`
mem::take(&mut me.data)
}
}
impl Drop for SelfRefVecFace {
fn drop(&mut self) {
self.face.take(); // ensure dropped before `data`
}
}