From 7a6ae6ac50177980aac794062b9c06b5f67939f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Dobra?= Date: Tue, 18 Jan 2022 07:42:14 +0100 Subject: [PATCH] Add support for SYSTEM font (#119) * Add support for SYSTEM font * Add System Font Name registry option Issue #87 --- SpaceCadetPinball/gdrv.cpp | 174 ++++++++++++++++++++++++++-------- SpaceCadetPinball/gdrv.h | 11 +++ SpaceCadetPinball/options.cpp | 4 + SpaceCadetPinball/options.h | 2 + SpaceCadetPinball/pch.h | 1 + 5 files changed, 152 insertions(+), 40 deletions(-) diff --git a/SpaceCadetPinball/gdrv.cpp b/SpaceCadetPinball/gdrv.cpp index e3fe5f8..5766e93 100644 --- a/SpaceCadetPinball/gdrv.cpp +++ b/SpaceCadetPinball/gdrv.cpp @@ -16,7 +16,10 @@ int gdrv::use_wing = 0; int gdrv::grtext_blue = 0; int gdrv::grtext_green = 0; int gdrv::grtext_red = -1; - +std::string gdrv::fontFamily; +std::string gdrv::fontFilename; +const int* gdrv::fontSizes = nullptr; +int gdrv::fontCharset = DEFAULT_CHARSET; int gdrv::init(HINSTANCE hInst, HWND hWnd) { @@ -26,6 +29,9 @@ int gdrv::init(HINSTANCE hInst, HWND hWnd) hwnd = hWnd; if (!palette_handle) palette_handle = CreatePalette(¤t_palette); + + choose_font(); + return 0; } @@ -33,6 +39,10 @@ int gdrv::uninit() { if (palette_handle) DeleteObject(palette_handle); + + if (!fontFilename.empty()) + RemoveFontResourceExA(fontFilename.c_str(), FR_PRIVATE, 0); + return 0; } @@ -426,23 +436,128 @@ void gdrv::ScrollBitmapHorizontal(gdrv_bitmap8* bmp, int xStart) } } +int CALLBACK gdrv_find_font_func( + ENUMLOGFONTEXA *lpelfe, + NEWTEXTMETRICEXA *lpntme, + DWORD FontType, + LPARAM lParam +) +{ + auto* params = reinterpret_cast(lParam); + if (strcmp(reinterpret_cast(lpelfe->elfFullName), params->name) == 0) + params->found = true; + return 1; // continue enumeration +} + +bool gdrv::find_font(const char* fontName) +{ + EnumFindFont params; + params.name = fontName; + params.found = false; + + LOGFONTA lf{}; + strcpy_s(lf.lfFaceName, fontName); + + HDC hDC = GetDC(NULL); + EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)&gdrv_find_font_func, reinterpret_cast(¶ms), 0); + ReleaseDC(NULL, hDC); + return params.found; +} + +void gdrv::choose_font() +{ + // Original font was 16 points, used with lowest table resolution + static const int fontSizes_Arial[3] = { 16, 22, 28 }; + static const int fontSizes_EastAsian[3] = { 22, 27, 32 }; + static const int fontSizes_System[3] = { 17, 21, 29 }; + static const int fontSizes_WinMenu[3] = { 17, 21, 27 }; + + const char* system_font_filename = nullptr; + // Only System font requires non-default charset, + // and custom charsets may break other fonts (like WinMenu). + int systemFontCharset = DEFAULT_CHARSET; + + switch (options::Options.Language) + { + case Languages::TraditionalChinese: + fontFamily = "Microsoft JhengHei"; + fontSizes = fontSizes_EastAsian; + break; + case Languages::SimplifiedChinese: + fontFamily = "Microsoft YaHei"; + fontSizes = fontSizes_EastAsian; + break; + case Languages::Japanese: + fontFamily = "MS UI Gothic"; + fontSizes = fontSizes_Arial; // we need feedback for this + break; + case Languages::Korean: + fontFamily = "Gulim"; + fontSizes = fontSizes_EastAsian; + break; + case Languages::Greek: + system_font_filename = "vgasysg.fon"; + systemFontCharset = GREEK_CHARSET; + break; + case Languages::Russian: + system_font_filename = "vgasysr.fon"; + systemFontCharset = RUSSIAN_CHARSET; + break; + case Languages::Turkish: + system_font_filename = "vgasyst.fon"; + systemFontCharset = TURKISH_CHARSET; + break; + case Languages::Danish: + case Languages::Dutch: + case Languages::Norwegian: + case Languages::Swedish: + system_font_filename = "vgasys.fon"; + systemFontCharset = DEFAULT_CHARSET; + break; + case Languages::Czech: + case Languages::Hungarian: + case Languages::Polish: + system_font_filename = "vgasyse.fon"; + systemFontCharset = EASTEUROPE_CHARSET; + break; + default: + system_font_filename = "vgasys.fon"; + break; + } + + if (fontFamily.empty()) // no font chosen yet + { + if (!options::Options.SystemFont) + { + fontFamily = "Arial"; + fontSizes = fontSizes_Arial; + } + else if (options::Options.SystemFontName[0] != '\0' && find_font(options::Options.SystemFontName)) + { + fontFamily = options::Options.SystemFontName; + fontSizes = fontSizes_WinMenu; + } + else + { + fontFamily = "System"; + fontSizes = fontSizes_System; + fontCharset = systemFontCharset; + + std::string windir(MAX_PATH, '\0'); + DWORD result = GetEnvironmentVariableA("WINDIR", &windir[0], MAX_PATH); + if (result == 0 || result > MAX_PATH) // fails or doesn't fit + windir = "C:\\Windows"; + else + windir.resize(result); + + fontFilename = windir + "\\Fonts\\" + system_font_filename; + AddFontResourceExA(fontFilename.c_str(), FR_PRIVATE, 0); + } + } +} void gdrv::grtext_draw_ttext_in_box(LPCWSTR text, int xOff, int yOff, int width, int height, bool centered) { - // Original font was 16 points, used with lowest table resolution - static const int fontSizes[3] = - { - 16, - 22, - 28 - }; - static const int fontSizes_EastAsian[3] = - { - 22, - 27, - 32 - }; - xOff = static_cast(xOff * fullscrn::ScaleX) + fullscrn::OffsetX; yOff = static_cast(yOff * fullscrn::ScaleY) + fullscrn::OffsetY; width = static_cast(width * fullscrn::ScaleX); @@ -464,33 +579,12 @@ void gdrv::grtext_draw_ttext_in_box(LPCWSTR text, int xOff, int yOff, int width, sscanf_s(fontColor, "%d %d %d", &grtext_red, &grtext_green, &grtext_blue); } - const char* font = "Arial"; - const int* selectedFontSizes = fontSizes; - switch (options::Options.Language) - { - case Languages::TraditionalChinese: - font = "Microsoft JhengHei"; - selectedFontSizes = fontSizes_EastAsian; - break; - case Languages::SimplifiedChinese: - font = "Microsoft YaHei"; - selectedFontSizes = fontSizes_EastAsian; - break; - case Languages::Japanese: - font = "MS UI Gothic"; - break; - case Languages::Korean: - font = "Malgun Gothic"; - selectedFontSizes = fontSizes_EastAsian; - break; - } - - auto fontSize = static_cast(round(selectedFontSizes[fullscrn::GetResolution()] * fullscrn::ScaleY)); + auto fontSize = static_cast(round(fontSizes[fullscrn::GetResolution()] * fullscrn::ScaleY)); // Default font does not scale well - auto hNewFont = CreateFont(fontSize, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, - DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, - DEFAULT_PITCH | FF_SWISS, font); + auto hNewFont = CreateFontA(fontSize, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, + fontCharset, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, + DEFAULT_PITCH | FF_SWISS, fontFamily.c_str()); HFONT hOldFont = static_cast(SelectObject(dc, hNewFont)); int prevMode = SetBkMode(dc, TRANSPARENT); COLORREF color = SetTextColor(dc, grtext_red | grtext_green << 8 | grtext_blue << 16); diff --git a/SpaceCadetPinball/gdrv.h b/SpaceCadetPinball/gdrv.h index 0006d7f..5266156 100644 --- a/SpaceCadetPinball/gdrv.h +++ b/SpaceCadetPinball/gdrv.h @@ -33,6 +33,11 @@ struct LOGPALETTEx256 : LOGPALETTE } }; +struct EnumFindFont +{ + const char* name; + bool found; +}; class gdrv { @@ -65,6 +70,8 @@ public: static void copy_bitmap_w_transparency(gdrv_bitmap8* dstBmp, int width, int height, int xOff, int yOff, gdrv_bitmap8* srcBmp, int srcXOff, int srcYOff); static void ScrollBitmapHorizontal(gdrv_bitmap8* bmp, int xStart); + static bool find_font(const char* fontName); + static void choose_font(); static void grtext_draw_ttext_in_box(LPCWSTR text, int xOff, int yOff, int width, int height, bool centered); private: /*COLORONCOLOR or HALFTONE*/ @@ -74,6 +81,10 @@ private: static int grtext_blue; static int grtext_green; static int grtext_red; + static std::string fontFamily; + static std::string fontFilename; + static const int* fontSizes; + static int fontCharset; static int StretchDIBitsScaled(HDC hdc, int xDest, int yDest, int DestWidth, int DestHeight, int xSrc, int ySrc, int SrcWidth, int SrcHeight, gdrv_bitmap8* bmp, UINT iUsage, diff --git a/SpaceCadetPinball/options.cpp b/SpaceCadetPinball/options.cpp index 7c8854e..100bb51 100644 --- a/SpaceCadetPinball/options.cpp +++ b/SpaceCadetPinball/options.cpp @@ -139,6 +139,8 @@ void options::ReadOptions() Options.TargetUps = get_int(nullptr, "Target UPS", 120); Options.TargetUps = max(60, Options.TargetUps); Options.TargetUps = min(Options.TargetUps, 360); + Options.SystemFont = get_int(nullptr, "System Font", false); + get_string(nullptr, "System Font Name", Options.SystemFontName, "", LF_FACESIZE); auto defaultLanguage = Languages::English; auto language = static_cast(get_int(nullptr, "Language", static_cast(defaultLanguage))); @@ -237,6 +239,8 @@ void options::uninit() set_int(nullptr, "Screen Resolution", Options.Resolution); set_int(nullptr, "Uniform scaling", Options.UniformScaling); set_int(nullptr, "Alternative Render", Options.AlternativeRender); + set_int(nullptr, "System Font", Options.SystemFont); + set_string(nullptr, "System Font Name", Options.SystemFontName); set_int(nullptr, "Language", static_cast(Options.Language)); set_int(nullptr, "Target UPS", Options.TargetUps); } diff --git a/SpaceCadetPinball/options.h b/SpaceCadetPinball/options.h index 0b489d0..4d5b808 100644 --- a/SpaceCadetPinball/options.h +++ b/SpaceCadetPinball/options.h @@ -60,6 +60,8 @@ struct optionsStruct bool UniformScaling; bool AlternativeRender; int TargetUps; + bool SystemFont; + char SystemFontName[LF_FACESIZE]; Languages Language; }; diff --git a/SpaceCadetPinball/pch.h b/SpaceCadetPinball/pch.h index 3cee88d..824e0f5 100644 --- a/SpaceCadetPinball/pch.h +++ b/SpaceCadetPinball/pch.h @@ -19,6 +19,7 @@ #include #include /*For control template*/ //#include +#include /*Use (void) to silent unused warnings.*/ #define assertm(exp, msg) assert(((void)msg, exp))