Implement support for custom fonts
Remap font names to unique generated names so that pango sees them. keep the font name for display and the internal name for everything else. * Fonts are still broken When exporting to pdf * Not sure if xcf files would be usable on other systems maybe use hash of psname internally instead * Not sure if plug-ins using text layer work correctly (do they use internal font name or the actual name?)
This commit is contained in:
parent
d337d2d196
commit
5972d8d97f
5 changed files with 224 additions and 22 deletions
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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 ("<?xml version=\"1.0\"?>\n<match>");
|
||||
|
||||
g_string_append_printf (xml,
|
||||
"<test name=\"family\"><string>%s</string></test>",
|
||||
newname);
|
||||
|
||||
escaped_fullname = g_markup_escape_text (fullname, -1);
|
||||
g_string_append_printf (xml,
|
||||
"<edit name=\"fullname\" mode=\"assign\" binding=\"strong\"><string>%s</string></edit>",
|
||||
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>",
|
||||
family);
|
||||
g_free (family);
|
||||
|
||||
file = g_markup_escape_text (file, -1);
|
||||
g_string_append_printf (xml,
|
||||
"<edit name=\"file\" mode=\"assign\" binding=\"strong\"><string>%s</string></edit>",
|
||||
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,
|
||||
"<edit name=\"postscriptname\" mode=\"assign\" binding=\"strong\"><string>%s</string></edit>",
|
||||
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,
|
||||
"<edit name=\"style\" mode=\"assign\" binding=\"strong\"><string>%s</string></edit>",
|
||||
style);
|
||||
g_free (style);
|
||||
}
|
||||
|
||||
if (FcPatternGetInteger (fontset->fonts[i], FC_WEIGHT, 0, &weight) == FcResultMatch)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
g_string_append_printf (xml,
|
||||
"<edit name=\"index\" mode=\"assign\" binding=\"strong\"><int>%i</int></edit>",
|
||||
index);
|
||||
|
||||
g_string_append (xml, "</match>\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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue