Added more options to font loading.
This commit is contained in:
parent
830fdd434b
commit
1d75400a2d
2
SModule
2
SModule
@ -4,7 +4,7 @@ Import('env')
|
|||||||
public_dir = env.Dir('public')
|
public_dir = env.Dir('public')
|
||||||
env.Append(CPPPATH = [public_dir])
|
env.Append(CPPPATH = [public_dir])
|
||||||
if env['BUILD_TYPE'] == 'release':
|
if env['BUILD_TYPE'] == 'release':
|
||||||
cppdefines += ['RAID_RELEASE=1']
|
env.Append(CPPDEFINES = ['RAID_RELEASE'])
|
||||||
env = env.Module('private/raid/SModule')
|
env = env.Module('private/raid/SModule')
|
||||||
|
|
||||||
LIB_CONFIG = {
|
LIB_CONFIG = {
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
#include <mijin/debug/assert.hpp>
|
#include <mijin/debug/assert.hpp>
|
||||||
#include <mijin/platform/folders.hpp>
|
#include <mijin/platform/folders.hpp>
|
||||||
|
#include <mijin/util/iterators.hpp>
|
||||||
#include <mijin/util/scope_guard.hpp>
|
#include <mijin/util/scope_guard.hpp>
|
||||||
#include <mijin/virtual_filesystem/mapping.hpp>
|
#include <mijin/virtual_filesystem/mapping.hpp>
|
||||||
#include <mijin/virtual_filesystem/relative.hpp>
|
#include <mijin/virtual_filesystem/relative.hpp>
|
||||||
@ -125,29 +126,55 @@ int Application::run(int argc, char** argv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Application::loadFont(const fs::path& path)
|
|
||||||
|
bool Application::loadFonts(std::span<const FontConfig> fonts)
|
||||||
{
|
{
|
||||||
ImGuiIO& imguiIO = ImGui::GetIO();
|
ImGuiIO& imguiIO = ImGui::GetIO();
|
||||||
|
|
||||||
|
std::vector<mijin::TypelessBuffer> buffers;
|
||||||
|
buffers.reserve(fonts.size());
|
||||||
|
|
||||||
|
for (const FontConfig& font : fonts)
|
||||||
|
{
|
||||||
std::unique_ptr<mijin::Stream> fontFile;
|
std::unique_ptr<mijin::Stream> fontFile;
|
||||||
if (const mijin::StreamError error = mFS.open(path, mijin::FileOpenMode::READ, fontFile);
|
if (const mijin::StreamError error = mFS.open(font.path, mijin::FileOpenMode::READ, fontFile);
|
||||||
error != mijin::StreamError::SUCCESS)
|
error != mijin::StreamError::SUCCESS)
|
||||||
{
|
{
|
||||||
msgError("Error opening font file {}: {}.", path.generic_string(), mijin::errorName(error));
|
msgError("Error opening font file {}: {}.", font.path.generic_string(), mijin::errorName(error));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mijin::TypelessBuffer data;
|
mijin::TypelessBuffer& data = buffers.emplace_back();
|
||||||
if (const mijin::StreamError readError = fontFile->readRest(data); readError != mijin::StreamError::SUCCESS)
|
if (const mijin::StreamError readError = fontFile->readRest(data); readError != mijin::StreamError::SUCCESS)
|
||||||
{
|
{
|
||||||
msgError("Error reading font data from {}: {}.", path.generic_string(), mijin::errorName(readError));
|
msgError("Error reading font data from {}: {}.", font.path.generic_string(), mijin::errorName(readError));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// by default ImGui takes ownership of the data, that's now what we want
|
// by default ImGui takes ownership of the data, that's now what we want
|
||||||
ImFontConfig config;
|
ImFontConfig config;
|
||||||
config.FontDataOwnedByAtlas = false;
|
config.FontDataOwnedByAtlas = false;
|
||||||
imguiIO.Fonts->AddFontFromMemoryTTF(data.data(), static_cast<int>(data.byteSize()), 20, &config);
|
std::vector<ImWchar> glyphRangesConverted;
|
||||||
|
for (const auto& [font, data] : mijin::zip(fonts, buffers))
|
||||||
|
{
|
||||||
|
ImWchar* glyphRanges = nullptr;
|
||||||
|
if (!font.glyphRanges.empty())
|
||||||
|
{
|
||||||
|
glyphRangesConverted.reserve(2 * font.glyphRanges.size() + 1);
|
||||||
|
glyphRangesConverted.clear();
|
||||||
|
for (const std::pair<ImWchar, ImWchar>& range : font.glyphRanges)
|
||||||
|
{
|
||||||
|
glyphRangesConverted.push_back(range.first);
|
||||||
|
glyphRangesConverted.push_back(range.second);
|
||||||
|
}
|
||||||
|
glyphRangesConverted.push_back(0);
|
||||||
|
glyphRanges = glyphRangesConverted.data();
|
||||||
|
}
|
||||||
|
config.PixelSnapH = font.flags.pixelSnapH;
|
||||||
|
imguiIO.Fonts->AddFontFromMemoryTTF(data.data(), static_cast<int>(data.byteSize()), font.size, &config, glyphRanges);
|
||||||
|
config.MergeMode = true; // for any more fonts
|
||||||
|
}
|
||||||
|
|
||||||
// but in that case Build() has to be run before the data gets deleted
|
// but in that case Build() has to be run before the data gets deleted
|
||||||
imguiIO.Fonts->Build();
|
imguiIO.Fonts->Build();
|
||||||
@ -209,6 +236,13 @@ void Application::configureImgui()
|
|||||||
imguiIO.ConfigViewportsNoAutoMerge = true;
|
imguiIO.ConfigViewportsNoAutoMerge = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<FontConfig> Application::getDefaultFonts()
|
||||||
|
{
|
||||||
|
return {{
|
||||||
|
.path = "/data/fonts/NotoSans-Regular.ttf"
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
void Application::handleMessage(const Message& message)
|
void Application::handleMessage(const Message& message)
|
||||||
{
|
{
|
||||||
switch (message.severity)
|
switch (message.severity)
|
||||||
@ -452,8 +486,7 @@ bool Application::initImGui()
|
|||||||
// init font
|
// init font
|
||||||
if (imguiIO.Fonts->Fonts.empty())
|
if (imguiIO.Fonts->Fonts.empty())
|
||||||
{
|
{
|
||||||
static const char* const DEFAULT_FONT = "/data/fonts/NotoSans-Regular.ttf";
|
if (!loadFonts(getDefaultFonts()))
|
||||||
if (!loadFont(DEFAULT_FONT))
|
|
||||||
{
|
{
|
||||||
imguiIO.Fonts->AddFontDefault();
|
imguiIO.Fonts->AddFontDefault();
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <fmt/format.h>
|
#include <fmt/format.h>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <mijin/async/coroutine.hpp>
|
#include <mijin/async/coroutine.hpp>
|
||||||
|
#include <mijin/util/bitflags.hpp>
|
||||||
#include <mijin/virtual_filesystem/stacked.hpp>
|
#include <mijin/virtual_filesystem/stacked.hpp>
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
|
||||||
@ -34,6 +35,19 @@ struct Message
|
|||||||
const char* text;
|
const char* text;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FontFlags : mijin::BitFlags<FontFlags>
|
||||||
|
{
|
||||||
|
bool pixelSnapH : 1 = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FontConfig
|
||||||
|
{
|
||||||
|
fs::path path;
|
||||||
|
std::vector<std::pair<ImWchar, ImWchar>> glyphRanges;
|
||||||
|
float size = 20.f;
|
||||||
|
FontFlags flags;
|
||||||
|
};
|
||||||
|
|
||||||
class Application
|
class Application
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -90,7 +104,13 @@ public:
|
|||||||
int run(int argc, char* argv[]);
|
int run(int argc, char* argv[]);
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
bool loadFont(const fs::path& path);
|
bool loadFonts(std::span<const FontConfig> fonts);
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
bool loadFont(const FontConfig& font)
|
||||||
|
{
|
||||||
|
return loadFonts({&font, 1});
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
ImTextureID getOrLoadTexture(fs::path path);
|
ImTextureID getOrLoadTexture(fs::path path);
|
||||||
@ -100,6 +120,7 @@ protected:
|
|||||||
virtual std::string getFolderName() = 0;
|
virtual std::string getFolderName() = 0;
|
||||||
virtual std::string getWindowTitle() = 0;
|
virtual std::string getWindowTitle() = 0;
|
||||||
virtual void configureImgui();
|
virtual void configureImgui();
|
||||||
|
virtual std::vector<FontConfig> getDefaultFonts();
|
||||||
virtual void handleMessage(const Message& message);
|
virtual void handleMessage(const Message& message);
|
||||||
virtual void handleSDLEvent(const SDL_Event& event);
|
virtual void handleSDLEvent(const SDL_Event& event);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user