mirror of
https://github.com/servo/servo.git
synced 2025-09-29 16:19:14 +01:00
fonts: Implement CSS font-variation-settings
property for FreeType platforms (#38642)
This change adds support for variable fonts via the [`font-variation-settings`](https://developer.mozilla.org/en-US/docs/Web/CSS/font-variation-settings) property. There are three areas where we need to set the variation values: * Webrender (`compositor.rs`), for drawing the glyphs * Harfbuzz (`shaper.rs`), for most shaping tasks * PlatformFont (`fonts/platform/`), for horizontal advances and kerning For now, freetype is the only platform shaper that supports variable fonts. I can't easily test the fonts with non-freetype shapers. Thats why variable fonts are behind the `layout_variable_fonts_enabled` pref, which is disabled by default. <img width="1250" height="710" alt="image" src="https://github.com/user-attachments/assets/1aee1407-f3a2-42f6-a106-af0443fcd588" /> <details><summary>HTML test file</summary> ```html <style> @font-face { font-family: "Amstelvar VF"; src: url("https://mdn.github.io/shared-assets/fonts/variable-fonts/AmstelvarAlpha-VF.woff2") format("woff2-variations"); font-weight: 300 900; font-stretch: 35% 100%; font-style: normal; font-display: swap; } p { font: 1.2em "Amstelvar VF", Georgia, serif; font-size: 4rem; margin: 1rem; display: inline-block; } .p1 { font-variation-settings: "wght" 300; } .p2 { font-variation-settings: "wght" 625; } .p3 { font-variation-settings: "wght" 900; } </style> <div> <p class="p1">Weight</p> <span>(font-variation-settings: "wght" 300)</span> </div> <div> <p class="p2">Weight</p> <span>(font-variation-settings: "wght" 625)</span> </div> <div> <p class="p3">Weight</p> <span>(font-variation-settings: "wght" 900)</span> </div> </div> ``` </details> https://github.com/user-attachments/assets/9e21101a-796a-49fe-b82c-8999d8fa9ee1 Testing: Needs decision on whether we want to enable the pref in CI Works towards https://github.com/servo/servo/issues/37236 Depends on https://github.com/servo/stylo/pull/230 --------- Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
parent
ce16fbce75
commit
7471ad7730
19 changed files with 274 additions and 79 deletions
|
@ -32,7 +32,7 @@ use style::shared_lock::SharedRwLockReadGuard;
|
|||
use style::stylesheets::{CssRule, DocumentStyleSheet, FontFaceRule, StylesheetInDocument};
|
||||
use style::values::computed::font::{FamilyName, FontFamilyNameSyntax, SingleFontFamily};
|
||||
use url::Url;
|
||||
use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey};
|
||||
use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey, FontVariation};
|
||||
|
||||
use crate::font::{
|
||||
Font, FontDescriptor, FontFamilyDescriptor, FontGroup, FontRef, FontSearchScope,
|
||||
|
@ -45,6 +45,8 @@ use crate::{FontData, LowercaseFontFamilyName, PlatformFontMethods, SystemFontSe
|
|||
|
||||
static SMALL_CAPS_SCALE_FACTOR: f32 = 0.8; // Matches FireFox (see gfxFont.h)
|
||||
|
||||
pub type FontParameters = (FontKey, Au, Vec<FontVariation>);
|
||||
|
||||
#[derive(MallocSizeOf)]
|
||||
struct FontGroupRef(#[conditional_malloc_size_of] Arc<RwLock<FontGroup>>);
|
||||
|
||||
|
@ -87,7 +89,7 @@ pub struct FontContext {
|
|||
|
||||
/// A collection of WebRender [`FontInstanceKey`]s generated for the web fonts that
|
||||
/// this [`FontContext`] controls.
|
||||
webrender_font_instance_keys: RwLock<HashMap<(FontKey, Au), FontInstanceKey>>,
|
||||
webrender_font_instance_keys: RwLock<HashMap<FontParameters, FontInstanceKey>>,
|
||||
|
||||
/// The data for each web font [`FontIdentifier`]. This data might be used by more than one
|
||||
/// [`FontTemplate`] as each identifier refers to a URL.
|
||||
|
@ -270,7 +272,7 @@ impl FontContext {
|
|||
) -> Result<FontRef, &'static str> {
|
||||
Ok(FontRef(Arc::new(Font::new(
|
||||
font_template.clone(),
|
||||
font_descriptor.clone(),
|
||||
font_descriptor,
|
||||
self.get_font_data(&font_template.identifier()),
|
||||
synthesized_small_caps,
|
||||
)?)))
|
||||
|
@ -282,11 +284,13 @@ impl FontContext {
|
|||
font.template.identifier(),
|
||||
font.descriptor.pt_size,
|
||||
font.webrender_font_instance_flags(),
|
||||
font.variations().to_owned(),
|
||||
),
|
||||
FontIdentifier::Web(_) => self.create_web_font_instance(
|
||||
font.template.clone(),
|
||||
font.descriptor.pt_size,
|
||||
font.webrender_font_instance_flags(),
|
||||
font.variations().to_owned(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -296,6 +300,7 @@ impl FontContext {
|
|||
font_template: FontTemplateRef,
|
||||
pt_size: Au,
|
||||
flags: FontInstanceFlags,
|
||||
variations: Vec<FontVariation>,
|
||||
) -> FontInstanceKey {
|
||||
let identifier = font_template.identifier().clone();
|
||||
let font_data = self
|
||||
|
@ -318,7 +323,7 @@ impl FontContext {
|
|||
let key = *self
|
||||
.webrender_font_instance_keys
|
||||
.write()
|
||||
.entry((font_key, pt_size))
|
||||
.entry((font_key, pt_size, variations.clone()))
|
||||
.or_insert_with(|| {
|
||||
let font_instance_key = self.system_font_service_proxy.generate_font_instance_key();
|
||||
self.compositor_api.lock().add_font_instance(
|
||||
|
@ -326,6 +331,7 @@ impl FontContext {
|
|||
font_key,
|
||||
pt_size.to_f32_px(),
|
||||
flags,
|
||||
variations,
|
||||
);
|
||||
font_instance_key
|
||||
});
|
||||
|
@ -612,7 +618,7 @@ impl FontContextWebFontMethods for Arc<FontContext> {
|
|||
});
|
||||
|
||||
let mut removed_instance_keys: HashSet<FontInstanceKey> = HashSet::new();
|
||||
webrender_font_instance_keys.retain(|(font_key, _), instance_key| {
|
||||
webrender_font_instance_keys.retain(|(font_key, _, _), instance_key| {
|
||||
if removed_keys.contains(font_key) {
|
||||
removed_instance_keys.insert(*instance_key);
|
||||
false
|
||||
|
@ -857,11 +863,11 @@ impl RemoteWebFontDownloader {
|
|||
|
||||
let url: ServoUrl = self.url.clone().into();
|
||||
let identifier = FontIdentifier::Web(url.clone());
|
||||
let Ok(handle) = PlatformFont::new_from_data(identifier, &font_data, None) else {
|
||||
let Ok(handle) = PlatformFont::new_from_data(identifier, &font_data, None, &[]) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let state = self.take_state();
|
||||
|
||||
let mut descriptor = handle.descriptor();
|
||||
descriptor
|
||||
.override_values_with_css_font_template_descriptors(&state.css_font_face_descriptors);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue