mirror of https://github.com/stenzek/duckstation
ImGuiManager: Load FreeType/plutosvg dynamically
parent
b42b6981e0
commit
f1f6b0ee79
@ -0,0 +1,47 @@
|
||||
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ft2build.h>
|
||||
|
||||
#include FT_FREETYPE_H // <freetype/freetype.h>
|
||||
#include FT_GLYPH_H // <freetype/ftglyph.h>
|
||||
#include FT_MULTIPLE_MASTERS_H // <freetype/ftmm.h>
|
||||
#include FT_MODULE_H // <freetype/ftmodapi.h>
|
||||
#include FT_SIZES_H // <freetype/ftsizes.h>
|
||||
#include FT_SYNTHESIS_H // <freetype/ftsynth.h>
|
||||
|
||||
class Error;
|
||||
|
||||
#define DYN_FREETYPE_FUNCTIONS(X) \
|
||||
X(FT_New_Memory_Face) \
|
||||
X(FT_Select_Charmap) \
|
||||
X(FT_Get_MM_Var) \
|
||||
X(FT_Done_MM_Var) \
|
||||
X(FT_Done_Face) \
|
||||
X(FT_Get_Char_Index) \
|
||||
X(FT_Load_Glyph) \
|
||||
X(FT_GlyphSlot_Embolden) \
|
||||
X(FT_GlyphSlot_Oblique) \
|
||||
X(FT_New_Library) \
|
||||
X(FT_Add_Default_Modules) \
|
||||
X(FT_Property_Set) \
|
||||
X(FT_Done_Library) \
|
||||
X(FT_New_Size) \
|
||||
X(FT_Activate_Size) \
|
||||
X(FT_Set_Var_Design_Coordinates) \
|
||||
X(FT_Request_Size) \
|
||||
X(FT_Done_Size) \
|
||||
X(FT_Render_Glyph)
|
||||
|
||||
struct DynFreeType
|
||||
{
|
||||
#define ADD_FUNC(F) decltype(&::F) F;
|
||||
DYN_FREETYPE_FUNCTIONS(ADD_FUNC)
|
||||
#undef ADD_FUNC
|
||||
|
||||
bool Open(Error* const error);
|
||||
};
|
||||
|
||||
extern DynFreeType g_dyn_freetype;
|
||||
@ -0,0 +1,32 @@
|
||||
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <plutosvg.h>
|
||||
|
||||
class Error;
|
||||
|
||||
#define DYN_PLUTOSVG_FUNCTIONS(X) \
|
||||
X(plutosvg_ft_svg_hooks) \
|
||||
X(plutosvg_document_load_from_data) \
|
||||
X(plutosvg_document_destroy) \
|
||||
X(plutosvg_document_get_width) \
|
||||
X(plutosvg_document_get_height) \
|
||||
X(plutosvg_document_render_to_surface) \
|
||||
X(plutovg_surface_destroy) \
|
||||
X(plutovg_surface_get_width) \
|
||||
X(plutovg_surface_get_height) \
|
||||
X(plutovg_surface_get_data) \
|
||||
X(plutovg_surface_get_stride)
|
||||
|
||||
struct DynPlutoSvg
|
||||
{
|
||||
#define ADD_FUNC(F) decltype(&::F) F;
|
||||
DYN_PLUTOSVG_FUNCTIONS(ADD_FUNC)
|
||||
#undef ADD_FUNC
|
||||
|
||||
bool Open(Error* const error = nullptr);
|
||||
};
|
||||
|
||||
extern DynPlutoSvg g_dyn_plutosvg;
|
||||
@ -0,0 +1,88 @@
|
||||
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <stenzek@gmail.com>
|
||||
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||
|
||||
#include "dyn_freetype.h"
|
||||
#include "dyn_plutosvg.h"
|
||||
|
||||
#include "common/dynamic_library.h"
|
||||
#include "common/error.h"
|
||||
#include "common/log.h"
|
||||
|
||||
LOG_CHANNEL(DynamicLibrary);
|
||||
|
||||
static_assert(std::is_trivially_copyable_v<DynFreeType> && std::is_standard_layout_v<DynFreeType>);
|
||||
static_assert(std::is_trivially_copyable_v<DynPlutoSvg> && std::is_standard_layout_v<DynPlutoSvg>);
|
||||
|
||||
// Because of course friggin linux is different...
|
||||
#ifdef _WIN32
|
||||
static constexpr int FREETYPE_MAJOR_VERSION = -1;
|
||||
static constexpr int PLUTOSVG_MAJOR_VERSION = -1;
|
||||
#else
|
||||
static constexpr int FREETYPE_MAJOR_VERSION = 6;
|
||||
static constexpr int PLUTOSVG_MAJOR_VERSION = 0;
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
struct Locals
|
||||
{
|
||||
// Dynamic libraries
|
||||
DynamicLibrary freetype_library;
|
||||
std::once_flag freetype_init_flag;
|
||||
DynamicLibrary plutosvg_library;
|
||||
std::once_flag plutosvg_init_flag;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
DynFreeType g_dyn_freetype;
|
||||
DynPlutoSvg g_dyn_plutosvg;
|
||||
static Locals s_locals;
|
||||
|
||||
static bool LoadDynLib(const char* libname, int major_version, DynamicLibrary& dynlib, std::once_flag& once_flag,
|
||||
std::span<const DynamicLibrary::SymbolTable> symbols, Error* const error)
|
||||
{
|
||||
std::call_once(once_flag, [&libname, &major_version, &dynlib, &symbols, error]() {
|
||||
Error lerror;
|
||||
DynamicLibrary lib;
|
||||
if (!lib.Open(DynamicLibrary::GetVersionedFilename(libname, major_version).c_str(), &lerror) ||
|
||||
!lib.ResolveSymbols(symbols.data(), symbols.size(), &lerror))
|
||||
{
|
||||
ERROR_LOG("Failed to load {}: {}", libname, lerror.GetDescription());
|
||||
Error::SetStringFmt(error, "Failed to load {}: {}", libname, lerror.GetDescription());
|
||||
return;
|
||||
}
|
||||
|
||||
dynlib = std::move(lib);
|
||||
});
|
||||
|
||||
return dynlib.IsOpen();
|
||||
}
|
||||
|
||||
static const DynamicLibrary::SymbolTable s_freetype_symbols[] = {
|
||||
#define RESOLVE_SYMBOL(F) {#F, (void**)&g_dyn_freetype.F},
|
||||
DYN_FREETYPE_FUNCTIONS(RESOLVE_SYMBOL)
|
||||
#undef RESOLVE_SYMBOL
|
||||
};
|
||||
|
||||
bool DynFreeType::Open(Error* const error)
|
||||
{
|
||||
if (s_locals.freetype_library.IsOpen()) [[likely]]
|
||||
return true;
|
||||
|
||||
return LoadDynLib("freetype", FREETYPE_MAJOR_VERSION, s_locals.freetype_library, s_locals.freetype_init_flag,
|
||||
s_freetype_symbols, error);
|
||||
}
|
||||
|
||||
static const DynamicLibrary::SymbolTable s_plutosvg_symbols[] = {
|
||||
#define RESOLVE_SYMBOL(F) {#F, (void**)&g_dyn_plutosvg.F},
|
||||
DYN_PLUTOSVG_FUNCTIONS(RESOLVE_SYMBOL)
|
||||
#undef RESOLVE_SYMBOL
|
||||
};
|
||||
|
||||
bool DynPlutoSvg::Open(Error* const error)
|
||||
{
|
||||
if (s_locals.plutosvg_library.IsOpen()) [[likely]]
|
||||
return true;
|
||||
|
||||
return LoadDynLib("plutosvg", PLUTOSVG_MAJOR_VERSION, s_locals.plutosvg_library, s_locals.plutosvg_init_flag,
|
||||
s_plutosvg_symbols, error);
|
||||
}
|
||||
Loading…
Reference in New Issue