[gimp] Bug 662787 - Segfaults when trying to set a large text size



commit 2aabbbd9c733a9078d08b15bedef6e9adae1031f
Author: Jehan <jehan girinstud io>
Date:   Sat Aug 31 03:16:44 2013 +1200

    Bug 662787 - Segfaults when trying to set a large text size
    
    If a font size is too big for cairo or pango to deal with, nicely back
    up from rendering and alert the user via an error dialog.

 app/text/gimptext-vectors.c |    9 ++++++++-
 app/text/gimptextlayer.c    |   24 ++++++++++++++++++++++--
 app/text/gimptextlayout.c   |   41 ++++++++++++++++++++++++++++++++++++-----
 app/text/gimptextlayout.h   |    3 ++-
 app/tools/gimptexttool.c    |    8 +++++++-
 5 files changed, 75 insertions(+), 10 deletions(-)
---
diff --git a/app/text/gimptext-vectors.c b/app/text/gimptext-vectors.c
index e7ef488..600c967 100644
--- a/app/text/gimptext-vectors.c
+++ b/app/text/gimptext-vectors.c
@@ -26,6 +26,7 @@
 
 #include "text-types.h"
 
+#include "core/gimp.h"
 #include "core/gimpimage.h"
 
 #include "vectors/gimpbezierstroke.h"
@@ -69,6 +70,7 @@ gimp_text_vectors_new (GimpImage *image,
       cairo_t         *cr;
       gdouble          xres;
       gdouble          yres;
+      GError          *error = NULL;
 
       if (text->text)
         gimp_object_set_name_safe (GIMP_OBJECT (vectors), text->text);
@@ -80,7 +82,12 @@ gimp_text_vectors_new (GimpImage *image,
 
       gimp_image_get_resolution (image, &xres, &yres);
 
-      layout = gimp_text_layout_new (text, xres, yres);
+      layout = gimp_text_layout_new (text, xres, yres, &error);
+      if (error)
+        {
+          gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_ERROR, error->message);
+          g_error_free (error);
+        }
       gimp_text_layout_render (layout, cr, text->base_dir, TRUE);
       g_object_unref (layout);
 
diff --git a/app/text/gimptextlayer.c b/app/text/gimptextlayer.c
index bc85a04..0097d33 100644
--- a/app/text/gimptextlayer.c
+++ b/app/text/gimptextlayer.c
@@ -614,6 +614,7 @@ gimp_text_layer_render (GimpTextLayer *layer)
   gdouble         yres;
   gint            width;
   gint            height;
+  GError         *error = NULL;
 
   if (! layer->text)
     return FALSE;
@@ -632,7 +633,12 @@ gimp_text_layer_render (GimpTextLayer *layer)
 
   gimp_image_get_resolution (image, &xres, &yres);
 
-  layout = gimp_text_layout_new (layer->text, xres, yres);
+  layout = gimp_text_layout_new (layer->text, xres, yres, &error);
+  if (error)
+    {
+      gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_ERROR, error->message);
+      g_error_free (error);
+    }
 
   g_object_freeze_notify (G_OBJECT (drawable));
 
@@ -693,7 +699,8 @@ gimp_text_layer_render (GimpTextLayer *layer)
         }
     }
 
-  gimp_text_layer_render_layout (layer, layout);
+  if (width > 0 && height > 0)
+    gimp_text_layer_render_layout (layer, layout);
 
   g_object_unref (layout);
 
@@ -713,6 +720,7 @@ gimp_text_layer_render_layout (GimpTextLayer  *layer,
   cairo_surface_t *surface;
   gint             width;
   gint             height;
+  cairo_status_t   status;
 
   g_return_if_fail (gimp_drawable_has_alpha (drawable));
 
@@ -720,6 +728,18 @@ gimp_text_layer_render_layout (GimpTextLayer  *layer,
   height = gimp_item_get_height (item);
 
   surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+  status = cairo_surface_status (surface);
+
+  if (status != CAIRO_STATUS_SUCCESS)
+    {
+      GimpImage *image = gimp_item_get_image (item);
+
+      gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_ERROR,
+                            _("Your text cannot be rendered. It is likely too big. "
+                              "Please make it shorter or use a smaller font."));
+      cairo_surface_destroy (surface);
+      return;
+    }
 
   cr = cairo_create (surface);
   gimp_text_layout_render (layout, cr, layer->text->base_dir, FALSE);
diff --git a/app/text/gimptextlayout.c b/app/text/gimptextlayout.c
index c4dc0c8..02c43ad 100644
--- a/app/text/gimptextlayout.c
+++ b/app/text/gimptextlayout.c
@@ -32,9 +32,12 @@
 
 #include "text-types.h"
 
+#include "core/gimperror.h"
+
 #include "gimptext.h"
 #include "gimptextlayout.h"
 
+#include "gimp-intl.h"
 
 struct _GimpTextLayout
 {
@@ -51,7 +54,8 @@ struct _GimpTextLayout
 static void           gimp_text_layout_finalize   (GObject        *object);
 
 static void           gimp_text_layout_position   (GimpTextLayout *layout);
-static void           gimp_text_layout_set_markup (GimpTextLayout *layout);
+static void           gimp_text_layout_set_markup (GimpTextLayout *layout,
+                                                   GError        **error);
 
 static PangoContext * gimp_text_get_pango_context (GimpText       *text,
                                                    gdouble         xres,
@@ -101,7 +105,8 @@ gimp_text_layout_finalize (GObject *object)
 GimpTextLayout *
 gimp_text_layout_new (GimpText  *text,
                       gdouble    xres,
-                      gdouble    yres)
+                      gdouble    yres,
+                      GError   **error)
 {
   GimpTextLayout       *layout;
   PangoContext         *context;
@@ -136,7 +141,7 @@ gimp_text_layout_new (GimpText  *text,
   pango_layout_set_font_description (layout->layout, font_desc);
   pango_font_description_free (font_desc);
 
-  gimp_text_layout_set_markup (layout);
+  gimp_text_layout_set_markup (layout, error);
 
   switch (text->justify)
     {
@@ -510,7 +515,8 @@ gimp_text_layout_apply_tags (GimpTextLayout *layout,
 }
 
 static void
-gimp_text_layout_set_markup (GimpTextLayout *layout)
+gimp_text_layout_set_markup (GimpTextLayout  *layout,
+                             GError         **error)
 {
   GimpText *text      = layout->text;
   gchar    *open_tag  = NULL;
@@ -550,7 +556,32 @@ gimp_text_layout_set_markup (GimpTextLayout *layout)
   g_free (tagged);
   g_free (close_tag);
 
-  pango_layout_set_markup (layout->layout, markup, -1);
+  if (pango_parse_markup (markup, -1, 0, NULL, NULL, NULL, error) == FALSE)
+    {
+      if (error && *error                       &&
+          (*error)->domain == G_MARKUP_ERROR    &&
+          (*error)->code == G_MARKUP_ERROR_INVALID_CONTENT)
+        {
+          /* Errors from pango lib are not accurate enough.
+           * Other possible error codes are: G_MARKUP_ERROR_UNKNOWN_ELEMENT
+           * and G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, which likely indicate a bug
+           * in GIMP code or a pango library version issue.
+           * G_MARKUP_ERROR_INVALID_CONTENT on the other hand likely indicates
+           * size/color/style/weight/variant/etc. value issue. Font size is the
+           * only free text in GIMP GUI so we assume that must be it.
+           * Also we output a custom message because pango's error->message is
+           * too technical (telling of <span> tags, not using user's font size
+           * unit, and such). */
+          g_error_free (*error);
+          *error = NULL;
+          g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
+                               _("The new text layout cannot be generated. "
+                                 "Most likely the font size is too big."));
+        }
+    }
+  else
+    pango_layout_set_markup (layout->layout, markup, -1);
+
   g_free (markup);
 }
 
diff --git a/app/text/gimptextlayout.h b/app/text/gimptextlayout.h
index fdb8a3d..510b039 100644
--- a/app/text/gimptextlayout.h
+++ b/app/text/gimptextlayout.h
@@ -39,7 +39,8 @@ GType            gimp_text_layout_get_type             (void) G_GNUC_CONST;
 
 GimpTextLayout * gimp_text_layout_new                  (GimpText       *text,
                                                         gdouble         xres,
-                                                        gdouble         yres);
+                                                        gdouble         yres,
+                                                        GError        **error);
 gboolean         gimp_text_layout_get_size             (GimpTextLayout *layout,
                                                         gint           *width,
                                                         gint           *heigth);
diff --git a/app/tools/gimptexttool.c b/app/tools/gimptexttool.c
index 508b08c..ed6fa26 100644
--- a/app/tools/gimptexttool.c
+++ b/app/tools/gimptexttool.c
@@ -1764,11 +1764,17 @@ gimp_text_tool_ensure_layout (GimpTextTool *text_tool)
       GimpImage *image = gimp_item_get_image (GIMP_ITEM (text_tool->layer));
       gdouble    xres;
       gdouble    yres;
+      GError    *error = NULL;
 
       gimp_image_get_resolution (image, &xres, &yres);
 
       text_tool->layout = gimp_text_layout_new (text_tool->layer->text,
-                                                xres, yres);
+                                                xres, yres, &error);
+      if (error)
+        {
+          gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_ERROR, error->message);
+          g_error_free (error);
+        }
     }
 
   return text_tool->layout != NULL;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]