fonts: Instantiate system fonts using system font loaders (#33747)

System fonts used to be instantiated using the system font loader and
this change restores that behavior. In addition, on macOS and FreeType
platforms font data for system fonts is loaded using memory mapping. The
benefit is that system font loaders typically are able to cache fonts in
system memory (using memory mapping, for instance) and we'd like to load
them in a the way most compatible with other applications.

On my Linux system, this manages to get the overhead of loading a very
large font down from 10ms to approximately 1ms. Subsequent runs show
even less overhead. We've measured similar gains on macOS systems.

Currently, system font data must be loaded into memory manually for
canvas and this is unlikely to change even with a switch to `vello`. The
use of explicit memmory mapping should help in this case -- though it
probably won't be possible to use this properly on macOS and Windows if
we ever want to load fonts from TTCs properly.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
This commit is contained in:
Martin Robinson 2024-10-10 16:09:51 -07:00 committed by GitHub
parent 4564ce2fcc
commit 0553789d48
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 771 additions and 810 deletions

View file

@ -20,33 +20,11 @@ use style::Atom;
use super::xml::{Attribute, Node};
use crate::{
FallbackFontSelectionOptions, FontIdentifier, FontTemplate, FontTemplateDescriptor,
LowercaseFontFamilyName,
LocalFontIdentifier, LowercaseFontFamilyName,
};
static FONT_LIST: LazyLock<FontList> = LazyLock::new(|| FontList::new());
/// An identifier for a local font on Android systems.
#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub struct LocalFontIdentifier {
/// The path to the font.
pub path: Atom,
}
impl LocalFontIdentifier {
pub(crate) fn index(&self) -> u32 {
0
}
pub(crate) fn read_data_from_file(&self) -> Vec<u8> {
let mut bytes = Vec::new();
File::open(Path::new(&*self.path))
.expect("Couldn't open font file!")
.read_to_end(&mut bytes)
.unwrap();
bytes
}
}
// Android doesn't provide an API to query system fonts until Android O:
// https://developer.android.com/reference/android/text/FontConfig.html
// System font configuration files must be parsed until Android O version is set as the minimum target.
@ -473,6 +451,7 @@ where
let mut produce_font = |font: &Font| {
let local_font_identifier = LocalFontIdentifier {
path: Atom::from(FontList::font_absolute_path(&font.filename)),
variation_index: 0,
};
let stretch = StyleFontStretch::NORMAL;
let weight = font

View file

@ -2,8 +2,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::ffi::CString;
use std::os::raw::c_long;
use std::sync::Arc;
use std::{mem, ptr};
use app_units::Au;
@ -11,10 +11,10 @@ use euclid::default::{Point2D, Rect, Size2D};
use freetype_sys::{
ft_sfnt_head, ft_sfnt_os2, FT_Byte, FT_Done_Face, FT_Error, FT_F26Dot6, FT_Face, FT_Fixed,
FT_Get_Char_Index, FT_Get_Kerning, FT_Get_Sfnt_Table, FT_GlyphSlot, FT_Int32, FT_Load_Glyph,
FT_Long, FT_MulFix, FT_New_Memory_Face, FT_Pos, FT_Select_Size, FT_Set_Char_Size, FT_Short,
FT_SizeRec, FT_Size_Metrics, FT_UInt, FT_ULong, FT_UShort, FT_Vector, FT_FACE_FLAG_COLOR,
FT_FACE_FLAG_FIXED_SIZES, FT_FACE_FLAG_SCALABLE, FT_KERNING_DEFAULT, FT_LOAD_COLOR,
FT_LOAD_DEFAULT, FT_LOAD_NO_HINTING, FT_STYLE_FLAG_ITALIC, TT_OS2,
FT_Long, FT_MulFix, FT_New_Face, FT_New_Memory_Face, FT_Pos, FT_Select_Size, FT_Set_Char_Size,
FT_Short, FT_SizeRec, FT_Size_Metrics, FT_UInt, FT_ULong, FT_UShort, FT_Vector,
FT_FACE_FLAG_COLOR, FT_FACE_FLAG_FIXED_SIZES, FT_FACE_FLAG_SCALABLE, FT_KERNING_DEFAULT,
FT_LOAD_COLOR, FT_LOAD_DEFAULT, FT_LOAD_NO_HINTING, FT_STYLE_FLAG_ITALIC, TT_OS2,
};
use log::debug;
use parking_lot::ReentrantMutex;
@ -25,12 +25,14 @@ use style::Zero;
use webrender_api::FontInstanceFlags;
use super::library_handle::FreeTypeLibraryHandle;
use super::LocalFontIdentifier;
use crate::font::{
FontMetrics, FontTableMethods, FontTableTag, FractionalPixel, PlatformFontMethods,
};
use crate::font_template::FontTemplateDescriptor;
use crate::glyph::GlyphId;
use crate::system_font_service::FontIdentifier;
use crate::FontData;
// This constant is not present in the freetype
// bindings due to bindgen not handling the way
@ -68,9 +70,6 @@ struct OS2Table {
#[derive(Debug)]
#[allow(unused)]
pub struct PlatformFont {
/// The font data itself, which must stay valid for the lifetime of the
/// platform [`FT_Face`].
font_data: Arc<Vec<u8>>,
face: ReentrantMutex<FT_Face>,
requested_face_size: Au,
actual_face_size: Au,
@ -98,37 +97,62 @@ impl Drop for PlatformFont {
}
}
fn create_face(data: Arc<Vec<u8>>, face_index: u32) -> Result<FT_Face, &'static str> {
unsafe {
let mut face: FT_Face = ptr::null_mut();
impl PlatformFontMethods for PlatformFont {
fn new_from_data(
_font_identifier: FontIdentifier,
font_data: &FontData,
requested_size: Option<Au>,
) -> Result<PlatformFont, &'static str> {
let library = FreeTypeLibraryHandle::get().lock();
// This is to support 32bit Android where FT_Long is defined as i32.
let result = FT_New_Memory_Face(
library.freetype_library,
data.as_ptr(),
data.len() as FT_Long,
face_index as FT_Long,
&mut face,
);
let data: &[u8] = font_data.as_ref();
let mut face: FT_Face = ptr::null_mut();
let result = unsafe {
FT_New_Memory_Face(
library.freetype_library,
data.as_ptr(),
data.len() as FT_Long,
0, /* face_index */
&mut face,
)
};
if 0 != result || face.is_null() {
return Err("Could not create FreeType face");
}
let (requested_face_size, actual_face_size) = match requested_size {
Some(requested_size) => (requested_size, face.set_size(requested_size)?),
None => (Au::zero(), Au::zero()),
};
Ok(PlatformFont {
face: ReentrantMutex::new(face),
requested_face_size,
actual_face_size,
})
}
fn new_from_local_font_identifier(
font_identifier: LocalFontIdentifier,
requested_size: Option<Au>,
) -> Result<PlatformFont, &'static str> {
let mut face: FT_Face = ptr::null_mut();
let library = FreeTypeLibraryHandle::get().lock();
let filename = CString::new(&*font_identifier.path).expect("filename contains NUL byte!");
let result = unsafe {
FT_New_Face(
library.freetype_library,
filename.as_ptr(),
font_identifier.index() as FT_Long,
&mut face,
)
};
if 0 != result || face.is_null() {
return Err("Could not create FreeType face");
}
Ok(face)
}
}
impl PlatformFontMethods for PlatformFont {
fn new_from_data(
_font_identifier: FontIdentifier,
data: Arc<Vec<u8>>,
face_index: u32,
requested_size: Option<Au>,
) -> Result<PlatformFont, &'static str> {
let face = create_face(data.clone(), face_index)?;
let (requested_face_size, actual_face_size) = match requested_size {
Some(requested_size) => (requested_size, face.set_size(requested_size)?),
None => (Au::zero(), Au::zero()),
@ -136,7 +160,6 @@ impl PlatformFontMethods for PlatformFont {
Ok(PlatformFont {
face: ReentrantMutex::new(face),
font_data: data,
requested_face_size,
actual_face_size,
})

View file

@ -2,11 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::convert::TryInto;
use std::ffi::CString;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::ptr;
use base::text::{UnicodeBlock, UnicodeBlockMethod};
@ -25,14 +21,12 @@ use fontconfig_sys::{
};
use libc::{c_char, c_int};
use log::debug;
use malloc_size_of_derive::MallocSizeOf;
use serde::{Deserialize, Serialize};
use style::values::computed::font::GenericFontFamily;
use style::values::computed::{FontStretch, FontStyle, FontWeight};
use style::Atom;
use unicode_script::Script;
use super::c_str_to_string;
use super::{c_str_to_string, LocalFontIdentifier};
use crate::font::map_platform_values_to_style_values;
use crate::font_template::{FontTemplate, FontTemplateDescriptor};
use crate::platform::add_noto_fallback_families;
@ -41,30 +35,6 @@ use crate::{
LowercaseFontFamilyName,
};
/// An identifier for a local font on systems using Freetype.
#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub struct LocalFontIdentifier {
/// The path to the font.
pub path: Atom,
/// The variation index within the font.
pub variation_index: i32,
}
impl LocalFontIdentifier {
pub(crate) fn index(&self) -> u32 {
self.variation_index.try_into().unwrap()
}
pub(crate) fn read_data_from_file(&self) -> Vec<u8> {
let mut bytes = Vec::new();
File::open(Path::new(&*self.path))
.expect("Couldn't open font file!")
.read_to_end(&mut bytes)
.unwrap();
bytes
}
}
pub fn for_each_available_family<F>(mut callback: F)
where
F: FnMut(String),

View file

@ -0,0 +1,74 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::convert::TryInto;
use std::ffi::CStr;
use std::fs::File;
use std::path::{Path, PathBuf};
use std::str;
use libc::c_char;
use malloc_size_of_derive::MallocSizeOf;
use memmap2::Mmap;
use serde::{Deserialize, Serialize};
use style::Atom;
use webrender_api::NativeFontHandle;
/// Creates a String from the given null-terminated buffer.
/// Panics if the buffer does not contain UTF-8.
unsafe fn c_str_to_string(s: *const c_char) -> String {
str::from_utf8(CStr::from_ptr(s).to_bytes())
.unwrap()
.to_owned()
}
pub mod font;
#[cfg(all(target_os = "linux", not(target_env = "ohos"), not(ohos_mock)))]
pub mod font_list;
#[cfg(target_os = "android")]
mod android {
pub mod font_list;
mod xml;
}
#[cfg(target_os = "android")]
pub use self::android::font_list;
#[cfg(any(target_env = "ohos", ohos_mock))]
mod ohos {
pub mod font_list;
}
#[cfg(any(target_env = "ohos", ohos_mock))]
pub use self::ohos::font_list;
mod library_handle;
/// An identifier for a local font on systems using Freetype.
#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub struct LocalFontIdentifier {
/// The path to the font.
pub path: Atom,
/// The variation index within the font.
pub variation_index: i32,
}
impl LocalFontIdentifier {
pub(crate) fn index(&self) -> u32 {
self.variation_index.try_into().unwrap()
}
pub(crate) fn native_font_handle(&self) -> NativeFontHandle {
NativeFontHandle {
path: PathBuf::from(&*self.path),
index: self.variation_index as u32,
}
}
pub(crate) fn read_data_from_file(&self) -> Option<Vec<u8>> {
let file = File::open(Path::new(&*self.path)).ok()?;
let mmap = unsafe { Mmap::map(&file).ok()? };
Some((&mmap[..]).to_vec())
}
}

View file

@ -23,7 +23,7 @@ use unicode_script::Script;
use crate::{
EmojiPresentationPreference, FallbackFontSelectionOptions, FontIdentifier, FontTemplate,
FontTemplateDescriptor, LowercaseFontFamilyName,
FontTemplateDescriptor, LocalFontIdentifier, LowercaseFontFamilyName,
};
static FONT_LIST: LazyLock<FontList> = LazyLock::new(|| FontList::new());
@ -37,28 +37,6 @@ static OHOS_FONTS_DIR: &'static str = env!("OHOS_SDK_FONTS_DIR");
#[cfg(not(ohos_mock))]
static OHOS_FONTS_DIR: &'static str = "/system/fonts";
/// An identifier for a local font on OpenHarmony systems.
#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
pub struct LocalFontIdentifier {
/// The path to the font.
pub path: Atom,
}
impl LocalFontIdentifier {
pub(crate) fn index(&self) -> u32 {
0
}
pub(crate) fn read_data_from_file(&self) -> Vec<u8> {
let mut bytes = Vec::new();
File::open(Path::new(&*self.path))
.expect("Couldn't open font file!")
.read_to_end(&mut bytes)
.unwrap();
bytes
}
}
#[allow(unused)]
#[derive(Clone, Copy, Debug, Default)]
// HarmonyOS only comes in Condensed and Normal variants
@ -473,6 +451,7 @@ where
let mut produce_font = |font: &Font| {
let local_font_identifier = LocalFontIdentifier {
path: Atom::from(font.filepath.clone()),
variation_index: 0,
};
let stretch = font.width.into();
let weight = font

View file

@ -17,6 +17,7 @@ use core_text::font_descriptor::kCTFontURLAttribute;
use parking_lot::RwLock;
use crate::system_font_service::FontIdentifier;
use crate::FontData;
/// A cache of `CTFont` to avoid having to create `CTFont` instances over and over. It is
/// always possible to create a `CTFont` using a `FontTemplate` even if it isn't in this
@ -33,7 +34,7 @@ type CachedCTFont = HashMap<Au, CTFont>;
impl CoreTextFontCache {
pub(crate) fn core_text_font(
font_identifier: FontIdentifier,
data: Arc<Vec<u8>>,
data: Option<&FontData>,
pt_size: f64,
) -> Option<CTFont> {
//// If you pass a zero font size to one of the Core Text APIs, it'll replace it with
@ -86,8 +87,11 @@ impl CoreTextFontCache {
core_text::font::new_from_descriptor(&descriptor, clamped_pt_size)
},
FontIdentifier::Web(_) | FontIdentifier::Mock(_) => {
let provider = CGDataProvider::from_buffer(data);
FontIdentifier::Web(_) => {
let data = data
.expect("Should always have FontData for web fonts")
.clone();
let provider = CGDataProvider::from_buffer(Arc::new(data));
let cgfont = CGFont::from_data_provider(provider).ok()?;
core_text::font::new_from_CGFont(&cgfont, clamped_pt_size)
},

View file

@ -4,7 +4,6 @@
use std::cmp::Ordering;
use std::ops::Range;
use std::sync::Arc;
use std::{fmt, ptr};
/// Implementation of Quartz (CoreGraphics) fonts.
@ -23,8 +22,9 @@ use style::values::computed::font::{FontStretch, FontStyle, FontWeight};
use webrender_api::FontInstanceFlags;
use super::core_text_font_cache::CoreTextFontCache;
use super::font_list::LocalFontIdentifier;
use crate::{
map_platform_values_to_style_values, FontIdentifier, FontMetrics, FontTableMethods,
map_platform_values_to_style_values, FontData, FontIdentifier, FontMetrics, FontTableMethods,
FontTableTag, FontTemplateDescriptor, FractionalPixel, GlyphId, PlatformFontMethods, CBDT,
COLR, KERN, SBIX,
};
@ -55,9 +55,6 @@ impl FontTableMethods for FontTable {
#[derive(Debug)]
pub struct PlatformFont {
ctfont: CTFont,
/// A reference to this data used to create this [`PlatformFont`], ensuring the
/// data stays alive of the lifetime of this struct.
_data: Arc<Vec<u8>>,
h_kern_subtable: Option<CachedKernTable>,
}
@ -167,31 +164,45 @@ impl fmt::Debug for CachedKernTable {
}
}
impl PlatformFontMethods for PlatformFont {
fn new_from_data(
impl PlatformFont {
fn new(
font_identifier: FontIdentifier,
data: Arc<Vec<u8>>,
_face_index: u32,
pt_size: Option<Au>,
data: Option<&FontData>,
requested_size: Option<Au>,
) -> Result<PlatformFont, &'static str> {
let size = match pt_size {
let size = match requested_size {
Some(s) => s.to_f64_px(),
None => 0.0,
};
let Some(core_text_font) =
CoreTextFontCache::core_text_font(font_identifier, data.clone(), size)
let Some(core_text_font) = CoreTextFontCache::core_text_font(font_identifier, data, size)
else {
return Err("Could not generate CTFont for FontTemplateData");
};
let mut handle = PlatformFont {
_data: data,
ctfont: core_text_font.clone_with_font_size(size),
h_kern_subtable: None,
};
handle.h_kern_subtable = handle.find_h_kern_subtable();
Ok(handle)
}
}
impl PlatformFontMethods for PlatformFont {
fn new_from_data(
font_identifier: FontIdentifier,
data: &FontData,
requested_size: Option<Au>,
) -> Result<PlatformFont, &'static str> {
Self::new(font_identifier, Some(data), requested_size)
}
fn new_from_local_font_identifier(
font_identifier: LocalFontIdentifier,
requested_size: Option<Au>,
) -> Result<PlatformFont, &'static str> {
Self::new(FontIdentifier::Local(font_identifier), None, requested_size)
}
fn descriptor(&self) -> FontTemplateDescriptor {
let traits = self.ctfont.all_traits();

View file

@ -3,12 +3,12 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::fs::File;
use std::io::Read;
use std::path::Path;
use base::text::{unicode_plane, UnicodeBlock, UnicodeBlockMethod};
use log::debug;
use malloc_size_of_derive::MallocSizeOf;
use memmap2::Mmap;
use serde::{Deserialize, Serialize};
use style::values::computed::font::GenericFontFamily;
use style::Atom;
@ -43,13 +43,16 @@ impl LocalFontIdentifier {
0
}
pub(crate) fn read_data_from_file(&self) -> Vec<u8> {
let mut bytes = Vec::new();
File::open(Path::new(&*self.path))
.expect("Couldn't open font file!")
.read_to_end(&mut bytes)
.unwrap();
bytes
pub(crate) fn read_data_from_file(&self) -> Option<Vec<u8>> {
// TODO: This is incorrect, if the font file is a TTC (collection) with more than
// one font. In that case we either need to reconstruct the pertinent tables into
// a bundle of font data (expensive) or make sure that the value returned by
// `index()` above is correct. The latter is potentially tricky as macOS might not
// do an accurate mapping between the PostScript name that it gives us and what is
// listed in the font.
let file = File::open(Path::new(&*self.path)).ok()?;
let mmap = unsafe { Mmap::map(&file).ok()? };
Some((&mmap[..]).to_vec())
}
}

View file

@ -8,49 +8,18 @@ use base::text::{UnicodeBlock, UnicodeBlockMethod};
use unicode_script::Script;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub use crate::platform::freetype::{font, font_list, library_handle};
pub use crate::platform::freetype::{font, font_list, LocalFontIdentifier};
#[cfg(target_os = "macos")]
pub use crate::platform::macos::{core_text_font_cache, font, font_list};
pub use crate::platform::macos::{
core_text_font_cache, font, font_list, font_list::LocalFontIdentifier,
};
#[cfg(target_os = "windows")]
pub use crate::platform::windows::{font, font_list};
pub use crate::platform::windows::{font, font_list, font_list::LocalFontIdentifier};
#[cfg(any(target_os = "linux", target_os = "macos"))]
use crate::FallbackFontSelectionOptions;
#[cfg(any(target_os = "linux", target_os = "android"))]
mod freetype {
use std::ffi::CStr;
use std::str;
use libc::c_char;
/// Creates a String from the given null-terminated buffer.
/// Panics if the buffer does not contain UTF-8.
unsafe fn c_str_to_string(s: *const c_char) -> String {
str::from_utf8(CStr::from_ptr(s).to_bytes())
.unwrap()
.to_owned()
}
pub mod font;
#[cfg(all(target_os = "linux", not(target_env = "ohos"), not(ohos_mock)))]
pub mod font_list;
#[cfg(target_os = "android")]
mod android {
pub mod font_list;
mod xml;
}
#[cfg(target_os = "android")]
pub use self::android::font_list;
#[cfg(any(target_env = "ohos", ohos_mock))]
mod ohos {
pub mod font_list;
}
#[cfg(any(target_env = "ohos", ohos_mock))]
pub use self::ohos::font_list;
pub mod library_handle;
}
pub mod freetype;
#[cfg(target_os = "macos")]
mod macos {

View file

@ -13,7 +13,7 @@ use std::ops::Deref;
use std::sync::Arc;
use app_units::Au;
use dwrote::{FontFace, FontFile};
use dwrote::{FontCollection, FontFace, FontFile};
use euclid::default::{Point2D, Rect, Size2D};
use log::{debug, warn};
use style::computed_values::font_stretch::T as StyleFontStretch;
@ -24,9 +24,10 @@ use truetype::tables::WindowsMetrics;
use truetype::value::Read;
use webrender_api::FontInstanceFlags;
use super::font_list::LocalFontIdentifier;
use crate::{
ot_tag, FontIdentifier, FontMetrics, FontTableMethods, FontTableTag, FontTemplateDescriptor,
FractionalPixel, GlyphId, PlatformFontMethods,
ot_tag, FontData, FontIdentifier, FontMetrics, FontTableMethods, FontTableTag,
FontTemplateDescriptor, FractionalPixel, GlyphId, PlatformFontMethods,
};
// 1em = 12pt = 16px, assuming 72 points per inch and 96 px per inch
@ -64,9 +65,6 @@ impl FontTableMethods for FontTable {
#[derive(Debug)]
pub struct PlatformFont {
face: Nondebug<FontFace>,
/// A reference to this data used to create this [`PlatformFont`], ensuring the
/// data stays alive of the lifetime of this struct.
_data: Arc<Vec<u8>>,
em_size: f32,
du_to_px: f32,
scaled_du_to_px: f32,
@ -94,20 +92,10 @@ impl<T> Deref for Nondebug<T> {
}
}
impl PlatformFontMethods for PlatformFont {
fn new_from_data(
_font_identifier: FontIdentifier,
data: Arc<Vec<u8>>,
face_index: u32,
pt_size: Option<Au>,
) -> Result<Self, &'static str> {
let font_file = FontFile::new_from_data(data.clone()).ok_or("Could not create FontFile")?;
let face = font_file
.create_face(face_index, dwrote::DWRITE_FONT_SIMULATIONS_NONE)
.map_err(|_| "Could not create FontFace")?;
impl PlatformFont {
fn new(font_face: FontFace, pt_size: Option<Au>) -> Result<Self, &'static str> {
let pt_size = pt_size.unwrap_or(au_from_pt(12.));
let du_per_em = face.metrics().metrics0().designUnitsPerEm as f32;
let du_per_em = font_face.metrics().metrics0().designUnitsPerEm as f32;
let em_size = pt_size.to_f32_px() / 16.;
let design_units_per_pixel = du_per_em / 16.;
@ -116,13 +104,40 @@ impl PlatformFontMethods for PlatformFont {
let scaled_design_units_to_pixels = em_size / design_units_per_pixel;
Ok(PlatformFont {
face: Nondebug(face),
_data: data,
face: Nondebug(font_face),
em_size,
du_to_px: design_units_to_pixels,
scaled_du_to_px: scaled_design_units_to_pixels,
})
}
}
impl PlatformFontMethods for PlatformFont {
fn new_from_data(
_font_identifier: FontIdentifier,
data: &FontData,
pt_size: Option<Au>,
) -> Result<Self, &'static str> {
let font_face = FontFile::new_from_buffer(Arc::new(data.clone()))
.ok_or("Could not create FontFile")?
.create_face(
0, /* face_index */
dwrote::DWRITE_FONT_SIMULATIONS_NONE,
)
.map_err(|_| "Could not create FontFace")?;
Self::new(font_face, pt_size)
}
fn new_from_local_font_identifier(
font_identifier: LocalFontIdentifier,
pt_size: Option<Au>,
) -> Result<PlatformFont, &'static str> {
let font_face = FontCollection::system()
.get_font_from_descriptor(&font_identifier.font_descriptor)
.ok_or("Could not create Font from descriptor")?
.create_font_face();
Self::new(font_face, pt_size)
}
fn descriptor(&self) -> FontTemplateDescriptor {
// We need the font (DWriteFont) in order to be able to query things like

View file

@ -12,6 +12,7 @@ use serde::{Deserialize, Serialize};
use style::values::computed::font::GenericFontFamily;
use style::values::computed::{FontStyle as StyleFontStyle, FontWeight as StyleFontWeight};
use style::values::specified::font::FontStretchKeyword;
use webrender_api::NativeFontHandle;
use crate::{
EmojiPresentationPreference, FallbackFontSelectionOptions, FontIdentifier, FontTemplate,
@ -43,14 +44,29 @@ impl LocalFontIdentifier {
.map_or(0, |font| font.create_font_face().get_index())
}
pub(crate) fn read_data_from_file(&self) -> Vec<u8> {
let font = FontCollection::system()
pub(crate) fn native_font_handle(&self) -> NativeFontHandle {
let face = FontCollection::system()
.get_font_from_descriptor(&self.font_descriptor)
.unwrap();
.expect("Could not create Font from FontDescriptor")
.create_font_face();
let path = face
.get_files()
.first()
.expect("Could not get FontFace files")
.get_font_file_path()
.expect("Could not get FontFace files path");
NativeFontHandle {
path,
index: face.get_index(),
}
}
pub(crate) fn read_data_from_file(&self) -> Option<Vec<u8>> {
let font = FontCollection::system().get_font_from_descriptor(&self.font_descriptor)?;
let face = font.create_font_face();
let files = face.get_files();
assert!(!files.is_empty());
files[0].get_font_file_bytes()
Some(files[0].get_font_file_bytes())
}
}