mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-20 19:45:12 +00:00
LibGfx: Load with fontconfig the fonts we use
This commit is contained in:
parent
f070264800
commit
a15aae5fa5
17 changed files with 325 additions and 17 deletions
|
@ -78,6 +78,10 @@
|
|||
# cmakedefine01 FLAC_ENCODER_DEBUG
|
||||
#endif
|
||||
|
||||
#ifndef FONTCONFIG_DEBUG
|
||||
# cmakedefine01 FONTCONFIG_DEBUG
|
||||
#endif
|
||||
|
||||
#ifndef GENERATE_DEBUG
|
||||
# cmakedefine01 GENERATE_DEBUG
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
include(skia)
|
||||
include(vulkan)
|
||||
include(fontconfig)
|
||||
|
||||
set(SOURCES
|
||||
AffineTransform.cpp
|
||||
|
@ -125,6 +126,11 @@ else()
|
|||
target_link_libraries(LibGfx PRIVATE libjxl::libjxl hwy::hwy)
|
||||
endif()
|
||||
|
||||
if (HAS_FONTCONFIG)
|
||||
target_sources(LibGfx PRIVATE Font/FontconfigFontProvider.cpp)
|
||||
target_link_libraries(LibGfx PRIVATE Fontconfig::Fontconfig)
|
||||
endif()
|
||||
|
||||
if (ENABLE_SWIFT)
|
||||
generate_clang_module_map(LibGfx GENERATED_FILES ${generated_headers} EXCLUDE_FILES ${SWIFT_EXCLUDE_HEADERS})
|
||||
target_sources(LibGfx PRIVATE
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <AK/FlyString.h>
|
||||
#include <AK/RefCounted.h>
|
||||
#include <AK/RefPtr.h>
|
||||
#include <AK/String.h>
|
||||
|
@ -46,10 +47,27 @@ enum FontWidth {
|
|||
UltraExpanded = 9
|
||||
};
|
||||
|
||||
enum class FontSlant : u8 {
|
||||
Upright,
|
||||
Italic,
|
||||
Oblique
|
||||
};
|
||||
|
||||
constexpr float text_shaping_resolution = 64;
|
||||
|
||||
class Typeface;
|
||||
|
||||
struct FontDescription {
|
||||
FlyString family;
|
||||
|
||||
// These fields correspond to SkFontStyle
|
||||
u16 weight { 400 }; // Normal
|
||||
FontWidth width { Normal };
|
||||
FontSlant slant { FontSlant::Upright };
|
||||
|
||||
Function<RefPtr<Typeface>()> load_typeface;
|
||||
};
|
||||
|
||||
class Font : public RefCounted<Font> {
|
||||
public:
|
||||
virtual ~Font();
|
||||
|
|
|
@ -39,7 +39,7 @@ RefPtr<Gfx::Font> FontDatabase::get(FlyString const& family, float point_size, u
|
|||
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)
|
||||
void FontDatabase::for_each_typeface_with_family_name(FlyString const& family_name, Function<void(FontDescription)> callback)
|
||||
{
|
||||
m_system_font_provider->for_each_typeface_with_family_name(family_name, move(callback));
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
|
||||
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;
|
||||
virtual void for_each_typeface_with_family_name(FlyString const& family_name, Function<void(FontDescription)>) = 0;
|
||||
};
|
||||
|
||||
class FontDatabase {
|
||||
|
@ -29,7 +29,7 @@ public:
|
|||
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 for_each_typeface_with_family_name(FlyString const& family_name, Function<void(FontDescription)>);
|
||||
[[nodiscard]] StringView system_font_provider_name() const;
|
||||
|
||||
private:
|
||||
|
|
221
Libraries/LibGfx/Font/FontconfigFontProvider.cpp
Normal file
221
Libraries/LibGfx/Font/FontconfigFontProvider.cpp
Normal file
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Andrew Kaster <andrew@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#ifndef USE_FONTCONFIG
|
||||
# error "FontconfigFontProvider requires USE_FONTCONFIG to be enabled"
|
||||
#endif
|
||||
|
||||
#include <AK/RefPtr.h>
|
||||
#include <LibGfx/Font/Font.h>
|
||||
#include <LibGfx/Font/FontconfigFontProvider.h>
|
||||
#include <LibGfx/Font/ScaledFont.h>
|
||||
#include <LibGfx/Font/WOFF/Loader.h>
|
||||
|
||||
#include <fontconfig/fontconfig.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
FontconfigFontProvider::FontconfigFontProvider()
|
||||
{
|
||||
[[maybe_unused]] auto fontconfig_initialized = FcInit();
|
||||
VERIFY(fontconfig_initialized);
|
||||
}
|
||||
|
||||
FontconfigFontProvider::~FontconfigFontProvider() = default;
|
||||
|
||||
void FontconfigFontProvider::add_uri_to_config(StringView uri)
|
||||
{
|
||||
auto* config = FcConfigGetCurrent();
|
||||
VERIFY(config);
|
||||
|
||||
auto path = MUST(Core::Resource::load_from_uri(uri));
|
||||
VERIFY(path->is_directory());
|
||||
ByteString const fs_path = path->filesystem_path().to_byte_string();
|
||||
|
||||
bool const success = FcConfigAppFontAddDir(config, reinterpret_cast<FcChar8 const*>(fs_path.characters()));
|
||||
VERIFY(success);
|
||||
}
|
||||
|
||||
RefPtr<Typeface> FontconfigFontProvider::load_typeface_from_path(ByteString const& path, int index)
|
||||
{
|
||||
dbgln_if(FONTCONFIG_DEBUG, "FontconfigFontProvider: Loading font {} from {}", index, path);
|
||||
|
||||
auto resource = Core::Resource::load_from_filesystem(path);
|
||||
if (resource.is_error())
|
||||
return nullptr;
|
||||
auto typeface_or_error = Typeface::try_load_from_resource(resource.release_value(), index);
|
||||
if (typeface_or_error.is_error()) {
|
||||
typeface_or_error = WOFF::try_load_from_resource(resource.release_value(), index);
|
||||
if (typeface_or_error.is_error())
|
||||
return nullptr;
|
||||
}
|
||||
auto typeface = typeface_or_error.release_value();
|
||||
|
||||
auto& family_list = m_typeface_by_family.ensure(typeface->family(), [] {
|
||||
return Vector<NonnullRefPtr<Typeface>> {};
|
||||
});
|
||||
family_list.append(typeface);
|
||||
return typeface;
|
||||
}
|
||||
|
||||
RefPtr<Gfx::Font> FontconfigFontProvider::get_font(FlyString const& family, float point_size, unsigned int weight, unsigned int width, unsigned int slope)
|
||||
{
|
||||
if (auto typefaces = m_typeface_by_family.get(family); typefaces.has_value()) {
|
||||
for (auto& typeface : *typefaces) {
|
||||
if (typeface->weight() == weight && typeface->width() == width && typeface->slope() == slope)
|
||||
return typeface->scaled_font(point_size);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: We should be able to avoid this allocation with a null-terminated flystring
|
||||
ByteString const nullterm_family = family.bytes_as_string_view();
|
||||
|
||||
auto* config = FcConfigGetCurrent();
|
||||
VERIFY(config);
|
||||
|
||||
auto* pattern = FcPatternBuild(nullptr, FC_FAMILY, FcTypeString, reinterpret_cast<FcChar8 const*>(nullterm_family.characters()), nullptr);
|
||||
VERIFY(pattern);
|
||||
ScopeGuard const pattern_guard { [pattern] { FcPatternDestroy(pattern); } };
|
||||
|
||||
auto success = FcConfigSubstitute(config, pattern, FcMatchPattern);
|
||||
VERIFY(success);
|
||||
|
||||
FcDefaultSubstitute(pattern);
|
||||
|
||||
FcResult result {};
|
||||
auto* matched_pattern = FcFontMatch(config, pattern, &result);
|
||||
if (result != FcResultMatch || !matched_pattern)
|
||||
return nullptr;
|
||||
ScopeGuard const matched_pattern_guard { [matched_pattern] { FcPatternDestroy(matched_pattern); } };
|
||||
|
||||
FcChar8* file = nullptr;
|
||||
if (FcPatternGetString(matched_pattern, FC_FILE, 0, &file) != FcResultMatch)
|
||||
return nullptr;
|
||||
auto filename = ByteString { reinterpret_cast<char const*>(file) };
|
||||
|
||||
int index = 0;
|
||||
if (FcPatternGetInteger(matched_pattern, FC_INDEX, 0, &index) != FcResultMatch)
|
||||
return nullptr;
|
||||
|
||||
auto typeface = load_typeface_from_path(filename, index);
|
||||
return typeface ? typeface->scaled_font(point_size) : nullptr;
|
||||
}
|
||||
|
||||
Optional<FontDescription> FontconfigFontProvider::description_for_fontconfig_parameters(FlyString const& family, ByteString const& path, int index, int weight, int width, int slant)
|
||||
{
|
||||
// FIXME: Do better validation and normalization of fontconfig parameters
|
||||
if (weight < 0 || weight > 1000) {
|
||||
dbgln_if(FONTCONFIG_DEBUG, "FontconfigFontProvider: Invalid weight {} for font {} in {}@{}", weight, family, path, index);
|
||||
return {};
|
||||
}
|
||||
if (width < 0 || width > 9) {
|
||||
dbgln_if(FONTCONFIG_DEBUG, "FontconfigFontProvider: Invalid width {} for font {} in {}@{}", width, family, path, index);
|
||||
return {};
|
||||
}
|
||||
FontSlant normalized_slant = FontSlant::Upright;
|
||||
if (slant == FC_SLANT_ITALIC)
|
||||
normalized_slant = FontSlant::Italic;
|
||||
else if (slant == FC_SLANT_OBLIQUE)
|
||||
normalized_slant = FontSlant::Oblique;
|
||||
else if (slant != FC_SLANT_ROMAN) {
|
||||
dbgln_if(FONTCONFIG_DEBUG, "FontconfigFontProvider: Invalid slant {} for font {} in {}@{}", slant, family, path, index);
|
||||
return {};
|
||||
}
|
||||
|
||||
return FontDescription {
|
||||
.family = family,
|
||||
.weight = static_cast<u16>(weight),
|
||||
.width = static_cast<FontWidth>(width),
|
||||
.slant = normalized_slant,
|
||||
.load_typeface = [this, family, path, index, weight, width, slant]() -> RefPtr<Typeface> {
|
||||
// FIXME: Use more normalized values here to check cache
|
||||
if (auto typefaces = m_typeface_by_family.get(family); typefaces.has_value()) {
|
||||
for (auto& typeface : *typefaces) {
|
||||
if (typeface->weight() == weight && typeface->width() == width && typeface->slope() == slant)
|
||||
return typeface;
|
||||
}
|
||||
}
|
||||
return load_typeface_from_path(path, index);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
void FontconfigFontProvider::for_each_typeface_with_family_name(FlyString const& family_name, Function<void(FontDescription)> callback)
|
||||
{
|
||||
auto* config = FcConfigGetCurrent();
|
||||
VERIFY(config);
|
||||
|
||||
auto* set = FcConfigGetFonts(config, FcSetSystem);
|
||||
VERIFY(set);
|
||||
|
||||
// FIXME: We should be able to avoid this allocation with a null-terminated flystring
|
||||
ByteString const nullterm_family = family_name.bytes_as_string_view();
|
||||
|
||||
auto* pattern = FcPatternBuild(nullptr, FC_FAMILY, FcTypeString, reinterpret_cast<FcChar8 const*>(nullterm_family.characters()), nullptr);
|
||||
VERIFY(pattern);
|
||||
auto pattern_guard = ScopeGuard { [pattern] { FcPatternDestroy(pattern); } };
|
||||
|
||||
auto* object_set = FcObjectSetBuild(FC_FAMILY, FC_WEIGHT, FC_WIDTH, FC_SLANT, FC_FILE, FC_INDEX, nullptr);
|
||||
VERIFY(object_set);
|
||||
auto object_set_guard = ScopeGuard { [object_set] { FcObjectSetDestroy(object_set); } };
|
||||
|
||||
auto* matches = FcFontSetList(config, &set, 1, pattern, object_set);
|
||||
if (!matches)
|
||||
return;
|
||||
ScopeGuard const matches_guard { [matches] { FcFontSetDestroy(matches); } };
|
||||
|
||||
FcResult result {};
|
||||
for (auto idx = 0; idx < matches->nfont; ++idx) {
|
||||
auto* current_pattern = matches->fonts[idx];
|
||||
|
||||
FcChar8* path = nullptr;
|
||||
result = FcPatternGetString(current_pattern, FC_FILE, 0, &path);
|
||||
VERIFY(result == FcResultMatch);
|
||||
auto pattern_path = ByteString { reinterpret_cast<char const*>(path) };
|
||||
|
||||
int pattern_index = 0;
|
||||
result = FcPatternGetInteger(current_pattern, FC_INDEX, 0, &pattern_index);
|
||||
VERIFY(result == FcResultMatch);
|
||||
|
||||
FcChar8* family = nullptr;
|
||||
result = FcPatternGetString(current_pattern, FC_FAMILY, 0, &family);
|
||||
VERIFY(result == FcResultMatch);
|
||||
StringView const family_view = StringView { reinterpret_cast<char const*>(family), strlen(reinterpret_cast<char const*>(family)) };
|
||||
auto pattern_family_or_error = FlyString::from_utf8(family_view);
|
||||
if (pattern_family_or_error.is_error()) {
|
||||
dbgln("FontconfigFontProvider: Failed to read UTF-8 family name for font {} in {}", pattern_index, pattern_path);
|
||||
continue;
|
||||
}
|
||||
auto pattern_family = pattern_family_or_error.release_value();
|
||||
|
||||
int weight = 0;
|
||||
result = FcPatternGetInteger(current_pattern, FC_WEIGHT, 0, &weight);
|
||||
if (result != FcResultMatch) {
|
||||
dbgln_if(FONTCONFIG_DEBUG, "FontconfigFontProvider: Failed to read weight for font {} in {}@{}", pattern_family, pattern_path, pattern_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
int width = 0;
|
||||
result = FcPatternGetInteger(current_pattern, FC_WIDTH, 0, &width);
|
||||
if (result != FcResultMatch) {
|
||||
dbgln_if(FONTCONFIG_DEBUG, "FontconfigFontProvider: Failed to read width for font {} in {}@{}", pattern_family, pattern_path, pattern_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
int slant = 0;
|
||||
result = FcPatternGetInteger(current_pattern, FC_SLANT, 0, &slant);
|
||||
if (result != FcResultMatch) {
|
||||
dbgln_if(FONTCONFIG_DEBUG, "FontconfigFontProvider: Failed to read slant for font {} in {}@{}", pattern_family, pattern_path, pattern_index);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto descriptor = description_for_fontconfig_parameters(pattern_family, pattern_path, pattern_index, weight, width, slant); descriptor.has_value()) {
|
||||
callback(descriptor.release_value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
34
Libraries/LibGfx/Font/FontconfigFontProvider.h
Normal file
34
Libraries/LibGfx/Font/FontconfigFontProvider.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2025, Andrew Kaster <andrew@ladybird.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <LibGfx/Font/FontDatabase.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
class FontconfigFontProvider final : public SystemFontProvider {
|
||||
AK_MAKE_NONCOPYABLE(FontconfigFontProvider);
|
||||
AK_MAKE_NONMOVABLE(FontconfigFontProvider);
|
||||
|
||||
public:
|
||||
FontconfigFontProvider();
|
||||
virtual ~FontconfigFontProvider() override;
|
||||
|
||||
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(FontDescription)>) override;
|
||||
virtual StringView name() const override { return "FontConfig"sv; }
|
||||
|
||||
void add_uri_to_config(StringView);
|
||||
|
||||
private:
|
||||
Optional<FontDescription> description_for_fontconfig_parameters(FlyString const& family, ByteString const& path, int index, int weight, int width, int slant);
|
||||
RefPtr<Typeface> load_typeface_from_path(ByteString const& path, int index);
|
||||
|
||||
HashMap<FlyString, Vector<NonnullRefPtr<Typeface>>, AK::ASCIICaseInsensitiveFlyStringTraits> m_typeface_by_family;
|
||||
};
|
||||
|
||||
}
|
|
@ -65,13 +65,21 @@ RefPtr<Gfx::Font> PathFontProvider::get_font(FlyString const& family, float poin
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void PathFontProvider::for_each_typeface_with_family_name(FlyString const& family_name, Function<void(Typeface const&)> callback)
|
||||
void PathFontProvider::for_each_typeface_with_family_name(FlyString const& family_name, Function<void(FontDescription)> 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);
|
||||
callback(FontDescription {
|
||||
.family = typeface->family(),
|
||||
.weight = typeface->weight(),
|
||||
.width = static_cast<FontWidth>(typeface->width()),
|
||||
.slant = static_cast<FontSlant>(typeface->slope()),
|
||||
.load_typeface = [typeface] {
|
||||
return typeface;
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ public:
|
|||
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 void for_each_typeface_with_family_name(FlyString const& family_name, Function<void(FontDescription)>) override;
|
||||
virtual StringView name() const override { return m_name.bytes_as_string_view(); }
|
||||
|
||||
private:
|
||||
|
|
|
@ -56,6 +56,8 @@ ErrorOr<NonnullRefPtr<TypefaceSkia>> TypefaceSkia::load_from_buffer(AK::Readonly
|
|||
return adopt_ref(*new TypefaceSkia { make<TypefaceSkia::Impl>(skia_typeface), buffer, ttc_index });
|
||||
}
|
||||
|
||||
TypefaceSkia::~TypefaceSkia() = default;
|
||||
|
||||
SkTypeface const* TypefaceSkia::sk_typeface() const
|
||||
{
|
||||
return impl().skia_typeface.get();
|
||||
|
|
|
@ -15,6 +15,7 @@ class TypefaceSkia : public Gfx::Typeface {
|
|||
|
||||
public:
|
||||
static ErrorOr<NonnullRefPtr<TypefaceSkia>> load_from_buffer(ReadonlyBytes, int index = 0);
|
||||
~TypefaceSkia() override;
|
||||
|
||||
virtual u32 glyph_count() const override;
|
||||
virtual u16 units_per_em() const override;
|
||||
|
|
|
@ -15,6 +15,7 @@ class Color;
|
|||
|
||||
class Emoji;
|
||||
class Font;
|
||||
struct FontDescription;
|
||||
class ImageDecoder;
|
||||
struct FontPixelMetrics;
|
||||
class ScaledFont;
|
||||
|
|
|
@ -291,12 +291,12 @@ ErrorOr<NonnullRefPtr<Gfx::Typeface>> FontLoader::try_load_font()
|
|||
|
||||
struct StyleComputer::MatchingFontCandidate {
|
||||
FontFaceKey key;
|
||||
Variant<FontLoaderList*, Gfx::Typeface const*> loader_or_typeface;
|
||||
Variant<FontLoaderList*, Gfx::FontDescription> loader_or_description;
|
||||
|
||||
[[nodiscard]] RefPtr<Gfx::FontCascadeList const> font_with_point_size(float point_size) const
|
||||
{
|
||||
RefPtr<Gfx::FontCascadeList> font_list = Gfx::FontCascadeList::create();
|
||||
if (auto* loader_list = loader_or_typeface.get_pointer<FontLoaderList*>(); loader_list) {
|
||||
if (auto const* loader_list = loader_or_description.get_pointer<FontLoaderList*>(); loader_list) {
|
||||
for (auto const& loader : **loader_list) {
|
||||
if (auto font = loader->font_with_point_size(point_size); font)
|
||||
font_list->add(*font, loader->unicode_ranges());
|
||||
|
@ -304,7 +304,8 @@ struct StyleComputer::MatchingFontCandidate {
|
|||
return font_list;
|
||||
}
|
||||
|
||||
font_list->add(loader_or_typeface.get<Gfx::Typeface const*>()->scaled_font(point_size));
|
||||
if (auto typeface = loader_or_description.get<Gfx::FontDescription>().load_typeface(); typeface)
|
||||
font_list->add(typeface->scaled_font(point_size));
|
||||
return font_list;
|
||||
}
|
||||
};
|
||||
|
@ -1790,14 +1791,14 @@ RefPtr<Gfx::FontCascadeList const> StyleComputer::font_matching_algorithm(FlyStr
|
|||
if (font_key_and_loader.key.family_name.equals_ignoring_ascii_case(family_name))
|
||||
matching_family_fonts.empend(font_key_and_loader.key, const_cast<FontLoaderList*>(&font_key_and_loader.value));
|
||||
}
|
||||
Gfx::FontDatabase::the().for_each_typeface_with_family_name(family_name, [&](Gfx::Typeface const& typeface) {
|
||||
Gfx::FontDatabase::the().for_each_typeface_with_family_name(family_name, [&](Gfx::FontDescription description) {
|
||||
matching_family_fonts.empend(
|
||||
FontFaceKey {
|
||||
.family_name = typeface.family(),
|
||||
.weight = static_cast<int>(typeface.weight()),
|
||||
.slope = typeface.slope(),
|
||||
.family_name = description.family,
|
||||
.weight = description.weight,
|
||||
.slope = static_cast<int>(description.slant),
|
||||
},
|
||||
&typeface);
|
||||
move(description));
|
||||
});
|
||||
quick_sort(matching_family_fonts, [](auto const& a, auto const& b) {
|
||||
return a.key.weight < b.key.weight;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <LibWebView/Plugins/FontPlugin.h>
|
||||
|
||||
#ifdef USE_FONTCONFIG
|
||||
# include <LibGfx/Font/FontconfigFontProvider.h>
|
||||
# include <fontconfig/fontconfig.h>
|
||||
#endif
|
||||
|
||||
|
@ -26,13 +27,13 @@ FontPlugin::FontPlugin(bool is_layout_test_mode, Gfx::SystemFontProvider* font_p
|
|||
{
|
||||
#ifdef USE_FONTCONFIG
|
||||
{
|
||||
auto fontconfig_initialized = FcInit();
|
||||
VERIFY(fontconfig_initialized);
|
||||
if (!font_provider)
|
||||
font_provider = &Gfx::FontDatabase::the().install_system_font_provider(make<Gfx::FontconfigFontProvider>());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!font_provider)
|
||||
font_provider = &static_cast<Gfx::PathFontProvider&>(Gfx::FontDatabase::the().install_system_font_provider(make<Gfx::PathFontProvider>()));
|
||||
font_provider = &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
|
||||
|
|
|
@ -15,6 +15,7 @@ set(EDITOR_DEBUG ON)
|
|||
set(EMOJI_DEBUG ON)
|
||||
set(FILE_WATCHER_DEBUG ON)
|
||||
set(FLAC_ENCODER_DEBUG ON)
|
||||
set(FONTCONFIG_DEBUG ON)
|
||||
set(GENERATE_DEBUG ON)
|
||||
set(GHASH_PROCESS_DEBUG ON)
|
||||
set(GIF_DEBUG ON)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
include(audio)
|
||||
include(fontconfig)
|
||||
|
||||
set(SOURCES
|
||||
BackingStoreManager.cpp
|
||||
|
|
|
@ -48,6 +48,10 @@
|
|||
# include <LibCore/Platform/ProcessStatisticsMach.h>
|
||||
#endif
|
||||
|
||||
#if USE_FONTCONFIG
|
||||
# include <LibGfx/Font/FontconfigFontProvider.h>
|
||||
#endif
|
||||
|
||||
static ErrorOr<void> load_content_filters(StringView config_path);
|
||||
static ErrorOr<void> initialize_resource_loader(GC::Heap&, int request_server_socket);
|
||||
static ErrorOr<void> initialize_image_decoder(int image_decoder_socket);
|
||||
|
@ -137,11 +141,16 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
Core::Process::wait_for_debugger_and_break();
|
||||
}
|
||||
|
||||
#if USE_FONTCONFIG
|
||||
auto& font_provider = static_cast<Gfx::FontconfigFontProvider&>(Gfx::FontDatabase::the().install_system_font_provider(make<Gfx::FontconfigFontProvider>()));
|
||||
font_provider.add_uri_to_config("resource://fonts"sv);
|
||||
#else
|
||||
auto& font_provider = static_cast<Gfx::PathFontProvider&>(Gfx::FontDatabase::the().install_system_font_provider(make<Gfx::PathFontProvider>()));
|
||||
if (force_fontconfig) {
|
||||
font_provider.set_name_but_fixme_should_create_custom_system_font_provider("FontConfig"_string);
|
||||
}
|
||||
font_provider.load_all_fonts_from_uri("resource://fonts"sv);
|
||||
#endif
|
||||
|
||||
// Layout test mode implies internals object is exposed and the Skia CPU backend is used
|
||||
if (is_layout_test_mode) {
|
||||
|
|
Loading…
Add table
Reference in a new issue