2022-10-24 08:56:48 -06:00
|
|
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
2022-11-15 12:26:59 -07:00
|
|
|
pub(crate) mod fallback;
|
2022-10-18 17:13:48 -06:00
|
|
|
|
2023-03-14 00:39:50 +01:00
|
|
|
use alloc::sync::Arc;
|
2023-03-02 18:16:57 -07:00
|
|
|
|
2022-10-18 12:07:22 -06:00
|
|
|
pub use self::system::*;
|
|
|
|
|
mod system;
|
2022-11-15 12:26:59 -07:00
|
|
|
|
2023-01-29 22:29:17 -03:30
|
|
|
/// A font
|
2023-03-12 10:23:54 +01:00
|
|
|
pub struct Font(FontInner);
|
|
|
|
|
|
|
|
|
|
#[ouroboros::self_referencing]
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
struct FontInner {
|
2023-03-14 00:39:50 +01:00
|
|
|
id: fontdb::ID,
|
|
|
|
|
data: Arc<dyn AsRef<[u8]> + Send + Sync>,
|
|
|
|
|
#[borrows(data)]
|
2023-03-12 10:23:54 +01:00
|
|
|
#[covariant]
|
|
|
|
|
rustybuzz: rustybuzz::Face<'this>,
|
|
|
|
|
// workaround, since ouroboros does not work with #[cfg(feature = "swash")]
|
|
|
|
|
swash: SwashKey,
|
2022-11-15 12:26:59 -07:00
|
|
|
}
|
|
|
|
|
|
2023-03-12 10:23:54 +01:00
|
|
|
#[cfg(feature = "swash")]
|
|
|
|
|
pub type SwashKey = (u32, swash::CacheKey);
|
|
|
|
|
|
|
|
|
|
#[cfg(not(feature = "swash"))]
|
|
|
|
|
pub type SwashKey = ();
|
|
|
|
|
|
|
|
|
|
impl Font {
|
|
|
|
|
pub fn new(info: &fontdb::FaceInfo) -> Option<Self> {
|
|
|
|
|
#[allow(unused_variables)]
|
2022-11-15 12:26:59 -07:00
|
|
|
let data = match &info.source {
|
2023-03-14 00:39:50 +01:00
|
|
|
fontdb::Source::Binary(data) => Arc::clone(data),
|
2022-11-15 12:26:59 -07:00
|
|
|
#[cfg(feature = "std")]
|
|
|
|
|
fontdb::Source::File(path) => {
|
|
|
|
|
log::warn!("Unsupported fontdb Source::File('{}')", path.display());
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
#[cfg(feature = "std")]
|
2023-03-14 00:39:50 +01:00
|
|
|
fontdb::Source::SharedFile(_path, data) => Arc::clone(data),
|
2022-11-15 12:26:59 -07:00
|
|
|
};
|
2023-03-12 10:23:54 +01:00
|
|
|
Some(Self(
|
|
|
|
|
FontInnerTryBuilder {
|
2023-03-14 00:39:50 +01:00
|
|
|
id: info.id,
|
2023-03-12 10:23:54 +01:00
|
|
|
swash: {
|
|
|
|
|
#[cfg(feature = "swash")]
|
|
|
|
|
let swash = {
|
|
|
|
|
let swash =
|
|
|
|
|
swash::FontRef::from_index((*data).as_ref(), info.index as usize)?;
|
|
|
|
|
(swash.offset, swash.key)
|
|
|
|
|
};
|
|
|
|
|
#[cfg(not(feature = "swash"))]
|
|
|
|
|
let swash = ();
|
|
|
|
|
swash
|
|
|
|
|
},
|
2023-03-14 00:39:50 +01:00
|
|
|
data,
|
|
|
|
|
rustybuzz_builder: |data| {
|
|
|
|
|
rustybuzz::Face::from_slice((**data).as_ref(), info.index).ok_or(())
|
2023-03-12 10:23:54 +01:00
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
.try_build()
|
|
|
|
|
.ok()?,
|
|
|
|
|
))
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-14 00:39:50 +01:00
|
|
|
pub fn id(&self) -> fontdb::ID {
|
|
|
|
|
*self.0.borrow_id()
|
2023-03-12 10:23:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn data(&self) -> &[u8] {
|
2023-03-14 00:39:50 +01:00
|
|
|
(**self.0.borrow_data()).as_ref()
|
2023-03-12 10:23:54 +01:00
|
|
|
}
|
2022-11-15 12:26:59 -07:00
|
|
|
|
2023-03-12 10:23:54 +01:00
|
|
|
pub fn rustybuzz(&self) -> &rustybuzz::Face {
|
|
|
|
|
self.0.borrow_rustybuzz()
|
2022-11-15 12:26:59 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "swash")]
|
|
|
|
|
pub fn as_swash(&self) -> swash::FontRef {
|
2023-03-12 10:23:54 +01:00
|
|
|
let swash = self.0.borrow_swash();
|
2022-11-15 12:26:59 -07:00
|
|
|
swash::FontRef {
|
2023-03-14 00:39:50 +01:00
|
|
|
data: self.data(),
|
2023-03-12 10:23:54 +01:00
|
|
|
offset: swash.0,
|
|
|
|
|
key: swash.1,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This is used to prevent warnings due to the swash field being unused.
|
|
|
|
|
#[cfg(not(feature = "swash"))]
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
fn as_swash(&self) {
|
|
|
|
|
self.0.borrow_swash();
|
|
|
|
|
}
|
|
|
|
|
}
|