From 7e72a9e0cf8afdb7ee330dc54d9c283a0b81ca30 Mon Sep 17 00:00:00 2001 From: Thomas Goyne Date: Wed, 1 Sep 2010 06:50:35 +0000 Subject: [PATCH] Add background fontconfig cache updating When the libass provider is enabled, initialize fontconfig on program startup rather than waiting for the user to open a video. If the user tries to open a video while the cache is still being updated, display a "progress" dialog, Updates #1115. Originally committed to SVN as r4768. --- aegisub/src/dialog_progress.cpp | 4 +- aegisub/src/dialog_progress.h | 1 + aegisub/src/subtitles_provider.cpp | 2 + aegisub/src/subtitles_provider_libass.cpp | 86 +++++++++++++++-------- aegisub/src/subtitles_provider_libass.h | 5 ++ 5 files changed, 69 insertions(+), 29 deletions(-) diff --git a/aegisub/src/dialog_progress.cpp b/aegisub/src/dialog_progress.cpp index 61c6c1dfe..21524dbdf 100644 --- a/aegisub/src/dialog_progress.cpp +++ b/aegisub/src/dialog_progress.cpp @@ -211,4 +211,6 @@ void DialogProgressThread::Close() { dialog->GetEventHandler()->ProcessEvent(event); } - +void DialogProgress::Pulse() { + gauge->Pulse(); +} diff --git a/aegisub/src/dialog_progress.h b/aegisub/src/dialog_progress.h index 08b05dc3e..d9d878192 100644 --- a/aegisub/src/dialog_progress.h +++ b/aegisub/src/dialog_progress.h @@ -81,6 +81,7 @@ public: void SetProgress(int cur,int max); void SetText(wxString text); void Run(); + void Pulse(); DECLARE_EVENT_TABLE() }; diff --git a/aegisub/src/subtitles_provider.cpp b/aegisub/src/subtitles_provider.cpp index 9e5564e3f..5ccc5d141 100644 --- a/aegisub/src/subtitles_provider.cpp +++ b/aegisub/src/subtitles_provider.cpp @@ -62,6 +62,7 @@ SubtitlesProvider* SubtitlesProviderFactory::GetProvider() { SubtitlesProvider *provider = Create(list[i], subType); if (provider) return provider; } + catch (agi::UserCancelException const&) { throw; } catch (wxString err) { error += list[i] + _T(" factory: ") + err + _T("\n"); } catch (const wxChar *err) { error += list[i] + _T(" factory: ") + wxString(err) + _T("\n"); } catch (...) { error += list[i] + _T(" factory: Unknown error\n"); } @@ -79,6 +80,7 @@ void SubtitlesProviderFactory::RegisterProviders() { #endif #ifdef WITH_LIBASS Register("libass"); + LibassSubtitlesProvider::CacheFonts(); #endif } diff --git a/aegisub/src/subtitles_provider_libass.cpp b/aegisub/src/subtitles_provider_libass.cpp index 62b50b3de..3d0b7da33 100644 --- a/aegisub/src/subtitles_provider_libass.cpp +++ b/aegisub/src/subtitles_provider_libass.cpp @@ -40,6 +40,7 @@ #ifndef AGI_PRE #include +#include #endif #ifdef __APPLE__ @@ -50,6 +51,9 @@ #include #include "ass_file.h" +#include "dialog_progress.h" +#include "frame_main.h" +#include "main.h" #include "standard_paths.h" #include "subtitles_provider_libass.h" #include "utils.h" @@ -73,33 +77,7 @@ static void msg_callback(int level, const char *fmt, va_list args, void *data) { LOG_D("subtitle/provider/libass") << buf; } -/// @brief Constructor -/// -LibassSubtitlesProvider::LibassSubtitlesProvider(std::string) { - // Initialize library - static bool first = true; - if (first) { - ass_library = ass_library_init(); - if (!ass_library) throw _T("ass_library_init failed"); - - wxString fonts_dir = StandardPaths::DecodePath(_T("?user/libass_fonts/")); - if (!wxDirExists(fonts_dir)) - // It's only one level below the user dir, and we assume the user dir already exists at this point. - wxMkdir(fonts_dir); - - ass_set_fonts_dir(ass_library, fonts_dir.mb_str(wxConvFile)); - ass_set_extract_fonts(ass_library, 0); - ass_set_style_overrides(ass_library, NULL); - ass_set_message_cb(ass_library, msg_callback, this); - first = false; - } - - // Initialize renderer - ass_track = NULL; - ass_renderer = ass_renderer_init(ass_library); - if (!ass_renderer) throw _T("ass_renderer_init failed"); - ass_set_font_scale(ass_renderer, 1.); - +static void load_config(ASS_Renderer *ass_renderer) { #ifdef __APPLE__ char config_path[MAXPATHLEN]; char *config_dir; @@ -111,7 +89,32 @@ LibassSubtitlesProvider::LibassSubtitlesProvider(std::string) { const char *config_path = NULL; #endif - ass_set_fonts(ass_renderer, NULL, "Sans", 1, config_path, 1); + ass_set_fonts(ass_renderer, NULL, "Sans", 1, config_path, true); +} + +/// @brief Constructor +/// +LibassSubtitlesProvider::LibassSubtitlesProvider(std::string) { + if (cache_worker) { + bool canceled; + DialogProgress *progress = new DialogProgress(AegisubApp::Get()->frame, L"", &canceled, L"Caching fonts", 0, 1); + progress->Show(); + while (cache_worker) { + if (canceled) throw agi::UserCancelException("Font caching cancelled"); + progress->Pulse(); + wxYield(); + wxMilliSleep(100); + } + progress->Destroy(); + } + ass_set_message_cb(ass_library, msg_callback, this); + + // Initialize renderer + ass_track = NULL; + ass_renderer = ass_renderer_init(ass_library); + if (!ass_renderer) throw _T("ass_renderer_init failed"); + ass_set_font_scale(ass_renderer, 1.); + load_config(ass_renderer); } /// @brief Destructor @@ -201,7 +204,34 @@ void LibassSubtitlesProvider::DrawSubtitles(AegiVideoFrame &frame,double time) { } } +class FontConfigCacheThread : public wxThread { + ASS_Library *ass_library; + FontConfigCacheThread** thisPtr; + ExitCode Entry() { + ASS_Renderer *ass_renderer = ass_renderer_init(ass_library); + load_config(ass_renderer); + ass_renderer_done(ass_renderer); + *thisPtr = NULL; + return EXIT_SUCCESS; + } +public: + FontConfigCacheThread(ASS_Library *ass_library, FontConfigCacheThread **thisPtr) + : ass_library(ass_library) + , thisPtr(thisPtr) + { + *thisPtr = this; + Create(); + Run(); + } +}; + +void LibassSubtitlesProvider::CacheFonts() { + ass_library = ass_library_init(); + new FontConfigCacheThread(ass_library, &cache_worker); +} + /// DOCME ASS_Library* LibassSubtitlesProvider::ass_library; +FontConfigCacheThread* LibassSubtitlesProvider::cache_worker = NULL; #endif // WITH_LIBASS diff --git a/aegisub/src/subtitles_provider_libass.h b/aegisub/src/subtitles_provider_libass.h index fb89f91a1..d093bea59 100644 --- a/aegisub/src/subtitles_provider_libass.h +++ b/aegisub/src/subtitles_provider_libass.h @@ -45,6 +45,7 @@ extern "C" { #include "../libass/ass.h" } +class FontConfigCacheThread; /// DOCME /// @class LibassSubtitlesProvider @@ -61,11 +62,15 @@ class LibassSubtitlesProvider : public SubtitlesProvider { /// DOCME ASS_Track* ass_track; + static FontConfigCacheThread *cache_worker; + public: LibassSubtitlesProvider(std::string); ~LibassSubtitlesProvider(); void LoadSubtitles(AssFile *subs); void DrawSubtitles(AegiVideoFrame &dst,double time); + + static void CacheFonts(); }; #endif