Always load initialize fontconfig on a worker thread so that installing a font then opening a new video does not block the GUI thread

Originally committed to SVN as r4818.
This commit is contained in:
Thomas Goyne 2010-10-17 02:36:28 +00:00
parent 7ce2e8f389
commit 49a57729ef
1 changed files with 56 additions and 44 deletions

View File

@ -63,7 +63,7 @@
/// @brief Handle libass messages /// @brief Handle libass messages
/// ///
static void msg_callback(int level, const char *fmt, va_list args, void *data) { static void msg_callback(int level, const char *fmt, va_list args, void *) {
if (level >= 7) return; if (level >= 7) return;
char buf[1024]; char buf[1024];
#ifdef _WIN32 #ifdef _WIN32
@ -78,44 +78,76 @@ static void msg_callback(int level, const char *fmt, va_list args, void *data) {
LOG_D("subtitle/provider/libass") << buf; LOG_D("subtitle/provider/libass") << buf;
} }
static void load_config(ASS_Renderer *ass_renderer) { class FontConfigCacheThread : public wxThread {
ASS_Library *ass_library;
ASS_Renderer *ass_renderer;
FontConfigCacheThread** thisPtr;
ExitCode Entry() {
#ifdef __APPLE__ #ifdef __APPLE__
char config_path[MAXPATHLEN]; char config_path[MAXPATHLEN];
char *config_dir; char *config_dir;
config_dir = agi::util::OSX_GetBundleResourcesDirectory(); config_dir = agi::util::OSX_GetBundleResourcesDirectory();
snprintf(config_path, MAXPATHLEN, "%s/etc/fonts/fonts.conf", config_dir); snprintf(config_path, MAXPATHLEN, "%s/etc/fonts/fonts.conf", config_dir);
free(config_dir); free(config_dir);
#else #else
const char *config_path = NULL; const char *config_path = NULL;
#endif #endif
ass_set_fonts(ass_renderer, NULL, "Sans", 1, config_path, true); if (ass_library) ass_renderer = ass_renderer_init(ass_library);
ass_set_fonts(ass_renderer, NULL, "Sans", 1, config_path, true);
if (ass_library) ass_renderer_done(ass_renderer);
*thisPtr = NULL;
return EXIT_SUCCESS;
}
public:
FontConfigCacheThread(ASS_Library *ass_library, FontConfigCacheThread **thisPtr)
: ass_library(ass_library)
, ass_renderer(NULL)
, thisPtr(thisPtr)
{
*thisPtr = this;
Create();
Run();
}
FontConfigCacheThread(ASS_Renderer *ass_renderer, FontConfigCacheThread **thisPtr)
: ass_library(NULL)
, ass_renderer(ass_renderer)
, thisPtr(thisPtr)
{
*thisPtr = this;
Create();
Run();
}
};
static void wait_for_cache_thread(FontConfigCacheThread const * const & cache_worker) {
if (!cache_worker) return;
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();
} }
/// @brief Constructor /// @brief Constructor
/// ///
LibassSubtitlesProvider::LibassSubtitlesProvider(std::string) { LibassSubtitlesProvider::LibassSubtitlesProvider(std::string) {
if (cache_worker) { wait_for_cache_thread(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 // Initialize renderer
ass_track = NULL; ass_track = NULL;
ass_renderer = ass_renderer_init(ass_library); ass_renderer = ass_renderer_init(ass_library);
if (!ass_renderer) throw _T("ass_renderer_init failed"); if (!ass_renderer) throw _T("ass_renderer_init failed");
ass_set_font_scale(ass_renderer, 1.); ass_set_font_scale(ass_renderer, 1.);
load_config(ass_renderer); new FontConfigCacheThread(ass_renderer, &cache_worker);
wait_for_cache_thread(cache_worker);
} }
/// @brief Destructor /// @brief Destructor
@ -205,29 +237,9 @@ 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() { void LibassSubtitlesProvider::CacheFonts() {
ass_library = ass_library_init(); ass_library = ass_library_init();
ass_set_message_cb(ass_library, msg_callback, NULL);
new FontConfigCacheThread(ass_library, &cache_worker); new FontConfigCacheThread(ass_library, &cache_worker);
} }