fonts/platform/freetype/
library_handle.rs1use std::os::raw::{c_long, c_void};
6use std::ptr;
7use std::sync::OnceLock;
8use std::sync::atomic::{AtomicUsize, Ordering};
9
10use freetype_sys::{
11 FT_Add_Default_Modules, FT_Done_Library, FT_Library, FT_Memory, FT_MemoryRec, FT_New_Library,
12};
13use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
14use parking_lot::ReentrantMutex;
15use servo_allocator::libc_compat::{free, malloc, realloc};
16use servo_allocator::usable_size;
17
18static FREETYPE_MEMORY_USAGE: AtomicUsize = AtomicUsize::new(0);
19static FREETYPE_LIBRARY_HANDLE: OnceLock<ReentrantMutex<FreeTypeLibraryHandle>> = OnceLock::new();
20
21extern "C" fn ft_alloc(_: FT_Memory, req_size: c_long) -> *mut c_void {
22 unsafe {
23 let pointer = malloc(req_size as usize);
24 FREETYPE_MEMORY_USAGE.fetch_add(usable_size(pointer), Ordering::Relaxed);
25 pointer
26 }
27}
28
29extern "C" fn ft_free(_: FT_Memory, pointer: *mut c_void) {
30 unsafe {
31 FREETYPE_MEMORY_USAGE.fetch_sub(usable_size(pointer), Ordering::Relaxed);
32 free(pointer as *mut _);
33 }
34}
35
36extern "C" fn ft_realloc(
37 _: FT_Memory,
38 _old_size: c_long,
39 new_req_size: c_long,
40 old_pointer: *mut c_void,
41) -> *mut c_void {
42 unsafe {
43 FREETYPE_MEMORY_USAGE.fetch_sub(usable_size(old_pointer), Ordering::Relaxed);
44 let new_pointer = realloc(old_pointer, new_req_size as usize);
45 FREETYPE_MEMORY_USAGE.fetch_add(usable_size(new_pointer), Ordering::Relaxed);
46 new_pointer
47 }
48}
49
50#[derive(Clone, Debug)]
55pub(crate) struct FreeTypeLibraryHandle {
56 pub(crate) freetype_library: FT_Library,
57 freetype_memory: FT_Memory,
58}
59
60unsafe impl Sync for FreeTypeLibraryHandle {}
61unsafe impl Send for FreeTypeLibraryHandle {}
62
63impl Drop for FreeTypeLibraryHandle {
64 #[allow(unused)]
65 fn drop(&mut self) {
66 assert!(!self.freetype_library.is_null());
67 unsafe {
68 FT_Done_Library(self.freetype_library);
69 Box::from_raw(self.freetype_memory);
70 }
71 }
72}
73
74impl MallocSizeOf for FreeTypeLibraryHandle {
75 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
76 unsafe {
77 FREETYPE_MEMORY_USAGE.load(Ordering::Relaxed) +
78 ops.malloc_size_of(self.freetype_library as *const _) +
79 ops.malloc_size_of(self.freetype_memory as *const _)
80 }
81 }
82}
83
84impl FreeTypeLibraryHandle {
85 pub(crate) fn get() -> &'static ReentrantMutex<FreeTypeLibraryHandle> {
94 FREETYPE_LIBRARY_HANDLE.get_or_init(|| {
95 let freetype_memory = Box::into_raw(Box::new(FT_MemoryRec {
96 user: ptr::null_mut(),
97 alloc: ft_alloc,
98 free: ft_free,
99 realloc: ft_realloc,
100 }));
101 unsafe {
102 let mut freetype_library: FT_Library = ptr::null_mut();
103 let result = FT_New_Library(freetype_memory, &mut freetype_library);
104 if 0 != result {
105 panic!("Unable to initialize FreeType library");
106 }
107 FT_Add_Default_Modules(freetype_library);
108 ReentrantMutex::new(FreeTypeLibraryHandle {
109 freetype_library,
110 freetype_memory,
111 })
112 }
113 })
114 }
115}