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.
This commit is contained in:
Jehan
2013-08-31 03:16:44 +12:00
parent 30a389866a
commit 2aabbbd9c7
5 changed files with 75 additions and 10 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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;