mirror of
https://github.com/servo/servo.git
synced 2025-09-29 16:19:14 +01:00
fonts: Add more types to fonts_traits
(#38898)
This is necessary so that `constellation_traits` can get these types via a dependency on `fonts_traits`. This will allow sending IPC channels to shared workers so that they can have access to a shared `FontContext` from `script`. Testing: This just moves code between crates, so is covered by existing tests. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
0b5bcfbf17
commit
3a97d4eed2
22 changed files with 495 additions and 446 deletions
|
@ -7,6 +7,7 @@ use std::fs::File;
|
|||
|
||||
use app_units::Au;
|
||||
use euclid::default::{Point2D, Rect, Size2D};
|
||||
use fonts_traits::{FontIdentifier, FontTemplateDescriptor, LocalFontIdentifier};
|
||||
use freetype_sys::{
|
||||
FT_F26Dot6, FT_Get_Char_Index, FT_Get_Kerning, FT_GlyphSlot, FT_KERNING_DEFAULT,
|
||||
FT_LOAD_DEFAULT, FT_LOAD_NO_HINTING, FT_Load_Glyph, FT_Size_Metrics, FT_SizeRec, FT_UInt,
|
||||
|
@ -21,14 +22,11 @@ use servo_arc::Arc;
|
|||
use style::Zero;
|
||||
use webrender_api::{FontInstanceFlags, FontVariation};
|
||||
|
||||
use super::LocalFontIdentifier;
|
||||
use super::library_handle::FreeTypeLibraryHandle;
|
||||
use crate::FontData;
|
||||
use crate::font::{FontMetrics, FontTableMethods, FractionalPixel, PlatformFontMethods};
|
||||
use crate::font_template::FontTemplateDescriptor;
|
||||
use crate::glyph::GlyphId;
|
||||
use crate::platform::freetype::freetype_face::FreeTypeFace;
|
||||
use crate::system_font_service::FontIdentifier;
|
||||
|
||||
/// Convert FreeType-style 26.6 fixed point to an [`f64`].
|
||||
fn fixed_26_dot_6_to_float(fixed: FT_F26Dot6) -> f64 {
|
||||
|
|
|
@ -19,6 +19,7 @@ use fontconfig_sys::{
|
|||
FcObjectSetCreate, FcObjectSetDestroy, FcPattern, FcPatternAddString, FcPatternCreate,
|
||||
FcPatternDestroy, FcPatternGetInteger, FcPatternGetString, FcResultMatch, FcSetSystem,
|
||||
};
|
||||
use fonts_traits::{FontTemplate, FontTemplateDescriptor, LocalFontIdentifier};
|
||||
use libc::{c_char, c_int};
|
||||
use log::debug;
|
||||
use style::Atom;
|
||||
|
@ -26,9 +27,7 @@ use style::values::computed::font::GenericFontFamily;
|
|||
use style::values::computed::{FontStretch, FontStyle, FontWeight};
|
||||
use unicode_script::Script;
|
||||
|
||||
use super::LocalFontIdentifier;
|
||||
use crate::font::map_platform_values_to_style_values;
|
||||
use crate::font_template::{FontTemplate, FontTemplateDescriptor};
|
||||
use crate::platform::add_noto_fallback_families;
|
||||
use crate::{
|
||||
EmojiPresentationPreference, FallbackFontSelectionOptions, FontIdentifier,
|
||||
|
|
|
@ -2,19 +2,6 @@
|
|||
* 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::convert::TryInto;
|
||||
use std::fs::File;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str;
|
||||
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use memmap2::Mmap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use style::Atom;
|
||||
use webrender_api::NativeFontHandle;
|
||||
|
||||
use crate::{FontData, FontDataAndIndex};
|
||||
|
||||
pub mod font;
|
||||
mod freetype_face;
|
||||
|
||||
|
@ -37,36 +24,3 @@ mod ohos {
|
|||
pub use self::ohos::font_list;
|
||||
|
||||
mod library_handle;
|
||||
|
||||
/// An identifier for a local font on systems using Freetype.
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub struct LocalFontIdentifier {
|
||||
/// The path to the font.
|
||||
pub path: Atom,
|
||||
/// The variation index within the font.
|
||||
pub variation_index: i32,
|
||||
}
|
||||
|
||||
impl LocalFontIdentifier {
|
||||
pub(crate) fn index(&self) -> u32 {
|
||||
self.variation_index.try_into().unwrap()
|
||||
}
|
||||
|
||||
pub(crate) fn native_font_handle(&self) -> NativeFontHandle {
|
||||
NativeFontHandle {
|
||||
path: PathBuf::from(&*self.path),
|
||||
index: self.variation_index as u32,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn font_data_and_index(&self) -> Option<FontDataAndIndex> {
|
||||
let file = File::open(Path::new(&*self.path)).ok()?;
|
||||
let mmap = unsafe { Mmap::map(&file).ok()? };
|
||||
let data = FontData::from_bytes(&mmap);
|
||||
|
||||
Some(FontDataAndIndex {
|
||||
data,
|
||||
index: self.variation_index as u32,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,12 +13,12 @@ use core_foundation::string::{CFString, CFStringRef};
|
|||
use core_foundation::url::{CFURL, kCFURLPOSIXPathStyle};
|
||||
use core_graphics::display::CFDictionary;
|
||||
use core_text::font_descriptor::{kCTFontURLAttribute, kCTFontVariationAttribute};
|
||||
use fonts_traits::FontIdentifier;
|
||||
use parking_lot::RwLock;
|
||||
use webrender_api::FontVariation;
|
||||
|
||||
use crate::FontData;
|
||||
use crate::platform::font::PlatformFont;
|
||||
use crate::system_font_service::FontIdentifier;
|
||||
|
||||
/// A cache of `CTFont` to avoid having to create `CTFont` instances over and over. It is
|
||||
/// always possible to create a `CTFont` using a `FontTemplate` even if it isn't in this
|
||||
|
|
|
@ -17,16 +17,16 @@ use core_text::font_descriptor::{
|
|||
CTFontTraits, SymbolicTraitAccessors, TraitAccessors, kCTFontDefaultOrientation,
|
||||
};
|
||||
use euclid::default::{Point2D, Rect, Size2D};
|
||||
use fonts_traits::{FontIdentifier, LocalFontIdentifier};
|
||||
use log::debug;
|
||||
use skrifa::Tag;
|
||||
use style::values::computed::font::{FontStretch, FontStyle, FontWeight};
|
||||
use webrender_api::{FontInstanceFlags, FontVariation};
|
||||
|
||||
use super::core_text_font_cache::CoreTextFontCache;
|
||||
use super::font_list::LocalFontIdentifier;
|
||||
use crate::{
|
||||
CBDT, COLR, FontData, FontIdentifier, FontMetrics, FontTableMethods, FontTemplateDescriptor,
|
||||
FractionalPixel, GlyphId, KERN, PlatformFontMethods, SBIX, map_platform_values_to_style_values,
|
||||
CBDT, COLR, FontData, FontMetrics, FontTableMethods, FontTemplateDescriptor, FractionalPixel,
|
||||
GlyphId, KERN, PlatformFontMethods, SBIX, map_platform_values_to_style_values,
|
||||
};
|
||||
|
||||
const KERN_PAIR_LEN: usize = 6;
|
||||
|
|
|
@ -2,107 +2,20 @@
|
|||
* 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::fs::File;
|
||||
use std::path::Path;
|
||||
|
||||
use base::text::{UnicodeBlock, UnicodeBlockMethod, unicode_plane};
|
||||
use log::{debug, warn};
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use memmap2::Mmap;
|
||||
use read_fonts::types::NameId;
|
||||
use read_fonts::{FileRef, TableProvider as _};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use fonts_traits::LocalFontIdentifier;
|
||||
use log::debug;
|
||||
use style::Atom;
|
||||
use style::values::computed::font::GenericFontFamily;
|
||||
use unicode_script::Script;
|
||||
use webrender_api::NativeFontHandle;
|
||||
|
||||
use crate::platform::add_noto_fallback_families;
|
||||
use crate::platform::font::CoreTextFontTraitsMapping;
|
||||
use crate::{
|
||||
EmojiPresentationPreference, FallbackFontSelectionOptions, FontData, FontDataAndIndex,
|
||||
FontIdentifier, FontTemplate, FontTemplateDescriptor, LowercaseFontFamilyName,
|
||||
EmojiPresentationPreference, FallbackFontSelectionOptions, FontIdentifier, FontTemplate,
|
||||
FontTemplateDescriptor, LowercaseFontFamilyName,
|
||||
};
|
||||
|
||||
/// An identifier for a local font on a MacOS system. These values comes from the CoreText
|
||||
/// CTFontCollection. Note that `path` here is required. We do not load fonts that do not
|
||||
/// have paths.
|
||||
#[derive(Clone, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub struct LocalFontIdentifier {
|
||||
pub postscript_name: Atom,
|
||||
pub path: Atom,
|
||||
}
|
||||
|
||||
impl LocalFontIdentifier {
|
||||
pub(crate) fn native_font_handle(&self) -> NativeFontHandle {
|
||||
NativeFontHandle {
|
||||
name: self.postscript_name.to_string(),
|
||||
path: self.path.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn index(&self) -> u32 {
|
||||
0
|
||||
}
|
||||
|
||||
pub(crate) fn font_data_and_index(&self) -> Option<FontDataAndIndex> {
|
||||
let file = File::open(Path::new(&*self.path)).ok()?;
|
||||
let mmap = unsafe { Mmap::map(&file).ok()? };
|
||||
|
||||
// Determine index
|
||||
let file_ref = FileRef::new(mmap.as_ref()).ok()?;
|
||||
let index = ttc_index_from_postscript_name(file_ref, &self.postscript_name);
|
||||
|
||||
Some(FontDataAndIndex {
|
||||
data: FontData::from_bytes(&mmap),
|
||||
index,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// CoreText font enumeration gives us a Postscript name rather than an index.
|
||||
/// This functions maps from a Postscript name to an index.
|
||||
///
|
||||
/// This mapping works for single-font files and for simple TTC files, but may not work in all cases.
|
||||
/// We are not 100% sure which cases (if any) will not work. But we suspect that variable fonts may cause
|
||||
/// issues due to the Postscript names corresponding to instances not being straightforward, and the possibility
|
||||
/// that CoreText may return a non-standard in that scenerio.
|
||||
fn ttc_index_from_postscript_name(font_file: FileRef<'_>, postscript_name: &str) -> u32 {
|
||||
match font_file {
|
||||
// File only contains one font: simply return 0
|
||||
FileRef::Font(_) => 0,
|
||||
// File is a collection: iterate through each font in the collection and check
|
||||
// whether the name matches
|
||||
FileRef::Collection(collection) => {
|
||||
for i in 0..collection.len() {
|
||||
let font = collection.get(i).unwrap();
|
||||
let name_table = font.name().unwrap();
|
||||
if name_table
|
||||
.name_record()
|
||||
.iter()
|
||||
.filter(|record| record.name_id() == NameId::POSTSCRIPT_NAME)
|
||||
.any(|record| {
|
||||
record
|
||||
.string(name_table.string_data())
|
||||
.unwrap()
|
||||
.chars()
|
||||
.eq(postscript_name.chars())
|
||||
})
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// If we fail to find a font, just use the first font in the file.
|
||||
warn!(
|
||||
"Font with postscript_name {} not found in collection",
|
||||
postscript_name
|
||||
);
|
||||
0
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_each_available_family<F>(mut callback: F)
|
||||
where
|
||||
F: FnMut(String),
|
||||
|
|
|
@ -22,13 +22,11 @@ use unicode_script::Script;
|
|||
))]
|
||||
use crate::FallbackFontSelectionOptions;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub use crate::platform::freetype::{LocalFontIdentifier, font, font_list};
|
||||
pub use crate::platform::freetype::{font, font_list};
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use crate::platform::macos::{
|
||||
core_text_font_cache, font, font_list, font_list::LocalFontIdentifier,
|
||||
};
|
||||
pub use crate::platform::macos::{core_text_font_cache, font, font_list};
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use crate::platform::windows::{font, font_list, font_list::LocalFontIdentifier};
|
||||
pub use crate::platform::windows::{font, font_list};
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub mod freetype;
|
||||
|
|
|
@ -17,6 +17,7 @@ use dwrote::{
|
|||
DWRITE_FONT_AXIS_VALUE, DWRITE_FONT_SIMULATIONS_NONE, FontCollection, FontFace, FontFile,
|
||||
};
|
||||
use euclid::default::{Point2D, Rect, Size2D};
|
||||
use fonts_traits::LocalFontIdentifier;
|
||||
use log::debug;
|
||||
use read_fonts::TableProvider;
|
||||
use skrifa::Tag;
|
||||
|
@ -24,7 +25,6 @@ use style::Zero;
|
|||
use webrender_api::{FontInstanceFlags, FontVariation};
|
||||
use winapi::shared::minwindef::{BOOL, FALSE};
|
||||
|
||||
use super::font_list::LocalFontIdentifier;
|
||||
use crate::{
|
||||
FontData, FontIdentifier, FontMetrics, FontTableMethods, FontTemplateDescriptor,
|
||||
FractionalPixel, GlyphId, PlatformFontMethods,
|
||||
|
|
|
@ -2,21 +2,18 @@
|
|||
* 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::hash::Hash;
|
||||
use std::sync::Arc;
|
||||
|
||||
use base::text::{UnicodeBlock, UnicodeBlockMethod, unicode_plane};
|
||||
use dwrote::{Font, FontCollection, FontDescriptor, FontStretch, FontStyle};
|
||||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use dwrote::{Font, FontCollection, FontStretch, FontStyle};
|
||||
use fonts_traits::LocalFontIdentifier;
|
||||
use style::values::computed::font::GenericFontFamily;
|
||||
use style::values::computed::{FontStyle as StyleFontStyle, FontWeight as StyleFontWeight};
|
||||
use style::values::specified::font::FontStretchKeyword;
|
||||
use webrender_api::NativeFontHandle;
|
||||
|
||||
use crate::{
|
||||
EmojiPresentationPreference, FallbackFontSelectionOptions, FontData, FontDataAndIndex,
|
||||
FontIdentifier, FontTemplate, FontTemplateDescriptor, LowercaseFontFamilyName,
|
||||
EmojiPresentationPreference, FallbackFontSelectionOptions, FontIdentifier, FontTemplate,
|
||||
FontTemplateDescriptor, LowercaseFontFamilyName,
|
||||
};
|
||||
|
||||
pub fn for_each_available_family<F>(mut callback: F)
|
||||
|
@ -31,71 +28,6 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
/// An identifier for a local font on a Windows system.
|
||||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub struct LocalFontIdentifier {
|
||||
/// The FontDescriptor of this font.
|
||||
#[ignore_malloc_size_of = "dwrote does not support MallocSizeOf"]
|
||||
pub font_descriptor: Arc<FontDescriptor>,
|
||||
}
|
||||
|
||||
impl LocalFontIdentifier {
|
||||
pub fn index(&self) -> u32 {
|
||||
FontCollection::system()
|
||||
.font_from_descriptor(&self.font_descriptor)
|
||||
.ok()
|
||||
.flatten()
|
||||
.map_or(0, |font| font.create_font_face().get_index())
|
||||
}
|
||||
|
||||
pub(crate) fn native_font_handle(&self) -> NativeFontHandle {
|
||||
let face = FontCollection::system()
|
||||
.font_from_descriptor(&self.font_descriptor)
|
||||
.ok()
|
||||
.flatten()
|
||||
.expect("Could not create Font from FontDescriptor")
|
||||
.create_font_face();
|
||||
let path = face
|
||||
.files()
|
||||
.ok()
|
||||
.and_then(|files| files.first().cloned())
|
||||
.expect("Could not get FontFace files")
|
||||
.font_file_path()
|
||||
.ok()
|
||||
.expect("Could not get FontFace files path");
|
||||
NativeFontHandle {
|
||||
path,
|
||||
index: face.get_index(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn font_data_and_index(&self) -> Option<FontDataAndIndex> {
|
||||
let font = FontCollection::system()
|
||||
.font_from_descriptor(&self.font_descriptor)
|
||||
.ok()??;
|
||||
let face = font.create_font_face();
|
||||
let index = face.get_index();
|
||||
let files = face.files().ok()?;
|
||||
assert!(!files.is_empty());
|
||||
|
||||
let data = files[0].font_file_bytes().ok()?;
|
||||
let data = FontData::from_bytes(&data);
|
||||
|
||||
Some(FontDataAndIndex { data, index })
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for LocalFontIdentifier {}
|
||||
|
||||
impl Hash for LocalFontIdentifier {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.font_descriptor.family_name.hash(state);
|
||||
self.font_descriptor.weight.to_u32().hash(state);
|
||||
self.font_descriptor.stretch.to_u32().hash(state);
|
||||
self.font_descriptor.style.to_u32().hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_each_variation<F>(family_name: &str, mut callback: F)
|
||||
where
|
||||
F: FnMut(FontTemplate),
|
||||
|
@ -107,7 +39,7 @@ where
|
|||
let Ok(font) = family.font(i) else {
|
||||
continue;
|
||||
};
|
||||
let template_descriptor = (&font).into();
|
||||
let template_descriptor = font_template_descriptor_from_font(&font);
|
||||
let local_font_identifier = LocalFontIdentifier {
|
||||
font_descriptor: Arc::new(font.to_descriptor()),
|
||||
};
|
||||
|
@ -383,29 +315,27 @@ pub fn fallback_font_families(options: FallbackFontSelectionOptions) -> Vec<&'st
|
|||
families
|
||||
}
|
||||
|
||||
impl From<&Font> for FontTemplateDescriptor {
|
||||
fn from(font: &Font) -> Self {
|
||||
let style = match font.style() {
|
||||
FontStyle::Normal => StyleFontStyle::NORMAL,
|
||||
FontStyle::Oblique => StyleFontStyle::OBLIQUE,
|
||||
FontStyle::Italic => StyleFontStyle::ITALIC,
|
||||
};
|
||||
let weight = StyleFontWeight::from_float(font.weight().to_u32() as f32);
|
||||
let stretch = match font.stretch() {
|
||||
FontStretch::Undefined => FontStretchKeyword::Normal,
|
||||
FontStretch::UltraCondensed => FontStretchKeyword::UltraCondensed,
|
||||
FontStretch::ExtraCondensed => FontStretchKeyword::ExtraCondensed,
|
||||
FontStretch::Condensed => FontStretchKeyword::Condensed,
|
||||
FontStretch::SemiCondensed => FontStretchKeyword::SemiCondensed,
|
||||
FontStretch::Normal => FontStretchKeyword::Normal,
|
||||
FontStretch::SemiExpanded => FontStretchKeyword::SemiExpanded,
|
||||
FontStretch::Expanded => FontStretchKeyword::Expanded,
|
||||
FontStretch::ExtraExpanded => FontStretchKeyword::ExtraExpanded,
|
||||
FontStretch::UltraExpanded => FontStretchKeyword::UltraExpanded,
|
||||
}
|
||||
.compute();
|
||||
FontTemplateDescriptor::new(weight, stretch, style)
|
||||
fn font_template_descriptor_from_font(font: &Font) -> FontTemplateDescriptor {
|
||||
let style = match font.style() {
|
||||
FontStyle::Normal => StyleFontStyle::NORMAL,
|
||||
FontStyle::Oblique => StyleFontStyle::OBLIQUE,
|
||||
FontStyle::Italic => StyleFontStyle::ITALIC,
|
||||
};
|
||||
let weight = StyleFontWeight::from_float(font.weight().to_u32() as f32);
|
||||
let stretch = match font.stretch() {
|
||||
FontStretch::Undefined => FontStretchKeyword::Normal,
|
||||
FontStretch::UltraCondensed => FontStretchKeyword::UltraCondensed,
|
||||
FontStretch::ExtraCondensed => FontStretchKeyword::ExtraCondensed,
|
||||
FontStretch::Condensed => FontStretchKeyword::Condensed,
|
||||
FontStretch::SemiCondensed => FontStretchKeyword::SemiCondensed,
|
||||
FontStretch::Normal => FontStretchKeyword::Normal,
|
||||
FontStretch::SemiExpanded => FontStretchKeyword::SemiExpanded,
|
||||
FontStretch::Expanded => FontStretchKeyword::Expanded,
|
||||
FontStretch::ExtraExpanded => FontStretchKeyword::ExtraExpanded,
|
||||
FontStretch::UltraExpanded => FontStretchKeyword::UltraExpanded,
|
||||
}
|
||||
.compute();
|
||||
FontTemplateDescriptor::new(weight, stretch, style)
|
||||
}
|
||||
|
||||
pub fn default_system_generic_font_family(generic: GenericFontFamily) -> LowercaseFontFamilyName {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue