2023-08-03 12:18:17 +02:00
/*
* Copyright ( c ) 2023 , Bastiaan van der Plaat < bastiaan . v . d . plaat @ gmail . com >
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# pragma once
2023-08-07 21:48:49 +02:00
# include <LibWeb/CSS/Parser/Parser.h>
# include <LibWeb/CSS/StyleComputer.h>
2023-09-19 16:39:50 +01:00
# include <LibWeb/CSS/StyleValues/ShorthandStyleValue.h>
2023-08-07 21:48:49 +02:00
# include <LibWeb/DOM/Document.h>
2023-08-03 12:18:17 +02:00
# include <LibWeb/HTML/Canvas/CanvasState.h>
2025-03-07 00:19:45 +01:00
# include <LibWeb/HTML/OffscreenCanvas.h>
# include <LibWeb/HTML/Window.h>
# include <LibWeb/HTML/WorkerGlobalScope.h>
2023-08-03 12:18:17 +02:00
namespace Web : : HTML {
// https://html.spec.whatwg.org/multipage/canvas.html#canvastextdrawingstyles
2025-03-07 00:19:45 +01:00
template < typename IncludingClass , typename CanvasType >
2023-08-03 12:18:17 +02:00
class CanvasTextDrawingStyles {
public :
~ CanvasTextDrawingStyles ( ) = default ;
2023-12-16 17:49:34 +03:30
ByteString font ( ) const
2023-08-07 21:48:49 +02:00
{
// When font style value is empty return default string
if ( ! my_drawing_state ( ) . font_style_value ) {
return " 10px sans-serif " ;
}
// On getting, the font attribute must return the serialized form of the current font of the context (with no 'line-height' component).
2023-09-19 16:39:50 +01:00
auto const & font_style_value = my_drawing_state ( ) . font_style_value - > as_shorthand ( ) ;
auto font_style = font_style_value . longhand ( CSS : : PropertyID : : FontStyle ) ;
auto font_weight = font_style_value . longhand ( CSS : : PropertyID : : FontWeight ) ;
auto font_size = font_style_value . longhand ( CSS : : PropertyID : : FontSize ) ;
auto font_family = font_style_value . longhand ( CSS : : PropertyID : : FontFamily ) ;
2024-12-07 00:59:49 +01:00
return ByteString : : formatted ( " {} {} {} {} " ,
2025-05-16 19:20:24 +01:00
font_style - > to_string ( CSS : : SerializationMode : : Normal ) ,
font_weight - > to_string ( CSS : : SerializationMode : : Normal ) ,
font_size - > to_string ( CSS : : SerializationMode : : Normal ) ,
font_family - > to_string ( CSS : : SerializationMode : : Normal ) ) ;
2023-08-07 21:48:49 +02:00
}
2025-03-07 00:19:45 +01:00
// https://html.spec.whatwg.org/multipage/canvas.html#font-style-source-object
Variant < DOM : : Document * , HTML : : WorkerGlobalScope * > get_font_source_for_font_style_source_object ( CanvasType & font_style_source_object )
{
// Font resolution for the font style source object requires a font source. This is determined for a given object implementing CanvasTextDrawingStyles by the following steps: [CSSFONTLOAD]
if constexpr ( SameAs < CanvasType , HTML : : HTMLCanvasElement > ) {
// 1. If object's font style source object is a canvas element, return the element's node document.
return & font_style_source_object . document ( ) ;
} else {
// 2. Otherwise, object's font style source object is an OffscreenCanvas object:
// 1. Let global be object's relevant global object.
auto & global_object = HTML : : relevant_global_object ( font_style_source_object ) ;
// 2. If global is a Window object, then return global's associated Document.
if ( is < HTML : : Window > ( global_object ) ) {
auto & window = as < HTML : : Window > ( global_object ) ;
return & ( window . associated_document ( ) ) ;
}
// 3. Assert: global implements WorkerGlobalScope.
VERIFY ( is < HTML : : WorkerGlobalScope > ( global_object ) ) ;
// 4. Return global.
return & ( as < HTML : : WorkerGlobalScope > ( global_object ) ) ;
} ;
}
2023-09-06 19:41:48 +12:00
void set_font ( StringView font )
2023-08-07 21:48:49 +02:00
{
// The font IDL attribute, on setting, must be parsed as a CSS <'font'> value (but without supporting property-independent style sheet syntax like 'inherit'),
// and the resulting font must be assigned to the context, with the 'line-height' component forced to 'normal', with the 'font-size' component converted to CSS pixels,
// and with system fonts being computed to explicit values.
2024-07-23 16:14:26 +01:00
// FIXME: with the 'line-height' component forced to 'normal'
// FIXME: with the 'font-size' component converted to CSS pixels
2025-02-05 12:08:27 +00:00
auto font_style_value_result = parse_css_value ( CSS : : Parser : : ParsingParams { } , font , CSS : : PropertyID : : Font ) ;
2023-08-07 21:48:49 +02:00
// If the new value is syntactically incorrect (including using property-independent style sheet syntax like 'inherit' or 'initial'), then it must be ignored, without assigning a new font value.
2024-07-23 16:14:26 +01:00
// NOTE: ShorthandStyleValue should be the only valid option here. We implicitly VERIFY this below.
if ( ! font_style_value_result | | ! font_style_value_result - > is_shorthand ( ) ) {
2023-08-07 21:48:49 +02:00
return ;
}
2023-08-19 15:01:21 +01:00
my_drawing_state ( ) . font_style_value = font_style_value_result . release_nonnull ( ) ;
2023-08-07 21:48:49 +02:00
// Load font with font style value properties
2023-09-19 16:39:50 +01:00
auto const & font_style_value = my_drawing_state ( ) . font_style_value - > as_shorthand ( ) ;
2023-08-07 21:48:49 +02:00
auto & canvas_element = reinterpret_cast < IncludingClass & > ( * this ) . canvas_element ( ) ;
2025-03-07 00:19:45 +01:00
2023-09-19 16:39:50 +01:00
auto & font_style = * font_style_value . longhand ( CSS : : PropertyID : : FontStyle ) ;
auto & font_weight = * font_style_value . longhand ( CSS : : PropertyID : : FontWeight ) ;
2024-09-27 14:04:59 +01:00
auto & font_width = * font_style_value . longhand ( CSS : : PropertyID : : FontWidth ) ;
2023-09-19 16:39:50 +01:00
auto & font_size = * font_style_value . longhand ( CSS : : PropertyID : : FontSize ) ;
auto & font_family = * font_style_value . longhand ( CSS : : PropertyID : : FontFamily ) ;
2025-03-07 00:19:45 +01:00
// https://drafts.csswg.org/css-font-loading/#font-source
auto font_source = get_font_source_for_font_style_source_object ( canvas_element ) ;
auto font_list = font_source . visit (
[ & ] ( DOM : : Document * document ) - > RefPtr < Gfx : : FontCascadeList const > {
if constexpr ( SameAs < CanvasType , HTML : : HTMLCanvasElement > ) {
return document - > style_computer ( ) . compute_font_for_style_values ( & canvas_element , { } , font_family , font_size , font_style , font_weight , font_width ) ;
} else {
return document - > style_computer ( ) . compute_font_for_style_values ( nullptr , { } , font_family , font_size , font_style , font_weight , font_width ) ;
}
} ,
[ ] ( HTML : : WorkerGlobalScope * ) - > RefPtr < Gfx : : FontCascadeList const > {
// FIXME: implement computing the font for HTML::WorkerGlobalScope
return { } ;
} ) ;
if ( ! font_list )
return ;
2025-06-18 00:57:33 +02:00
my_drawing_state ( ) . current_font_cascade_list = font_list ;
2023-08-07 21:48:49 +02:00
}
2023-08-03 12:18:17 +02:00
Bindings : : CanvasTextAlign text_align ( ) const { return my_drawing_state ( ) . text_align ; }
2023-08-07 21:48:49 +02:00
void set_text_align ( Bindings : : CanvasTextAlign text_align ) { my_drawing_state ( ) . text_align = text_align ; }
2023-08-03 12:18:17 +02:00
Bindings : : CanvasTextBaseline text_baseline ( ) const { return my_drawing_state ( ) . text_baseline ; }
2023-08-07 21:48:49 +02:00
void set_text_baseline ( Bindings : : CanvasTextBaseline text_baseline ) { my_drawing_state ( ) . text_baseline = text_baseline ; }
2023-08-03 12:18:17 +02:00
protected :
CanvasTextDrawingStyles ( ) = default ;
private :
CanvasState : : DrawingState & my_drawing_state ( ) { return reinterpret_cast < IncludingClass & > ( * this ) . drawing_state ( ) ; }
CanvasState : : DrawingState const & my_drawing_state ( ) const { return reinterpret_cast < IncludingClass const & > ( * this ) . drawing_state ( ) ; }
} ;
}