mirror of
https://github.com/servo/servo.git
synced 2025-09-23 05:10:09 +01:00
Seperate freetype face and named instance indices (#39213)
In servo, each `LocalFontIdentifier` has an `fn index() -> u32`, which returns the index of the font within the font file in case it is a font collection (`.ttc` instead of `.ttf`). The way this index is obtained is platform-dependent. On systems using `fontconfig`, we get the index by querying `FC_INDEX`:d2c78db981/components/fonts/platform/freetype/font_list.rs (L109-L112)
There is a sneaky bug here: In addition to the aforementioned face index, the value for `FC_INDEX` contains the index of the named instance of the face in the upper 16 bits. This behaviour is completely undocumented, but FreeType uses the same format: https://freetype.org/freetype2/docs/reference/ft2-face_creation.html#ft_open_face. This wasn't a problem for the longest time, because the only consumer of the `index` value coming from fontconfig was FreeType. However, sometime after29e618dcf7
, we started also passing it to`read-fonts` . `read-fonts` expects only the face index, causing it to return errors as seen in https://github.com/servo/servo/issues/39209. The fix is to seperate the two indices when storing them in a `LocalFontDescriptor` and pass only the lower 16 bits to `read-fonts`. I'm unsure whether we should continue passing the named instance index to FreeType since we don't actually support variable fonts, but I've opted to keep the current behaviour for now. Fixes: https://github.com/servo/servo/issues/39209 Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
parent
d2c78db981
commit
fcf4beeac0
6 changed files with 36 additions and 9 deletions
|
@ -432,7 +432,8 @@ where
|
||||||
let mut produce_font = |font: &Font| {
|
let mut produce_font = |font: &Font| {
|
||||||
let local_font_identifier = LocalFontIdentifier {
|
let local_font_identifier = LocalFontIdentifier {
|
||||||
path: Atom::from(FontList::font_absolute_path(&font.filename)),
|
path: Atom::from(FontList::font_absolute_path(&font.filename)),
|
||||||
variation_index: 0,
|
face_index: 0,
|
||||||
|
named_instance_index: 0,
|
||||||
};
|
};
|
||||||
let stretch = StyleFontStretch::NORMAL;
|
let stretch = StyleFontStretch::NORMAL;
|
||||||
let weight = font
|
let weight = font
|
||||||
|
|
|
@ -96,7 +96,11 @@ impl PlatformFontMethods for PlatformFont {
|
||||||
let library = FreeTypeLibraryHandle::get().lock();
|
let library = FreeTypeLibraryHandle::get().lock();
|
||||||
let filename = CString::new(&*font_identifier.path).expect("filename contains NUL byte!");
|
let filename = CString::new(&*font_identifier.path).expect("filename contains NUL byte!");
|
||||||
|
|
||||||
let face = FreeTypeFace::new_from_file(&library, &filename, font_identifier.index())?;
|
let face = FreeTypeFace::new_from_file(
|
||||||
|
&library,
|
||||||
|
&filename,
|
||||||
|
font_identifier.face_index_for_freetype(),
|
||||||
|
)?;
|
||||||
|
|
||||||
let normalized_variations = face.set_variations_for_font(variations, &library)?;
|
let normalized_variations = face.set_variations_for_font(variations, &library)?;
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,8 @@ where
|
||||||
|
|
||||||
let local_font_identifier = LocalFontIdentifier {
|
let local_font_identifier = LocalFontIdentifier {
|
||||||
path: Atom::from(c_str_to_string(path as *const c_char)),
|
path: Atom::from(c_str_to_string(path as *const c_char)),
|
||||||
variation_index: index as i32,
|
face_index: (index & 0xFFFF) as u16,
|
||||||
|
named_instance_index: (index >> 16) as u16,
|
||||||
};
|
};
|
||||||
let descriptor = FontTemplateDescriptor::new(weight, stretch, style);
|
let descriptor = FontTemplateDescriptor::new(weight, stretch, style);
|
||||||
|
|
||||||
|
|
|
@ -444,7 +444,8 @@ where
|
||||||
let mut produce_font = |font: &Font| {
|
let mut produce_font = |font: &Font| {
|
||||||
let local_font_identifier = LocalFontIdentifier {
|
let local_font_identifier = LocalFontIdentifier {
|
||||||
path: Atom::from(font.filepath.clone()),
|
path: Atom::from(font.filepath.clone()),
|
||||||
variation_index: 0,
|
face_index: 0,
|
||||||
|
named_instance_index: 0,
|
||||||
};
|
};
|
||||||
let stretch = font.width.into();
|
let stretch = font.width.into();
|
||||||
let weight = font
|
let weight = font
|
||||||
|
|
|
@ -186,7 +186,8 @@ mod font_context {
|
||||||
|
|
||||||
let local_font_identifier = LocalFontIdentifier {
|
let local_font_identifier = LocalFontIdentifier {
|
||||||
path: path.to_str().expect("Could not load test font").into(),
|
path: path.to_str().expect("Could not load test font").into(),
|
||||||
variation_index: 0,
|
face_index: 0,
|
||||||
|
named_instance_index: 0,
|
||||||
};
|
};
|
||||||
let handle = PlatformFont::new_from_local_font_identifier(
|
let handle = PlatformFont::new_from_local_font_identifier(
|
||||||
local_font_identifier.clone(),
|
local_font_identifier.clone(),
|
||||||
|
|
|
@ -41,18 +41,26 @@ mod platform {
|
||||||
/// The path to the font.
|
/// The path to the font.
|
||||||
pub path: Atom,
|
pub path: Atom,
|
||||||
/// The variation index within the font.
|
/// The variation index within the font.
|
||||||
pub variation_index: i32,
|
pub face_index: u16,
|
||||||
|
/// The index of the named instance within the font.
|
||||||
|
///
|
||||||
|
/// For non-variable fonts, this is ignored.
|
||||||
|
pub named_instance_index: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalFontIdentifier {
|
impl LocalFontIdentifier {
|
||||||
pub fn index(&self) -> u32 {
|
pub fn index(&self) -> u32 {
|
||||||
self.variation_index.try_into().unwrap()
|
self.face_index as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn named_instance_index(&self) -> u32 {
|
||||||
|
self.named_instance_index as u32
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn native_font_handle(&self) -> NativeFontHandle {
|
pub fn native_font_handle(&self) -> NativeFontHandle {
|
||||||
NativeFontHandle {
|
NativeFontHandle {
|
||||||
path: PathBuf::from(&*self.path),
|
path: PathBuf::from(&*self.path),
|
||||||
index: self.variation_index as u32,
|
index: self.face_index as u32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,9 +72,20 @@ mod platform {
|
||||||
|
|
||||||
Some(FontDataAndIndex {
|
Some(FontDataAndIndex {
|
||||||
data,
|
data,
|
||||||
index: self.variation_index as u32,
|
index: self.face_index as u32,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fontconfig and FreeType use a packed format to represent face and
|
||||||
|
/// named instance indexes in a single integer. The first 16 bits make
|
||||||
|
/// up the named instance index and the second 16 bits make up the
|
||||||
|
/// face index.
|
||||||
|
///
|
||||||
|
/// See <https://freetype.org/freetype2/docs/reference/ft2-face_creation.html#ft_open_face>
|
||||||
|
/// for more information.
|
||||||
|
pub fn face_index_for_freetype(&self) -> u32 {
|
||||||
|
((self.named_instance_index()) << 16) | self.index()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue