Serialize GimpFont and fix loading older xcf files

MR #1011 breaks that because now we have a display name
and a lookup name, so font info is saved in the xcf file,
and when loading, the font which matches these info is used.

This doesn't fix pango markup having the wrong fonts names.
This commit is contained in:
Idriss Fekir 2023-08-05 00:04:16 +01:00 committed by Jehan
parent a966297498
commit 7be3f56f5c
4 changed files with 582 additions and 58 deletions

View File

@ -37,12 +37,14 @@
#include FT_TRUETYPE_TABLES_H
#include "libgimpbase/gimpbase.h"
#include "libgimpconfig/gimpconfig.h"
#include "text-types.h"
#include "core/gimptempbuf.h"
#include "core/gimp-memsize.h"
#include "core/gimpcontainer.h"
#include "gimpfont.h"
@ -74,47 +76,440 @@ struct _GimpFont
gint popup_width;
gint popup_height;
gchar *lookup_name;
/*properties for serialization*/
gchar *hash;
gchar *fullname;
gchar *family;
gchar *style;
gchar *psname;
gint weight;
gint width;
gint index;
gint slant;
gint fontversion;
/*for backward compatibility*/
gchar *desc;
};
struct _GimpFontClass
{
GimpDataClass parent_class;
GimpContainer *fontfactory;
};
static void gimp_font_finalize (GObject *object);
static void gimp_font_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_font_finalize (GObject *object);
static void gimp_font_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_font_get_preview_size (GimpViewable *viewable,
gint size,
gboolean popup,
gboolean dot_for_dot,
gint *width,
gint *height);
static gboolean gimp_font_get_popup_size (GimpViewable *viewable,
gint width,
gint height,
gboolean dot_for_dot,
gint *popup_width,
gint *popup_height);
static GimpTempBuf * gimp_font_get_new_preview (GimpViewable *viewable,
GimpContext *context,
gint width,
gint height);
static void gimp_font_get_preview_size (GimpViewable *viewable,
gint size,
gboolean popup,
gboolean dot_for_dot,
gint *width,
gint *height);
static gboolean gimp_font_get_popup_size (GimpViewable *viewable,
gint width,
gint height,
gboolean dot_for_dot,
gint *popup_width,
gint *popup_height);
static GimpTempBuf * gimp_font_get_new_preview (GimpViewable *viewable,
GimpContext *context,
gint width,
gint height);
static const gchar * gimp_font_get_sample_string (PangoContext *context,
PangoFontDescription *font_desc);
static const gchar * gimp_font_get_sample_string (PangoContext *context,
PangoFontDescription *font_desc);
static void gimp_font_config_iface_init (GimpConfigInterface *iface);
static gboolean gimp_font_serialize (GimpConfig *config,
GimpConfigWriter *writer,
gpointer data);
static GimpConfig * gimp_font_deserialize_create (GType type,
GScanner *scanner,
gint nest_level,
gpointer data);
static gint64 gimp_font_get_memsize (GimpObject *object,
gint64 *gui_size);
G_DEFINE_TYPE (GimpFont, gimp_font, GIMP_TYPE_DATA)
G_DEFINE_TYPE_WITH_CODE (GimpFont, gimp_font, GIMP_TYPE_DATA,
G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONFIG,
gimp_font_config_iface_init))
#define parent_class gimp_font_parent_class
static void
gimp_font_config_iface_init (GimpConfigInterface *iface)
{
iface->serialize = gimp_font_serialize;
iface->deserialize_create = gimp_font_deserialize_create;
}
static gboolean
gimp_font_serialize (GimpConfig *config,
GimpConfigWriter *writer,
gpointer data)
{
GimpFont *font;
g_return_val_if_fail (GIMP_IS_FONT (config), FALSE);
font = GIMP_FONT (config);
if (font == GIMP_FONT (gimp_font_get_standard ()))
return TRUE;
/* Computing the hash is expensive, so it's only done when serializing, then it's cached,
* or it's done when deserializing in case the hash hasn't been computed for that particular font.
*/
if (font->hash == NULL)
{
PangoFontDescription *pfd = pango_font_description_from_string (font->lookup_name);
PangoFcFont *pango_font = PANGO_FC_FONT (pango_context_load_font (font->pango_context, pfd));
GChecksum *checksum = g_checksum_new (G_CHECKSUM_SHA256);
gchar *file;
hb_blob_t *hb_blob;
guint length;
const char *hb_data;
FcPatternGetString (pango_fc_font_get_pattern (pango_font), FC_FILE, 0, (FcChar8 **) &file);
hb_blob = hb_blob_create_from_file (file);
hb_data = hb_blob_get_data (hb_blob, &length);
g_checksum_update (checksum, (const guchar*)hb_data, length);
font->hash = g_strdup (g_checksum_get_string (checksum));
pango_font_description_free (pfd);
g_object_unref (pango_font);
hb_blob_destroy (hb_blob);
g_checksum_free (checksum);
}
gimp_config_writer_open (writer, "fonthash");
gimp_config_writer_string (writer, font->hash);
gimp_config_writer_close (writer);
gimp_config_writer_open (writer, "fullname");
gimp_config_writer_string (writer, font->fullname);
gimp_config_writer_close (writer);
gimp_config_writer_open (writer, "family");
gimp_config_writer_string (writer, font->family);
gimp_config_writer_close (writer);
gimp_config_writer_open (writer, "style");
gimp_config_writer_string (writer, font->style);
gimp_config_writer_close (writer);
gimp_config_writer_open (writer, "psname");
gimp_config_writer_string (writer, font->psname);
gimp_config_writer_close (writer);
gimp_config_writer_open (writer, "index");
gimp_config_writer_printf (writer, "%d", font->index);
gimp_config_writer_close (writer);
gimp_config_writer_open (writer, "weight");
gimp_config_writer_printf (writer, "%d", font->weight);
gimp_config_writer_close (writer);
gimp_config_writer_open (writer, "slant");
gimp_config_writer_printf (writer, "%d", font->slant);
gimp_config_writer_close (writer);
gimp_config_writer_open (writer, "width");
gimp_config_writer_printf (writer, "%d", font->width);
gimp_config_writer_close (writer);
gimp_config_writer_open (writer, "fontversion");
gimp_config_writer_printf (writer, "%d", font->fontversion);
gimp_config_writer_close (writer);
return TRUE;
}
static GimpConfig *
gimp_font_deserialize_create (GType type,
GScanner *scanner,
gint nest_level,
gpointer data)
{
GimpFont *font;
GimpContainer *fonts_container = GIMP_FONT_CLASS (g_type_class_peek (GIMP_TYPE_FONT))->fontfactory;
gint most_similar_font_index = -1;
gint font_count = gimp_container_get_n_children (fonts_container);
gint largest_similarity = 0;
gint similar_fonts = 0;
gboolean match_found = FALSE;
gint i;
gchar *fonthash;
gchar *fullname;
gchar *family;
gchar *psname;
gchar *style;
gint index;
gint weight;
gint slant;
gint width;
gint fontversion;
/* This is for backward compatibility with older xcf files.
* The font used to be serialized as a string containing
* its name.
*/
if (g_scanner_peek_next_token (scanner) == G_TOKEN_STRING)
{
gchar* font_name;
gimp_scanner_parse_string (scanner, &font_name);
for (i = 0; i < font_count; i++)
{
font = GIMP_FONT (gimp_container_get_child_by_index (fonts_container, i));
if (!g_strcmp0 (font->desc, font_name))
break;
font = NULL;
}
if (font == NULL)
font = GIMP_FONT (gimp_font_get_standard ());
else
g_object_ref (font);
return GIMP_CONFIG (GIMP_FONT (font));
}
if (g_scanner_peek_next_token (scanner) == G_TOKEN_RIGHT_PAREN)
return GIMP_CONFIG (GIMP_FONT (gimp_font_get_standard ()));
g_scanner_get_next_token (scanner); /* ( */
g_scanner_get_next_token (scanner); /* "fonthash" */
gimp_scanner_parse_string (scanner, &fonthash);
g_scanner_get_next_token (scanner); /* ) */
g_scanner_get_next_token (scanner); /* ( */
g_scanner_get_next_token (scanner); /* "fullname" */
gimp_scanner_parse_string (scanner, &fullname);
g_scanner_get_next_token (scanner); /* ) */
g_scanner_get_next_token (scanner); /* ( */
g_scanner_get_next_token (scanner); /* "family" */
gimp_scanner_parse_string (scanner, &family);
g_scanner_get_next_token (scanner); /* ) */
g_scanner_get_next_token (scanner); /* ( */
g_scanner_get_next_token (scanner); /* "style" */
gimp_scanner_parse_string (scanner, &style);
g_scanner_get_next_token (scanner); /* ) */
g_scanner_get_next_token (scanner); /* ( */
g_scanner_get_next_token (scanner); /* "psname" */
gimp_scanner_parse_string (scanner, &psname);
g_scanner_get_next_token (scanner); /* ( */
g_scanner_get_next_token (scanner); /* ( */
g_scanner_get_next_token (scanner); /* "font index" */
gimp_scanner_parse_int (scanner, &index);
g_scanner_get_next_token (scanner); /* ) */
g_scanner_get_next_token (scanner); /* ( */
g_scanner_get_next_token (scanner); /* "weight" */
gimp_scanner_parse_int (scanner, &weight);
g_scanner_get_next_token (scanner); /* ) */
g_scanner_get_next_token (scanner); /* ( */
g_scanner_get_next_token (scanner); /* "slant" */
gimp_scanner_parse_int (scanner, &slant);
g_scanner_get_next_token (scanner); /* ) */
g_scanner_get_next_token (scanner); /* ( */
g_scanner_get_next_token (scanner); /* "width" */
gimp_scanner_parse_int (scanner, &width);
g_scanner_get_next_token (scanner); /* ) */
g_scanner_get_next_token (scanner); /* ( */
g_scanner_get_next_token (scanner); /* "fontversion" */
gimp_scanner_parse_int (scanner, &fontversion);
g_scanner_get_next_token (scanner); /* ) */
for (i = 0; i < font_count; i++)
{
gint current_font_similarity = 0;
font = GIMP_FONT (gimp_container_get_child_by_index (fonts_container, i));
if (font->hash != NULL && !g_strcmp0 (font->hash, fonthash))
{
most_similar_font_index = i;
match_found = TRUE;
break;
}
/* Some attrs are more identifying than others,
* hence their higher importance in measuring similarity.
*/
if (!g_strcmp0 (font->fullname, fullname))
current_font_similarity += 5;
if (!g_strcmp0 (font->family, family))
current_font_similarity += 5;
if (font->psname != NULL && !g_strcmp0 (font->psname, psname))
current_font_similarity += 5;
if (current_font_similarity < 5)
continue;
if (font->style != NULL && !g_strcmp0 (font->style, style))
current_font_similarity++;
if (font->weight != -1 && font->weight == weight)
current_font_similarity++;
if (font->width != -1 && font->width == width)
current_font_similarity++;
if (font->slant != -1 && font->slant == slant)
current_font_similarity++;
if (font->index != -1 && font->index == index)
current_font_similarity++;
if (font->fontversion != -1 && font->fontversion == fontversion)
current_font_similarity++;
if (current_font_similarity > largest_similarity)
{
largest_similarity = current_font_similarity;
most_similar_font_index = i;
similar_fonts++;
}
}
/* In case there are multiple font with identical info,
* the font file hash should be used for comparison.
*/
if (!match_found && similar_fonts > 1)
for (i = 0; i < font_count; i++)
{
gint current_font_similarity = 0;
font = GIMP_FONT (gimp_container_get_child_by_index (fonts_container, i));
if (!g_strcmp0 (font->fullname, fullname))
current_font_similarity += 5;
if (!g_strcmp0 (font->family, family))
current_font_similarity += 5;
if (font->psname != NULL && !g_strcmp0 (font->psname, psname))
current_font_similarity += 5;
if (current_font_similarity < 5)
continue;
if (font->style != NULL && !g_strcmp0 (font->style, style))
current_font_similarity++;
if (font->weight != -1 && font->weight == weight)
current_font_similarity++;
if (font->width != -1 && font->width == width)
current_font_similarity++;
if (font->slant != -1 && font->slant == slant)
current_font_similarity++;
if (font->index != -1 && font->index == index)
current_font_similarity++;
if (font->fontversion != -1 && font->fontversion == fontversion)
current_font_similarity++;
if (current_font_similarity == largest_similarity)
{
if (font->hash == NULL)
{
PangoFontDescription *pfd = pango_font_description_from_string (font->lookup_name);
PangoFcFont *pango_font = PANGO_FC_FONT (pango_context_load_font (font->pango_context, pfd));
GChecksum *checksum = g_checksum_new (G_CHECKSUM_SHA256);
gchar *file;
hb_blob_t *hb_blob;
guint length;
const char *hb_data;
FcPatternGetString (pango_fc_font_get_pattern (pango_font), FC_FILE, 0, (FcChar8 **) &file);
hb_blob = hb_blob_create_from_file (file);
hb_data = hb_blob_get_data (hb_blob, &length);
g_checksum_update (checksum, (const guchar*)hb_data, length);
font->hash = g_strdup (g_checksum_get_string (checksum));
pango_font_description_free (pfd);
g_object_unref (pango_font);
hb_blob_destroy (hb_blob);
g_checksum_free (checksum);
}
if (!g_strcmp0 (font->hash, fonthash))
{
most_similar_font_index = i;
break;
}
}
}
if (most_similar_font_index > -1)
{
font = GIMP_FONT (gimp_container_get_child_by_index (fonts_container, most_similar_font_index));
g_object_ref (font);
}
else
{
font = GIMP_FONT (gimp_font_get_standard ());
}
g_free (fonthash);
g_free (fullname);
g_free (family);
g_free (psname);
g_free (style);
return GIMP_CONFIG (font);
}
void
gimp_font_class_set_font_factory (GimpContainer *factory)
{
GimpFontClass *klass = GIMP_FONT_CLASS (g_type_class_peek (GIMP_TYPE_FONT));
klass->fontfactory = factory;
}
void
gimp_font_set_font_info (GimpFont *font,
gpointer font_info[])
{
font->fullname = g_strdup ((gchar*)font_info[PROP_FULLNAME]);
font->family = g_strdup ((gchar*)font_info[PROP_FAMILY]);
font->style = g_strdup ((gchar*)font_info[PROP_STYLE]);
font->psname = g_strdup ((gchar*)font_info[PROP_PSNAME]);
font->desc = g_strdup ((gchar*)font_info[PROP_DESC]);
font->weight = *(gint*)font_info[PROP_WEIGHT];
font->width = *(gint*)font_info[PROP_WIDTH];
font->index = *(gint*)font_info[PROP_INDEX];
font->slant = *(gint*)font_info[PROP_SLANT];
font->fontversion = *(gint*)font_info[PROP_FONTVERSION];
}
void
gimp_font_set_lookup_name (GimpFont *font,
gchar *name)
@ -172,6 +567,12 @@ gimp_font_finalize (GObject *object)
g_clear_object (&font->pango_context);
g_clear_object (&font->popup_layout);
g_free (font->lookup_name);
g_free (font->hash);
g_free (font->fullname);
g_free (font->family);
g_free (font->style);
g_free (font->psname);
g_free (font->desc);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -206,6 +607,12 @@ gimp_font_get_memsize (GimpObject *object,
gint64 memsize = 0;
memsize += gimp_string_get_memsize (font->lookup_name);
memsize += gimp_string_get_memsize (font->hash);
memsize += gimp_string_get_memsize (font->fullname);
memsize += gimp_string_get_memsize (font->family);
memsize += gimp_string_get_memsize (font->style);
memsize += gimp_string_get_memsize (font->psname);
memsize += gimp_string_get_memsize (font->desc);
return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
gui_size);
@ -369,6 +776,8 @@ gimp_font_get_standard (void)
"name", "",
NULL));;
/* pango_font_description_from_string doesn't accept NULL */
GIMP_FONT (standard_font)->lookup_name = "";
gimp_data_clean (standard_font);
gimp_data_make_internal (standard_font, "gimp-font-standard");
}

View File

@ -36,14 +36,36 @@
typedef struct _GimpFontClass GimpFontClass;
GType gimp_font_get_type (void) G_GNUC_CONST;
GType gimp_font_get_type (void) G_GNUC_CONST;
GimpData * gimp_font_get_standard (void);
const gchar * gimp_font_get_lookup_name (GimpFont *font);
void gimp_font_set_lookup_name (GimpFont *font,
gchar *name);
gboolean gimp_font_match_by_lookup_name (GimpFont *font,
const gchar *name);
void gimp_font_set_font_info (GimpFont *font,
gpointer font_info[]);
void gimp_font_class_set_font_factory (GimpContainer *factory);
GimpData * gimp_font_get_standard (void);
const gchar * gimp_font_get_lookup_name (GimpFont *font);
void gimp_font_set_lookup_name (GimpFont *font,
gchar *name);
gboolean gimp_font_match_by_lookup_name (GimpFont *font,
const gchar *name);
enum
{
/* properties for serialization*/
PROP_HASH,
PROP_FULLNAME,
PROP_FAMILY,
PROP_STYLE,
PROP_PSNAME,
PROP_WEIGHT,
PROP_WIDTH,
PROP_INDEX,
PROP_SLANT,
PROP_FONTVERSION,
/*for backward compatibility*/
PROP_DESC,
PROPERTIES_COUNT
};
#endif /* __GIMP_FONT_H__ */

View File

@ -512,7 +512,8 @@ gimp_font_factory_add_font (GimpContainer *container,
PangoContext *context,
PangoFontDescription *desc,
const gchar *full_name,
const gchar *path)
const gchar *path,
gpointer font_info[])
{
gchar *name = (gchar *) full_name;
@ -537,6 +538,9 @@ gimp_font_factory_add_font (GimpContainer *container,
NULL);
gimp_font_set_lookup_name (font, pango_font_description_to_string (desc));
if (font_info != NULL)
gimp_font_set_font_info (font, font_info);
if (path != NULL)
{
GFile *file;
@ -571,7 +575,18 @@ gimp_font_factory_make_alias (GimpContainer *container,
gboolean bold,
gboolean italic)
{
PangoFontDescription *desc = pango_font_description_new ();
FcPattern *fcpattern;
PangoFontDescription *desc = pango_font_description_new ();
gchar *desc_str = NULL;
gchar *style = NULL;
gchar *psname = NULL;
gchar *fullname = NULL;
gint index = -1;
gint weight = -1;
gint width = -1;
gint slant = -1;
gint fontversion = -1;
gpointer font_info[PROPERTIES_COUNT];
pango_font_description_set_family (desc, family);
pango_font_description_set_style (desc,
@ -583,13 +598,39 @@ gimp_font_factory_make_alias (GimpContainer *container,
PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
pango_font_description_set_stretch (desc, PANGO_STRETCH_NORMAL);
fcpattern = pango_fc_font_get_pattern (PANGO_FC_FONT (pango_context_load_font (context, desc)));
/* this is for backward compatibility*/
desc_str = pango_font_description_to_string (desc);
FcPatternGetString (fcpattern, FC_FULLNAME, 0, (FcChar8 **) &fullname);
FcPatternGetString (fcpattern, FC_POSTSCRIPT_NAME, 0, (FcChar8 **) &psname);
FcPatternGetString (fcpattern, FC_STYLE, 0, (FcChar8 **) &style);
FcPatternGetInteger (fcpattern, FC_WEIGHT, 0, &weight);
FcPatternGetInteger (fcpattern, FC_WIDTH, 0, &width);
FcPatternGetInteger (fcpattern, FC_INDEX, 0, &index);
FcPatternGetInteger (fcpattern, FC_SLANT, 0, &slant);
FcPatternGetInteger (fcpattern, FC_FONTVERSION, 0, &fontversion);
font_info[PROP_DESC] = (gpointer) desc_str;
font_info[PROP_FULLNAME] = (gpointer) fullname;
font_info[PROP_FAMILY] = (gpointer) family;
font_info[PROP_STYLE] = (gpointer) style;
font_info[PROP_PSNAME] = (gpointer) psname;
font_info[PROP_WEIGHT] = (gpointer) &weight;
font_info[PROP_WIDTH] = (gpointer) &width;
font_info[PROP_INDEX] = (gpointer) &index;
font_info[PROP_SLANT] = (gpointer) &slant;
font_info[PROP_FONTVERSION] = (gpointer) &fontversion;
/* This might be the only valid time where a NULL path is valid. Though I do
* wonder if really these aliases are the right thing to do. Generic aliases
* are the best way to have differing text renders over time (and that's not
* something to be wished for). XXX
*/
gimp_font_factory_add_font (container, context, desc, NULL, NULL);
gimp_font_factory_add_font (container, context, desc, NULL, NULL, font_info);
g_free (desc_str);
pango_font_description_free (desc);
}
@ -660,20 +701,23 @@ gimp_font_factory_load_names (GimpContainer *container,
PangoFontDescription *pfd;
GString *xml;
gchar *fontformat;
gchar *family;
gchar *style;
gchar *psname;
gchar *newname;
gchar *escaped_fullname;
gchar *fullname;
gchar *fullname2;
gchar *escaped_file;
gchar *file;
gint index;
gint weight;
gint width;
gint slant;
gint fontversion;
gchar *family = NULL;
gchar *style = NULL;
gchar *psname = NULL;
gchar *newname = NULL;
gchar *escaped_fullname = NULL;
gchar *fullname = NULL;
gchar *fullname2 = NULL;
gchar *escaped_file = NULL;
gchar *file = NULL;
gint index = -1;
gint weight = -1;
gint width = -1;
gint slant = -1;
gint fontversion = -1;
gpointer font_info[PROPERTIES_COUNT];
PangoFontDescription *pattern_pfd;
gchar *pattern_pfd_desc;
FcPatternGetString (fontset->fonts[i], FC_FILE, 0, (FcChar8 **) &file);
@ -713,6 +757,30 @@ gimp_font_factory_load_names (GimpContainer *container,
continue;
}
FcPatternGetString (fontset->fonts[i], FC_FAMILY, 0, (FcChar8 **) &family);
FcPatternGetString (fontset->fonts[i], FC_POSTSCRIPT_NAME, 0, (FcChar8 **) &psname);
FcPatternGetString (fontset->fonts[i], FC_STYLE, 0, (FcChar8 **) &style);
FcPatternGetInteger (fontset->fonts[i], FC_WEIGHT, 0, &weight);
FcPatternGetInteger (fontset->fonts[i], FC_WIDTH, 0, &width);
FcPatternGetInteger (fontset->fonts[i], FC_INDEX, 0, &index);
FcPatternGetInteger (fontset->fonts[i], FC_SLANT, 0, &slant);
FcPatternGetInteger (fontset->fonts[i], FC_FONTVERSION, 0, &fontversion);
/* this is for backward compatibility*/
pattern_pfd = pango_fc_font_description_from_pattern (fontset->fonts[i], FALSE);
pattern_pfd_desc = pango_font_description_to_string (pattern_pfd);
font_info[PROP_DESC] = (gpointer) pattern_pfd_desc;
font_info[PROP_FULLNAME] = (gpointer) fullname;
font_info[PROP_FAMILY] = (gpointer) family;
font_info[PROP_STYLE] = (gpointer) style;
font_info[PROP_PSNAME] = (gpointer) psname;
font_info[PROP_WEIGHT] = (gpointer) &weight;
font_info[PROP_WIDTH] = (gpointer) &width;
font_info[PROP_INDEX] = (gpointer) &index;
font_info[PROP_SLANT] = (gpointer) &slant;
font_info[PROP_FONTVERSION] = (gpointer) &fontversion;
/* Sometimes a font has more than one fullname,
* sometimes the second is more appropriate for display,
* in such cases we use it instead of the first.
@ -734,8 +802,6 @@ gimp_font_factory_load_names (GimpContainer *container,
escaped_fullname);
g_free (escaped_fullname);
FcPatternGetString (fontset->fonts[i], FC_FAMILY, 0, (FcChar8 **) &family);
family = g_markup_escape_text (family, -1);
g_string_append_printf (xml,
"<edit name=\"family\" mode=\"assign\" binding=\"strong\"><string>%s</string></edit>",
@ -748,7 +814,7 @@ gimp_font_factory_load_names (GimpContainer *container,
escaped_file);
g_free (escaped_file);
if (FcPatternGetString (fontset->fonts[i], FC_POSTSCRIPT_NAME, 0, (FcChar8 **) &psname) == FcResultMatch)
if (psname != NULL)
{
psname = g_markup_escape_text (psname, -1);
g_string_append_printf (xml,
@ -757,7 +823,7 @@ gimp_font_factory_load_names (GimpContainer *container,
g_free (psname);
}
if (FcPatternGetString (fontset->fonts[i], FC_STYLE, 0, (FcChar8 **) &style) == FcResultMatch)
if (style != NULL)
{
style = g_markup_escape_text (style, -1);
g_string_append_printf (xml,
@ -766,27 +832,27 @@ gimp_font_factory_load_names (GimpContainer *container,
g_free (style);
}
if (FcPatternGetInteger (fontset->fonts[i], FC_WEIGHT, 0, &weight) == FcResultMatch)
if (weight != -1)
g_string_append_printf (xml,
"<edit name=\"weight\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
weight);
if (FcPatternGetInteger (fontset->fonts[i], FC_WIDTH, 0, &width) == FcResultMatch)
if (width != -1)
g_string_append_printf (xml,
"<edit name=\"width\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
width);
if (FcPatternGetInteger (fontset->fonts[i], FC_SLANT, 0, &slant) == FcResultMatch)
if (slant != -1)
g_string_append_printf (xml,
"<edit name=\"slant\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
slant);
if (FcPatternGetInteger (fontset->fonts[i], FC_FONTVERSION, 0, &fontversion) == FcResultMatch)
if (fontversion != -1)
g_string_append_printf (xml,
"<edit name=\"fontversion\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
fontversion);
if (FcPatternGetInteger (fontset->fonts[i], FC_INDEX, 0, &index) == FcResultMatch)
if (index != -1)
g_string_append_printf (xml,
"<edit name=\"index\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
index);
@ -800,8 +866,10 @@ gimp_font_factory_load_names (GimpContainer *container,
if (fullname2 != NULL && g_str_is_ascii (fullname2))
fullname = fullname2;
gimp_font_factory_add_font (container, context, pfd, fullname, (const gchar *) file);
gimp_font_factory_add_font (container, context, pfd, fullname, (const gchar *) file, font_info);
pango_font_description_free (pattern_pfd);
g_free (pattern_pfd_desc);
pango_font_description_free (pfd);
g_free (newname);
g_string_free (xml, TRUE);
@ -822,4 +890,6 @@ gimp_font_factory_load_names (GimpContainer *container,
gimp_font_factory_load_aliases (container, context);
FcFontSetDestroy (fontset);
gimp_font_class_set_font_factory (container);
}

View File

@ -82,12 +82,35 @@ gimp_text_from_parasite (const GimpParasite *parasite,
parasite_data = (gchar *) gimp_parasite_get_data (parasite, &parasite_data_size);
if (parasite_data)
{
gboolean is_old = !g_str_has_prefix (strstr (parasite_data, "\")\n(font"), "\")\n(font \"GimpFont\"");
GimpParasite *new_parasite = NULL;
GString *new_data;
/* This is for backward compatibility with older xcf files.
* font used to be serialized as a string, but now it is serialized/deserialized as
* GimpFont, so the object Type name is inserted for the GimpFont deserialization function to be called.
*/
if (is_old)
{
new_data = g_string_new (parasite_data);
g_string_replace (new_data, "\")\n(font", "\")\n(font \"GimpFont\"", 1);
new_parasite = gimp_parasite_new (gimp_parasite_get_name (parasite),
gimp_parasite_get_flags (parasite),
new_data->len+1,
new_data->str);
parasite = new_parasite;
g_string_free (new_data, TRUE);
}
parasite_data = g_strndup (parasite_data, parasite_data_size);
gimp_config_deserialize_parasite (GIMP_CONFIG (text),
parasite,
NULL,
error);
g_free (parasite_data);
gimp_parasite_free (new_parasite);
}
else
{