Reinitialize libass every time the font is changed in the style editor

libass doesn't free any font data it requests until the ass_renderer is
destroyed, so recreate it every time the font is changed to avoid
holding on to extremely large amounts of data when the user quickly
switches between fonts.

Closes #1320.
This commit is contained in:
Thomas Goyne 2015-02-08 09:13:53 -08:00
parent 9f196adc2e
commit acb9b8adac
3 changed files with 20 additions and 3 deletions

View File

@ -49,6 +49,7 @@ public:
virtual ~SubtitlesProvider() = default; virtual ~SubtitlesProvider() = default;
void LoadSubtitles(AssFile *subs, int time = -1); void LoadSubtitles(AssFile *subs, int time = -1);
virtual void DrawSubtitles(VideoFrame &dst, double time)=0; virtual void DrawSubtitles(VideoFrame &dst, double time)=0;
virtual void Reinitialize() { }
}; };
namespace agi { class BackgroundRunner; } namespace agi { class BackgroundRunner; }

View File

@ -74,6 +74,9 @@ SubtitlesPreview::~SubtitlesPreview() {
} }
void SubtitlesPreview::SetStyle(AssStyle const& new_style) { void SubtitlesPreview::SetStyle(AssStyle const& new_style) {
if (provider && style->font != new_style.font)
provider->Reinitialize();
*style = new_style; *style = new_style;
style->name = "Default"; style->name = "Default";
style->alignment = 5; style->alignment = 5;

View File

@ -108,7 +108,9 @@ class LibassSubtitlesProvider final : public SubtitlesProvider {
if (shared->ready) if (shared->ready)
return shared->renderer; return shared->renderer;
auto block = [&]{ auto block = [&] {
if (shared->ready)
return;
br->Run([=](agi::ProgressSink *ps) { br->Run([=](agi::ProgressSink *ps) {
ps->SetTitle(from_wx(_("Updating font index"))); ps->SetTitle(from_wx(_("Updating font index")));
ps->SetMessage(from_wx(_("This may take several minutes"))); ps->SetMessage(from_wx(_("This may take several minutes")));
@ -136,6 +138,17 @@ public:
} }
void DrawSubtitles(VideoFrame &dst, double time) override; void DrawSubtitles(VideoFrame &dst, double time) override;
void Reinitialize() override {
// No need to reinit if we're not even done with the initial init
if (!shared->ready)
return;
ass_renderer_done(shared->renderer);
shared->renderer = ass_renderer_init(library);
ass_set_font_scale(shared->renderer, 1.);
ass_set_fonts(shared->renderer, nullptr, "Sans", 1, CONFIG_PATH, true);
}
}; };
LibassSubtitlesProvider::LibassSubtitlesProvider(agi::BackgroundRunner *br) LibassSubtitlesProvider::LibassSubtitlesProvider(agi::BackgroundRunner *br)
@ -143,7 +156,7 @@ LibassSubtitlesProvider::LibassSubtitlesProvider(agi::BackgroundRunner *br)
, shared(std::make_shared<cache_thread_shared>()) , shared(std::make_shared<cache_thread_shared>())
{ {
auto state = shared; auto state = shared;
cache_queue->Async([state]{ cache_queue->Async([state] {
auto ass_renderer = ass_renderer_init(library); auto ass_renderer = ass_renderer_init(library);
if (ass_renderer) { if (ass_renderer) {
ass_set_font_scale(ass_renderer, 1.); ass_set_font_scale(ass_renderer, 1.);
@ -215,7 +228,7 @@ void CacheFonts() {
ass_set_message_cb(library, msg_callback, nullptr); ass_set_message_cb(library, msg_callback, nullptr);
// Initialize a renderer to force fontconfig to update its cache // Initialize a renderer to force fontconfig to update its cache
cache_queue->Async([]{ cache_queue->Async([] {
auto ass_renderer = ass_renderer_init(library); auto ass_renderer = ass_renderer_init(library);
ass_set_fonts(ass_renderer, nullptr, "Sans", 1, CONFIG_PATH, true); ass_set_fonts(ass_renderer, nullptr, "Sans", 1, CONFIG_PATH, true);
ass_renderer_done(ass_renderer); ass_renderer_done(ass_renderer);