app, libgimp, pdb, plug-ins: GimpText* using GeglColor.

One of the big improvement in this commit is that text layers are now much
better at space accuracy. They were already space-aware, yet rendered as sRGB u8
only before being converted to the image's space. It means that text layers had
the following limitations:

* Any color out of sRGB gamut were trimmed.
* Precision was always 8-bit (even if the image was high-bit depth).

Now GimpTextLayout keeps track of its source space (for RGB and CMYK only, this
won't be as easy when we will support more backend, since Cairo has only RGB
support for image data) and the image TRC (in case it bypasses the color space's
TRB) and it draws within this gamut and space.
It means first that we are not limited to sRGB colors; we will draw text main
color in the full image gamut, with still 2 remaining limitations:

* Unbounded colors are impossible because Pango format (to color text) uses
  hexadecimal (so even with half/float images, you can't draw out-of-gamut text
  unfortunately).
* Main color precision is still 8-bit, yet a tiny bit better than before as we
  at least follow TRC (so we avoid some of the precision loss when converting,
  even though the bit-depth is still the biggest loss).

The outline color on the other hand is drawn through Cairo API entirely, in
float. This means that the outline color will now be without any precision loss.

Note that this depends on CAIRO_FORMAT_RGBA128F which is only available since
Cairo 1.17.2 which is not in Debian bookworm (our current baseline for GIMP
3.0). It means that the old precision will still happen with older Cairo
version, as determined by #if code at compilation.
This commit is contained in:
Jehan 2023-11-17 22:36:31 +01:00
parent a60b16f497
commit e992ca3e51
24 changed files with 276 additions and 173 deletions

View file

@ -815,20 +815,6 @@ gimp_image_get_color_transform_to_srgb_u8 (GimpImage *image)
return private->transform_to_srgb_u8; return private->transform_to_srgb_u8;
} }
GimpColorTransform *
gimp_image_get_color_transform_from_srgb_u8 (GimpImage *image)
{
GimpImagePrivate *private;
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
private = GIMP_IMAGE_GET_PRIVATE (image);
gimp_image_create_color_transforms (image);
return private->transform_from_srgb_u8;
}
GimpColorTransform * GimpColorTransform *
gimp_image_get_color_transform_to_srgb_double (GimpImage *image) gimp_image_get_color_transform_to_srgb_double (GimpImage *image)
{ {
@ -938,7 +924,6 @@ _gimp_image_free_color_transforms (GimpImage *image)
GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image); GimpImagePrivate *private = GIMP_IMAGE_GET_PRIVATE (image);
g_clear_object (&private->transform_to_srgb_u8); g_clear_object (&private->transform_to_srgb_u8);
g_clear_object (&private->transform_from_srgb_u8);
g_clear_object (&private->transform_to_srgb_double); g_clear_object (&private->transform_to_srgb_double);
g_clear_object (&private->transform_from_srgb_double); g_clear_object (&private->transform_from_srgb_double);
@ -1162,14 +1147,6 @@ gimp_image_create_color_transforms (GimpImage *image)
GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL, GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
flags); flags);
private->transform_from_srgb_u8 =
gimp_color_transform_new (srgb_profile,
babl_format ("R'G'B'A u8"),
private->color_profile,
gimp_image_get_layer_format (image, TRUE),
GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL,
flags);
private->transform_to_srgb_double = private->transform_to_srgb_double =
gimp_color_transform_new (private->color_profile, gimp_color_transform_new (private->color_profile,
gimp_image_get_layer_format (image, TRUE), gimp_image_get_layer_format (image, TRUE),

View file

@ -110,8 +110,6 @@ void gimp_image_import_color_profile (GimpImage *ima
GimpColorTransform * gimp_image_get_color_transform_to_srgb_u8 GimpColorTransform * gimp_image_get_color_transform_to_srgb_u8
(GimpImage *image); (GimpImage *image);
GimpColorTransform * gimp_image_get_color_transform_from_srgb_u8
(GimpImage *image);
GimpColorTransform * gimp_image_get_color_transform_to_srgb_double GimpColorTransform * gimp_image_get_color_transform_to_srgb_double
(GimpImage *image); (GimpImage *image);

View file

@ -74,7 +74,6 @@ struct _GimpImagePrivate
/* Cached color transforms: from layer to sRGB u8 and double, and back */ /* Cached color transforms: from layer to sRGB u8 and double, and back */
gboolean color_transforms_created; gboolean color_transforms_created;
GimpColorTransform *transform_to_srgb_u8; GimpColorTransform *transform_to_srgb_u8;
GimpColorTransform *transform_from_srgb_u8;
GimpColorTransform *transform_to_srgb_double; GimpColorTransform *transform_to_srgb_double;
GimpColorTransform *transform_from_srgb_double; GimpColorTransform *transform_from_srgb_double;

View file

@ -389,17 +389,14 @@ gimp_display_shell_dnd_fill (GimpDisplayShell *shell,
gimp_fill_options_get_style (options) == GIMP_FILL_STYLE_BG_COLOR)) gimp_fill_options_get_style (options) == GIMP_FILL_STYLE_BG_COLOR))
{ {
GeglColor *color; GeglColor *color;
GimpRGB rgb;
if (gimp_fill_options_get_style (options) == GIMP_FILL_STYLE_FG_COLOR) if (gimp_fill_options_get_style (options) == GIMP_FILL_STYLE_FG_COLOR)
color = gimp_context_get_foreground (GIMP_CONTEXT (options)); color = gimp_context_get_foreground (GIMP_CONTEXT (options));
else else
color = gimp_context_get_background (GIMP_CONTEXT (options)); color = gimp_context_get_background (GIMP_CONTEXT (options));
gegl_color_get_rgba_with_space (color, &rgb.r, &rgb.g, &rgb.b, &rgb.a, NULL);
gimp_text_layer_set (iter->data, NULL, gimp_text_layer_set (iter->data, NULL,
"color", &rgb, "color", color,
NULL); NULL);
} }
else else

View file

@ -734,20 +734,20 @@ text_layer_get_color_invoker (GimpProcedure *procedure,
gboolean success = TRUE; gboolean success = TRUE;
GimpValueArray *return_vals; GimpValueArray *return_vals;
GimpTextLayer *layer; GimpTextLayer *layer;
GimpRGB color = { 0.0, 0.0, 0.0, 1.0 }; GeglColor *color = NULL;
layer = g_value_get_object (gimp_value_array_index (args, 0)); layer = g_value_get_object (gimp_value_array_index (args, 0));
if (success) if (success)
{ {
color = gimp_text_layer_get_text (layer)->color; color = gegl_color_duplicate (gimp_text_layer_get_text (layer)->color);
} }
return_vals = gimp_procedure_get_return_values (procedure, success, return_vals = gimp_procedure_get_return_values (procedure, success,
error ? *error : NULL); error ? *error : NULL);
if (success) if (success)
gimp_value_set_rgb (gimp_value_array_index (return_vals, 1), &color); g_value_take_object (gimp_value_array_index (return_vals, 1), color);
return return_vals; return return_vals;
} }
@ -1685,10 +1685,9 @@ register_text_layer_procs (GimpPDB *pdb)
FALSE, FALSE,
GIMP_PARAM_READWRITE)); GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure, gimp_procedure_add_return_value (procedure,
gimp_param_spec_rgb ("color", gegl_param_spec_color ("color",
"color", "color",
"The color of the text.", "The color of the text.",
FALSE,
NULL, NULL,
GIMP_PARAM_READWRITE)); GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure); gimp_pdb_register_procedure (pdb, procedure);

View file

@ -82,7 +82,7 @@ gimp_text_vectors_new (GimpImage *image,
gimp_image_get_resolution (image, &xres, &yres); gimp_image_get_resolution (image, &xres, &yres);
layout = gimp_text_layout_new (text, xres, yres, &error); layout = gimp_text_layout_new (text, image, xres, yres, &error);
if (error) if (error)
{ {
gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_ERROR, error->message); gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_ERROR, error->message);

View file

@ -141,8 +141,8 @@ gimp_text_class_init (GimpTextClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass); GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
GimpRGB black; GeglColor *black = gegl_color_new ("black");
GimpRGB gray; GeglColor *gray = gegl_color_new ("gray");
GimpMatrix2 identity; GimpMatrix2 identity;
gchar *language; gchar *language;
GParamSpec *array_spec; GParamSpec *array_spec;
@ -162,8 +162,6 @@ gimp_text_class_init (GimpTextClass *klass)
gimp_object_class->get_memsize = gimp_text_get_memsize; gimp_object_class->get_memsize = gimp_text_get_memsize;
gimp_rgba_set (&black, 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE);
gimp_rgba_set (&gray, 0.75, 0.75, 0.75, GIMP_OPACITY_OPAQUE);
gimp_matrix2_identity (&identity); gimp_matrix2_identity (&identity);
GIMP_CONFIG_PROP_STRING (object_class, PROP_TEXT, GIMP_CONFIG_PROP_STRING (object_class, PROP_TEXT,
@ -235,10 +233,10 @@ gimp_text_class_init (GimpTextClass *klass)
GIMP_TEXT_DIRECTION_LTR, GIMP_TEXT_DIRECTION_LTR,
GIMP_PARAM_STATIC_STRINGS); GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_RGB (object_class, PROP_COLOR, GIMP_CONFIG_PROP_COLOR (object_class, PROP_COLOR,
"color", "color",
NULL, NULL, NULL, NULL,
FALSE, &black, black,
GIMP_PARAM_STATIC_STRINGS); GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_ENUM (object_class, PROP_OUTLINE, GIMP_CONFIG_PROP_ENUM (object_class, PROP_OUTLINE,
@ -341,9 +339,9 @@ gimp_text_class_init (GimpTextClass *klass)
"outline-pattern", NULL, NULL, "outline-pattern", NULL, NULL,
GIMP_TYPE_PATTERN, GIMP_TYPE_PATTERN,
GIMP_PARAM_STATIC_STRINGS); GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_RGB (object_class, PROP_OUTLINE_FOREGROUND, GIMP_CONFIG_PROP_COLOR (object_class, PROP_OUTLINE_FOREGROUND,
"outline-foreground", NULL, NULL, "outline-foreground", NULL, NULL,
FALSE, &gray, gray,
GIMP_PARAM_STATIC_STRINGS); GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_OUTLINE_WIDTH, GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_OUTLINE_WIDTH,
"outline-width", NULL, NULL, "outline-width", NULL, NULL,
@ -394,6 +392,8 @@ gimp_text_class_init (GimpTextClass *klass)
GIMP_PARAM_READWRITE | GIMP_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY)); G_PARAM_CONSTRUCT_ONLY));
g_object_unref (black);
g_object_unref (gray);
} }
static void static void
@ -417,6 +417,8 @@ gimp_text_finalize (GObject *object)
g_clear_pointer (&text->markup, g_free); g_clear_pointer (&text->markup, g_free);
g_clear_pointer (&text->language, g_free); g_clear_pointer (&text->language, g_free);
g_clear_object (&text->font); g_clear_object (&text->font);
g_clear_object (&text->color);
g_clear_object (&text->outline_foreground);
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
@ -462,7 +464,7 @@ gimp_text_get_property (GObject *object,
g_value_set_string (value, text->language); g_value_set_string (value, text->language);
break; break;
case PROP_COLOR: case PROP_COLOR:
g_value_set_boxed (value, &text->color); g_value_set_object (value, text->color);
break; break;
case PROP_OUTLINE: case PROP_OUTLINE:
g_value_set_enum (value, text->outline); g_value_set_enum (value, text->outline);
@ -504,7 +506,7 @@ gimp_text_get_property (GObject *object,
g_value_set_enum (value, text->outline_style); g_value_set_enum (value, text->outline_style);
break; break;
case PROP_OUTLINE_FOREGROUND: case PROP_OUTLINE_FOREGROUND:
g_value_set_boxed (value, &text->outline_foreground); g_value_set_object (value, text->outline_foreground);
break; break;
case PROP_OUTLINE_PATTERN: case PROP_OUTLINE_PATTERN:
g_value_set_object (value, text->outline_pattern); g_value_set_object (value, text->outline_pattern);
@ -555,7 +557,6 @@ gimp_text_set_property (GObject *object,
GParamSpec *pspec) GParamSpec *pspec)
{ {
GimpText *text = GIMP_TEXT (object); GimpText *text = GIMP_TEXT (object);
GimpRGB *color;
GimpMatrix2 *matrix; GimpMatrix2 *matrix;
switch (property_id) switch (property_id)
@ -609,8 +610,7 @@ gimp_text_set_property (GObject *object,
text->base_dir = g_value_get_enum (value); text->base_dir = g_value_get_enum (value);
break; break;
case PROP_COLOR: case PROP_COLOR:
color = g_value_get_boxed (value); g_set_object (&text->color, g_value_get_object (value));;
text->color = *color;
break; break;
case PROP_OUTLINE: case PROP_OUTLINE:
text->outline = g_value_get_enum (value); text->outline = g_value_get_enum (value);
@ -653,8 +653,7 @@ gimp_text_set_property (GObject *object,
text->outline_style = g_value_get_enum (value); text->outline_style = g_value_get_enum (value);
break; break;
case PROP_OUTLINE_FOREGROUND: case PROP_OUTLINE_FOREGROUND:
color = g_value_get_boxed (value); g_set_object (&text->outline_foreground, g_value_get_object (value));;
text->outline_foreground = *color;
break; break;
case PROP_OUTLINE_PATTERN: case PROP_OUTLINE_PATTERN:
{ {

View file

@ -49,10 +49,10 @@ struct _GimpText
gboolean kerning; gboolean kerning;
gchar *language; gchar *language;
GimpTextDirection base_dir; GimpTextDirection base_dir;
GimpRGB color; GeglColor *color;
GimpCustomStyle outline_style; GimpCustomStyle outline_style;
GimpPattern *outline_pattern; GimpPattern *outline_pattern;
GimpRGB outline_foreground; GeglColor *outline_foreground;
gdouble outline_width; gdouble outline_width;
GimpCapStyle outline_cap_style; GimpCapStyle outline_cap_style;
GimpJoinStyle outline_join_style; GimpJoinStyle outline_join_style;

View file

@ -53,7 +53,6 @@
#include "gimptext.h" #include "gimptext.h"
#include "gimptextlayer.h" #include "gimptextlayer.h"
#include "gimptextlayer-transform.h"
#include "gimptextlayout.h" #include "gimptextlayout.h"
#include "gimptextlayout-render.h" #include "gimptextlayout-render.h"
@ -725,7 +724,7 @@ gimp_text_layer_render (GimpTextLayer *layer)
gimp_image_get_resolution (image, &xres, &yres); gimp_image_get_resolution (image, &xres, &yres);
layout = gimp_text_layout_new (layer->text, xres, yres, &error); layout = gimp_text_layout_new (layer->text, image, xres, yres, &error);
if (error) if (error)
{ {
gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_ERROR, error->message); gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_ERROR, error->message);
@ -927,9 +926,8 @@ gimp_text_layer_render_layout (GimpTextLayer *layer,
{ {
GimpDrawable *drawable = GIMP_DRAWABLE (layer); GimpDrawable *drawable = GIMP_DRAWABLE (layer);
GimpItem *item = GIMP_ITEM (layer); GimpItem *item = GIMP_ITEM (layer);
GimpImage *image = gimp_item_get_image (item); const Babl *format;
GeglBuffer *buffer; GeglBuffer *buffer;
GimpColorTransform *transform;
cairo_t *cr; cairo_t *cr;
cairo_surface_t *surface; cairo_surface_t *surface;
gint width; gint width;
@ -941,7 +939,11 @@ gimp_text_layer_render_layout (GimpTextLayer *layer,
width = gimp_item_get_width (item); width = gimp_item_get_width (item);
height = gimp_item_get_height (item); height = gimp_item_get_height (item);
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 2)
surface = cairo_image_surface_create (CAIRO_FORMAT_RGBA128F, width, height);
#else
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
#endif
status = cairo_surface_status (surface); status = cairo_surface_status (surface);
if (status != CAIRO_STATUS_SUCCESS) if (status != CAIRO_STATUS_SUCCESS)
@ -968,7 +970,6 @@ gimp_text_layer_render_layout (GimpTextLayer *layer,
if (layer->text->outline != GIMP_TEXT_OUTLINE_NONE) if (layer->text->outline != GIMP_TEXT_OUTLINE_NONE)
{ {
GimpText *text = layer->text; GimpText *text = layer->text;
GimpRGB col = text->outline_foreground;
cairo_save (cr); cairo_save (cr);
@ -998,7 +999,16 @@ gimp_text_layer_render_layout (GimpTextLayer *layer,
} }
else else
{ {
cairo_set_source_rgba (cr, col.r, col.g, col.b, col.a); GeglColor *col = text->outline_foreground;
gdouble color[3];
format = gimp_text_layout_get_format (layout, "double");
gegl_color_get_pixel (col, format, color);
/* Text layout can be either grayscale or RGB without alpha. */
if (! babl_space_is_gray (babl_format_get_space (format)))
cairo_set_source_rgba (cr, color[0], color[1], color[2], 1.0);
else
cairo_set_source_rgba (cr, color[0], color[0], color[0], 1.0);
} }
cairo_set_line_width (cr, text->outline_width * 2); cairo_set_line_width (cr, text->outline_width * 2);
@ -1014,23 +1024,29 @@ gimp_text_layer_render_layout (GimpTextLayer *layer,
cairo_surface_flush (surface); cairo_surface_flush (surface);
buffer = gimp_cairo_surface_create_buffer (surface); #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 2)
/* The CAIRO_FORMAT_RGBA128F surface maps to the layout TRC and space. */
transform = gimp_image_get_color_transform_from_srgb_u8 (image); switch (gimp_text_layout_get_trc (layout))
if (transform)
{ {
gimp_color_transform_process_buffer (transform, case GIMP_TRC_LINEAR:
buffer, format = babl_format_with_space ("RGBA float", gimp_text_layout_get_space (layout));
NULL, break;
gimp_drawable_get_buffer (drawable), case GIMP_TRC_NON_LINEAR:
NULL); format = babl_format_with_space ("R'G'B'A float", gimp_text_layout_get_space (layout));
break;
case GIMP_TRC_PERCEPTUAL:
format = babl_format_with_space ("R~G~B~A float", gimp_text_layout_get_space (layout));
break;
default:
g_return_if_reached ();
} }
else #else
{ format = babl_format_with_space ("cairo-ARGB32", gimp_text_layout_get_space (layout));
#endif
buffer = gimp_cairo_surface_create_buffer (surface, format);
gimp_gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, gimp_gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE,
gimp_drawable_get_buffer (drawable), NULL); gimp_drawable_get_buffer (drawable), NULL);
}
g_object_unref (buffer); g_object_unref (buffer);
cairo_surface_destroy (surface); cairo_surface_destroy (surface);

View file

@ -32,7 +32,10 @@
#include "text-types.h" #include "text-types.h"
#include "gegl/gimp-babl.h"
#include "core/gimperror.h" #include "core/gimperror.h"
#include "core/gimpimage.h"
#include "gimpfont.h" #include "gimpfont.h"
@ -50,6 +53,8 @@ struct _GimpTextLayout
gdouble yres; gdouble yres;
PangoLayout *layout; PangoLayout *layout;
PangoRectangle extents; PangoRectangle extents;
const Babl *layout_space;
GimpTRCType layout_trc;
}; };
@ -106,17 +111,20 @@ gimp_text_layout_finalize (GObject *object)
GimpTextLayout * GimpTextLayout *
gimp_text_layout_new (GimpText *text, gimp_text_layout_new (GimpText *text,
GimpImage *target_image,
gdouble xres, gdouble xres,
gdouble yres, gdouble yres,
GError **error) GError **error)
{ {
GimpTextLayout *layout; GimpTextLayout *layout;
const Babl *target_space;
PangoContext *context; PangoContext *context;
PangoFontDescription *font_desc; PangoFontDescription *font_desc;
PangoAlignment alignment = PANGO_ALIGN_LEFT; PangoAlignment alignment = PANGO_ALIGN_LEFT;
gint size; gint size;
g_return_val_if_fail (GIMP_IS_TEXT (text), NULL); g_return_val_if_fail (GIMP_IS_TEXT (text), NULL);
g_return_val_if_fail (GIMP_IS_IMAGE (target_image), NULL);
font_desc = pango_font_description_from_string (gimp_font_get_lookup_name (text->font)); font_desc = pango_font_description_from_string (gimp_font_get_lookup_name (text->font));
g_return_val_if_fail (font_desc != NULL, NULL); g_return_val_if_fail (font_desc != NULL, NULL);
@ -141,6 +149,25 @@ gimp_text_layout_new (GimpText *text,
pango_layout_set_font_description (layout->layout, font_desc); pango_layout_set_font_description (layout->layout, font_desc);
pango_font_description_free (font_desc); pango_font_description_free (font_desc);
target_space = gimp_image_get_layer_space (target_image);
#if BABL_MINOR_VERSION > 1 || (BABL_MINOR_VERSION == 1 && BABL_MICRO_VERSION >= 107)
if (babl_space_is_rgb (target_space) || babl_space_is_gray (target_space))
#else
if (! babl_space_is_cmyk (target_space))
#endif
layout->layout_space = target_space;
else
layout->layout_space = NULL;
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 2)
layout->layout_trc = gimp_babl_trc (gimp_image_get_precision (target_image));
#else
/* With older Cairo, we just use cairo-ARGB32 with no linear or perceptual
* option.
*/
layout->layout_trc = GIMP_TRC_NON_LINEAR;
#endif
gimp_text_layout_set_markup (layout, error); gimp_text_layout_set_markup (layout, error);
switch (text->justify) switch (text->justify)
@ -221,6 +248,72 @@ gimp_text_layout_new (GimpText *text,
return layout; return layout;
} }
const GimpTRCType
gimp_text_layout_get_trc (GimpTextLayout *layout)
{
g_return_val_if_fail (GIMP_IS_TEXT_LAYOUT (layout), GIMP_TRC_NON_LINEAR);
return layout->layout_trc;
}
const Babl *
gimp_text_layout_get_format (GimpTextLayout *layout,
const gchar *babl_type)
{
const Babl *format;
gchar *format_name;
g_return_val_if_fail (GIMP_IS_TEXT_LAYOUT (layout), NULL);
if (! babl_space_is_gray (layout->layout_space))
{
switch (layout->layout_trc)
{
case GIMP_TRC_LINEAR:
format_name = g_strdup_printf ("RGB %s", babl_type);
break;
case GIMP_TRC_NON_LINEAR:
format_name = g_strdup_printf ("R'G'B' %s", babl_type);
break;
case GIMP_TRC_PERCEPTUAL:
format_name = g_strdup_printf ("R~G~B~ %s", babl_type);
break;
default:
g_return_val_if_reached (NULL);
}
}
else
{
switch (layout->layout_trc)
{
case GIMP_TRC_LINEAR:
format_name = g_strdup_printf ("Y %s", babl_type);
break;
case GIMP_TRC_NON_LINEAR:
format_name = g_strdup_printf ("Y' %s", babl_type);
break;
case GIMP_TRC_PERCEPTUAL:
format_name = g_strdup_printf ("Y~ %s", babl_type);
break;
default:
g_return_val_if_reached (NULL);
}
}
format = babl_format_with_space (format_name, layout->layout_space);
g_free (format_name);
return format;
}
const Babl *
gimp_text_layout_get_space (GimpTextLayout *layout)
{
g_return_val_if_fail (GIMP_IS_TEXT_LAYOUT (layout), NULL);
return layout->layout_space;
}
gboolean gboolean
gimp_text_layout_get_size (GimpTextLayout *layout, gimp_text_layout_get_size (GimpTextLayout *layout,
gint *width, gint *width,
@ -499,17 +592,31 @@ static gchar *
gimp_text_layout_apply_tags (GimpTextLayout *layout, gimp_text_layout_apply_tags (GimpTextLayout *layout,
const gchar *markup) const gchar *markup)
{ {
const Babl *format;
GimpText *text = layout->text; GimpText *text = layout->text;
gchar *result; gchar *result;
guchar color[3];
{ /* Unfortunately Pango markup are very limited, color-wise. Colors are
guchar r, g, b; * written in hexadecimal, so they are u8 as maximum precision, and
* unbounded colors are not accessible.
gimp_rgb_get_uchar (&text->color, &r, &g, &b); * At the very least, what we do is to write color values in the target
* space in the PangoLayout, so that we don't end up stuck to sRGB text
* colors even in images with wider gamut spaces.
*
* Moreover this is limited to RGB and Grayscale spaces. Therefore, images
* with other backends will be limited to the sRGB gamut, for as long as Pango
* do not evolve (or unless we changed our rendering backend).
*/
format = gimp_text_layout_get_format (layout, "u8");
gegl_color_get_pixel (text->color, format, color);
if (! babl_space_is_gray (babl_format_get_space (format)))
result = g_strdup_printf ("<span color=\"#%02x%02x%02x\">%s</span>", result = g_strdup_printf ("<span color=\"#%02x%02x%02x\">%s</span>",
r, g, b, markup); color[0], color[1], color[2], markup);
} else
result = g_strdup_printf ("<span color=\"#%02x%02x%02x\">%s</span>",
color[0], color[0], color[0], markup);
/* Updating font 'locl' (if supported) with 'lang' feature tag */ /* Updating font 'locl' (if supported) with 'lang' feature tag */
if (text->language) if (text->language)
{ {
@ -598,7 +705,9 @@ gimp_text_layout_set_markup (GimpTextLayout *layout,
} }
} }
else else
{
pango_layout_set_markup (layout->layout, markup, -1); pango_layout_set_markup (layout->layout, markup, -1);
}
g_free (markup); g_free (markup);
} }

View file

@ -38,9 +38,16 @@ struct _GimpTextLayoutClass
GType gimp_text_layout_get_type (void) G_GNUC_CONST; GType gimp_text_layout_get_type (void) G_GNUC_CONST;
GimpTextLayout * gimp_text_layout_new (GimpText *text, GimpTextLayout * gimp_text_layout_new (GimpText *text,
GimpImage *target_image,
gdouble xres, gdouble xres,
gdouble yres, gdouble yres,
GError **error); GError **error);
const Babl * gimp_text_layout_get_space (GimpTextLayout *layout);
const GimpTRCType gimp_text_layout_get_trc (GimpTextLayout *layout);
const Babl * gimp_text_layout_get_format (GimpTextLayout *layout,
const gchar *babl_type);
gboolean gimp_text_layout_get_size (GimpTextLayout *layout, gboolean gimp_text_layout_get_size (GimpTextLayout *layout,
gint *width, gint *width,
gint *height); gint *height);

View file

@ -152,10 +152,9 @@ static void
gimp_text_options_class_init (GimpTextOptionsClass *klass) gimp_text_options_class_init (GimpTextOptionsClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass); GObjectClass *object_class = G_OBJECT_CLASS (klass);
GimpRGB gray; GeglColor *gray = gegl_color_new ("gray");
GParamSpec *array_spec; GParamSpec *array_spec;
gimp_rgba_set (&gray, 0.75, 0.75, 0.75, GIMP_OPACITY_OPAQUE);
object_class->finalize = gimp_text_options_finalize; object_class->finalize = gimp_text_options_finalize;
object_class->set_property = gimp_text_options_set_property; object_class->set_property = gimp_text_options_set_property;
object_class->get_property = gimp_text_options_get_property; object_class->get_property = gimp_text_options_get_property;
@ -286,10 +285,10 @@ gimp_text_options_class_init (GimpTextOptionsClass *klass)
GIMP_TYPE_CUSTOM_STYLE, GIMP_TYPE_CUSTOM_STYLE,
GIMP_CUSTOM_STYLE_SOLID_COLOR, GIMP_CUSTOM_STYLE_SOLID_COLOR,
GIMP_PARAM_STATIC_STRINGS); GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_RGB (object_class, PROP_OUTLINE_FOREGROUND, GIMP_CONFIG_PROP_COLOR (object_class, PROP_OUTLINE_FOREGROUND,
"outline-foreground", "outline-foreground",
NULL, NULL, NULL, NULL,
FALSE, &gray, gray,
GIMP_PARAM_STATIC_STRINGS); GIMP_PARAM_STATIC_STRINGS);
GIMP_CONFIG_PROP_OBJECT (object_class, PROP_OUTLINE_PATTERN, GIMP_CONFIG_PROP_OBJECT (object_class, PROP_OUTLINE_PATTERN,
"outline-pattern", "outline-pattern",
@ -349,6 +348,8 @@ gimp_text_options_class_init (GimpTextOptionsClass *klass)
array_spec, array_spec,
GIMP_PARAM_STATIC_STRINGS | GIMP_PARAM_STATIC_STRINGS |
GIMP_CONFIG_PARAM_FLAGS)); GIMP_CONFIG_PARAM_FLAGS));
g_object_unref (gray);
} }
static void static void
@ -365,7 +366,10 @@ gimp_text_options_config_iface_init (GimpConfigInterface *config_iface)
static void static void
gimp_text_options_init (GimpTextOptions *options) gimp_text_options_init (GimpTextOptions *options)
{ {
GeglColor *gray = gegl_color_new ("gray");
options->size_entry = NULL; options->size_entry = NULL;
options->outline_foreground = gray;
} }
static void static void
@ -374,6 +378,7 @@ gimp_text_options_finalize (GObject *object)
GimpTextOptions *options = GIMP_TEXT_OPTIONS (object); GimpTextOptions *options = GIMP_TEXT_OPTIONS (object);
g_clear_pointer (&options->language, g_free); g_clear_pointer (&options->language, g_free);
g_clear_object (&options->outline_foreground);
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
@ -429,7 +434,7 @@ gimp_text_options_get_property (GObject *object,
g_value_set_enum (value, options->outline_style); g_value_set_enum (value, options->outline_style);
break; break;
case PROP_OUTLINE_FOREGROUND: case PROP_OUTLINE_FOREGROUND:
g_value_set_boxed (value, &options->outline_foreground); g_value_set_object (value, options->outline_foreground);
break; break;
case PROP_OUTLINE_PATTERN: case PROP_OUTLINE_PATTERN:
g_value_set_object (value, options->outline_pattern); g_value_set_object (value, options->outline_pattern);
@ -491,7 +496,6 @@ gimp_text_options_set_property (GObject *object,
GParamSpec *pspec) GParamSpec *pspec)
{ {
GimpTextOptions *options = GIMP_TEXT_OPTIONS (object); GimpTextOptions *options = GIMP_TEXT_OPTIONS (object);
GimpRGB *color;
switch (property_id) switch (property_id)
{ {
@ -537,8 +541,7 @@ gimp_text_options_set_property (GObject *object,
options->outline_style = g_value_get_enum (value); options->outline_style = g_value_get_enum (value);
break; break;
case PROP_OUTLINE_FOREGROUND: case PROP_OUTLINE_FOREGROUND:
color = g_value_get_boxed (value); g_set_object (&options->outline_foreground, g_value_get_object (value));;
options->outline_foreground = *color;
break; break;
case PROP_OUTLINE_PATTERN: case PROP_OUTLINE_PATTERN:
{ {
@ -683,17 +686,11 @@ gimp_text_options_notify_color (GimpContext *context,
GParamSpec *pspec, GParamSpec *pspec,
GimpText *text) GimpText *text)
{ {
GeglColor *color;
GimpRGB rgb;
color = gimp_context_get_foreground (context);
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), &rgb);
g_signal_handlers_block_by_func (text, g_signal_handlers_block_by_func (text,
gimp_text_options_notify_text_color, gimp_text_options_notify_text_color,
context); context);
g_object_set (text, "color", &rgb, NULL); g_object_set (text, "color", gimp_context_get_foreground (context), NULL);
g_signal_handlers_unblock_by_func (text, g_signal_handlers_unblock_by_func (text,
gimp_text_options_notify_text_color, gimp_text_options_notify_text_color,
@ -705,18 +702,13 @@ gimp_text_options_notify_text_color (GimpText *text,
GParamSpec *pspec, GParamSpec *pspec,
GimpContext *context) GimpContext *context)
{ {
GeglColor *color = gegl_color_new ("black");
g_signal_handlers_block_by_func (context, g_signal_handlers_block_by_func (context,
gimp_text_options_notify_color, text); gimp_text_options_notify_color, text);
gegl_color_set_rgba_with_space (color, text->color.r, text->color.g, text->color.b, text->color.a, NULL); gimp_context_set_foreground (context, text->color);
gimp_context_set_foreground (context, color);
g_signal_handlers_unblock_by_func (context, g_signal_handlers_unblock_by_func (context,
gimp_text_options_notify_color, text); gimp_text_options_notify_color, text);
g_object_unref (color);
} }
/* This function could live in gimptexttool.c also. /* This function could live in gimptexttool.c also.
@ -727,21 +719,16 @@ gimp_text_options_connect_text (GimpTextOptions *options,
GimpText *text) GimpText *text)
{ {
GimpContext *context; GimpContext *context;
GeglColor *color;
GimpRGB rgb;
g_return_if_fail (GIMP_IS_TEXT_OPTIONS (options)); g_return_if_fail (GIMP_IS_TEXT_OPTIONS (options));
g_return_if_fail (GIMP_IS_TEXT (text)); g_return_if_fail (GIMP_IS_TEXT (text));
context = GIMP_CONTEXT (options); context = GIMP_CONTEXT (options);
color = gimp_context_get_foreground (context);
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), &rgb);
gimp_config_sync (G_OBJECT (options), G_OBJECT (text), 0); gimp_config_sync (G_OBJECT (options), G_OBJECT (text), 0);
g_object_set (text, g_object_set (text,
"color", &rgb, "color", gimp_context_get_foreground (context),
"font", gimp_context_get_font (context), "font", gimp_context_get_font (context),
NULL); NULL);

View file

@ -51,7 +51,7 @@ struct _GimpTextOptions
GimpTextOutline outline; GimpTextOutline outline;
GimpCustomStyle outline_style; GimpCustomStyle outline_style;
GimpRGB outline_foreground; GeglColor *outline_foreground;
GimpPattern *outline_pattern; GimpPattern *outline_pattern;
gdouble outline_width; gdouble outline_width;
GimpUnit outline_unit; GimpUnit outline_unit;

View file

@ -2031,7 +2031,7 @@ gimp_text_tool_ensure_layout (GimpTextTool *text_tool)
gimp_image_get_resolution (image, &xres, &yres); gimp_image_get_resolution (image, &xres, &yres);
text_tool->layout = gimp_text_layout_new (text_tool->layer->text, text_tool->layout = gimp_text_layout_new (text_tool->layer->text,
xres, yres, &error); image, xres, yres, &error);
if (error) if (error)
{ {
gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_ERROR, error->message); gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_ERROR, error->message);

View file

@ -781,12 +781,14 @@ gimp_text_style_editor_set_color (GimpTextStyleEditor *editor,
static void static void
gimp_text_style_editor_set_default_color (GimpTextStyleEditor *editor) gimp_text_style_editor_set_default_color (GimpTextStyleEditor *editor)
{ {
GimpRGB rgb;
g_signal_handlers_block_by_func (editor->color_button, g_signal_handlers_block_by_func (editor->color_button,
gimp_text_style_editor_color_changed, gimp_text_style_editor_color_changed,
editor); editor);
gimp_color_button_set_color (GIMP_COLOR_BUTTON (editor->color_button), gegl_color_get_pixel (editor->text->color, babl_format ("R'G'B'A double"), &rgb);
&editor->text->color); gimp_color_button_set_color (GIMP_COLOR_BUTTON (editor->color_button), &rgb);
g_signal_handlers_unblock_by_func (editor->color_button, g_signal_handlers_unblock_by_func (editor->color_button,
gimp_text_style_editor_color_changed, gimp_text_style_editor_color_changed,

View file

@ -1209,7 +1209,7 @@ gimp_view_render_temp_buf_to_surface (GimpViewRenderer *renderer,
width, height); width, height);
src_buffer = gimp_temp_buf_create_buffer (temp_buf); src_buffer = gimp_temp_buf_create_buffer (temp_buf);
dest_buffer = gimp_cairo_surface_create_buffer (alpha_surface); dest_buffer = gimp_cairo_surface_create_buffer (alpha_surface, NULL);
transform = transform =
gimp_view_renderer_get_color_transform (renderer, widget, gimp_view_renderer_get_color_transform (renderer, widget,
@ -1258,7 +1258,7 @@ gimp_view_render_temp_buf_to_surface (GimpViewRenderer *renderer,
cairo_surface_flush (surface); cairo_surface_flush (surface);
src_buffer = gimp_temp_buf_create_buffer (temp_buf); src_buffer = gimp_temp_buf_create_buffer (temp_buf);
dest_buffer = gimp_cairo_surface_create_buffer (surface); dest_buffer = gimp_cairo_surface_create_buffer (surface, NULL);
transform = transform =
gimp_view_renderer_get_color_transform (renderer, widget, gimp_view_renderer_get_color_transform (renderer, widget,

View file

@ -285,7 +285,7 @@ gimp_layer_new_from_surface (GimpImage *image,
if (layer == NULL) if (layer == NULL)
return NULL; return NULL;
src_buffer = gimp_cairo_surface_create_buffer (surface); src_buffer = gimp_cairo_surface_create_buffer (surface, NULL);
dest_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)); dest_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer));
gegl_buffer_copy (src_buffer, NULL, GEGL_ABYSS_NONE, gegl_buffer_copy (src_buffer, NULL, GEGL_ABYSS_NONE,

View file

@ -869,23 +869,21 @@ gimp_text_layer_set_justification (GimpTextLayer *layer,
/** /**
* gimp_text_layer_get_color: * gimp_text_layer_get_color:
* @layer: The text layer. * @layer: The text layer.
* @color: (out caller-allocates): The color of the text.
* *
* Get the color of the text in a text layer. * Get the color of the text in a text layer.
* *
* This procedure returns the color of the text in a text layer. * This procedure returns the color of the text in a text layer.
* *
* Returns: TRUE on success. * Returns: (transfer full): The color of the text.
* *
* Since: 2.6 * Since: 2.6
**/ **/
gboolean GeglColor *
gimp_text_layer_get_color (GimpTextLayer *layer, gimp_text_layer_get_color (GimpTextLayer *layer)
GimpRGB *color)
{ {
GimpValueArray *args; GimpValueArray *args;
GimpValueArray *return_vals; GimpValueArray *return_vals;
gboolean success = TRUE; GeglColor *color = NULL;
args = gimp_value_array_new_from_types (NULL, args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_TEXT_LAYER, layer, GIMP_TYPE_TEXT_LAYER, layer,
@ -896,14 +894,12 @@ gimp_text_layer_get_color (GimpTextLayer *layer,
args); args);
gimp_value_array_unref (args); gimp_value_array_unref (args);
success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS; if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
color = g_value_dup_object (gimp_value_array_index (return_vals, 1));
if (success)
GIMP_VALUES_GET_RGB (return_vals, 1, &*color);
gimp_value_array_unref (return_vals); gimp_value_array_unref (return_vals);
return success; return color;
} }
/** /**

View file

@ -69,8 +69,7 @@ gboolean gimp_text_layer_set_base_direction (GimpTextLayer
GimpTextJustification gimp_text_layer_get_justification (GimpTextLayer *layer); GimpTextJustification gimp_text_layer_get_justification (GimpTextLayer *layer);
gboolean gimp_text_layer_set_justification (GimpTextLayer *layer, gboolean gimp_text_layer_set_justification (GimpTextLayer *layer,
GimpTextJustification justify); GimpTextJustification justify);
gboolean gimp_text_layer_get_color (GimpTextLayer *layer, GeglColor* gimp_text_layer_get_color (GimpTextLayer *layer);
GimpRGB *color);
gboolean gimp_text_layer_set_color (GimpTextLayer *layer, gboolean gimp_text_layer_set_color (GimpTextLayer *layer,
const GimpRGB *color); const GimpRGB *color);
gdouble gimp_text_layer_get_indent (GimpTextLayer *layer); gdouble gimp_text_layer_get_indent (GimpTextLayer *layer);

View file

@ -165,6 +165,11 @@ gimp_cairo_surface_get_format (cairo_surface_t *surface)
case CAIRO_FORMAT_RGB24: return babl_format ("cairo-RGB24"); case CAIRO_FORMAT_RGB24: return babl_format ("cairo-RGB24");
case CAIRO_FORMAT_ARGB32: return babl_format ("cairo-ARGB32"); case CAIRO_FORMAT_ARGB32: return babl_format ("cairo-ARGB32");
case CAIRO_FORMAT_A8: return babl_format ("cairo-A8"); case CAIRO_FORMAT_A8: return babl_format ("cairo-A8");
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 2)
/* Since Cairo 1.17.2 */
case CAIRO_FORMAT_RGB96F: return babl_format ("R'B'B' float");
case CAIRO_FORMAT_RGBA128F: return babl_format ("R'G'B'A float");
#endif
default: default:
break; break;
@ -176,26 +181,36 @@ gimp_cairo_surface_get_format (cairo_surface_t *surface)
/** /**
* gimp_cairo_surface_create_buffer: * gimp_cairo_surface_create_buffer:
* @surface: a Cairo surface * @surface: a Cairo surface
* @format: a Babl format.
* *
* This function returns a #GeglBuffer which wraps @surface's pixels. * This function returns a #GeglBuffer which wraps @surface's pixels.
* It must only be called on image surfaces, calling it on other surface * It must only be called on image surfaces, calling it on other surface
* types is an error. * types is an error.
* *
* If @format is set, the returned [class@Gegl.Buffer] will use it. It has to
* map with @surface Cairo format. If unset, the buffer format will be
* determined from @surface. The main difference is that automatically
* determined format has sRGB space and TRC by default.
*
* Returns: (transfer full): a #GeglBuffer * Returns: (transfer full): a #GeglBuffer
* *
* Since: 2.10 * Since: 2.10
**/ **/
GeglBuffer * GeglBuffer *
gimp_cairo_surface_create_buffer (cairo_surface_t *surface) gimp_cairo_surface_create_buffer (cairo_surface_t *surface,
const Babl *format)
{ {
const Babl *format;
gint width; gint width;
gint height; gint height;
g_return_val_if_fail (surface != NULL, NULL); g_return_val_if_fail (surface != NULL, NULL);
g_return_val_if_fail (cairo_surface_get_type (surface) == g_return_val_if_fail (cairo_surface_get_type (surface) ==
CAIRO_SURFACE_TYPE_IMAGE, NULL); CAIRO_SURFACE_TYPE_IMAGE, NULL);
g_return_val_if_fail (format == NULL ||
babl_format_get_bytes_per_pixel (format) == babl_format_get_bytes_per_pixel (gimp_cairo_surface_get_format (surface)),
NULL);
if (format == NULL)
format = gimp_cairo_surface_get_format (surface); format = gimp_cairo_surface_get_format (surface);
width = cairo_image_surface_get_width (surface); width = cairo_image_surface_get_width (surface);
height = cairo_image_surface_get_height (surface); height = cairo_image_surface_get_height (surface);

View file

@ -35,7 +35,8 @@ cairo_pattern_t * gimp_cairo_checkerboard_create (cairo_t *cr,
const GimpRGB *dark); const GimpRGB *dark);
const Babl * gimp_cairo_surface_get_format (cairo_surface_t *surface); const Babl * gimp_cairo_surface_get_format (cairo_surface_t *surface);
GeglBuffer * gimp_cairo_surface_create_buffer (cairo_surface_t *surface); GeglBuffer * gimp_cairo_surface_create_buffer (cairo_surface_t *surface,
const Babl *format);
/* some useful macros for writing directly to a Cairo surface */ /* some useful macros for writing directly to a Cairo surface */

View file

@ -351,6 +351,9 @@ if not babl.found()
# because it would be a newer version. # because it would be a newer version.
babl = dependency('babl', version: '>='+babl_minver) babl = dependency('babl', version: '>='+babl_minver)
endif endif
# TODO: we want to bump to Cairo 1.17.2 when possible in order to use
# CAIRO_FORMAT_RGBA128F unconditionally. At time of writing, it's not possible
# because of our bookworm availability requirement.
cairo_minver = '1.14.0' cairo_minver = '1.14.0'
cairo = dependency('cairo', version: '>='+cairo_minver) cairo = dependency('cairo', version: '>='+cairo_minver)

View file

@ -732,14 +732,14 @@ HELP
); );
@outargs = ( @outargs = (
{ name => 'color', type => 'color', void_ret => 1, { name => 'color', type => 'geglcolor',
desc => 'The color of the text.' } desc => 'The color of the text.' }
); );
%invoke = ( %invoke = (
code => <<'CODE' code => <<'CODE'
{ {
color = gimp_text_layer_get_text (layer)->color; color = gegl_color_duplicate (gimp_text_layer_get_text (layer)->color);
} }
CODE CODE
); );

View file

@ -1438,7 +1438,7 @@ get_cairo_surface (GimpDrawable *drawable,
return NULL; return NULL;
} }
dest_buffer = gimp_cairo_surface_create_buffer (surface); dest_buffer = gimp_cairo_surface_create_buffer (surface, NULL);
if (as_mask) if (as_mask)
{ {
/* src_buffer represents a mask in "Y u8", "Y u16", etc. formats. /* src_buffer represents a mask in "Y u8", "Y u16", etc. formats.
@ -1555,7 +1555,8 @@ drawText (GimpLayer *layer,
cairo_font_options_t *options; cairo_font_options_t *options;
gint x; gint x;
gint y; gint y;
GimpRGB rgb; GeglColor *color;
gdouble rgb[3];
GimpUnit unit; GimpUnit unit;
gdouble size; gdouble size;
GimpTextHintStyle hinting; GimpTextHintStyle hinting;
@ -1588,20 +1589,18 @@ drawText (GimpLayer *layer,
/* When dealing with a gray/indexed image, the viewed color of the text layer /* When dealing with a gray/indexed image, the viewed color of the text layer
* can be different than the one kept in the memory */ * can be different than the one kept in the memory */
if (type == GIMP_RGBA_IMAGE) if (type == GIMP_RGBA_IMAGE)
{ color = gimp_text_layer_get_color (GIMP_TEXT_LAYER (layer));
gimp_text_layer_get_color (GIMP_TEXT_LAYER (layer), &rgb);
}
else else
{
GeglColor *color;
gimp_image_pick_color (gimp_item_get_image (GIMP_ITEM (layer)), 1, gimp_image_pick_color (gimp_item_get_image (GIMP_ITEM (layer)), 1,
(const GimpItem**) &layer, x, y, FALSE, FALSE, 0, (const GimpItem**) &layer, x, y, FALSE, FALSE, 0,
&color); &color);
gegl_color_get_rgba_with_space (color, &rgb.r, &rgb.g, &rgb.b, &rgb.a, NULL);
}
cairo_set_source_rgba (cr, rgb.r, rgb.g, rgb.b, opacity); /* TODO: this export plug-in is not space-aware yet, so we draw everything as
* sRGB for the time being.
*/
gegl_color_get_pixel (color, babl_format_with_space ("R'G'B' double", NULL), rgb);
cairo_set_source_rgba (cr, rgb[0], rgb[1], rgb[2], opacity);
g_object_unref (color);
/* Hinting */ /* Hinting */
hinting = gimp_text_layer_get_hint_style (GIMP_TEXT_LAYER (layer)); hinting = gimp_text_layer_get_hint_style (GIMP_TEXT_LAYER (layer));