2022-03-28 20:30:26 +01:00
/*
2025-04-03 12:05:49 +01:00
* Copyright ( c ) 2022 - 2025 , Sam Atkins < sam @ ladybird . org >
2024-10-04 13:19:50 +02:00
* Copyright ( c ) 2022 - 2023 , Andreas Kling < andreas @ ladybird . org >
2022-03-28 20:30:26 +01:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2024-10-02 14:18:08 +01:00
# include <LibGfx/Font/Font.h>
2023-05-24 19:58:52 +02:00
# include <LibGfx/Font/FontStyleMapping.h>
2022-09-24 16:34:04 -06:00
# include <LibWeb/Bindings/CSSFontFaceRulePrototype.h>
# include <LibWeb/Bindings/Intrinsics.h>
2022-03-28 20:30:26 +01:00
# include <LibWeb/CSS/CSSFontFaceRule.h>
2022-09-11 12:20:16 -04:00
# include <LibWeb/CSS/Serialize.h>
2023-02-12 22:44:04 +01:00
# include <LibWeb/WebIDL/ExceptionOr.h>
2022-03-28 20:30:26 +01:00
namespace Web : : CSS {
2024-11-15 04:01:23 +13:00
GC_DEFINE_ALLOCATOR ( CSSFontFaceRule ) ;
2023-12-23 15:15:27 +01:00
2025-04-03 12:05:49 +01:00
GC : : Ref < CSSFontFaceRule > CSSFontFaceRule : : create ( JS : : Realm & realm , GC : : Ref < CSSFontFaceDescriptors > style )
2022-03-28 20:30:26 +01:00
{
2025-04-03 12:05:49 +01:00
return realm . create < CSSFontFaceRule > ( realm , style ) ;
2022-08-07 15:46:44 +02:00
}
2025-04-03 12:05:49 +01:00
CSSFontFaceRule : : CSSFontFaceRule ( JS : : Realm & realm , GC : : Ref < CSSFontFaceDescriptors > style )
2024-10-28 20:16:28 +01:00
: CSSRule ( realm , Type : : FontFace )
2025-04-03 12:05:49 +01:00
, m_style ( style )
2022-08-07 15:46:44 +02:00
{
2025-05-02 11:13:02 +01:00
m_style - > set_parent_rule ( * this ) ;
2023-01-10 06:28:20 -05:00
}
2023-08-07 08:41:28 +02:00
void CSSFontFaceRule : : initialize ( JS : : Realm & realm )
2023-01-10 06:28:20 -05:00
{
2024-03-16 13:13:08 +01:00
WEB_SET_PROTOTYPE_FOR_INTERFACE ( CSSFontFaceRule ) ;
2025-04-20 16:22:57 +02:00
Base : : initialize ( realm ) ;
2022-03-28 20:30:26 +01:00
}
2025-04-03 12:15:11 +01:00
bool CSSFontFaceRule : : is_valid ( ) const
{
// @font-face rules require a font-family and src descriptor; if either of these are missing, the @font-face rule
// must not be considered when performing the font matching algorithm.
// https://drafts.csswg.org/css-fonts-4/#font-face-rule
return ! m_style - > descriptor ( DescriptorID : : FontFamily ) . is_null ( )
& & ! m_style - > descriptor ( DescriptorID : : Src ) . is_null ( ) ;
}
2025-04-03 12:05:49 +01:00
ParsedFontFace CSSFontFaceRule : : font_face ( ) const
2022-03-28 20:30:26 +01:00
{
2025-04-03 12:05:49 +01:00
return ParsedFontFace : : from_descriptors ( m_style ) ;
2022-03-28 20:30:26 +01:00
}
// https://www.w3.org/TR/cssom/#ref-for-cssfontfacerule
2023-11-20 23:16:39 +13:00
String CSSFontFaceRule : : serialized ( ) const
2022-03-28 20:30:26 +01:00
{
2025-04-04 12:18:53 +01:00
auto & descriptors = * m_style ;
2022-09-11 12:20:16 -04:00
StringBuilder builder ;
// The result of concatenating the following:
// 1. The string "@font-face {", followed by a single SPACE (U+0020).
builder . append ( " @font-face { " sv ) ;
// 2. The string "font-family:", followed by a single SPACE (U+0020).
builder . append ( " font-family: " sv ) ;
// 3. The result of performing serialize a string on the rule’ s font family name.
2025-05-16 19:20:24 +01:00
builder . append ( descriptors . descriptor ( DescriptorID : : FontFamily ) - > to_string ( SerializationMode : : Normal ) ) ;
2022-09-11 12:20:16 -04:00
// 4. The string ";", i.e., SEMICOLON (U+003B).
builder . append ( ' ; ' ) ;
// 5. If the rule’ s associated source list is not empty, follow these substeps:
2025-04-04 12:18:53 +01:00
if ( auto sources = descriptors . descriptor ( DescriptorID : : Src ) ) {
2022-09-11 12:20:16 -04:00
// 1. A single SPACE (U+0020), followed by the string "src:", followed by a single SPACE (U+0020).
builder . append ( " src: " sv ) ;
// 2. The result of invoking serialize a comma-separated list on performing serialize a URL or serialize a LOCAL for each source on the source list.
2025-05-16 19:20:24 +01:00
builder . append ( sources - > to_string ( SerializationMode : : Normal ) ) ;
2022-09-11 12:20:16 -04:00
// 3. The string ";", i.e., SEMICOLON (U+003B).
builder . append ( ' ; ' ) ;
}
// 6. If rule’ s associated unicode-range descriptor is present, a single SPACE (U+0020), followed by the string "unicode-range:", followed by a single SPACE (U+0020), followed by the result of performing serialize a <'unicode-range'>, followed by the string ";", i.e., SEMICOLON (U+003B).
2025-04-04 12:18:53 +01:00
if ( auto unicode_range = descriptors . descriptor ( DescriptorID : : UnicodeRange ) ) {
builder . append ( " unicode-range: " sv ) ;
2025-05-16 19:20:24 +01:00
builder . append ( unicode_range - > to_string ( SerializationMode : : Normal ) ) ;
2025-04-04 12:18:53 +01:00
builder . append ( ' ; ' ) ;
}
2022-09-11 12:20:16 -04:00
// FIXME: 7. If rule’ s associated font-variant descriptor is present, a single SPACE (U+0020),
// followed by the string "font-variant:", followed by a single SPACE (U+0020),
// followed by the result of performing serialize a <'font-variant'>,
// followed by the string ";", i.e., SEMICOLON (U+003B).
2024-10-02 14:18:08 +01:00
// 8. If rule’ s associated font-feature-settings descriptor is present, a single SPACE (U+0020),
// followed by the string "font-feature-settings:", followed by a single SPACE (U+0020),
// followed by the result of performing serialize a <'font-feature-settings'>,
// followed by the string ";", i.e., SEMICOLON (U+003B).
2025-04-04 12:18:53 +01:00
if ( auto font_feature_settings = descriptors . descriptor ( DescriptorID : : FontFeatureSettings ) ) {
2024-10-02 14:18:08 +01:00
builder . append ( " font-feature-settings: " sv ) ;
2025-05-16 19:20:24 +01:00
builder . append ( font_feature_settings - > to_string ( SerializationMode : : Normal ) ) ;
2024-10-02 14:18:08 +01:00
builder . append ( " ; " sv ) ;
}
// 9. If rule’ s associated font-stretch descriptor is present, a single SPACE (U+0020),
// followed by the string "font-stretch:", followed by a single SPACE (U+0020),
// followed by the result of performing serialize a <'font-stretch'>,
// followed by the string ";", i.e., SEMICOLON (U+003B).
// NOTE: font-stretch is now an alias for font-width, so we use that instead.
2025-04-04 12:18:53 +01:00
if ( auto font_width = descriptors . descriptor ( DescriptorID : : FontWidth ) ) {
builder . append ( " font-stretch: " sv ) ;
2025-05-16 19:20:24 +01:00
builder . append ( font_width - > to_string ( SerializationMode : : Normal ) ) ;
2024-10-02 14:18:08 +01:00
builder . append ( " ; " sv ) ;
}
2022-09-11 12:20:16 -04:00
2023-05-24 19:58:52 +02:00
// 10. If rule’ s associated font-weight descriptor is present, a single SPACE (U+0020),
// followed by the string "font-weight:", followed by a single SPACE (U+0020),
// followed by the result of performing serialize a <'font-weight'>,
// followed by the string ";", i.e., SEMICOLON (U+003B).
2025-04-04 12:18:53 +01:00
if ( auto font_weight = descriptors . descriptor ( DescriptorID : : FontWeight ) ) {
2023-05-24 19:58:52 +02:00
builder . append ( " font-weight: " sv ) ;
2025-05-16 19:20:24 +01:00
builder . append ( font_weight - > to_string ( SerializationMode : : Normal ) ) ;
2023-05-24 19:58:52 +02:00
builder . append ( " ; " sv ) ;
}
2022-09-11 12:20:16 -04:00
2023-05-24 19:58:52 +02:00
// 11. If rule’ s associated font-style descriptor is present, a single SPACE (U+0020),
// followed by the string "font-style:", followed by a single SPACE (U+0020),
// followed by the result of performing serialize a <'font-style'>,
// followed by the string ";", i.e., SEMICOLON (U+003B).
2025-04-04 12:18:53 +01:00
if ( auto font_style = descriptors . descriptor ( DescriptorID : : FontStyle ) ) {
2023-05-24 19:58:52 +02:00
builder . append ( " font-style: " sv ) ;
2025-05-16 19:20:24 +01:00
builder . append ( font_style - > to_string ( SerializationMode : : Normal ) ) ;
2023-05-24 19:58:52 +02:00
builder . append ( " ; " sv ) ;
}
2022-09-11 12:20:16 -04:00
// 12. A single SPACE (U+0020), followed by the string "}", i.e., RIGHT CURLY BRACKET (U+007D).
builder . append ( " } " sv ) ;
2023-11-20 23:16:39 +13:00
return MUST ( builder . to_string ( ) ) ;
2022-03-28 20:30:26 +01:00
}
2025-04-03 12:05:49 +01:00
void CSSFontFaceRule : : visit_edges ( Visitor & visitor )
{
Base : : visit_edges ( visitor ) ;
visitor . visit ( m_style ) ;
}
2022-03-28 20:30:26 +01:00
}