mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-28 11:49:44 +00:00
LibWeb: Parse oblique font-style
with an angle value
This commit is contained in:
parent
e537e426c1
commit
c0f9b11070
Notes:
github-actions[bot]
2025-05-03 10:06:24 +00:00
Author: https://github.com/tcl3
Commit: c0f9b11070
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4552
Reviewed-by: https://github.com/konradekk
13 changed files with 172 additions and 31 deletions
|
@ -173,6 +173,7 @@ set(SOURCES
|
|||
CSS/StyleValues/EdgeStyleValue.cpp
|
||||
CSS/StyleValues/FilterValueListStyleValue.cpp
|
||||
CSS/StyleValues/FontSourceStyleValue.cpp
|
||||
CSS/StyleValues/FontStyleStyleValue.cpp
|
||||
CSS/StyleValues/GridAutoFlowStyleValue.cpp
|
||||
CSS/StyleValues/GridTemplateAreaStyleValue.cpp
|
||||
CSS/StyleValues/GridTrackPlacementStyleValue.cpp
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <LibWeb/CSS/StyleValues/FitContentStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/FlexStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/FontSourceStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/FontStyleStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/FrequencyStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/GridAutoFlowStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.h>
|
||||
|
@ -203,6 +204,12 @@ FontSourceStyleValue const& CSSStyleValue::as_font_source() const
|
|||
return static_cast<FontSourceStyleValue const&>(*this);
|
||||
}
|
||||
|
||||
FontStyleStyleValue const& CSSStyleValue::as_font_style() const
|
||||
{
|
||||
VERIFY(is_font_style());
|
||||
return static_cast<FontStyleStyleValue const&>(*this);
|
||||
}
|
||||
|
||||
FrequencyStyleValue const& CSSStyleValue::as_frequency() const
|
||||
{
|
||||
VERIFY(is_frequency());
|
||||
|
|
|
@ -107,6 +107,7 @@ public:
|
|||
FitContent,
|
||||
Flex,
|
||||
FontSource,
|
||||
FontStyle,
|
||||
FontVariant,
|
||||
Frequency,
|
||||
GridAutoFlow,
|
||||
|
@ -234,6 +235,10 @@ public:
|
|||
FontSourceStyleValue const& as_font_source() const;
|
||||
FontSourceStyleValue& as_font_source() { return const_cast<FontSourceStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_font_source()); }
|
||||
|
||||
bool is_font_style() const { return type() == Type::FontStyle; }
|
||||
FontStyleStyleValue const& as_font_style() const;
|
||||
FontStyleStyleValue& as_font_style() { return const_cast<FontStyleStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_font_style()); }
|
||||
|
||||
bool is_frequency() const { return type() == Type::Frequency; }
|
||||
FrequencyStyleValue const& as_frequency() const;
|
||||
FrequencyStyleValue& as_frequency() { return const_cast<FrequencyStyleValue&>(const_cast<CSSStyleValue const&>(*this).as_frequency()); }
|
||||
|
|
|
@ -247,6 +247,13 @@
|
|||
"fallback",
|
||||
"optional"
|
||||
],
|
||||
"font-style": [
|
||||
"normal",
|
||||
"italic",
|
||||
"left",
|
||||
"right",
|
||||
"oblique"
|
||||
],
|
||||
"font-variant-alternates": [
|
||||
"normal",
|
||||
"historical-forms"
|
||||
|
|
|
@ -394,6 +394,7 @@ private:
|
|||
RefPtr<CSSStyleValue const> parse_font_family_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<CSSStyleValue const> parse_font_language_override_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<CSSStyleValue const> parse_font_feature_settings_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<CSSStyleValue const> parse_font_style_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<CSSStyleValue const> parse_font_variation_settings_value(TokenStream<ComponentValue>&);
|
||||
RefPtr<CSSStyleValue const> parse_font_variant(TokenStream<ComponentValue>&);
|
||||
RefPtr<CSSStyleValue const> parse_font_variant_alternates_value(TokenStream<ComponentValue>&);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <LibWeb/CSS/StyleValues/FilterValueListStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/FitContentStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/FlexStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/FontStyleStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/FrequencyStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/GridAutoFlowStyleValue.h>
|
||||
#include <LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.h>
|
||||
|
@ -523,6 +524,10 @@ Parser::ParseErrorOr<NonnullRefPtr<CSSStyleValue const>> Parser::parse_css_value
|
|||
if (auto parsed_value = parse_font_language_override_value(tokens); parsed_value && !tokens.has_next_token())
|
||||
return parsed_value.release_nonnull();
|
||||
return ParseError::SyntaxError;
|
||||
case PropertyID::FontStyle:
|
||||
if (auto parsed_value = parse_font_style_value(tokens); parsed_value && !tokens.has_next_token())
|
||||
return parsed_value.release_nonnull();
|
||||
return ParseError::SyntaxError;
|
||||
case PropertyID::FontVariationSettings:
|
||||
if (auto parsed_value = parse_font_variation_settings_value(tokens); parsed_value && !tokens.has_next_token())
|
||||
return parsed_value.release_nonnull();
|
||||
|
@ -2361,7 +2366,7 @@ RefPtr<CSSStyleValue const> Parser::parse_font_value(TokenStream<ComponentValue>
|
|||
}
|
||||
case PropertyID::FontStyle: {
|
||||
VERIFY(!font_style);
|
||||
font_style = value.release_nonnull();
|
||||
font_style = FontStyleStyleValue::create(*keyword_to_font_style(value.release_nonnull()->to_keyword()));
|
||||
continue;
|
||||
}
|
||||
case PropertyID::FontVariant: {
|
||||
|
@ -2597,6 +2602,34 @@ RefPtr<CSSStyleValue const> Parser::parse_font_feature_settings_value(TokenStrea
|
|||
return StyleValueList::create(move(feature_tags), StyleValueList::Separator::Comma);
|
||||
}
|
||||
|
||||
RefPtr<CSSStyleValue const> Parser::parse_font_style_value(TokenStream<ComponentValue>& tokens)
|
||||
{
|
||||
// https://drafts.csswg.org/css-fonts/#font-style-prop
|
||||
// normal | italic | left | right | oblique <angle [-90deg,90deg]>?
|
||||
auto transaction = tokens.begin_transaction();
|
||||
auto keyword_value = parse_css_value_for_property(PropertyID::FontStyle, tokens);
|
||||
if (!keyword_value)
|
||||
return nullptr;
|
||||
auto font_style = keyword_to_font_style(keyword_value->to_keyword());
|
||||
VERIFY(font_style.has_value());
|
||||
if (tokens.has_next_token() && keyword_value->to_keyword() == Keyword::Oblique) {
|
||||
if (auto angle_value = parse_angle_value(tokens)) {
|
||||
if (angle_value->is_angle()) {
|
||||
auto angle = angle_value->as_angle().angle();
|
||||
auto angle_degrees = angle.to_degrees();
|
||||
if (angle_degrees < -90 || angle_degrees > 90)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
transaction.commit();
|
||||
return FontStyleStyleValue::create(*font_style, angle_value);
|
||||
}
|
||||
}
|
||||
|
||||
transaction.commit();
|
||||
return FontStyleStyleValue::create(*font_style);
|
||||
}
|
||||
|
||||
RefPtr<CSSStyleValue const> Parser::parse_font_variation_settings_value(TokenStream<ComponentValue>& tokens)
|
||||
{
|
||||
// https://drafts.csswg.org/css-fonts/#propdef-font-variation-settings
|
||||
|
|
|
@ -1440,10 +1440,8 @@
|
|||
"animation-type": "custom",
|
||||
"inherited": true,
|
||||
"initial": "normal",
|
||||
"valid-identifiers": [
|
||||
"italic",
|
||||
"normal",
|
||||
"oblique"
|
||||
"valid-types": [
|
||||
"font-style"
|
||||
]
|
||||
},
|
||||
"font-variant": {
|
||||
|
|
42
Libraries/LibWeb/CSS/StyleValues/FontStyleStyleValue.cpp
Normal file
42
Libraries/LibWeb/CSS/StyleValues/FontStyleStyleValue.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Tim Ledbetter <tim.ledbetter@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include "FontStyleStyleValue.h"
|
||||
#include <LibWeb/CSS/CSSStyleValue.h>
|
||||
#include <LibWeb/CSS/Serialize.h>
|
||||
#include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
FontStyleStyleValue::FontStyleStyleValue(FontStyle font_style, ValueComparingRefPtr<CSSStyleValue const> angle_value)
|
||||
: StyleValueWithDefaultOperators(Type::FontStyle)
|
||||
, m_font_style(font_style)
|
||||
, m_angle_value(angle_value)
|
||||
{
|
||||
}
|
||||
|
||||
FontStyleStyleValue::~FontStyleStyleValue() = default;
|
||||
|
||||
String FontStyleStyleValue::to_string(SerializationMode mode) const
|
||||
{
|
||||
Optional<String> angle_string;
|
||||
if (m_angle_value) {
|
||||
angle_string = m_angle_value->to_string(mode);
|
||||
if (m_font_style == FontStyle::Oblique && angle_string == "0deg"sv)
|
||||
return "normal"_string;
|
||||
}
|
||||
StringBuilder builder;
|
||||
builder.append(CSS::to_string(m_font_style));
|
||||
// https://drafts.csswg.org/css-fonts/#valdef-font-style-oblique-angle--90deg-90deg
|
||||
// The lack of an <angle> represents 14deg. (Note that a font might internally provide its own mapping for "oblique", but the mapping within the font is disregarded.)
|
||||
static auto default_angle = Angle::make_degrees(14);
|
||||
if (angle_string.has_value() && !(m_angle_value->is_angle() && m_angle_value->as_angle().angle() == default_angle))
|
||||
builder.appendff(" {}", angle_string);
|
||||
|
||||
return MUST(builder.to_string());
|
||||
}
|
||||
|
||||
}
|
45
Libraries/LibWeb/CSS/StyleValues/FontStyleStyleValue.h
Normal file
45
Libraries/LibWeb/CSS/StyleValues/FontStyleStyleValue.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Tim Ledbetter <tim.ledbetter@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibWeb/CSS/CSSStyleValue.h>
|
||||
#include <LibWeb/CSS/Enums.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
class FontStyleStyleValue final : public StyleValueWithDefaultOperators<FontStyleStyleValue> {
|
||||
public:
|
||||
static ValueComparingNonnullRefPtr<FontStyleStyleValue const> create(FontStyle font_style, ValueComparingRefPtr<CSSStyleValue const> angle_value = {})
|
||||
{
|
||||
return adopt_ref(*new (nothrow) FontStyleStyleValue(font_style, angle_value));
|
||||
}
|
||||
|
||||
virtual ~FontStyleStyleValue() override;
|
||||
|
||||
FontStyle font_style() const { return m_font_style; }
|
||||
ValueComparingRefPtr<CSSStyleValue const> angle() const { return m_angle_value; }
|
||||
|
||||
virtual String to_string(SerializationMode) const override;
|
||||
|
||||
bool equals(CSSStyleValue const& other) const override
|
||||
{
|
||||
if (type() != other.type())
|
||||
return false;
|
||||
auto const& other_font_style = other.as_font_style();
|
||||
return m_font_style == other_font_style.m_font_style && m_angle_value == other_font_style.m_angle_value;
|
||||
}
|
||||
|
||||
bool properties_equal(FontStyleStyleValue const& other) const { return m_font_style == other.m_font_style && m_angle_value == other.m_angle_value; }
|
||||
|
||||
private:
|
||||
FontStyleStyleValue(FontStyle, ValueComparingRefPtr<CSSStyleValue const> angle_value);
|
||||
|
||||
FontStyle m_font_style;
|
||||
ValueComparingRefPtr<CSSStyleValue const> m_angle_value;
|
||||
};
|
||||
|
||||
}
|
|
@ -233,8 +233,9 @@ String ShorthandStyleValue::to_string(SerializationMode mode) const
|
|||
builder.append(' ');
|
||||
builder.append(string);
|
||||
};
|
||||
if (font_style->to_keyword() != Keyword::Normal && font_style->to_keyword() != Keyword::Initial)
|
||||
append(font_style->to_string(mode));
|
||||
auto font_style_string = font_style->to_string(mode);
|
||||
if (font_style_string != "normal"sv)
|
||||
append(font_style_string);
|
||||
if (font_variant_string != "normal"sv && font_variant_string != "initial"sv)
|
||||
append(font_variant_string);
|
||||
if (font_weight->to_font_weight() != Gfx::FontWeight::Regular && font_weight->to_keyword() != Keyword::Initial)
|
||||
|
|
|
@ -204,6 +204,7 @@ class FlexStyleValue;
|
|||
class FontFace;
|
||||
class FontFaceSet;
|
||||
class FontSourceStyleValue;
|
||||
class FontStyleStyleValue;
|
||||
class Frequency;
|
||||
class FrequencyOrCalculated;
|
||||
class FrequencyPercentage;
|
||||
|
|
|
@ -2,20 +2,20 @@ Harness status: OK
|
|||
|
||||
Found 15 tests
|
||||
|
||||
3 Pass
|
||||
12 Fail
|
||||
12 Pass
|
||||
3 Fail
|
||||
Pass Property font-style value 'normal'
|
||||
Pass Property font-style value 'italic'
|
||||
Pass Property font-style value 'oblique'
|
||||
Fail Property font-style value 'oblique 0deg'
|
||||
Fail Property font-style value 'oblique calc(10deg - 10deg)'
|
||||
Fail Property font-style value 'oblique 10deg'
|
||||
Fail Property font-style value 'oblique -10deg'
|
||||
Fail Property font-style value 'oblique -90deg'
|
||||
Fail Property font-style value 'oblique 90deg'
|
||||
Fail Property font-style value 'oblique 10grad'
|
||||
Fail Property font-style value 'oblique calc(90deg)'
|
||||
Pass Property font-style value 'oblique 0deg'
|
||||
Pass Property font-style value 'oblique calc(10deg - 10deg)'
|
||||
Pass Property font-style value 'oblique 10deg'
|
||||
Pass Property font-style value 'oblique -10deg'
|
||||
Pass Property font-style value 'oblique -90deg'
|
||||
Pass Property font-style value 'oblique 90deg'
|
||||
Pass Property font-style value 'oblique 10grad'
|
||||
Pass Property font-style value 'oblique calc(90deg)'
|
||||
Fail Property font-style value 'oblique calc(100deg)'
|
||||
Fail Property font-style value 'oblique calc(-100deg)'
|
||||
Fail Property font-style value 'oblique calc(30deg * 2)'
|
||||
Pass Property font-style value 'oblique calc(30deg * 2)'
|
||||
Fail Property font-style value 'oblique calc(30deg + (sign(20cqw - 10px) * 5deg))'
|
|
@ -2,20 +2,20 @@ Harness status: OK
|
|||
|
||||
Found 15 tests
|
||||
|
||||
3 Pass
|
||||
12 Fail
|
||||
14 Pass
|
||||
1 Fail
|
||||
Pass e.style['font-style'] = "normal" should set the property value
|
||||
Pass e.style['font-style'] = "italic" should set the property value
|
||||
Pass e.style['font-style'] = "oblique" should set the property value
|
||||
Fail e.style['font-style'] = "oblique 0deg" should set the property value
|
||||
Fail e.style['font-style'] = "oblique calc(10deg - 10deg)" should set the property value
|
||||
Fail e.style['font-style'] = "oblique 10deg" should set the property value
|
||||
Fail e.style['font-style'] = "oblique -10deg" should set the property value
|
||||
Fail e.style['font-style'] = "oblique -90deg" should set the property value
|
||||
Fail e.style['font-style'] = "oblique 90deg" should set the property value
|
||||
Fail e.style['font-style'] = "oblique 10grad" should set the property value
|
||||
Fail e.style['font-style'] = "oblique calc(90deg)" should set the property value
|
||||
Fail e.style['font-style'] = "oblique calc(100deg)" should set the property value
|
||||
Fail e.style['font-style'] = "oblique calc(-100deg)" should set the property value
|
||||
Fail e.style['font-style'] = "oblique calc(30deg * 2)" should set the property value
|
||||
Pass e.style['font-style'] = "oblique 0deg" should set the property value
|
||||
Pass e.style['font-style'] = "oblique calc(10deg - 10deg)" should set the property value
|
||||
Pass e.style['font-style'] = "oblique 10deg" should set the property value
|
||||
Pass e.style['font-style'] = "oblique -10deg" should set the property value
|
||||
Pass e.style['font-style'] = "oblique -90deg" should set the property value
|
||||
Pass e.style['font-style'] = "oblique 90deg" should set the property value
|
||||
Pass e.style['font-style'] = "oblique 10grad" should set the property value
|
||||
Pass e.style['font-style'] = "oblique calc(90deg)" should set the property value
|
||||
Pass e.style['font-style'] = "oblique calc(100deg)" should set the property value
|
||||
Pass e.style['font-style'] = "oblique calc(-100deg)" should set the property value
|
||||
Pass e.style['font-style'] = "oblique calc(30deg * 2)" should set the property value
|
||||
Fail e.style['font-style'] = "oblique calc(30deg + (sign(2cqw - 10px) * 5deg))" should set the property value
|
Loading…
Add table
Add a link
Reference in a new issue