diff --git a/LunaHook/engines/python/python.cpp b/LunaHook/engines/python/python.cpp index 27f72dc..3959b4d 100644 --- a/LunaHook/engines/python/python.cpp +++ b/LunaHook/engines/python/python.cpp @@ -4,6 +4,12 @@ #include"stackoffset.hpp" #include"types.h" #include"defs.h" +#include +#include + +extern "C" __declspec(dllexport) const wchar_t* internal_renpy_call_host(const wchar_t* text,int split){ + return text; +} namespace{ typedef enum {PyGILState_LOCKED, PyGILState_UNLOCKED} @@ -46,18 +52,71 @@ void hook_internal_renpy_call_host(){ NewHook(hp_internal, "internal_renpy_call_host"); PyRunScript(LoadResData(L"renpy_hook_text",L"PYSOURCE").c_str()); } + +typedef BOOL(WINAPI* PGFRI)(LPCWSTR, LPDWORD, LPVOID, DWORD); +#define QFR_LOGFONT (2) +#define LOADFONTTHREADNUM 4 +std::unordered_map loadfontfiles() { + + PWSTR localAppDataPath; + HRESULT result = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &localAppDataPath); + std::unordered_map fnts; -void patchfontfunction(){ - //由于不知道怎么从字体名映射到ttc/ttf文件名,所以暂时写死arial/msyh - if(wcslen(embedsharedmem->fontFamily)==0)return; - PyRunScript(LoadResData(L"renpy_hook_font",L"PYSOURCE").c_str()); + std::vector< std::wstring>collectfile; + for (auto fontdir : { std::wstring(LR"(C:\Windows\Fonts)"),std::wstring(localAppDataPath) + LR"(\Microsoft\Windows\Fonts)" }) { + + for (auto entry : std::filesystem::directory_iterator(fontdir)) { + collectfile.emplace_back(entry.path()); + } + } + std::vectorts; + std::vector fntss(LOADFONTTHREADNUM); + auto singletask = [&](int i) { + HINSTANCE hGdi32 = GetModuleHandleA("gdi32.dll"); + if (hGdi32 == 0)return; + PGFRI GetFontResourceInfo = (PGFRI)GetProcAddress(hGdi32, "GetFontResourceInfoW"); + for (auto j = i; j < collectfile.size(); j += LOADFONTTHREADNUM) { + auto fontfile = collectfile[j]; + DWORD dwFontsLoaded = AddFontResourceExW(fontfile.c_str(), FR_PRIVATE, 0); + if (dwFontsLoaded == 0) { + continue; + } + + auto lpLogfonts = std::make_unique(dwFontsLoaded); + DWORD cbBuffer = dwFontsLoaded * sizeof(LOGFONTW); + if (!GetFontResourceInfo(fontfile.c_str(), &cbBuffer, lpLogfonts.get(), QFR_LOGFONT)) { + RemoveFontResourceExW(fontfile.c_str(), FR_PRIVATE, 0); + continue; + } + for (int k = 0; k < dwFontsLoaded; k++) + fntss[i].insert(std::make_pair(lpLogfonts[k].lfFaceName, fontfile)); + RemoveFontResourceExW(fontfile.c_str(), FR_PRIVATE, 0); + + } + }; + for (int i = 0; i < LOADFONTTHREADNUM; i++) { + ts.emplace_back(std::thread(singletask,i)); + } + for (int i = 0; i < LOADFONTTHREADNUM; i++) + ts[i].join(); + for (int i = 0; i < LOADFONTTHREADNUM; i++) { + for (auto p : fntss[i]) + fnts.insert(std::move(p)); + } + return fnts; } } -const wchar_t* internal_renpy_call_host(const wchar_t* text,int split){ - return text; +extern "C" __declspec(dllexport) const wchar_t* internal_renpy_get_font(){ + if(wcslen(embedsharedmem->fontFamily)==0)return NULL; + static auto fontname2fontfile=std::move(loadfontfiles()); + if(fontname2fontfile.find(embedsharedmem->fontFamily)==fontname2fontfile.end())return NULL; + else return fontname2fontfile.at(embedsharedmem->fontFamily).c_str(); + } void hookrenpy(HMODULE module){ LoadPyRun(module); - patch_fun=patchfontfunction; + patch_fun=[](){ + PyRunScript(LoadResData(L"renpy_hook_font",L"PYSOURCE").c_str()); + }; hook_internal_renpy_call_host(); } \ No newline at end of file diff --git a/LunaHook/engines/python/python.h b/LunaHook/engines/python/python.h index 4ef4d61..3eb89b3 100644 --- a/LunaHook/engines/python/python.h +++ b/LunaHook/engines/python/python.h @@ -4,7 +4,4 @@ bool InsertRenpy3Hook(); bool InsertRenpyHook(); -extern "C" __declspec(dllexport) const wchar_t* internal_renpy_call_host(const wchar_t* text,int split); - - void hookrenpy(HMODULE module); diff --git a/LunaHook/resource/renpy_hook_font.py b/LunaHook/resource/renpy_hook_font.py index 4b3c1ad..6135cc9 100644 --- a/LunaHook/resource/renpy_hook_font.py +++ b/LunaHook/resource/renpy_hook_font.py @@ -1,16 +1,23 @@ +def callLunaHostFont(): + try: + import ctypes + try: + internal_renpy_get_font=ctypes.CDLL('LunaHook64').internal_renpy_get_font + except: + internal_renpy_get_font=ctypes.CDLL('LunaHook32').internal_renpy_get_font + internal_renpy_get_font.restype=ctypes.c_wchar_p + return internal_renpy_get_font() + except: + return None try: import os import renpy def hook_renpy_text_font_get_font_init(original): def new_init(*args, **kwargs): #ctypes.windll.user32.MessageBoxW(None, str(kwargs), str(args), 0) - if os.path.exists(r'C:\Windows\Fonts\msyh.ttc'): - font='msyh.ttc' - elif os.path.exists(r'C:\Windows\Fonts\arial.ttf'): - font='arial.ttf' - else: - font=None - if font: + font=callLunaHostFont() + if font and font!='' and os.path.exists(font): + font=font.replace('\\','/')#不知道为什么,用\会报错,但之前写死C:\Windows\Fonts\msyh.ttc时就没事 args=(font,)+args[1:] if 'fn' in kwargs: kwargs['fn']=font diff --git a/README.md b/README.md index 0e4a1b6..827fc21 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ +[LunaTranslator](https://github.com/HIllya51/LunaTranslator)核心文本提取器模块 + +也可以单独使用,兼容Textractor插件 + Core Text Hook Module For [LunaTranslator](https://github.com/HIllya51/LunaTranslator) -Can also be used separately - -Compatible with Textractor plugin \ No newline at end of file +Can also be used separately and compatible with Textractor plugins \ No newline at end of file