diff --git a/app/core/gimpimage-color-profile.c b/app/core/gimpimage-color-profile.c index bcf8f2d604..56deec69f0 100644 --- a/app/core/gimpimage-color-profile.c +++ b/app/core/gimpimage-color-profile.c @@ -815,20 +815,6 @@ gimp_image_get_color_transform_to_srgb_u8 (GimpImage *image) 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 * 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); 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_from_srgb_double); @@ -1162,14 +1147,6 @@ gimp_image_create_color_transforms (GimpImage *image) GIMP_COLOR_RENDERING_INTENT_PERCEPTUAL, 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 = gimp_color_transform_new (private->color_profile, gimp_image_get_layer_format (image, TRUE), diff --git a/app/core/gimpimage-color-profile.h b/app/core/gimpimage-color-profile.h index 607b9af531..1ad617217c 100644 --- a/app/core/gimpimage-color-profile.h +++ b/app/core/gimpimage-color-profile.h @@ -110,8 +110,6 @@ void gimp_image_import_color_profile (GimpImage *ima GimpColorTransform * gimp_image_get_color_transform_to_srgb_u8 (GimpImage *image); -GimpColorTransform * gimp_image_get_color_transform_from_srgb_u8 - (GimpImage *image); GimpColorTransform * gimp_image_get_color_transform_to_srgb_double (GimpImage *image); diff --git a/app/core/gimpimage-private.h b/app/core/gimpimage-private.h index b2f3d9448c..187d95ae5e 100644 --- a/app/core/gimpimage-private.h +++ b/app/core/gimpimage-private.h @@ -74,7 +74,6 @@ struct _GimpImagePrivate /* Cached color transforms: from layer to sRGB u8 and double, and back */ gboolean color_transforms_created; GimpColorTransform *transform_to_srgb_u8; - GimpColorTransform *transform_from_srgb_u8; GimpColorTransform *transform_to_srgb_double; GimpColorTransform *transform_from_srgb_double; diff --git a/app/display/gimpdisplayshell-dnd.c b/app/display/gimpdisplayshell-dnd.c index 89663fa717..d7aad98815 100644 --- a/app/display/gimpdisplayshell-dnd.c +++ b/app/display/gimpdisplayshell-dnd.c @@ -389,17 +389,14 @@ gimp_display_shell_dnd_fill (GimpDisplayShell *shell, gimp_fill_options_get_style (options) == GIMP_FILL_STYLE_BG_COLOR)) { GeglColor *color; - GimpRGB rgb; if (gimp_fill_options_get_style (options) == GIMP_FILL_STYLE_FG_COLOR) color = gimp_context_get_foreground (GIMP_CONTEXT (options)); else 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, - "color", &rgb, + "color", color, NULL); } else diff --git a/app/pdb/text-layer-cmds.c b/app/pdb/text-layer-cmds.c index fef0f974c1..9da53abd3d 100644 --- a/app/pdb/text-layer-cmds.c +++ b/app/pdb/text-layer-cmds.c @@ -734,20 +734,20 @@ text_layer_get_color_invoker (GimpProcedure *procedure, gboolean success = TRUE; GimpValueArray *return_vals; 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)); 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, error ? *error : NULL); 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; } @@ -1685,12 +1685,11 @@ register_text_layer_procs (GimpPDB *pdb) FALSE, GIMP_PARAM_READWRITE)); gimp_procedure_add_return_value (procedure, - gimp_param_spec_rgb ("color", - "color", - "The color of the text.", - FALSE, - NULL, - GIMP_PARAM_READWRITE)); + gegl_param_spec_color ("color", + "color", + "The color of the text.", + NULL, + GIMP_PARAM_READWRITE)); gimp_pdb_register_procedure (pdb, procedure); g_object_unref (procedure); diff --git a/app/text/gimptext-vectors.c b/app/text/gimptext-vectors.c index 3a6901e9da..b6414cb507 100644 --- a/app/text/gimptext-vectors.c +++ b/app/text/gimptext-vectors.c @@ -82,7 +82,7 @@ gimp_text_vectors_new (GimpImage *image, 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) { gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_ERROR, error->message); diff --git a/app/text/gimptext.c b/app/text/gimptext.c index 7e72fecbd6..e4d607e4a9 100644 --- a/app/text/gimptext.c +++ b/app/text/gimptext.c @@ -141,8 +141,8 @@ gimp_text_class_init (GimpTextClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass); - GimpRGB black; - GimpRGB gray; + GeglColor *black = gegl_color_new ("black"); + GeglColor *gray = gegl_color_new ("gray"); GimpMatrix2 identity; gchar *language; GParamSpec *array_spec; @@ -162,8 +162,6 @@ gimp_text_class_init (GimpTextClass *klass) 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_CONFIG_PROP_STRING (object_class, PROP_TEXT, @@ -235,11 +233,11 @@ gimp_text_class_init (GimpTextClass *klass) GIMP_TEXT_DIRECTION_LTR, GIMP_PARAM_STATIC_STRINGS); - GIMP_CONFIG_PROP_RGB (object_class, PROP_COLOR, - "color", - NULL, NULL, - FALSE, &black, - GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_COLOR (object_class, PROP_COLOR, + "color", + NULL, NULL, + black, + GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_ENUM (object_class, PROP_OUTLINE, "outline", @@ -341,10 +339,10 @@ gimp_text_class_init (GimpTextClass *klass) "outline-pattern", NULL, NULL, GIMP_TYPE_PATTERN, GIMP_PARAM_STATIC_STRINGS); - GIMP_CONFIG_PROP_RGB (object_class, PROP_OUTLINE_FOREGROUND, - "outline-foreground", NULL, NULL, - FALSE, &gray, - GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_COLOR (object_class, PROP_OUTLINE_FOREGROUND, + "outline-foreground", NULL, NULL, + gray, + GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_OUTLINE_WIDTH, "outline-width", NULL, NULL, 0.0, 8192.0, 4.0, @@ -394,6 +392,8 @@ gimp_text_class_init (GimpTextClass *klass) GIMP_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_unref (black); + g_object_unref (gray); } static void @@ -417,6 +417,8 @@ gimp_text_finalize (GObject *object) g_clear_pointer (&text->markup, g_free); g_clear_pointer (&text->language, g_free); g_clear_object (&text->font); + g_clear_object (&text->color); + g_clear_object (&text->outline_foreground); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -462,7 +464,7 @@ gimp_text_get_property (GObject *object, g_value_set_string (value, text->language); break; case PROP_COLOR: - g_value_set_boxed (value, &text->color); + g_value_set_object (value, text->color); break; case PROP_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); break; case PROP_OUTLINE_FOREGROUND: - g_value_set_boxed (value, &text->outline_foreground); + g_value_set_object (value, text->outline_foreground); break; case PROP_OUTLINE_PATTERN: g_value_set_object (value, text->outline_pattern); @@ -555,7 +557,6 @@ gimp_text_set_property (GObject *object, GParamSpec *pspec) { GimpText *text = GIMP_TEXT (object); - GimpRGB *color; GimpMatrix2 *matrix; switch (property_id) @@ -609,8 +610,7 @@ gimp_text_set_property (GObject *object, text->base_dir = g_value_get_enum (value); break; case PROP_COLOR: - color = g_value_get_boxed (value); - text->color = *color; + g_set_object (&text->color, g_value_get_object (value));; break; case PROP_OUTLINE: 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); break; case PROP_OUTLINE_FOREGROUND: - color = g_value_get_boxed (value); - text->outline_foreground = *color; + g_set_object (&text->outline_foreground, g_value_get_object (value));; break; case PROP_OUTLINE_PATTERN: { diff --git a/app/text/gimptext.h b/app/text/gimptext.h index 6b6434edd1..c013a949a0 100644 --- a/app/text/gimptext.h +++ b/app/text/gimptext.h @@ -49,10 +49,10 @@ struct _GimpText gboolean kerning; gchar *language; GimpTextDirection base_dir; - GimpRGB color; + GeglColor *color; GimpCustomStyle outline_style; GimpPattern *outline_pattern; - GimpRGB outline_foreground; + GeglColor *outline_foreground; gdouble outline_width; GimpCapStyle outline_cap_style; GimpJoinStyle outline_join_style; diff --git a/app/text/gimptextlayer.c b/app/text/gimptextlayer.c index a5d728f0df..82af355a31 100644 --- a/app/text/gimptextlayer.c +++ b/app/text/gimptextlayer.c @@ -53,7 +53,6 @@ #include "gimptext.h" #include "gimptextlayer.h" -#include "gimptextlayer-transform.h" #include "gimptextlayout.h" #include "gimptextlayout-render.h" @@ -725,7 +724,7 @@ gimp_text_layer_render (GimpTextLayer *layer) 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) { 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); GimpItem *item = GIMP_ITEM (layer); - GimpImage *image = gimp_item_get_image (item); + const Babl *format; GeglBuffer *buffer; - GimpColorTransform *transform; cairo_t *cr; cairo_surface_t *surface; gint width; @@ -941,7 +939,11 @@ gimp_text_layer_render_layout (GimpTextLayer *layer, width = gimp_item_get_width (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); +#endif status = cairo_surface_status (surface); if (status != CAIRO_STATUS_SUCCESS) @@ -968,7 +970,6 @@ gimp_text_layer_render_layout (GimpTextLayer *layer, if (layer->text->outline != GIMP_TEXT_OUTLINE_NONE) { GimpText *text = layer->text; - GimpRGB col = text->outline_foreground; cairo_save (cr); @@ -998,7 +999,16 @@ gimp_text_layer_render_layout (GimpTextLayer *layer, } 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); @@ -1014,23 +1024,29 @@ gimp_text_layer_render_layout (GimpTextLayer *layer, cairo_surface_flush (surface); - buffer = gimp_cairo_surface_create_buffer (surface); - - transform = gimp_image_get_color_transform_from_srgb_u8 (image); - - if (transform) +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 17, 2) + /* The CAIRO_FORMAT_RGBA128F surface maps to the layout TRC and space. */ + switch (gimp_text_layout_get_trc (layout)) { - gimp_color_transform_process_buffer (transform, - buffer, - NULL, - gimp_drawable_get_buffer (drawable), - NULL); - } - else - { - gimp_gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE, - gimp_drawable_get_buffer (drawable), NULL); + case GIMP_TRC_LINEAR: + format = babl_format_with_space ("RGBA float", gimp_text_layout_get_space (layout)); + break; + case GIMP_TRC_NON_LINEAR: + 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 + 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_drawable_get_buffer (drawable), NULL); g_object_unref (buffer); cairo_surface_destroy (surface); diff --git a/app/text/gimptextlayout.c b/app/text/gimptextlayout.c index 50cd670d8d..7869e38327 100644 --- a/app/text/gimptextlayout.c +++ b/app/text/gimptextlayout.c @@ -32,7 +32,10 @@ #include "text-types.h" +#include "gegl/gimp-babl.h" + #include "core/gimperror.h" +#include "core/gimpimage.h" #include "gimpfont.h" @@ -50,6 +53,8 @@ struct _GimpTextLayout gdouble yres; PangoLayout *layout; PangoRectangle extents; + const Babl *layout_space; + GimpTRCType layout_trc; }; @@ -105,18 +110,21 @@ gimp_text_layout_finalize (GObject *object) GimpTextLayout * -gimp_text_layout_new (GimpText *text, - gdouble xres, - gdouble yres, - GError **error) +gimp_text_layout_new (GimpText *text, + GimpImage *target_image, + gdouble xres, + gdouble yres, + GError **error) { GimpTextLayout *layout; + const Babl *target_space; PangoContext *context; PangoFontDescription *font_desc; PangoAlignment alignment = PANGO_ALIGN_LEFT; gint size; 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)); 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_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); switch (text->justify) @@ -221,6 +248,72 @@ gimp_text_layout_new (GimpText *text, 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 gimp_text_layout_get_size (GimpTextLayout *layout, gint *width, @@ -499,17 +592,31 @@ static gchar * gimp_text_layout_apply_tags (GimpTextLayout *layout, const gchar *markup) { - GimpText *text = layout->text; - gchar *result; - - { - guchar r, g, b; - - gimp_rgb_get_uchar (&text->color, &r, &g, &b); + const Babl *format; + GimpText *text = layout->text; + gchar *result; + guchar color[3]; + /* Unfortunately Pango markup are very limited, color-wise. Colors are + * written in hexadecimal, so they are u8 as maximum precision, and + * unbounded colors are not accessible. + * 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 ("%s", - r, g, b, markup); - } + color[0], color[1], color[2], markup); + else + result = g_strdup_printf ("%s", + color[0], color[0], color[0], markup); + /* Updating font 'locl' (if supported) with 'lang' feature tag */ if (text->language) { @@ -598,7 +705,9 @@ gimp_text_layout_set_markup (GimpTextLayout *layout, } } else - pango_layout_set_markup (layout->layout, markup, -1); + { + pango_layout_set_markup (layout->layout, markup, -1); + } g_free (markup); } diff --git a/app/text/gimptextlayout.h b/app/text/gimptextlayout.h index 042751b21d..ed7fd89ed8 100644 --- a/app/text/gimptextlayout.h +++ b/app/text/gimptextlayout.h @@ -38,9 +38,16 @@ struct _GimpTextLayoutClass GType gimp_text_layout_get_type (void) G_GNUC_CONST; GimpTextLayout * gimp_text_layout_new (GimpText *text, + GimpImage *target_image, gdouble xres, gdouble yres, 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, gint *width, gint *height); diff --git a/app/tools/gimptextoptions.c b/app/tools/gimptextoptions.c index 15879b7f92..4ca43a6747 100644 --- a/app/tools/gimptextoptions.c +++ b/app/tools/gimptextoptions.c @@ -152,10 +152,9 @@ static void gimp_text_options_class_init (GimpTextOptionsClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - GimpRGB gray; + GeglColor *gray = gegl_color_new ("gray"); 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->set_property = gimp_text_options_set_property; object_class->get_property = gimp_text_options_get_property; @@ -286,11 +285,11 @@ gimp_text_options_class_init (GimpTextOptionsClass *klass) GIMP_TYPE_CUSTOM_STYLE, GIMP_CUSTOM_STYLE_SOLID_COLOR, GIMP_PARAM_STATIC_STRINGS); - GIMP_CONFIG_PROP_RGB (object_class, PROP_OUTLINE_FOREGROUND, - "outline-foreground", - NULL, NULL, - FALSE, &gray, - GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_COLOR (object_class, PROP_OUTLINE_FOREGROUND, + "outline-foreground", + NULL, NULL, + gray, + GIMP_PARAM_STATIC_STRINGS); GIMP_CONFIG_PROP_OBJECT (object_class, PROP_OUTLINE_PATTERN, "outline-pattern", NULL, NULL, @@ -349,6 +348,8 @@ gimp_text_options_class_init (GimpTextOptionsClass *klass) array_spec, GIMP_PARAM_STATIC_STRINGS | GIMP_CONFIG_PARAM_FLAGS)); + + g_object_unref (gray); } static void @@ -365,7 +366,10 @@ gimp_text_options_config_iface_init (GimpConfigInterface *config_iface) static void gimp_text_options_init (GimpTextOptions *options) { - options->size_entry = NULL; + GeglColor *gray = gegl_color_new ("gray"); + + options->size_entry = NULL; + options->outline_foreground = gray; } static void @@ -374,6 +378,7 @@ gimp_text_options_finalize (GObject *object) GimpTextOptions *options = GIMP_TEXT_OPTIONS (object); g_clear_pointer (&options->language, g_free); + g_clear_object (&options->outline_foreground); 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); break; case PROP_OUTLINE_FOREGROUND: - g_value_set_boxed (value, &options->outline_foreground); + g_value_set_object (value, options->outline_foreground); break; case PROP_OUTLINE_PATTERN: g_value_set_object (value, options->outline_pattern); @@ -491,7 +496,6 @@ gimp_text_options_set_property (GObject *object, GParamSpec *pspec) { GimpTextOptions *options = GIMP_TEXT_OPTIONS (object); - GimpRGB *color; switch (property_id) { @@ -537,8 +541,7 @@ gimp_text_options_set_property (GObject *object, options->outline_style = g_value_get_enum (value); break; case PROP_OUTLINE_FOREGROUND: - color = g_value_get_boxed (value); - options->outline_foreground = *color; + g_set_object (&options->outline_foreground, g_value_get_object (value));; break; case PROP_OUTLINE_PATTERN: { @@ -683,17 +686,11 @@ gimp_text_options_notify_color (GimpContext *context, GParamSpec *pspec, 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, gimp_text_options_notify_text_color, 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, gimp_text_options_notify_text_color, @@ -705,18 +702,13 @@ gimp_text_options_notify_text_color (GimpText *text, GParamSpec *pspec, GimpContext *context) { - GeglColor *color = gegl_color_new ("black"); - g_signal_handlers_block_by_func (context, 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, color); + gimp_context_set_foreground (context, text->color); g_signal_handlers_unblock_by_func (context, gimp_text_options_notify_color, text); - - g_object_unref (color); } /* This function could live in gimptexttool.c also. @@ -727,21 +719,16 @@ gimp_text_options_connect_text (GimpTextOptions *options, GimpText *text) { GimpContext *context; - GeglColor *color; - GimpRGB rgb; g_return_if_fail (GIMP_IS_TEXT_OPTIONS (options)); g_return_if_fail (GIMP_IS_TEXT (text)); 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); g_object_set (text, - "color", &rgb, + "color", gimp_context_get_foreground (context), "font", gimp_context_get_font (context), NULL); diff --git a/app/tools/gimptextoptions.h b/app/tools/gimptextoptions.h index d004fcd35e..c1a6cc10d0 100644 --- a/app/tools/gimptextoptions.h +++ b/app/tools/gimptextoptions.h @@ -51,7 +51,7 @@ struct _GimpTextOptions GimpTextOutline outline; GimpCustomStyle outline_style; - GimpRGB outline_foreground; + GeglColor *outline_foreground; GimpPattern *outline_pattern; gdouble outline_width; GimpUnit outline_unit; diff --git a/app/tools/gimptexttool.c b/app/tools/gimptexttool.c index 2e49bfc6a9..f98a62e95e 100644 --- a/app/tools/gimptexttool.c +++ b/app/tools/gimptexttool.c @@ -2031,7 +2031,7 @@ gimp_text_tool_ensure_layout (GimpTextTool *text_tool) gimp_image_get_resolution (image, &xres, &yres); text_tool->layout = gimp_text_layout_new (text_tool->layer->text, - xres, yres, &error); + image, xres, yres, &error); if (error) { gimp_message_literal (image->gimp, NULL, GIMP_MESSAGE_ERROR, error->message); diff --git a/app/widgets/gimptextstyleeditor.c b/app/widgets/gimptextstyleeditor.c index 68062227b1..bece227ce5 100644 --- a/app/widgets/gimptextstyleeditor.c +++ b/app/widgets/gimptextstyleeditor.c @@ -781,12 +781,14 @@ gimp_text_style_editor_set_color (GimpTextStyleEditor *editor, static void gimp_text_style_editor_set_default_color (GimpTextStyleEditor *editor) { + GimpRGB rgb; + g_signal_handlers_block_by_func (editor->color_button, gimp_text_style_editor_color_changed, editor); - gimp_color_button_set_color (GIMP_COLOR_BUTTON (editor->color_button), - &editor->text->color); + gegl_color_get_pixel (editor->text->color, babl_format ("R'G'B'A double"), &rgb); + gimp_color_button_set_color (GIMP_COLOR_BUTTON (editor->color_button), &rgb); g_signal_handlers_unblock_by_func (editor->color_button, gimp_text_style_editor_color_changed, diff --git a/app/widgets/gimpviewrenderer.c b/app/widgets/gimpviewrenderer.c index f5214e7bbb..18e128e4df 100644 --- a/app/widgets/gimpviewrenderer.c +++ b/app/widgets/gimpviewrenderer.c @@ -1209,7 +1209,7 @@ gimp_view_render_temp_buf_to_surface (GimpViewRenderer *renderer, width, height); 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 = 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); 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 = gimp_view_renderer_get_color_transform (renderer, widget, diff --git a/libgimp/gimplayer.c b/libgimp/gimplayer.c index 86275235c1..a6f3ccbc15 100644 --- a/libgimp/gimplayer.c +++ b/libgimp/gimplayer.c @@ -285,7 +285,7 @@ gimp_layer_new_from_surface (GimpImage *image, if (layer == 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)); gegl_buffer_copy (src_buffer, NULL, GEGL_ABYSS_NONE, diff --git a/libgimp/gimptextlayer_pdb.c b/libgimp/gimptextlayer_pdb.c index a40a8a8f93..eb3416e21d 100644 --- a/libgimp/gimptextlayer_pdb.c +++ b/libgimp/gimptextlayer_pdb.c @@ -869,23 +869,21 @@ gimp_text_layer_set_justification (GimpTextLayer *layer, /** * gimp_text_layer_get_color: * @layer: The text layer. - * @color: (out caller-allocates): The color of the text. * * Get 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 **/ -gboolean -gimp_text_layer_get_color (GimpTextLayer *layer, - GimpRGB *color) +GeglColor * +gimp_text_layer_get_color (GimpTextLayer *layer) { GimpValueArray *args; GimpValueArray *return_vals; - gboolean success = TRUE; + GeglColor *color = NULL; args = gimp_value_array_new_from_types (NULL, GIMP_TYPE_TEXT_LAYER, layer, @@ -896,14 +894,12 @@ gimp_text_layer_get_color (GimpTextLayer *layer, args); gimp_value_array_unref (args); - success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS; - - if (success) - GIMP_VALUES_GET_RGB (return_vals, 1, &*color); + if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS) + color = g_value_dup_object (gimp_value_array_index (return_vals, 1)); gimp_value_array_unref (return_vals); - return success; + return color; } /** diff --git a/libgimp/gimptextlayer_pdb.h b/libgimp/gimptextlayer_pdb.h index a5c0a88480..15a80a6a0a 100644 --- a/libgimp/gimptextlayer_pdb.h +++ b/libgimp/gimptextlayer_pdb.h @@ -69,8 +69,7 @@ gboolean gimp_text_layer_set_base_direction (GimpTextLayer GimpTextJustification gimp_text_layer_get_justification (GimpTextLayer *layer); gboolean gimp_text_layer_set_justification (GimpTextLayer *layer, GimpTextJustification justify); -gboolean gimp_text_layer_get_color (GimpTextLayer *layer, - GimpRGB *color); +GeglColor* gimp_text_layer_get_color (GimpTextLayer *layer); gboolean gimp_text_layer_set_color (GimpTextLayer *layer, const GimpRGB *color); gdouble gimp_text_layer_get_indent (GimpTextLayer *layer); diff --git a/libgimpcolor/gimpcairo.c b/libgimpcolor/gimpcairo.c index 756b62fcf8..850ad22bbf 100644 --- a/libgimpcolor/gimpcairo.c +++ b/libgimpcolor/gimpcairo.c @@ -162,9 +162,14 @@ gimp_cairo_surface_get_format (cairo_surface_t *surface) switch (cairo_image_surface_get_format (surface)) { - case CAIRO_FORMAT_RGB24: return babl_format ("cairo-RGB24"); - case CAIRO_FORMAT_ARGB32: return babl_format ("cairo-ARGB32"); - case CAIRO_FORMAT_A8: return babl_format ("cairo-A8"); + case CAIRO_FORMAT_RGB24: return babl_format ("cairo-RGB24"); + case CAIRO_FORMAT_ARGB32: return babl_format ("cairo-ARGB32"); + 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: break; @@ -176,27 +181,37 @@ gimp_cairo_surface_get_format (cairo_surface_t *surface) /** * gimp_cairo_surface_create_buffer: * @surface: a Cairo surface + * @format: a Babl format. * * This function returns a #GeglBuffer which wraps @surface's pixels. * It must only be called on image surfaces, calling it on other surface * 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 * * Since: 2.10 **/ 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 height; + gint width; + gint height; g_return_val_if_fail (surface != NULL, NULL); g_return_val_if_fail (cairo_surface_get_type (surface) == 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); - format = gimp_cairo_surface_get_format (surface); + if (format == NULL) + format = gimp_cairo_surface_get_format (surface); width = cairo_image_surface_get_width (surface); height = cairo_image_surface_get_height (surface); diff --git a/libgimpcolor/gimpcairo.h b/libgimpcolor/gimpcairo.h index d96e963aad..a88ab5a496 100644 --- a/libgimpcolor/gimpcairo.h +++ b/libgimpcolor/gimpcairo.h @@ -35,7 +35,8 @@ cairo_pattern_t * gimp_cairo_checkerboard_create (cairo_t *cr, const GimpRGB *dark); 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 */ diff --git a/meson.build b/meson.build index 6f4e0172e3..fb22530dcc 100644 --- a/meson.build +++ b/meson.build @@ -351,6 +351,9 @@ if not babl.found() # because it would be a newer version. babl = dependency('babl', version: '>='+babl_minver) 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 = dependency('cairo', version: '>='+cairo_minver) diff --git a/pdb/groups/text_layer.pdb b/pdb/groups/text_layer.pdb index 7ce06bb692..6b6f639d75 100644 --- a/pdb/groups/text_layer.pdb +++ b/pdb/groups/text_layer.pdb @@ -732,14 +732,14 @@ HELP ); @outargs = ( - { name => 'color', type => 'color', void_ret => 1, + { name => 'color', type => 'geglcolor', desc => 'The color of the text.' } ); %invoke = ( code => <<'CODE' { - color = gimp_text_layer_get_text (layer)->color; + color = gegl_color_duplicate (gimp_text_layer_get_text (layer)->color); } CODE ); diff --git a/plug-ins/common/file-pdf-save.c b/plug-ins/common/file-pdf-save.c index ffa72aacd0..9753357bc1 100644 --- a/plug-ins/common/file-pdf-save.c +++ b/plug-ins/common/file-pdf-save.c @@ -1438,7 +1438,7 @@ get_cairo_surface (GimpDrawable *drawable, return NULL; } - dest_buffer = gimp_cairo_surface_create_buffer (surface); + dest_buffer = gimp_cairo_surface_create_buffer (surface, NULL); if (as_mask) { /* src_buffer represents a mask in "Y u8", "Y u16", etc. formats. @@ -1555,7 +1555,8 @@ drawText (GimpLayer *layer, cairo_font_options_t *options; gint x; gint y; - GimpRGB rgb; + GeglColor *color; + gdouble rgb[3]; GimpUnit unit; gdouble size; GimpTextHintStyle hinting; @@ -1588,20 +1589,18 @@ drawText (GimpLayer *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 */ if (type == GIMP_RGBA_IMAGE) - { - gimp_text_layer_get_color (GIMP_TEXT_LAYER (layer), &rgb); - } + color = gimp_text_layer_get_color (GIMP_TEXT_LAYER (layer)); else - { - GeglColor *color; + gimp_image_pick_color (gimp_item_get_image (GIMP_ITEM (layer)), 1, + (const GimpItem**) &layer, x, y, FALSE, FALSE, 0, + &color); - gimp_image_pick_color (gimp_item_get_image (GIMP_ITEM (layer)), 1, - (const GimpItem**) &layer, x, y, FALSE, FALSE, 0, - &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 = gimp_text_layer_get_hint_style (GIMP_TEXT_LAYER (layer));