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;