mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-07-03 17:33:25 +00:00
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:
parent
a60b16f497
commit
e992ca3e51
24 changed files with 276 additions and 173 deletions
|
@ -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),
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,12 +1685,11 @@ 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);
|
||||||
g_object_unref (procedure);
|
g_object_unref (procedure);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,11 +233,11 @@ 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,
|
||||||
"outline",
|
"outline",
|
||||||
|
@ -341,10 +339,10 @@ 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,
|
||||||
0.0, 8192.0, 4.0,
|
0.0, 8192.0, 4.0,
|
||||||
|
@ -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:
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
else
|
case GIMP_TRC_PERCEPTUAL:
|
||||||
{
|
format = babl_format_with_space ("R~G~B~A float", gimp_text_layout_get_space (layout));
|
||||||
gimp_gegl_buffer_copy (buffer, NULL, GEGL_ABYSS_NONE,
|
break;
|
||||||
gimp_drawable_get_buffer (drawable), NULL);
|
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);
|
g_object_unref (buffer);
|
||||||
cairo_surface_destroy (surface);
|
cairo_surface_destroy (surface);
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -105,18 +110,21 @@ gimp_text_layout_finalize (GObject *object)
|
||||||
|
|
||||||
|
|
||||||
GimpTextLayout *
|
GimpTextLayout *
|
||||||
gimp_text_layout_new (GimpText *text,
|
gimp_text_layout_new (GimpText *text,
|
||||||
gdouble xres,
|
GimpImage *target_image,
|
||||||
gdouble yres,
|
gdouble xres,
|
||||||
GError **error)
|
gdouble yres,
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
GimpText *text = layout->text;
|
const Babl *format;
|
||||||
gchar *result;
|
GimpText *text = layout->text;
|
||||||
|
gchar *result;
|
||||||
{
|
guchar color[3];
|
||||||
guchar r, g, b;
|
|
||||||
|
|
||||||
gimp_rgb_get_uchar (&text->color, &r, &g, &b);
|
|
||||||
|
|
||||||
|
/* 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 ("<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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,11 +285,11 @@ 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",
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
options->size_entry = NULL;
|
GeglColor *gray = gegl_color_new ("gray");
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -162,9 +162,14 @@ gimp_cairo_surface_get_format (cairo_surface_t *surface)
|
||||||
|
|
||||||
switch (cairo_image_surface_get_format (surface))
|
switch (cairo_image_surface_get_format (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,27 +181,37 @@ 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);
|
||||||
|
|
||||||
format = gimp_cairo_surface_get_format (surface);
|
if (format == NULL)
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
|
|
|
@ -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
|
||||||
{
|
gimp_image_pick_color (gimp_item_get_image (GIMP_ITEM (layer)), 1,
|
||||||
GeglColor *color;
|
(const GimpItem**) &layer, x, y, FALSE, FALSE, 0,
|
||||||
|
&color);
|
||||||
|
|
||||||
gimp_image_pick_color (gimp_item_get_image (GIMP_ITEM (layer)), 1,
|
/* TODO: this export plug-in is not space-aware yet, so we draw everything as
|
||||||
(const GimpItem**) &layer, x, y, FALSE, FALSE, 0,
|
* sRGB for the time being.
|
||||||
&color);
|
*/
|
||||||
gegl_color_get_rgba_with_space (color, &rgb.r, &rgb.g, &rgb.b, &rgb.a, NULL);
|
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);
|
||||||
cairo_set_source_rgba (cr, rgb.r, rgb.g, rgb.b, opacity);
|
|
||||||
|
|
||||||
/* Hinting */
|
/* Hinting */
|
||||||
hinting = gimp_text_layer_get_hint_style (GIMP_TEXT_LAYER (layer));
|
hinting = gimp_text_layer_get_hint_style (GIMP_TEXT_LAYER (layer));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue