summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrigori Goronzy <greg@chown.ath.cx>2011-08-19 05:03:45 +0200
committerGrigori Goronzy <greg@chown.ath.cx>2015-07-10 10:42:40 +0200
commitb39fc626727165bd3f82900e293136d9b18deb10 (patch)
treeaa8967043cfa58df20d117bbe198144574a23f1a
parenteb1f95a6d82832586e1fd50f98b14f508e7ff4be (diff)
downloadlibass-b39fc626727165bd3f82900e293136d9b18deb10.tar.bz2
libass-b39fc626727165bd3f82900e293136d9b18deb10.tar.xz
Free a provider's fonts when it is freed
When a provider is freed, iterate the font database, free all fonts that belong to that provider and compact the database afterwards.
-rw-r--r--libass/ass_fontselect.c90
1 files changed, 65 insertions, 25 deletions
diff --git a/libass/ass_fontselect.c b/libass/ass_fontselect.c
index 97fa2c4..e94fc9e 100644
--- a/libass/ass_fontselect.c
+++ b/libass/ass_fontselect.c
@@ -225,13 +225,66 @@ ass_font_provider_add_font(ASS_FontProvider *provider,
return 1;
}
+/**
+ * \brief Clean up font database. Deletes all fonts that have an invalid
+ * font provider (NULL).
+ * \param selector the font selector
+ */
+static void ass_fontselect_cleanup(ASS_FontSelector *selector)
+{
+ int i, w;
+
+ for (i = 0, w = 0; i < selector->n_font; i++) {
+ ASS_FontInfo *info = selector->font_infos + i;
+
+ // update write pointer
+ if (info->provider != NULL) {
+ // rewrite, if needed
+ if (w != i)
+ memcpy(selector->font_infos + w, selector->font_infos + i,
+ sizeof(ASS_FontInfo));
+ w++;
+ }
+
+ }
+
+ selector->n_font = w;
+}
+
void ass_font_provider_free(ASS_FontProvider *provider)
{
- // TODO: this should probably remove all fonts that belong
- // to this provider from the list
+ int i, j;
+ ASS_FontSelector *selector = provider->parent;
+
+ // free all fonts and mark their entries
+ for (i = 0; i < selector->n_font; i++) {
+ ASS_FontInfo *info = selector->font_infos + i;
+
+ if (info->provider == provider) {
+ for (j = 0; j < info->n_fullname; j++)
+ free(info->fullnames[j]);
+
+ free(info->fullnames);
+ free(info->family);
+
+ if (info->path)
+ free(info->path);
- if (provider && provider->funcs.destroy_provider)
+ if (info->provider->funcs.destroy_font)
+ info->provider->funcs.destroy_font(info->priv);
+
+ info->provider = NULL;
+ }
+
+ }
+
+ // delete marked entries
+ ass_fontselect_cleanup(selector);
+
+ // free private data of the provider
+ if (provider->funcs.destroy_provider)
provider->funcs.destroy_provider(provider->priv);
+
free(provider);
}
@@ -667,30 +720,17 @@ ass_fontselect_init(ASS_Library *library,
*/
void ass_fontselect_free(ASS_FontSelector *priv)
{
- int i;
+ if (priv->default_provider)
+ ass_font_provider_free(priv->default_provider);
+ ass_font_provider_free(priv->embedded_provider);
- if (priv) {
- for (i = 0; i < priv->n_font; i++) {
- ASS_FontInfo *info = priv->font_infos + i;
- int j;
- for (j = 0; j < info->n_fullname; j++)
- free(info->fullnames[j]);
- free(info->fullnames);
- free(info->family);
- if (info->path)
- free(info->path);
- if (info->provider && info->provider->funcs.destroy_font)
- info->provider->funcs.destroy_font(info->priv);
- }
- free(priv->font_infos);
- free(priv->path_default);
- free(priv->family_default);
- }
+ // XXX: not quite sure, maybe we should track all registered
+ // providers and free them right here. or should that be the
+ // responsibility of the library user?
- // TODO: we should track all child font providers and
- // free them here
- ass_font_provider_free(priv->default_provider);
- ass_font_provider_free(priv->embedded_provider);
+ free(priv->font_infos);
+ free(priv->path_default);
+ free(priv->family_default);
free(priv);
}