Skip to content

Improve loading of @font-face rules #45975

Description

@simonwuelker

The current mechanism for loading @font-face rules is pretty naive: Whenever a new stylesheet is added to the page, we walk through all its rules and load any @font-faces we find. This happens here:

for rule in stylesheet
.contents(guard)
.effective_rules(device, custom_media, guard)
{
let CssRule::FontFace(ref lock) = *rule else {
continue;
};
let rule: &FontFaceRule = lock.read_with(guard);
// Per https://github.com/w3c/csswg-drafts/issues/1133 an @font-face rule
// is valid as far as the CSS parser is concerned even if it doesn’t have
// a font-family or src declaration.
// However, both are required for the rule to represent an actual font face.
if rule.descriptors.font_family.is_none() {
continue;
}
let Some(ref sources) = rule.descriptors.src else {
continue;
};
let css_font_face_descriptors = rule.into();
let initiator = FontFaceRuleInitiator {
stylesheet: stylesheet.clone(),
font_face_rule: rule.descriptors.clone(),
callback: finished_callback.clone(),
};
number_loading += 1;
self.start_loading_one_web_font(
Some(webview_id),
sources,
css_font_face_descriptors,
WebFontLoadInitiator::Stylesheet(Box::new(initiator)),
document_context,
);
}
number_loading
}

Whenever a stylesheet is removed then we in turn remove all web fonts associated with it.

We should buffer loading and unloading font faces until a reflow occurs (In theory we should not download font faces until they are used by the page, but thats a separate issue). That way we save work if a stylesheet is removed and reinserted.
That can be implemented by using the list of applicable @font-faces stored in the Stylist (https://docs.rs/stylo/latest/style/stylist/struct.ExtraStyleData.html), which also saves us from having to walk over the entire stylesheet.

#45901 prepares servo to use the data from the stylist. A second PR will implement the rest.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions