feat: font generation from ttf (#882)

* chore: add file variant of json fonts

* chore: add stb dependency

* feat: generate fonts from ttf files

* chore: add option to add yOffset to file font

* chore: dynamically adjust generated font bitmap size

* fix: printable characters should respect ISO-8859-1 control characters

* chore: do not write missing glyphs into the bitmap

* chore: remove test texture conversion

* chore: adjust font compiler for iw3,iw4,iw5,t4,t5

* chore: add possibility to fill color channels when converting

* fix: games other than t6 use rgba for fonts

* fix: make sure no mipmaps are set on loaddef

* fix: t4 and iw3 use dimensions in image loaddef

* chore: also include optional glyphs in fonts
This commit is contained in:
Jan Laupetin
2026-07-08 23:35:58 +02:00
committed by GitHub
parent c385f50a0e
commit 0874f0c36f
21 changed files with 724 additions and 30 deletions
+7 -14
View File
@@ -13,6 +13,7 @@ namespace font
return path.string();
}
// ISO-8859-1
bool IsPrintableLetter(const unsigned letter)
{
// Control characters
@@ -23,25 +24,17 @@ namespace font
if (letter < 0x7F)
return true;
// 0xA0 is not a control character but NBSP that just looks like a space
if (letter < 0xA1)
return false;
// There are characters after this point that are printable as well
// But they don't seem to play a role in cod fonts
if (letter > 0xFF)
return false;
switch (letter)
{
case 0x7F:
case 0x81:
case 0x8D:
case 0x8F:
case 0x90:
case 0x9D:
case 0xA0:
case 0xAD:
return false;
default:
return true;
}
// 0xAD is soft hyphen
return letter != 0xAD;
}
std::string LetterToString(const unsigned letter)
+62 -2
View File
@@ -15,9 +15,11 @@
#include "Json/JsonExtension.h"
#include "Font/FontCommon.h"
#include <cassert>
#include <nlohmann/json.hpp>
#include <optional>
#include <string>
#include <variant>
#include <vector>
namespace GAME
@@ -100,7 +102,7 @@ namespace GAME
}
#endif
class JsonFont
class JsonCompiledFont
{
public:
unsigned pixelHeight;
@@ -116,7 +118,7 @@ namespace GAME
};
NLOHMANN_DEFINE_TYPE_EXTENSION(
JsonFont,
JsonCompiledFont,
pixelHeight,
#ifdef FEATURE_T6
isScalingAllowed,
@@ -130,4 +132,62 @@ namespace GAME
glyphs
#endif
);
class JsonFileFont
{
public:
std::string file;
std::optional<unsigned> fontSize;
std::optional<int> yOffset;
#ifdef FEATURE_T6
std::optional<bool> isScalingAllowed;
#endif
std::optional<std::string> generatedMaterialName;
std::optional<std::string> generatedGlowMaterialName;
};
NLOHMANN_DEFINE_TYPE_EXTENSION(
JsonFileFont,
file,
fontSize,
yOffset,
#ifdef FEATURE_T6
isScalingAllowed,
#endif
generatedMaterialName,
generatedGlowMaterialName
);
class JsonFont
{
public:
std::variant<JsonCompiledFont, JsonFileFont> font;
};
NLOHMANN_TO_JSON_METHOD(JsonFont)
{
if (std::holds_alternative<JsonCompiledFont>(nlohmann_json_t.font))
{
to_json(nlohmann_json_j, std::get<JsonCompiledFont>(nlohmann_json_t.font));
}
else
{
assert(std::holds_alternative<JsonFileFont>(nlohmann_json_t.font));
to_json(nlohmann_json_j, std::get<JsonFileFont>(nlohmann_json_t.font));
}
}
NLOHMANN_FROM_JSON_METHOD(JsonFont)
{
if (nlohmann_json_j.contains("file"))
{
nlohmann_json_t.font.emplace<JsonFileFont>();
from_json(nlohmann_json_j, std::get<JsonFileFont>(nlohmann_json_t.font));
}
else
{
nlohmann_json_t.font.emplace<JsonCompiledFont>();
from_json(nlohmann_json_j, std::get<JsonCompiledFont>(nlohmann_json_t.font));
}
}
} // namespace GAME