mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
fonts: Depend directly on freetype-sys
(#32318)
Instead of depending on `rust-freetype`, depend directly on `freetype-sys` which is a transitive dependency. This provides almost everything we need (apart from one function call). This will help us eliminate one crate in the dependency chain.
This commit is contained in:
parent
1bcb4787d2
commit
67e556e3be
5 changed files with 40 additions and 47 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -2027,7 +2027,7 @@ dependencies = [
|
||||||
"euclid",
|
"euclid",
|
||||||
"fnv",
|
"fnv",
|
||||||
"fontsan",
|
"fontsan",
|
||||||
"freetype",
|
"freetype-sys",
|
||||||
"gfx_traits",
|
"gfx_traits",
|
||||||
"harfbuzz-sys",
|
"harfbuzz-sys",
|
||||||
"ipc-channel",
|
"ipc-channel",
|
||||||
|
|
|
@ -37,6 +37,7 @@ encoding_rs = "0.8"
|
||||||
env_logger = "0.10"
|
env_logger = "0.10"
|
||||||
euclid = "0.22"
|
euclid = "0.22"
|
||||||
fnv = "1.0"
|
fnv = "1.0"
|
||||||
|
freetype-sys = "0.20"
|
||||||
fxhash = "0.2"
|
fxhash = "0.2"
|
||||||
getopts = "0.2.11"
|
getopts = "0.2.11"
|
||||||
gfx_traits = { path = "components/shared/gfx" }
|
gfx_traits = { path = "components/shared/gfx" }
|
||||||
|
|
|
@ -56,7 +56,7 @@ core-text = "20.1"
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
|
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
|
||||||
harfbuzz-sys = { version = "0.6", features = ["bundled"] }
|
harfbuzz-sys = { version = "0.6", features = ["bundled"] }
|
||||||
freetype = "0.7"
|
freetype-sys = { workspace = true }
|
||||||
servo_allocator = { path = "../allocator" }
|
servo_allocator = { path = "../allocator" }
|
||||||
|
|
||||||
[target.'cfg(all(target_os = "linux", not(target_env = "ohos")))'.dependencies]
|
[target.'cfg(all(target_os = "linux", not(target_env = "ohos")))'.dependencies]
|
||||||
|
|
|
@ -8,16 +8,14 @@ use std::sync::Arc;
|
||||||
use std::{mem, ptr};
|
use std::{mem, ptr};
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use freetype::freetype::{
|
use freetype_sys::{
|
||||||
FT_Done_Face, FT_F26Dot6, FT_Face, FT_Fixed, FT_Get_Char_Index, FT_Get_Kerning,
|
ft_sfnt_head, ft_sfnt_os2, FT_Byte, FT_Done_Face, FT_Error, FT_F26Dot6, FT_Face, FT_Fixed,
|
||||||
FT_Get_Sfnt_Table, FT_GlyphSlot, FT_Int32, FT_Kerning_Mode, FT_Load_Glyph, FT_Load_Sfnt_Table,
|
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_Sfnt_Tag,
|
FT_Long, FT_MulFix, FT_New_Memory_Face, FT_Pos, FT_Select_Size, FT_Set_Char_Size, FT_Short,
|
||||||
FT_Short, FT_SizeRec, FT_Size_Metrics, FT_UInt, FT_ULong, FT_UShort, FT_Vector,
|
FT_SizeRec, FT_Size_Metrics, FT_UInt, FT_ULong, FT_UShort, FT_Vector, FT_FACE_FLAG_COLOR,
|
||||||
FT_FACE_FLAG_COLOR, FT_FACE_FLAG_FIXED_SIZES, FT_FACE_FLAG_SCALABLE, FT_LOAD_COLOR,
|
FT_FACE_FLAG_FIXED_SIZES, FT_FACE_FLAG_SCALABLE, FT_KERNING_DEFAULT, FT_LOAD_COLOR,
|
||||||
FT_LOAD_DEFAULT, FT_STYLE_FLAG_ITALIC,
|
FT_LOAD_DEFAULT, FT_STYLE_FLAG_ITALIC, TT_OS2,
|
||||||
};
|
};
|
||||||
use freetype::succeeded;
|
|
||||||
use freetype::tt_os2::TT_OS2;
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use parking_lot::ReentrantMutex;
|
use parking_lot::ReentrantMutex;
|
||||||
use style::computed_values::font_stretch::T as FontStretch;
|
use style::computed_values::font_stretch::T as FontStretch;
|
||||||
|
@ -95,7 +93,7 @@ impl Drop for PlatformFont {
|
||||||
// should be protected by a mutex.
|
// should be protected by a mutex.
|
||||||
// See https://freetype.org/freetype2/docs/reference/ft2-library_setup.html.
|
// See https://freetype.org/freetype2/docs/reference/ft2-library_setup.html.
|
||||||
let _guard = FreeTypeLibraryHandle::get().lock();
|
let _guard = FreeTypeLibraryHandle::get().lock();
|
||||||
if !succeeded(FT_Done_Face(*face)) {
|
if FT_Done_Face(*face) != 0 {
|
||||||
panic!("FT_Done_Face failed");
|
panic!("FT_Done_Face failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,7 +115,7 @@ fn create_face(data: Arc<Vec<u8>>, face_index: u32) -> Result<FT_Face, &'static
|
||||||
&mut face,
|
&mut face,
|
||||||
);
|
);
|
||||||
|
|
||||||
if !succeeded(result) || face.is_null() {
|
if 0 != result || face.is_null() {
|
||||||
return Err("Could not create FreeType face");
|
return Err("Could not create FreeType face");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +209,7 @@ impl PlatformFontMethods for PlatformFont {
|
||||||
*face,
|
*face,
|
||||||
first_glyph,
|
first_glyph,
|
||||||
second_glyph,
|
second_glyph,
|
||||||
FT_Kerning_Mode::FT_KERNING_DEFAULT as FT_UInt,
|
FT_KERNING_DEFAULT,
|
||||||
&mut delta,
|
&mut delta,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -228,7 +226,7 @@ impl PlatformFontMethods for PlatformFont {
|
||||||
|
|
||||||
let load_flags = face.glyph_load_flags();
|
let load_flags = face.glyph_load_flags();
|
||||||
let result = unsafe { FT_Load_Glyph(*face, glyph as FT_UInt, load_flags) };
|
let result = unsafe { FT_Load_Glyph(*face, glyph as FT_UInt, load_flags) };
|
||||||
if !succeeded(result) {
|
if 0 != result {
|
||||||
debug!("Unable to load glyph {}. reason: {:?}", glyph, result);
|
debug!("Unable to load glyph {}. reason: {:?}", glyph, result);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
@ -243,7 +241,7 @@ impl PlatformFontMethods for PlatformFont {
|
||||||
|
|
||||||
fn metrics(&self) -> FontMetrics {
|
fn metrics(&self) -> FontMetrics {
|
||||||
let face_ptr = *self.face.lock();
|
let face_ptr = *self.face.lock();
|
||||||
let face = unsafe { *face_ptr };
|
let face = unsafe { &*face_ptr };
|
||||||
|
|
||||||
// face.size is a *c_void in the bindings, presumably to avoid recursive structural types
|
// face.size is a *c_void in the bindings, presumably to avoid recursive structural types
|
||||||
let freetype_size: &FT_SizeRec = unsafe { mem::transmute(&(*face.size)) };
|
let freetype_size: &FT_SizeRec = unsafe { mem::transmute(&(*face.size)) };
|
||||||
|
@ -281,8 +279,7 @@ impl PlatformFontMethods for PlatformFont {
|
||||||
// scalable outlines". If it's an sfnt, we can get units_per_EM from the 'head' table
|
// scalable outlines". If it's an sfnt, we can get units_per_EM from the 'head' table
|
||||||
// instead; otherwise, we don't have a unitsPerEm value so we can't compute y_scale and
|
// instead; otherwise, we don't have a unitsPerEm value so we can't compute y_scale and
|
||||||
// x_scale.
|
// x_scale.
|
||||||
let head =
|
let head = unsafe { FT_Get_Sfnt_Table(face_ptr, ft_sfnt_head) as *mut TtHeader };
|
||||||
unsafe { FT_Get_Sfnt_Table(face_ptr, FT_Sfnt_Tag::FT_SFNT_HEAD) as *mut TtHeader };
|
|
||||||
if !head.is_null() && unsafe { (*head).table_version != 0xffff } {
|
if !head.is_null() && unsafe { (*head).table_version != 0xffff } {
|
||||||
// Bug 1267909 - Even if the font is not explicitly scalable, if the face has color
|
// Bug 1267909 - Even if the font is not explicitly scalable, if the face has color
|
||||||
// bitmaps, it should be treated as scalable and scaled to the desired size. Metrics
|
// bitmaps, it should be treated as scalable and scaled to the desired size. Metrics
|
||||||
|
@ -381,18 +378,12 @@ impl PlatformFontMethods for PlatformFont {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Get the length
|
// Get the length
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
if !succeeded(FT_Load_Sfnt_Table(*face, tag, 0, ptr::null_mut(), &mut len)) {
|
if 0 != FT_Load_Sfnt_Table(*face, tag, 0, ptr::null_mut(), &mut len) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
// Get the bytes
|
// Get the bytes
|
||||||
let mut buf = vec![0u8; len as usize];
|
let mut buf = vec![0u8; len as usize];
|
||||||
if !succeeded(FT_Load_Sfnt_Table(
|
if 0 != FT_Load_Sfnt_Table(*face, tag, 0, buf.as_mut_ptr(), &mut len) {
|
||||||
*face,
|
|
||||||
tag,
|
|
||||||
0,
|
|
||||||
buf.as_mut_ptr(),
|
|
||||||
&mut len,
|
|
||||||
)) {
|
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Some(FontTable { buffer: buf })
|
Some(FontTable { buffer: buf })
|
||||||
|
@ -438,7 +429,7 @@ impl FreeTypeFaceHelpers for FT_Face {
|
||||||
if self.scalable() {
|
if self.scalable() {
|
||||||
let size_in_fixed_point = (requested_size.to_f64_px() * 64.0 + 0.5) as FT_F26Dot6;
|
let size_in_fixed_point = (requested_size.to_f64_px() * 64.0 + 0.5) as FT_F26Dot6;
|
||||||
let result = unsafe { FT_Set_Char_Size(self, size_in_fixed_point, 0, 72, 72) };
|
let result = unsafe { FT_Set_Char_Size(self, size_in_fixed_point, 0, 72, 72) };
|
||||||
if !succeeded(result) {
|
if 0 != result {
|
||||||
return Err("FT_Set_Char_Size failed");
|
return Err("FT_Set_Char_Size failed");
|
||||||
}
|
}
|
||||||
return Ok(requested_size);
|
return Ok(requested_size);
|
||||||
|
@ -469,7 +460,7 @@ impl FreeTypeFaceHelpers for FT_Face {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if succeeded(unsafe { FT_Select_Size(self, best_index) }) {
|
if 0 == unsafe { FT_Select_Size(self, best_index) } {
|
||||||
Ok(Au::from_f64_px(best_size.1 as f64 / 64.0))
|
Ok(Au::from_f64_px(best_size.1 as f64 / 64.0))
|
||||||
} else {
|
} else {
|
||||||
Err("FT_Select_Size failed")
|
Err("FT_Select_Size failed")
|
||||||
|
@ -483,7 +474,7 @@ impl FreeTypeFaceHelpers for FT_Face {
|
||||||
// Linux distros use by default, and is a better
|
// Linux distros use by default, and is a better
|
||||||
// default than no hinting.
|
// default than no hinting.
|
||||||
// TODO(gw): Make this configurable.
|
// TODO(gw): Make this configurable.
|
||||||
load_flags |= FT_LOAD_TARGET_LIGHT;
|
load_flags |= FT_LOAD_TARGET_LIGHT as i32;
|
||||||
|
|
||||||
let face_flags = unsafe { (*self).face_flags };
|
let face_flags = unsafe { (*self).face_flags };
|
||||||
if (face_flags & (FT_FACE_FLAG_FIXED_SIZES as FT_Long)) != 0 {
|
if (face_flags & (FT_FACE_FLAG_FIXED_SIZES as FT_Long)) != 0 {
|
||||||
|
@ -497,20 +488,12 @@ impl FreeTypeFaceHelpers for FT_Face {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_table(self, tag: FontTableTag) -> bool {
|
fn has_table(self, tag: FontTableTag) -> bool {
|
||||||
unsafe {
|
unsafe { 0 == FT_Load_Sfnt_Table(self, tag as FT_ULong, 0, ptr::null_mut(), &mut 0) }
|
||||||
succeeded(FT_Load_Sfnt_Table(
|
|
||||||
self,
|
|
||||||
tag as FT_ULong,
|
|
||||||
0,
|
|
||||||
ptr::null_mut(),
|
|
||||||
&mut 0,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn os2_table(self) -> Option<OS2Table> {
|
fn os2_table(self) -> Option<OS2Table> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let os2 = FT_Get_Sfnt_Table(self, FT_Sfnt_Tag::FT_SFNT_OS2) as *mut TT_OS2;
|
let os2 = FT_Get_Sfnt_Table(self, ft_sfnt_os2) as *mut TT_OS2;
|
||||||
let valid = !os2.is_null() && (*os2).version != 0xffff;
|
let valid = !os2.is_null() && (*os2).version != 0xffff;
|
||||||
|
|
||||||
if !valid {
|
if !valid {
|
||||||
|
@ -555,3 +538,13 @@ struct TtHeader {
|
||||||
index_to_loc_format: FT_Short,
|
index_to_loc_format: FT_Short,
|
||||||
glyph_data_format: FT_Short,
|
glyph_data_format: FT_Short,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
fn FT_Load_Sfnt_Table(
|
||||||
|
face: FT_Face,
|
||||||
|
tag: FT_ULong,
|
||||||
|
offset: FT_Long,
|
||||||
|
buffer: *mut FT_Byte,
|
||||||
|
length: *mut FT_ULong,
|
||||||
|
) -> FT_Error;
|
||||||
|
}
|
||||||
|
|
|
@ -7,10 +7,9 @@ use std::ptr;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
use freetype::freetype::{
|
use freetype_sys::{
|
||||||
FT_Add_Default_Modules, FT_Done_Library, FT_Library, FT_Memory, FT_MemoryRec_, FT_New_Library,
|
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 malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use servo_allocator::libc_compat::{free, malloc, realloc};
|
use servo_allocator::libc_compat::{free, malloc, realloc};
|
||||||
|
@ -93,16 +92,16 @@ impl FreeTypeLibraryHandle {
|
||||||
/// See <https://freetype.org/freetype2/docs/reference/ft2-library_setup.html>.
|
/// See <https://freetype.org/freetype2/docs/reference/ft2-library_setup.html>.
|
||||||
pub(crate) fn get() -> &'static Mutex<FreeTypeLibraryHandle> {
|
pub(crate) fn get() -> &'static Mutex<FreeTypeLibraryHandle> {
|
||||||
FREETYPE_LIBRARY_HANDLE.get_or_init(|| {
|
FREETYPE_LIBRARY_HANDLE.get_or_init(|| {
|
||||||
let freetype_memory = Box::into_raw(Box::new(FT_MemoryRec_ {
|
let freetype_memory = Box::into_raw(Box::new(FT_MemoryRec {
|
||||||
user: ptr::null_mut(),
|
user: ptr::null_mut(),
|
||||||
alloc: Some(ft_alloc),
|
alloc: ft_alloc,
|
||||||
free: Some(ft_free),
|
free: ft_free,
|
||||||
realloc: Some(ft_realloc),
|
realloc: ft_realloc,
|
||||||
}));
|
}));
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut freetype_library: FT_Library = ptr::null_mut();
|
let mut freetype_library: FT_Library = ptr::null_mut();
|
||||||
let result = FT_New_Library(freetype_memory, &mut freetype_library);
|
let result = FT_New_Library(freetype_memory, &mut freetype_library);
|
||||||
if !succeeded(result) {
|
if 0 != result {
|
||||||
panic!("Unable to initialize FreeType library");
|
panic!("Unable to initialize FreeType library");
|
||||||
}
|
}
|
||||||
FT_Add_Default_Modules(freetype_library);
|
FT_Add_Default_Modules(freetype_library);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue