float g_fontSizeMultiplier = 1.0f;
static void ReadConfigurationFile()
{
char cfgPath[MAX_PATH];
GetModuleFileNameA(GetModuleHandleA(nullptr), cfgPath, sizeof(cfgPath));
PathRemoveFileSpecA(cfgPath);
strcat_s(cfgPath, "\\TTF.ini");
// Установка значений по умолчанию
g_fontSizeMultiplier = 1.0f; // Множитель размера шрифта по умолчанию
g_useScaling = true; // Масштабирование включено по умолчанию
g_useEncoding = 0; // Кодировка по умолчанию (UTF-8)
FILE* f;
errno_t err = fopen_s(&f, cfgPath, "r");
if(err == 0)
{
std::string currentSector = "none";
char readedLine[1024];
while(fgets(readedLine, sizeof(readedLine), f) != nullptr)
{
size_t len = strlen(readedLine);
if(len > 0)
{
if(readedLine[len - 1] == '\n' || readedLine[len - 1] == '\r')
len -= 1;
if(len > 0)
{
if(readedLine[len - 1] == '\n' || readedLine[len - 1] == '\r')
len -= 1;
}
}
if(len == 0)
continue;
if(readedLine[0] == '[' && readedLine[len - 1] == ']')
{
currentSector = std::string(readedLine + 1, len - 2);
std::transform(currentSector.begin(), currentSector.end(), currentSector.begin(), toupper);
}
else if(readedLine[0] != ';' && readedLine[0] != '/')
{
std::size_t eqpos;
std::string rLine = std::string(readedLine, len);
std::transform(rLine.begin(), rLine.end(), rLine.begin(), toupper);
if((eqpos = rLine.find("=")) != std::string::npos)
{
std::string lhLine = rLine.substr(0, eqpos);
std::string rhLine = rLine.substr(eqpos + 1);
lhLine.erase(lhLine.find_last_not_of(' ') + 1);
lhLine.erase(0, lhLine.find_first_not_of(' '));
rhLine.erase(rhLine.find_last_not_of(' ') + 1);
rhLine.erase(0, rhLine.find_first_not_of(' '));
if(currentSector == "CONFIGURATION")
{
if(lhLine == "SCALEFONTS")
{
g_useScaling = (rhLine == "TRUE" || rhLine == "1");
}
else if(lhLine == "CODEPAGE")
{
if(rhLine == "WINDOWS-1250" || rhLine == "WINDOWS1250" || rhLine == "WINDOWS 1250" || rhLine == "1250")
g_useEncoding = 1250;
else if(rhLine == "WINDOWS-1251" || rhLine == "WINDOWS1251" || rhLine == "WINDOWS 1251" || rhLine == "1251")
g_useEncoding = 1251;
else if(rhLine == "WINDOWS-1252" || rhLine == "WINDOWS1252" || rhLine == "WINDOWS 1252" || rhLine == "1252")
g_useEncoding = 1252;
else if(rhLine == "WINDOWS-1253" || rhLine == "WINDOWS1253" || rhLine == "WINDOWS 1253" || rhLine == "1253")
g_useEncoding = 1253;
else if(rhLine == "WINDOWS-1254" || rhLine == "WINDOWS1254" || rhLine == "WINDOWS 1254" || rhLine == "1254")
g_useEncoding = 1254;
else if(rhLine == "WINDOWS-1255" || rhLine == "WINDOWS1255" || rhLine == "WINDOWS 1255" || rhLine == "1255")
g_useEncoding = 1255;
else if(rhLine == "WINDOWS-1256" || rhLine == "WINDOWS1256" || rhLine == "WINDOWS 1256" || rhLine == "1256")
g_useEncoding = 1256;
else if(rhLine == "WINDOWS-1257" || rhLine == "WINDOWS1257" || rhLine == "WINDOWS 1257" || rhLine == "1257")
g_useEncoding = 1257;
else if(rhLine == "WINDOWS-1258" || rhLine == "WINDOWS1258" || rhLine == "WINDOWS 1258" || rhLine == "1258")
g_useEncoding = 1258;
else
g_useEncoding = 0;
}
// Обработка нового параметра - множителя размера шрифта
else if(lhLine == "FONTSIZE_MULTIPLIER")
{
try {
g_fontSizeMultiplier = std::stof(rhLine);
// Защита от некорректных значений
if(g_fontSizeMultiplier < 0.1f)
g_fontSizeMultiplier = 0.1f;
else if(g_fontSizeMultiplier > 10.0f)
g_fontSizeMultiplier = 10.0f;
}
catch(const std::exception&) {
g_fontSizeMultiplier = 1.0f;
}
}
}
else if(currentSector == "FONTS")
{
g_fontsWrapper.emplace(lhLine, rhLine);
}
}
}
}
fclose(f);
}
}
int __fastcall G1_zCFont_LoadFontTexture(DWORD zCFont, DWORD _EDX, zSTRING_G2& fName)
{
int size = 20, r = 0xFF, g = 0xFF, b = 0xFF, a = 0xFF;
std::string fontName(fName.ToChar(), fName.Length());
std::transform(fontName.begin(), fontName.end(), fontName.begin(), toupper);
if(fontName.find(':') == std::string::npos)
{
auto it = g_fontsWrapper.find(fontName);
if(it == g_fontsWrapper.end())
{
it = g_fontsWrapper.find("DEFAULT");
if(it == g_fontsWrapper.end())
return 0;
}
fontName.assign(it->second);
}
std::string fntName;
ReadFontDetails(fontName, fntName, size, r, g, b, a);
if(g_useBGRA) std::swap(r, b);
// Применение множителя размера шрифта
if(g_useScaling && *reinterpret_cast<BYTE*>(0x6E0238) == 0xE9)
{
float UIscale = *reinterpret_cast<float*>(*reinterpret_cast<DWORD*>(0x5A88E1));
size = static_cast<int>(size * UIscale * g_fontSizeMultiplier);
}
else
{
// Применяем множитель даже если масштабирование интерфейса отключено
size = static_cast<int>(size * g_fontSizeMultiplier);
}
*reinterpret_cast<int*>(zCFont + 0x14) = size;
zSTRING_G2& path = reinterpret_cast<zSTRING_G2&(__thiscall*)(DWORD, int)>(0x45FC00)(*reinterpret_cast<DWORD*>(0x869694), 23);
fntName.insert(0, "\\_WORK\\FONTS\\G1_");
fntName.insert(0, path.ToChar(), path.Length());
TTFont* ttFont = new TTFont;
ttFont->r = r; ttFont->g = g; ttFont->b = b; ttFont->a = a;
*reinterpret_cast<TTFont**>(zCFont + 0x20) = ttFont;
if(FT_New_Face(g_ft, fntName.c_str(), 0, &ttFont->fontFace))
{
MessageBoxW(nullptr, L"Failed to load font", L"Gothic TTF", MB_ICONHAND);
exit(-1);
}
for(int i = 0; i < ttFont->fontFace->num_charmaps; ++i)
{
FT_CharMap charmap = ttFont->fontFace->charmaps[i];
if((charmap->platform_id == 3 && charmap->encoding_id == 1) /* Windows Unicode */
|| (charmap->platform_id == 3 && charmap->encoding_id == 0) /* Windows Symbol */
|| (charmap->platform_id == 2 && charmap->encoding_id == 1) /* ISO Unicode */
|| (charmap->platform_id == 0)) /* Apple Unicode */
{
FT_Set_Charmap(ttFont->fontFace, charmap);
break;
}
}
FT_Set_Pixel_Sizes(ttFont->fontFace, 0, size);
if(FT_IS_SCALABLE(ttFont->fontFace))
{
FT_Fixed scale = ttFont->fontFace->size->metrics.y_scale;
int height = FT_MulFix(ttFont->fontFace->height, scale);
int ascent = FT_MulFix(ttFont->fontFace->ascender, scale);
int descent = FT_MulFix(ttFont->fontFace->descender, scale);
*reinterpret_cast<int*>(zCFont + 0x24) = static_cast<int>(((height + 63) & -64) / 64);
*reinterpret_cast<int*>(zCFont + 0x28) = static_cast<int>(((ascent + 63) & -64) / 64);
*reinterpret_cast<int*>(zCFont + 0x2C) = static_cast<int>(((descent + 63) & -64) / 64);
}
else
{
*reinterpret_cast<int*>(zCFont + 0x24) = static_cast<int>(((ttFont->fontFace->size->metrics.height + 63) & -64) / 64);
*reinterpret_cast<int*>(zCFont + 0x28) = static_cast<int>(((ttFont->fontFace->size->metrics.ascender + 63) & -64) / 64);
*reinterpret_cast<int*>(zCFont + 0x2C) = static_cast<int>(((ttFont->fontFace->size->metrics.descender + 63) & -64) / 64);
}
g_fonts.emplace(ttFont);
return 1;
}
int __fastcall G2_zCFont_LoadFontTexture(DWORD zCFont, DWORD _EDX, zSTRING_G2& fName)
{
int size = 20, r = 0xFF, g = 0xFF, b = 0xFF, a = 0xFF;
std::string fontName(fName.ToChar(), fName.Length());
std::transform(fontName.begin(), fontName.end(), fontName.begin(), toupper);
if(fontName.find(':') == std::string::npos)
{
auto it = g_fontsWrapper.find(fontName);
if(it == g_fontsWrapper.end())
{
it = g_fontsWrapper.find("DEFAULT");
if(it == g_fontsWrapper.end())
return 0;
}
fontName.assign(it->second);
}
std::string fntName;
ReadFontDetails(fontName, fntName, size, r, g, b, a);
if(g_useBGRA) std::swap(r, b);
// Применение множителя размера шрифта
if(g_useScaling && *reinterpret_cast<BYTE*>(0x789518) == 0xE9)
{
float UIscale = *reinterpret_cast<float*>(*reinterpret_cast<DWORD*>(0x66714F));
size = static_cast<int>(size * UIscale * g_fontSizeMultiplier);
}
else
{
// Применяем множитель даже если масштабирование интерфейса отключено
size = static_cast<int>(size * g_fontSizeMultiplier);
}
*reinterpret_cast<int*>(zCFont + 0x14) = size;
zSTRING_G2& path = reinterpret_cast<zSTRING_G2&(__thiscall*)(DWORD, int)>(0x465260)(*reinterpret_cast<DWORD*>(0x8CD988), 24);
fntName.insert(0, "\\_WORK\\FONTS\\G2_");
fntName.insert(0, path.ToChar(), path.Length());
TTFont* ttFont = new TTFont;
ttFont->r = r; ttFont->g = g; ttFont->b = b; ttFont->a = a;
*reinterpret_cast<TTFont**>(zCFont + 0x20) = ttFont;
if(FT_New_Face(g_ft, fntName.c_str(), 0, &ttFont->fontFace))
{
MessageBoxW(nullptr, L"Failed to load font", L"Gothic TTF", MB_ICONHAND);
exit(-1);
}
for(int i = 0; i < ttFont->fontFace->num_charmaps; ++i)
{
FT_CharMap charmap = ttFont->fontFace->charmaps[i];
if((charmap->platform_id == 3 && charmap->encoding_id == 1) /* Windows Unicode */
|| (charmap->platform_id == 3 && charmap->encoding_id == 0) /* Windows Symbol */
|| (charmap->platform_id == 2 && charmap->encoding_id == 1) /* ISO Unicode */
|| (charmap->platform_id == 0)) /* Apple Unicode */
{
FT_Set_Charmap(ttFont->fontFace, charmap);
break;
}
}
FT_Set_Pixel_Sizes(ttFont->fontFace, 0, size);
if(FT_IS_SCALABLE(ttFont->fontFace))
{
FT_Fixed scale = ttFont->fontFace->size->metrics.y_scale;
int height = FT_MulFix(ttFont->fontFace->height, scale);
int ascent = FT_MulFix(ttFont->fontFace->ascender, scale);
int descent = FT_MulFix(ttFont->fontFace->descender, scale);
*reinterpret_cast<int*>(zCFont + 0x24) = static_cast<int>(((height + 63) & -64) / 64);
*reinterpret_cast<int*>(zCFont + 0x28) = static_cast<int>(((ascent + 63) & -64) / 64);
*reinterpret_cast<int*>(zCFont + 0x2C) = static_cast<int>(((descent + 63) & -64) / 64);
}
else
{
*reinterpret_cast<int*>(zCFont + 0x24) = static_cast<int>(((ttFont->fontFace->size->metrics.height + 63) & -64) / 64);
*reinterpret_cast<int*>(zCFont + 0x28) = static_cast<int>(((ttFont->fontFace->size->metrics.ascender + 63) & -64) / 64);
*reinterpret_cast<int*>(zCFont + 0x2C) = static_cast<int>(((ttFont->fontFace->size->metrics.descender + 63) & -64) / 64);
}
g_fonts.emplace(ttFont);
return 1;
}