From 9bffdfeda06078320ea5e5445cb9804e50399db2 Mon Sep 17 00:00:00 2001 From: copyliu <1076640+copyliu@users.noreply.github.com> Date: Mon, 4 May 2020 22:38:09 +0800 Subject: [PATCH] Get subtitles can load fonts from fonts_dir (#6) --- .../libass-unicode-fontdir-path-win.patch | 109 ++++++++++++++++++ Dependencies/pkgs/libass.pkgbuild | 3 + Engine/Core/ONScripter.hpp | 1 + Engine/Core/Text.cpp | 6 + Engine/Media/SubtitleDriver.cpp | 2 +- 5 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 Dependencies/patches/libass-unicode-fontdir-path-win.patch diff --git a/Dependencies/patches/libass-unicode-fontdir-path-win.patch b/Dependencies/patches/libass-unicode-fontdir-path-win.patch new file mode 100644 index 00000000..2fbe4ec1 --- /dev/null +++ b/Dependencies/patches/libass-unicode-fontdir-path-win.patch @@ -0,0 +1,109 @@ +--- a/libass/ass_fontselect.c 2017-10-27 01:34:18.000000000 +0800 ++++ b/libass/ass_fontselect.c 2020-05-04 19:50:58.926098100 +0800 +@@ -47,6 +47,9 @@ + #include "ass_font.h" + #include "ass_string.h" + ++#include ++#include ++ + #define ABS(x) ((x) < 0 ? -(x) : (x)) + #define MAX_FULLNAME 100 + +@@ -163,26 +166,78 @@ static ASS_FontProviderFuncs ft_funcs = + + static void load_fonts_from_dir(ASS_Library *library, const char *dir) + { +- DIR *d = opendir(dir); +- if (!d) ++ wchar_t wpath[PATH_MAX]; ++ if (!MultiByteToWideChar(CP_UTF8, 0, dir, -1, wpath, PATH_MAX)) ++ { ++ ass_msg(library, MSGL_WARN, ++ "Error obtaining unicode path for font dir: '%s' (code: %d)", dir, GetLastError()); + return; +- while (1) { +- struct dirent *entry = readdir(d); +- if (!entry) +- break; +- if (entry->d_name[0] == '.') +- continue; +- char fullname[4096]; +- snprintf(fullname, sizeof(fullname), "%s/%s", dir, entry->d_name); +- size_t bufsize = 0; +- ass_msg(library, MSGL_INFO, "Loading font file '%s'", fullname); +- void *data = read_file(library, fullname, &bufsize); +- if (data) { +- ass_add_font(library, entry->d_name, data, bufsize); +- free(data); +- } + } +- closedir(d); ++ wchar_t wpath_wc[PATH_MAX]; ++ wcscpy(wpath_wc, wpath); ++ wcscat_s(wpath_wc, PATH_MAX, L"\\*.*"); ++ HANDLE hFind; ++ WIN32_FIND_DATAW FindFileData; ++ if ((hFind = FindFirstFileW(wpath_wc, &FindFileData)) != INVALID_HANDLE_VALUE) { ++ do { ++ if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { ++ HANDLE hFile; ++ wchar_t fullName[PATH_MAX]; ++ wcscpy(fullName, wpath); ++ wcscat_s(fullName, PATH_MAX, L"\\"); ++ wcscat_s(fullName, PATH_MAX, FindFileData.cFileName); ++ hFile = CreateFileW(fullName, ++ GENERIC_READ, ++ FILE_SHARE_READ, ++ NULL, ++ OPEN_EXISTING, ++ FILE_ATTRIBUTE_NORMAL, ++ NULL); ++ if (hFile == INVALID_HANDLE_VALUE) { ++ char tmp[PATH_MAX]; ++ WideCharToMultiByte(CP_UTF8, 0, &fullName, -1, tmp, PATH_MAX, NULL, NULL); ++ ass_msg(library, MSGL_WARN, ++ "Error opening font file: '%s' (code: %d)", tmp, GetLastError()); ++ continue; ++ } ++ DWORD fileSize; ++ char fname[PATH_MAX]; ++ WideCharToMultiByte(CP_UTF8, 0, &FindFileData.cFileName, -1, fname, PATH_MAX, NULL, NULL); ++ ass_msg(library, MSGL_INFO, "Loading font file '%s'", fname); ++ fileSize = GetFileSize(hFile, NULL); ++ if (fileSize == INVALID_FILE_SIZE) { ++ char tmp[PATH_MAX]; ++ WideCharToMultiByte(CP_UTF8, 0, &fullName, -1, tmp, PATH_MAX, NULL, NULL); ++ ass_msg(library, MSGL_WARN, ++ "Error opening font file: '%s' (code: %d)", tmp, GetLastError()); ++ CloseHandle(hFile); ++ continue; ++ } ++ char *data = malloc(fileSize + 1); ++ if (data == NULL) { ++ char tmp[PATH_MAX]; ++ WideCharToMultiByte(CP_UTF8, 0, &fullName, -1, tmp, PATH_MAX, NULL, NULL); ++ ass_msg(library, MSGL_WARN, ++ "Error reading font file: '%s', can not allocate memory for reading, is your system running out of memory?", tmp); ++ CloseHandle(hFile); ++ continue; ++ } ++ DWORD dwBytesRead = 0; ++ if (!ReadFile(hFile, data, fileSize, &dwBytesRead, NULL)) { ++ char tmp[PATH_MAX]; ++ WideCharToMultiByte(CP_UTF8, 0, &fullName, -1, tmp, PATH_MAX, NULL, NULL); ++ ass_msg(library, MSGL_WARN, ++ "Error reading font file: '%s' (code: %d)", tmp, GetLastError()); ++ CloseHandle(hFile); ++ continue; ++ } ++ CloseHandle(hFile); ++ ass_add_font(library, fname, data, dwBytesRead); ++ free(data); ++ } ++ } while (FindNextFileW(hFind, &FindFileData)); ++ FindClose(hFind); ++ } + } + + /** diff --git a/Dependencies/pkgs/libass.pkgbuild b/Dependencies/pkgs/libass.pkgbuild index 7ba92ad7..0cb98d16 100644 --- a/Dependencies/pkgs/libass.pkgbuild +++ b/Dependencies/pkgs/libass.pkgbuild @@ -7,12 +7,14 @@ sources=( "https://raw.githubusercontent.com/umineko-project/onscripter-deps/master/archives/$pkgname-$pkgver.tar.xz" 'libass-ignore-iconv.patch' 'libass-unicode-font-path-win.patch' + 'libass-unicode-fontdir-path-win.patch' ) hashes=( '881f2382af48aead75b7a0e02e65d88c5ebd369fe46bc77d9270a94aa8fd38a2' '2482308db0690ec34248cc12d5a7ca3d9e9c7cb8db4273e61a205637d7dfc6fd' '71e38cb4c8ec7e4bc62af64f0c5a6576e7cf2fc750ca43bac725198f2c214fa0' + '45988f43b494f4e512b5a3d0b23906edc8ff2a8a8d0b6717656080c5be7c5cbf' ) configopts=( @@ -67,6 +69,7 @@ prebuild() { # This patch enforces utf-8 path support for ass_set_fonts on Windows. if [ "$(getTarget)" == "win32" ]; then apply_patch "${sources[2]}" + apply_patch "${sources[3]}" fi } diff --git a/Engine/Core/ONScripter.hpp b/Engine/Core/ONScripter.hpp index acf98669..07be88ae 100644 --- a/Engine/Core/ONScripter.hpp +++ b/Engine/Core/ONScripter.hpp @@ -1178,6 +1178,7 @@ class ONScripter : public ScriptParser { int getCharacterPostDisplayDelay(char16_t codepoint, int speed); int unpackInlineCall(const char *cmd, int &val); const char *getFontPath(int i, bool fallback = true); + const char *getSubtitleFontDir(); private: void enterTextDisplayMode(); diff --git a/Engine/Core/Text.cpp b/Engine/Core/Text.cpp index 3529ef41..a7cf81c3 100644 --- a/Engine/Core/Text.cpp +++ b/Engine/Core/Text.cpp @@ -1008,6 +1008,12 @@ const char *ONScripter::getFontPath(int i, bool /*fallback*/) { return path; } +const char *ONScripter::getSubtitleFontDir() { + char *path = static_cast(malloc(PATH_MAX)); + std::snprintf(path, PATH_MAX, "%s%c%s", fonts.fontdir, DELIMITER, "subfonts"); + return path; +} + void ONScripter::addTextWindowClip(DirtyRect &rect) { if (wndCtrl.usingDynamicTextWindow) { // This represents the whole text window, when it is current and active diff --git a/Engine/Media/SubtitleDriver.cpp b/Engine/Media/SubtitleDriver.cpp index 52cb99f9..c4bd995a 100644 --- a/Engine/Media/SubtitleDriver.cpp +++ b/Engine/Media/SubtitleDriver.cpp @@ -225,7 +225,7 @@ bool SubtitleDriver::init(int width, int height, const char *ass_sub_file, BaseR ass_library = nullptr; sendToLog(LogLevel::Error, "ass_renderer_init failed!\n"); } else { - //ass_set_fonts_dir(ass_library,nullptr); + ass_set_fonts_dir(ass_library, ons.getSubtitleFontDir()); ass_set_frame_size(ass_renderer, width, height); ass_set_fonts(ass_renderer, ons.getFontPath(currentFontID, true), "Sans", ASS_FONTPROVIDER_NONE, nullptr, 0); bool subs_ok{false};