Implement SDF fonts. (#24)

* Initial SDF font generation work.

* Text now correctly displaying with proper spacing.

* Fix untextured draws, implement custom rectangles.

* Fix regular image display.

* Slightly refactor ImGui rendering.

* Implement outlines.

* Implement bevel.

* Create host device after loading the module if the installer wasn't run.

* Move ImGui files to its own folder.

* Fix outline sizes.

* Fix default ImGui font and font scales.

* Update font atlas files.
This commit is contained in:
Skyth (Asilkan)
2024-12-11 23:30:19 +03:00
committed by GitHub
parent 632cf2619e
commit cdcacff53b
23 changed files with 536 additions and 154 deletions
+12 -14
View File
@@ -13,7 +13,7 @@
#include <res/images/achievements_menu/trophy.dds.h>
#include <res/images/common/general_window.dds.h>
#include <res/images/common/select_fill.dds.h>
#include <gpu/imgui_snapshot.h>
#include <gpu/imgui/imgui_snapshot.h>
constexpr double HEADER_CONTAINER_INTRO_MOTION_START = 0;
constexpr double HEADER_CONTAINER_INTRO_MOTION_END = 15;
@@ -141,14 +141,14 @@ static void DrawHeaderContainer(const char* text)
SetTextSkew((min.y + max.y) / 2.0f, Scale(3.0f));
// TODO: Apply bevel.
DrawTextWithOutline<float>
DrawTextWithOutline
(
g_fntNewRodinUB,
fontSize,
{ /* X */ min.x + textMarginX, /* Y */ CENTRE_TEXT_VERT(min, max, textSize) - Scale(5) },
IM_COL32(255, 255, 255, 255 * alpha),
text,
1.65f,
4,
IM_COL32(0, 0, 0, 255 * alpha)
);
@@ -222,7 +222,7 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
isUnlocked ? IM_COL32(252, 243, 5, 255) : colLockedText,
achievement.Name.c_str(),
shadowOffset,
0.4f,
1.0f,
colTextShadow
);
@@ -261,7 +261,7 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
isUnlocked ? IM_COL32_WHITE : colLockedText,
desc,
shadowOffset,
0.4f,
1.0f,
colTextShadow
);
}
@@ -349,14 +349,14 @@ static void DrawAchievement(int rowIndex, float yOffset, Achievement& achievemen
);
// Draw timestamp text.
DrawTextWithOutline<int>
DrawTextWithOutline
(
g_fntNewRodinDB,
fontSize,
{ /* X */ CENTRE_TEXT_HORZ(timestampMin, timestampMax, textSize), /* Y */ CENTRE_TEXT_VERT(timestampMin, timestampMax, textSize) },
IM_COL32(255, 255, 255, 255),
buffer,
2,
4,
IM_COL32(8, 8, 8, 255)
);
@@ -523,14 +523,14 @@ static void DrawAchievementTotal(ImVec2 min, ImVec2 max)
auto fontSize = Scale(20);
auto textSize = g_fntNewRodinDB->CalcTextSizeA(fontSize, FLT_MAX, 0, str.c_str());
DrawTextWithOutline<int>
DrawTextWithOutline
(
g_fntNewRodinDB,
fontSize,
{ /* X */ imageMin.x - textSize.x - Scale(6), /* Y */ CENTRE_TEXT_VERT(imageMin, imageMax, textSize) },
IM_COL32(255, 255, 255, 255 * alpha),
str.c_str(),
2,
4,
IM_COL32(0, 0, 0, 255 * alpha)
);
}
@@ -765,11 +765,9 @@ void AchievementMenu::Init()
{
auto& io = ImGui::GetIO();
constexpr float FONT_SCALE = 2.0f;
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
g_fntNewRodinDB = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf", 20.0f * FONT_SCALE);
g_fntNewRodinUB = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-UB.otf", 20.0f * FONT_SCALE);
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
g_fntNewRodinDB = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf");
g_fntNewRodinUB = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-UB.otf");
g_upTrophyIcon = LOAD_ZSTD_TEXTURE(g_trophy);
g_upSelectionCursor = LOAD_ZSTD_TEXTURE(g_select_fill);
+4 -6
View File
@@ -10,7 +10,7 @@
#include <exports.h>
#include <decompressor.h>
#include <res/images/common/general_window.dds.h>
#include <gpu/imgui_snapshot.h>
#include <gpu/imgui/imgui_snapshot.h>
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_START = 0;
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_END = 11;
@@ -76,9 +76,7 @@ void AchievementOverlay::Init()
{
auto& io = ImGui::GetIO();
constexpr float FONT_SCALE = 2.0f;
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
g_upWindow = LOAD_ZSTD_TEXTURE(g_general_window);
}
@@ -145,7 +143,7 @@ void AchievementOverlay::Draw()
IM_COL32(252, 243, 5, 255), // colour
strAchievementUnlocked, // text
2, // offset
0.4f, // radius
1.0f, // radius
IM_COL32(0, 0, 0, 255) // shadowColour
);
@@ -158,7 +156,7 @@ void AchievementOverlay::Draw()
IM_COL32(255, 255, 255, 255), // colour
strAchievementName, // text
2, // offset
0.4f, // radius
1.0f, // radius
IM_COL32(0, 0, 0, 255) // shadowColour
);
+4 -6
View File
@@ -1,6 +1,6 @@
#include "button_guide.h"
#include "imgui_utils.h"
#include <gpu/imgui_snapshot.h>
#include <gpu/imgui/imgui_snapshot.h>
#include <gpu/video.h>
#include <hid/hid_detail.h>
#include <user/config.h>
@@ -188,7 +188,7 @@ static void DrawGuide(float* offset, ImVec2 regionMin, ImVec2 regionMax, EButton
ImVec2 textPosition = { textMarginX, textMarginY };
DrawTextWithOutline<int>(font, fontSize, textPosition, IM_COL32_WHITE, text, 2, IM_COL32_BLACK);
DrawTextWithOutline(font, fontSize, textPosition, IM_COL32_WHITE, text, 4, IM_COL32_BLACK);
// Add extra luminance to low quality text.
if (fontQuality == EFontQuality::Low)
@@ -214,10 +214,8 @@ void ButtonGuide::Init()
{
auto& io = ImGui::GetIO();
constexpr float FONT_SCALE = 2.0f;
g_fntNewRodin = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-M.otf", 24.0f * FONT_SCALE);
g_fntNewRodinLQ = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-M.otf", 19.0f);
g_fntNewRodin = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-M.otf");
g_fntNewRodinLQ = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-M.otf");
g_upControllerIcons = LOAD_ZSTD_TEXTURE(g_controller);
g_upKBMIcons = LOAD_ZSTD_TEXTURE(g_kbm);
+25 -35
View File
@@ -1,6 +1,6 @@
#pragma once
#include <gpu/imgui_common.h>
#include <gpu/imgui/imgui_common.h>
#include <gpu/video.h>
#include <app.h>
@@ -83,6 +83,17 @@ static void ResetMarqueeFade()
SetScale({ 1.0f, 1.0f });
}
static void SetOutline(float outline)
{
auto callbackData = AddImGuiCallback(ImGuiCallback::SetOutline);
callbackData->setOutline.outline = outline;
}
static void ResetOutline()
{
SetOutline(0.0f);
}
// Aspect ratio aware.
static float Scale(float size)
{
@@ -179,53 +190,32 @@ static void DrawTextWithMarquee(const ImFont* font, float fontSize, const ImVec2
drawList->PopClipRect();
}
template<typename T>
static void DrawTextWithOutline(const ImFont* font, float fontSize, const ImVec2& pos, ImU32 color, const char* text, T outlineSize, ImU32 outlineColor)
static void DrawTextWithOutline(const ImFont* font, float fontSize, const ImVec2& pos, ImU32 color, const char* text, float outlineSize, ImU32 outlineColor, uint32_t shaderModifier = IMGUI_SHADER_MODIFIER_NONE)
{
auto drawList = ImGui::GetForegroundDrawList();
outlineSize = Scale(outlineSize);
SetOutline(outlineSize);
drawList->AddText(font, fontSize, pos, outlineColor, text);
ResetOutline();
if constexpr (std::is_same_v<float, T> || std::is_same_v<double, T>)
{
auto step = outlineSize / 2.0f;
// TODO: This is still very inefficient!
for (float i = -outlineSize; i <= outlineSize; i += step)
{
for (float j = -outlineSize; j <= outlineSize; j += step)
{
if (i == 0.0f && j == 0.0f)
continue;
drawList->AddText(font, fontSize, { pos.x + i, pos.y + j }, outlineColor, text);
}
}
}
else if constexpr (std::is_integral_v<T>)
{
// TODO: This is very inefficient!
for (int32_t i = -outlineSize + 1; i < outlineSize; i++)
{
for (int32_t j = -outlineSize + 1; j < outlineSize; j++)
{
if (i != 0 || j != 0)
drawList->AddText(font, fontSize, { pos.x + i, pos.y + j }, outlineColor, text);
}
}
}
if (shaderModifier != IMGUI_SHADER_MODIFIER_NONE)
SetShaderModifier(shaderModifier);
drawList->AddText(font, fontSize, pos, color, text);
if (shaderModifier != IMGUI_SHADER_MODIFIER_NONE)
SetShaderModifier(IMGUI_SHADER_MODIFIER_NONE);
}
static void DrawTextWithShadow(const ImFont* font, float fontSize, const ImVec2& pos, ImU32 colour, const char* text, float offset = 2.0f, float radius = 0.4f, ImU32 shadowColour = IM_COL32(0, 0, 0, 255))
static void DrawTextWithShadow(const ImFont* font, float fontSize, const ImVec2& pos, ImU32 colour, const char* text, float offset = 2.0f, float radius = 1.0f, ImU32 shadowColour = IM_COL32(0, 0, 0, 255))
{
auto drawList = ImGui::GetForegroundDrawList();
offset = Scale(offset);
radius = Scale(radius);
DrawTextWithOutline<float>(font, fontSize, { pos.x + offset, pos.y + offset }, shadowColour, text, radius, shadowColour);
SetOutline(radius);
drawList->AddText(font, fontSize, { pos.x + offset, pos.y + offset }, shadowColour, text);
ResetOutline();
drawList->AddText(font, fontSize, pos, colour, text, nullptr);
}
+7 -8
View File
@@ -4,7 +4,7 @@
#include <install/installer.h>
#include <gpu/video.h>
#include <gpu/imgui_snapshot.h>
#include <gpu/imgui/imgui_snapshot.h>
#include <hid/hid.h>
#include <hid/hid_detail.h>
#include <locale/locale.h>
@@ -559,7 +559,7 @@ static void DrawScanlineBars()
// Installer text
const std::string &headerText = Localise(g_currentPage == WizardPage::Installing ? "Installer_Header_Installing" : "Installer_Header_Installer");
int textAlpha = std::lround(255.0f * ComputeMotionInstaller(g_appearTime, g_disappearTime, TITLE_ANIMATION_TIME, TITLE_ANIMATION_DURATION));
DrawTextWithOutline<int>(g_dfsogeistdFont, Scale(42.0f), { Scale(285.0f), Scale(57.0f) }, IM_COL32(255, 195, 0, textAlpha), headerText.c_str(), 4, IM_COL32(0, 0, 0, textAlpha));
DrawTextWithOutline(g_dfsogeistdFont, Scale(42.0f), { Scale(285.0f), Scale(57.0f) }, IM_COL32(255, 195, 0, textAlpha), headerText.c_str(), 4, IM_COL32(0, 0, 0, textAlpha), IMGUI_SHADER_MODIFIER_TITLE_BEVEL);
// Top bar line
drawList->AddLine
@@ -761,14 +761,14 @@ static void DrawButton(ImVec2 min, ImVec2 max, const char *buttonText, bool sour
IM_COL32(baser + 128, baseg + 170, 0, 255)
);
DrawTextWithOutline<int>
DrawTextWithOutline
(
font,
size,
min,
IM_COL32(255, 255, 255, 255 * alpha),
buttonText,
2,
4,
IM_COL32(baser, baseg, 0, 255 * alpha)
);
@@ -1334,10 +1334,9 @@ static void DrawMessagePrompt()
void InstallerWizard::Init()
{
auto &io = ImGui::GetIO();
constexpr float FONT_SCALE = 2.0f;
g_seuratFont = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
g_dfsogeistdFont = ImFontAtlasSnapshot::GetFont("DFSoGeiStd-W7.otf", 48.0f * FONT_SCALE);
g_newRodinFont = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf", 20.0f * FONT_SCALE);
g_seuratFont = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
g_dfsogeistdFont = ImFontAtlasSnapshot::GetFont("DFSoGeiStd-W7.otf");
g_newRodinFont = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf");
g_installTextures[0] = LOAD_ZSTD_TEXTURE(g_install_001);
g_installTextures[1] = LOAD_ZSTD_TEXTURE(g_install_002);
g_installTextures[2] = LOAD_ZSTD_TEXTURE(g_install_003);
+2 -4
View File
@@ -11,7 +11,7 @@
#include <res/images/common/general_window.dds.h>
#include <decompressor.h>
#include <res/images/common/select_fade.dds.h>
#include <gpu/imgui_snapshot.h>
#include <gpu/imgui/imgui_snapshot.h>
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_START = 0;
constexpr double OVERLAY_CONTAINER_COMMON_MOTION_END = 11;
@@ -256,9 +256,7 @@ void MessageWindow::Init()
{
auto& io = ImGui::GetIO();
constexpr float FONT_SCALE = 2.0f;
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
g_fntSeurat = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
g_upSelectionCursor = LOAD_ZSTD_TEXTURE(g_select_fade);
g_upWindow = LOAD_ZSTD_TEXTURE(g_general_window);
+20 -13
View File
@@ -5,9 +5,9 @@
#include "exports.h"
#include <api/SWA/System/InputState.h>
#include <gpu/imgui_common.h>
#include <gpu/imgui/imgui_common.h>
#include <gpu/video.h>
#include <gpu/imgui_snapshot.h>
#include <gpu/imgui/imgui_snapshot.h>
#include <kernel/heap.h>
#include <kernel/memory.h>
#include <locale/locale.h>
@@ -138,7 +138,15 @@ static void DrawScanlineBars()
// Options text
// TODO: localise this.
DrawTextWithOutline<int>(g_dfsogeistdFont, Scale(48.0f), { Scale(122.0f), Scale(56.0f) }, IM_COL32(255, 195, 0, 255), "OPTIONS", 4, IM_COL32_BLACK);
DrawTextWithOutline(
g_dfsogeistdFont,
Scale(48.0f),
{ Scale(122.0f), Scale(56.0f) },
IM_COL32(255, 190, 33, 255),
"OPTIONS",
4,
IM_COL32_BLACK,
IMGUI_SHADER_MODIFIER_TITLE_BEVEL);
// Top bar line
drawList->AddLine
@@ -389,15 +397,16 @@ static bool DrawCategories()
IM_COL32(255, 192, 0, alpha)
);
DrawTextWithOutline<int>
DrawTextWithOutline
(
g_dfsogeistdFont,
size,
min,
IM_COL32_WHITE,
GetCategory(i).c_str(),
3,
IM_COL32_BLACK
4,
IM_COL32_BLACK,
IMGUI_SHADER_MODIFIER_CATEGORY_BEVEL
);
ResetGradient();
@@ -755,14 +764,14 @@ static void DrawConfigOption(int32_t rowIndex, float yOffset, ConfigDef<T>* conf
IM_COL32(128, 170, 0, 255)
);
DrawTextWithOutline<int>
DrawTextWithOutline
(
g_newRodinFont,
size,
min,
IM_COL32(255, 255, 255, 255 * alpha),
valueText.data(),
2,
4,
IM_COL32(0, 0, 0, 255 * alpha)
);
@@ -990,11 +999,9 @@ void OptionsMenu::Init()
{
auto& io = ImGui::GetIO();
constexpr float FONT_SCALE = 2.0f;
g_seuratFont = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf", 24.0f * FONT_SCALE);
g_dfsogeistdFont = ImFontAtlasSnapshot::GetFont("DFSoGeiStd-W7.otf", 48.0f * FONT_SCALE);
g_newRodinFont = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf", 20.0f * FONT_SCALE);
g_seuratFont = ImFontAtlasSnapshot::GetFont("FOT-SeuratPro-M.otf");
g_dfsogeistdFont = ImFontAtlasSnapshot::GetFont("DFSoGeiStd-W7.otf");
g_newRodinFont = ImFontAtlasSnapshot::GetFont("FOT-NewRodinPro-DB.otf");
LoadThumbnails();
}