Skip to content

Commit

Permalink
Allow handles to store native fonts and return those from 'Handle::lo…
Browse files Browse the repository at this point in the history
…ad' if possible.

This fixes another chokepoint in Iosevka loading, as we were needlessly reading fonts from disk and stuff with load, whereas we've already had a font at our disposal before creating a handle. That seemed wasteful.
Note that I did cargo check --all-features this code, but I am only sure of coretext part compiling. If we pursue cross-platform support, we'll need to revisit this (probably). The idea from this commit is not specific to this commit though.
  • Loading branch information
osiewicz committed Jan 15, 2024
1 parent 5ba9505 commit b9a336e
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 47 deletions.
23 changes: 23 additions & 0 deletions src/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
//!
//! To open the font referenced by a handle, use a loader.
use std::any::Any;
use std::path::PathBuf;
use std::sync::Arc;

use crate::error::FontLoadingError;
use crate::font::Font;
use crate::loader::Loader;

/// Encapsulates the information needed to locate and open a font.
///
Expand All @@ -45,6 +47,11 @@ pub enum Handle {
/// If the memory consists of a single font, this value will be 0.
font_index: u32,
},
/// An already-loaded font.
Native {
/// Type-erased font storage. Use [`Self::from_native`] to retrieve the font object.
inner: Arc<dyn Any + Send + Sync>,
},
}

impl Handle {
Expand All @@ -66,6 +73,22 @@ impl Handle {
Handle::Memory { bytes, font_index }
}

/// Creates a new handle from a system handle.
pub fn from_native<T: Loader>(inner: &T) -> Self {
Self::Native {
inner: Arc::new(inner.native_font()),
}
}
/// Retrieves a handle to the font object.
///
/// May return None if inner object is not of type `T` or if this handle does not contain a native font object.
pub fn native_as<T: 'static + Send + Sync>(&self) -> Option<&T> {
if let Self::Native { inner } = self {
inner.downcast_ref()
} else {
None
}
}
/// A convenience method to load this handle with the default loader, producing a Font.
#[inline]
pub fn load(&self) -> Result<Font, FontLoadingError> {
Expand Down
24 changes: 13 additions & 11 deletions src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use log::warn;
use pathfinder_geometry::rect::{RectF, RectI};
use pathfinder_geometry::transform2d::Transform2F;
use pathfinder_geometry::vector::Vector2F;
use std::convert::TryFrom;
use std::sync::Arc;

use crate::canvas::{Canvas, RasterizationOptions};
Expand All @@ -35,7 +36,7 @@ use std::path::Path;
/// fonts.
pub trait Loader: Clone + Sized {
/// The handle that the API natively uses to represent a font.
type NativeFont;
type NativeFont: 'static + Send + Sync;

/// Loads a font from raw font data (the contents of a `.ttf`/`.otf`/etc. file).
///
Expand Down Expand Up @@ -63,22 +64,23 @@ pub trait Loader: Clone + Sized {
}

/// Creates a font from a native API handle.
unsafe fn from_native_font(native_font: Self::NativeFont) -> Self;
unsafe fn from_native_font(native_font: &Self::NativeFont) -> Self;

/// Loads the font pointed to by a handle.
fn from_handle(handle: &Handle) -> Result<Self, FontLoadingError> {
match *handle {
Handle::Memory {
ref bytes,
font_index,
} => Self::from_bytes((*bytes).clone(), font_index),
match handle {
Handle::Memory { bytes, font_index } => Self::from_bytes((*bytes).clone(), *font_index),
#[cfg(not(target_arch = "wasm32"))]
Handle::Path {
ref path,
font_index,
} => Self::from_path(path, font_index),
Handle::Path { path, font_index } => Self::from_path(path, *font_index),
#[cfg(target_arch = "wasm32")]
Handle::Path { .. } => Err(FontLoadingError::NoFilesystem),
Handle::Native { .. } => {
if let Some(native) = handle.native_as::<Self::NativeFont>() {
unsafe { Ok(Self::from_native_font(native)) }
} else {
Err(FontLoadingError::UnknownFormat)
}
}
}
}

Expand Down
27 changes: 3 additions & 24 deletions src/loaders/core_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ impl Font {
}

/// Creates a font from a native API handle.
pub unsafe fn from_native_font(core_text_font: NativeFont) -> Font {
Font::from_core_text_font_no_path(core_text_font)
pub unsafe fn from_native_font(core_text_font: &NativeFont) -> Font {
Font::from_core_text_font_no_path(core_text_font.clone())
}
/// Creates a font from a native API handle, without performing a lookup on the disk.
pub unsafe fn from_core_text_font_no_path(core_text_font: NativeFont) -> Font {
Expand All @@ -132,27 +132,6 @@ impl Font {
font_data: FontData::Unavailable,
}
}
unsafe fn from_core_text_font(core_text_font: NativeFont) -> Font {
let mut font_data = FontData::Unavailable;
match core_text_font.url() {
None => warn!("No URL found for Core Text font!"),
Some(url) => match url.to_path() {
Some(path) => match File::open(path) {
Ok(ref mut file) => match utils::slurp_file(file) {
Ok(data) => font_data = FontData::Memory(Arc::new(data)),
Err(_) => warn!("Couldn't read file data for Core Text font!"),
},
Err(_) => warn!("Could not open file for Core Text font!"),
},
None => warn!("Could not convert URL from Core Text font to path!"),
},
}

Font {
core_text_font,
font_data,
}
}

/// Creates a font from a Core Graphics font handle.
///
Expand Down Expand Up @@ -637,7 +616,7 @@ impl Loader for Font {
}

#[inline]
unsafe fn from_native_font(native_font: Self::NativeFont) -> Self {
unsafe fn from_native_font(native_font: &Self::NativeFont) -> Self {
Font::from_native_font(native_font)
}

Expand Down
5 changes: 3 additions & 2 deletions src/loaders/directwrite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ impl Font {

/// Creates a font from a native API handle.
#[inline]
pub unsafe fn from_native_font(native_font: NativeFont) -> Font {
pub unsafe fn from_native_font(native_font: &NativeFont) -> Font {
let native_font = native_font.clone();
Font {
dwrite_font: native_font.dwrite_font,
dwrite_font_face: native_font.dwrite_font_face,
Expand Down Expand Up @@ -747,7 +748,7 @@ impl Loader for Font {
}

#[inline]
unsafe fn from_native_font(native_font: Self::NativeFont) -> Self {
unsafe fn from_native_font(native_font: &Self::NativeFont) -> Self {
Font::from_native_font(native_font)
}

Expand Down
5 changes: 3 additions & 2 deletions src/loaders/freetype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,10 @@ impl Font {
}

/// Creates a font from a native API handle.
pub unsafe fn from_native_font(freetype_face: NativeFont) -> Font {
pub unsafe fn from_native_font(freetype_face: &NativeFont) -> Font {
// We make an in-memory copy of the underlying font data. This is because the native font
// does not necessarily hold a strong reference to the memory backing it.
let freetype_face = *freetype_face;
const CHUNK_SIZE: usize = 4096;
let mut font_data = vec![];
loop {
Expand Down Expand Up @@ -1013,7 +1014,7 @@ impl Loader for Font {
}

#[inline]
unsafe fn from_native_font(native_font: Self::NativeFont) -> Self {
unsafe fn from_native_font(native_font: &Self::NativeFont) -> Self {
Font::from_native_font(native_font)
}

Expand Down
10 changes: 2 additions & 8 deletions src/sources/core_text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,6 @@ fn css_stretchiness_to_core_text_width(css_stretchiness: Stretch) -> f32 {
0.25 * core_text_loader::piecewise_linear_find_index(css_stretchiness, &Stretch::MAPPING) - 1.0
}

#[derive(Clone)]
struct FontDataInfo {
data: Arc<Vec<u8>>,
file_type: FileType,
}

fn create_handles_from_core_text_collection(
collection: CTFontCollection,
) -> Result<Vec<Handle>, SelectionError> {
Expand All @@ -169,8 +163,8 @@ fn create_handles_from_core_text_collection(
let descriptor = descriptors.get(index).unwrap();
let native = new_from_descriptor(&descriptor, 16.);
let font = unsafe { Font::from_core_text_font_no_path(native.clone()) };
todo!();
//fonts.push(Handle::from(font));

fonts.push(Handle::from_native(&font));
}
}
if fonts.is_empty() {
Expand Down

0 comments on commit b9a336e

Please sign in to comment.