2020-01-18 09:38:21 +01:00
/*
* Copyright ( c ) 2018 - 2020 , Andreas Kling < kling @ serenityos . org >
*
2021-04-22 01:24:48 -07:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 09:38:21 +01:00
*/
2023-11-19 15:34:55 +04:00
# include <AK/GenericLexer.h>
2022-09-30 17:16:16 -06:00
# include <LibWeb/Bindings/Intrinsics.h>
2023-11-19 15:34:55 +04:00
# include <LibWeb/CSS/Parser/Parser.h>
# include <LibWeb/CSS/Parser/ParsingContext.h>
2020-03-07 10:32:51 +01:00
# include <LibWeb/CSS/StyleProperties.h>
2023-03-23 21:12:15 +00:00
# include <LibWeb/CSS/StyleValues/ColorStyleValue.h>
2020-07-26 15:08:16 +02:00
# include <LibWeb/HTML/HTMLFontElement.h>
2023-05-28 15:06:12 +12:00
# include <LibWeb/HTML/Parser/HTMLParser.h>
2023-11-19 15:34:55 +04:00
# include <LibWeb/Infra/CharacterTypes.h>
2019-10-04 21:14:59 +02:00
2020-07-28 18:20:36 +02:00
namespace Web : : HTML {
2020-03-07 10:27:02 +01:00
2023-11-19 19:47:52 +01:00
JS_DEFINE_ALLOCATOR ( HTMLFontElement ) ;
2023-11-19 15:34:55 +04:00
enum class Mode {
RelativePlus ,
RelativeMinus ,
Absolute ,
} ;
// https://html.spec.whatwg.org/multipage/rendering.html#rules-for-parsing-a-legacy-font-size
static Optional < CSS : : ValueID > parse_legacy_font_size ( StringView string )
{
// 1. Let input be the attribute's value.
// 2. Let position be a pointer into input, initially pointing at the start of the string.
GenericLexer lexer { string } ;
// 3. Skip ASCII whitespace within input given position.
lexer . ignore_while ( Web : : Infra : : is_ascii_whitespace ) ;
// 4. If position is past the end of input, there is no presentational hint. Return.
if ( lexer . is_eof ( ) )
return { } ;
// 5. If the character at position is a U+002B PLUS SIGN character (+), then let mode be relative-plus, and advance position to the next character. Otherwise, if the character at position is a U+002D HYPHEN-MINUS character (-), then let mode be relative-minus, and advance position to the next character. Otherwise, let mode be absolute.
Mode mode { Mode : : Absolute } ;
if ( lexer . peek ( ) = = ' + ' ) {
mode = Mode : : RelativePlus ;
lexer . consume ( ) ;
} else if ( lexer . peek ( ) = = ' - ' ) {
mode = Mode : : RelativeMinus ;
lexer . consume ( ) ;
}
// 6. Collect a sequence of code points that are ASCII digits from input given position, and let the resulting sequence be digits.
size_t start_index = lexer . tell ( ) ;
lexer . consume_while ( is_ascii_digit ) ;
size_t end_index = lexer . tell ( ) ;
auto digits = lexer . input ( ) . substring_view ( start_index , end_index - start_index ) ;
auto value_or_empty = AK : : StringUtils : : convert_to_int < i32 > ( digits ) ;
// 7. If digits is the empty string, there is no presentational hint. Return.
if ( ! value_or_empty . has_value ( ) )
return { } ;
// 8. Interpret digits as a base-ten integer. Let value be the resulting number.
auto value = value_or_empty . release_value ( ) ;
// 9. If mode is relative-plus, then increment value by 3. If mode is relative-minus, then let value be the result of subtracting value from 3.
if ( mode = = Mode : : RelativePlus )
value + = 3 ;
else if ( mode = = Mode : : RelativeMinus )
value = 3 - value ;
// 10. If value is greater than 7, let it be 7.
if ( value > 7 )
value = 7 ;
// 11. If value is less than 1, let it be 1.
if ( value < 1 )
value = 1 ;
// 12. Set 'font-size' to the keyword corresponding to the value of value according to the following table:
switch ( value ) {
case 1 :
return CSS : : ValueID : : XSmall ;
case 2 :
return CSS : : ValueID : : Small ;
case 3 :
return CSS : : ValueID : : Medium ;
case 4 :
return CSS : : ValueID : : Large ;
case 5 :
return CSS : : ValueID : : XLarge ;
case 6 :
return CSS : : ValueID : : XxLarge ;
case 7 :
return CSS : : ValueID : : XxxLarge ;
default :
VERIFY_NOT_REACHED ( ) ;
}
}
2022-02-18 21:00:52 +01:00
HTMLFontElement : : HTMLFontElement ( DOM : : Document & document , DOM : : QualifiedName qualified_name )
2021-02-07 11:20:15 +01:00
: HTMLElement ( document , move ( qualified_name ) )
2019-10-04 21:14:59 +02:00
{
}
2022-03-14 13:21:51 -06:00
HTMLFontElement : : ~ HTMLFontElement ( ) = default ;
2019-10-04 21:14:59 +02:00
2023-08-07 08:41:28 +02:00
void HTMLFontElement : : initialize ( JS : : Realm & realm )
2023-01-10 06:28:20 -05:00
{
2023-08-07 08:41:28 +02:00
Base : : initialize ( realm ) ;
2023-01-10 06:28:20 -05:00
set_prototype ( & Bindings : : ensure_web_prototype < Bindings : : HTMLFontElementPrototype > ( realm , " HTMLFontElement " ) ) ;
}
2020-07-26 20:01:35 +02:00
void HTMLFontElement : : apply_presentational_hints ( CSS : : StyleProperties & style ) const
2019-10-04 21:14:59 +02:00
{
for_each_attribute ( [ & ] ( auto & name , auto & value ) {
2023-03-10 08:48:54 +01:00
if ( name . equals_ignoring_ascii_case ( " color " sv ) ) {
2023-05-28 15:06:12 +12:00
// https://html.spec.whatwg.org/multipage/rendering.html#phrasing-content-3:rules-for-parsing-a-legacy-colour-value
auto color = parse_legacy_color_value ( value ) ;
2019-10-04 21:14:59 +02:00
if ( color . has_value ( ) )
2023-08-19 14:00:10 +01:00
style . set_property ( CSS : : PropertyID : : Color , CSS : : ColorStyleValue : : create ( color . value ( ) ) ) ;
2023-11-19 15:34:55 +04:00
} else if ( name . equals_ignoring_ascii_case ( " size " sv ) ) {
// When a font element has a size attribute, the user agent is expected to use the following steps, known as the rules for parsing a legacy font size, to treat the attribute as a presentational hint setting the element's 'font-size' property:
auto font_size_or_empty = parse_legacy_font_size ( value ) ;
if ( font_size_or_empty . has_value ( ) ) {
auto font_size = string_from_value_id ( font_size_or_empty . release_value ( ) ) ;
if ( auto parsed_value = parse_css_value ( CSS : : Parser : : ParsingContext { document ( ) } , font_size , CSS : : PropertyID : : FontSize ) )
style . set_property ( CSS : : PropertyID : : FontSize , parsed_value . release_nonnull ( ) ) ;
}
2019-10-04 21:14:59 +02:00
}
} ) ;
}
2020-03-07 10:27:02 +01:00
}