app: GimpGradient now uses GeglColor.

I still see some limitations in GimpGradient, and in particular, they are still
always stored as RGB in GGR files. It would be nice if we could store the actual
color format. This way, if someone chooses a gradient stop as Lab or CMYK color,
that's what the gradient file would keep track of. But also even storing the
space of a color (instead of storing/loading always in sRGB, even though this
may still work fine as we store unbounded double values). This might warrant for
a v2 of GGR file format.

This commit also fixes loading of SVG gradient which was apparently broken
regarding hexadecimal color parsing.

Finally I improve gegl_color_set_alpha() by adding an alpha channel when the
initial format had none.
This commit is contained in:
Jehan 2023-11-26 21:37:52 +01:00
parent 916d032f67
commit b6856af9d8
28 changed files with 1330 additions and 722 deletions

View File

@ -461,22 +461,22 @@ void
gradient_editor_actions_update (GimpActionGroup *group,
gpointer data)
{
GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data);
GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
GimpDataEditor *data_editor = GIMP_DATA_EDITOR (data);
GimpGradient *gradient;
gboolean editable = FALSE;
gboolean editable = FALSE;
GeglColor *color;
GimpRGB left_color;
GimpRGB right_color;
GimpRGB left_seg_color;
GimpRGB right_seg_color;
gboolean blending_equal = TRUE;
gboolean coloring_equal = TRUE;
gboolean left_editable = TRUE;
gboolean right_editable = TRUE;
gboolean selection = FALSE;
gboolean delete = FALSE;
gboolean edit_active = FALSE;
GeglColor *left_color = NULL;
GeglColor *right_color = NULL;
GeglColor *left_seg_color = NULL;
GeglColor *right_seg_color = NULL;
gboolean blending_equal = TRUE;
gboolean coloring_equal = TRUE;
gboolean left_editable = TRUE;
gboolean right_editable = TRUE;
gboolean selection = FALSE;
gboolean delete = FALSE;
gboolean edit_active = FALSE;
gradient = GIMP_GRADIENT (data_editor->data);
@ -491,35 +491,31 @@ gradient_editor_actions_update (GimpActionGroup *group,
if (data_editor->data_editable)
editable = TRUE;
gimp_gradient_segment_get_left_flat_color (gradient,
data_editor->context,
editor->control_sel_l,
&left_color);
left_color = gimp_gradient_segment_get_left_flat_color (gradient,
data_editor->context,
editor->control_sel_l);
if (editor->control_sel_l->prev)
left_seg = editor->control_sel_l->prev;
else
left_seg = gimp_gradient_segment_get_last (editor->control_sel_l);
gimp_gradient_segment_get_right_flat_color (gradient,
data_editor->context,
left_seg,
&left_seg_color);
left_seg_color = gimp_gradient_segment_get_right_flat_color (gradient,
data_editor->context,
left_seg);
gimp_gradient_segment_get_right_flat_color (gradient,
data_editor->context,
editor->control_sel_r,
&right_color);
right_color = gimp_gradient_segment_get_right_flat_color (gradient,
data_editor->context,
editor->control_sel_r);
if (editor->control_sel_r->next)
right_seg = editor->control_sel_r->next;
else
right_seg = gimp_gradient_segment_get_first (editor->control_sel_r);
gimp_gradient_segment_get_left_flat_color (gradient,
data_editor->context,
right_seg,
&right_seg_color);
right_seg_color = gimp_gradient_segment_get_left_flat_color (gradient,
data_editor->context,
right_seg);
left_editable = (editor->control_sel_l->left_color_type ==
GIMP_GRADIENT_COLOR_FIXED);
@ -610,12 +606,9 @@ gradient_editor_actions_update (GimpActionGroup *group,
if (gradient)
{
gegl_color_set_pixel (color, babl_format ("R'G'B'A double"), &left_color);
SET_COLOR ("gradient-editor-left-color", color, FALSE);
gegl_color_set_pixel (color, babl_format ("R'G'B'A double"), &left_seg_color);
SET_COLOR ("gradient-editor-load-left-left-neighbor", color, FALSE);
gegl_color_set_pixel (color, babl_format ("R'G'B'A double"), &right_color);
SET_COLOR ("gradient-editor-load-left-right-endpoint", color, FALSE);
SET_COLOR ("gradient-editor-left-color", left_color, FALSE);
SET_COLOR ("gradient-editor-load-left-left-neighbor", left_seg_color, FALSE);
SET_COLOR ("gradient-editor-load-left-right-endpoint", right_color, FALSE);
}
SET_SENSITIVE ("gradient-editor-load-left-fg", left_editable);
@ -724,12 +717,9 @@ gradient_editor_actions_update (GimpActionGroup *group,
if (gradient)
{
gegl_color_set_pixel (color, babl_format ("R'G'B'A double"), &right_color);
SET_COLOR ("gradient-editor-right-color", color, FALSE);
gegl_color_set_pixel (color, babl_format ("R'G'B'A double"), &right_seg_color);
SET_COLOR ("gradient-editor-load-right-right-neighbor", color, FALSE);
gegl_color_set_pixel (color, babl_format ("R'G'B'A double"), &left_color);
SET_COLOR ("gradient-editor-load-right-left-endpoint", color, FALSE);
SET_COLOR ("gradient-editor-right-color", right_color, FALSE);
SET_COLOR ("gradient-editor-load-right-right-neighbor", right_seg_color, FALSE);
SET_COLOR ("gradient-editor-load-right-left-endpoint", left_color, FALSE);
}
SET_SENSITIVE ("gradient-editor-load-right-fg", right_editable);
@ -939,4 +929,8 @@ gradient_editor_actions_update (GimpActionGroup *group,
#undef SET_VISIBLE
g_object_unref (color);
g_clear_object (&left_color);
g_clear_object (&right_color);
g_clear_object (&left_seg_color);
g_clear_object (&right_seg_color);
}

View File

@ -80,18 +80,21 @@ gradient_editor_left_color_type_cmd_callback (GimpAction *action,
color_type !=
gimp_gradient_segment_get_left_color_type (gradient, left))
{
GimpRGB color;
gimp_gradient_segment_get_left_flat_color (gradient,
GIMP_DATA_EDITOR (editor)->context,
left, &color);
gimp_data_freeze (GIMP_DATA (gradient));
gimp_gradient_segment_set_left_color_type (gradient, left, color_type);
if (color_type == GIMP_GRADIENT_COLOR_FIXED)
gimp_gradient_segment_set_left_color (gradient, left, &color);
{
GeglColor *color;
color = gimp_gradient_segment_get_left_flat_color (gradient,
GIMP_DATA_EDITOR (editor)->context,
left);
gimp_gradient_segment_set_left_color (gradient, left, color);
g_object_unref (color);
}
gimp_data_thaw (GIMP_DATA (gradient));
}
@ -108,8 +111,7 @@ gradient_editor_load_left_cmd_callback (GimpAction *action,
GimpGradientSegment *left;
GimpGradientSegment *right;
GimpGradientSegment *seg;
GeglColor *color = NULL;
GimpRGB rgb;
GeglColor *color;
GimpGradientColor color_type = GIMP_GRADIENT_COLOR_FIXED;
gint index = g_variant_get_int32 (value);
@ -123,12 +125,12 @@ gradient_editor_load_left_cmd_callback (GimpAction *action,
else
seg = gimp_gradient_segment_get_last (left);
rgb = seg->right_color;
color = seg->right_color;
color_type = seg->right_color_type;
break;
case GRADIENT_EDITOR_COLOR_OTHER_ENDPOINT:
rgb = right->right_color;
color = right->right_color;
color_type = right->right_color_type;
break;
@ -141,19 +143,14 @@ gradient_editor_load_left_cmd_callback (GimpAction *action,
break;
default: /* Load a color */
rgb = editor->saved_colors[index - GRADIENT_EDITOR_COLOR_FIRST_CUSTOM];
color = editor->saved_colors[index - GRADIENT_EDITOR_COLOR_FIRST_CUSTOM];
break;
}
if (color != NULL)
gegl_color_get_rgba_with_space (color, &rgb.r, &rgb.g, &rgb.b, &rgb.a, NULL);
gimp_data_freeze (GIMP_DATA (gradient));
gimp_gradient_segment_range_blend (gradient, left, right,
&rgb,
&right->right_color,
TRUE, TRUE);
gimp_gradient_segment_range_blend (gradient, left, right, color,
right->right_color, TRUE, TRUE);
gimp_gradient_segment_set_left_color_type (gradient, left, color_type);
gimp_data_thaw (GIMP_DATA (gradient));
@ -171,8 +168,8 @@ gradient_editor_save_left_cmd_callback (GimpAction *action,
gimp_gradient_editor_get_selection (editor, &gradient, &left, NULL);
gimp_gradient_segment_get_left_color (gradient, left,
&editor->saved_colors[index]);
g_clear_object (&editor->saved_colors[index]);
editor->saved_colors[index] = gegl_color_duplicate (gimp_gradient_segment_get_left_color (gradient, left));
}
void
@ -204,18 +201,20 @@ gradient_editor_right_color_type_cmd_callback (GimpAction *action,
color_type !=
gimp_gradient_segment_get_right_color_type (gradient, right))
{
GimpRGB color;
gimp_gradient_segment_get_right_flat_color (gradient,
GIMP_DATA_EDITOR (editor)->context,
right, &color);
gimp_data_freeze (GIMP_DATA (gradient));
gimp_gradient_segment_set_right_color_type (gradient, right, color_type);
if (color_type == GIMP_GRADIENT_COLOR_FIXED)
gimp_gradient_segment_set_right_color (gradient, right, &color);
{
GeglColor *color;
color = gimp_gradient_segment_get_right_flat_color (gradient, GIMP_DATA_EDITOR (editor)->context,
right);
gimp_gradient_segment_set_right_color (gradient, right, color);
g_object_unref (color);
}
gimp_data_thaw (GIMP_DATA (gradient));
}
@ -232,8 +231,7 @@ gradient_editor_load_right_cmd_callback (GimpAction *action,
GimpGradientSegment *left;
GimpGradientSegment *right;
GimpGradientSegment *seg;
GeglColor *color = NULL;
GimpRGB rgb;
GeglColor *color;
GimpGradientColor color_type = GIMP_GRADIENT_COLOR_FIXED;
gint index = g_variant_get_int32 (value);
@ -247,12 +245,12 @@ gradient_editor_load_right_cmd_callback (GimpAction *action,
else
seg = gimp_gradient_segment_get_first (right);
rgb = seg->left_color;
color = seg->left_color;
color_type = seg->left_color_type;
break;
case GRADIENT_EDITOR_COLOR_OTHER_ENDPOINT:
rgb = left->left_color;
color = left->left_color;
color_type = left->left_color_type;
break;
@ -265,19 +263,14 @@ gradient_editor_load_right_cmd_callback (GimpAction *action,
break;
default: /* Load a color */
rgb = editor->saved_colors[index - GRADIENT_EDITOR_COLOR_FIRST_CUSTOM];
color = editor->saved_colors[index - GRADIENT_EDITOR_COLOR_FIRST_CUSTOM];
break;
}
if (color != NULL)
gegl_color_get_rgba_with_space (color, &rgb.r, &rgb.g, &rgb.b, &rgb.a, NULL);
gimp_data_freeze (GIMP_DATA (gradient));
gimp_gradient_segment_range_blend (gradient, left, right,
&left->left_color,
&rgb,
TRUE, TRUE);
gimp_gradient_segment_range_blend (gradient, left, right, left->left_color,
color, TRUE, TRUE);
gimp_gradient_segment_set_right_color_type (gradient, left, color_type);
gimp_data_thaw (GIMP_DATA (gradient));
@ -295,8 +288,8 @@ gradient_editor_save_right_cmd_callback (GimpAction *action,
gimp_gradient_editor_get_selection (editor, &gradient, NULL, &right);
gimp_gradient_segment_get_right_color (gradient, right,
&editor->saved_colors[index]);
g_clear_object (&editor->saved_colors[index]);
editor->saved_colors[index] = gegl_color_duplicate (gimp_gradient_segment_get_right_color (gradient, right));
}
void
@ -637,8 +630,8 @@ gradient_editor_blend_color_cmd_callback (GimpAction *action,
gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
gimp_gradient_segment_range_blend (gradient, left, right,
&left->left_color,
&right->right_color,
left->left_color,
right->right_color,
TRUE, FALSE);
}
@ -655,8 +648,8 @@ gradient_editor_blend_opacity_cmd_callback (GimpAction *action,
gimp_gradient_editor_get_selection (editor, &gradient, &left, &right);
gimp_gradient_segment_range_blend (gradient, left, right,
&left->left_color,
&right->right_color,
left->left_color,
right->right_color,
FALSE, TRUE);
}

View File

@ -133,6 +133,8 @@ gimp_gradient_load (GimpContext *context,
gint type;
gint left_color_type;
gint right_color_type;
gdouble left_rgba[4];
gdouble right_rgba[4];
seg = gimp_gradient_segment_new ();
@ -150,19 +152,19 @@ gimp_gradient_load (GimpContext *context,
if (! line)
goto failed;
if (! gimp_ascii_strtod (line, &end, &seg->left) ||
! gimp_ascii_strtod (end, &end, &seg->middle) ||
! gimp_ascii_strtod (end, &end, &seg->right) ||
if (! gimp_ascii_strtod (line, &end, &seg->left) ||
! gimp_ascii_strtod (end, &end, &seg->middle) ||
! gimp_ascii_strtod (end, &end, &seg->right) ||
! gimp_ascii_strtod (end, &end, &seg->left_color.r) ||
! gimp_ascii_strtod (end, &end, &seg->left_color.g) ||
! gimp_ascii_strtod (end, &end, &seg->left_color.b) ||
! gimp_ascii_strtod (end, &end, &seg->left_color.a) ||
! gimp_ascii_strtod (end, &end, &left_rgba[0]) ||
! gimp_ascii_strtod (end, &end, &left_rgba[1]) ||
! gimp_ascii_strtod (end, &end, &left_rgba[2]) ||
! gimp_ascii_strtod (end, &end, &left_rgba[3]) ||
! gimp_ascii_strtod (end, &end, &seg->right_color.r) ||
! gimp_ascii_strtod (end, &end, &seg->right_color.g) ||
! gimp_ascii_strtod (end, &end, &seg->right_color.b) ||
! gimp_ascii_strtod (end, &end, &seg->right_color.a))
! gimp_ascii_strtod (end, &end, &right_rgba[0]) ||
! gimp_ascii_strtod (end, &end, &right_rgba[1]) ||
! gimp_ascii_strtod (end, &end, &right_rgba[2]) ||
! gimp_ascii_strtod (end, &end, &right_rgba[3]))
{
g_set_error (error, GIMP_DATA_ERROR, GIMP_DATA_ERROR_READ,
_("Corrupt segment %d."), i);
@ -170,6 +172,9 @@ gimp_gradient_load (GimpContext *context,
goto failed;
}
gegl_color_set_pixel (seg->left_color, babl_format ("R'G'B'A double"), left_rgba);
gegl_color_set_pixel (seg->right_color, babl_format ("R'G'B'A double"), right_rgba);
switch (sscanf (end, "%d %d %d %d",
&type, &color,
&left_color_type, &right_color_type))
@ -276,7 +281,8 @@ typedef struct
typedef struct
{
gdouble offset;
GimpRGB color;
GeglColor *color;
gdouble opacity;
} SvgStop;
@ -414,7 +420,12 @@ svg_parser_end_element (GMarkupParseContext *context,
parser->gradient->segments = svg_parser_gradient_segments (parser->stops);
for (list = parser->stops; list; list = list->next)
g_slice_free (SvgStop, list->data);
{
SvgStop *stop = list->data;
g_clear_object (&stop->color);
g_slice_free (SvgStop, stop);
}
g_list_free (parser->stops);
parser->stops = NULL;
@ -443,8 +454,10 @@ svg_parser_gradient_segments (GList *stops)
segment = gimp_gradient_segment_new ();
segment->left_color = stop->color;
segment->right_color = stop->color;
g_clear_object (&segment->left_color);
segment->left_color = gegl_color_duplicate (stop->color);
g_clear_object (&segment->right_color);
segment->right_color = gegl_color_duplicate (stop->color);
/* the list of offsets is sorted from largest to smallest */
for (list = g_list_next (stops); list; list = g_list_next (list))
@ -460,17 +473,22 @@ svg_parser_gradient_segments (GList *stops)
next->prev = segment;
segment->right = stop->offset;
segment->right_color = stop->color;
g_clear_object (&segment->right_color);
segment->right_color = gegl_color_duplicate (stop->color);
stop = list->data;
segment->left_color = stop->color;
g_clear_object (&segment->left_color);
segment->left_color = gegl_color_duplicate (stop->color);
}
segment->middle = (segment->left + segment->right) / 2.0;
if (stop->offset > 0.0)
segment->right_color = stop->color;
{
g_clear_object (&segment->right_color);
segment->right_color = gegl_color_duplicate (stop->color);
}
/* FIXME: remove empty segments here or add a GimpGradient API to do that
*/
@ -485,14 +503,15 @@ svg_parse_gradient_stop_style_prop (SvgStop *stop,
{
if (strcmp (name, "stop-color") == 0)
{
gimp_rgb_parse_css (&stop->color, value, -1);
g_clear_object (&stop->color);
stop->color = gimp_color_parse_css (value, -1);
}
else if (strcmp (name, "stop-opacity") == 0)
{
gdouble opacity = g_ascii_strtod (value, NULL);
if (errno != ERANGE)
gimp_rgb_set_alpha (&stop->color, CLAMP (opacity, 0.0, 1.0));
stop->opacity = CLAMP (opacity, 0.0, 1.0);
}
}
@ -522,7 +541,7 @@ svg_parse_gradient_stop_style (SvgStop *stop,
name = g_strndup (style, sep - style);
sep++;
value = g_strndup (sep, end - sep - (*end == ';' ? 1 : 0));
value = g_strndup (sep, end - sep);
svg_parse_gradient_stop_style_prop (stop, name, value);
@ -543,7 +562,8 @@ svg_parse_gradient_stop (const gchar **names,
{
SvgStop *stop = g_slice_new0 (SvgStop);
gimp_rgb_set_alpha (&stop->color, 1.0);
stop->color = NULL;
stop->opacity = 1.0;
while (*names && *values)
{
@ -571,5 +591,13 @@ svg_parse_gradient_stop (const gchar **names,
values++;
}
if (! stop->color)
/* Default stop color is black:
* https://svgwg.org/svg2-draft/pservers.html#GradientStops
*/
stop->color = gegl_color_new ("black");
gimp_color_set_alpha (stop->color, stop->opacity);
return stop;
}

View File

@ -70,19 +70,24 @@ gimp_gradient_save (GimpData *data,
for (seg = gradient->segments; seg; seg = seg->next)
{
gchar buf[11][G_ASCII_DTOSTR_BUF_SIZE];
gchar buf[11][G_ASCII_DTOSTR_BUF_SIZE];
gdouble rgba[4];
g_ascii_dtostr (buf[0], G_ASCII_DTOSTR_BUF_SIZE, seg->left);
g_ascii_dtostr (buf[1], G_ASCII_DTOSTR_BUF_SIZE, seg->middle);
g_ascii_dtostr (buf[2], G_ASCII_DTOSTR_BUF_SIZE, seg->right);
g_ascii_dtostr (buf[3], G_ASCII_DTOSTR_BUF_SIZE, seg->left_color.r);
g_ascii_dtostr (buf[4], G_ASCII_DTOSTR_BUF_SIZE, seg->left_color.g);
g_ascii_dtostr (buf[5], G_ASCII_DTOSTR_BUF_SIZE, seg->left_color.b);
g_ascii_dtostr (buf[6], G_ASCII_DTOSTR_BUF_SIZE, seg->left_color.a);
g_ascii_dtostr (buf[7], G_ASCII_DTOSTR_BUF_SIZE, seg->right_color.r);
g_ascii_dtostr (buf[8], G_ASCII_DTOSTR_BUF_SIZE, seg->right_color.g);
g_ascii_dtostr (buf[9], G_ASCII_DTOSTR_BUF_SIZE, seg->right_color.b);
g_ascii_dtostr (buf[10], G_ASCII_DTOSTR_BUF_SIZE, seg->right_color.a);
gegl_color_get_pixel (seg->left_color, babl_format ("R'G'B'A double"), rgba);
g_ascii_dtostr (buf[3], G_ASCII_DTOSTR_BUF_SIZE, rgba[0]);
g_ascii_dtostr (buf[4], G_ASCII_DTOSTR_BUF_SIZE, rgba[1]);
g_ascii_dtostr (buf[5], G_ASCII_DTOSTR_BUF_SIZE, rgba[2]);
g_ascii_dtostr (buf[6], G_ASCII_DTOSTR_BUF_SIZE, rgba[3]);
gegl_color_get_pixel (seg->right_color, babl_format ("R'G'B'A double"), rgba);
g_ascii_dtostr (buf[7], G_ASCII_DTOSTR_BUF_SIZE, rgba[0]);
g_ascii_dtostr (buf[8], G_ASCII_DTOSTR_BUF_SIZE, rgba[1]);
g_ascii_dtostr (buf[9], G_ASCII_DTOSTR_BUF_SIZE, rgba[2]);
g_ascii_dtostr (buf[10], G_ASCII_DTOSTR_BUF_SIZE, rgba[3]);
g_string_append_printf (string,
"%s %s %s %s %s %s %s %s %s %s %s %d %d %d %d\n",
@ -136,17 +141,17 @@ gimp_gradient_save_pov (GimpGradient *gradient,
for (seg = gradient->segments; seg; seg = seg->next)
{
gdouble left_rgba[4];
gdouble right_rgba[4];
/* Left */
g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE,
seg->left);
g_ascii_dtostr (color_buf[0], G_ASCII_DTOSTR_BUF_SIZE,
seg->left_color.r);
g_ascii_dtostr (color_buf[1], G_ASCII_DTOSTR_BUF_SIZE,
seg->left_color.g);
g_ascii_dtostr (color_buf[2], G_ASCII_DTOSTR_BUF_SIZE,
seg->left_color.b);
g_ascii_dtostr (color_buf[3], G_ASCII_DTOSTR_BUF_SIZE,
1.0 - seg->left_color.a);
gegl_color_get_pixel (seg->left_color, babl_format ("R'G'B'A double"), left_rgba);
g_ascii_dtostr (color_buf[0], G_ASCII_DTOSTR_BUF_SIZE, left_rgba[0]);
g_ascii_dtostr (color_buf[1], G_ASCII_DTOSTR_BUF_SIZE, left_rgba[1]);
g_ascii_dtostr (color_buf[2], G_ASCII_DTOSTR_BUF_SIZE, left_rgba[2]);
g_ascii_dtostr (color_buf[3], G_ASCII_DTOSTR_BUF_SIZE, 1.0 - left_rgba[3]);
g_string_append_printf (string,
"\t[%s color rgbt <%s, %s, %s, %s>]\n",
@ -157,14 +162,15 @@ gimp_gradient_save_pov (GimpGradient *gradient,
/* Middle */
g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE,
seg->middle);
gegl_color_get_pixel (seg->right_color, babl_format ("R'G'B'A double"), right_rgba);
g_ascii_dtostr (color_buf[0], G_ASCII_DTOSTR_BUF_SIZE,
(seg->left_color.r + seg->right_color.r) / 2.0);
(left_rgba[0] + right_rgba[0]) / 2.0);
g_ascii_dtostr (color_buf[1], G_ASCII_DTOSTR_BUF_SIZE,
(seg->left_color.g + seg->right_color.g) / 2.0);
(left_rgba[1] + right_rgba[1]) / 2.0);
g_ascii_dtostr (color_buf[2], G_ASCII_DTOSTR_BUF_SIZE,
(seg->left_color.b + seg->right_color.b) / 2.0);
(left_rgba[2] + right_rgba[2]) / 2.0);
g_ascii_dtostr (color_buf[3], G_ASCII_DTOSTR_BUF_SIZE,
1.0 - (seg->left_color.a + seg->right_color.a) / 2.0);
1.0 - (left_rgba[3] + right_rgba[3]) / 2.0);
g_string_append_printf (string,
"\t[%s color rgbt <%s, %s, %s, %s>]\n",
@ -175,14 +181,10 @@ gimp_gradient_save_pov (GimpGradient *gradient,
/* Right */
g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE,
seg->right);
g_ascii_dtostr (color_buf[0], G_ASCII_DTOSTR_BUF_SIZE,
seg->right_color.r);
g_ascii_dtostr (color_buf[1], G_ASCII_DTOSTR_BUF_SIZE,
seg->right_color.g);
g_ascii_dtostr (color_buf[2], G_ASCII_DTOSTR_BUF_SIZE,
seg->right_color.b);
g_ascii_dtostr (color_buf[3], G_ASCII_DTOSTR_BUF_SIZE,
1.0 - seg->right_color.a);
g_ascii_dtostr (color_buf[0], G_ASCII_DTOSTR_BUF_SIZE, right_rgba[0]);
g_ascii_dtostr (color_buf[1], G_ASCII_DTOSTR_BUF_SIZE, right_rgba[1]);
g_ascii_dtostr (color_buf[2], G_ASCII_DTOSTR_BUF_SIZE, right_rgba[2]);
g_ascii_dtostr (color_buf[3], G_ASCII_DTOSTR_BUF_SIZE, 1.0 - right_rgba[3]);
g_string_append_printf (string,
"\t[%s color rgbt <%s, %s, %s, %s>]\n",

View File

@ -74,10 +74,9 @@ static inline GimpGradientSegment *
gimp_gradient_get_segment_at_internal (GimpGradient *gradient,
GimpGradientSegment *seg,
gdouble pos);
static void gimp_gradient_get_flat_color (GimpContext *context,
const GimpRGB *color,
GimpGradientColor color_type,
GimpRGB *flat_color);
static GeglColor * gimp_gradient_get_flat_color (GimpContext *context,
GeglColor *color,
GimpGradientColor color_type);
static inline gdouble gimp_gradient_calc_linear_factor (gdouble middle,
@ -224,7 +223,6 @@ gimp_gradient_get_new_preview (GimpViewable *viewable,
guchar *row;
gint x, y;
gdouble dx, cur_x;
GimpRGB color;
dx = 1.0 / (width - 1);
cur_x = 0.0;
@ -234,17 +232,19 @@ gimp_gradient_get_new_preview (GimpViewable *viewable,
for (x = 0; x < width; x++)
{
GeglColor *color = NULL;
seg = gimp_gradient_get_color_at (gradient, context, seg, cur_x,
FALSE,
GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
&color);
*p++ = ROUND (color.r * 255.0);
*p++ = ROUND (color.g * 255.0);
*p++ = ROUND (color.b * 255.0);
*p++ = ROUND (color.a * 255.0);
gegl_color_get_pixel (color, babl_format ("R'G'B'A u8"), p);
p += 4;
cur_x += dx;
g_object_unref (color);
}
temp_buf = gimp_temp_buf_new (width, height, babl_format ("R'G'B'A u8"));
@ -285,6 +285,8 @@ gimp_gradient_copy (GimpData *data,
cur->prev = prev;
cur->next = NULL;
cur->left_color = gegl_color_duplicate (orig->left_color);
cur->right_color = gegl_color_duplicate (orig->right_color);
if (prev)
prev->next = cur;
@ -341,9 +343,13 @@ gimp_gradient_get_checksum (GimpTagged *tagged)
{
GChecksum *checksum = g_checksum_new (G_CHECKSUM_MD5);
GimpGradientSegment *segment = gradient->segments;
guchar data[40];
while (segment)
{
const Babl *format;
gsize length;
g_checksum_update (checksum,
(const guchar *) &segment->left,
sizeof (segment->left));
@ -356,15 +362,25 @@ gimp_gradient_get_checksum (GimpTagged *tagged)
g_checksum_update (checksum,
(const guchar *) &segment->left_color_type,
sizeof (segment->left_color_type));
g_checksum_update (checksum,
(const guchar *) &segment->left_color,
sizeof (segment->left_color));
format = gegl_color_get_format (segment->left_color);
gegl_color_get_pixel (segment->left_color, format, data);
length = babl_format_get_bytes_per_pixel (format);
g_checksum_update (checksum, data, (gssize) length);
g_checksum_update (checksum, (const guchar *) babl_get_name (format),
strlen (babl_get_name (format)));
g_checksum_update (checksum,
(const guchar *) &segment->right_color_type,
sizeof (segment->right_color_type));
g_checksum_update (checksum,
(const guchar *) &segment->right_color,
sizeof (segment->right_color));
format = gegl_color_get_format (segment->right_color);
gegl_color_get_pixel (segment->right_color, format, data);
length = babl_format_get_bytes_per_pixel (format);
g_checksum_update (checksum, data, (gssize) length);
g_checksum_update (checksum, (const guchar *) babl_get_name (format),
strlen (babl_get_name (format)));
g_checksum_update (checksum,
(const guchar *) &segment->type,
sizeof (segment->type));
@ -435,7 +451,7 @@ gimp_gradient_get_extension (GimpData *data)
* @pos: position in the gradient (between 0.0 and 1.0)
* @reverse: when %TRUE, use the reversed gradient
* @blend_color_space: color space to use for blending RGB segments
* @color: returns the color
* @color: returns a newly allocated color
*
* If you are iterating over an gradient, you should pass the the
* return value from the last call for @seg.
@ -443,24 +459,27 @@ gimp_gradient_get_extension (GimpData *data)
* Returns: the gradient segment the color is from
**/
GimpGradientSegment *
gimp_gradient_get_color_at (GimpGradient *gradient,
GimpContext *context,
GimpGradientSegment *seg,
gdouble pos,
gboolean reverse,
GimpGradientBlendColorSpace blend_color_space,
GimpRGB *color)
gimp_gradient_get_color_at (GimpGradient *gradient,
GimpContext *context,
GimpGradientSegment *seg,
gdouble pos,
gboolean reverse,
GimpGradientBlendColorSpace blend_color_space,
GeglColor **color)
{
gdouble factor = 0.0;
gdouble seg_len;
gdouble middle;
GimpRGB left_color;
GimpRGB right_color;
GimpRGB rgb;
gdouble factor = 0.0;
gdouble seg_len;
gdouble middle;
GeglColor *left_color;
GeglColor *right_color;
gdouble left_alpha;
gdouble right_alpha;
/* type-check disabled to improve speed */
/* g_return_val_if_fail (GIMP_IS_GRADIENT (gradient), NULL); */
g_return_val_if_fail (color != NULL, NULL);
g_return_val_if_fail (color != NULL && *color == NULL, NULL);
*color = gegl_color_new (NULL);
pos = CLAMP (pos, 0.0, 1.0);
@ -517,98 +536,99 @@ gimp_gradient_get_color_at (GimpGradient *gradient,
if (context)
{
gimp_gradient_segment_get_left_flat_color (gradient,
context, seg, &left_color);
gimp_gradient_segment_get_right_flat_color (gradient,
context, seg, &right_color);
left_color = gimp_gradient_segment_get_left_flat_color (gradient, context, seg);
right_color = gimp_gradient_segment_get_right_flat_color (gradient, context, seg);
}
else
{
left_color = seg->left_color;
right_color = seg->right_color;
left_color = g_object_ref (seg->left_color);
right_color = g_object_ref (seg->right_color);
}
/* Calculate color components */
if (seg->color == GIMP_GRADIENT_SEGMENT_RGB)
{
gdouble left_components[3];
gdouble right_components[3];
gdouble ret_components[3];
switch (blend_color_space)
{
case GIMP_GRADIENT_BLEND_CIE_LAB:
babl_process (fish_srgb_to_cie_lab,
&left_color, &left_color, 1);
babl_process (fish_srgb_to_cie_lab,
&right_color, &right_color, 1);
gegl_color_get_pixel (left_color, babl_format ("CIE Lab double"), left_components);
gegl_color_get_pixel (right_color, babl_format ("CIE Lab double"), right_components);
break;
case GIMP_GRADIENT_BLEND_RGB_LINEAR:
babl_process (fish_srgb_to_linear_rgb,
&left_color, &left_color, 1);
babl_process (fish_srgb_to_linear_rgb,
&right_color, &right_color, 1);
gegl_color_get_pixel (left_color, babl_format ("RGB double"), left_components);
gegl_color_get_pixel (right_color, babl_format ("RGB double"), right_components);
case GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL:
/* TODO: shouldn't this format use the color space of the target
* image? Will it change computation? */
gegl_color_get_pixel (left_color, babl_format ("R'G'B' double"), left_components);
gegl_color_get_pixel (right_color, babl_format ("R'G'B' double"), right_components);
break;
}
rgb.r = left_color.r + (right_color.r - left_color.r) * factor;
rgb.g = left_color.g + (right_color.g - left_color.g) * factor;
rgb.b = left_color.b + (right_color.b - left_color.b) * factor;
ret_components[0] = left_components[0] + (right_components[0] - left_components[0]) * factor;
ret_components[1] = left_components[1] + (right_components[1] - left_components[1]) * factor;
ret_components[2] = left_components[2] + (right_components[2] - left_components[2]) * factor;
switch (blend_color_space)
{
case GIMP_GRADIENT_BLEND_CIE_LAB:
babl_process (fish_cie_lab_to_srgb,
&rgb, &rgb, 1);
gegl_color_set_pixel (*color, babl_format ("CIE Lab double"), ret_components);
break;
case GIMP_GRADIENT_BLEND_RGB_LINEAR:
babl_process (fish_linear_rgb_to_srgb,
&rgb, &rgb, 1);
gegl_color_set_pixel (*color, babl_format ("RGB double"), ret_components);
break;
case GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL:
gegl_color_set_pixel (*color, babl_format ("R'G'B' double"), ret_components);
break;
}
}
else
{
GimpHSV left_hsv;
GimpHSV right_hsv;
gdouble left_hsv[3];
gdouble right_hsv[3];
gimp_rgb_to_hsv (&left_color, &left_hsv);
gimp_rgb_to_hsv (&right_color, &right_hsv);
gegl_color_get_pixel (left_color, babl_format ("HSV double"), left_hsv);
gegl_color_get_pixel (right_color, babl_format ("HSV double"), right_hsv);
left_hsv.s = left_hsv.s + (right_hsv.s - left_hsv.s) * factor;
left_hsv.v = left_hsv.v + (right_hsv.v - left_hsv.v) * factor;
left_hsv[1] = left_hsv[1] + (right_hsv[1] - left_hsv[1]) * factor;
left_hsv[2] = left_hsv[2] + (right_hsv[2] - left_hsv[2]) * factor;
switch (seg->color)
{
case GIMP_GRADIENT_SEGMENT_HSV_CCW:
if (left_hsv.h < right_hsv.h)
if (left_hsv[0] < right_hsv[0])
{
left_hsv.h += (right_hsv.h - left_hsv.h) * factor;
left_hsv[0] += (right_hsv[0] - left_hsv[0]) * factor;
}
else
{
left_hsv.h += (1.0 - (left_hsv.h - right_hsv.h)) * factor;
left_hsv[0] += (1.0 - (left_hsv[0] - right_hsv[0])) * factor;
if (left_hsv.h > 1.0)
left_hsv.h -= 1.0;
if (left_hsv[0] > 1.0)
left_hsv[0] -= 1.0;
}
break;
case GIMP_GRADIENT_SEGMENT_HSV_CW:
if (right_hsv.h < left_hsv.h)
if (right_hsv[0] < left_hsv[0])
{
left_hsv.h -= (left_hsv.h - right_hsv.h) * factor;
left_hsv[0] -= (left_hsv[0] - right_hsv[0]) * factor;
}
else
{
left_hsv.h -= (1.0 - (right_hsv.h - left_hsv.h)) * factor;
left_hsv[0] -= (1.0 - (right_hsv[0] - left_hsv[0])) * factor;
if (left_hsv.h < 0.0)
left_hsv.h += 1.0;
if (left_hsv[0] < 0.0)
left_hsv[0] += 1.0;
}
break;
@ -618,14 +638,17 @@ gimp_gradient_get_color_at (GimpGradient *gradient,
break;
}
gimp_hsv_to_rgb (&left_hsv, &rgb);
gegl_color_set_pixel (*color, babl_format ("HSV double"), left_hsv);
}
/* Calculate alpha */
rgb.a = left_color.a + (right_color.a - left_color.a) * factor;
gegl_color_get_rgba (left_color, NULL, NULL, NULL, &left_alpha);
gegl_color_get_rgba (right_color, NULL, NULL, NULL, &right_alpha);
gimp_color_set_alpha (*color, left_alpha + (right_alpha - left_alpha) * factor);
*color = rgb;
g_object_unref (left_color);
g_object_unref (right_color);
return seg;
}
@ -663,7 +686,7 @@ gimp_gradient_split_at (GimpGradient *gradient,
GimpGradientSegment **newl,
GimpGradientSegment **newr)
{
GimpRGB color;
GeglColor *color = NULL;
GimpGradientSegment *newseg;
g_return_if_fail (GIMP_IS_GRADIENT (gradient));
@ -703,11 +726,15 @@ gimp_gradient_split_at (GimpGradient *gradient,
/* Set colors of both segments */
g_clear_object (&newseg->right_color);
g_clear_object (&newseg->left_color);
newseg->right_color_type = seg->right_color_type;
newseg->right_color = seg->right_color;
seg->right_color_type = newseg->left_color_type = GIMP_GRADIENT_COLOR_FIXED;
seg->right_color = newseg->left_color = color;
seg->right_color = color;
newseg->left_color = gegl_color_duplicate (color);
/* Set parameters of new segment */
@ -736,15 +763,17 @@ gimp_gradient_flatten (GimpGradient *gradient,
for (seg = flat->segments; seg; seg = seg->next)
{
gimp_gradient_segment_get_left_flat_color (gradient,
context, seg,
&seg->left_color);
GeglColor *color;
color = gimp_gradient_segment_get_left_flat_color (gradient, context, seg);
g_clear_object (&seg->left_color);
seg->left_color = color;
seg->left_color_type = GIMP_GRADIENT_COLOR_FIXED;
gimp_gradient_segment_get_right_flat_color (gradient,
context, seg,
&seg->right_color);
color = gimp_gradient_segment_get_right_flat_color (gradient, context, seg);
g_clear_object (&seg->right_color);
seg->right_color = color;
seg->right_color_type = GIMP_GRADIENT_COLOR_FIXED;
}
@ -767,10 +796,10 @@ gimp_gradient_segment_new (void)
seg->right = 1.0;
seg->left_color_type = GIMP_GRADIENT_COLOR_FIXED;
gimp_rgba_set (&seg->left_color, 0.0, 0.0, 0.0, 1.0);
seg->left_color = gegl_color_new ("black");
seg->right_color_type = GIMP_GRADIENT_COLOR_FIXED;
gimp_rgba_set (&seg->right_color, 1.0, 1.0, 1.0, 1.0);
seg->right_color = gegl_color_new ("white");
seg->type = GIMP_GRADIENT_SEGMENT_LINEAR;
seg->color = GIMP_GRADIENT_SEGMENT_RGB;
@ -786,15 +815,29 @@ gimp_gradient_segment_free (GimpGradientSegment *seg)
{
g_return_if_fail (seg != NULL);
g_clear_object (&seg->right_color);
g_clear_object (&seg->left_color);
g_slice_free (GimpGradientSegment, seg);
}
void
gimp_gradient_segments_free (GimpGradientSegment *seg)
{
GimpGradientSegment *current = seg;
GimpGradientSegment *next;
g_return_if_fail (seg != NULL);
g_slice_free_chain (GimpGradientSegment, seg, next);
if (seg->prev)
seg->prev->next = NULL;
do
{
next = current->next;
gimp_gradient_segment_free (current);
current = next;
}
while (next);
}
GimpGradientSegment *
@ -891,6 +934,8 @@ gimp_gradient_segment_split_uniform (GimpGradient *gradient,
for (i = 0; i < parts; i++)
{
GeglColor *color = NULL;
seg = gimp_gradient_segment_new ();
if (i == 0)
@ -905,10 +950,16 @@ gimp_gradient_segment_split_uniform (GimpGradient *gradient,
gimp_gradient_get_color_at (gradient, context, lseg,
seg->left, FALSE, blend_color_space,
&seg->left_color);
&color);
g_clear_object (&seg->left_color);
seg->left_color = color;
color = NULL;
gimp_gradient_get_color_at (gradient, context, lseg,
seg->right, FALSE, blend_color_space,
&seg->right_color);
&color);
g_clear_object (&seg->right_color);
seg->right_color = color;
seg->type = lseg->type;
seg->color = lseg->color;
@ -925,10 +976,12 @@ gimp_gradient_segment_split_uniform (GimpGradient *gradient,
/* Fix edges */
tmp->left_color_type = lseg->left_color_type;
tmp->left_color = lseg->left_color;
g_clear_object (&tmp->left_color);
tmp->left_color = gegl_color_duplicate (lseg->left_color);
seg->right_color_type = lseg->right_color_type;
seg->right_color = lseg->right_color;
g_clear_object (&seg->right_color);
seg->right_color = gegl_color_duplicate (lseg->right_color);
tmp->left = lseg->left;
seg->right = lseg->right; /* To squish accumulative error */
@ -956,61 +1009,57 @@ gimp_gradient_segment_split_uniform (GimpGradient *gradient,
gimp_data_thaw (GIMP_DATA (gradient));
}
void
GeglColor *
gimp_gradient_segment_get_left_color (GimpGradient *gradient,
GimpGradientSegment *seg,
GimpRGB *color)
GimpGradientSegment *seg)
{
g_return_if_fail (GIMP_IS_GRADIENT (gradient));
g_return_if_fail (seg != NULL);
g_return_if_fail (color != NULL);
g_return_val_if_fail (GIMP_IS_GRADIENT (gradient), NULL);
g_return_val_if_fail (seg != NULL, NULL);
*color = seg->left_color;
return seg->left_color;
}
void
gimp_gradient_segment_set_left_color (GimpGradient *gradient,
GimpGradientSegment *seg,
const GimpRGB *color)
GeglColor *color)
{
g_return_if_fail (GIMP_IS_GRADIENT (gradient));
g_return_if_fail (seg != NULL);
g_return_if_fail (color != NULL);
g_return_if_fail (GEGL_IS_COLOR (color));
gimp_data_freeze (GIMP_DATA (gradient));
gimp_gradient_segment_range_blend (gradient, seg, seg,
color, &seg->right_color,
color, seg->right_color,
TRUE, TRUE);
gimp_data_thaw (GIMP_DATA (gradient));
}
void
GeglColor *
gimp_gradient_segment_get_right_color (GimpGradient *gradient,
GimpGradientSegment *seg,
GimpRGB *color)
GimpGradientSegment *seg)
{
g_return_if_fail (GIMP_IS_GRADIENT (gradient));
g_return_if_fail (seg != NULL);
g_return_if_fail (color != NULL);
g_return_val_if_fail (GIMP_IS_GRADIENT (gradient), NULL);
g_return_val_if_fail (seg != NULL, NULL);
*color = seg->right_color;
return seg->right_color;
}
void
gimp_gradient_segment_set_right_color (GimpGradient *gradient,
GimpGradientSegment *seg,
const GimpRGB *color)
GeglColor *color)
{
g_return_if_fail (GIMP_IS_GRADIENT (gradient));
g_return_if_fail (seg != NULL);
g_return_if_fail (color != NULL);
g_return_if_fail (GEGL_IS_COLOR (color));
gimp_data_freeze (GIMP_DATA (gradient));
gimp_gradient_segment_range_blend (gradient, seg, seg,
&seg->left_color, color,
seg->left_color, color,
TRUE, TRUE);
gimp_data_thaw (GIMP_DATA (gradient));
@ -1066,34 +1115,28 @@ gimp_gradient_segment_set_right_color_type (GimpGradient *gradient,
gimp_data_thaw (GIMP_DATA (gradient));
}
void
GeglColor *
gimp_gradient_segment_get_left_flat_color (GimpGradient *gradient,
GimpContext *context,
GimpGradientSegment *seg,
GimpRGB *color)
GimpGradientSegment *seg)
{
g_return_if_fail (GIMP_IS_GRADIENT (gradient));
g_return_if_fail (seg != NULL);
g_return_if_fail (color != NULL);
g_return_val_if_fail (GIMP_IS_GRADIENT (gradient), NULL);
g_return_val_if_fail (seg != NULL, NULL);
gimp_gradient_get_flat_color (context,
&seg->left_color, seg->left_color_type,
color);
return gimp_gradient_get_flat_color (context,
seg->left_color, seg->left_color_type);
}
void
GeglColor *
gimp_gradient_segment_get_right_flat_color (GimpGradient *gradient,
GimpContext *context,
GimpGradientSegment *seg,
GimpRGB *color)
GimpGradientSegment *seg)
{
g_return_if_fail (GIMP_IS_GRADIENT (gradient));
g_return_if_fail (seg != NULL);
g_return_if_fail (color != NULL);
g_return_val_if_fail (GIMP_IS_GRADIENT (gradient), NULL);
g_return_val_if_fail (seg != NULL, NULL);
gimp_gradient_get_flat_color (context,
&seg->right_color, seg->right_color_type,
color);
return gimp_gradient_get_flat_color (context,
seg->right_color, seg->right_color_type);
}
gdouble
@ -1320,15 +1363,26 @@ void
gimp_gradient_segment_range_blend (GimpGradient *gradient,
GimpGradientSegment *lseg,
GimpGradientSegment *rseg,
const GimpRGB *rgb1,
const GimpRGB *rgb2,
GeglColor *color1,
GeglColor *color2,
gboolean blend_colors,
gboolean blend_opacity)
{
GimpRGB d;
gdouble left, len;
GimpGradientSegment *seg;
GimpGradientSegment *aseg;
gdouble red1;
gdouble green1;
gdouble blue1;
gdouble alpha1;
gdouble red2;
gdouble green2;
gdouble blue2;
gdouble alpha2;
gdouble dred;
gdouble dgreen;
gdouble dblue;
gdouble dalpha;
g_return_if_fail (GIMP_IS_GRADIENT (gradient));
g_return_if_fail (lseg != NULL);
@ -1338,10 +1392,15 @@ gimp_gradient_segment_range_blend (GimpGradient *gradient,
if (! rseg)
rseg = gimp_gradient_segment_get_last (lseg);
d.r = rgb2->r - rgb1->r;
d.g = rgb2->g - rgb1->g;
d.b = rgb2->b - rgb1->b;
d.a = rgb2->a - rgb1->a;
/* TODO: currently doing this computation with sRGB value, because that's what
* was done historically. Is it right though?
*/
gegl_color_get_rgba_with_space (color1, &red1, &green1, &blue1, &alpha1, NULL);
gegl_color_get_rgba_with_space (color2, &red2, &green2, &blue2, &alpha2, NULL);
dred = red2 - red1;
dgreen = green2 - green1;
dblue = blue2 - blue1;
dalpha = alpha2 - alpha1;
left = lseg->left;
len = rseg->right - left;
@ -1350,21 +1409,50 @@ gimp_gradient_segment_range_blend (GimpGradient *gradient,
do
{
gdouble seg_left_red;
gdouble seg_left_green;
gdouble seg_left_blue;
gdouble seg_left_alpha;
gdouble seg_right_red;
gdouble seg_right_green;
gdouble seg_right_blue;
gdouble seg_right_alpha;
if (blend_colors)
{
seg->left_color.r = rgb1->r + (seg->left - left) / len * d.r;
seg->left_color.g = rgb1->g + (seg->left - left) / len * d.g;
seg->left_color.b = rgb1->b + (seg->left - left) / len * d.b;
seg_left_red = red1 + (seg->left - left) / len * dred;
seg_left_green = green1 + (seg->left - left) / len * dgreen;
seg_left_blue = blue1 + (seg->left - left) / len * dblue;
seg->right_color.r = rgb1->r + (seg->right - left) / len * d.r;
seg->right_color.g = rgb1->g + (seg->right - left) / len * d.g;
seg->right_color.b = rgb1->b + (seg->right - left) / len * d.b;
seg_right_red = red1 + (seg->right - left) / len * dred;
seg_right_green = green1 + (seg->right - left) / len * dgreen;
seg_right_blue = blue1 + (seg->right - left) / len * dblue;
}
else if (blend_opacity)
{
gegl_color_get_rgba_with_space (seg->left_color, &seg_left_red, &seg_left_green,
&seg_left_blue, NULL, NULL);
gegl_color_get_rgba_with_space (seg->right_color, &seg_right_red, &seg_right_green,
&seg_right_blue, NULL, NULL);
}
if (blend_opacity)
{
seg->left_color.a = rgb1->a + (seg->left - left) / len * d.a;
seg->right_color.a = rgb1->a + (seg->right - left) / len * d.a;
seg_left_alpha = alpha1 + (seg->left - left) / len * dalpha;
seg_right_alpha = alpha1 + (seg->right - left) / len * dalpha;
}
else if (blend_colors)
{
gegl_color_get_rgba_with_space (seg->left_color, NULL, NULL, NULL, &seg_left_alpha, NULL);
gegl_color_get_rgba_with_space (seg->right_color, NULL, NULL, NULL, &seg_right_alpha, NULL);
}
if (blend_colors || blend_opacity)
{
gegl_color_set_rgba_with_space (seg->left_color, seg_left_red, seg_left_green,
seg_left_blue, seg_left_alpha, NULL);
gegl_color_set_rgba_with_space (seg->right_color, seg_right_red, seg_right_green,
seg_right_blue, seg_right_alpha, NULL);
}
aseg = seg;
@ -1465,16 +1553,21 @@ gimp_gradient_segment_range_flip (GimpGradient *gradient,
tmp = seg; /* Remember first segment */
}
else
seg->left = left + right - oseg->right;
{
seg->left = left + right - oseg->right;
}
seg->middle = left + right - oseg->middle;
seg->right = left + right - oseg->left;
g_clear_object (&seg->left_color);
g_clear_object (&seg->right_color);
seg->left_color_type = oseg->right_color_type;
seg->left_color = oseg->right_color;
seg->left_color = gegl_color_duplicate (oseg->right_color);
seg->right_color_type = oseg->left_color_type;
seg->right_color = oseg->left_color;
seg->right_color = gegl_color_duplicate (oseg->left_color);
switch (oseg->type)
{
@ -1629,11 +1722,14 @@ gimp_gradient_segment_range_replicate (GimpGradient *gradient,
seg->middle = new_left + factor * (oseg->middle - sel_left);
seg->right = new_left + factor * (oseg->right - sel_left);
g_clear_object (&seg->left_color);
g_clear_object (&seg->right_color);
seg->left_color_type = oseg->left_color_type;
seg->left_color = oseg->left_color;
seg->left_color = gegl_color_duplicate (oseg->left_color);
seg->right_color_type = oseg->right_color_type;
seg->right_color = oseg->right_color;
seg->right_color = gegl_color_duplicate (oseg->right_color);
seg->type = oseg->type;
seg->color = oseg->color;
@ -1908,11 +2004,15 @@ gimp_gradient_segment_range_merge (GimpGradient *gradient,
gimp_data_freeze (GIMP_DATA (gradient));
if (start_seg == end_seg)
goto out;
/* Copy the end segment's right position and color to the start segment */
start_seg->right = end_seg->right;
start_seg->right_color_type = end_seg->right_color_type;
start_seg->right_color = end_seg->right_color;
g_clear_object (&start_seg->right_color);
start_seg->right_color = gegl_color_duplicate (end_seg->right_color);
/* Center the start segment's midpoint */
@ -1948,6 +2048,8 @@ gimp_gradient_segment_range_merge (GimpGradient *gradient,
seg = prev;
}
out:
if (final_start_seg)
*final_start_seg = start_seg;
if (final_end_seg)
@ -2193,41 +2295,37 @@ gimp_gradient_get_segment_at_internal (GimpGradient *gradient,
return seg;
}
static void
static GeglColor *
gimp_gradient_get_flat_color (GimpContext *context,
const GimpRGB *rgb,
GimpGradientColor color_type,
GimpRGB *flat_color)
GeglColor *color,
GimpGradientColor color_type)
{
GeglColor *color = NULL;
GeglColor *flat_color = NULL;
switch (color_type)
{
case GIMP_GRADIENT_COLOR_FIXED:
*flat_color = *rgb;
flat_color = gegl_color_duplicate (color);
break;
case GIMP_GRADIENT_COLOR_FOREGROUND:
case GIMP_GRADIENT_COLOR_FOREGROUND_TRANSPARENT:
color = gegl_color_duplicate (gimp_context_get_foreground (context));
flat_color = gegl_color_duplicate (gimp_context_get_foreground (context));
if (color_type == GIMP_GRADIENT_COLOR_FOREGROUND_TRANSPARENT)
gimp_color_set_alpha (color, 0.0);
gimp_color_set_alpha (flat_color, 0.0);
break;
case GIMP_GRADIENT_COLOR_BACKGROUND:
case GIMP_GRADIENT_COLOR_BACKGROUND_TRANSPARENT:
color = gegl_color_duplicate (gimp_context_get_background (context));
flat_color = gegl_color_duplicate (gimp_context_get_background (context));
if (color_type == GIMP_GRADIENT_COLOR_BACKGROUND_TRANSPARENT)
gimp_color_set_alpha (color, 0.0);
gimp_color_set_alpha (flat_color, 0.0);
break;
}
if (color != NULL)
gegl_color_get_rgba_with_space (color, &flat_color->r, &flat_color->g, &flat_color->b, &flat_color->a, NULL);
g_clear_object (&color);
return flat_color;
}
static inline gdouble

View File

@ -30,9 +30,9 @@ struct _GimpGradientSegment
gdouble left, middle, right;
GimpGradientColor left_color_type;
GimpRGB left_color;
GeglColor *left_color;
GimpGradientColor right_color_type;
GimpRGB right_color;
GeglColor *right_color;
GimpGradientSegmentType type; /* Segment's blending function */
GimpGradientSegmentColor color; /* Segment's coloring type */
@ -71,22 +71,22 @@ GimpData * gimp_gradient_new (GimpContext *context,
const gchar *name);
GimpData * gimp_gradient_get_standard (GimpContext *context);
GimpGradientSegment * gimp_gradient_get_color_at (GimpGradient *gradient,
GimpContext *context,
GimpGradientSegment *seg,
gdouble pos,
gboolean reverse,
GimpGradientBlendColorSpace blend_color_space,
GimpRGB *color);
GimpGradientSegment * gimp_gradient_get_segment_at (GimpGradient *grad,
gdouble pos);
void gimp_gradient_split_at (GimpGradient *gradient,
GimpContext *context,
GimpGradientSegment *seg,
gdouble pos,
GimpGradientBlendColorSpace blend_color_space,
GimpGradientSegment **newl,
GimpGradientSegment **newr);
GimpGradientSegment * gimp_gradient_get_color_at (GimpGradient *gradient,
GimpContext *context,
GimpGradientSegment *seg,
gdouble pos,
gboolean reverse,
GimpGradientBlendColorSpace blend_color_space,
GeglColor **color);
GimpGradientSegment * gimp_gradient_get_segment_at (GimpGradient *grad,
gdouble pos);
void gimp_gradient_split_at (GimpGradient *gradient,
GimpContext *context,
GimpGradientSegment *seg,
gdouble pos,
GimpGradientBlendColorSpace blend_color_space,
GimpGradientSegment **newl,
GimpGradientSegment **newr);
gboolean gimp_gradient_has_fg_bg_segments (GimpGradient *gradient);
GimpGradient * gimp_gradient_flatten (GimpGradient *gradient,
@ -104,37 +104,35 @@ GimpGradientSegment * gimp_gradient_segment_get_nth (GimpGradientSegment *seg,
void gimp_gradient_segment_free (GimpGradientSegment *seg);
void gimp_gradient_segments_free (GimpGradientSegment *seg);
void gimp_gradient_segment_split_midpoint (GimpGradient *gradient,
GimpContext *context,
GimpGradientSegment *lseg,
GimpGradientBlendColorSpace blend_color_space,
GimpGradientSegment **newl,
GimpGradientSegment **newr);
void gimp_gradient_segment_split_uniform (GimpGradient *gradient,
GimpContext *context,
GimpGradientSegment *lseg,
gint parts,
GimpGradientBlendColorSpace blend_color_space,
GimpGradientSegment **newl,
GimpGradientSegment **newr);
void gimp_gradient_segment_split_midpoint (GimpGradient *gradient,
GimpContext *context,
GimpGradientSegment *lseg,
GimpGradientBlendColorSpace blend_color_space,
GimpGradientSegment **newl,
GimpGradientSegment **newr);
void gimp_gradient_segment_split_uniform (GimpGradient *gradient,
GimpContext *context,
GimpGradientSegment *lseg,
gint parts,
GimpGradientBlendColorSpace blend_color_space,
GimpGradientSegment **newl,
GimpGradientSegment **newr);
/* Colors Setting/Getting Routines */
void gimp_gradient_segment_get_left_color (GimpGradient *gradient,
GimpGradientSegment *seg,
GimpRGB *color);
GeglColor * gimp_gradient_segment_get_left_color (GimpGradient *gradient,
GimpGradientSegment *seg);
void gimp_gradient_segment_set_left_color (GimpGradient *gradient,
GimpGradientSegment *seg,
const GimpRGB *color);
void gimp_gradient_segment_set_left_color (GimpGradient *gradient,
GimpGradientSegment *seg,
GeglColor *color);
void gimp_gradient_segment_get_right_color (GimpGradient *gradient,
GimpGradientSegment *seg,
GimpRGB *color);
GeglColor * gimp_gradient_segment_get_right_color (GimpGradient *gradient,
GimpGradientSegment *seg);
void gimp_gradient_segment_set_right_color (GimpGradient *gradient,
GimpGradientSegment *seg,
const GimpRGB *color);
void gimp_gradient_segment_set_right_color (GimpGradient *gradient,
GimpGradientSegment *seg,
GeglColor *color);
GimpGradientColor
@ -157,18 +155,16 @@ gimp_gradient_segment_set_right_color_type (GimpGradient *gradient,
GimpGradientColor color_type);
void
GeglColor *
gimp_gradient_segment_get_left_flat_color (GimpGradient *gradient,
GimpContext *context,
GimpGradientSegment *seg,
GimpRGB *color);
GimpGradientSegment *seg);
void
GeglColor *
gimp_gradient_segment_get_right_flat_color (GimpGradient *gradient,
GimpContext *context,
GimpGradientSegment *seg,
GimpRGB *color);
GimpGradientSegment *seg);
/* Position Setting/Getting Routines */
@ -216,8 +212,8 @@ void gimp_gradient_segment_range_compress (GimpGradient *gradient,
void gimp_gradient_segment_range_blend (GimpGradient *gradient,
GimpGradientSegment *lseg,
GimpGradientSegment *rseg,
const GimpRGB *rgb1,
const GimpRGB *rgb2,
GeglColor *color1,
GeglColor *color2,
gboolean blend_colors,
gboolean blend_opacity);

View File

@ -56,7 +56,6 @@ gimp_palette_import_from_gradient (GimpGradient *gradient,
GimpPalette *palette;
GimpGradientSegment *seg = NULL;
gdouble dx, cur_x;
GimpRGB color;
gint i;
g_return_val_if_fail (GIMP_IS_GRADIENT (gradient), NULL);
@ -70,10 +69,19 @@ gimp_palette_import_from_gradient (GimpGradient *gradient,
for (i = 0, cur_x = 0; i < n_colors; i++, cur_x += dx)
{
GeglColor *color = NULL;
GimpRGB rgb;
seg = gimp_gradient_get_color_at (gradient, context,
seg, cur_x, reverse, blend_color_space,
&color);
gimp_palette_add_entry (palette, -1, NULL, &color);
g_return_val_if_fail (color != NULL, palette);
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), &rgb);
gimp_palette_add_entry (palette, -1, NULL, &rgb);
g_clear_object (&color);
}
return palette;

View File

@ -455,6 +455,9 @@ gimp_operation_gradient_set_property (GObject *object,
{
GimpGradient *gradient = g_value_get_object (value);
if (gradient)
g_object_ref (gradient);
g_clear_object (&self->gradient);
if (gradient)
@ -466,6 +469,7 @@ gimp_operation_gradient_set_property (GObject *object,
}
gimp_operation_gradient_invalidate_cache (self);
g_clear_object (&gradient);
}
break;
@ -877,7 +881,7 @@ gradient_calc_shapeburst_dimpled_factor (GeglSampler *dist_sampler,
static void
gradient_render_pixel (gdouble x,
gdouble y,
GimpRGB *color,
GimpRGB *rgb,
gpointer render_data)
{
RenderBlendData *rbd = render_data;
@ -990,7 +994,7 @@ gradient_render_pixel (gdouble x,
case GIMP_REPEAT_TRUNCATE:
if (factor < 0.0 || factor > 1.0)
{
gimp_rgba_set (color, 0.0, 0.0, 0.0, 0.0);
gimp_rgba_set (rgb, 0.0, 0.0, 0.0, 0.0);
return;
}
break;
@ -1002,16 +1006,22 @@ gradient_render_pixel (gdouble x,
{
factor = CLAMP (factor, 0.0, 1.0);
*color =
*rgb =
rbd->gradient_cache[ROUND (factor * (rbd->gradient_cache_size - 1))];
}
else
{
GeglColor *color = NULL;
rbd->last_seg = gimp_gradient_get_color_at (rbd->gradient, NULL,
rbd->last_seg, factor,
rbd->reverse,
rbd->blend_color_space,
color);
&color);
if (color)
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), rgb);
g_clear_object (&color);
}
}
@ -1270,13 +1280,18 @@ gimp_operation_gradient_validate_cache (GimpOperationGradient *self)
for (i = 0; i < self->gradient_cache_size; i++)
{
gdouble factor = (gdouble) i / (gdouble) (self->gradient_cache_size - 1);
GeglColor *color = NULL;
gdouble factor = (gdouble) i / (gdouble) (self->gradient_cache_size - 1);
last_seg = gimp_gradient_get_color_at (self->gradient, NULL, last_seg,
factor,
self->gradient_reverse,
self->gradient_blend_color_space,
self->gradient_cache + i);
&color);
if (color)
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), self->gradient_cache + i);
g_clear_object (&color);
}
g_mutex_unlock (&self->gradient_cache_mutex);

View File

@ -188,6 +188,7 @@ gimp_paintbrush_real_get_paint_params (GimpPaintbrush *paintbrush,
GimpBrushCore *brush_core = GIMP_BRUSH_CORE (paintbrush);
GimpContext *context = GIMP_CONTEXT (paint_options);
GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
GeglColor *color = NULL;
*paint_mode = gimp_context_get_paint_mode (context);
@ -195,13 +196,16 @@ gimp_paintbrush_real_get_paint_params (GimpPaintbrush *paintbrush,
gimp_paint_options_get_gradient_color (paint_options, image,
grad_point,
paint_core->pixel_dist,
paint_color))
&color))
{
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), paint_color);
/* optionally take the color from the current gradient */
gimp_pickable_srgb_to_image_color (GIMP_PICKABLE (drawable),
paint_color, paint_color);
*paint_appl_mode = GIMP_PAINT_INCREMENTAL;
g_clear_object (&color);
}
else if (brush_core->brush && gimp_brush_get_pixmap (brush_core->brush))
{
@ -215,7 +219,6 @@ gimp_paintbrush_real_get_paint_params (GimpPaintbrush *paintbrush,
else
{
/* otherwise fill the area with the foreground color */
GeglColor *color;
color = gimp_context_get_foreground (context);
gegl_color_get_rgba_with_space (color, &paint_color->r, &paint_color->g, &paint_color->b, &paint_color->a, NULL);

View File

@ -1054,17 +1054,17 @@ gimp_paint_options_get_jitter (GimpPaintOptions *paint_options,
}
gboolean
gimp_paint_options_get_gradient_color (GimpPaintOptions *paint_options,
GimpImage *image,
gdouble grad_point,
gdouble pixel_dist,
GimpRGB *color)
gimp_paint_options_get_gradient_color (GimpPaintOptions *paint_options,
GimpImage *image,
gdouble grad_point,
gdouble pixel_dist,
GeglColor **color)
{
GimpDynamics *dynamics;
g_return_val_if_fail (GIMP_IS_PAINT_OPTIONS (paint_options), FALSE);
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
g_return_val_if_fail (color != NULL, FALSE);
g_return_val_if_fail (color != NULL && *color == NULL, FALSE);
dynamics = gimp_context_get_dynamics (GIMP_CONTEXT (paint_options));

View File

@ -149,7 +149,7 @@ gboolean gimp_paint_options_get_gradient_color (GimpPaintOptions *options,
GimpImage *image,
gdouble grad_point,
gdouble pixel_dist,
GimpRGB *color);
GeglColor **color);
GimpBrushApplicationMode
gimp_paint_options_get_brush_mode (GimpPaintOptions *options);

View File

@ -366,8 +366,8 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
gdouble flow;
gdouble grad_point;
/* brush color */
GimpRGB brush_color;
GimpRGB *brush_color_ptr; /* whether use single color or pixmap */
GeglColor *brush_color = NULL;
GimpRGB brush_rgb; /* whether use single color or pixmap */
/* accum buffer */
gint x, y;
GeglBuffer *accum_buffer;
@ -441,7 +441,6 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
fade_point);
/* Get current gradient color, brush pixmap, or foreground color */
brush_color_ptr = &brush_color;
if (gimp_paint_options_get_gradient_color (paint_options, image,
grad_point,
paint_core->pixel_dist,
@ -451,23 +450,12 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
}
else if (brush_core->brush && gimp_brush_get_pixmap (brush_core->brush))
{
brush_color_ptr = NULL;
}
else
{
GeglColor *color;
color = gimp_context_get_foreground (context);
gegl_color_get_rgba_with_space (color, &brush_color.r, &brush_color.g, &brush_color.b, &brush_color.a, NULL);
brush_color = g_object_ref (gimp_context_get_foreground (context));
}
/* Convert to linear RGBA */
if (brush_color_ptr)
gimp_pickable_rgb_to_pixel (dest_pickable,
&brush_color,
babl_format ("RGBA double"),
&brush_color);
n_strokes = gimp_symmetry_get_size (sym);
for (i = 0; i < n_strokes; i++)
{
@ -514,7 +502,7 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
* gimp_gegl_smudge_with_paint() instead of calling
* gegl_buffer_set_color() to reduce gegl's internal processing.
*/
if (! brush_color_ptr && flow > 0.0)
if (! brush_color && flow > 0.0)
{
gimp_brush_core_color_area_with_pixmap (brush_core, drawable,
&coords,
@ -524,6 +512,10 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
TRUE);
}
if (brush_color)
/* Convert to linear RGBA */
gegl_color_get_pixel (brush_color, babl_format ("RGBA double"), &brush_rgb);
gimp_gegl_smudge_with_paint (accum_buffer,
GEGL_RECTANGLE (paint_buffer_x - x,
paint_buffer_y - y,
@ -536,7 +528,7 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
dest_pickable_off_y,
paint_buffer_width,
paint_buffer_height),
brush_color_ptr,
brush_color ? &brush_rgb : NULL,
paint_buffer,
options->no_erasing,
flow,
@ -559,6 +551,8 @@ gimp_smudge_motion (GimpPaintCore *paint_core,
force,
GIMP_PAINT_INCREMENTAL);
}
g_clear_object (&brush_color);
}
static void

View File

@ -21,15 +21,12 @@
#include "stamp-pdbgen.h"
#include <cairo.h>
#include <string.h>
#include <gegl.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "libgimpcolor/gimpcolor.h"
#include "libgimpbase/gimpbase.h"
#include "pdb-types.h"
@ -178,23 +175,27 @@ gradient_get_uniform_samples_invoker (GimpProcedure *procedure,
num_color_samples = num_samples * 4;
sample = color_samples = g_new (gdouble, num_color_samples);
sample = color_samples = g_new0 (gdouble, num_color_samples);
while (num_samples--)
{
GimpRGB color;
GeglColor *color = NULL;
seg = gimp_gradient_get_color_at (gradient, context, seg,
pos, reverse,
GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
&color);
/* XXX "float" in PDB are in fact double. */
if (color)
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), sample);
/* TODO: should we really return a list of floats? What about a list
* of GeglColor?
*/
*sample++ = color.r;
*sample++ = color.g;
*sample++ = color.b;
*sample++ = color.a;
sample += 4;
pos += delta;
pos += delta;
g_clear_object (&color);
}
}
else
@ -244,11 +245,11 @@ gradient_get_custom_samples_invoker (GimpProcedure *procedure,
num_color_samples = num_samples * 4;
sample = color_samples = g_new (gdouble, num_color_samples);
sample = color_samples = g_new0 (gdouble, num_color_samples);
while (num_samples--)
{
GimpRGB color;
GeglColor *color = NULL;
seg = gimp_gradient_get_color_at (gradient, context,
seg, *positions,
@ -256,12 +257,13 @@ gradient_get_custom_samples_invoker (GimpProcedure *procedure,
GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
&color);
*sample++ = color.r;
*sample++ = color.g;
*sample++ = color.b;
*sample++ = color.a;
if (color)
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), sample);
sample += 4;
positions++;
g_clear_object (&color);
}
}
else
@ -292,8 +294,7 @@ gradient_segment_get_left_color_invoker (GimpProcedure *procedure,
GimpValueArray *return_vals;
GimpGradient *gradient;
gint segment;
GimpRGB color = { 0.0, 0.0, 0.0, 1.0 };
gdouble opacity = 0.0;
GeglColor *color = NULL;
gradient = g_value_get_object (gimp_value_array_index (args, 0));
segment = g_value_get_int (gimp_value_array_index (args, 1));
@ -305,10 +306,7 @@ gradient_segment_get_left_color_invoker (GimpProcedure *procedure,
seg = gimp_gradient_segment_get_nth (gradient->segments, segment);
if (seg)
{
gimp_gradient_segment_get_left_color (gradient, seg, &color);
opacity = color.a * 100.0;
}
color = g_object_ref (gimp_gradient_segment_get_left_color (gradient, seg));
else
success = FALSE;
}
@ -317,10 +315,7 @@ gradient_segment_get_left_color_invoker (GimpProcedure *procedure,
error ? *error : NULL);
if (success)
{
gimp_value_set_rgb (gimp_value_array_index (return_vals, 1), &color);
g_value_set_double (gimp_value_array_index (return_vals, 2), opacity);
}
g_value_take_object (gimp_value_array_index (return_vals, 1), color);
return return_vals;
}
@ -336,30 +331,23 @@ gradient_segment_set_left_color_invoker (GimpProcedure *procedure,
gboolean success = TRUE;
GimpGradient *gradient;
gint segment;
GimpRGB color;
gdouble opacity;
GeglColor *color;
gradient = g_value_get_object (gimp_value_array_index (args, 0));
segment = g_value_get_int (gimp_value_array_index (args, 1));
gimp_value_get_rgb (gimp_value_array_index (args, 2), &color);
opacity = g_value_get_double (gimp_value_array_index (args, 3));
color = g_value_get_object (gimp_value_array_index (args, 2));
if (success)
{
if (gimp_data_is_writable (GIMP_DATA (gradient)))
{
GimpGradientSegment *seg = gimp_gradient_segment_get_nth (gradient->segments, segment);
GimpGradientSegment *seg = gimp_gradient_segment_get_nth (gradient->segments, segment);
if (seg)
{
color.a = opacity / 100.0;
gimp_gradient_segment_set_left_color (gradient, seg, &color);
}
else
{
if (seg)
gimp_gradient_segment_set_left_color (gradient, seg, color);
else
success = FALSE;
}
}
else
{
success = FALSE;
@ -382,8 +370,7 @@ gradient_segment_get_right_color_invoker (GimpProcedure *procedure,
GimpValueArray *return_vals;
GimpGradient *gradient;
gint segment;
GimpRGB color = { 0.0, 0.0, 0.0, 1.0 };
gdouble opacity = 0.0;
GeglColor *color = NULL;
gradient = g_value_get_object (gimp_value_array_index (args, 0));
segment = g_value_get_int (gimp_value_array_index (args, 1));
@ -395,10 +382,7 @@ gradient_segment_get_right_color_invoker (GimpProcedure *procedure,
seg = gimp_gradient_segment_get_nth (gradient->segments, segment);
if (seg)
{
gimp_gradient_segment_get_right_color (gradient, seg, &color);
opacity = color.a * 100.0;
}
color = g_object_ref (gimp_gradient_segment_get_right_color (gradient, seg));
else
success = FALSE;
}
@ -407,10 +391,7 @@ gradient_segment_get_right_color_invoker (GimpProcedure *procedure,
error ? *error : NULL);
if (success)
{
gimp_value_set_rgb (gimp_value_array_index (return_vals, 1), &color);
g_value_set_double (gimp_value_array_index (return_vals, 2), opacity);
}
g_value_take_object (gimp_value_array_index (return_vals, 1), color);
return return_vals;
}
@ -426,13 +407,11 @@ gradient_segment_set_right_color_invoker (GimpProcedure *procedure,
gboolean success = TRUE;
GimpGradient *gradient;
gint segment;
GimpRGB color;
gdouble opacity;
GeglColor *color;
gradient = g_value_get_object (gimp_value_array_index (args, 0));
segment = g_value_get_int (gimp_value_array_index (args, 1));
gimp_value_get_rgb (gimp_value_array_index (args, 2), &color);
opacity = g_value_get_double (gimp_value_array_index (args, 3));
color = g_value_get_object (gimp_value_array_index (args, 2));
if (success)
{
@ -441,10 +420,7 @@ gradient_segment_set_right_color_invoker (GimpProcedure *procedure,
GimpGradientSegment *seg = gimp_gradient_segment_get_nth (gradient->segments, segment);
if (seg)
{
color.a = opacity / 100.0;
gimp_gradient_segment_set_right_color (gradient, seg, &color);
}
gimp_gradient_segment_set_right_color (gradient, seg, color);
else
success = FALSE;
}
@ -1156,8 +1132,8 @@ gradient_segment_range_blend_colors_invoker (GimpProcedure *procedure,
if (start_seg && end_seg)
gimp_gradient_segment_range_blend (gradient,
start_seg, end_seg,
&start_seg->left_color,
&end_seg->right_color,
start_seg->left_color,
end_seg->right_color,
TRUE, FALSE);
else
success = FALSE;
@ -1202,8 +1178,8 @@ gradient_segment_range_blend_opacity_invoker (GimpProcedure *procedure,
if (start_seg && end_seg)
gimp_gradient_segment_range_blend (gradient,
start_seg, end_seg,
&start_seg->left_color,
&end_seg->right_color,
start_seg->left_color,
end_seg->right_color,
FALSE, TRUE);
else
success = FALSE;
@ -1493,18 +1469,11 @@ register_gradient_procs (GimpPDB *pdb)
0, G_MAXINT32, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
gimp_param_spec_rgb ("color",
"color",
"The return color",
FALSE,
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
g_param_spec_double ("opacity",
"opacity",
"The opacity of the endpoint",
-G_MAXDOUBLE, G_MAXDOUBLE, 0,
GIMP_PARAM_READWRITE));
gegl_param_spec_color ("color",
"color",
"The return color",
NULL,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
@ -1516,7 +1485,7 @@ register_gradient_procs (GimpPDB *pdb)
"gimp-gradient-segment-set-left-color");
gimp_procedure_set_static_help (procedure,
"Sets the left endpoint color of a segment",
"Sets the color of the left endpoint the indexed segment of the gradient.\n"
"Sets the color of the left endpoint the indexed segment of the gradient. The alpha channel of the [class@Gegl.Color] is taken into account.\n"
"Returns an error when gradient is not editable or index is out of range.",
NULL);
gimp_procedure_set_static_attribution (procedure,
@ -1536,18 +1505,11 @@ register_gradient_procs (GimpPDB *pdb)
0, G_MAXINT32, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_rgb ("color",
"color",
"The color to set",
FALSE,
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_double ("opacity",
"opacity",
"The opacity to set for the endpoint",
0, 100.0, 0,
GIMP_PARAM_READWRITE));
gegl_param_spec_color ("color",
"color",
"The color to set",
NULL,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
@ -1579,18 +1541,11 @@ register_gradient_procs (GimpPDB *pdb)
0, G_MAXINT32, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
gimp_param_spec_rgb ("color",
"color",
"The return color",
FALSE,
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_return_value (procedure,
g_param_spec_double ("opacity",
"opacity",
"The opacity of the endpoint",
-G_MAXDOUBLE, G_MAXDOUBLE, 0,
GIMP_PARAM_READWRITE));
gegl_param_spec_color ("color",
"color",
"The return color",
NULL,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);
@ -1602,7 +1557,7 @@ register_gradient_procs (GimpPDB *pdb)
"gimp-gradient-segment-set-right-color");
gimp_procedure_set_static_help (procedure,
"Sets the right endpoint color of the segment",
"Sets the right endpoint color of the segment of the gradient.\n"
"Sets the right endpoint color of the segment of the gradient. The alpha channel of the [class@Gegl.Color] is taken into account.\n"
"Returns an error when gradient is not editable or segment index is out of range.",
NULL);
gimp_procedure_set_static_attribution (procedure,
@ -1622,18 +1577,11 @@ register_gradient_procs (GimpPDB *pdb)
0, G_MAXINT32, 0,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
gimp_param_spec_rgb ("color",
"color",
"The color to set",
FALSE,
NULL,
GIMP_PARAM_READWRITE));
gimp_procedure_add_argument (procedure,
g_param_spec_double ("opacity",
"opacity",
"The opacity to set for the endpoint",
0, 100.0, 0,
GIMP_PARAM_READWRITE));
gegl_param_spec_color ("color",
"color",
"The color to set",
NULL,
GIMP_PARAM_READWRITE));
gimp_pdb_register_procedure (pdb, procedure);
g_object_unref (procedure);

View File

@ -22,6 +22,7 @@
#include <gdk/gdkkeysyms.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpcolor/gimpcolor.h"
#include "libgimpmath/gimpmath.h"
#include "libgimpwidgets/gimpwidgets.h"
@ -331,10 +332,7 @@ gimp_gradient_tool_editor_line_selection_changed (GimpToolLine *line,
seg = gimp_gradient_tool_editor_handle_get_segment (gradient_tool,
selection);
homogeneous = seg->right_color.r == seg->next->left_color.r &&
seg->right_color.g == seg->next->left_color.g &&
seg->right_color.b == seg->next->left_color.b &&
seg->right_color.a == seg->next->left_color.a &&
homogeneous = gimp_color_is_perceptually_identical (seg->right_color, seg->next->left_color) &&
seg->right_color_type == seg->next->left_color_type;
gimp_chain_button_set_active (
@ -401,7 +399,6 @@ gimp_gradient_tool_editor_color_entry_color_changed (GimpColorButton *button,
GimpPaintOptions *paint_options = GIMP_PAINT_OPTIONS (options);
gint selection;
GeglColor *color;
GimpRGB rgb;
Direction direction;
GtkWidget *chain_button;
GimpGradientSegment *seg;
@ -413,8 +410,6 @@ gimp_gradient_tool_editor_color_entry_color_changed (GimpColorButton *button,
gimp_tool_line_get_selection (GIMP_TOOL_LINE (gradient_tool->widget));
color = gimp_color_button_get_color (button);
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), &rgb);
g_object_unref (color);
direction =
GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button),
@ -445,12 +440,14 @@ gimp_gradient_tool_editor_color_entry_color_changed (GimpColorButton *button,
switch (selection)
{
case GIMP_TOOL_LINE_HANDLE_START:
seg->left_color = rgb;
g_clear_object (&seg->left_color);
seg->left_color = g_object_ref (color);
seg->left_color_type = GIMP_GRADIENT_COLOR_FIXED;
break;
case GIMP_TOOL_LINE_HANDLE_END:
seg->right_color = rgb;
g_clear_object (&seg->right_color);
seg->right_color = g_object_ref (color);
seg->right_color_type = GIMP_GRADIENT_COLOR_FIXED;
break;
@ -459,7 +456,8 @@ gimp_gradient_tool_editor_color_entry_color_changed (GimpColorButton *button,
(chain_button &&
gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (chain_button))))
{
seg->right_color = rgb;
g_clear_object (&seg->right_color);
seg->right_color = gegl_color_duplicate (color);
seg->right_color_type = GIMP_GRADIENT_COLOR_FIXED;
}
@ -467,13 +465,16 @@ gimp_gradient_tool_editor_color_entry_color_changed (GimpColorButton *button,
(chain_button &&
gimp_chain_button_get_active (GIMP_CHAIN_BUTTON (chain_button))))
{
seg->next->left_color = rgb;
g_clear_object (&seg->next->left_color);
seg->next->left_color = g_object_ref (color);
seg->next->left_color_type = GIMP_GRADIENT_COLOR_FIXED;
}
}
gimp_gradient_tool_editor_thaw_gradient (gradient_tool);
gimp_gradient_tool_editor_end_edit (gradient_tool, FALSE);
g_object_unref (color);
}
static void
@ -1574,8 +1575,7 @@ gimp_gradient_tool_editor_update_endpoint_gui (GimpGradientTool *gradient_tool,
const gchar *title;
gdouble x;
gdouble y;
GeglColor *color;
GimpRGB rgb;
GeglColor *color = NULL;
GimpGradientColor color_type;
editable = gimp_gradient_tool_editor_is_gradient_editable (gradient_tool);
@ -1622,16 +1622,16 @@ gimp_gradient_tool_editor_update_endpoint_gui (GimpGradientTool *gradient_tool,
case GIMP_TOOL_LINE_HANDLE_START:
title = _("Start Endpoint");
gimp_gradient_segment_get_left_flat_color (gradient_tool->gradient, context,
seg, &rgb);
color = gimp_gradient_segment_get_left_flat_color (gradient_tool->gradient, context,
seg);
color_type = seg->left_color_type;
break;
case GIMP_TOOL_LINE_HANDLE_END:
title = _("End Endpoint");
gimp_gradient_segment_get_right_flat_color (gradient_tool->gradient, context,
seg, &rgb);
color = gimp_gradient_segment_get_right_flat_color (gradient_tool->gradient, context,
seg);
color_type = seg->right_color_type;
break;
@ -1644,11 +1644,7 @@ gimp_gradient_tool_editor_update_endpoint_gui (GimpGradientTool *gradient_tool,
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (gradient_tool->endpoint_se), 0, x);
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (gradient_tool->endpoint_se), 1, y);
color = gegl_color_new (NULL);
gegl_color_set_pixel (color, babl_format ("R'G'B'A double"), &rgb);
gimp_color_button_set_color (
GIMP_COLOR_BUTTON (gradient_tool->endpoint_color_panel), color);
g_object_unref (color);
gimp_color_button_set_color (GIMP_COLOR_BUTTON (gradient_tool->endpoint_color_panel), color);
gimp_int_combo_box_set_active (
GIMP_INT_COMBO_BOX (gradient_tool->endpoint_type_combo), color_type);
@ -1656,6 +1652,8 @@ gimp_gradient_tool_editor_update_endpoint_gui (GimpGradientTool *gradient_tool,
gtk_widget_set_sensitive (gradient_tool->endpoint_type_combo, editable);
gtk_widget_show (gradient_tool->endpoint_editor);
g_object_unref (color);
}
static void
@ -1671,10 +1669,9 @@ gimp_gradient_tool_editor_update_stop_gui (GimpGradientTool *gradient_tool,
gdouble min;
gdouble max;
gdouble value;
GeglColor *color;
GimpRGB left_color;
GeglColor *left_color;
GimpGradientColor left_color_type;
GimpRGB right_color;
GeglColor *right_color;
GimpGradientColor right_color_type;
editable = gimp_gradient_tool_editor_is_gradient_editable (gradient_tool);
@ -1691,12 +1688,11 @@ gimp_gradient_tool_editor_update_stop_gui (GimpGradientTool *gradient_tool,
max = seg->next->right;
value = seg->right;
gimp_gradient_segment_get_right_flat_color (gradient_tool->gradient, context,
seg, &left_color);
left_color = gimp_gradient_segment_get_right_flat_color (gradient_tool->gradient, context, seg);
left_color_type = seg->right_color_type;
gimp_gradient_segment_get_left_flat_color (gradient_tool->gradient, context,
seg->next, &right_color);
right_color = gimp_gradient_segment_get_left_flat_color (gradient_tool->gradient, context,
seg->next);
right_color_type = seg->next->left_color_type;
gimp_tool_gui_set_title (gradient_tool->gui, title);
@ -1706,17 +1702,13 @@ gimp_gradient_tool_editor_update_stop_gui (GimpGradientTool *gradient_tool,
gimp_size_entry_set_refval (GIMP_SIZE_ENTRY (gradient_tool->stop_se),
0, 100.0 * value);
color = gegl_color_new (NULL);
gegl_color_set_pixel (color, babl_format ("R'G'B'A double"), &left_color);
gimp_color_button_set_color (
GIMP_COLOR_BUTTON (gradient_tool->stop_left_color_panel), color);
GIMP_COLOR_BUTTON (gradient_tool->stop_left_color_panel), left_color);
gimp_int_combo_box_set_active (
GIMP_INT_COMBO_BOX (gradient_tool->stop_left_type_combo), left_color_type);
gegl_color_set_pixel (color, babl_format ("R'G'B'A double"), &right_color);
gimp_color_button_set_color (
GIMP_COLOR_BUTTON (gradient_tool->stop_right_color_panel), color);
GIMP_COLOR_BUTTON (gradient_tool->stop_right_color_panel), right_color);
gimp_int_combo_box_set_active (
GIMP_INT_COMBO_BOX (gradient_tool->stop_right_type_combo), right_color_type);
@ -1731,7 +1723,8 @@ gimp_gradient_tool_editor_update_stop_gui (GimpGradientTool *gradient_tool,
editable);
g_free (title);
g_object_unref (color);
g_object_unref (left_color);
g_object_unref (right_color);
gtk_widget_show (gradient_tool->stop_editor);
}

View File

@ -435,18 +435,23 @@ gimp_gradient_editor_init (GimpGradientEditor *editor)
editor->hint_label4 = gradient_hint_label_add (GTK_BOX (hint_vbox));
/* Black, 50% Gray, White, Clear */
gimp_rgba_set (&editor->saved_colors[0], 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE);
gimp_rgba_set (&editor->saved_colors[1], 0.5, 0.5, 0.5, GIMP_OPACITY_OPAQUE);
gimp_rgba_set (&editor->saved_colors[2], 1.0, 1.0, 1.0, GIMP_OPACITY_OPAQUE);
gimp_rgba_set (&editor->saved_colors[3], 0.0, 0.0, 0.0, GIMP_OPACITY_TRANSPARENT);
editor->saved_colors[0] = gegl_color_new ("black");
editor->saved_colors[1] = gegl_color_new ("gray");
editor->saved_colors[2] = gegl_color_new ("white");
editor->saved_colors[3] = gegl_color_new ("transparent");
/* Red, Yellow, Green, Cyan, Blue, Magenta */
gimp_rgba_set (&editor->saved_colors[4], 1.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE);
gimp_rgba_set (&editor->saved_colors[5], 1.0, 1.0, 0.0, GIMP_OPACITY_OPAQUE);
gimp_rgba_set (&editor->saved_colors[6], 0.0, 1.0, 0.0, GIMP_OPACITY_OPAQUE);
gimp_rgba_set (&editor->saved_colors[7], 0.0, 1.0, 1.0, GIMP_OPACITY_OPAQUE);
gimp_rgba_set (&editor->saved_colors[8], 0.0, 0.0, 1.0, GIMP_OPACITY_OPAQUE);
gimp_rgba_set (&editor->saved_colors[9], 1.0, 0.0, 1.0, GIMP_OPACITY_OPAQUE);
editor->saved_colors[4] = gegl_color_new ("red");
editor->saved_colors[5] = gegl_color_new ("yellow");
/* XXX: green in GEGL is 0 0.5 0, so we override it. */
editor->saved_colors[6] = gegl_color_new ("green");
gegl_color_set_rgba_with_space (editor->saved_colors[6], 0.0, 1.0, 0.0, GIMP_OPACITY_OPAQUE, NULL);
/* XXX: Cyan */
editor->saved_colors[7] = gegl_color_new (NULL);
gegl_color_set_rgba_with_space (editor->saved_colors[7], 0.0, 1.0, 1.0, GIMP_OPACITY_OPAQUE, NULL);
editor->saved_colors[8] = gegl_color_new ("blue");
/* XXX: what we defined Magenta is "fuchsia" in GEGL. */
editor->saved_colors[9] = gegl_color_new ("fuchsia");
g_object_unref (transp);
}
@ -479,6 +484,9 @@ gimp_gradient_editor_dispose (GObject *object)
g_clear_object (&editor->zoom_gesture);
for (gint i = 0; i < GRAD_NUM_COLORS; i++)
g_clear_object (&editor->saved_colors[i]);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@ -594,6 +602,7 @@ void
gimp_gradient_editor_edit_left_color (GimpGradientEditor *editor)
{
GimpGradient *gradient;
GimpRGB rgb;
g_return_if_fail (GIMP_IS_GRADIENT_EDITOR (editor));
@ -607,6 +616,8 @@ gimp_gradient_editor_edit_left_color (GimpGradientEditor *editor)
editor->saved_dirty = gimp_data_is_dirty (GIMP_DATA (gradient));
editor->saved_segments = gradient_editor_save_selection (editor);
gegl_color_get_pixel (editor->control_sel_l->left_color, babl_format ("R'G'B'A double"),
&rgb);
editor->color_dialog =
gimp_color_dialog_new (GIMP_VIEWABLE (gradient),
GIMP_DATA_EDITOR (editor)->context,
@ -617,7 +628,7 @@ gimp_gradient_editor_edit_left_color (GimpGradientEditor *editor)
GTK_WIDGET (editor),
gimp_dialog_factory_get_singleton (),
"gimp-gradient-editor-color-dialog",
&editor->control_sel_l->left_color,
&rgb,
TRUE, TRUE);
g_signal_connect (editor->color_dialog, "destroy",
@ -639,6 +650,7 @@ void
gimp_gradient_editor_edit_right_color (GimpGradientEditor *editor)
{
GimpGradient *gradient;
GimpRGB rgb;
g_return_if_fail (GIMP_IS_GRADIENT_EDITOR (editor));
@ -652,6 +664,8 @@ gimp_gradient_editor_edit_right_color (GimpGradientEditor *editor)
editor->saved_dirty = gimp_data_is_dirty (GIMP_DATA (gradient));
editor->saved_segments = gradient_editor_save_selection (editor);
gegl_color_get_pixel (editor->control_sel_l->right_color, babl_format ("R'G'B'A double"),
&rgb);
editor->color_dialog =
gimp_color_dialog_new (GIMP_VIEWABLE (gradient),
GIMP_DATA_EDITOR (editor)->context,
@ -662,8 +676,7 @@ gimp_gradient_editor_edit_right_color (GimpGradientEditor *editor)
GTK_WIDGET (editor),
gimp_dialog_factory_get_singleton (),
"gimp-gradient-editor-color-dialog",
&editor->control_sel_l->right_color,
TRUE, TRUE);
&rgb, TRUE, TRUE);
g_signal_connect (editor->color_dialog, "destroy",
G_CALLBACK (gtk_widget_destroyed),
@ -840,7 +853,7 @@ static void
gradient_editor_drop_color (GtkWidget *widget,
gint x,
gint y,
const GimpRGB *color,
const GimpRGB *rgb,
gpointer data)
{
GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
@ -865,14 +878,14 @@ gradient_editor_drop_color (GtkWidget *widget,
{
lseg->right = xpos;
lseg->middle = (lseg->left + lseg->right) / 2.0;
lseg->right_color = *color;
gegl_color_set_pixel (lseg->right_color, babl_format ("R'G'B'A double"), rgb);
}
if (rseg)
{
rseg->left = xpos;
rseg->middle = (rseg->left + rseg->right) / 2.0;
rseg->left_color = *color;
gegl_color_set_pixel (rseg->left_color, babl_format ("R'G'B'A double"), rgb);
}
gimp_data_thaw (GIMP_DATA (gradient));
@ -882,7 +895,7 @@ static void
gradient_editor_control_drop_color (GtkWidget *widget,
gint x,
gint y,
const GimpRGB *color,
const GimpRGB *rgb,
gpointer data)
{
GimpGradientEditor *editor = GIMP_GRADIENT_EDITOR (data);
@ -915,10 +928,10 @@ gradient_editor_control_drop_color (GtkWidget *widget,
gimp_data_freeze (GIMP_DATA (gradient));
if (lseg)
lseg->right_color = *color;
gegl_color_set_pixel (lseg->right_color, babl_format ("R'G'B'A double"), rgb);
if (rseg)
rseg->left_color = *color;
gegl_color_set_pixel (rseg->left_color, babl_format ("R'G'B'A double"), rgb);
gimp_data_thaw (GIMP_DATA (gradient));
}
@ -1048,11 +1061,14 @@ gradient_editor_replace_selection (GimpGradientEditor *editor,
static void
gradient_editor_left_color_update (GimpColorDialog *dialog,
const GimpRGB *color,
const GimpRGB *rgb,
GimpColorDialogState state,
GimpGradientEditor *editor)
{
GimpGradient *gradient = GIMP_GRADIENT (GIMP_DATA_EDITOR (editor)->data);
GeglColor *color = gegl_color_new (NULL);
gegl_color_set_pixel (color, babl_format ("R'G'B'A double"), rgb);
switch (state)
{
@ -1061,7 +1077,7 @@ gradient_editor_left_color_update (GimpColorDialog *dialog,
editor->control_sel_l,
editor->control_sel_r,
color,
&editor->control_sel_r->right_color,
editor->control_sel_r->right_color,
TRUE, TRUE);
break;
@ -1070,7 +1086,7 @@ gradient_editor_left_color_update (GimpColorDialog *dialog,
editor->control_sel_l,
editor->control_sel_r,
color,
&editor->control_sel_r->right_color,
editor->control_sel_r->right_color,
TRUE, TRUE);
gimp_gradient_segments_free (editor->saved_segments);
gtk_widget_destroy (editor->color_dialog);
@ -1092,15 +1108,20 @@ gradient_editor_left_color_update (GimpColorDialog *dialog,
gimp_editor_get_popup_data (GIMP_EDITOR (editor)));
break;
}
g_object_unref (color);
}
static void
gradient_editor_right_color_update (GimpColorDialog *dialog,
const GimpRGB *color,
const GimpRGB *rgb,
GimpColorDialogState state,
GimpGradientEditor *editor)
{
GimpGradient *gradient = GIMP_GRADIENT (GIMP_DATA_EDITOR (editor)->data);
GeglColor *color = gegl_color_new (NULL);
gegl_color_set_pixel (color, babl_format ("R'G'B'A double"), rgb);
switch (state)
{
@ -1108,7 +1129,7 @@ gradient_editor_right_color_update (GimpColorDialog *dialog,
gimp_gradient_segment_range_blend (gradient,
editor->control_sel_l,
editor->control_sel_r,
&editor->control_sel_l->left_color,
editor->control_sel_l->left_color,
color,
TRUE, TRUE);
break;
@ -1117,7 +1138,7 @@ gradient_editor_right_color_update (GimpColorDialog *dialog,
gimp_gradient_segment_range_blend (gradient,
editor->control_sel_l,
editor->control_sel_r,
&editor->control_sel_l->left_color,
editor->control_sel_l->left_color,
color,
TRUE, TRUE);
gimp_gradient_segments_free (editor->saved_segments);
@ -1140,6 +1161,8 @@ gradient_editor_right_color_update (GimpColorDialog *dialog,
gimp_editor_get_popup_data (GIMP_EDITOR (editor)));
break;
}
g_object_unref (color);
}
@ -1285,9 +1308,9 @@ view_set_hint (GimpGradientEditor *editor,
gint x)
{
GimpDataEditor *data_editor = GIMP_DATA_EDITOR (editor);
GeglColor *color = gegl_color_new ("black");
GimpRGB rgb;
GimpHSV hsv;
GeglColor *color = NULL;
gdouble rgb[4];
gdouble hsv[3];
gdouble xpos;
gchar *str1;
gchar *str2;
@ -1298,21 +1321,24 @@ view_set_hint (GimpGradientEditor *editor,
gimp_gradient_get_color_at (GIMP_GRADIENT (data_editor->data),
data_editor->context, NULL,
xpos, FALSE, FALSE, &rgb);
xpos, FALSE, FALSE, &color);
gegl_color_set_pixel (color, babl_format ("R'G'B'A double"), &rgb);
gimp_color_area_set_color (GIMP_COLOR_AREA (editor->current_color), color);
gimp_rgb_to_hsv (&rgb, &hsv);
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), rgb);
gegl_color_get_pixel (color, babl_format ("HSV double"), hsv);
str1 = g_strdup_printf (_("Position: %0.4f"), xpos);
str2 = g_strdup_printf (_("RGB (%0.3f, %0.3f, %0.3f)"),
rgb.r, rgb.g, rgb.b);
/* TODO: Current hints are displaying sRGB values. Ideally we'd want to update
* the RGB space depending on the active image.
*/
str2 = g_strdup_printf (_("sRGB (%0.3f, %0.3f, %0.3f)"),
rgb[0], rgb[1], rgb[2]);
str3 = g_strdup_printf (_("HSV (%0.1f, %0.1f, %0.1f)"),
hsv.h * 360.0, hsv.s * 100.0, hsv.v * 100.0);
hsv[0] * 360.0, hsv[1] * 100.0, hsv[2] * 100.0);
str4 = g_strdup_printf (_("Luminance: %0.1f Opacity: %0.1f"),
GIMP_RGB_LUMINANCE (rgb.r, rgb.g, rgb.b) * 100.0,
rgb.a * 100.0);
GIMP_RGB_LUMINANCE (rgb[0], rgb[1], rgb[2]) * 100.0,
rgb[3] * 100.0);
gradient_editor_set_hint (editor, str1, str2, str3, str4);
@ -1330,8 +1356,8 @@ view_pick_color (GimpGradientEditor *editor,
gint x)
{
GimpDataEditor *data_editor = GIMP_DATA_EDITOR (editor);
GeglColor *color = gegl_color_new ("black");
GimpRGB rgb;
GeglColor *color = NULL;
gdouble rgb[3];
gdouble xpos;
gchar *str2;
gchar *str3;
@ -1340,17 +1366,17 @@ view_pick_color (GimpGradientEditor *editor,
gimp_gradient_get_color_at (GIMP_GRADIENT (data_editor->data),
data_editor->context, NULL,
xpos, FALSE, FALSE, &rgb);
xpos, FALSE, FALSE, &color);
gegl_color_set_pixel (color, babl_format ("R'G'B'A double"), &rgb);
gimp_color_area_set_color (GIMP_COLOR_AREA (editor->current_color), color);
str2 = g_strdup_printf (_("RGB (%d, %d, %d)"),
(gint) (rgb.r * 255.0),
(gint) (rgb.g * 255.0),
(gint) (rgb.b * 255.0));
gegl_color_get_pixel (color, babl_format ("R'G'B' double"), rgb);
str2 = g_strdup_printf (_("sRGB (%d, %d, %d)"),
(gint) (rgb[0] * 255.0),
(gint) (rgb[1] * 255.0),
(gint) (rgb[2] * 255.0));
str3 = g_strdup_printf ("(%0.3f, %0.3f, %0.3f)", rgb.r, rgb.g, rgb.b);
str3 = g_strdup_printf ("(%0.3f, %0.3f, %0.3f)", rgb[0], rgb[1], rgb[2]);
if (pick_target == GIMP_COLOR_PICK_TARGET_FOREGROUND)
{

View File

@ -83,7 +83,7 @@ struct _GimpGradientEditor
GimpGradientBlendColorSpace blend_color_space;
/* Saved colors */
GimpRGB saved_colors[GRAD_NUM_COLORS];
GeglColor *saved_colors[GRAD_NUM_COLORS];
/* Color dialog */
GtkWidget *color_dialog;

View File

@ -145,7 +145,6 @@ gimp_gradient_select_run_callback (GimpPdbDialog *dialog,
GimpGradientSegment *seg = NULL;
gdouble *values, *pv;
gdouble pos, delta;
GimpRGB color;
gint i;
GimpArray *array;
GimpValueArray *return_vals;
@ -159,17 +158,19 @@ gimp_gradient_select_run_callback (GimpPdbDialog *dialog,
while (i--)
{
GeglColor *color = NULL;
seg = gimp_gradient_get_color_at (gradient, dialog->caller_context,
seg, pos, FALSE,
GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
&color);
*pv++ = color.r;
*pv++ = color.g;
*pv++ = color.b;
*pv++ = color.a;
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), pv);
pv += 4;
pos += delta;
g_object_unref (color);
}
array = gimp_array_new ((guint8 *) values,

View File

@ -550,6 +550,14 @@ gimp_view_renderer_set_color_config (GimpViewRenderer *renderer,
}
}
GimpColorConfig *
gimp_view_renderer_get_color_config (GimpViewRenderer *renderer)
{
g_return_val_if_fail (GIMP_IS_VIEW_RENDERER (renderer), NULL);
return renderer->priv->color_config;
}
void
gimp_view_renderer_invalidate (GimpViewRenderer *renderer)
{

View File

@ -125,6 +125,8 @@ void gimp_view_renderer_set_background (GimpViewRenderer *renderer,
const gchar *icon_name);
void gimp_view_renderer_set_color_config (GimpViewRenderer *renderer,
GimpColorConfig *color_config);
GimpColorConfig *
gimp_view_renderer_get_color_config (GimpViewRenderer *renderer);
void gimp_view_renderer_invalidate (GimpViewRenderer *renderer);
void gimp_view_renderer_update (GimpViewRenderer *renderer);

View File

@ -158,22 +158,27 @@ gimp_view_renderer_gradient_render (GimpViewRenderer *renderer,
GimpViewRendererGradient *rendergrad = GIMP_VIEW_RENDERER_GRADIENT (renderer);
GimpGradient *gradient = GIMP_GRADIENT (renderer->viewable);
GimpGradientSegment *seg = NULL;
GimpColorTransform *transform;
GimpColorConfig *color_config;
const Babl *dest_space;
guchar *buf;
guchar *dest;
gint dest_stride;
gint x;
gint y;
gdouble dx, cur_x;
GimpRGB color;
buf = g_alloca (4 * renderer->width);
dx = (rendergrad->right - rendergrad->left) / (renderer->width - 1);
cur_x = rendergrad->left;
color_config = gimp_view_renderer_get_color_config (renderer);
g_return_if_fail (color_config != NULL);
dest_space = gimp_widget_get_render_space (widget, color_config);
for (x = 0, dest = buf; x < renderer->width; x++, dest += 4)
{
guchar r, g, b, a;
GeglColor *color = NULL;
seg = gimp_gradient_get_color_at (gradient, renderer->context, seg,
cur_x,
@ -182,9 +187,14 @@ gimp_view_renderer_gradient_render (GimpViewRenderer *renderer,
&color);
cur_x += dx;
gimp_rgba_get_uchar (&color, &r, &g, &b, &a);
/* This is only for rendering the gradient on thumbnails or small
* previews, so cairo-ARGB32 is probably enough.
*/
gegl_color_get_pixel (color,
babl_format_with_space ("cairo-ARGB32", dest_space),
dest);
GIMP_CAIRO_ARGB32_SET_PIXEL (dest, r, g, b, a);
g_object_unref (color);
}
if (! renderer->surface)
@ -197,20 +207,8 @@ gimp_view_renderer_gradient_render (GimpViewRenderer *renderer,
dest = cairo_image_surface_get_data (renderer->surface);
dest_stride = cairo_image_surface_get_stride (renderer->surface);
transform = gimp_view_renderer_get_color_transform (renderer, widget,
babl_format ("cairo-ARGB32"),
babl_format ("cairo-ARGB32"));
if (transform)
gimp_color_transform_process_pixels (transform,
babl_format ("cairo-ARGB32"), buf,
babl_format ("cairo-ARGB32"), buf,
renderer->width);
for (y = 0; y < renderer->height; y++, dest += dest_stride)
{
memcpy (dest, buf, renderer->width * 4);
}
memcpy (dest, buf, renderer->width * 4);
cairo_surface_mark_dirty (renderer->surface);
}

View File

@ -268,27 +268,23 @@ gimp_gradient_get_custom_samples (GimpGradient *gradient,
* gimp_gradient_segment_get_left_color:
* @gradient: The gradient.
* @segment: The index of a segment within the gradient.
* @color: (out caller-allocates): The return color.
* @opacity: (out): The opacity of the endpoint.
*
* Gets the left endpoint color of the segment
*
* Gets the left endpoint color of the indexed segment of the gradient.
* Returns an error when the segment index is out of range.
*
* Returns: TRUE on success.
* Returns: (transfer full): The return color.
*
* Since: 2.2
**/
gboolean
GeglColor *
gimp_gradient_segment_get_left_color (GimpGradient *gradient,
gint segment,
GimpRGB *color,
gdouble *opacity)
gint segment)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gboolean success = TRUE;
GeglColor *color = NULL;
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_GRADIENT, gradient,
@ -300,19 +296,12 @@ gimp_gradient_segment_get_left_color (GimpGradient *gradient,
args);
gimp_value_array_unref (args);
*opacity = 0.0;
success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS;
if (success)
{
GIMP_VALUES_GET_RGB (return_vals, 1, &*color);
*opacity = GIMP_VALUES_GET_DOUBLE (return_vals, 2);
}
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;
}
/**
@ -320,12 +309,12 @@ gimp_gradient_segment_get_left_color (GimpGradient *gradient,
* @gradient: The gradient.
* @segment: The index of a segment within the gradient.
* @color: The color to set.
* @opacity: The opacity to set for the endpoint.
*
* Sets the left endpoint color of a segment
*
* Sets the color of the left endpoint the indexed segment of the
* gradient.
* gradient. The alpha channel of the [class@Gegl.Color] is taken into
* account.
* Returns an error when gradient is not editable or index is out of
* range.
*
@ -334,10 +323,9 @@ gimp_gradient_segment_get_left_color (GimpGradient *gradient,
* Since: 2.2
**/
gboolean
gimp_gradient_segment_set_left_color (GimpGradient *gradient,
gint segment,
const GimpRGB *color,
gdouble opacity)
gimp_gradient_segment_set_left_color (GimpGradient *gradient,
gint segment,
GeglColor *color)
{
GimpValueArray *args;
GimpValueArray *return_vals;
@ -346,8 +334,7 @@ gimp_gradient_segment_set_left_color (GimpGradient *gradient,
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_GRADIENT, gradient,
G_TYPE_INT, segment,
GIMP_TYPE_RGB, color,
G_TYPE_DOUBLE, opacity,
GEGL_TYPE_COLOR, color,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
@ -366,8 +353,6 @@ gimp_gradient_segment_set_left_color (GimpGradient *gradient,
* gimp_gradient_segment_get_right_color:
* @gradient: The gradient.
* @segment: The index of a segment within the gradient.
* @color: (out caller-allocates): The return color.
* @opacity: (out): The opacity of the endpoint.
*
* Gets the right endpoint color of the segment
*
@ -375,19 +360,17 @@ gimp_gradient_segment_set_left_color (GimpGradient *gradient,
* gradient.
* Returns an error when the segment index is out of range.
*
* Returns: TRUE on success.
* Returns: (transfer full): The return color.
*
* Since: 2.2
**/
gboolean
GeglColor *
gimp_gradient_segment_get_right_color (GimpGradient *gradient,
gint segment,
GimpRGB *color,
gdouble *opacity)
gint segment)
{
GimpValueArray *args;
GimpValueArray *return_vals;
gboolean success = TRUE;
GeglColor *color = NULL;
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_GRADIENT, gradient,
@ -399,19 +382,12 @@ gimp_gradient_segment_get_right_color (GimpGradient *gradient,
args);
gimp_value_array_unref (args);
*opacity = 0.0;
success = GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS;
if (success)
{
GIMP_VALUES_GET_RGB (return_vals, 1, &*color);
*opacity = GIMP_VALUES_GET_DOUBLE (return_vals, 2);
}
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;
}
/**
@ -419,11 +395,11 @@ gimp_gradient_segment_get_right_color (GimpGradient *gradient,
* @gradient: The gradient.
* @segment: The index of a segment within the gradient.
* @color: The color to set.
* @opacity: The opacity to set for the endpoint.
*
* Sets the right endpoint color of the segment
*
* Sets the right endpoint color of the segment of the gradient.
* Sets the right endpoint color of the segment of the gradient. The
* alpha channel of the [class@Gegl.Color] is taken into account.
* Returns an error when gradient is not editable or segment index is
* out of range.
*
@ -432,10 +408,9 @@ gimp_gradient_segment_get_right_color (GimpGradient *gradient,
* Since: 2.2
**/
gboolean
gimp_gradient_segment_set_right_color (GimpGradient *gradient,
gint segment,
const GimpRGB *color,
gdouble opacity)
gimp_gradient_segment_set_right_color (GimpGradient *gradient,
gint segment,
GeglColor *color)
{
GimpValueArray *args;
GimpValueArray *return_vals;
@ -444,8 +419,7 @@ gimp_gradient_segment_set_right_color (GimpGradient *gradient,
args = gimp_value_array_new_from_types (NULL,
GIMP_TYPE_GRADIENT, gradient,
G_TYPE_INT, segment,
GIMP_TYPE_RGB, color,
G_TYPE_DOUBLE, opacity,
GEGL_TYPE_COLOR, color,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),

View File

@ -46,22 +46,16 @@ gboolean gimp_gradient_get_custom_samples (GimpGradient
gboolean reverse,
gint *num_color_samples,
gdouble **color_samples);
gboolean gimp_gradient_segment_get_left_color (GimpGradient *gradient,
gint segment,
GimpRGB *color,
gdouble *opacity);
GeglColor* gimp_gradient_segment_get_left_color (GimpGradient *gradient,
gint segment);
gboolean gimp_gradient_segment_set_left_color (GimpGradient *gradient,
gint segment,
const GimpRGB *color,
gdouble opacity);
gboolean gimp_gradient_segment_get_right_color (GimpGradient *gradient,
gint segment,
GimpRGB *color,
gdouble *opacity);
GeglColor *color);
GeglColor* gimp_gradient_segment_get_right_color (GimpGradient *gradient,
gint segment);
gboolean gimp_gradient_segment_set_right_color (GimpGradient *gradient,
gint segment,
const GimpRGB *color,
gdouble opacity);
GeglColor *color);
gboolean gimp_gradient_segment_get_left_pos (GimpGradient *gradient,
gint segment,
gdouble *pos);

View File

@ -0,0 +1,481 @@
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
*
* gimpcolor-parse.c
* Copyright (C) 2023 Jehan
*
* Some of the code in here was inspired and partly copied from pango
* and librsvg.
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <babl/babl.h>
#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gegl.h>
#include "gimpcolor.h"
static GeglColor * gimp_color_parse_name_internal (const gchar *name);
static GeglColor * gimp_color_parse_hex_internal (const gchar *hex);
static GeglColor * gimp_color_parse_css_numeric (const gchar *css);
static GeglColor * gimp_color_parse_css_internal (const gchar *css);
static gchar * gimp_color_parse_strip (const gchar *str,
gint len);
static gint gimp_color_entry_compare (gconstpointer a,
gconstpointer b);
static gboolean gimp_color_parse_hex_component (const gchar *hex,
gint len,
gdouble *value);
typedef struct
{
const gchar *name;
const guchar red;
const guchar green;
const guchar blue;
} ColorEntry;
static const ColorEntry named_colors[] =
{
{ "aliceblue", 240, 248, 255 },
{ "antiquewhite", 250, 235, 215 },
{ "aqua", 0, 255, 255 },
{ "aquamarine", 127, 255, 212 },
{ "azure", 240, 255, 255 },
{ "beige", 245, 245, 220 },
{ "bisque", 255, 228, 196 },
{ "black", 0, 0, 0 },
{ "blanchedalmond", 255, 235, 205 },
{ "blue", 0, 0, 255 },
{ "blueviolet", 138, 43, 226 },
{ "brown", 165, 42, 42 },
{ "burlywood", 222, 184, 135 },
{ "cadetblue", 95, 158, 160 },
{ "chartreuse", 127, 255, 0 },
{ "chocolate", 210, 105, 30 },
{ "coral", 255, 127, 80 },
{ "cornflowerblue", 100, 149, 237 },
{ "cornsilk", 255, 248, 220 },
{ "crimson", 220, 20, 60 },
{ "cyan", 0, 255, 255 },
{ "darkblue", 0, 0, 139 },
{ "darkcyan", 0, 139, 139 },
{ "darkgoldenrod", 184, 134, 11 },
{ "darkgray", 169, 169, 169 },
{ "darkgreen", 0, 100, 0 },
{ "darkgrey", 169, 169, 169 },
{ "darkkhaki", 189, 183, 107 },
{ "darkmagenta", 139, 0, 139 },
{ "darkolivegreen", 85, 107, 47 },
{ "darkorange", 255, 140, 0 },
{ "darkorchid", 153, 50, 204 },
{ "darkred", 139, 0, 0 },
{ "darksalmon", 233, 150, 122 },
{ "darkseagreen", 143, 188, 143 },
{ "darkslateblue", 72, 61, 139 },
{ "darkslategray", 47, 79, 79 },
{ "darkslategrey", 47, 79, 79 },
{ "darkturquoise", 0, 206, 209 },
{ "darkviolet", 148, 0, 211 },
{ "deeppink", 255, 20, 147 },
{ "deepskyblue", 0, 191, 255 },
{ "dimgray", 105, 105, 105 },
{ "dimgrey", 105, 105, 105 },
{ "dodgerblue", 30, 144, 255 },
{ "firebrick", 178, 34, 34 },
{ "floralwhite" , 255, 250, 240 },
{ "forestgreen", 34, 139, 34 },
{ "fuchsia", 255, 0, 255 },
{ "gainsboro", 220, 220, 220 },
{ "ghostwhite", 248, 248, 255 },
{ "gold", 255, 215, 0 },
{ "goldenrod", 218, 165, 32 },
{ "gray", 128, 128, 128 },
{ "green", 0, 128, 0 },
{ "greenyellow", 173, 255, 47 },
{ "grey", 128, 128, 128 },
{ "honeydew", 240, 255, 240 },
{ "hotpink", 255, 105, 180 },
{ "indianred", 205, 92, 92 },
{ "indigo", 75, 0, 130 },
{ "ivory", 255, 255, 240 },
{ "khaki", 240, 230, 140 },
{ "lavender", 230, 230, 250 },
{ "lavenderblush", 255, 240, 245 },
{ "lawngreen", 124, 252, 0 },
{ "lemonchiffon", 255, 250, 205 },
{ "lightblue", 173, 216, 230 },
{ "lightcoral", 240, 128, 128 },
{ "lightcyan", 224, 255, 255 },
{ "lightgoldenrodyellow", 250, 250, 210 },
{ "lightgray", 211, 211, 211 },
{ "lightgreen", 144, 238, 144 },
{ "lightgrey", 211, 211, 211 },
{ "lightpink", 255, 182, 193 },
{ "lightsalmon", 255, 160, 122 },
{ "lightseagreen", 32, 178, 170 },
{ "lightskyblue", 135, 206, 250 },
{ "lightslategray", 119, 136, 153 },
{ "lightslategrey", 119, 136, 153 },
{ "lightsteelblue", 176, 196, 222 },
{ "lightyellow", 255, 255, 224 },
{ "lime", 0, 255, 0 },
{ "limegreen", 50, 205, 50 },
{ "linen", 250, 240, 230 },
{ "magenta", 255, 0, 255 },
{ "maroon", 128, 0, 0 },
{ "mediumaquamarine", 102, 205, 170 },
{ "mediumblue", 0, 0, 205 },
{ "mediumorchid", 186, 85, 211 },
{ "mediumpurple", 147, 112, 219 },
{ "mediumseagreen", 60, 179, 113 },
{ "mediumslateblue", 123, 104, 238 },
{ "mediumspringgreen", 0, 250, 154 },
{ "mediumturquoise", 72, 209, 204 },
{ "mediumvioletred", 199, 21, 133 },
{ "midnightblue", 25, 25, 112 },
{ "mintcream", 245, 255, 250 },
{ "mistyrose", 255, 228, 225 },
{ "moccasin", 255, 228, 181 },
{ "navajowhite", 255, 222, 173 },
{ "navy", 0, 0, 128 },
{ "oldlace", 253, 245, 230 },
{ "olive", 128, 128, 0 },
{ "olivedrab", 107, 142, 35 },
{ "orange", 255, 165, 0 },
{ "orangered", 255, 69, 0 },
{ "orchid", 218, 112, 214 },
{ "palegoldenrod", 238, 232, 170 },
{ "palegreen", 152, 251, 152 },
{ "paleturquoise", 175, 238, 238 },
{ "palevioletred", 219, 112, 147 },
{ "papayawhip", 255, 239, 213 },
{ "peachpuff", 255, 218, 185 },
{ "peru", 205, 133, 63 },
{ "pink", 255, 192, 203 },
{ "plum", 221, 160, 221 },
{ "powderblue", 176, 224, 230 },
{ "purple", 128, 0, 128 },
{ "red", 255, 0, 0 },
{ "rosybrown", 188, 143, 143 },
{ "royalblue", 65, 105, 225 },
{ "saddlebrown", 139, 69, 19 },
{ "salmon", 250, 128, 114 },
{ "sandybrown", 244, 164, 96 },
{ "seagreen", 46, 139, 87 },
{ "seashell", 255, 245, 238 },
{ "sienna", 160, 82, 45 },
{ "silver", 192, 192, 192 },
{ "skyblue", 135, 206, 235 },
{ "slateblue", 106, 90, 205 },
{ "slategray", 112, 128, 144 },
{ "slategrey", 112, 128, 144 },
{ "snow", 255, 250, 250 },
{ "springgreen", 0, 255, 127 },
{ "steelblue", 70, 130, 180 },
{ "tan", 210, 180, 140 },
{ "teal", 0, 128, 128 },
{ "thistle", 216, 191, 216 },
{ "tomato", 255, 99, 71 },
{ "turquoise", 64, 224, 208 },
{ "violet", 238, 130, 238 },
{ "wheat", 245, 222, 179 },
{ "white", 255, 255, 255 },
{ "whitesmoke", 245, 245, 245 },
{ "yellow", 255, 255, 0 },
{ "yellowgreen", 154, 205, 50 }
};
/**
* gimp_color_parse_css:
* @css: (array length=len): a string describing a color in CSS notation
* @len: the length of @css, in bytes. or -1 if @css is nul-terminated
*
* Attempts to parse a string describing an sRGB color in CSS notation. This can
* be either a numerical representation (`rgb(255,0,0)` or `rgb(100%,0%,0%)`)
* or a hexadecimal notation as parsed by gimp_color_parse_hex()
* (`##ff0000`) or a color name as parsed by gimp_color_parse_name() (`red`).
*
* Additionally the `rgba()`, `hsl()` and `hsla()` functions are supported too.
*
* Returns: a newly allocated [class@Gegl.Color] if @css was parsed successfully
* %NULL otherwise
*
* Since: 2.2
**/
GeglColor *
gimp_color_parse_css (const gchar *css,
gint len)
{
gchar *tmp;
GeglColor *color;
g_return_val_if_fail (css != NULL, FALSE);
tmp = gimp_color_parse_strip (css, len);
color = gimp_color_parse_css_internal (tmp);
g_free (tmp);
return color;
}
/* Private functions. */
static GeglColor *
gimp_color_parse_name_internal (const gchar *name)
{
/* GeglColor also has name reading support. It supports HTML 4.01 standard
* whereas here we have SVG 1.0 name support. Moreover we support a lot more
* colors.
*/
ColorEntry *entry = bsearch (name, named_colors,
G_N_ELEMENTS (named_colors), sizeof (ColorEntry),
gimp_color_entry_compare);
if (entry)
{
GeglColor *color = gegl_color_new (NULL);
gegl_color_set_rgba_with_space (color, (gdouble) entry->red / 255.0,
(gdouble) entry->green / 255.0, (gdouble) entry->blue / 255.0,
1.0, NULL);
return color;
}
return NULL;
}
static GeglColor *
gimp_color_parse_hex_internal (const gchar *hex)
{
GeglColor *color;
gint i;
gsize len;
gdouble val[3];
if (hex[0] == '#')
hex++;
len = strlen (hex);
if (len % 3 || len < 3 || len > 12)
return NULL;
len /= 3;
for (i = 0; i < 3; i++, hex += len)
{
if (! gimp_color_parse_hex_component (hex, len, val + i))
return NULL;
}
color = gegl_color_new (NULL);
gegl_color_set_pixel (color, babl_format ("R'G'B' double"), val);
return color;
}
static GeglColor *
gimp_color_parse_css_numeric (const gchar *css)
{
GeglColor *color;
gdouble values[4];
gboolean alpha;
gboolean hsl;
gint i;
if (css[0] == 'r' && css[1] == 'g' && css[2] == 'b')
hsl = FALSE;
else if (css[0] == 'h' && css[1] == 's' && css[2] == 'l')
hsl = TRUE;
else
g_return_val_if_reached (NULL);
if (css[3] == 'a' && css[4] == '(')
alpha = TRUE;
else if (css[3] == '(')
alpha = FALSE;
else
g_return_val_if_reached (NULL);
css += (alpha ? 5 : 4);
for (i = 0; i < (alpha ? 4 : 3); i++)
{
const gchar *end = css;
while (*end && *end != ',' && *end != '%' && *end != ')')
end++;
if (i == 3 || *end == '%')
{
values[i] = g_ascii_strtod (css, (gchar **) &end);
if (errno == ERANGE)
return FALSE;
if (*end == '%')
{
end++;
values[i] /= 100.0;
}
}
else
{
glong value = strtol (css, (gchar **) &end, 10);
if (errno == ERANGE)
return FALSE;
if (hsl)
values[i] = value / (i == 0 ? 360.0 : 100.0);
else
values[i] = value / 255.0;
}
/* CSS Color specs indicates:
* > Values outside these ranges are not invalid, but are clamped to the
* > ranges defined here at parsed-value time.
* See: https://drafts.csswg.org/css-color/#rgb-functions
* So even though we might hope being able to reach non-sRGB colors when
* using the percentage syntax, the spec explicitly forbids it.
*/
values[i] = CLAMP (values[i], 0.0, 1.0);
while (*end == ',' || g_ascii_isspace (*end))
end++;
css = end;
}
if (*css != ')')
return NULL;
color = gegl_color_new (NULL);
if (hsl)
{
if (alpha)
gegl_color_set_pixel (color, babl_format ("HSLA double"), values);
else
gegl_color_set_pixel (color, babl_format ("HSL double"), values);
}
else
{
if (alpha)
gegl_color_set_pixel (color, babl_format ("R'G'B'A double"), values);
else
gegl_color_set_pixel (color, babl_format ("R'G'B' double"), values);
}
return color;
}
static GeglColor *
gimp_color_parse_css_internal (const gchar *css)
{
if (css[0] == '#')
{
return gimp_color_parse_hex_internal (css);
}
else if (strncmp (css, "rgb(", 4) == 0 ||
strncmp (css, "hsl(", 4) == 0)
{
return gimp_color_parse_css_numeric (css);
}
else
{
return gimp_color_parse_name_internal (css);
}
}
static gchar *
gimp_color_parse_strip (const gchar *str,
gint len)
{
gchar *result;
while (len > 0 && g_ascii_isspace (*str))
{
str++;
len--;
}
if (len < 0)
{
while (g_ascii_isspace (*str))
str++;
len = strlen (str);
}
while (len > 0 && g_ascii_isspace (str[len - 1]))
len--;
result = g_malloc (len + 1);
memcpy (result, str, len);
result[len] = '\0';
return result;
}
static gint
gimp_color_entry_compare (gconstpointer a,
gconstpointer b)
{
const gchar *name = a;
const ColorEntry *entry = b;
return g_ascii_strcasecmp (name, entry->name);
}
static gboolean
gimp_color_parse_hex_component (const gchar *hex,
gint len,
gdouble *value)
{
gint i;
guint c = 0;
for (i = 0; i < len; i++, hex++)
{
if (!*hex || !g_ascii_isxdigit (*hex))
return FALSE;
c = (c << 4) | g_ascii_xdigit_value (*hex);
}
switch (len)
{
case 1: *value = (gdouble) c / 15.0; break;
case 2: *value = (gdouble) c / 255.0; break;
case 3: *value = (gdouble) c / 4095.0; break;
case 4: *value = (gdouble) c / 65535.0; break;
default:
g_return_val_if_reached (FALSE);
}
return TRUE;
}

View File

@ -39,6 +39,10 @@
* objects more easily.
**/
static const Babl * gimp_babl_format_get_with_alpha (const Babl *format);
/**
* gimp_color_set_alpha:
* @color: a [class@Gegl.Color]
@ -79,6 +83,7 @@ gimp_color_set_alpha (GeglColor *color,
* Let's assume that since we use an unbounded 32-bit intermediate value
* (float), the loss would be acceptable.
*/
format = gimp_babl_format_get_with_alpha (format);
gegl_color_get_pixel (color, format, pixel);
gegl_color_set_pixel (color, format, pixel);
}
@ -138,3 +143,62 @@ gimp_color_is_perceptually_identical (GeglColor *color1,
SQR (pixel1[2] - pixel2[2]) <= 1e-4));
#undef SQR
}
/* Private functions. */
static const Babl *
gimp_babl_format_get_with_alpha (const Babl *format)
{
const Babl *new_format = NULL;
const gchar *new_model = NULL;
const gchar *model;
const gchar *type;
gchar *name;
if (babl_format_has_alpha (format))
return format;
model = babl_get_name (babl_format_get_model (format));
/* Assuming we use Babl formats with same type for all components. */
type = babl_get_name (babl_format_get_type (format, 0));
if (g_strcmp0 (model, "Y") == 0)
new_model = "YA";
else if (g_strcmp0 (model, "RGB") == 0)
new_model = "RGBA";
else if (g_strcmp0 (model, "Y'") == 0)
new_model = "Y'A";
else if (g_strcmp0 (model, "R'G'B'") == 0)
new_model = "R'G'B'A";
else if (g_strcmp0 (model, "Y~") == 0)
new_model = "Y~A";
else if (g_strcmp0 (model, "R~G~B~") == 0)
new_model = "R~G~B~A";
else if (g_strcmp0 (model, "CIE Lab") == 0)
new_model = "CIE Lab alpha";
else if (g_strcmp0 (model, "CIE xyY") == 0)
new_model = "CIE xyY alpha";
else if (g_strcmp0 (model, "CIE XYZ") == 0)
new_model = "CIE XYZ alpha";
else if (g_strcmp0 (model, "CIE Yuv") == 0)
new_model = "CIE Yuv alpha";
else if (g_strcmp0 (model, "CMYK") == 0)
new_model = "CMYKA";
else if (g_strcmp0 (model, "cmyk") == 0)
new_model = "cmykA";
else if (g_strcmp0 (model, "HSL") == 0)
new_model = "HSLA";
else if (g_strcmp0 (model, "HSV") == 0)
new_model = "HSVA";
else if (g_strcmp0 (model, "cairo-RGB24") == 0)
new_model = "cairo-ARGB32";
g_return_val_if_fail (new_model != NULL, format);
name = g_strdup_printf ("%s %s", new_model, type);
new_format = babl_format_with_space (name, format);
g_free (name);
return new_format;
}

View File

@ -30,6 +30,7 @@ EXPORTS
gimp_color_managed_simulation_bpc_changed
gimp_color_managed_simulation_intent_changed
gimp_color_managed_simulation_profile_changed
gimp_color_parse_css
gimp_color_profile_get_copyright
gimp_color_profile_get_description
gimp_color_profile_get_format

View File

@ -47,11 +47,14 @@ G_BEGIN_DECLS
#define GIMP_VALUE_HOLDS_COLOR(value) (G_TYPE_CHECK_VALUE_TYPE ((value), GEGL_TYPE_COLOR))
void gimp_color_set_alpha (GeglColor *color,
gdouble alpha);
void gimp_color_set_alpha (GeglColor *color,
gdouble alpha);
gboolean gimp_color_is_perceptually_identical (GeglColor *color1,
GeglColor *color2);
gboolean gimp_color_is_perceptually_identical (GeglColor *color1,
GeglColor *color2);
GeglColor * gimp_color_parse_css (const gchar *css,
gint len);
G_END_DECLS

View File

@ -5,6 +5,7 @@ libgimpcolor_sources = files(
'gimpcairo.c',
'gimpcmyk.c',
'gimpcolor.c',
'gimpcolor-parse.c',
'gimpcolormanaged.c',
'gimpcolorprofile.c',
'gimpcolorspace.c',

View File

@ -168,23 +168,27 @@ HELP
num_color_samples = num_samples * 4;
sample = color_samples = g_new (gdouble, num_color_samples);
sample = color_samples = g_new0 (gdouble, num_color_samples);
while (num_samples--)
{
GimpRGB color;
GeglColor *color = NULL;
seg = gimp_gradient_get_color_at (gradient, context, seg,
pos, reverse,
GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
&color);
/* XXX "float" in PDB are in fact double. */
if (color)
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), sample);
/* TODO: should we really return a list of floats? What about a list
* of GeglColor?
*/
*sample++ = color.r;
*sample++ = color.g;
*sample++ = color.b;
*sample++ = color.a;
sample += 4;
pos += delta;
pos += delta;
g_clear_object (&color);
}
}
else
@ -233,11 +237,11 @@ HELP
num_color_samples = num_samples * 4;
sample = color_samples = g_new (gdouble, num_color_samples);
sample = color_samples = g_new0 (gdouble, num_color_samples);
while (num_samples--)
{
GimpRGB color;
GeglColor *color = NULL;
seg = gimp_gradient_get_color_at (gradient, context,
seg, *positions,
@ -245,12 +249,13 @@ HELP
GIMP_GRADIENT_BLEND_RGB_PERCEPTUAL,
&color);
*sample++ = color.r;
*sample++ = color.g;
*sample++ = color.b;
*sample++ = color.a;
if (color)
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), sample);
sample += 4;
positions++;
g_clear_object (&color);
}
}
else
@ -277,10 +282,8 @@ HELP
);
@outargs = (
{ name => 'color', type => 'color', void_ret => 1,
{ name => 'color', type => 'geglcolor',
desc => 'The return color' },
{ name => 'opacity', type => 'float',
desc => 'The opacity of the endpoint' }
);
%invoke = (
@ -291,10 +294,7 @@ HELP
seg = gimp_gradient_segment_get_nth (gradient->segments, segment);
if (seg)
{
gimp_gradient_segment_get_left_color (gradient, seg, &color);
opacity = color.a * 100.0;
}
color = g_object_ref (gimp_gradient_segment_get_left_color (gradient, seg));
else
success = FALSE;
}
@ -318,10 +318,8 @@ HELP
);
@outargs = (
{ name => 'color', type => 'color', void_ret => 1,
desc => 'The return color' },
{ name => 'opacity', type => 'float',
desc => 'The opacity of the endpoint' }
{ name => 'color', type => 'geglcolor',
desc => 'The return color' }
);
%invoke = (
@ -332,10 +330,7 @@ HELP
seg = gimp_gradient_segment_get_nth (gradient->segments, segment);
if (seg)
{
gimp_gradient_segment_get_right_color (gradient, seg, &color);
opacity = color.a * 100.0;
}
color = g_object_ref (gimp_gradient_segment_get_right_color (gradient, seg));
else
success = FALSE;
}
@ -346,7 +341,8 @@ CODE
sub gradient_segment_set_left_color {
$blurb = 'Sets the left endpoint color of a segment';
$help = <<'HELP';
Sets the color of the left endpoint the indexed segment of the gradient.
Sets the color of the left endpoint the indexed segment of the gradient. The
alpha channel of the [class@Gegl.Color] is taken into account.
Returns an error when gradient is not editable or index is out of range.
HELP
@ -356,10 +352,7 @@ HELP
@inargs = (
${gradient_arg_spec},
${gradient_seg_arg_spec},
{ name => 'color', type => 'color',
desc => 'The color to set' },
{ name => 'opacity', type => '0 <= float <= 100.0',
desc => 'The opacity to set for the endpoint' }
{ name => 'color', type => 'geglcolor', desc => 'The color to set' }
);
%invoke = (
@ -367,18 +360,13 @@ HELP
{
if (gimp_data_is_writable (GIMP_DATA (gradient)))
{
GimpGradientSegment *seg = gimp_gradient_segment_get_nth (gradient->segments, segment);
GimpGradientSegment *seg = gimp_gradient_segment_get_nth (gradient->segments, segment);
if (seg)
{
color.a = opacity / 100.0;
gimp_gradient_segment_set_left_color (gradient, seg, &color);
}
else
{
if (seg)
gimp_gradient_segment_set_left_color (gradient, seg, color);
else
success = FALSE;
}
}
else
{
success = FALSE;
@ -392,7 +380,8 @@ sub gradient_segment_set_right_color {
$blurb = 'Sets the right endpoint color of the segment';
$help = <<'HELP';
Sets the right endpoint color of the segment of the gradient.
Sets the right endpoint color of the segment of the gradient. The alpha channel
of the [class@Gegl.Color] is taken into account.
Returns an error when gradient is not editable or segment index is out of range.
HELP
@ -402,10 +391,7 @@ HELP
@inargs = (
${gradient_arg_spec},
${gradient_seg_arg_spec},
{ name => 'color', type => 'color',
desc => 'The color to set' },
{ name => 'opacity', type => '0 <= float <= 100.0',
desc => 'The opacity to set for the endpoint' }
{ name => 'color', type => 'geglcolor', desc => 'The color to set' }
);
%invoke = (
@ -416,10 +402,7 @@ HELP
GimpGradientSegment *seg = gimp_gradient_segment_get_nth (gradient->segments, segment);
if (seg)
{
color.a = opacity / 100.0;
gimp_gradient_segment_set_right_color (gradient, seg, &color);
}
gimp_gradient_segment_set_right_color (gradient, seg, color);
else
success = FALSE;
}
@ -1129,8 +1112,8 @@ HELP
if (start_seg && end_seg)
gimp_gradient_segment_range_blend (gradient,
start_seg, end_seg,
&start_seg->left_color,
&end_seg->right_color,
start_seg->left_color,
end_seg->right_color,
TRUE, FALSE);
else
success = FALSE;
@ -1176,8 +1159,8 @@ HELP
if (start_seg && end_seg)
gimp_gradient_segment_range_blend (gradient,
start_seg, end_seg,
&start_seg->left_color,
&end_seg->right_color,
start_seg->left_color,
end_seg->right_color,
FALSE, TRUE);
else
success = FALSE;