mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 00:50:22 +00:00
LibGfx: Move FontDatabase internals to SystemFontProvider interface
Some checks are pending
CI / Lagom (false, FUZZ, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, macos-14, macOS, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (true, NO_FUZZ, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Push notes / build (push) Waiting to run
Some checks are pending
CI / Lagom (false, FUZZ, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, macos-14, macOS, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (true, NO_FUZZ, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Push notes / build (push) Waiting to run
This will be the first step is making better use of system libraries like fontconfig and CoreText to load system fonts for use by the UI process and the CSS style computer.
This commit is contained in:
parent
e8ff9b6eb4
commit
36a8ad9157
Notes:
github-actions[bot]
2024-10-15 21:10:07 +00:00
Author: https://github.com/ADKaster Commit: https://github.com/LadybirdBrowser/ladybird/commit/36a8ad91575 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1736
11 changed files with 174 additions and 89 deletions
|
@ -8,9 +8,11 @@
|
|||
#include "FontPlugin.h"
|
||||
#include <AK/ByteString.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/TypeCasts.h>
|
||||
#include <LibCore/Resource.h>
|
||||
#include <LibCore/StandardPaths.h>
|
||||
#include <LibGfx/Font/FontDatabase.h>
|
||||
#include <LibGfx/Font/PathFontProvider.h>
|
||||
|
||||
#ifdef USE_FONTCONFIG
|
||||
# include <fontconfig/fontconfig.h>
|
||||
|
@ -18,7 +20,7 @@
|
|||
|
||||
namespace Ladybird {
|
||||
|
||||
FontPlugin::FontPlugin(bool is_layout_test_mode)
|
||||
FontPlugin::FontPlugin(bool is_layout_test_mode, Gfx::SystemFontProvider* font_provider)
|
||||
: m_is_layout_test_mode(is_layout_test_mode)
|
||||
{
|
||||
#ifdef USE_FONTCONFIG
|
||||
|
@ -28,9 +30,14 @@ FontPlugin::FontPlugin(bool is_layout_test_mode)
|
|||
}
|
||||
#endif
|
||||
|
||||
// Load anything we can find in the system's font directories
|
||||
for (auto const& path : Core::StandardPaths::font_directories().release_value_but_fixme_should_propagate_errors())
|
||||
Gfx::FontDatabase::the().load_all_fonts_from_uri(MUST(String::formatted("file://{}", path)));
|
||||
if (!font_provider)
|
||||
font_provider = &static_cast<Gfx::PathFontProvider&>(Gfx::FontDatabase::the().install_system_font_provider(make<Gfx::PathFontProvider>()));
|
||||
if (is<Gfx::PathFontProvider>(*font_provider)) {
|
||||
auto& path_font_provider = static_cast<Gfx::PathFontProvider&>(*font_provider);
|
||||
// Load anything we can find in the system's font directories
|
||||
for (auto const& path : Core::StandardPaths::font_directories().release_value_but_fixme_should_propagate_errors())
|
||||
path_font_provider.load_all_fonts_from_uri(MUST(String::formatted("file://{}", path)));
|
||||
}
|
||||
|
||||
update_generic_fonts();
|
||||
|
||||
|
|
|
@ -8,13 +8,14 @@
|
|||
|
||||
#include <AK/RefPtr.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibGfx/Font/FontDatabase.h>
|
||||
#include <LibWeb/Platform/FontPlugin.h>
|
||||
|
||||
namespace Ladybird {
|
||||
|
||||
class FontPlugin final : public Web::Platform::FontPlugin {
|
||||
public:
|
||||
FontPlugin(bool is_layout_test_mode);
|
||||
FontPlugin(bool is_layout_test_mode, Gfx::SystemFontProvider* = nullptr);
|
||||
virtual ~FontPlugin();
|
||||
|
||||
virtual Gfx::Font& default_font() override;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <LibCore/Resource.h>
|
||||
#include <LibCore/SystemServerTakeover.h>
|
||||
#include <LibGfx/Font/FontDatabase.h>
|
||||
#include <LibGfx/Font/PathFontProvider.h>
|
||||
#include <LibIPC/ConnectionFromClient.h>
|
||||
#include <LibJS/Bytecode/Interpreter.h>
|
||||
#include <LibMain/Main.h>
|
||||
|
@ -128,11 +129,11 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
Core::Process::wait_for_debugger_and_break();
|
||||
}
|
||||
|
||||
auto& font_provider = static_cast<Gfx::PathFontProvider&>(Gfx::FontDatabase::the().install_system_font_provider(make<Gfx::PathFontProvider>()));
|
||||
if (force_fontconfig) {
|
||||
Gfx::FontDatabase::the().set_force_fontconfig(true);
|
||||
font_provider.set_name_but_fixme_should_create_custom_system_font_provider("FontConfig"_string);
|
||||
}
|
||||
|
||||
Gfx::FontDatabase::the().load_all_fonts_from_uri("resource://fonts"sv);
|
||||
font_provider.load_all_fonts_from_uri("resource://fonts"sv);
|
||||
|
||||
// Layout test mode implies internals object is exposed and the Skia CPU backend is used
|
||||
if (is_layout_test_mode) {
|
||||
|
@ -167,7 +168,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
|
||||
Web::HTML::Window::set_internals_object_exposed(expose_internals_object);
|
||||
|
||||
Web::Platform::FontPlugin::install(*new Ladybird::FontPlugin(is_layout_test_mode));
|
||||
Web::Platform::FontPlugin::install(*new Ladybird::FontPlugin(is_layout_test_mode, &font_provider));
|
||||
|
||||
TRY(Web::Bindings::initialize_main_thread_vm(Web::HTML::EventLoop::Type::Window));
|
||||
|
||||
|
|
|
@ -4,11 +4,22 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibGfx/Font/FontDatabase.h>
|
||||
#include <LibGfx/Font/PathFontProvider.h>
|
||||
#include <LibGfx/Font/WOFF2/Loader.h>
|
||||
#include <LibTest/TestCase.h>
|
||||
|
||||
#define TEST_INPUT(x) ("test-inputs/" x)
|
||||
|
||||
namespace {
|
||||
struct Global {
|
||||
Global()
|
||||
{
|
||||
Gfx::FontDatabase::the().install_system_font_provider(make<Gfx::PathFontProvider>());
|
||||
}
|
||||
} global;
|
||||
}
|
||||
|
||||
TEST_CASE(tolerate_incorrect_sfnt_size)
|
||||
{
|
||||
auto file = MUST(Core::MappedFile::map(TEST_INPUT("woff2/incorrect_sfnt_size.woff2"sv)));
|
||||
|
|
|
@ -15,6 +15,7 @@ set(SOURCES
|
|||
Font/Font.cpp
|
||||
Font/FontData.cpp
|
||||
Font/FontDatabase.cpp
|
||||
Font/PathFontProvider.cpp
|
||||
Font/ScaledFont.cpp
|
||||
Font/ScaledFontSkia.cpp
|
||||
Font/Typeface.cpp
|
||||
|
|
|
@ -4,100 +4,44 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/DeprecatedFlyString.h>
|
||||
#include <AK/FlyString.h>
|
||||
#include <AK/LexicalPath.h>
|
||||
#include <AK/Queue.h>
|
||||
#include <LibCore/Resource.h>
|
||||
#include <LibGfx/Font/Font.h>
|
||||
#include <LibGfx/Font/FontDatabase.h>
|
||||
#include <LibGfx/Font/ScaledFont.h>
|
||||
#include <LibGfx/Font/WOFF/Loader.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
// Key function for SystemFontProvider to emit the vtable here
|
||||
SystemFontProvider::~SystemFontProvider() = default;
|
||||
|
||||
FontDatabase& FontDatabase::the()
|
||||
{
|
||||
static FontDatabase s_the;
|
||||
return s_the;
|
||||
}
|
||||
|
||||
struct FontDatabase::Private {
|
||||
bool force_fontconfig { false };
|
||||
HashMap<FlyString, Vector<NonnullRefPtr<Typeface>>, AK::ASCIICaseInsensitiveFlyStringTraits> typeface_by_family;
|
||||
};
|
||||
|
||||
void FontDatabase::set_force_fontconfig(bool force_fontconfig)
|
||||
SystemFontProvider& FontDatabase::install_system_font_provider(NonnullOwnPtr<SystemFontProvider> provider)
|
||||
{
|
||||
m_private->force_fontconfig = force_fontconfig;
|
||||
VERIFY(!m_system_font_provider);
|
||||
m_system_font_provider = move(provider);
|
||||
return *m_system_font_provider;
|
||||
}
|
||||
|
||||
bool FontDatabase::should_force_fontconfig() const
|
||||
StringView FontDatabase::system_font_provider_name() const
|
||||
{
|
||||
return m_private->force_fontconfig;
|
||||
VERIFY(m_system_font_provider);
|
||||
return m_system_font_provider->name();
|
||||
}
|
||||
|
||||
void FontDatabase::load_all_fonts_from_uri(StringView uri)
|
||||
{
|
||||
auto root_or_error = Core::Resource::load_from_uri(uri);
|
||||
if (root_or_error.is_error()) {
|
||||
if (root_or_error.error().is_errno() && root_or_error.error().code() == ENOENT) {
|
||||
return;
|
||||
}
|
||||
dbgln("FontDatabase::load_all_fonts_from_uri('{}'): {}", uri, root_or_error.error());
|
||||
return;
|
||||
}
|
||||
auto root = root_or_error.release_value();
|
||||
|
||||
root->for_each_descendant_file([this](Core::Resource const& resource) -> IterationDecision {
|
||||
auto uri = resource.uri();
|
||||
auto path = LexicalPath(uri.bytes_as_string_view());
|
||||
if (path.has_extension(".ttf"sv) || path.has_extension(".ttc"sv)) {
|
||||
// FIXME: What about .otf
|
||||
if (auto font_or_error = Typeface::try_load_from_resource(resource); !font_or_error.is_error()) {
|
||||
auto font = font_or_error.release_value();
|
||||
auto& family = m_private->typeface_by_family.ensure(font->family(), [] {
|
||||
return Vector<NonnullRefPtr<Typeface>> {};
|
||||
});
|
||||
family.append(font);
|
||||
}
|
||||
} else if (path.has_extension(".woff"sv)) {
|
||||
if (auto font_or_error = WOFF::try_load_from_resource(resource); !font_or_error.is_error()) {
|
||||
auto font = font_or_error.release_value();
|
||||
auto& family = m_private->typeface_by_family.ensure(font->family(), [] {
|
||||
return Vector<NonnullRefPtr<Typeface>> {};
|
||||
});
|
||||
family.append(font);
|
||||
}
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
FontDatabase::FontDatabase()
|
||||
: m_private(make<Private>())
|
||||
{
|
||||
}
|
||||
FontDatabase::FontDatabase() = default;
|
||||
|
||||
RefPtr<Gfx::Font> FontDatabase::get(FlyString const& family, float point_size, unsigned weight, unsigned width, unsigned slope)
|
||||
{
|
||||
auto it = m_private->typeface_by_family.find(family);
|
||||
if (it == m_private->typeface_by_family.end())
|
||||
return nullptr;
|
||||
for (auto const& typeface : it->value) {
|
||||
if (typeface->weight() == weight && typeface->width() == width && typeface->slope() == slope)
|
||||
return typeface->scaled_font(point_size);
|
||||
}
|
||||
return nullptr;
|
||||
return m_system_font_provider->get_font(family, point_size, weight, width, slope);
|
||||
}
|
||||
|
||||
void FontDatabase::for_each_typeface_with_family_name(FlyString const& family_name, Function<void(Typeface const&)> callback)
|
||||
{
|
||||
auto it = m_private->typeface_by_family.find(family_name);
|
||||
if (it == m_private->typeface_by_family.end())
|
||||
return;
|
||||
for (auto const& typeface : it->value)
|
||||
callback(*typeface);
|
||||
m_system_font_provider->for_each_typeface_with_family_name(family_name, move(callback));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,36 +6,38 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/ByteString.h>
|
||||
#include <AK/FlyString.h>
|
||||
#include <AK/Function.h>
|
||||
#include <AK/HashMap.h>
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <LibGfx/Font/FontWeight.h>
|
||||
#include <LibGfx/Font/Typeface.h>
|
||||
#include <LibGfx/Forward.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
class SystemFontProvider {
|
||||
public:
|
||||
virtual ~SystemFontProvider();
|
||||
|
||||
virtual StringView name() const = 0;
|
||||
virtual RefPtr<Gfx::Font> get_font(FlyString const& family, float point_size, unsigned weight, unsigned width, unsigned slope) = 0;
|
||||
virtual void for_each_typeface_with_family_name(FlyString const& family_name, Function<void(Typeface const&)>) = 0;
|
||||
};
|
||||
|
||||
class FontDatabase {
|
||||
public:
|
||||
static FontDatabase& the();
|
||||
SystemFontProvider& install_system_font_provider(NonnullOwnPtr<SystemFontProvider>);
|
||||
|
||||
RefPtr<Gfx::Font> get(FlyString const& family, float point_size, unsigned weight, unsigned width, unsigned slope);
|
||||
|
||||
void for_each_typeface_with_family_name(FlyString const& family_name, Function<void(Typeface const&)>);
|
||||
|
||||
void load_all_fonts_from_uri(StringView);
|
||||
|
||||
void set_force_fontconfig(bool);
|
||||
[[nodiscard]] bool should_force_fontconfig() const;
|
||||
[[nodiscard]] StringView system_font_provider_name() const;
|
||||
|
||||
private:
|
||||
FontDatabase();
|
||||
~FontDatabase() = default;
|
||||
|
||||
struct Private;
|
||||
OwnPtr<Private> m_private;
|
||||
OwnPtr<SystemFontProvider> m_system_font_provider;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
78
Userland/Libraries/LibGfx/Font/PathFontProvider.cpp
Normal file
78
Userland/Libraries/LibGfx/Font/PathFontProvider.cpp
Normal file
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Format.h>
|
||||
#include <AK/LexicalPath.h>
|
||||
#include <LibCore/Resource.h>
|
||||
#include <LibGfx/Font/PathFontProvider.h>
|
||||
#include <LibGfx/Font/ScaledFont.h>
|
||||
#include <LibGfx/Font/WOFF/Loader.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
PathFontProvider::PathFontProvider() = default;
|
||||
PathFontProvider::~PathFontProvider() = default;
|
||||
|
||||
void PathFontProvider::load_all_fonts_from_uri(StringView uri)
|
||||
{
|
||||
auto root_or_error = Core::Resource::load_from_uri(uri);
|
||||
if (root_or_error.is_error()) {
|
||||
if (root_or_error.error().is_errno() && root_or_error.error().code() == ENOENT) {
|
||||
return;
|
||||
}
|
||||
dbgln("PathFontProvider::load_all_fonts_from_uri('{}'): {}", uri, root_or_error.error());
|
||||
return;
|
||||
}
|
||||
auto root = root_or_error.release_value();
|
||||
|
||||
root->for_each_descendant_file([this](Core::Resource const& resource) -> IterationDecision {
|
||||
auto uri = resource.uri();
|
||||
auto path = LexicalPath(uri.bytes_as_string_view());
|
||||
if (path.has_extension(".ttf"sv) || path.has_extension(".ttc"sv)) {
|
||||
// FIXME: What about .otf
|
||||
if (auto font_or_error = Typeface::try_load_from_resource(resource); !font_or_error.is_error()) {
|
||||
auto font = font_or_error.release_value();
|
||||
auto& family = m_typeface_by_family.ensure(font->family(), [] {
|
||||
return Vector<NonnullRefPtr<Typeface>> {};
|
||||
});
|
||||
family.append(font);
|
||||
}
|
||||
} else if (path.has_extension(".woff"sv)) {
|
||||
if (auto font_or_error = WOFF::try_load_from_resource(resource); !font_or_error.is_error()) {
|
||||
auto font = font_or_error.release_value();
|
||||
auto& family = m_typeface_by_family.ensure(font->family(), [] {
|
||||
return Vector<NonnullRefPtr<Typeface>> {};
|
||||
});
|
||||
family.append(font);
|
||||
}
|
||||
}
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
RefPtr<Gfx::Font> PathFontProvider::get_font(FlyString const& family, float point_size, unsigned weight, unsigned width, unsigned slope)
|
||||
{
|
||||
auto it = m_typeface_by_family.find(family);
|
||||
if (it == m_typeface_by_family.end())
|
||||
return nullptr;
|
||||
for (auto const& typeface : it->value) {
|
||||
if (typeface->weight() == weight && typeface->width() == width && typeface->slope() == slope)
|
||||
return typeface->scaled_font(point_size);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PathFontProvider::for_each_typeface_with_family_name(FlyString const& family_name, Function<void(Typeface const&)> callback)
|
||||
{
|
||||
auto it = m_typeface_by_family.find(family_name);
|
||||
if (it == m_typeface_by_family.end())
|
||||
return;
|
||||
for (auto const& typeface : it->value) {
|
||||
callback(*typeface);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
39
Userland/Libraries/LibGfx/Font/PathFontProvider.h
Normal file
39
Userland/Libraries/LibGfx/Font/PathFontProvider.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/FlyString.h>
|
||||
#include <AK/Function.h>
|
||||
#include <AK/HashMap.h>
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <LibGfx/Font/FontDatabase.h>
|
||||
#include <LibGfx/Font/Typeface.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
class PathFontProvider final : public SystemFontProvider {
|
||||
AK_MAKE_NONCOPYABLE(PathFontProvider);
|
||||
AK_MAKE_NONMOVABLE(PathFontProvider);
|
||||
|
||||
public:
|
||||
PathFontProvider();
|
||||
virtual ~PathFontProvider() override;
|
||||
|
||||
void set_name_but_fixme_should_create_custom_system_font_provider(String name) { m_name = move(name); }
|
||||
|
||||
void load_all_fonts_from_uri(StringView);
|
||||
|
||||
virtual RefPtr<Gfx::Font> get_font(FlyString const& family, float point_size, unsigned weight, unsigned width, unsigned slope) override;
|
||||
virtual void for_each_typeface_with_family_name(FlyString const& family_name, Function<void(Typeface const&)>) override;
|
||||
virtual StringView name() const override { return m_name.bytes_as_string_view(); }
|
||||
|
||||
private:
|
||||
HashMap<FlyString, Vector<NonnullRefPtr<Typeface>>, AK::ASCIICaseInsensitiveFlyStringTraits> m_typeface_by_family;
|
||||
String m_name { "Path"_string };
|
||||
};
|
||||
|
||||
}
|
|
@ -35,7 +35,7 @@ ErrorOr<NonnullRefPtr<TypefaceSkia>> TypefaceSkia::load_from_buffer(AK::Readonly
|
|||
{
|
||||
if (!s_font_manager) {
|
||||
#ifdef AK_OS_MACOS
|
||||
if (!Gfx::FontDatabase::the().should_force_fontconfig()) {
|
||||
if (Gfx::FontDatabase::the().system_font_provider_name() != "FontConfig"sv) {
|
||||
s_font_manager = SkFontMgr_New_CoreText(nullptr);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <LibGfx/Font/Font.h>
|
||||
#include <LibGfx/Font/FontDatabase.h>
|
||||
#include <LibGfx/Font/FontStyleMapping.h>
|
||||
#include <LibGfx/Font/FontWeight.h>
|
||||
#include <LibGfx/Font/ScaledFont.h>
|
||||
#include <LibGfx/Font/Typeface.h>
|
||||
#include <LibGfx/Font/WOFF/Loader.h>
|
||||
|
|
Loading…
Reference in a new issue