Skip to content

Commit beaa981

Browse files
committed
thcrap/TSA: cover System/GDI's default font with fontrules
Note that this will mess up some text size calculations done with GetTextExtent. Because of that, that function has been removed
1 parent ebb0674 commit beaa981

File tree

2 files changed

+145
-16
lines changed

2 files changed

+145
-16
lines changed

thcrap/src/textdisp.cpp

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,103 @@ W32U8_DETOUR_CHAIN_DEF(CreateFont);
1616
W32U8_DETOUR_CHAIN_DEF(CreateFontIndirectEx);
1717
auto chain_CreateFontW = CreateFontW;
1818
auto chain_CreateFontIndirectExW = CreateFontIndirectExW;
19+
auto chain_SelectObject = SelectObject;
20+
21+
#define CHAIN(f) auto chain_##f = f
22+
W32U8_DETOUR_CHAIN_DEF(DrawText);
23+
W32U8_DETOUR_CHAIN_DEF(DrawTextEx);
24+
W32U8_DETOUR_CHAIN_DEF(ExtTextOut);
25+
W32U8_DETOUR_CHAIN_DEF(PolyTextOut);
26+
W32U8_DETOUR_CHAIN_DEF(TabbedTextOut);
27+
W32U8_DETOUR_CHAIN_DEF(TextOut);
28+
29+
CHAIN(DrawTextW);
30+
CHAIN(DrawTextExW);
31+
CHAIN(ExtTextOutW);
32+
CHAIN(PolyTextOutW);
33+
CHAIN(TabbedTextOutW);
34+
CHAIN(TextOutW);
35+
36+
/// -------------
37+
HFONT hSystemFont = NULL;
1938
/// -------------
2039

40+
#define CUSTOM_SYSTEM_FONT \
41+
do { \
42+
if (GetCurrentObject(hdc, OBJ_FONT) == GetStockObject(SYSTEM_FONT)) { \
43+
SelectObject(hdc, hSystemFont); \
44+
} \
45+
} while(0)
46+
47+
int WINAPI textdisp_DrawTextW(HDC hdc, LPWSTR lpchText, int cchText, LPRECT lprc, UINT format) {
48+
CUSTOM_SYSTEM_FONT;
49+
return chain_DrawTextW(hdc, lpchText, cchText, lprc, format);
50+
}
51+
52+
int WINAPI textdisp_DrawTextA(HDC hdc, LPSTR lpchText, int cchText, LPRECT lprc, UINT format) {
53+
CUSTOM_SYSTEM_FONT;
54+
return chain_DrawTextU(hdc, lpchText, cchText, lprc, format);
55+
}
56+
57+
int WINAPI textdisp_DrawTextExW(HDC hdc, LPWSTR lpchText, int cchText, LPRECT lprc, UINT format, LPDRAWTEXTPARAMS lpdtp) {
58+
CUSTOM_SYSTEM_FONT;
59+
return chain_DrawTextExW(hdc, lpchText, cchText, lprc, format, lpdtp);
60+
}
61+
62+
int WINAPI textdisp_DrawTextExA(HDC hdc, LPSTR lpchText, int cchText, LPRECT lprc, UINT format, LPDRAWTEXTPARAMS lpdtp) {
63+
CUSTOM_SYSTEM_FONT;
64+
return chain_DrawTextExU(hdc, lpchText, cchText, lprc, format, lpdtp);
65+
}
66+
67+
BOOL WINAPI textdisp_ExtTextOutW(HDC hdc, int x, int y, UINT options, const RECT * lprect, LPCWSTR lpString, UINT c, const INT* lpDx) {
68+
CUSTOM_SYSTEM_FONT;
69+
return chain_ExtTextOutW(hdc, x, y, options, lprect, lpString, x, lpDx);
70+
}
71+
72+
BOOL WINAPI textdisp_ExtTextOutA(HDC hdc, int x, int y, UINT options, const RECT* lprect, LPCSTR lpString, UINT c, const INT* lpDx) {
73+
CUSTOM_SYSTEM_FONT;
74+
return chain_ExtTextOutU(hdc, x, y, options, lprect, lpString, x, lpDx);
75+
}
76+
77+
BOOL WINAPI textdisp_PolyTextOutW(HDC hdc, const POLYTEXTW* ppt, int nstrings) {
78+
CUSTOM_SYSTEM_FONT;
79+
return chain_PolyTextOutW(hdc, ppt, nstrings);
80+
}
81+
82+
BOOL WINAPI textdisp_PolyTextOutA(HDC hdc, const POLYTEXTA* ppt, int nstrings) {
83+
CUSTOM_SYSTEM_FONT;
84+
return chain_PolyTextOutU(hdc, ppt, nstrings);
85+
}
86+
87+
LONG WINAPI textdisp_TabbedTextOutW(HDC hdc, int x, int y, LPCWSTR lpString, int chCount, int nTabPositions, const INT* lpnTabStopPositions, int nTabOrigin) {
88+
CUSTOM_SYSTEM_FONT;
89+
return chain_TabbedTextOutW(hdc, x, y, lpString, chCount, nTabPositions, lpnTabStopPositions, nTabOrigin);
90+
}
91+
92+
LONG WINAPI textdisp_TabbedTextOutA(HDC hdc, int x, int y, LPCSTR lpString, int chCount, int nTabPositions, const INT* lpnTabStopPositions, int nTabOrigin) {
93+
CUSTOM_SYSTEM_FONT;
94+
return chain_TabbedTextOutU(hdc, x, y, lpString, chCount, nTabPositions, lpnTabStopPositions, nTabOrigin);
95+
}
96+
97+
BOOL WINAPI textdisp_TextOutW(HDC hdc, int x, int y, LPCWSTR lpString, int c) {
98+
CUSTOM_SYSTEM_FONT;
99+
return chain_TextOutW(hdc, x, y, lpString, c);
100+
}
101+
102+
BOOL WINAPI textdisp_TextOutA(HDC hdc, int x, int y, LPCSTR lpString, int c) {
103+
CUSTOM_SYSTEM_FONT;
104+
return chain_TextOutU(hdc, x, y, lpString, c);
105+
}
106+
107+
HGDIOBJ textdisp_SelectObject(HDC hdc, HGDIOBJ h) {
108+
if (!h || h == GetStockObject(SYSTEM_FONT)) {
109+
return chain_SelectObject(hdc, hSystemFont);
110+
}
111+
else {
112+
return chain_SelectObject(hdc, h);
113+
}
114+
}
115+
21116
/// Quality enum
22117
/// ------------
23118
#define UNSPECIFIED_QUALITY 0xFF
@@ -427,6 +522,32 @@ void patch_fonts_load(const patch_t *patch_info)
427522
}
428523
}
429524

525+
void textdisp_load_system_font() {
526+
const char* legacy_fontname;
527+
528+
if (legacy_fontname = json_string_value(strings_get("System"))) {
529+
goto checked_legacy_font_name;
530+
}
531+
if (legacy_fontname = json_object_get_string(runconfig_json_get(), "font")) {
532+
goto checked_legacy_font_name;
533+
}
534+
535+
checked_legacy_font_name:
536+
ENUMLOGFONTEXDVA elfe = {};
537+
#define lf elfe.elfEnumLogfontEx.elfLogFont
538+
539+
GetObjectA(GetStockObject(SYSTEM_FONT), sizeof(lf), &lf);
540+
541+
if (legacy_fontname) {
542+
strncpy(lf.lfFaceName, legacy_fontname, sizeof(lf.lfFaceName));
543+
}
544+
545+
fontrules_apply(&lf);
546+
#undef lf
547+
548+
hSystemFont = chain_CreateFontIndirectExU(&elfe);
549+
}
550+
430551
extern "C" {
431552

432553
TH_EXPORT void textdisp_mod_detour(void)
@@ -436,8 +557,26 @@ TH_EXPORT void textdisp_mod_detour(void)
436557
"CreateFontIndirectExA", textdisp_CreateFontIndirectExA, &chain_CreateFontIndirectExU,
437558
"CreateFontW", textdisp_CreateFontW, &chain_CreateFontW,
438559
"CreateFontIndirectExW", textdisp_CreateFontIndirectExW, &chain_CreateFontIndirectExW,
560+
"SelectObject", textdisp_SelectObject, &chain_SelectObject,
561+
562+
"DrawTextW", textdisp_DrawTextW, & chain_DrawTextW,
563+
"DrawTextExW", textdisp_DrawTextExW, & chain_DrawTextExW,
564+
"ExtTextOutW", textdisp_ExtTextOutW, & chain_ExtTextOutW,
565+
"PolyTextOutW", textdisp_PolyTextOutW, & chain_PolyTextOutW,
566+
"TabbedTextOutW", textdisp_TabbedTextOutW, & chain_TabbedTextOutW,
567+
"TextOutW", textdisp_TextOutW, & chain_TextOutW,
568+
569+
"DrawTextA", textdisp_DrawTextA, & chain_DrawTextU,
570+
"DrawTextExA", textdisp_DrawTextExA, & chain_DrawTextExU,
571+
"ExtTextOutA", textdisp_ExtTextOutA, & chain_ExtTextOutU,
572+
"PolyTextOutA", textdisp_PolyTextOutA, & chain_PolyTextOutU,
573+
"TabbedTextOutA", textdisp_TabbedTextOutA, & chain_TabbedTextOutU,
574+
"TextOutA", textdisp_TextOutA, &chain_TextOutU,
575+
439576
NULL
440577
);
578+
579+
textdisp_load_system_font();
441580
}
442581

443582
TH_EXPORT void textdisp_mod_init(void)

thcrap_tsa/src/layout.cpp

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -575,18 +575,6 @@ BOOL WINAPI fontcache_DeleteObject(HGDIOBJ obj)
575575
return chain_DeleteObject(obj);
576576
}
577577

578-
HGDIOBJ WINAPI layout_SelectObject(
579-
HDC hdc,
580-
HGDIOBJ h
581-
)
582-
{
583-
if(h == GetStockObject(SYSTEM_FONT)) {
584-
return GetCurrentObject(hdc, OBJ_FONT);
585-
} else {
586-
return (HGDIOBJ)chain_SelectObject(hdc, h);
587-
}
588-
}
589-
590578
// Since the games themselves would just multiply the half-size ruby offset
591579
// with 2, we capture the actual full-size result of the ruby offset division.
592580
// This admittedly pretty gross hack allows ruby annotations to also be placed
@@ -698,9 +686,9 @@ size_t TH_STDCALL text_extent_full_for_font(const char *str, HFONT font)
698686
{
699687
// TH08 doesn't create the DC prior to the first binhacked call of this.
700688
auto dc = layout_CreateCompatibleDC(nullptr);
701-
HGDIOBJ prev_font = layout_SelectObject(dc, font);
689+
HGDIOBJ prev_font = chain_SelectObject(dc, font);
702690
size_t ret = text_extent_full(str);
703-
layout_SelectObject(text_dc, prev_font);
691+
chain_SelectObject(text_dc, prev_font);
704692
return ret;
705693
}
706694

@@ -805,14 +793,16 @@ void layout_mod_detour(void)
805793
// continue supporting the legacy "font" runconfig key, as
806794
// well as font changes via hardcoded string translation.
807795
"CreateFontA", fontcache_CreateFontU, &chain_CreateFontU,
796+
"CreateFontW", fontcache_CreateFontW, &chain_CreateFontW,
808797

809798
"DeleteDC", layout_DeleteDC, NULL,
810799
"DeleteObject", fontcache_DeleteObject, &chain_DeleteObject,
811-
"SelectObject", layout_SelectObject, &chain_SelectObject,
812800
"TextOutA", layout_TextOutU, &chain_TextOutU,
813-
"TextOutW", layout_TextOutW, &chain_TextOutU,
801+
"TextOutW", layout_TextOutW, &chain_TextOutW,
814802
NULL
815803
);
804+
805+
chain_SelectObject = (decltype(SelectObject)*)detour_top("gdi32.dll", "SelectObject", (FARPROC)SelectObject);
816806
}
817807

818808
void layout_mod_exit(void)

0 commit comments

Comments
 (0)