1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 21:07:35 +00:00

LibWeb: Implement and use FontStyleValue

After working with the code for a while, it makes more sense to put all
the parsing in Parser, instead of some of it living in StyleResolver.
That means our current ValueListStyleValue needs to be replaced with
specific StyleValue types for the properties that are shorthands or
otherwise combine several values together.

Here we implement FontStyleProperty, which represents a `font` CSS
property.

Also adjusted the fonts.html test page so that font-weights are featured
in test cases without things we do not yet support.
This commit is contained in:
Sam Atkins 2021-08-03 11:37:24 +01:00 committed by Andreas Kling
parent 5e1fad2dff
commit 59501f1940
5 changed files with 247 additions and 164 deletions

View file

@ -326,76 +326,6 @@ static inline bool is_font_family(StyleValue const& value)
}
}
static inline bool is_font_size(StyleValue const& value)
{
if (value.is_builtin_or_dynamic())
return true;
if (value.is_length())
return true;
switch (value.to_identifier()) {
case ValueID::XxSmall:
case ValueID::XSmall:
case ValueID::Small:
case ValueID::Medium:
case ValueID::Large:
case ValueID::XLarge:
case ValueID::XxLarge:
case ValueID::XxxLarge:
case ValueID::Smaller:
case ValueID::Larger:
return true;
default:
return false;
}
}
static inline bool is_font_style(StyleValue const& value)
{
// FIXME: Handle angle parameter to `oblique`: https://www.w3.org/TR/css-fonts-4/#font-style-prop
if (value.is_builtin_or_dynamic())
return true;
switch (value.to_identifier()) {
case ValueID::Normal:
case ValueID::Italic:
case ValueID::Oblique:
return true;
default:
return false;
}
}
static inline bool is_font_weight(StyleValue const& value)
{
if (value.is_builtin_or_dynamic())
return true;
if (value.is_numeric()) {
auto weight = static_cast<NumericStyleValue const&>(value).value();
return (weight >= 1 && weight <= 1000);
}
switch (value.to_identifier()) {
case ValueID::Normal:
case ValueID::Bold:
case ValueID::Bolder:
case ValueID::Lighter:
return true;
default:
return false;
}
}
static inline bool is_line_height(StyleValue const& value)
{
if (value.is_builtin_or_dynamic())
return true;
if (value.is_numeric())
return true;
if (value.is_length())
return true;
if (value.to_identifier() == ValueID::Normal)
return true;
return false;
}
static inline bool is_line_style(StyleValue const& value)
{
if (value.is_builtin_or_dynamic())
@ -1096,103 +1026,27 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
}
if (property_id == CSS::PropertyID::Font) {
if (value.is_component_value_list()) {
auto parts = static_cast<CSS::ValueListStyleValue const&>(value).values();
RefPtr<StyleValue> font_style_value;
RefPtr<StyleValue> font_weight_value;
RefPtr<StyleValue> font_size_value;
RefPtr<StyleValue> line_height_value;
RefPtr<StyleValue> font_family_value;
// FIXME: Implement font-stretch and font-variant.
for (size_t i = 0; i < parts.size(); ++i) {
auto value = Parser::parse_css_value(context, property_id, parts[i]);
if (!value)
return;
if (is_font_style(*value)) {
if (font_style_value)
return;
font_style_value = move(value);
continue;
}
if (is_font_weight(*value)) {
if (font_weight_value)
return;
font_weight_value = move(value);
continue;
}
if (is_font_size(*value)) {
if (font_size_value)
return;
font_size_value = move(value);
// Consume `/ line-height` if present
if (i + 2 < parts.size()) {
auto solidus_part = parts[i + 1];
if (!(solidus_part.is(Token::Type::Delim) && solidus_part.token().delim() == "/"sv))
break;
auto line_height = Parser::parse_css_value(context, property_id, parts[i + 2]);
if (!(line_height && is_line_height(*line_height)))
return;
line_height_value = move(line_height);
i += 2;
}
// Consume font-family
// FIXME: Handle multiple font-families separated by commas, for fallback purposes.
if (i + 1 < parts.size()) {
auto& font_family_part = parts[i + 1];
auto font_family = Parser::parse_css_value(context, property_id, font_family_part);
if (!font_family) {
// Single-word font-families may not be quoted. We convert it to a String for convenience.
if (font_family_part.is(Token::Type::Ident))
font_family = StringStyleValue::create(font_family_part.token().ident());
else
return;
} else if (!is_font_family(*font_family)) {
dbgln("*** Unable to parse '{}' as a font-family.", font_family_part.to_debug_string());
return;
}
font_family_value = move(font_family);
}
break;
}
return;
}
if (!font_size_value || !font_family_value)
return;
style.set_property(CSS::PropertyID::FontSize, *font_size_value);
style.set_property(CSS::PropertyID::FontFamily, *font_family_value);
if (font_style_value)
style.set_property(CSS::PropertyID::FontStyle, *font_style_value);
if (font_weight_value)
style.set_property(CSS::PropertyID::FontWeight, *font_weight_value);
if (line_height_value)
style.set_property(CSS::PropertyID::LineHeight, *line_height_value);
if (value.is_font()) {
auto& font_shorthand = static_cast<CSS::FontStyleValue const&>(value);
style.set_property(CSS::PropertyID::FontSize, font_shorthand.font_size());
// FIXME: Support multiple font-families
style.set_property(CSS::PropertyID::FontFamily, font_shorthand.font_families().first());
style.set_property(CSS::PropertyID::FontStyle, font_shorthand.font_style());
style.set_property(CSS::PropertyID::FontWeight, font_shorthand.font_weight());
style.set_property(CSS::PropertyID::LineHeight, font_shorthand.line_height());
// FIXME: Implement font-stretch and font-variant
return;
}
if (value.is_inherit()) {
if (value.is_builtin()) {
style.set_property(CSS::PropertyID::FontSize, value);
// FIXME: Support multiple font-families
style.set_property(CSS::PropertyID::FontFamily, value);
style.set_property(CSS::PropertyID::FontStyle, value);
style.set_property(CSS::PropertyID::FontVariant, value);
style.set_property(CSS::PropertyID::FontWeight, value);
style.set_property(CSS::PropertyID::LineHeight, value);
// FIXME: Implement font-stretch
// FIXME: Implement font-stretch and font-variant
return;
}
// FIXME: Handle system fonts. (caption, icon, menu, message-box, small-caption, status-bar)
return;
}
@ -1211,11 +1065,7 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
return;
}
if (is_font_family(value)) {
style.set_property(CSS::PropertyID::FontFamily, value);
return;
}
style.set_property(CSS::PropertyID::FontFamily, value);
return;
}