mirror of
https://github.com/servo/servo.git
synced 2025-08-10 16:05:43 +01:00
fonts: Add support for more @font-face features (#32164)
There are a couple major changes here: 1. Support is added for the `weight`, `style`, `stretch` and `unicode-range` declarations in `@font-face`. 2. Font matching in the font cache can return templates and `FontGroupFamily` can own mulitple templates. This is due to needing support for "composite fonts". These are `@font-face` declarations that only differ in their `unicode-range` definition. This fixes a lot of non-determinism in font selection especially when dealing with pages that define "composite faces." A notable example of such a page is servo.org, which now consistently displays the correct web font. One test starts to fail due to an uncovered bug, but this will be fixed in a followup change. Fixes #20686. Fixes #20684. Co-authored-by: Mukilan Thiyagarajan <mukilan@igalia.com>
This commit is contained in:
parent
628e33bfa9
commit
4732da3477
56 changed files with 613 additions and 593 deletions
|
@ -12,12 +12,10 @@ use std::rc::Rc;
|
|||
use app_units::Au;
|
||||
use gfx::font::{
|
||||
fallback_font_families, FontDescriptor, FontFamilyDescriptor, FontFamilyName, FontSearchScope,
|
||||
PlatformFontMethods,
|
||||
};
|
||||
use gfx::font_cache_thread::{FontIdentifier, FontTemplateAndWebRenderFontKey, FontTemplates};
|
||||
use gfx::font_cache_thread::{CSSFontFaceDescriptors, FontIdentifier, FontTemplates};
|
||||
use gfx::font_context::{FontContext, FontSource};
|
||||
use gfx::font_template::{FontTemplate, FontTemplateDescriptor};
|
||||
use gfx::platform::font::PlatformFont;
|
||||
use gfx::font_template::{FontTemplate, FontTemplateRef};
|
||||
use servo_arc::Arc;
|
||||
use servo_atoms::Atom;
|
||||
use servo_url::ServoUrl;
|
||||
|
@ -29,7 +27,7 @@ use style::values::computed::font::{
|
|||
};
|
||||
use style::values::computed::{FontLanguageOverride, XLang};
|
||||
use style::values::generics::font::LineHeight;
|
||||
use webrender_api::{FontInstanceKey, FontKey, IdNamespace};
|
||||
use webrender_api::{FontInstanceKey, IdNamespace};
|
||||
|
||||
struct TestFontSource {
|
||||
families: HashMap<String, FontTemplates>,
|
||||
|
@ -78,40 +76,36 @@ impl TestFontSource {
|
|||
|
||||
let file = File::open(path).unwrap();
|
||||
let data: Vec<u8> = file.bytes().map(|b| b.unwrap()).collect();
|
||||
let data = std::sync::Arc::new(data);
|
||||
let handle = PlatformFont::new_from_data(
|
||||
Self::identifier_for_font_name(name),
|
||||
data.clone(),
|
||||
0,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
family.add_template(FontTemplate::new_web_font(
|
||||
Self::url_for_font_name(name),
|
||||
handle.descriptor(),
|
||||
data,
|
||||
));
|
||||
family.add_template(
|
||||
FontTemplate::new_web_font(
|
||||
Self::url_for_font_name(name),
|
||||
std::sync::Arc::new(data),
|
||||
CSSFontFaceDescriptors::new(name),
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl FontSource for TestFontSource {
|
||||
fn get_font_instance(&mut self, _key: FontKey, _size: Au) -> FontInstanceKey {
|
||||
fn get_font_instance(
|
||||
&mut self,
|
||||
_font_identifier: FontIdentifier,
|
||||
_size: Au,
|
||||
) -> FontInstanceKey {
|
||||
FontInstanceKey(IdNamespace(0), 0)
|
||||
}
|
||||
|
||||
fn font_template(
|
||||
fn find_matching_font_templates(
|
||||
&mut self,
|
||||
template_descriptor: FontTemplateDescriptor,
|
||||
descriptor_to_match: &FontDescriptor,
|
||||
family_descriptor: FontFamilyDescriptor,
|
||||
) -> Option<FontTemplateAndWebRenderFontKey> {
|
||||
) -> Vec<FontTemplateRef> {
|
||||
self.find_font_count.set(self.find_font_count.get() + 1);
|
||||
self.families
|
||||
.get_mut(family_descriptor.name())
|
||||
.and_then(|family| family.find_font_for_style(&template_descriptor))
|
||||
.map(|template| FontTemplateAndWebRenderFontKey {
|
||||
font_template: template,
|
||||
font_key: FontKey(IdNamespace(0), 0),
|
||||
})
|
||||
.map(|family| family.find_for_descriptor(descriptor_to_match))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +185,7 @@ fn test_font_group_find_by_codepoint() {
|
|||
.find_by_codepoint(&mut context, 'a')
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
font.borrow().template.borrow().identifier,
|
||||
font.borrow().identifier(),
|
||||
TestFontSource::identifier_for_font_name("csstest-ascii")
|
||||
);
|
||||
assert_eq!(
|
||||
|
@ -205,7 +199,7 @@ fn test_font_group_find_by_codepoint() {
|
|||
.find_by_codepoint(&mut context, 'a')
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
font.borrow().template.borrow().identifier,
|
||||
font.borrow().identifier(),
|
||||
TestFontSource::identifier_for_font_name("csstest-ascii")
|
||||
);
|
||||
assert_eq!(
|
||||
|
@ -219,7 +213,7 @@ fn test_font_group_find_by_codepoint() {
|
|||
.find_by_codepoint(&mut context, 'á')
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
font.borrow().template.borrow().identifier,
|
||||
font.borrow().identifier(),
|
||||
TestFontSource::identifier_for_font_name("csstest-basic-regular")
|
||||
);
|
||||
assert_eq!(count.get(), 2, "both fonts should now have been loaded");
|
||||
|
@ -240,7 +234,7 @@ fn test_font_fallback() {
|
|||
.find_by_codepoint(&mut context, 'a')
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
font.borrow().template.borrow().identifier,
|
||||
font.borrow().identifier(),
|
||||
TestFontSource::identifier_for_font_name("csstest-ascii"),
|
||||
"a family in the group should be used if there is a matching glyph"
|
||||
);
|
||||
|
@ -250,7 +244,7 @@ fn test_font_fallback() {
|
|||
.find_by_codepoint(&mut context, 'á')
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
font.borrow().template.borrow().identifier,
|
||||
font.borrow().identifier(),
|
||||
TestFontSource::identifier_for_font_name("csstest-basic-regular"),
|
||||
"a fallback font should be used if there is no matching glyph in the group"
|
||||
);
|
||||
|
@ -263,11 +257,9 @@ fn test_font_template_is_cached() {
|
|||
let mut context = FontContext::new(source);
|
||||
|
||||
let mut font_descriptor = FontDescriptor {
|
||||
template_descriptor: FontTemplateDescriptor {
|
||||
weight: FontWeight::normal(),
|
||||
stretch: FontStretch::hundred(),
|
||||
style: FontStyle::normal(),
|
||||
},
|
||||
weight: FontWeight::normal(),
|
||||
stretch: FontStretch::hundred(),
|
||||
style: FontStyle::normal(),
|
||||
variant: FontVariantCaps::Normal,
|
||||
pt_size: Au(10),
|
||||
};
|
||||
|
@ -275,10 +267,16 @@ fn test_font_template_is_cached() {
|
|||
let family_descriptor =
|
||||
FontFamilyDescriptor::new(FontFamilyName::from("CSSTest Basic"), FontSearchScope::Any);
|
||||
|
||||
let font1 = context.font(&font_descriptor, &family_descriptor).unwrap();
|
||||
let font_template = context.matching_templates(&font_descriptor, &family_descriptor)[0].clone();
|
||||
|
||||
let font1 = context
|
||||
.font(font_template.clone(), &font_descriptor)
|
||||
.unwrap();
|
||||
|
||||
font_descriptor.pt_size = Au(20);
|
||||
let font2 = context.font(&font_descriptor, &family_descriptor).unwrap();
|
||||
let font2 = context
|
||||
.font(font_template.clone(), &font_descriptor)
|
||||
.unwrap();
|
||||
|
||||
assert_ne!(
|
||||
font1.borrow().descriptor.pt_size,
|
||||
|
|
|
@ -39,37 +39,33 @@ fn test_font_template_descriptor() {
|
|||
|
||||
assert_eq!(
|
||||
descriptor("DejaVuSans"),
|
||||
FontTemplateDescriptor {
|
||||
weight: FontWeight::NORMAL,
|
||||
stretch: FontStretch::hundred(),
|
||||
style: FontStyle::NORMAL,
|
||||
}
|
||||
FontTemplateDescriptor::new(
|
||||
FontWeight::NORMAL,
|
||||
FontStretch::hundred(),
|
||||
FontStyle::NORMAL,
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
descriptor("DejaVuSans-Bold"),
|
||||
FontTemplateDescriptor {
|
||||
weight: FontWeight::BOLD,
|
||||
stretch: FontStretch::hundred(),
|
||||
style: FontStyle::NORMAL,
|
||||
}
|
||||
FontTemplateDescriptor::new(FontWeight::BOLD, FontStretch::hundred(), FontStyle::NORMAL,)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
descriptor("DejaVuSans-Oblique"),
|
||||
FontTemplateDescriptor {
|
||||
weight: FontWeight::NORMAL,
|
||||
stretch: FontStretch::hundred(),
|
||||
style: FontStyle::ITALIC,
|
||||
}
|
||||
FontTemplateDescriptor::new(
|
||||
FontWeight::NORMAL,
|
||||
FontStretch::hundred(),
|
||||
FontStyle::ITALIC,
|
||||
)
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
descriptor("DejaVuSansCondensed-BoldOblique"),
|
||||
FontTemplateDescriptor {
|
||||
weight: FontWeight::BOLD,
|
||||
stretch: FontStretch::from_percentage(0.875),
|
||||
style: FontStyle::ITALIC,
|
||||
}
|
||||
FontTemplateDescriptor::new(
|
||||
FontWeight::BOLD,
|
||||
FontStretch::from_percentage(0.875),
|
||||
FontStyle::ITALIC,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue