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



commit c79e7f5e8755e66696b98628eb9b555e24c7a4eb
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.
    (cherry picked from commit 2aabbbd9c733a9078d08b15bedef6e9adae1031f)

 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 d47a703..fb84aaf 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 8984c76..58ccab5 100644
--- a/app/text/gimptextlayer.c
+++ b/app/text/gimptextlayer.c
@@ -567,6 +567,7 @@ gimp_text_layer_render (GimpTextLayer *layer)
   gdouble         yres;
   gint            width;
   gint            height;
+  GError         *error = NULL;
 
   if (! layer->text)
     return FALSE;
@@ -585,7 +586,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));
 
@@ -645,7 +651,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);
 
@@ -671,6 +678,7 @@ gimp_text_layer_render_layout (GimpTextLayer  *layer,
   gint             width;
   gint             height;
   gpointer         pr;
+  cairo_status_t   status;
 
   g_return_if_fail (gimp_drawable_has_alpha (drawable));
 
@@ -678,6 +686,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 06161e5..5266bc8 100644
--- a/app/text/gimptextlayout.c
+++ b/app/text/gimptextlayout.c
@@ -31,9 +31,12 @@
 
 #include "text-types.h"
 
+#include "core/gimperror.h"
+
 #include "gimptext.h"
 #include "gimptextlayout.h"
 
+#include "gimp-intl.h"
 
 struct _GimpTextLayout
 {
@@ -50,7 +53,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,
@@ -100,7 +104,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;
@@ -135,7 +140,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)
     {
@@ -509,7 +514,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;
@@ -549,7 +555,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 9160396..a6ca9ec 100644
--- a/app/tools/gimptexttool.c
+++ b/app/tools/gimptexttool.c
@@ -1765,11 +1765,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]