mirror of
https://github.com/Laupetin/OpenAssetTools.git
synced 2026-07-26 18:00:38 +00:00
feat: font loading and dumping (#866)
* feat: font loading and dumping * chore: make font properties unsigned if possible * chore: use merge_patch to dump json font * chore: font material is required * chore: move static methods from font loader and dumper to anonymous namespace * chore: make sure loaded fonts have their glyphs sorted * chore: add macros for json NLOHMANN_TO_JSON_METHOD and NLOHMANN_FROM_JSON_METHOD * feat: encode printable letters as string in json Co-authored-by: hindercanrun <[email protected]> * chore: omit redundant glyph count from jsons --------- Co-authored-by: Jan Laupetin <[email protected]> Co-authored-by: hindercanrun <[email protected]> Co-authored-by: MrIkso <[email protected]>
This commit is contained in:
co-authored by
Jan Laupetin
hindercanrun
MrIkso
parent
fb4b00398c
commit
3fb8b2bb17
@@ -0,0 +1,107 @@
|
||||
#include "FontCommon.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace font
|
||||
{
|
||||
std::string GetJsonFileNameForAssetName(const std::string& assetName)
|
||||
{
|
||||
fs::path path(assetName);
|
||||
path.replace_extension(".json");
|
||||
return path.string();
|
||||
}
|
||||
|
||||
bool IsPrintableLetter(const unsigned letter)
|
||||
{
|
||||
// Control characters
|
||||
if (letter < 0x20)
|
||||
return false;
|
||||
|
||||
// Printable ascii characters
|
||||
if (letter < 0x7F)
|
||||
return true;
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
std::string LetterToString(const unsigned letter)
|
||||
{
|
||||
// UTF-8 => 1 byte
|
||||
if (letter < 0x80)
|
||||
return std::string(1, static_cast<char>(letter));
|
||||
|
||||
if (letter < 0x800)
|
||||
{
|
||||
// UTF-8 => 2 bytes
|
||||
std::string s(2, '\0');
|
||||
s[0] = static_cast<char>(0xC0 | (letter >> 6u));
|
||||
s[1] = static_cast<char>(0x80 | (letter & 0x3F));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
// UTF-8 => 3 bytes
|
||||
std::string s(3, '\0');
|
||||
s[0] = static_cast<char>(0xE0 | (letter >> 12u));
|
||||
s[1] = static_cast<char>(0x80 | ((letter >> 6u) & 0x3F));
|
||||
s[2] = static_cast<char>(0x80 | (letter & 0x3F));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
unsigned StringToLetter(const std::string& str)
|
||||
{
|
||||
const auto strSize = str.size();
|
||||
if (strSize < 1)
|
||||
return 0;
|
||||
|
||||
const auto firstByte = static_cast<unsigned char>(str[0]);
|
||||
|
||||
// UTF-8 => 1 byte
|
||||
if ((firstByte & 0x80) == 0)
|
||||
return firstByte;
|
||||
|
||||
if (strSize < 2)
|
||||
return 0;
|
||||
const auto secondByte = static_cast<unsigned char>(str[1]);
|
||||
|
||||
if ((firstByte & 0xE0) == 0xC0 && (secondByte & 0xC0) == 0x80)
|
||||
{
|
||||
// UTF-8 => 2 bytes
|
||||
return ((firstByte & 0x1F) << 6u) | (secondByte & 0x3F);
|
||||
}
|
||||
|
||||
if (strSize < 3)
|
||||
return 0;
|
||||
const auto thirdByte = static_cast<unsigned char>(str[2]);
|
||||
|
||||
if ((firstByte & 0xF0) == 0xE0 && (secondByte & 0xC0) == 0x80 && (thirdByte & 0xC0) == 0x80)
|
||||
{
|
||||
// UTF-8 => 3 bytes
|
||||
return ((firstByte & 0x0F) << 12u) | ((secondByte & 0x3F) << 6u) | (thirdByte & 0x3F);
|
||||
}
|
||||
|
||||
// Unsupported
|
||||
return 0;
|
||||
}
|
||||
} // namespace font
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace font
|
||||
{
|
||||
std::string GetJsonFileNameForAssetName(const std::string& assetName);
|
||||
|
||||
bool IsPrintableLetter(unsigned letter);
|
||||
|
||||
std::string LetterToString(unsigned letter);
|
||||
unsigned StringToLetter(const std::string& str);
|
||||
} // namespace font
|
||||
@@ -0,0 +1,67 @@
|
||||
#options GAME (IW3, IW4, IW5, T4, T5)
|
||||
|
||||
#filename "Game/" + GAME + "/Font/JsonFont" + GAME + ".h"
|
||||
|
||||
// This file was templated.
|
||||
// See JsonFont.h.template.
|
||||
// Do not modify, changes will be lost.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Json/JsonExtension.h"
|
||||
#include "Font/FontCommon.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace GAME
|
||||
{
|
||||
class JsonGlyph
|
||||
{
|
||||
public:
|
||||
unsigned letter;
|
||||
int x0;
|
||||
int y0;
|
||||
unsigned dx;
|
||||
unsigned pixelWidth;
|
||||
unsigned pixelHeight;
|
||||
float s0;
|
||||
float t0;
|
||||
float s1;
|
||||
float t1;
|
||||
};
|
||||
|
||||
NLOHMANN_TO_JSON_METHOD(JsonGlyph)
|
||||
{
|
||||
if (font::IsPrintableLetter(nlohmann_json_t.letter))
|
||||
extended_to_json("letter", nlohmann_json_j, font::LetterToString(nlohmann_json_t.letter));
|
||||
else
|
||||
extended_to_json("letter", nlohmann_json_j, nlohmann_json_t.letter);
|
||||
|
||||
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(EXTEND_JSON_TO, x0, y0, dx, pixelWidth, pixelHeight, s0, t0, s1, t1))
|
||||
}
|
||||
|
||||
NLOHMANN_FROM_JSON_METHOD(JsonGlyph)
|
||||
{
|
||||
const auto jLetter = nlohmann_json_j.at("letter");
|
||||
if (jLetter.type() == BasicJsonType::value_t::string)
|
||||
nlohmann_json_t.letter = font::StringToLetter(jLetter.template get<std::string>());
|
||||
else
|
||||
nlohmann_json_t.letter = jLetter.template get<unsigned>();
|
||||
|
||||
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(EXTEND_JSON_FROM, x0, y0, dx, pixelWidth, pixelHeight, s0, t0, s1, t1))
|
||||
}
|
||||
|
||||
class JsonFont
|
||||
{
|
||||
public:
|
||||
unsigned pixelHeight;
|
||||
std::string material;
|
||||
std::optional<std::string> glowMaterial;
|
||||
std::vector<JsonGlyph> glyphs;
|
||||
};
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_EXTENSION(JsonFont, pixelHeight, material, glowMaterial, glyphs);
|
||||
} // namespace GAME
|
||||
Reference in New Issue
Block a user