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:
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user