Skip to content

Commit 2bc51f0

Browse files
ADKasterAtkinsSJ
authored andcommitted
LibWeb: Implement or stub FontFace interface's attribute getters/setters
We only support parsing half of these, so the ones we don't recognize get a friendly exception thrown.
1 parent de98c12 commit 2bc51f0

File tree

5 files changed

+269
-12
lines changed

5 files changed

+269
-12
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
face.family: Some font family
2+
face.style: normal
3+
face.weight: normal
4+
face.stretch: normal
5+
face.unicodeRange: U+0-10FFFF
6+
face.featureSettings: normal
7+
face.variationSettings: normal
8+
face.display: auto
9+
face.ascentOverride: normal
10+
face.descentOverride: normal
11+
face.lineGapOverride: normal
12+
face.family: Another font family
13+
face.style: italic
14+
face.weight: bold
15+
face.stretch: condensed
16+
face.family = 1: SyntaxError: FontFace.family setter: Invalid font descriptor
17+
face.style = 1: SyntaxError: FontFace.style setter: Invalid font descriptor
18+
face.weight = 500kg: SyntaxError: FontFace.weight setter: Invalid font descriptor
19+
face.stretch = super stretched: SyntaxError: FontFace.stretch setter: Invalid font descriptor
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<!DOCTYPE html>
2+
<script src="../include.js"></script>
3+
<script>
4+
test(() => {
5+
let face = new FontFace("Some font family", "url(some_font_family.ttf)");
6+
7+
println(`face.family: ${face.family}`);
8+
println(`face.style: ${face.style}`);
9+
println(`face.weight: ${face.weight}`);
10+
println(`face.stretch: ${face.stretch}`);
11+
12+
// FIXME: Implement setters for the following props:
13+
println(`face.unicodeRange: ${face.unicodeRange}`);
14+
println(`face.featureSettings: ${face.featureSettings}`);
15+
println(`face.variationSettings: ${face.variationSettings}`);
16+
println(`face.display: ${face.display}`);
17+
println(`face.ascentOverride: ${face.ascentOverride}`);
18+
println(`face.descentOverride: ${face.descentOverride}`);
19+
println(`face.lineGapOverride: ${face.lineGapOverride}`);
20+
21+
// Set valid values
22+
face.family = "Another font family";
23+
face.style = "italic";
24+
face.weight = "bold";
25+
face.stretch = "condensed";
26+
27+
println(`face.family: ${face.family}`);
28+
println(`face.style: ${face.style}`);
29+
println(`face.weight: ${face.weight}`);
30+
println(`face.stretch: ${face.stretch}`);
31+
32+
// Set invalid values and expect exception
33+
try {
34+
face.family = 1;
35+
} catch (e) {
36+
println(`face.family = 1: ${e}`);
37+
}
38+
39+
try {
40+
face.style = 1;
41+
} catch (e) {
42+
println(`face.style = 1: ${e}`);
43+
}
44+
45+
try {
46+
face.weight = "500kg";
47+
} catch (e) {
48+
println(`face.weight = 500kg: ${e}`);
49+
}
50+
51+
try {
52+
face.stretch = "super stretched";
53+
} catch (e) {
54+
println(`face.stretch = super stretched: ${e}`);
55+
}
56+
57+
});
58+
</script>

Userland/Libraries/LibWeb/CSS/FontFace.cpp

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,43 @@
99
#include <LibWeb/Bindings/FontFacePrototype.h>
1010
#include <LibWeb/Bindings/Intrinsics.h>
1111
#include <LibWeb/CSS/FontFace.h>
12+
#include <LibWeb/CSS/Parser/Parser.h>
1213
#include <LibWeb/WebIDL/Promise.h>
1314

1415
namespace Web::CSS {
1516

1617
JS_DEFINE_ALLOCATOR(FontFace);
1718

19+
template<CSS::PropertyID PropertyID>
20+
RefPtr<CSS::StyleValue const> parse_property_string(JS::Realm& realm, StringView value)
21+
{
22+
auto maybe_parser = CSS::Parser::Parser::create(CSS::Parser::ParsingContext(realm), value);
23+
if (maybe_parser.is_error())
24+
return {};
25+
26+
return maybe_parser.release_value().parse_as_css_value(PropertyID);
27+
}
28+
1829
JS::NonnullGCPtr<FontFace> FontFace::construct_impl(JS::Realm& realm, String family, FontFaceSource source, FontFaceDescriptors const& descriptors)
1930
{
2031
return realm.heap().allocate<FontFace>(realm, realm, move(family), move(source), descriptors);
2132
}
2233

23-
FontFace::FontFace(JS::Realm& realm, String, FontFaceSource, FontFaceDescriptors const&)
34+
FontFace::FontFace(JS::Realm& realm, String font_family, FontFaceSource, FontFaceDescriptors const& descriptors)
2435
: Bindings::PlatformObject(realm)
2536
{
37+
// FIXME: Validate these values the same way as the setters
38+
m_family = move(font_family);
39+
m_style = descriptors.style;
40+
m_weight = descriptors.weight;
41+
m_stretch = descriptors.stretch;
42+
m_unicode_range = descriptors.unicode_range;
43+
m_feature_settings = descriptors.feature_settings;
44+
m_variation_settings = descriptors.variation_settings;
45+
m_display = descriptors.display;
46+
m_ascent_override = descriptors.ascent_override;
47+
m_descent_override = descriptors.descent_override;
48+
m_line_gap_override = descriptors.line_gap_override;
2649
}
2750

2851
void FontFace::initialize(JS::Realm& realm)
@@ -32,6 +55,114 @@ void FontFace::initialize(JS::Realm& realm)
3255
WEB_SET_PROTOTYPE_FOR_INTERFACE(FontFace);
3356
}
3457

58+
// https://drafts.csswg.org/css-font-loading/#dom-fontface-family
59+
WebIDL::ExceptionOr<void> FontFace::set_family(String const& string)
60+
{
61+
auto property = parse_property_string<CSS::PropertyID::FontFamily>(realm(), string);
62+
if (!property)
63+
return WebIDL::SyntaxError::create(realm(), "FontFace.family setter: Invalid font descriptor"_fly_string);
64+
65+
if (m_is_css_connected) {
66+
// FIXME: Propagate to the CSSFontFaceRule and update the font-family property
67+
}
68+
69+
m_family = property->to_string();
70+
71+
return {};
72+
}
73+
74+
// https://drafts.csswg.org/css-font-loading/#dom-fontface-style
75+
WebIDL::ExceptionOr<void> FontFace::set_style(String const& string)
76+
{
77+
auto property = parse_property_string<CSS::PropertyID::FontStyle>(realm(), string);
78+
if (!property)
79+
return WebIDL::SyntaxError::create(realm(), "FontFace.style setter: Invalid font descriptor"_fly_string);
80+
81+
if (m_is_css_connected) {
82+
// FIXME: Propagate to the CSSFontFaceRule and update the font-style property
83+
}
84+
85+
m_style = property->to_string();
86+
87+
return {};
88+
}
89+
90+
// https://drafts.csswg.org/css-font-loading/#dom-fontface-weight
91+
WebIDL::ExceptionOr<void> FontFace::set_weight(String const& string)
92+
{
93+
auto property = parse_property_string<CSS::PropertyID::FontWeight>(realm(), string);
94+
if (!property)
95+
return WebIDL::SyntaxError::create(realm(), "FontFace.weight setter: Invalid font descriptor"_fly_string);
96+
97+
if (m_is_css_connected) {
98+
// FIXME: Propagate to the CSSFontFaceRule and update the font-weight property
99+
}
100+
101+
m_weight = property->to_string();
102+
103+
return {};
104+
}
105+
106+
// https://drafts.csswg.org/css-font-loading/#dom-fontface-stretch
107+
WebIDL::ExceptionOr<void> FontFace::set_stretch(String const& string)
108+
{
109+
auto property = parse_property_string<CSS::PropertyID::FontStretch>(realm(), string);
110+
if (!property)
111+
return WebIDL::SyntaxError::create(realm(), "FontFace.stretch setter: Invalid font descriptor"_fly_string);
112+
113+
if (m_is_css_connected) {
114+
// FIXME: Propagate to the CSSFontFaceRule and update the font-stretch property
115+
}
116+
117+
m_stretch = property->to_string();
118+
119+
return {};
120+
}
121+
122+
// https://drafts.csswg.org/css-font-loading/#dom-fontface-unicoderange
123+
WebIDL::ExceptionOr<void> FontFace::set_unicode_range(String const&)
124+
{
125+
// FIXME: This *should* work, but the <urange> production is hard to parse
126+
// from just a value string in our implementation
127+
return WebIDL::NotSupportedError::create(realm(), "unicode range is not yet implemented"_fly_string);
128+
}
129+
130+
// https://drafts.csswg.org/css-font-loading/#dom-fontface-featuresettings
131+
WebIDL::ExceptionOr<void> FontFace::set_feature_settings(String const&)
132+
{
133+
return WebIDL::NotSupportedError::create(realm(), "feature settings is not yet implemented"_fly_string);
134+
}
135+
136+
// https://drafts.csswg.org/css-font-loading/#dom-fontface-variationsettings
137+
WebIDL::ExceptionOr<void> FontFace::set_variation_settings(String const&)
138+
{
139+
return WebIDL::NotSupportedError::create(realm(), "variation settings is not yet implemented"_fly_string);
140+
}
141+
142+
// https://drafts.csswg.org/css-font-loading/#dom-fontface-display
143+
WebIDL::ExceptionOr<void> FontFace::set_display(String const&)
144+
{
145+
return WebIDL::NotSupportedError::create(realm(), "display is not yet implemented"_fly_string);
146+
}
147+
148+
// https://drafts.csswg.org/css-font-loading/#dom-fontface-ascentoverride
149+
WebIDL::ExceptionOr<void> FontFace::set_ascent_override(String const&)
150+
{
151+
return WebIDL::NotSupportedError::create(realm(), "ascent override is not yet implemented"_fly_string);
152+
}
153+
154+
// https://drafts.csswg.org/css-font-loading/#dom-fontface-descentoverride
155+
WebIDL::ExceptionOr<void> FontFace::set_descent_override(String const&)
156+
{
157+
return WebIDL::NotSupportedError::create(realm(), "descent override is not yet implemented"_fly_string);
158+
}
159+
160+
// https://drafts.csswg.org/css-font-loading/#dom-fontface-linegapoverride
161+
WebIDL::ExceptionOr<void> FontFace::set_line_gap_override(String const&)
162+
{
163+
return WebIDL::NotSupportedError::create(realm(), "line gap override is not yet implemented"_fly_string);
164+
}
165+
35166
// https://drafts.csswg.org/css-font-loading/#dom-fontface-load
36167
JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Promise>> FontFace::load()
37168
{

Userland/Libraries/LibWeb/CSS/FontFace.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,61 @@ class FontFace final : public Bindings::PlatformObject {
3333
[[nodiscard]] static JS::NonnullGCPtr<FontFace> construct_impl(JS::Realm&, String family, FontFaceSource source, FontFaceDescriptors const& descriptors);
3434
virtual ~FontFace() override = default;
3535

36+
String family() const { return m_family; }
37+
WebIDL::ExceptionOr<void> set_family(String const&);
38+
39+
String style() const { return m_style; }
40+
WebIDL::ExceptionOr<void> set_style(String const&);
41+
42+
String weight() const { return m_weight; }
43+
WebIDL::ExceptionOr<void> set_weight(String const&);
44+
45+
String stretch() const { return m_stretch; }
46+
WebIDL::ExceptionOr<void> set_stretch(String const&);
47+
48+
String unicode_range() const { return m_unicode_range; }
49+
WebIDL::ExceptionOr<void> set_unicode_range(String const&);
50+
51+
String feature_settings() const { return m_feature_settings; }
52+
WebIDL::ExceptionOr<void> set_feature_settings(String const&);
53+
54+
String variation_settings() const { return m_variation_settings; }
55+
WebIDL::ExceptionOr<void> set_variation_settings(String const&);
56+
57+
String display() const { return m_display; }
58+
WebIDL::ExceptionOr<void> set_display(String const&);
59+
60+
String ascent_override() const { return m_ascent_override; }
61+
WebIDL::ExceptionOr<void> set_ascent_override(String const&);
62+
63+
String descent_override() const { return m_descent_override; }
64+
WebIDL::ExceptionOr<void> set_descent_override(String const&);
65+
66+
String line_gap_override() const { return m_line_gap_override; }
67+
WebIDL::ExceptionOr<void> set_line_gap_override(String const&);
68+
3669
JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Promise>> load();
3770

3871
private:
3972
FontFace(JS::Realm&, String family, FontFaceSource source, FontFaceDescriptors const& descriptors);
4073

4174
virtual void initialize(JS::Realm&) override;
75+
76+
// FIXME: Should we be storing StyleValues instead?
77+
String m_family;
78+
String m_style;
79+
String m_weight;
80+
String m_stretch;
81+
String m_unicode_range;
82+
String m_feature_settings;
83+
String m_variation_settings;
84+
String m_display;
85+
String m_ascent_override;
86+
String m_descent_override;
87+
String m_line_gap_override;
88+
89+
// https://drafts.csswg.org/css-font-loading/#css-connected
90+
bool m_is_css_connected { false };
4291
};
4392

4493
}

Userland/Libraries/LibWeb/CSS/FontFace.idl

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@ enum FontFaceLoadStatus { "unloaded", "loading", "loaded", "error" };
2020
interface FontFace {
2121
// FIXME: constructor(CSSOMString family, (CSSOMString or BinaryData) source, optional FontFaceDescriptors descriptors = {});
2222
constructor(CSSOMString family, CSSOMString source, optional FontFaceDescriptors descriptors = {});
23-
// FIXME: attribute CSSOMString family;
24-
// FIXME: attribute CSSOMString style;
25-
// FIXME: attribute CSSOMString weight;
26-
// FIXME: attribute CSSOMString stretch;
27-
// FIXME: attribute CSSOMString unicodeRange;
28-
// FIXME: attribute CSSOMString featureSettings;
29-
// FIXME: attribute CSSOMString variationSettings;
30-
// FIXME: attribute CSSOMString display;
31-
// FIXME: attribute CSSOMString ascentOverride;
32-
// FIXME: attribute CSSOMString descentOverride;
33-
// FIXME: attribute CSSOMString lineGapOverride;
23+
attribute CSSOMString family;
24+
attribute CSSOMString style;
25+
attribute CSSOMString weight;
26+
attribute CSSOMString stretch;
27+
attribute CSSOMString unicodeRange;
28+
attribute CSSOMString featureSettings;
29+
attribute CSSOMString variationSettings;
30+
attribute CSSOMString display;
31+
attribute CSSOMString ascentOverride;
32+
attribute CSSOMString descentOverride;
33+
attribute CSSOMString lineGapOverride;
3434

3535
// FIXME: readonly attribute FontFaceLoadStatus status;
3636

0 commit comments

Comments
 (0)