(De)Serialize fonts in pango markup
This commit is contained in:
parent
7be3f56f5c
commit
899dee5926
3 changed files with 219 additions and 2 deletions
|
|
@ -26,6 +26,7 @@
|
|||
#include <cairo.h>
|
||||
#include <gegl.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <pango/pango.h>
|
||||
|
||||
#include "libgimpbase/gimpbase.h"
|
||||
#include "libgimpcolor/gimpcolor.h"
|
||||
|
|
@ -82,19 +83,76 @@ gimp_text_from_parasite (const GimpParasite *parasite,
|
|||
parasite_data = (gchar *) gimp_parasite_get_data (parasite, ¶site_data_size);
|
||||
if (parasite_data)
|
||||
{
|
||||
gboolean is_old = !g_str_has_prefix (strstr (parasite_data, "\")\n(font"), "\")\n(font \"GimpFont\"");
|
||||
gboolean is_old = strstr (parasite_data, "\"GimpFont\"") == NULL;
|
||||
gboolean has_markup = g_str_has_prefix (parasite_data, "(markup ");
|
||||
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.
|
||||
* And more importantly, fonts in the markup are extracted into their own fields for deserialization.
|
||||
*/
|
||||
if (is_old)
|
||||
{
|
||||
new_data = g_string_new (parasite_data);
|
||||
g_string_replace (new_data, "\")\n(font", "\")\n(font \"GimpFont\"", 1);
|
||||
|
||||
if (has_markup)
|
||||
{
|
||||
PangoAttrList *attr_list;
|
||||
gchar *desc;
|
||||
guint length;
|
||||
GSList *list = NULL;
|
||||
GSList *fonts = NULL;
|
||||
GString *markup_fonts = g_string_new (NULL);
|
||||
glong markup_start_pos = strstr (parasite_data, "\"<") - parasite_data + 1;
|
||||
glong markup_end_pos = strstr (parasite_data, ">\")") - parasite_data + 1;
|
||||
gchar *markup_str = g_utf8_substring (parasite_data,
|
||||
markup_start_pos,
|
||||
markup_end_pos);
|
||||
GString *markup = g_string_new (markup_str);
|
||||
|
||||
g_string_replace (markup, "\\\"", "\"", 0);
|
||||
pango_parse_markup (markup->str, -1, 0, &attr_list, NULL, NULL, NULL);
|
||||
|
||||
list = pango_attr_list_get_attributes (attr_list);
|
||||
length = g_slist_length (list);
|
||||
|
||||
for (guint i = 0; i < length; ++i)
|
||||
{
|
||||
PangoAttrFontDesc *attr_font_desc = pango_attribute_as_font_desc ((PangoAttribute*)g_slist_nth_data (list, i));
|
||||
|
||||
if (attr_font_desc != NULL)
|
||||
{
|
||||
desc = pango_font_description_to_string (attr_font_desc->desc);
|
||||
|
||||
if (g_slist_find_custom (fonts, (gconstpointer) desc, g_str_equal) == NULL)
|
||||
{
|
||||
fonts = g_slist_prepend (fonts, (gpointer) desc);
|
||||
/*duplicate font name to making parsing easier when deserializing*/
|
||||
g_string_append_printf (markup_fonts,
|
||||
"\n\"%s\" \"%s\"",
|
||||
desc, desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_free (desc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
g_slist_free_full (fonts, (GDestroyNotify) g_free);
|
||||
g_slist_free_full (list, (GDestroyNotify) pango_attribute_destroy);
|
||||
pango_attr_list_unref (attr_list);
|
||||
|
||||
g_string_insert (new_data, markup_end_pos + 1, markup_fonts->str);
|
||||
|
||||
g_free (markup_str);
|
||||
g_string_free (markup_fonts, TRUE);
|
||||
g_string_free (markup, TRUE);
|
||||
}
|
||||
|
||||
new_parasite = gimp_parasite_new (gimp_parasite_get_name (parasite),
|
||||
gimp_parasite_get_flags (parasite),
|
||||
new_data->len+1,
|
||||
|
|
|
|||
|
|
@ -781,6 +781,91 @@ gimp_text_serialize_property (GimpConfig *config,
|
|||
|
||||
gimp_config_writer_close (writer);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (property_id == PROP_MARKUP)
|
||||
{
|
||||
gchar *markup = (gchar*)g_value_get_string (value);
|
||||
GRegex *regex;
|
||||
GimpText *text;
|
||||
GimpContainer *container;
|
||||
PangoAttrList *attr_list;
|
||||
GimpFont *font;
|
||||
guint length;
|
||||
GSList *list = NULL;
|
||||
GSList *fonts = NULL;
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_TEXT (config), FALSE);
|
||||
|
||||
if (markup == NULL)
|
||||
return FALSE;
|
||||
|
||||
text = GIMP_TEXT (config);
|
||||
container = gimp_data_factory_get_container (text->gimp->font_factory);
|
||||
|
||||
/*lookupname format is "gimpfont%d" we keep only the "font%d" part
|
||||
* this is to avoid problems when deserializing
|
||||
* e.g. if there are 2 fonts with lookupname gimpfont17 and gimpfont23
|
||||
* we might replace the first with a font whose lookupname is gimpfont23,
|
||||
* and we might replace the original gimpfont23 with say gimpfont29
|
||||
* this means that all occurences of gimpfont23 turned into gimpfont29
|
||||
*/
|
||||
regex = g_regex_new ("\"gimpfont(\\d+)\"", 0, 0, NULL);
|
||||
markup = g_regex_replace (regex, markup, -1, 0, "\"font\\1\"", 0, NULL);
|
||||
|
||||
gimp_config_writer_open (writer, "markup");
|
||||
gimp_config_writer_string (writer, markup);
|
||||
|
||||
pango_parse_markup (markup, -1, 0, &attr_list, NULL, NULL, NULL);
|
||||
|
||||
list = pango_attr_list_get_attributes (attr_list);
|
||||
length = g_slist_length (list);
|
||||
|
||||
for (guint i = 0; i < length; ++i)
|
||||
{
|
||||
PangoAttrFontDesc *attr_font_desc = pango_attribute_as_font_desc ((PangoAttribute*)g_slist_nth_data (list, i));
|
||||
|
||||
if (attr_font_desc != NULL)
|
||||
{
|
||||
gchar *altered_font_name = pango_font_description_to_string (attr_font_desc->desc);
|
||||
gchar *font_name = g_strdup_printf ("gimp%s", altered_font_name);
|
||||
|
||||
if (g_slist_find_custom (fonts, (gconstpointer) font_name, g_str_equal) == NULL)
|
||||
{
|
||||
fonts = g_slist_prepend (fonts, (gpointer) font_name);
|
||||
|
||||
font = GIMP_FONT (gimp_container_search (container,
|
||||
(GimpContainerSearchFunc) gimp_font_match_by_lookup_name,
|
||||
(gpointer) font_name));
|
||||
|
||||
gimp_config_writer_open (writer, "markupfont");
|
||||
/*lookupname format is "font%d" we keep only the "font%d" (see the above comment)*/
|
||||
gimp_config_writer_string (writer, font_name+4);
|
||||
|
||||
gimp_config_writer_open (writer, "font");
|
||||
GIMP_CONFIG_GET_IFACE (GIMP_CONFIG (font))->serialize (GIMP_CONFIG (font),
|
||||
writer,
|
||||
NULL);
|
||||
gimp_config_writer_close (writer);
|
||||
gimp_config_writer_close (writer);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
g_free (font_name);
|
||||
}
|
||||
g_free (altered_font_name);
|
||||
}
|
||||
}
|
||||
|
||||
gimp_config_writer_close (writer);
|
||||
|
||||
g_slist_free_full (fonts, (GDestroyNotify) g_free);
|
||||
g_slist_free_full (list, (GDestroyNotify) pango_attribute_destroy);
|
||||
pango_attr_list_unref (attr_list);
|
||||
g_free (markup);
|
||||
g_regex_unref (regex);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -836,6 +921,80 @@ gimp_text_deserialize_property (GimpConfig *object,
|
|||
return TRUE;
|
||||
}
|
||||
}
|
||||
else if (property_id == PROP_MARKUP)
|
||||
{
|
||||
gchar *markup;
|
||||
GString *markup_str;
|
||||
GimpFont *dummy_object = g_object_new (GIMP_TYPE_FONT, NULL);
|
||||
|
||||
gimp_scanner_parse_string (scanner, &markup);
|
||||
|
||||
markup_str = g_string_new (markup);
|
||||
|
||||
/* This is for backward compatibility with older xcf files.*/
|
||||
if (g_scanner_peek_next_token (scanner) == G_TOKEN_STRING)
|
||||
while (g_scanner_peek_next_token (scanner) == G_TOKEN_STRING)
|
||||
{
|
||||
gchar *markup_fontname;
|
||||
gchar *escaped_markup_fontname;
|
||||
gchar *actual_font_lookupname;
|
||||
GimpFont *font;
|
||||
|
||||
gimp_scanner_parse_string (scanner, &markup_fontname);
|
||||
|
||||
font = GIMP_FONT (GIMP_CONFIG_GET_IFACE (dummy_object)->deserialize_create (GIMP_TYPE_FONT,
|
||||
scanner,
|
||||
-1,
|
||||
NULL));
|
||||
escaped_markup_fontname = g_strdup_printf ("\"%s\"", markup_fontname);
|
||||
actual_font_lookupname = g_strdup_printf ("\"%s\"", gimp_font_get_lookup_name (font));
|
||||
g_string_replace (markup_str, escaped_markup_fontname, actual_font_lookupname, 0);
|
||||
|
||||
g_free (markup_fontname);
|
||||
g_free (escaped_markup_fontname);
|
||||
g_free (actual_font_lookupname);
|
||||
g_object_unref (font);
|
||||
}
|
||||
|
||||
else
|
||||
while (g_scanner_peek_next_token (scanner) == G_TOKEN_LEFT_PAREN)
|
||||
{
|
||||
gchar *lookupname;
|
||||
gchar *escaped_lookupname;
|
||||
gchar *actual_font_lookupname;
|
||||
GimpFont *font;
|
||||
|
||||
g_scanner_get_next_token (scanner); /* ( */
|
||||
g_scanner_get_next_token (scanner); /* "lookupname" */
|
||||
gimp_scanner_parse_string (scanner, &lookupname);
|
||||
|
||||
g_scanner_get_next_token (scanner); /* ) */
|
||||
g_scanner_get_next_token (scanner); /* font */
|
||||
|
||||
font = GIMP_FONT (GIMP_CONFIG_GET_IFACE (dummy_object)->deserialize_create (GIMP_TYPE_FONT,
|
||||
scanner,
|
||||
-1,
|
||||
NULL));
|
||||
g_scanner_get_next_token (scanner); /* ) */
|
||||
g_scanner_get_next_token (scanner); /* ) */
|
||||
|
||||
escaped_lookupname = g_strdup_printf ("\"%s\"", lookupname);
|
||||
actual_font_lookupname = g_strdup_printf ("\"%s\"", gimp_font_get_lookup_name (font));
|
||||
g_string_replace (markup_str, escaped_lookupname, actual_font_lookupname, 0);
|
||||
|
||||
g_free (lookupname);
|
||||
g_free (escaped_lookupname);
|
||||
g_free (actual_font_lookupname);
|
||||
g_object_unref (font);
|
||||
}
|
||||
|
||||
g_value_set_string (value, markup_str->str);
|
||||
|
||||
g_object_unref (dummy_object);
|
||||
g_string_free (markup_str, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -290,7 +290,7 @@ gimp_text_tool_constructed (GObject *object)
|
|||
|
||||
G_OBJECT_CLASS (parent_class)->constructed (object);
|
||||
|
||||
text_tool->proxy = g_object_new (GIMP_TYPE_TEXT, NULL);
|
||||
text_tool->proxy = g_object_new (GIMP_TYPE_TEXT, "gimp", tool->tool_info->gimp, NULL);
|
||||
|
||||
gimp_text_options_connect_text (options, text_tool->proxy);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue