Skip to content

Commit 046dbd8

Browse files
authored
fonts: Use skrifa to get raw font table data on Linux (servo#38690)
Use skrifa instead of freetype for extracting raw table data. Allows us to replace unsafe Freetype code with safe Skrifa code. Also allows us to avoid copying the table data. Instead we return Arc'd data. --------- Signed-off-by: Nico Burns <nico@nicoburns.com>
1 parent a4fdbe8 commit 046dbd8

File tree

4 files changed

+27
-35
lines changed

4 files changed

+27
-35
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ servo-media-dummy = { git = "https://github.com/servo/media" }
138138
servo-media-gstreamer = { git = "https://github.com/servo/media" }
139139
servo-tracing = { path = "components/servo_tracing" }
140140
servo_arc = { git = "https://github.com/servo/stylo", branch = "2025-08-01" }
141+
skrifa = "0.31.3"
141142
smallbitvec = "2.6.0"
142143
smallvec = { version = "1.15", features = ["serde", "union"] }
143144
string_cache = "0.8"

components/fonts/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ serde = { workspace = true }
4545
servo_arc = { workspace = true }
4646
servo_config = { path = "../config" }
4747
servo_url = { path = "../url" }
48+
skrifa = { workspace = true }
4849
smallvec = { workspace = true }
4950
stylo = { workspace = true }
5051
stylo_atoms = { workspace = true }

components/fonts/platform/freetype/font.rs

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,19 @@ use std::{mem, ptr};
1010
use app_units::Au;
1111
use euclid::default::{Point2D, Rect, Size2D};
1212
use freetype_sys::{
13-
FT_Byte, FT_Done_Face, FT_Error, FT_F26Dot6, FT_FACE_FLAG_COLOR, FT_FACE_FLAG_FIXED_SIZES,
14-
FT_FACE_FLAG_SCALABLE, FT_Face, FT_Get_Char_Index, FT_Get_Kerning, FT_GlyphSlot, FT_Int32,
15-
FT_KERNING_DEFAULT, FT_LOAD_COLOR, FT_LOAD_DEFAULT, FT_LOAD_NO_HINTING, FT_Load_Glyph, FT_Long,
16-
FT_New_Face, FT_New_Memory_Face, FT_Pos, FT_Select_Size, FT_Set_Char_Size, FT_Size_Metrics,
17-
FT_SizeRec, FT_UInt, FT_ULong, FT_Vector,
13+
FT_Done_Face, FT_F26Dot6, FT_FACE_FLAG_COLOR, FT_FACE_FLAG_FIXED_SIZES, FT_FACE_FLAG_SCALABLE,
14+
FT_Face, FT_Get_Char_Index, FT_Get_Kerning, FT_GlyphSlot, FT_Int32, FT_KERNING_DEFAULT,
15+
FT_LOAD_COLOR, FT_LOAD_DEFAULT, FT_LOAD_NO_HINTING, FT_Load_Glyph, FT_Long, FT_New_Face,
16+
FT_New_Memory_Face, FT_Pos, FT_Select_Size, FT_Set_Char_Size, FT_Size_Metrics, FT_SizeRec,
17+
FT_UInt, FT_ULong, FT_Vector,
1818
};
1919
use log::debug;
2020
use memmap2::Mmap;
2121
use parking_lot::ReentrantMutex;
2222
use read_fonts::tables::os2::SelectionFlags;
23+
use read_fonts::types::Tag;
2324
use read_fonts::{FontRef, ReadError, TableProvider};
25+
use servo_arc::Arc;
2426
use style::Zero;
2527
use style::computed_values::font_stretch::T as FontStretch;
2628
use style::computed_values::font_weight::T as FontWeight;
@@ -49,12 +51,17 @@ fn fixed_26_dot_6_to_float(fixed: FT_F26Dot6) -> f64 {
4951

5052
#[derive(Debug)]
5153
pub struct FontTable {
52-
buffer: Vec<u8>,
54+
data: FreeTypeFaceTableProviderData,
55+
tag: Tag,
5356
}
5457

5558
impl FontTableMethods for FontTable {
5659
fn buffer(&self) -> &[u8] {
57-
&self.buffer
60+
let font_ref = self.data.font_ref().expect("Font checked before creating");
61+
let table_data = font_ref
62+
.table_data(self.tag)
63+
.expect("Table existence checked before creating");
64+
table_data.as_bytes()
5865
}
5966
}
6067

@@ -164,7 +171,7 @@ impl PlatformFontMethods for PlatformFont {
164171
requested_face_size,
165172
actual_face_size,
166173
table_provider_data: FreeTypeFaceTableProviderData::Local(
167-
memory_mapped_font_data,
174+
Arc::new(memory_mapped_font_data),
168175
font_identifier.index(),
169176
),
170177
})
@@ -393,22 +400,13 @@ impl PlatformFontMethods for PlatformFont {
393400
}
394401

395402
fn table_for_tag(&self, tag: FontTableTag) -> Option<FontTable> {
396-
let face = self.face.lock();
397-
let tag = tag as FT_ULong;
398-
399-
unsafe {
400-
// Get the length
401-
let mut len = 0;
402-
if 0 != FT_Load_Sfnt_Table(*face, tag, 0, ptr::null_mut(), &mut len) {
403-
return None;
404-
}
405-
// Get the bytes
406-
let mut buf = vec![0u8; len as usize];
407-
if 0 != FT_Load_Sfnt_Table(*face, tag, 0, buf.as_mut_ptr(), &mut len) {
408-
return None;
409-
}
410-
Some(FontTable { buffer: buf })
411-
}
403+
let tag = Tag::from_u32(tag);
404+
let font_ref = self.table_provider_data.font_ref().ok()?;
405+
let _table_data = font_ref.table_data(tag)?;
406+
Some(FontTable {
407+
data: self.table_provider_data.clone(),
408+
tag,
409+
})
412410
}
413411

414412
fn typographic_bounds(&self, glyph_id: GlyphId) -> Rect<f32> {
@@ -529,19 +527,10 @@ impl FreeTypeFaceHelpers for FT_Face {
529527
}
530528
}
531529

532-
unsafe extern "C" {
533-
fn FT_Load_Sfnt_Table(
534-
face: FT_Face,
535-
tag: FT_ULong,
536-
offset: FT_Long,
537-
buffer: *mut FT_Byte,
538-
length: *mut FT_ULong,
539-
) -> FT_Error;
540-
}
541-
530+
#[derive(Clone)]
542531
enum FreeTypeFaceTableProviderData {
543532
Web(FontData),
544-
Local(Mmap, u32),
533+
Local(Arc<Mmap>, u32),
545534
}
546535

547536
impl FreeTypeFaceTableProviderData {

0 commit comments

Comments
 (0)