aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--components/gfx/Cargo.toml1
-rw-r--r--components/gfx/font.rs2
-rw-r--r--components/gfx/font_cache_thread.rs13
-rw-r--r--components/gfx/font_context.rs18
-rw-r--r--components/gfx/font_template.rs18
-rw-r--r--components/gfx/platform/freetype/font.rs37
-rw-r--r--components/gfx/platform/freetype/font_context.rs136
-rw-r--r--components/gfx/platform/freetype/library_handle.rs116
-rw-r--r--components/gfx/platform/macos/font.rs2
-rw-r--r--components/gfx/platform/macos/font_context.rs17
-rw-r--r--components/gfx/platform/mod.rs13
-rw-r--r--components/gfx/platform/windows/font.rs2
-rw-r--r--components/gfx/platform/windows/font_context.rs10
-rw-r--r--components/gfx/tests/font_context.rs8
-rw-r--r--components/gfx/tests/font_template.rs5
16 files changed, 152 insertions, 247 deletions
diff --git a/Cargo.lock b/Cargo.lock
index a9b79df93cf..f2278ff4d7b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1949,6 +1949,7 @@ dependencies = [
"log",
"malloc_size_of",
"net_traits",
+ "parking_lot",
"range",
"serde",
"servo_allocator",
diff --git a/components/gfx/Cargo.toml b/components/gfx/Cargo.toml
index 114e727d041..976687b953e 100644
--- a/components/gfx/Cargo.toml
+++ b/components/gfx/Cargo.toml
@@ -27,6 +27,7 @@ libc = { workspace = true }
log = { workspace = true }
malloc_size_of = { workspace = true }
net_traits = { workspace = true }
+parking_lot = { workspace = true }
range = { path = "../range" }
serde = { workspace = true }
servo_arc = { workspace = true }
diff --git a/components/gfx/font.rs b/components/gfx/font.rs
index 6916b2e5261..f01f916d4ba 100644
--- a/components/gfx/font.rs
+++ b/components/gfx/font.rs
@@ -28,7 +28,6 @@ use crate::font_cache_thread::FontIdentifier;
use crate::font_context::{FontContext, FontSource};
use crate::font_template::FontTemplateDescriptor;
use crate::platform::font::{FontHandle, FontTable};
-use crate::platform::font_context::FontContextHandle;
pub use crate::platform::font_list::fallback_font_families;
use crate::platform::font_template::FontTemplateData;
use crate::text::glyph::{ByteIndex, GlyphData, GlyphId, GlyphStore};
@@ -56,7 +55,6 @@ static TEXT_SHAPING_PERFORMANCE_COUNTER: AtomicUsize = AtomicUsize::new(0);
pub trait FontHandleMethods: Sized {
fn new_from_template(
- fctx: &FontContextHandle,
template: Arc<FontTemplateData>,
pt_size: Option<Au>,
) -> Result<Self, &'static str>;
diff --git a/components/gfx/font_cache_thread.rs b/components/gfx/font_cache_thread.rs
index 5808295a4a3..a5c6a2b0974 100644
--- a/components/gfx/font_cache_thread.rs
+++ b/components/gfx/font_cache_thread.rs
@@ -26,7 +26,6 @@ use webrender_api::{FontInstanceKey, FontKey};
use crate::font::{FontFamilyDescriptor, FontFamilyName, FontSearchScope};
use crate::font_context::FontSource;
use crate::font_template::{FontTemplate, FontTemplateDescriptor};
-use crate::platform::font_context::FontContextHandle;
use crate::platform::font_list::{
for_each_available_family, for_each_variation, system_default_family, LocalFontIdentifier,
SANS_SERIF_FONT_FAMILY,
@@ -75,13 +74,12 @@ impl FontTemplates {
pub fn find_font_for_style(
&mut self,
desc: &FontTemplateDescriptor,
- fctx: &FontContextHandle,
) -> Option<Arc<FontTemplateData>> {
// TODO(Issue #189): optimize lookup for
// regular/bold/italic/bolditalic with fixed offsets and a
// static decision table for fallback between these values.
for template in &mut self.templates {
- let maybe_template = template.data_for_descriptor(fctx, desc);
+ let maybe_template = template.data_for_descriptor(desc);
if maybe_template.is_some() {
return maybe_template;
}
@@ -91,8 +89,7 @@ impl FontTemplates {
// TODO(#190): Do a better job.
let (mut best_template_data, mut best_distance) = (None, f32::MAX);
for template in &mut self.templates {
- if let Some((template_data, distance)) =
- template.data_for_approximate_descriptor(fctx, desc)
+ if let Some((template_data, distance)) = template.data_for_approximate_descriptor(desc)
{
if distance < best_distance {
best_template_data = Some(template_data);
@@ -159,7 +156,6 @@ struct FontCache {
generic_fonts: HashMap<FontFamilyName, LowercaseString>,
local_families: HashMap<LowercaseString, FontTemplates>,
web_families: HashMap<LowercaseString, FontTemplates>,
- font_context: FontContextHandle,
core_resource_thread: CoreResourceThread,
webrender_api: Box<dyn WebrenderApi>,
webrender_fonts: HashMap<FontIdentifier, FontKey>,
@@ -404,7 +400,7 @@ impl FontCache {
// TODO(Issue #192: handle generic font families, like 'serif' and 'sans-serif'.
// if such family exists, try to match style to a font
- s.find_font_for_style(template_descriptor, &self.font_context)
+ s.find_font_for_style(template_descriptor)
} else {
debug!(
"FontList: Couldn't find font family with name={}",
@@ -423,7 +419,7 @@ impl FontCache {
if self.web_families.contains_key(&family_name) {
let templates = self.web_families.get_mut(&family_name).unwrap();
- templates.find_font_for_style(template_descriptor, &self.font_context)
+ templates.find_font_for_style(template_descriptor)
} else {
None
}
@@ -498,7 +494,6 @@ impl FontCacheThread {
generic_fonts,
local_families: HashMap::new(),
web_families: HashMap::new(),
- font_context: FontContextHandle::default(),
core_resource_thread,
webrender_api,
webrender_fonts: HashMap::new(),
diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs
index c7f2eaef530..d316ceb50c1 100644
--- a/components/gfx/font_context.rs
+++ b/components/gfx/font_context.rs
@@ -12,7 +12,6 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use app_units::Au;
use fnv::FnvHasher;
use log::debug;
-use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use servo_arc::Arc;
use style::computed_values::font_variant_caps::T as FontVariantCaps;
use style::properties::style_structs::Font as FontStyleStruct;
@@ -24,7 +23,6 @@ use crate::font::{
use crate::font_cache_thread::FontTemplateInfo;
use crate::font_template::FontTemplateDescriptor;
use crate::platform::font::FontHandle;
-pub use crate::platform::font_context::FontContextHandle;
static SMALL_CAPS_SCALE_FACTOR: f32 = 0.8; // Matches FireFox (see gfxFont.h)
@@ -48,7 +46,6 @@ pub trait FontSource {
/// required.
#[derive(Debug)]
pub struct FontContext<S: FontSource> {
- platform_handle: FontContextHandle,
font_source: S,
// TODO: The font context holds a strong ref to the cached fonts
@@ -66,9 +63,7 @@ pub struct FontContext<S: FontSource> {
impl<S: FontSource> FontContext<S> {
pub fn new(font_source: S) -> FontContext<S> {
#[allow(clippy::default_constructed_unit_structs)]
- let handle = FontContextHandle::default();
FontContext {
- platform_handle: handle,
font_source,
font_cache: HashMap::new(),
font_template_cache: HashMap::new(),
@@ -217,11 +212,7 @@ impl<S: FontSource> FontContext<S> {
descriptor: FontDescriptor,
synthesized_small_caps: Option<FontRef>,
) -> Result<Font, &'static str> {
- let handle = FontHandle::new_from_template(
- &self.platform_handle,
- info.font_template,
- Some(descriptor.pt_size),
- )?;
+ let handle = FontHandle::new_from_template(info.font_template, Some(descriptor.pt_size))?;
let font_instance_key = self
.font_source
@@ -235,13 +226,6 @@ impl<S: FontSource> FontContext<S> {
}
}
-impl<S: FontSource> MallocSizeOf for FontContext<S> {
- fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
- // FIXME(njn): Measure other fields eventually.
- self.platform_handle.size_of(ops)
- }
-}
-
#[derive(Debug, Eq, Hash, PartialEq)]
struct FontCacheKey {
font_descriptor: FontDescriptor,
diff --git a/components/gfx/font_template.rs b/components/gfx/font_template.rs
index 00d95159632..66db059db13 100644
--- a/components/gfx/font_template.rs
+++ b/components/gfx/font_template.rs
@@ -15,7 +15,6 @@ use style::values::computed::font::FontWeight;
use crate::font::FontHandleMethods;
use crate::font_cache_thread::FontIdentifier;
use crate::platform::font::FontHandle;
-use crate::platform::font_context::FontContextHandle;
use crate::platform::font_template::FontTemplateData;
/// Describes how to select a font from a given family. This is very basic at the moment and needs
@@ -130,10 +129,7 @@ impl FontTemplate {
}
/// Get the descriptor. Returns `None` when instantiating the data fails.
- pub fn descriptor(
- &mut self,
- font_context: &FontContextHandle,
- ) -> Option<FontTemplateDescriptor> {
+ pub fn descriptor(&mut self) -> Option<FontTemplateDescriptor> {
// The font template data can be unloaded when nothing is referencing
// it (via the Weak reference to the Arc above). However, if we have
// already loaded a font, store the style information about it separately,
@@ -141,7 +137,7 @@ impl FontTemplate {
// without having to reload the font (unless it is an actual match).
self.descriptor.or_else(|| {
- if self.instantiate(font_context).is_err() {
+ if self.instantiate().is_err() {
return None;
};
@@ -155,10 +151,9 @@ impl FontTemplate {
/// Get the data for creating a font if it matches a given descriptor.
pub fn data_for_descriptor(
&mut self,
- fctx: &FontContextHandle,
requested_desc: &FontTemplateDescriptor,
) -> Option<Arc<FontTemplateData>> {
- self.descriptor(fctx).and_then(|descriptor| {
+ self.descriptor().and_then(|descriptor| {
if *requested_desc == descriptor {
self.data().ok()
} else {
@@ -171,23 +166,22 @@ impl FontTemplate {
/// descriptor, if the font can be loaded.
pub fn data_for_approximate_descriptor(
&mut self,
- font_context: &FontContextHandle,
requested_descriptor: &FontTemplateDescriptor,
) -> Option<(Arc<FontTemplateData>, f32)> {
- self.descriptor(font_context).and_then(|descriptor| {
+ self.descriptor().and_then(|descriptor| {
self.data()
.ok()
.map(|data| (data, descriptor.distance_from(requested_descriptor)))
})
}
- fn instantiate(&mut self, font_context: &FontContextHandle) -> Result<(), &'static str> {
+ fn instantiate(&mut self) -> Result<(), &'static str> {
if !self.is_valid {
return Err("Invalid font template");
}
let data = self.data().map_err(|_| "Could not get FontTemplate data")?;
- let handle = FontHandleMethods::new_from_template(font_context, data, None);
+ let handle = FontHandleMethods::new_from_template(data, None);
self.is_valid = handle.is_ok();
let handle: FontHandle = handle?;
self.descriptor = Some(FontTemplateDescriptor::new(
diff --git a/components/gfx/platform/freetype/font.rs b/components/gfx/platform/freetype/font.rs
index 024b3c563e1..44e51bc218c 100644
--- a/components/gfx/platform/freetype/font.rs
+++ b/components/gfx/platform/freetype/font.rs
@@ -10,7 +10,7 @@ use std::{mem, ptr};
use app_units::Au;
use freetype::freetype::{
FT_Done_Face, FT_F26Dot6, FT_Face, FT_FaceRec, FT_Get_Char_Index, FT_Get_Kerning,
- FT_Get_Postscript_Name, FT_Get_Sfnt_Table, FT_GlyphSlot, FT_Int32, FT_Kerning_Mode, FT_Library,
+ FT_Get_Postscript_Name, FT_Get_Sfnt_Table, FT_GlyphSlot, FT_Int32, FT_Kerning_Mode,
FT_Load_Glyph, FT_Load_Sfnt_Table, FT_Long, FT_New_Face, FT_New_Memory_Face, FT_Set_Char_Size,
FT_Sfnt_Tag, FT_SizeRec, FT_Size_Metrics, FT_UInt, FT_ULong, FT_Vector, FT_STYLE_FLAG_ITALIC,
};
@@ -22,12 +22,12 @@ use style::computed_values::font_weight::T as FontWeight;
use style::values::computed::font::FontStyle;
use super::c_str_to_string;
+use super::library_handle::FreeTypeLibraryHandle;
use crate::font::{
FontHandleMethods, FontMetrics, FontTableMethods, FontTableTag, FractionalPixel, GPOS, GSUB,
KERN,
};
use crate::font_cache_thread::FontIdentifier;
-use crate::platform::font_context::FontContextHandle;
use crate::platform::font_template::FontTemplateData;
use crate::text::glyph::GlyphId;
use crate::text::util::fixed_to_float;
@@ -76,9 +76,6 @@ pub struct FontHandle {
// if the font is created using FT_Memory_Face.
font_data: Arc<FontTemplateData>,
face: FT_Face,
- // `context_handle` is unused, but here to ensure that the underlying
- // FreeTypeLibraryHandle is not dropped.
- context_handle: FontContextHandle,
can_do_fast_shaping: bool,
}
@@ -86,6 +83,10 @@ impl Drop for FontHandle {
fn drop(&mut self) {
assert!(!self.face.is_null());
unsafe {
+ // The FreeType documentation says that both `FT_New_Face` and `FT_Done_Face`
+ // should be protected by a mutex.
+ // See https://freetype.org/freetype2/docs/reference/ft2-library_setup.html.
+ let _guard = FreeTypeLibraryHandle::get().lock();
if !succeeded(FT_Done_Face(self.face)) {
panic!("FT_Done_Face failed");
}
@@ -93,20 +94,17 @@ impl Drop for FontHandle {
}
}
-fn create_face(
- lib: FT_Library,
- template: &FontTemplateData,
- pt_size: Option<Au>,
-) -> Result<FT_Face, &'static str> {
+fn create_face(template: &FontTemplateData, pt_size: Option<Au>) -> Result<FT_Face, &'static str> {
unsafe {
let mut face: FT_Face = ptr::null_mut();
let face_index = 0 as FT_Long;
+ let library = FreeTypeLibraryHandle::get().lock();
let result = match template.identifier {
FontIdentifier::Web(_) => {
let bytes = template.bytes();
FT_New_Memory_Face(
- lib,
+ library.freetype_library,
bytes.as_ptr(),
bytes.len() as FT_Long,
face_index,
@@ -120,7 +118,12 @@ fn create_face(
// https://github.com/servo/servo/pull/20506#issuecomment-378838800
let filename =
CString::new(&*local_identifier.path).expect("filename contains NUL byte!");
- FT_New_Face(lib, filename.as_ptr(), face_index, &mut face)
+ FT_New_Face(
+ library.freetype_library,
+ filename.as_ptr(),
+ face_index,
+ &mut face,
+ )
},
};
@@ -138,21 +141,13 @@ fn create_face(
impl FontHandleMethods for FontHandle {
fn new_from_template(
- fctx: &FontContextHandle,
template: Arc<FontTemplateData>,
pt_size: Option<Au>,
) -> Result<FontHandle, &'static str> {
- let ft_ctx: FT_Library = fctx.ctx.ctx;
- if ft_ctx.is_null() {
- return Err("Null FT_Library");
- }
-
- let face = create_face(ft_ctx, &template, pt_size)?;
-
+ let face = create_face(&template, pt_size)?;
let mut handle = FontHandle {
face,
font_data: template,
- context_handle: fctx.clone(),
can_do_fast_shaping: false,
};
// TODO (#11310): Implement basic support for GPOS and GSUB.
diff --git a/components/gfx/platform/freetype/font_context.rs b/components/gfx/platform/freetype/font_context.rs
deleted file mode 100644
index b08ff552261..00000000000
--- a/components/gfx/platform/freetype/font_context.rs
+++ /dev/null
@@ -1,136 +0,0 @@
-/* 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::os::raw::{c_long, c_void};
-use std::ptr;
-use std::rc::Rc;
-
-use freetype::freetype::{
- FT_Add_Default_Modules, FT_Done_Library, FT_Library, FT_Memory, FT_MemoryRec_, FT_New_Library,
-};
-use freetype::succeeded;
-use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
-use servo_allocator::libc_compat::{free, malloc, realloc};
-use servo_allocator::usable_size;
-
-// We pass a |User| struct -- via an opaque |void*| -- to FreeType each time a new instance is
-// created. FreeType passes it back to the ft_alloc/ft_realloc/ft_free callbacks. We use it to
-// record the memory usage of each FreeType instance.
-pub struct User {
- size: usize,
-}
-
-extern "C" fn ft_alloc(mem: FT_Memory, req_size: c_long) -> *mut c_void {
- unsafe {
- let ptr = malloc(req_size as usize);
- let ptr = ptr as *mut c_void; // libc::c_void vs std::os::raw::c_void
- let actual_size = usable_size(ptr);
- let user = (*mem).user as *mut User;
- (*user).size += actual_size;
- ptr
- }
-}
-
-extern "C" fn ft_free(mem: FT_Memory, ptr: *mut c_void) {
- unsafe {
- let actual_size = usable_size(ptr);
- let user = (*mem).user as *mut User;
- (*user).size -= actual_size;
- free(ptr as *mut _);
- }
-}
-
-extern "C" fn ft_realloc(
- mem: FT_Memory,
- _old_size: c_long,
- new_req_size: c_long,
- old_ptr: *mut c_void,
-) -> *mut c_void {
- unsafe {
- let old_actual_size = usable_size(old_ptr);
- let new_ptr = realloc(old_ptr as *mut _, new_req_size as usize);
- let new_ptr = new_ptr as *mut c_void;
- let new_actual_size = usable_size(new_ptr);
- let user = (*mem).user as *mut User;
- (*user).size += new_actual_size;
- (*user).size -= old_actual_size;
- new_ptr
- }
-}
-
-// A |*mut User| field in a struct triggers a "use of `#[derive]` with a raw pointer" warning from
-// rustc. But using a typedef avoids this, so...
-pub type UserPtr = *mut User;
-
-// WARNING: We need to be careful how we use this struct. See the comment about Rc<> in
-// FontContextHandle.
-#[derive(Clone, Debug)]
-pub struct FreeTypeLibraryHandle {
- pub ctx: FT_Library,
- mem: FT_Memory,
- user: UserPtr,
-}
-
-impl Drop for FreeTypeLibraryHandle {
- #[allow(unused)]
- fn drop(&mut self) {
- assert!(!self.ctx.is_null());
- unsafe {
- FT_Done_Library(self.ctx);
- Box::from_raw(self.mem);
- Box::from_raw(self.user);
- }
- }
-}
-
-impl MallocSizeOf for FreeTypeLibraryHandle {
- fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
- unsafe {
- (*self.user).size +
- ops.malloc_size_of(self.ctx as *const _) +
- ops.malloc_size_of(self.mem as *const _) +
- ops.malloc_size_of(self.user as *const _)
- }
- }
-}
-
-#[derive(Clone, Debug)]
-pub struct FontContextHandle {
- // WARNING: FreeTypeLibraryHandle contains raw pointers, is clonable, and also implements
- // `Drop`. This field needs to be Rc<> to make sure that the `drop` function is only called
- // once, otherwise we'll get crashes. Yuk.
- pub ctx: Rc<FreeTypeLibraryHandle>,
-}
-
-impl MallocSizeOf for FontContextHandle {
- fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
- self.ctx.size_of(ops)
- }
-}
-
-impl Default for FontContextHandle {
- fn default() -> Self {
- let user = Box::into_raw(Box::new(User { size: 0 }));
- let mem = Box::into_raw(Box::new(FT_MemoryRec_ {
- user: user as *mut c_void,
- alloc: Some(ft_alloc),
- free: Some(ft_free),
- realloc: Some(ft_realloc),
- }));
- unsafe {
- let mut ctx: FT_Library = ptr::null_mut();
-
- let result = FT_New_Library(mem, &mut ctx);
- if !succeeded(result) {
- panic!("Unable to initialize FreeType library");
- }
-
- FT_Add_Default_Modules(ctx);
-
- FontContextHandle {
- ctx: Rc::new(FreeTypeLibraryHandle { ctx, mem, user }),
- }
- }
- }
-}
diff --git a/components/gfx/platform/freetype/library_handle.rs b/components/gfx/platform/freetype/library_handle.rs
new file mode 100644
index 00000000000..bcd8b2e4865
--- /dev/null
+++ b/components/gfx/platform/freetype/library_handle.rs
@@ -0,0 +1,116 @@
+/* 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::os::raw::{c_long, c_void};
+use std::ptr;
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::OnceLock;
+
+use freetype::freetype::{
+ FT_Add_Default_Modules, FT_Done_Library, FT_Library, FT_Memory, FT_MemoryRec_, FT_New_Library,
+};
+use freetype::succeeded;
+use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
+use parking_lot::Mutex;
+use servo_allocator::libc_compat::{free, malloc, realloc};
+use servo_allocator::usable_size;
+
+static FREETYPE_MEMORY_USAGE: AtomicUsize = AtomicUsize::new(0);
+static FREETYPE_LIBRARY_HANDLE: OnceLock<Mutex<FreeTypeLibraryHandle>> = OnceLock::new();
+
+extern "C" fn ft_alloc(_: FT_Memory, req_size: c_long) -> *mut c_void {
+ unsafe {
+ let pointer = malloc(req_size as usize);
+ FREETYPE_MEMORY_USAGE.fetch_add(usable_size(pointer), Ordering::Relaxed);
+ pointer
+ }
+}
+
+extern "C" fn ft_free(_: FT_Memory, pointer: *mut c_void) {
+ unsafe {
+ FREETYPE_MEMORY_USAGE.fetch_sub(usable_size(pointer), Ordering::Relaxed);
+ free(pointer as *mut _);
+ }
+}
+
+extern "C" fn ft_realloc(
+ _: FT_Memory,
+ _old_size: c_long,
+ new_req_size: c_long,
+ old_pointer: *mut c_void,
+) -> *mut c_void {
+ unsafe {
+ FREETYPE_MEMORY_USAGE.fetch_sub(usable_size(old_pointer), Ordering::Relaxed);
+ let new_pointer = realloc(old_pointer, new_req_size as usize);
+ FREETYPE_MEMORY_USAGE.fetch_add(usable_size(new_pointer), Ordering::Relaxed);
+ new_pointer
+ }
+}
+
+/// A FreeType library handle to be used for creating and dropping FreeType font faces.
+/// It is very important that this handle lives as long as the faces themselves, which
+/// is why only one of these is created for the entire execution of Servo and never
+/// dropped during execution.
+#[derive(Clone, Debug)]
+pub(crate) struct FreeTypeLibraryHandle {
+ pub freetype_library: FT_Library,
+ freetype_memory: FT_Memory,
+}
+
+unsafe impl Sync for FreeTypeLibraryHandle {}
+unsafe impl Send for FreeTypeLibraryHandle {}
+
+impl Drop for FreeTypeLibraryHandle {
+ #[allow(unused)]
+ fn drop(&mut self) {
+ assert!(!self.freetype_library.is_null());
+ unsafe {
+ FT_Done_Library(self.freetype_library);
+ Box::from_raw(self.freetype_memory);
+ }
+ }
+}
+
+impl MallocSizeOf for FreeTypeLibraryHandle {
+ fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
+ unsafe {
+ FREETYPE_MEMORY_USAGE.load(Ordering::Relaxed) +
+ ops.malloc_size_of(self.freetype_library as *const _) +
+ ops.malloc_size_of(self.freetype_memory as *const _)
+ }
+ }
+}
+
+impl FreeTypeLibraryHandle {
+ /// Get the shared FreeType library handle. This is protected by a mutex because according to
+ /// the FreeType documentation:
+ ///
+ /// > [Since 2.5.6] In multi-threaded applications it is easiest to use one FT_Library object per
+ /// > thread. In case this is too cumbersome, a single FT_Library object across threads is possible
+ /// > also, as long as a mutex lock is used around FT_New_Face and FT_Done_Face.
+ ///
+ /// See <https://freetype.org/freetype2/docs/reference/ft2-library_setup.html>.
+ pub(crate) fn get() -> &'static Mutex<FreeTypeLibraryHandle> {
+ FREETYPE_LIBRARY_HANDLE.get_or_init(|| {
+ let freetype_memory = Box::into_raw(Box::new(FT_MemoryRec_ {
+ user: ptr::null_mut(),
+ alloc: Some(ft_alloc),
+ free: Some(ft_free),
+ realloc: Some(ft_realloc),
+ }));
+ unsafe {
+ let mut freetype_library: FT_Library = ptr::null_mut();
+ let result = FT_New_Library(freetype_memory, &mut freetype_library);
+ if !succeeded(result) {
+ panic!("Unable to initialize FreeType library");
+ }
+ FT_Add_Default_Modules(freetype_library);
+ Mutex::new(FreeTypeLibraryHandle {
+ freetype_library,
+ freetype_memory,
+ })
+ }
+ })
+ }
+}
diff --git a/components/gfx/platform/macos/font.rs b/components/gfx/platform/macos/font.rs
index f8088b24412..3e355c7d1ce 100644
--- a/components/gfx/platform/macos/font.rs
+++ b/components/gfx/platform/macos/font.rs
@@ -27,7 +27,6 @@ use crate::font::{
};
use crate::font_cache_thread::FontIdentifier;
use crate::platform::font_template::FontTemplateData;
-use crate::platform::macos::font_context::FontContextHandle;
use crate::text::glyph::GlyphId;
const KERN_PAIR_LEN: usize = 6;
@@ -158,7 +157,6 @@ impl fmt::Debug for CachedKernTable {
impl FontHandleMethods for FontHandle {
fn new_from_template(
- _fctx: &FontContextHandle,
template: Arc<FontTemplateData>,
pt_size: Option<Au>,
) -> Result<FontHandle, &'static str> {
diff --git a/components/gfx/platform/macos/font_context.rs b/components/gfx/platform/macos/font_context.rs
deleted file mode 100644
index b296ce6738b..00000000000
--- a/components/gfx/platform/macos/font_context.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-/* 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 malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
-
-#[derive(Clone, Debug, Default)]
-pub struct FontContextHandle {
- // this is a placeholder until NSFontManager or whatever is bound in here.
- _ctx: (),
-}
-
-impl MallocSizeOf for FontContextHandle {
- fn size_of(&self, _: &mut MallocSizeOfOps) -> usize {
- 0
- }
-}
diff --git a/components/gfx/platform/mod.rs b/components/gfx/platform/mod.rs
index cc4d28ee575..6e3d191529e 100644
--- a/components/gfx/platform/mod.rs
+++ b/components/gfx/platform/mod.rs
@@ -3,13 +3,11 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
#[cfg(any(target_os = "linux", target_os = "android"))]
-pub use crate::platform::freetype::{font, font_context};
-#[cfg(any(target_os = "linux", target_os = "android"))]
-pub use crate::platform::freetype::{font_list, font_template};
+pub use crate::platform::freetype::{font, font_list, font_template, library_handle};
#[cfg(target_os = "macos")]
-pub use crate::platform::macos::{font, font_context, font_list, font_template};
+pub use crate::platform::macos::{font, font_list, font_template};
#[cfg(target_os = "windows")]
-pub use crate::platform::windows::{font, font_context, font_list, font_template};
+pub use crate::platform::windows::{font, font_list, font_template};
#[cfg(any(target_os = "linux", target_os = "android"))]
mod freetype {
@@ -27,7 +25,6 @@ mod freetype {
}
pub mod font;
- pub mod font_context;
#[cfg(target_os = "linux")]
pub mod font_list;
@@ -39,14 +36,13 @@ mod freetype {
#[cfg(target_os = "android")]
pub use self::android::font_list;
- #[cfg(any(target_os = "linux", target_os = "android"))]
pub mod font_template;
+ pub mod library_handle;
}
#[cfg(target_os = "macos")]
mod macos {
pub mod font;
- pub mod font_context;
pub mod font_list;
pub mod font_template;
}
@@ -54,7 +50,6 @@ mod macos {
#[cfg(target_os = "windows")]
mod windows {
pub mod font;
- pub mod font_context;
pub mod font_list;
pub mod font_template;
}
diff --git a/components/gfx/platform/windows/font.rs b/components/gfx/platform/windows/font.rs
index 3ec4c73ecf8..03b82022068 100644
--- a/components/gfx/platform/windows/font.rs
+++ b/components/gfx/platform/windows/font.rs
@@ -23,7 +23,6 @@ use crate::font::{
};
use crate::font_cache_thread::FontIdentifier;
use crate::platform::font_template::FontTemplateData;
-use crate::platform::windows::font_context::FontContextHandle;
use crate::text::glyph::GlyphId;
// 1em = 12pt = 16px, assuming 72 points per inch and 96 px per inch
@@ -228,7 +227,6 @@ impl FontHandle {}
impl FontHandleMethods for FontHandle {
fn new_from_template(
- _: &FontContextHandle,
template: Arc<FontTemplateData>,
pt_size: Option<Au>,
) -> Result<Self, &'static str> {
diff --git a/components/gfx/platform/windows/font_context.rs b/components/gfx/platform/windows/font_context.rs
deleted file mode 100644
index a67a366fc11..00000000000
--- a/components/gfx/platform/windows/font_context.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-/* 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 malloc_size_of::malloc_size_of_is_0;
-
-#[derive(Clone, Debug, Default)]
-pub struct FontContextHandle;
-
-malloc_size_of_is_0!(FontContextHandle);
diff --git a/components/gfx/tests/font_context.rs b/components/gfx/tests/font_context.rs
index 3447493399d..24965e272f1 100644
--- a/components/gfx/tests/font_context.rs
+++ b/components/gfx/tests/font_context.rs
@@ -14,7 +14,7 @@ use gfx::font::{
fallback_font_families, FontDescriptor, FontFamilyDescriptor, FontFamilyName, FontSearchScope,
};
use gfx::font_cache_thread::{FontIdentifier, FontTemplateInfo, FontTemplates};
-use gfx::font_context::{FontContext, FontContextHandle, FontSource};
+use gfx::font_context::{FontContext, FontSource};
use gfx::font_template::FontTemplateDescriptor;
use servo_arc::Arc;
use servo_atoms::Atom;
@@ -30,7 +30,6 @@ use style::values::generics::font::LineHeight;
use webrender_api::{FontInstanceKey, FontKey, IdNamespace};
struct TestFontSource {
- handle: FontContextHandle,
families: HashMap<String, FontTemplates>,
find_font_count: Rc<Cell<isize>>,
}
@@ -52,7 +51,6 @@ impl TestFontSource {
families.insert(fallback_font_families(None)[0].to_owned(), fallback);
TestFontSource {
- handle: FontContextHandle::default(),
families,
find_font_count: Rc::new(Cell::new(0)),
}
@@ -90,12 +88,10 @@ impl FontSource for TestFontSource {
template_descriptor: FontTemplateDescriptor,
family_descriptor: FontFamilyDescriptor,
) -> Option<FontTemplateInfo> {
- let handle = &self.handle;
-
self.find_font_count.set(self.find_font_count.get() + 1);
self.families
.get_mut(family_descriptor.name())
- .and_then(|family| family.find_font_for_style(&template_descriptor, handle))
+ .and_then(|family| family.find_font_for_style(&template_descriptor))
.map(|template| FontTemplateInfo {
font_template: template,
font_key: FontKey(IdNamespace(0), 0),
diff --git a/components/gfx/tests/font_template.rs b/components/gfx/tests/font_template.rs
index 1c8420bc45c..d35c3607497 100644
--- a/components/gfx/tests/font_template.rs
+++ b/components/gfx/tests/font_template.rs
@@ -11,7 +11,6 @@ fn test_font_template_descriptor() {
use std::path::PathBuf;
use gfx::font_cache_thread::FontIdentifier;
- use gfx::font_context::FontContextHandle;
use gfx::font_template::{FontTemplate, FontTemplateDescriptor};
use servo_url::ServoUrl;
use style::values::computed::font::{FontStretch, FontStyle, FontWeight};
@@ -35,9 +34,7 @@ fn test_font_template_descriptor() {
)
.unwrap();
- let context = FontContextHandle::default();
-
- template.descriptor(&context).unwrap()
+ template.descriptor().unwrap()
}
assert_eq!(