diff --git a/Tests/LibWeb/Text/expected/css/FontFace.txt b/Tests/LibWeb/Text/expected/css/FontFace.txt
new file mode 100644
index 00000000000..64358935537
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/css/FontFace.txt
@@ -0,0 +1,19 @@
+face.family: Some font family
+face.style: normal
+face.weight: normal
+face.stretch: normal
+face.unicodeRange: U+0-10FFFF
+face.featureSettings: normal
+face.variationSettings: normal
+face.display: auto
+face.ascentOverride: normal
+face.descentOverride: normal
+face.lineGapOverride: normal
+face.family: Another font family
+face.style: italic
+face.weight: bold
+face.stretch: condensed
+face.family = 1: SyntaxError: FontFace.family setter: Invalid font descriptor
+face.style = 1: SyntaxError: FontFace.style setter: Invalid font descriptor
+face.weight = 500kg: SyntaxError: FontFace.weight setter: Invalid font descriptor
+face.stretch = super stretched: SyntaxError: FontFace.stretch setter: Invalid font descriptor
diff --git a/Tests/LibWeb/Text/input/css/FontFace.html b/Tests/LibWeb/Text/input/css/FontFace.html
new file mode 100644
index 00000000000..b0446f66f36
--- /dev/null
+++ b/Tests/LibWeb/Text/input/css/FontFace.html
@@ -0,0 +1,58 @@
+
+
+
diff --git a/Userland/Libraries/LibWeb/CSS/FontFace.cpp b/Userland/Libraries/LibWeb/CSS/FontFace.cpp
index 1315652a5dc..5a6b55ed8b9 100644
--- a/Userland/Libraries/LibWeb/CSS/FontFace.cpp
+++ b/Userland/Libraries/LibWeb/CSS/FontFace.cpp
@@ -9,20 +9,43 @@
#include
#include
#include
+#include
#include
namespace Web::CSS {
JS_DEFINE_ALLOCATOR(FontFace);
+template
+RefPtr parse_property_string(JS::Realm& realm, StringView value)
+{
+ auto maybe_parser = CSS::Parser::Parser::create(CSS::Parser::ParsingContext(realm), value);
+ if (maybe_parser.is_error())
+ return {};
+
+ return maybe_parser.release_value().parse_as_css_value(PropertyID);
+}
+
JS::NonnullGCPtr FontFace::construct_impl(JS::Realm& realm, String family, FontFaceSource source, FontFaceDescriptors const& descriptors)
{
return realm.heap().allocate(realm, realm, move(family), move(source), descriptors);
}
-FontFace::FontFace(JS::Realm& realm, String, FontFaceSource, FontFaceDescriptors const&)
+FontFace::FontFace(JS::Realm& realm, String font_family, FontFaceSource, FontFaceDescriptors const& descriptors)
: Bindings::PlatformObject(realm)
{
+ // FIXME: Validate these values the same way as the setters
+ m_family = move(font_family);
+ m_style = descriptors.style;
+ m_weight = descriptors.weight;
+ m_stretch = descriptors.stretch;
+ m_unicode_range = descriptors.unicode_range;
+ m_feature_settings = descriptors.feature_settings;
+ m_variation_settings = descriptors.variation_settings;
+ m_display = descriptors.display;
+ m_ascent_override = descriptors.ascent_override;
+ m_descent_override = descriptors.descent_override;
+ m_line_gap_override = descriptors.line_gap_override;
}
void FontFace::initialize(JS::Realm& realm)
@@ -32,6 +55,114 @@ void FontFace::initialize(JS::Realm& realm)
WEB_SET_PROTOTYPE_FOR_INTERFACE(FontFace);
}
+// https://drafts.csswg.org/css-font-loading/#dom-fontface-family
+WebIDL::ExceptionOr FontFace::set_family(String const& string)
+{
+ auto property = parse_property_string(realm(), string);
+ if (!property)
+ return WebIDL::SyntaxError::create(realm(), "FontFace.family setter: Invalid font descriptor"_fly_string);
+
+ if (m_is_css_connected) {
+ // FIXME: Propagate to the CSSFontFaceRule and update the font-family property
+ }
+
+ m_family = property->to_string();
+
+ return {};
+}
+
+// https://drafts.csswg.org/css-font-loading/#dom-fontface-style
+WebIDL::ExceptionOr FontFace::set_style(String const& string)
+{
+ auto property = parse_property_string(realm(), string);
+ if (!property)
+ return WebIDL::SyntaxError::create(realm(), "FontFace.style setter: Invalid font descriptor"_fly_string);
+
+ if (m_is_css_connected) {
+ // FIXME: Propagate to the CSSFontFaceRule and update the font-style property
+ }
+
+ m_style = property->to_string();
+
+ return {};
+}
+
+// https://drafts.csswg.org/css-font-loading/#dom-fontface-weight
+WebIDL::ExceptionOr FontFace::set_weight(String const& string)
+{
+ auto property = parse_property_string(realm(), string);
+ if (!property)
+ return WebIDL::SyntaxError::create(realm(), "FontFace.weight setter: Invalid font descriptor"_fly_string);
+
+ if (m_is_css_connected) {
+ // FIXME: Propagate to the CSSFontFaceRule and update the font-weight property
+ }
+
+ m_weight = property->to_string();
+
+ return {};
+}
+
+// https://drafts.csswg.org/css-font-loading/#dom-fontface-stretch
+WebIDL::ExceptionOr FontFace::set_stretch(String const& string)
+{
+ auto property = parse_property_string(realm(), string);
+ if (!property)
+ return WebIDL::SyntaxError::create(realm(), "FontFace.stretch setter: Invalid font descriptor"_fly_string);
+
+ if (m_is_css_connected) {
+ // FIXME: Propagate to the CSSFontFaceRule and update the font-stretch property
+ }
+
+ m_stretch = property->to_string();
+
+ return {};
+}
+
+// https://drafts.csswg.org/css-font-loading/#dom-fontface-unicoderange
+WebIDL::ExceptionOr FontFace::set_unicode_range(String const&)
+{
+ // FIXME: This *should* work, but the production is hard to parse
+ // from just a value string in our implementation
+ return WebIDL::NotSupportedError::create(realm(), "unicode range is not yet implemented"_fly_string);
+}
+
+// https://drafts.csswg.org/css-font-loading/#dom-fontface-featuresettings
+WebIDL::ExceptionOr FontFace::set_feature_settings(String const&)
+{
+ return WebIDL::NotSupportedError::create(realm(), "feature settings is not yet implemented"_fly_string);
+}
+
+// https://drafts.csswg.org/css-font-loading/#dom-fontface-variationsettings
+WebIDL::ExceptionOr FontFace::set_variation_settings(String const&)
+{
+ return WebIDL::NotSupportedError::create(realm(), "variation settings is not yet implemented"_fly_string);
+}
+
+// https://drafts.csswg.org/css-font-loading/#dom-fontface-display
+WebIDL::ExceptionOr FontFace::set_display(String const&)
+{
+ return WebIDL::NotSupportedError::create(realm(), "display is not yet implemented"_fly_string);
+}
+
+// https://drafts.csswg.org/css-font-loading/#dom-fontface-ascentoverride
+WebIDL::ExceptionOr FontFace::set_ascent_override(String const&)
+{
+ return WebIDL::NotSupportedError::create(realm(), "ascent override is not yet implemented"_fly_string);
+}
+
+// https://drafts.csswg.org/css-font-loading/#dom-fontface-descentoverride
+WebIDL::ExceptionOr FontFace::set_descent_override(String const&)
+{
+ return WebIDL::NotSupportedError::create(realm(), "descent override is not yet implemented"_fly_string);
+}
+
+// https://drafts.csswg.org/css-font-loading/#dom-fontface-linegapoverride
+WebIDL::ExceptionOr FontFace::set_line_gap_override(String const&)
+{
+ return WebIDL::NotSupportedError::create(realm(), "line gap override is not yet implemented"_fly_string);
+}
+
// https://drafts.csswg.org/css-font-loading/#dom-fontface-load
JS::ThrowCompletionOr> FontFace::load()
{
diff --git a/Userland/Libraries/LibWeb/CSS/FontFace.h b/Userland/Libraries/LibWeb/CSS/FontFace.h
index fff97d3c09c..2206224d45c 100644
--- a/Userland/Libraries/LibWeb/CSS/FontFace.h
+++ b/Userland/Libraries/LibWeb/CSS/FontFace.h
@@ -33,12 +33,61 @@ public:
[[nodiscard]] static JS::NonnullGCPtr construct_impl(JS::Realm&, String family, FontFaceSource source, FontFaceDescriptors const& descriptors);
virtual ~FontFace() override = default;
+ String family() const { return m_family; }
+ WebIDL::ExceptionOr set_family(String const&);
+
+ String style() const { return m_style; }
+ WebIDL::ExceptionOr set_style(String const&);
+
+ String weight() const { return m_weight; }
+ WebIDL::ExceptionOr set_weight(String const&);
+
+ String stretch() const { return m_stretch; }
+ WebIDL::ExceptionOr set_stretch(String const&);
+
+ String unicode_range() const { return m_unicode_range; }
+ WebIDL::ExceptionOr set_unicode_range(String const&);
+
+ String feature_settings() const { return m_feature_settings; }
+ WebIDL::ExceptionOr set_feature_settings(String const&);
+
+ String variation_settings() const { return m_variation_settings; }
+ WebIDL::ExceptionOr set_variation_settings(String const&);
+
+ String display() const { return m_display; }
+ WebIDL::ExceptionOr set_display(String const&);
+
+ String ascent_override() const { return m_ascent_override; }
+ WebIDL::ExceptionOr set_ascent_override(String const&);
+
+ String descent_override() const { return m_descent_override; }
+ WebIDL::ExceptionOr set_descent_override(String const&);
+
+ String line_gap_override() const { return m_line_gap_override; }
+ WebIDL::ExceptionOr set_line_gap_override(String const&);
+
JS::ThrowCompletionOr> load();
private:
FontFace(JS::Realm&, String family, FontFaceSource source, FontFaceDescriptors const& descriptors);
virtual void initialize(JS::Realm&) override;
+
+ // FIXME: Should we be storing StyleValues instead?
+ String m_family;
+ String m_style;
+ String m_weight;
+ String m_stretch;
+ String m_unicode_range;
+ String m_feature_settings;
+ String m_variation_settings;
+ String m_display;
+ String m_ascent_override;
+ String m_descent_override;
+ String m_line_gap_override;
+
+ // https://drafts.csswg.org/css-font-loading/#css-connected
+ bool m_is_css_connected { false };
};
}
diff --git a/Userland/Libraries/LibWeb/CSS/FontFace.idl b/Userland/Libraries/LibWeb/CSS/FontFace.idl
index f219c78c378..b73fc541f66 100644
--- a/Userland/Libraries/LibWeb/CSS/FontFace.idl
+++ b/Userland/Libraries/LibWeb/CSS/FontFace.idl
@@ -20,17 +20,17 @@ enum FontFaceLoadStatus { "unloaded", "loading", "loaded", "error" };
interface FontFace {
// FIXME: constructor(CSSOMString family, (CSSOMString or BinaryData) source, optional FontFaceDescriptors descriptors = {});
constructor(CSSOMString family, CSSOMString source, optional FontFaceDescriptors descriptors = {});
- // FIXME: attribute CSSOMString family;
- // FIXME: attribute CSSOMString style;
- // FIXME: attribute CSSOMString weight;
- // FIXME: attribute CSSOMString stretch;
- // FIXME: attribute CSSOMString unicodeRange;
- // FIXME: attribute CSSOMString featureSettings;
- // FIXME: attribute CSSOMString variationSettings;
- // FIXME: attribute CSSOMString display;
- // FIXME: attribute CSSOMString ascentOverride;
- // FIXME: attribute CSSOMString descentOverride;
- // FIXME: attribute CSSOMString lineGapOverride;
+ attribute CSSOMString family;
+ attribute CSSOMString style;
+ attribute CSSOMString weight;
+ attribute CSSOMString stretch;
+ attribute CSSOMString unicodeRange;
+ attribute CSSOMString featureSettings;
+ attribute CSSOMString variationSettings;
+ attribute CSSOMString display;
+ attribute CSSOMString ascentOverride;
+ attribute CSSOMString descentOverride;
+ attribute CSSOMString lineGapOverride;
// FIXME: readonly attribute FontFaceLoadStatus status;