Issue #14139: wait for fonts to be loaded before loading files.
This was happening when trying to load a file before fonts were fully loaded, which may happen when loading while starting GIMP (either from CLI, or from a file browser, etc.), or simply just after start for people with a lot of fonts, whose font loading may take a long time as background task. Note that I didn't manage to reproduce properly because from reports, it seems like the problem appears where some fonts may be only partly loaded so gimp_font_get_hash() fails to load the font and get a hash. I never managed to trigger such a case and no reporters answered my call for testing of debug builds. As a consequence, I'll just assume that simply waiting for all fonts to be loaded before starting to load images would work out. Note that the crash was not happening when text layers were using the older syntax (pre-XCF 19) of text layer data, since it was not storing any font hash, which means that we were not trying to compare hashes. It would also not crash if fonts were not fully loaded yet, but we didn't have any weird intermediate state where fonts appeared in the list yet their file were not hashable (cf. what I failed to reproduce, as explained in previous paragraph). But both these cases were not ideal either anyway because then we could load the XCF apparently OK… except that the correct fonts would not be associated to the related text layers (hence as soon as you start to edit said texts, the rendering would break). So we should wait for fonts to be loaded, and that was a bug even when you can't reproduce the crash. When starting GIMP without loading an image, or simply when fonts are loaded quickly enough, it won't make any difference. So it should not make startup any slower for most common use cases and installations.
This commit is contained in:
parent
56a17c73eb
commit
bf6fcac0a9
6 changed files with 102 additions and 1 deletions
|
|
@ -32,12 +32,14 @@
|
|||
#include "gimp-gradients.h"
|
||||
#include "gimp-memsize.h"
|
||||
#include "gimp-palettes.h"
|
||||
#include "gimp-utils.h"
|
||||
#include "gimpcontainer.h"
|
||||
#include "gimpbrush-load.h"
|
||||
#include "gimpbrush.h"
|
||||
#include "gimpbrushclipboard.h"
|
||||
#include "gimpbrushgenerated-load.h"
|
||||
#include "gimpbrushpipe-load.h"
|
||||
#include "gimpcurve.h"
|
||||
#include "gimpdataloaderfactory.h"
|
||||
#include "gimpdynamics.h"
|
||||
#include "gimpdynamics-load.h"
|
||||
|
|
@ -300,6 +302,52 @@ gimp_data_factories_exit (Gimp *gimp)
|
|||
g_clear_object (&gimp->tag_cache);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gimp_data_factories_wait (Gimp *gimp)
|
||||
{
|
||||
GList *data_types;
|
||||
GList *excluded;
|
||||
gboolean loaded = TRUE;
|
||||
|
||||
/* TODO: when bumping GLib >= 2.80, use GTYPE_TO_POINTER instead. */
|
||||
#define GIMPTYPE_TO_POINTER(t) ((gpointer) (guintptr) (t))
|
||||
/* Curves are the only data type without a factory. */
|
||||
excluded = g_list_prepend (NULL, GIMPTYPE_TO_POINTER (GIMP_TYPE_CURVE));
|
||||
#undef GIMPTYPE_TO_POINTER
|
||||
|
||||
data_types = gimp_get_type_children (GIMP_TYPE_DATA, NULL, excluded);
|
||||
g_list_free (excluded);
|
||||
|
||||
/* TODO: when bumping GLib >= 2.80, use GPOINTER_TO_TYPE instead. */
|
||||
#define GIMPPOINTER_TO_TYPE(p) ((GType) (guintptr) (p))
|
||||
|
||||
for (GList *iter = data_types; iter; iter = iter->next)
|
||||
{
|
||||
GimpDataFactory *factory;
|
||||
|
||||
factory = gimp_get_data_factory (gimp, GIMPPOINTER_TO_TYPE (iter->data));
|
||||
|
||||
if (factory)
|
||||
{
|
||||
GimpAsyncSet *set;
|
||||
|
||||
set = gimp_data_factory_get_async_set (factory);
|
||||
g_object_get (set, "empty", &loaded, NULL);
|
||||
if (! loaded)
|
||||
{
|
||||
gimp_data_factory_data_wait (factory);
|
||||
loaded = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#undef GIMPPOINTER_TO_TYPE
|
||||
|
||||
g_list_free (data_types);
|
||||
|
||||
return loaded;
|
||||
}
|
||||
|
||||
gint64
|
||||
gimp_data_factories_get_memsize (Gimp *gimp,
|
||||
gint64 *gui_size)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ void gimp_data_factories_add_builtin (Gimp *gimp);
|
|||
void gimp_data_factories_clear (Gimp *gimp);
|
||||
void gimp_data_factories_exit (Gimp *gimp);
|
||||
|
||||
gboolean gimp_data_factories_wait (Gimp *gimp);
|
||||
|
||||
gint64 gimp_data_factories_get_memsize (Gimp *gimp,
|
||||
gint64 *gui_size);
|
||||
void gimp_data_factories_data_clean (Gimp *gimp);
|
||||
|
|
|
|||
|
|
@ -1630,6 +1630,50 @@ gimp_version_cmp (const gchar *v1,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_get_type_children:
|
||||
* @type: the %GType to find children types for.
|
||||
* @types: set %NULL for the initial call (internal variable for
|
||||
* recursive calls).
|
||||
* @excluded: a list of types to exclude.
|
||||
*
|
||||
* Gather and recursively return all the subtypes of @type (except any
|
||||
* type listed in @excluded).
|
||||
*
|
||||
* Note that @type itself is not included, so if you wished to have it,
|
||||
* you must add it yourself after calling this function.
|
||||
*
|
||||
* Returns: a list of %Gtypes.
|
||||
*/
|
||||
GList *
|
||||
gimp_get_type_children (GType type,
|
||||
GList *types,
|
||||
GList *excluded)
|
||||
{
|
||||
GType *dtypes;
|
||||
guint n_types;
|
||||
|
||||
dtypes = g_type_children (type, &n_types);
|
||||
|
||||
/* TODO: when bumping GLib >= 2.80, use GTYPE_TO_POINTER instead. */
|
||||
#define GIMPTYPE_TO_POINTER(t) ((gpointer) (guintptr) (t))
|
||||
|
||||
for (gint i = 0; i < n_types; i++)
|
||||
{
|
||||
if (g_list_find (excluded, GIMPTYPE_TO_POINTER (dtypes[i])))
|
||||
continue;
|
||||
|
||||
types = gimp_get_type_children (dtypes[i], types, excluded);
|
||||
types = g_list_prepend (types, GIMPTYPE_TO_POINTER (dtypes[i]));
|
||||
}
|
||||
|
||||
#undef GIMPTYPE_TO_POINTER
|
||||
|
||||
g_free (dtypes);
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
/* Private functions */
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -155,3 +155,7 @@ gboolean gimp_win32_have_windows_ink (void);
|
|||
|
||||
gint gimp_version_cmp (const gchar *v1,
|
||||
const gchar *v2);
|
||||
|
||||
GList * gimp_get_type_children (GType type,
|
||||
GList *types,
|
||||
GList *excluded);
|
||||
|
|
|
|||
|
|
@ -892,7 +892,7 @@ gimp_is_restored (Gimp *gimp)
|
|||
{
|
||||
g_return_val_if_fail (GIMP_IS_GIMP (gimp), FALSE);
|
||||
|
||||
return gimp->initialized && gimp->restored;
|
||||
return gimp->initialized && gimp->restored && gimp_data_factories_wait (gimp);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "gegl/gimp-babl.h"
|
||||
|
||||
#include "core/gimp.h"
|
||||
#include "core/gimp-data-factories.h"
|
||||
#include "core/gimpcontext.h"
|
||||
#include "core/gimpdocumentlist.h"
|
||||
#include "core/gimpimage.h"
|
||||
|
|
@ -523,6 +524,8 @@ file_open_with_proc_and_display (Gimp *gimp,
|
|||
g_return_val_if_fail (monitor == NULL || G_IS_OBJECT (monitor), NULL);
|
||||
g_return_val_if_fail (status != NULL, NULL);
|
||||
|
||||
gimp_data_factories_wait (gimp);
|
||||
|
||||
if (gimp->no_interface)
|
||||
run_mode = GIMP_RUN_NONINTERACTIVE;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue