html: Parse a comma-separated list of faces in the <font> tag (#32622)

This change parses a comma-separated list of faces in the `<font>` tag
and also moves the parsing code from `stylo` to Servo. This means that
the servo-specific code can be removed from stylo decreasing the
differences between Gecko and Servo's version of `stylo`.
This commit is contained in:
Martin Robinson 2024-06-26 20:28:35 +02:00 committed by GitHub
parent 47678a61b9
commit da2de4fc68
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 89 additions and 4 deletions

View file

@ -751,19 +751,18 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> {
)); ));
} }
let font_family = if let Some(this) = self.downcast::<HTMLFontElement>() { let font_face = if let Some(this) = self.downcast::<HTMLFontElement>() {
this.get_face() this.get_face()
} else { } else {
None None
}; };
if let Some(font_family) = font_family { if let Some(font_face) = font_face {
// FIXME(emilio): This in Gecko parses a whole family list.
hints.push(from_declaration( hints.push(from_declaration(
shared_lock, shared_lock,
PropertyDeclaration::FontFamily(font_family::SpecifiedValue::Values( PropertyDeclaration::FontFamily(font_family::SpecifiedValue::Values(
computed::font::FontFamilyList { computed::font::FontFamilyList {
list: Box::new([computed::font::SingleFontFamily::from_atom(font_family)]), list: HTMLFontElement::parse_face_attribute(font_face).into_boxed_slice(),
}, },
)), )),
)); ));

View file

@ -2,6 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use cssparser::match_ignore_ascii_case;
use dom_struct::dom_struct; use dom_struct::dom_struct;
use html5ever::{local_name, namespace_url, ns, LocalName, Prefix}; use html5ever::{local_name, namespace_url, ns, LocalName, Prefix};
use js::rust::HandleObject; use js::rust::HandleObject;
@ -9,6 +10,9 @@ use servo_atoms::Atom;
use style::attr::AttrValue; use style::attr::AttrValue;
use style::color::AbsoluteColor; use style::color::AbsoluteColor;
use style::str::{read_numbers, HTML_SPACE_CHARACTERS}; use style::str::{read_numbers, HTML_SPACE_CHARACTERS};
use style::values::computed::font::{
FamilyName, FontFamilyNameSyntax, GenericFontFamily, SingleFontFamily,
};
use crate::dom::attr::Attr; use crate::dom::attr::Attr;
use crate::dom::bindings::codegen::Bindings::HTMLFontElementBinding::HTMLFontElementMethods; use crate::dom::bindings::codegen::Bindings::HTMLFontElementBinding::HTMLFontElementMethods;
@ -50,6 +54,38 @@ impl HTMLFontElement {
proto, proto,
) )
} }
pub(crate) fn parse_face_attribute(face_value: Atom) -> Vec<SingleFontFamily> {
face_value
.to_string()
.split(",")
.map(|string| Self::parse_single_face_value_from_string(string.trim()))
.collect()
}
fn parse_single_face_value_from_string(string: &str) -> SingleFontFamily {
match_ignore_ascii_case! { string,
"serif" => return SingleFontFamily::Generic(GenericFontFamily::Serif),
"sans-serif" => return SingleFontFamily::Generic(GenericFontFamily::SansSerif),
"cursive" => return SingleFontFamily::Generic(GenericFontFamily::Cursive),
"fantasy" => return SingleFontFamily::Generic(GenericFontFamily::Fantasy),
"monospace" => return SingleFontFamily::Generic(GenericFontFamily::Monospace),
"system-ui" => return SingleFontFamily::Generic(GenericFontFamily::SystemUi),
_ => {}
}
let name = string.to_owned().replace(['\'', '"'], "");
let syntax = if name == string {
FontFamilyNameSyntax::Identifiers
} else {
FontFamilyNameSyntax::Quoted
};
SingleFontFamily::FamilyName(FamilyName {
name: name.into(),
syntax,
})
}
} }
impl HTMLFontElementMethods for HTMLFontElement { impl HTMLFontElementMethods for HTMLFontElement {

View file

@ -7576,6 +7576,19 @@
{} {}
] ]
], ],
"font-element-comma-separated.html": [
"db7e13f2ca3db0ebd3c610c3c25b052749b85e30",
[
null,
[
[
"/_mozilla/mozilla/font-element-comma-separated-ref.html",
"=="
]
],
{}
]
],
"fullscreen": { "fullscreen": {
"reftests": { "reftests": {
"fullscreen-baseline.html": [ "fullscreen-baseline.html": [
@ -10436,6 +10449,10 @@
"6783d72a6629f4938df8126dc5114d936eaaa48f", "6783d72a6629f4938df8126dc5114d936eaaa48f",
[] []
], ],
"font-element-comma-separated-ref.html": [
"97efe2b83d5f78bdac0d4aa951b63342fb1fa1cf",
[]
],
"form_submit_about_frame.html": [ "form_submit_about_frame.html": [
"7beb90f1ab7bce0b162050180c4a44380940aed8", "7beb90f1ab7bce0b162050180c4a44380940aed8",
[] []

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>The &lt;font&gt; element should support a comma separated list of font family names</title>
<link rel="author" title="Martin Robinson" href="mrobinson@igalia.com">
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
</head>
<body>
The elements below should be rendered with the Ahem font and show as a black rectangles.
<br/>
<span style="font-family: 'Ahem', serif;">XXXX</font>
<br/>
<span style="font-family: 'Ahem', serif;">XXXX</font>
</body>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>The &lt;font&gt; element should support a comma separated list of font family names</title>
<link rel="author" title="Martin Robinson" href="mrobinson@igalia.com">
<link rel="match" href="font-element-comma-separated-ref.html">
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css">
</head>
<body>
The elements below should be rendered with the Ahem font and show as a black rectangles.
<br/>
<font face="Ahem, serif">XXXX</font>
<br/>
<font face="'Ahem', serif">XXXX</font>
</body>