2022-09-08 10:44:17 +00:00
/*
2023-07-29 08:54:33 +00:00
* Copyright ( c ) 2022 - 2023 , Andreas Kling < kling @ serenityos . org >
2023-01-11 20:34:59 +00:00
* Copyright ( c ) 2023 , Linus Groh < linusg @ serenityos . org >
2022-09-08 10:44:17 +00:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
2023-08-02 18:01:17 +00:00
# include "FontPlugin.h"
2023-12-16 14:19:34 +00:00
# include <AK/ByteString.h>
2023-01-11 20:34:59 +00:00
# include <AK/String.h>
2024-03-19 17:54:38 +00:00
# include <LibCore/Resource.h>
2023-01-11 20:34:59 +00:00
# include <LibCore/StandardPaths.h>
2023-03-01 13:44:34 +00:00
# include <LibGfx/Font/Emoji.h>
2022-09-08 10:44:17 +00:00
# include <LibGfx/Font/FontDatabase.h>
namespace Ladybird {
2023-08-02 18:01:17 +00:00
FontPlugin : : FontPlugin ( bool is_layout_test_mode )
2023-05-06 10:46:14 +00:00
: m_is_layout_test_mode ( is_layout_test_mode )
2022-09-08 10:44:17 +00:00
{
2023-10-03 21:40:24 +00:00
// Load anything we can find in the system's font directories
2023-01-11 20:34:59 +00:00
for ( auto const & path : Core : : StandardPaths : : font_directories ( ) . release_value_but_fixme_should_propagate_errors ( ) )
2023-10-03 21:40:24 +00:00
Gfx : : FontDatabase : : the ( ) . load_all_fonts_from_uri ( MUST ( String : : formatted ( " file://{} " , path ) ) ) ;
2022-09-08 10:44:17 +00:00
Gfx : : FontDatabase : : set_default_font_query ( " Katica 10 400 0 " ) ;
Gfx : : FontDatabase : : set_fixed_width_font_query ( " Csilla 10 400 0 " ) ;
2024-03-19 17:54:38 +00:00
auto emoji_path = MUST ( Core : : Resource : : load_from_uri ( " resource://emoji " sv ) ) ;
VERIFY ( emoji_path - > is_directory ( ) ) ;
Gfx : : Emoji : : set_emoji_lookup_path ( emoji_path - > filesystem_path ( ) ) ;
2023-03-01 13:44:34 +00:00
2022-09-08 10:44:17 +00:00
update_generic_fonts ( ) ;
2022-09-17 19:25:15 +00:00
auto default_font_name = generic_font_name ( Web : : Platform : : GenericFont : : UiSansSerif ) ;
2023-09-06 05:45:47 +00:00
m_default_font = Gfx : : FontDatabase : : the ( ) . get ( default_font_name , 12.0 , 400 , Gfx : : FontWidth : : Normal , 0 ) ;
2022-09-17 19:25:15 +00:00
VERIFY ( m_default_font ) ;
2022-09-18 00:11:48 +00:00
auto default_fixed_width_font_name = generic_font_name ( Web : : Platform : : GenericFont : : UiMonospace ) ;
2023-09-06 05:45:47 +00:00
m_default_fixed_width_font = Gfx : : FontDatabase : : the ( ) . get ( default_fixed_width_font_name , 12.0 , 400 , Gfx : : FontWidth : : Normal , 0 ) ;
2022-09-18 00:11:48 +00:00
VERIFY ( m_default_fixed_width_font ) ;
2022-09-08 10:44:17 +00:00
}
2023-08-02 18:01:17 +00:00
FontPlugin : : ~ FontPlugin ( ) = default ;
2022-09-08 10:44:17 +00:00
2023-08-02 18:01:17 +00:00
Gfx : : Font & FontPlugin : : default_font ( )
2022-09-17 19:25:15 +00:00
{
return * m_default_font ;
}
2023-08-02 18:01:17 +00:00
Gfx : : Font & FontPlugin : : default_fixed_width_font ( )
2022-09-17 19:25:15 +00:00
{
return * m_default_fixed_width_font ;
}
2023-08-02 18:01:17 +00:00
void FontPlugin : : update_generic_fonts ( )
2022-09-08 10:44:17 +00:00
{
// How we choose which system font to use for each CSS font:
2023-07-29 08:54:33 +00:00
// 1. Try a list of known-suitable fonts with their names hard-coded below.
// 2. If that didn't work, fall back to Gfx::FontDatabase::default_font() (or default_fixed_width_font())
2022-09-08 10:44:17 +00:00
2023-07-29 08:54:33 +00:00
// This is rather weird, but it's how things work right now.
// We should eventually have a way to query the system for the default font.
// Furthermore, we should allow overriding via some kind of configuration mechanism.
2022-09-08 10:44:17 +00:00
m_generic_font_names . resize ( static_cast < size_t > ( Web : : Platform : : GenericFont : : __Count ) ) ;
2023-09-06 05:45:47 +00:00
auto update_mapping = [ & ] ( Web : : Platform : : GenericFont generic_font , ReadonlySpan < FlyString > fallbacks ) {
2023-05-06 10:46:14 +00:00
if ( m_is_layout_test_mode ) {
2023-09-06 05:45:47 +00:00
m_generic_font_names [ static_cast < size_t > ( generic_font ) ] = " SerenitySans " _fly_string ;
2023-05-06 10:46:14 +00:00
return ;
}
2023-07-29 08:54:33 +00:00
RefPtr < Gfx : : Font const > gfx_font ;
2023-04-26 12:17:40 +00:00
2023-07-29 08:54:33 +00:00
for ( auto & fallback : fallbacks ) {
2023-09-06 05:45:47 +00:00
gfx_font = Gfx : : FontDatabase : : the ( ) . get ( fallback , 16 , 400 , Gfx : : FontWidth : : Normal , 0 , Gfx : : Font : : AllowInexactSizeMatch : : Yes ) ;
2023-07-29 08:54:33 +00:00
if ( gfx_font )
break ;
2022-09-08 10:44:17 +00:00
}
if ( ! gfx_font ) {
if ( generic_font = = Web : : Platform : : GenericFont : : Monospace | | generic_font = = Web : : Platform : : GenericFont : : UiMonospace )
gfx_font = Gfx : : FontDatabase : : default_fixed_width_font ( ) ;
else
gfx_font = Gfx : : FontDatabase : : default_font ( ) ;
}
2023-09-06 05:45:47 +00:00
m_generic_font_names [ static_cast < size_t > ( generic_font ) ] = gfx_font - > family ( ) ;
2022-09-08 10:44:17 +00:00
} ;
2023-07-31 23:52:36 +00:00
// Fallback fonts to look for if Gfx::Font can't load expected font
2022-09-08 10:44:17 +00:00
// The lists are basically arbitrary, taken from https://www.w3.org/Style/Examples/007/fonts.en.html
2023-09-06 05:45:47 +00:00
Vector < FlyString > cursive_fallbacks { " Comic Sans MS " _fly_string , " Comic Sans " _fly_string , " Apple Chancery " _fly_string , " Bradley Hand " _fly_string , " Brush Script MT " _fly_string , " Snell Roundhand " _fly_string , " URW Chancery L " _fly_string } ;
Vector < FlyString > fantasy_fallbacks { " Impact " _fly_string , " Luminari " _fly_string , " Chalkduster " _fly_string , " Jazz LET " _fly_string , " Blippo " _fly_string , " Stencil Std " _fly_string , " Marker Felt " _fly_string , " Trattatello " _fly_string } ;
Vector < FlyString > monospace_fallbacks { " Andale Mono " _fly_string , " Courier New " _fly_string , " Courier " _fly_string , " FreeMono " _fly_string , " OCR A Std " _fly_string , " DejaVu Sans Mono " _fly_string , " Liberation Mono " _fly_string , " Csilla " _fly_string } ;
Vector < FlyString > sans_serif_fallbacks { " Arial " _fly_string , " Helvetica " _fly_string , " Verdana " _fly_string , " Trebuchet MS " _fly_string , " Gill Sans " _fly_string , " Noto Sans " _fly_string , " Avantgarde " _fly_string , " Optima " _fly_string , " Arial Narrow " _fly_string , " Liberation Sans " _fly_string , " Katica " _fly_string } ;
Vector < FlyString > serif_fallbacks { " Times " _fly_string , " Times New Roman " _fly_string , " Didot " _fly_string , " Georgia " _fly_string , " Palatino " _fly_string , " Bookman " _fly_string , " New Century Schoolbook " _fly_string , " American Typewriter " _fly_string , " Liberation Serif " _fly_string , " Roman " _fly_string } ;
2022-09-08 10:44:17 +00:00
2023-07-29 08:54:33 +00:00
update_mapping ( Web : : Platform : : GenericFont : : Cursive , cursive_fallbacks ) ;
update_mapping ( Web : : Platform : : GenericFont : : Fantasy , fantasy_fallbacks ) ;
update_mapping ( Web : : Platform : : GenericFont : : Monospace , monospace_fallbacks ) ;
update_mapping ( Web : : Platform : : GenericFont : : SansSerif , sans_serif_fallbacks ) ;
update_mapping ( Web : : Platform : : GenericFont : : Serif , serif_fallbacks ) ;
update_mapping ( Web : : Platform : : GenericFont : : UiMonospace , monospace_fallbacks ) ;
update_mapping ( Web : : Platform : : GenericFont : : UiRounded , sans_serif_fallbacks ) ;
update_mapping ( Web : : Platform : : GenericFont : : UiSansSerif , sans_serif_fallbacks ) ;
update_mapping ( Web : : Platform : : GenericFont : : UiSerif , serif_fallbacks ) ;
2022-09-08 10:44:17 +00:00
}
2023-09-06 05:45:47 +00:00
FlyString FontPlugin : : generic_font_name ( Web : : Platform : : GenericFont generic_font )
2022-09-08 10:44:17 +00:00
{
return m_generic_font_names [ static_cast < size_t > ( generic_font ) ] ;
}
}