diff --git a/app/core/gimpcontext.c b/app/core/gimpcontext.c index 534356ee13..9f0abba300 100644 --- a/app/core/gimpcontext.c +++ b/app/core/gimpcontext.c @@ -3224,7 +3224,9 @@ gimp_context_set_font_name (GimpContext *context, g_return_if_fail (GIMP_IS_CONTEXT (context)); container = gimp_data_factory_get_container (context->gimp->font_factory); - font = gimp_container_get_child_by_name (container, name); + font = gimp_container_search (container, + (GimpContainerSearchFunc) gimp_font_match_by_lookup_name, + (gpointer) name); if (font) { @@ -3324,7 +3326,7 @@ gimp_context_real_set_font (GimpContext *context, 0); if (font != GIMP_FONT (gimp_font_get_standard ())) - context->font_name = g_strdup (gimp_object_get_name (font)); + context->font_name = g_strdup (gimp_font_get_lookup_name (font)); } g_object_notify (G_OBJECT (context), "font"); diff --git a/app/text/gimpfont.c b/app/text/gimpfont.c index 1041bd5029..c74e560c1e 100644 --- a/app/text/gimpfont.c +++ b/app/text/gimpfont.c @@ -71,6 +71,7 @@ struct _GimpFont PangoLayout *popup_layout; gint popup_width; gint popup_height; + gchar *lookup_name; }; struct _GimpFontClass @@ -111,6 +112,25 @@ G_DEFINE_TYPE (GimpFont, gimp_font, GIMP_TYPE_DATA) #define parent_class gimp_font_parent_class +void +gimp_font_set_lookup_name (GimpFont *font, + gchar *name) +{ + font->lookup_name = name; +} + +gboolean +gimp_font_match_by_lookup_name (GimpFont *font, + const gchar *name) +{ + return !g_strcmp0 (gimp_font_get_lookup_name (font), name); +} + +const gchar* +gimp_font_get_lookup_name (GimpFont *font) +{ + return font->lookup_name; +} static void gimp_font_class_init (GimpFontClass *klass) @@ -156,6 +176,7 @@ gimp_font_finalize (GObject *object) g_clear_object (&font->pango_context); g_clear_object (&font->popup_layout); + g_free (font->lookup_name); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -211,7 +232,7 @@ gimp_font_get_popup_size (GimpViewable *viewable, if (! font->pango_context) return FALSE; - name = gimp_object_get_name (font); + name = gimp_font_get_lookup_name (font); font_desc = pango_font_description_from_string (name); g_return_val_if_fail (font_desc != NULL, FALSE); @@ -266,7 +287,7 @@ gimp_font_get_new_preview (GimpViewable *viewable, PangoFontDescription *font_desc; const gchar *name; - name = gimp_object_get_name (font); + name = gimp_font_get_lookup_name (font); DEBUGPRINT (("%s: ", name)); diff --git a/app/text/gimpfont.h b/app/text/gimpfont.h index 1b6a632d26..39fd468fe4 100644 --- a/app/text/gimpfont.h +++ b/app/text/gimpfont.h @@ -37,9 +37,13 @@ typedef struct _GimpFontClass GimpFontClass; -GType gimp_font_get_type (void) G_GNUC_CONST; - -GimpData * gimp_font_get_standard (void); +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); #endif /* __GIMP_FONT_H__ */ diff --git a/app/text/gimpfontfactory.c b/app/text/gimpfontfactory.c index ead75d590f..9a713eb123 100644 --- a/app/text/gimpfontfactory.c +++ b/app/text/gimpfontfactory.c @@ -516,14 +516,16 @@ gimp_font_factory_recursive_add_fontdir (FcConfig *config, static void gimp_font_factory_add_font (GimpContainer *container, PangoContext *context, - PangoFontDescription *desc) + PangoFontDescription *desc, + gchar *full_name) { - gchar *name; + gchar *name = full_name; - if (! desc) + if (! desc && ! full_name) return; - name = pango_font_description_to_string (desc); + if (! full_name) + name = pango_font_description_to_string (desc); /* It doesn't look like pango_font_description_to_string() could ever * return NULL. But just to be double sure and avoid a segfault, I @@ -538,12 +540,13 @@ gimp_font_factory_add_font (GimpContainer *container, "name", name, "pango-context", context, NULL); - + gimp_font_set_lookup_name (font, pango_font_description_to_string (desc)); gimp_container_add (container, GIMP_OBJECT (font)); g_object_unref (font); } - g_free (name); + if (!full_name) + g_free (name); } #ifdef USE_FONTCONFIG_DIRECTLY @@ -571,7 +574,7 @@ gimp_font_factory_make_alias (GimpContainer *container, PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL); pango_font_description_set_stretch (desc, PANGO_STRETCH_NORMAL); - gimp_font_factory_add_font (container, context, desc); + gimp_font_factory_add_font (container, context, desc, NULL); pango_font_description_free (desc); } @@ -606,8 +609,17 @@ gimp_font_factory_load_names (GimpContainer *container, FcFontSet *fontset; gint i; - os = FcObjectSetBuild (FC_FAMILY, FC_STYLE, - FC_SLANT, FC_WEIGHT, FC_WIDTH, + os = FcObjectSetBuild (FC_FAMILY, + FC_STYLE, + FC_POSTSCRIPT_NAME, + FC_FULLNAME, + FC_FILE, + FC_WEIGHT, + FC_SLANT, + FC_WIDTH, + FC_INDEX, + FC_FONTVERSION, + FC_FONTFORMAT, NULL); g_return_if_fail (os); @@ -628,11 +640,173 @@ gimp_font_factory_load_names (GimpContainer *container, for (i = 0; i < fontset->nfont; i++) { - PangoFontDescription *desc; + PangoFcFont *font; + PangoFontDescription *pfd; + GString *xml; + gchar *fontformat; + gchar *family; + gchar *style; + gchar *psname; + gchar *newname; + gchar *escaped_fullname; + gchar *fullname; + gchar *fullname2; + gchar *desc_fullname; + gchar *desc_file; + gchar *file; + gint index; + gint weight; + gint width; + gint slant; + gint fontversion; - desc = pango_fc_font_description_from_pattern (fontset->fonts[i], FALSE); - gimp_font_factory_add_font (container, context, desc); - pango_font_description_free (desc); + FcPatternGetString (fontset->fonts[i], FC_FILE, 0, (FcChar8 **) &file); + + /* + * woff and woff2 cause problems with pango (probably with harfbuzz). + * pcf,pcf.gz are bitmap font formats, not supported by pango (because of harfbuzz). + * afm, pfm, pfb are type1 font formats, not supported by pango (because of harfbuzz). + */ + if (g_str_has_suffix (file, ".woff") || + g_str_has_suffix (file, ".woff2") || + g_str_has_suffix (file, ".pcf") || + g_str_has_suffix (file, ".pcf.gz") || + g_str_has_suffix (file, ".afm") || + g_str_has_suffix (file, ".pfm") || + g_str_has_suffix (file, ".pfb")) + { + g_printerr("Font file: %s is not supported by Pango, it can not be loaded.\n", + file); + continue; + } + + /* Pango doesn't support non SFNT fonts because harfbuzz doesn't support them. */ + if (FcPatternGetString (fontset->fonts[i], FC_FONTFORMAT, 0, (FcChar8 **) &fontformat) != FcResultMatch || + (g_ascii_strcasecmp (fontformat, "TrueType") != 0 && + g_ascii_strcasecmp (fontformat, "CFF") != 0)) + continue; + + /* Some variable fonts have only a family name and a font version. */ + if (FcPatternGetString (fontset->fonts[i], FC_FULLNAME, 0, (FcChar8 **) &fullname) != FcResultMatch) + continue; + + /* 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. + */ + if (FcPatternGetString (fontset->fonts[i], FC_FULLNAME, 1, (FcChar8 **) &fullname2) != FcResultMatch) + fullname2 = NULL; + + /* + * In case the pango font description constructed from the fc pattern is correct, + * we use it instead of renaming the font in fontconfig. + */ + pfd = pango_fc_font_description_from_pattern (fontset->fonts[i], FALSE); + + font = PANGO_FC_FONT (pango_context_load_font (context, pfd)); + + FcPatternGetString (pango_fc_font_get_pattern (font), FC_FULLNAME, 0, (FcChar8 **) &desc_fullname); + FcPatternGetString (pango_fc_font_get_pattern (font), FC_FILE, 0, (FcChar8 **) &desc_file); + + g_object_unref (font); + + if (!g_strcmp0 (desc_fullname, fullname) && !g_strcmp0 (desc_file, file)) + { + if (fullname2 != NULL && g_str_is_ascii (fullname2)) + fullname = fullname2; + + gimp_font_factory_add_font (container, context, pfd, fullname); + pango_font_description_free (pfd); + continue; + } + + pango_font_description_free (pfd); + + newname = g_strdup_printf ("gimpfont%i", i); + + xml = g_string_new ("\n"); + + g_string_append_printf (xml, + "%s", + newname); + + escaped_fullname = g_markup_escape_text (fullname, -1); + g_string_append_printf (xml, + "%s", + 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, + "%s", + family); + g_free (family); + + file = g_markup_escape_text (file, -1); + g_string_append_printf (xml, + "%s", + file); + g_free (file); + + if (FcPatternGetString (fontset->fonts[i], FC_POSTSCRIPT_NAME, 0, (FcChar8 **) &psname) == FcResultMatch) + { + psname = g_markup_escape_text (psname, -1); + g_string_append_printf (xml, + "%s", + psname); + g_free (psname); + } + + if (FcPatternGetString (fontset->fonts[i], FC_STYLE, 0, (FcChar8 **) &style) == FcResultMatch) + { + style = g_markup_escape_text (style, -1); + g_string_append_printf (xml, + "%s", + style); + g_free (style); + } + + if (FcPatternGetInteger (fontset->fonts[i], FC_WEIGHT, 0, &weight) == FcResultMatch) + g_string_append_printf (xml, + "%i", + weight); + + if (FcPatternGetInteger (fontset->fonts[i], FC_WIDTH, 0, &width) == FcResultMatch) + g_string_append_printf (xml, + "%i", + width); + + if (FcPatternGetInteger (fontset->fonts[i], FC_SLANT, 0, &slant) == FcResultMatch) + g_string_append_printf (xml, + "%i", + slant); + + if (FcPatternGetInteger (fontset->fonts[i], FC_FONTVERSION, 0, &fontversion) == FcResultMatch) + g_string_append_printf (xml, + "%i", + fontversion); + + if (FcPatternGetInteger (fontset->fonts[i], FC_INDEX, 0, &index) == FcResultMatch) + g_string_append_printf (xml, + "%i", + index); + + g_string_append (xml, "\n"); + + FcConfigParseAndLoadFromMemory (FcConfigGetCurrent (), (const FcChar8 *) xml->str, FcTrue); + + pfd = pango_font_description_from_string (newname); + + if (fullname2 != NULL && g_str_is_ascii (fullname2)) + fullname = fullname2; + + gimp_font_factory_add_font (container, context, pfd, fullname); + + pango_font_description_free (pfd); + g_free (newname); + g_string_free (xml, TRUE); } /* only create aliases if there is at least one font available */ @@ -666,7 +840,7 @@ gimp_font_factory_load_names (GimpContainer *container, PangoFontDescription *desc; desc = pango_font_face_describe (faces[j]); - gimp_font_factory_add_font (container, context, desc); + gimp_font_factory_add_font (container, context, desc, NULL); pango_font_description_free (desc); } } diff --git a/app/widgets/gimptextstyleeditor.c b/app/widgets/gimptextstyleeditor.c index 09aff50f4b..a835a61da1 100644 --- a/app/widgets/gimptextstyleeditor.c +++ b/app/widgets/gimptextstyleeditor.c @@ -34,6 +34,7 @@ #include "core/gimpcontext.h" #include "text/gimptext.h" +#include "text/gimpfont.h" #include "gimpcolorpanel.h" #include "gimpcontainerentry.h" @@ -1308,7 +1309,7 @@ gimp_text_style_editor_update_idle (GimpTextStyleEditor *editor) if (editor->context->font_name && g_strcmp0 (editor->context->font_name, - gimp_object_get_name (gimp_context_get_font (editor->context)))) + gimp_font_get_lookup_name (gimp_context_get_font (editor->context)))) { /* A font is set, but is unavailable; change the help text. */ gchar *help_text;