1use crate::preparse::{FaceSubtables, PreParsedSubtables};
2#[cfg(not(feature = "std"))]
3use alloc::{boxed::Box, vec::Vec};
4use core::{fmt, marker::PhantomPinned, mem, pin::Pin, slice};
5
6/// An owned version of font [`Face`](struct.Face.html).
7pub struct OwnedFace(Pin<Box<SelfRefVecFace>>);
8
9impl OwnedFace {
10 /// Creates an `OwnedFace` from owned data.
11 ///
12 /// You can set index for font collections. For simple ttf fonts set index to 0.
13 ///
14 /// # Example
15 /// ```
16 /// # use owned_ttf_parser::OwnedFace;
17 /// # let owned_font_data = include_bytes!("../fonts/font.ttf").to_vec();
18 /// let owned_face = OwnedFace::from_vec(owned_font_data, 0).unwrap();
19 /// ```
20 // Note: not `try_from_vec` to better mimic `ttf_parser::Face::from_data`.
21 pub fn from_vec(data: Vec<u8>, index: u32) -> Result<Self, ttf_parser::FaceParsingError> {
22 let inner = SelfRefVecFace::try_from_vec(data, index)?;
23 Ok(Self(inner))
24 }
25
26 pub(crate) fn pre_parse_subtables(self) -> PreParsedSubtables<'static, Self> {
27 // build subtables referencing fake static data
28 let subtables = FaceSubtables::from(match self.0.face.as_ref() {
29 Some(f) => f,
30 None => unsafe { core::hint::unreachable_unchecked() },
31 });
32
33 // bundle everything together so self-reference lifetimes hold
34 PreParsedSubtables {
35 face: self,
36 subtables,
37 }
38 }
39
40 /// Extracts a slice containing the data passed into [`OwnedFace::from_vec`].
41 ///
42 /// # Example
43 /// ```
44 /// # use owned_ttf_parser::OwnedFace;
45 /// # let owned_font_data = include_bytes!("../fonts/font.ttf").to_vec();
46 /// let data_clone = owned_font_data.clone();
47 /// let owned_face = OwnedFace::from_vec(owned_font_data, 0).unwrap();
48 /// assert_eq!(owned_face.as_slice(), data_clone);
49 /// ```
50 pub fn as_slice(&self) -> &[u8] {
51 &self.0.data
52 }
53
54 /// Unwraps the data passed into [`OwnedFace::from_vec`].
55 ///
56 /// # Example
57 /// ```
58 /// # use owned_ttf_parser::OwnedFace;
59 /// # let owned_font_data = include_bytes!("../fonts/font.ttf").to_vec();
60 /// let data_clone = owned_font_data.clone();
61 /// let owned_face = OwnedFace::from_vec(owned_font_data, 0).unwrap();
62 /// assert_eq!(owned_face.into_vec(), data_clone);
63 /// ```
64 pub fn into_vec(self) -> Vec<u8> {
65 self.0.into_vec()
66 }
67}
68
69impl fmt::Debug for OwnedFace {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 write!(f, "OwnedFace()")
72 }
73}
74
75impl crate::convert::AsFaceRef for OwnedFace {
76 #[inline]
77 fn as_face_ref(&self) -> &ttf_parser::Face<'_> {
78 self.0.inner_ref()
79 }
80}
81
82impl crate::convert::AsFaceRef for &OwnedFace {
83 #[inline]
84 fn as_face_ref(&self) -> &ttf_parser::Face<'_> {
85 self.0.inner_ref()
86 }
87}
88
89impl crate::convert::FaceMut for OwnedFace {
90 fn set_variation(&mut self, axis: ttf_parser::Tag, value: f32) -> Option<()> {
91 unsafe {
92 let mut_ref: Pin<&mut SelfRefVecFace> = Pin::as_mut(&mut self.0);
93 let mut_inner: &mut SelfRefVecFace = mut_ref.get_unchecked_mut();
94 match mut_inner.face.as_mut() {
95 Some(face: &mut Face<'_>) => face.set_variation(axis, value),
96 None => None,
97 }
98 }
99 }
100}
101impl crate::convert::FaceMut for &mut OwnedFace {
102 #[inline]
103 fn set_variation(&mut self, axis: ttf_parser::Tag, value: f32) -> Option<()> {
104 (*self).set_variation(axis, value)
105 }
106}
107
108// Face data in a `Vec` with a self-referencing `Face`.
109struct SelfRefVecFace {
110 data: Vec<u8>,
111 face: Option<ttf_parser::Face<'static>>,
112 _pin: PhantomPinned,
113}
114
115impl SelfRefVecFace {
116 /// Creates an underlying face object from owned data.
117 fn try_from_vec(
118 data: Vec<u8>,
119 index: u32,
120 ) -> Result<Pin<Box<Self>>, ttf_parser::FaceParsingError> {
121 let face = Self {
122 data,
123 face: None,
124 _pin: PhantomPinned,
125 };
126 let mut b = Box::pin(face);
127 unsafe {
128 // 'static lifetime is a lie, this data is owned, it has pseudo-self lifetime.
129 let slice: &'static [u8] = slice::from_raw_parts(b.data.as_ptr(), b.data.len());
130 let mut_ref: Pin<&mut Self> = Pin::as_mut(&mut b);
131 let mut_inner = mut_ref.get_unchecked_mut();
132 mut_inner.face = Some(ttf_parser::Face::parse(slice, index)?);
133 }
134 Ok(b)
135 }
136
137 // Must not leak the fake 'static lifetime that we lied about earlier to the
138 // compiler. Since the lifetime 'a will not outlive our owned data it's
139 // safe to provide Face<'a>
140 #[inline]
141 #[allow(clippy::needless_lifetimes)] // explicit is nice as it's important 'static isn't leaked
142 fn inner_ref<'a>(self: &'a Pin<Box<Self>>) -> &'a ttf_parser::Face<'a> {
143 // Safety: if you have a ref `face` is always Some
144 unsafe { self.face.as_ref().unwrap_unchecked() }
145 }
146
147 fn into_vec(self: Pin<Box<Self>>) -> Vec<u8> {
148 // Safety: safe as `face` is dropped.
149 let mut me = unsafe { Pin::into_inner_unchecked(self) };
150 me.face.take(); // ensure dropped before taking `data`
151 mem::take(&mut me.data)
152 }
153}
154
155impl Drop for SelfRefVecFace {
156 fn drop(&mut self) {
157 self.face.take(); // ensure dropped before `data`
158 }
159}
160