From 2770cce833415cfdf97f6418cc417ea2c92bed0a Mon Sep 17 00:00:00 2001 From: Alx Sa Date: Fri, 8 Nov 2024 05:37:19 +0000 Subject: [PATCH] pdb, operations, tool: Replace GimpContext with GeglColor... in gimp:offset filter. Since gimp:offset is now an NDE filter, always loading the background color from context causes the color to change each time the filter is redrawn. This is inconsistent behavior. This patch replaces the GimpContext parameter with GeglColor, and updates gimp_drawable_offset and related functions to set the color directly. The libgimp version loads the background color from context and passes it on since the API is now frozen. --- app/core/gimpdrawable-offset.c | 19 ++++- app/core/gimpdrawable-offset.h | 1 + app/operations/gimpoperationoffset.c | 47 ++++++----- app/operations/gimpoperationoffset.h | 2 +- app/pdb/drawable-cmds.c | 17 +++- app/tools/gimpoffsettool.c | 112 ++++++++++++++++++--------- app/tools/gimpoffsettool.h | 1 + libgimp/gimpdrawable_pdb.c | 3 + libgimp/gimpdrawable_pdb.h | 1 + libgimpbase/gimpbaseenums.c | 4 +- libgimpbase/gimpbaseenums.h | 4 +- pdb/enums.pl | 4 +- pdb/groups/drawable.pdb | 5 +- 13 files changed, 142 insertions(+), 78 deletions(-) diff --git a/app/core/gimpdrawable-offset.c b/app/core/gimpdrawable-offset.c index b7f5eb21fc..b0e1fc03fc 100644 --- a/app/core/gimpdrawable-offset.c +++ b/app/core/gimpdrawable-offset.c @@ -39,6 +39,7 @@ gimp_drawable_offset (GimpDrawable *drawable, GimpContext *context, gboolean wrap_around, GimpOffsetType fill_type, + GeglColor *color, gint offset_x, gint offset_y) { @@ -69,12 +70,22 @@ gimp_drawable_offset (GimpDrawable *drawable, node = gegl_node_new_child (NULL, "operation", "gimp:offset", - "context", context, - "type", fill_type, - "x", offset_x, - "y", offset_y, + "type", fill_type, + "x", offset_x, + "y", offset_y, NULL); + if (color == NULL) + { + color = gegl_color_duplicate (gimp_context_get_background (context)); + gegl_node_set (node, "color", color, NULL); + g_object_unref (color); + } + else + { + gegl_node_set (node, "color", color, NULL); + } + gimp_drawable_apply_operation (drawable, NULL, C_("undo-type", "Offset Drawable"), node); diff --git a/app/core/gimpdrawable-offset.h b/app/core/gimpdrawable-offset.h index 662915024f..f41a1b53ff 100644 --- a/app/core/gimpdrawable-offset.h +++ b/app/core/gimpdrawable-offset.h @@ -23,6 +23,7 @@ void gimp_drawable_offset (GimpDrawable *drawable, GimpContext *context, gboolean wrap_around, GimpOffsetType fill_type, + GeglColor *color, gint offset_x, gint offset_y); diff --git a/app/operations/gimpoperationoffset.c b/app/operations/gimpoperationoffset.c index 788fa268ad..2c06129a13 100644 --- a/app/operations/gimpoperationoffset.c +++ b/app/operations/gimpoperationoffset.c @@ -24,6 +24,8 @@ #include #include +#include "libgimpcolor/gimpcolor.h" + #include "operations-types.h" #include "gegl/gimp-gegl-loops.h" @@ -39,7 +41,7 @@ enum { PROP_0, - PROP_CONTEXT, + PROP_COLOR, PROP_TYPE, PROP_X, PROP_Y @@ -118,13 +120,13 @@ gimp_operation_offset_class_init (GimpOperationOffsetClass *klass) "description", _("Shift the pixels, optionally wrapping them at the borders"), NULL); - g_object_class_install_property (object_class, PROP_CONTEXT, - g_param_spec_object ("context", - "Context", - "A GimpContext", - GIMP_TYPE_CONTEXT, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_COLOR, + gimp_param_spec_color_from_string ("color", + _("Fill Color"), + _("Fill Color"), + FALSE, "white", + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, PROP_TYPE, g_param_spec_enum ("type", @@ -162,7 +164,7 @@ gimp_operation_offset_dispose (GObject *object) { GimpOperationOffset *offset = GIMP_OPERATION_OFFSET (object); - g_clear_object (&offset->context); + g_object_unref (offset->color); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -177,8 +179,8 @@ gimp_operation_offset_get_property (GObject *object, switch (property_id) { - case PROP_CONTEXT: - g_value_set_object (value, offset->context); + case PROP_COLOR: + g_value_set_object (value, offset->color); break; case PROP_TYPE: @@ -201,16 +203,17 @@ gimp_operation_offset_get_property (GObject *object, static void gimp_operation_offset_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) + guint property_id, + const GValue *value, + GParamSpec *pspec) { GimpOperationOffset *offset = GIMP_OPERATION_OFFSET (object); switch (property_id) { - case PROP_CONTEXT: - g_set_object (&offset->context, g_value_get_object (value)); + case PROP_COLOR: + g_clear_object (&offset->color); + offset->color = gegl_color_duplicate (g_value_get_object (value)); break; case PROP_TYPE: @@ -293,9 +296,7 @@ gimp_operation_offset_parent_process (GeglOperation *operation, return TRUE; } - else if (offset->type == GIMP_OFFSET_TRANSPARENT || - (offset->type == GIMP_OFFSET_BACKGROUND && - ! offset->context)) + else if (offset->type == GIMP_OFFSET_TRANSPARENT) { GObject *output = NULL; @@ -346,7 +347,6 @@ gimp_operation_offset_process (GeglOperation *operation, gint level) { GimpOperationOffset *offset = GIMP_OPERATION_OFFSET (operation); - GeglColor *color = NULL; GeglRectangle bounds; gint x; gint y; @@ -356,9 +356,6 @@ gimp_operation_offset_process (GeglOperation *operation, gimp_operation_offset_get_offset (offset, FALSE, &x, &y); - if (offset->type == GIMP_OFFSET_BACKGROUND && offset->context) - color = gimp_context_get_background (offset->context); - for (i = 0; i < 4; i++) { GeglRectangle offset_bounds = bounds; @@ -385,9 +382,9 @@ gimp_operation_offset_process (GeglOperation *operation, gimp_gegl_buffer_copy (input, &offset_roi, GEGL_ABYSS_NONE, output, &offset_bounds); } - else if (color) + else if (offset->color) { - gegl_buffer_set_color (output, &offset_bounds, color); + gegl_buffer_set_color (output, &offset_bounds, offset->color); } } } diff --git a/app/operations/gimpoperationoffset.h b/app/operations/gimpoperationoffset.h index dcd0e0b320..edc567029c 100644 --- a/app/operations/gimpoperationoffset.h +++ b/app/operations/gimpoperationoffset.h @@ -37,7 +37,7 @@ struct _GimpOperationOffset { GeglOperationFilter parent_instance; - GimpContext *context; + GeglColor *color; GimpOffsetType type; gint x; gint y; diff --git a/app/pdb/drawable-cmds.c b/app/pdb/drawable-cmds.c index 8755d8c31f..9d81a5dc80 100644 --- a/app/pdb/drawable-cmds.c +++ b/app/pdb/drawable-cmds.c @@ -758,14 +758,16 @@ drawable_offset_invoker (GimpProcedure *procedure, GimpDrawable *drawable; gboolean wrap_around; gint fill_type; + GeglColor *color; gint offset_x; gint offset_y; drawable = g_value_get_object (gimp_value_array_index (args, 0)); wrap_around = g_value_get_boolean (gimp_value_array_index (args, 1)); fill_type = g_value_get_enum (gimp_value_array_index (args, 2)); - offset_x = g_value_get_int (gimp_value_array_index (args, 3)); - offset_y = g_value_get_int (gimp_value_array_index (args, 4)); + color = g_value_get_object (gimp_value_array_index (args, 3)); + offset_x = g_value_get_int (gimp_value_array_index (args, 4)); + offset_y = g_value_get_int (gimp_value_array_index (args, 5)); if (success) { @@ -773,7 +775,7 @@ drawable_offset_invoker (GimpProcedure *procedure, GIMP_PDB_ITEM_CONTENT, error) && gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error)) gimp_drawable_offset (drawable, context, wrap_around, fill_type, - offset_x, offset_y); + color, offset_x, offset_y); else success = FALSE; } @@ -1737,8 +1739,15 @@ register_drawable_procs (GimpPDB *pdb) "fill type", "fill vacated regions of drawable with background or transparent", GIMP_TYPE_OFFSET_TYPE, - GIMP_OFFSET_BACKGROUND, + GIMP_OFFSET_COLOR, GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + gimp_param_spec_color ("color", + "color", + "fills in the background color when fill_type is set to OFFSET-COLOR", + FALSE, + NULL, + GIMP_PARAM_READWRITE)); gimp_procedure_add_argument (procedure, g_param_spec_int ("offset-x", "offset x", diff --git a/app/tools/gimpoffsettool.c b/app/tools/gimpoffsettool.c index 4042d98d3f..9596720637 100644 --- a/app/tools/gimpoffsettool.c +++ b/app/tools/gimpoffsettool.c @@ -36,6 +36,7 @@ #include "core/gimplayermask.h" #include "widgets/gimphelp-ids.h" +#include "widgets/gimppropwidgets.h" #include "display/gimpdisplay.h" #include "display/gimptoolgui.h" @@ -101,8 +102,7 @@ static void gimp_offset_tool_half_y_clicked (GtkButton static void gimp_offset_tool_edge_behavior_toggled (GtkToggleButton *toggle, GimpOffsetTool *offset_tool); -static void gimp_offset_tool_background_changed (GimpContext *context, - GeglColor *color, +static void gimp_offset_tool_color_changed (GimpColorButton *button, GimpOffsetTool *offset_tool); static gint gimp_offset_tool_get_width (GimpOffsetTool *offset_tool); @@ -175,6 +175,7 @@ gimp_offset_tool_initialize (GimpTool *tool, GimpContext *context = GIMP_CONTEXT (GIMP_TOOL_GET_OPTIONS (tool)); GimpImage *image; GimpDrawable *drawable; + GeglColor *color; gdouble xres; gdouble yres; @@ -225,14 +226,9 @@ gimp_offset_tool_initialize (GimpTool *tool, gimp_offset_tool_offset_changed, offset_tool); - gegl_node_set ( - filter_tool->operation, - "context", context, - NULL); - - g_signal_connect (context, "background-changed", - G_CALLBACK (gimp_offset_tool_background_changed), - offset_tool); + color = gegl_color_duplicate (gimp_context_get_background (context)); + gegl_node_set (filter_tool->operation, "color", color, NULL); + g_object_unref (color); gimp_offset_tool_update (offset_tool); @@ -467,6 +463,8 @@ gimp_offset_tool_dialog (GimpFilterTool *filter_tool) GtkWidget *spinbutton; GtkWidget *frame; GtkAdjustment *adjustment; + GeglColor *color = NULL; + gint type = 0; main_vbox = gimp_filter_tool_dialog_get_vbox (filter_tool); @@ -540,6 +538,11 @@ gimp_offset_tool_dialog (GimpFilterTool *filter_tool) G_CALLBACK (gimp_offset_tool_half_y_clicked), offset_tool); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); + gtk_widget_set_halign (hbox, GTK_ALIGN_START); + gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, FALSE, 0); + gtk_widget_set_visible (hbox, TRUE); + /* The edge behavior frame */ frame = gimp_int_radio_group_new (TRUE, _("Edge Behavior"), @@ -551,16 +554,40 @@ gimp_offset_tool_dialog (GimpFilterTool *filter_tool) _("W_rap around"), GIMP_OFFSET_WRAP_AROUND, NULL, - _("Fill with _background color"), - GIMP_OFFSET_BACKGROUND, NULL, + _("Fill with plain color"), + GIMP_OFFSET_COLOR, NULL, _("Make _transparent"), GIMP_OFFSET_TRANSPARENT, &offset_tool->transparent_radio, NULL); - gtk_box_pack_start (GTK_BOX (main_vbox), frame, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); + + /* Color area */ + gegl_node_get (filter_tool->operation, + "color", &color, + "type", &type, + NULL); + + vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + gtk_widget_set_valign (vbox, GTK_ALIGN_END); + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, FALSE, 0); + gtk_widget_set_visible (vbox, TRUE); + + offset_tool->color_button = gimp_color_button_new (_("Fill Color"), + 40, 24, color, + GIMP_COLOR_AREA_FLAT); + gtk_box_pack_start (GTK_BOX (vbox), offset_tool->color_button, TRUE, FALSE, 0); + if (type == GIMP_OFFSET_COLOR) + gtk_widget_set_visible (offset_tool->color_button, TRUE); + + g_signal_connect (GIMP_COLOR_BUTTON (offset_tool->color_button), + "color-changed", + G_CALLBACK (gimp_offset_tool_color_changed), + offset_tool); + g_object_unref (color); } static void @@ -632,29 +659,27 @@ gimp_offset_tool_edge_behavior_toggled (GtkToggleButton *toggle, g_object_set (GIMP_FILTER_TOOL (offset_tool)->config, "type", type, NULL); + + if (type == GIMP_OFFSET_COLOR) + gtk_widget_set_visible (offset_tool->color_button, TRUE); + else + gtk_widget_set_visible (offset_tool->color_button, FALSE); } } static void -gimp_offset_tool_background_changed (GimpContext *context, - GeglColor *color, - GimpOffsetTool *offset_tool) +gimp_offset_tool_color_changed (GimpColorButton *button, + GimpOffsetTool *offset_tool) { + GeglColor *color = gimp_color_button_get_color (button); GimpFilterTool *filter_tool = GIMP_FILTER_TOOL (offset_tool); - GimpOffsetType type; - g_object_get (filter_tool->config, - "type", &type, - NULL); + gegl_node_set (filter_tool->operation, + "color", color, + NULL); - if (type == GIMP_OFFSET_BACKGROUND) - { - gegl_node_set (filter_tool->operation, - "context", context, - NULL); - - gimp_drawable_filter_apply (filter_tool->filter, NULL); - } + gimp_drawable_filter_apply (filter_tool->filter, NULL); + g_object_unref (color); } static gint @@ -723,11 +748,11 @@ gimp_offset_tool_update (GimpOffsetTool *offset_tool) type = orig_type; - if (tool->drawables && + if (tool->drawables && ! gimp_drawable_has_alpha (tool->drawables->data) && type == GIMP_OFFSET_TRANSPARENT) { - type = GIMP_OFFSET_BACKGROUND; + type = GIMP_OFFSET_COLOR; } if (x != orig_x || @@ -780,18 +805,31 @@ gimp_offset_tool_update (GimpOffsetTool *offset_tool) GTK_RADIO_BUTTON (offset_tool->transparent_radio), type); } + + if (offset_tool->color_button) + { + GeglColor *color; + + gegl_node_get (filter_tool->operation, "color", &color, NULL); + + g_signal_handlers_block_by_func (offset_tool->color_button, + gimp_offset_tool_color_changed, + offset_tool); + gimp_color_button_set_color (GIMP_COLOR_BUTTON (offset_tool->color_button), + color); + g_signal_handlers_unblock_by_func (offset_tool->color_button, + gimp_offset_tool_color_changed, + offset_tool); + + g_object_unref (color); + } + } static void gimp_offset_tool_halt (GimpOffsetTool *offset_tool) { - GimpContext *context = GIMP_CONTEXT (GIMP_TOOL_GET_OPTIONS (offset_tool)); - offset_tool->offset_se = NULL; offset_tool->transparent_radio = NULL; - - g_signal_handlers_disconnect_by_func ( - context, - gimp_offset_tool_background_changed, - offset_tool); + offset_tool->color_button = NULL; } diff --git a/app/tools/gimpoffsettool.h b/app/tools/gimpoffsettool.h index ff651dede3..39b86ab242 100644 --- a/app/tools/gimpoffsettool.h +++ b/app/tools/gimpoffsettool.h @@ -46,6 +46,7 @@ struct _GimpOffsetTool /* dialog */ GtkWidget *offset_se; GtkWidget *transparent_radio; + GtkWidget *color_button; }; struct _GimpOffsetToolClass diff --git a/libgimp/gimpdrawable_pdb.c b/libgimp/gimpdrawable_pdb.c index 8610e972f4..8778fd9855 100644 --- a/libgimp/gimpdrawable_pdb.c +++ b/libgimp/gimpdrawable_pdb.c @@ -886,6 +886,7 @@ gimp_drawable_fill (GimpDrawable *drawable, * @drawable: The drawable to offset. * @wrap_around: wrap image around or fill vacated regions. * @fill_type: fill vacated regions of drawable with background or transparent. + * @color: fills in the background color when fill_type is set to OFFSET-COLOR. * @offset_x: offset by this amount in X direction. * @offset_y: offset by this amount in Y direction. * @@ -905,6 +906,7 @@ gboolean gimp_drawable_offset (GimpDrawable *drawable, gboolean wrap_around, GimpOffsetType fill_type, + GeglColor *color, gint offset_x, gint offset_y) { @@ -916,6 +918,7 @@ gimp_drawable_offset (GimpDrawable *drawable, GIMP_TYPE_DRAWABLE, drawable, G_TYPE_BOOLEAN, wrap_around, GIMP_TYPE_OFFSET_TYPE, fill_type, + GEGL_TYPE_COLOR, color, G_TYPE_INT, offset_x, G_TYPE_INT, offset_y, G_TYPE_NONE); diff --git a/libgimp/gimpdrawable_pdb.h b/libgimp/gimpdrawable_pdb.h index 180125d70c..c0e6723365 100644 --- a/libgimp/gimpdrawable_pdb.h +++ b/libgimp/gimpdrawable_pdb.h @@ -77,6 +77,7 @@ gboolean gimp_drawable_fill (GimpDrawable gboolean gimp_drawable_offset (GimpDrawable *drawable, gboolean wrap_around, GimpOffsetType fill_type, + GeglColor *color, gint offset_x, gint offset_y); G_GNUC_INTERNAL gboolean _gimp_drawable_thumbnail (GimpDrawable *drawable, diff --git a/libgimpbase/gimpbaseenums.c b/libgimpbase/gimpbaseenums.c index ff8e708ae5..490e08b1e5 100644 --- a/libgimpbase/gimpbaseenums.c +++ b/libgimpbase/gimpbaseenums.c @@ -1119,7 +1119,7 @@ gimp_offset_type_get_type (void) { static const GEnumValue values[] = { - { GIMP_OFFSET_BACKGROUND, "GIMP_OFFSET_BACKGROUND", "background" }, + { GIMP_OFFSET_COLOR, "GIMP_OFFSET_COLOR", "color" }, { GIMP_OFFSET_TRANSPARENT, "GIMP_OFFSET_TRANSPARENT", "transparent" }, { GIMP_OFFSET_WRAP_AROUND, "GIMP_OFFSET_WRAP_AROUND", "wrap-around" }, { 0, NULL, NULL } @@ -1127,7 +1127,7 @@ gimp_offset_type_get_type (void) static const GimpEnumDesc descs[] = { - { GIMP_OFFSET_BACKGROUND, "GIMP_OFFSET_BACKGROUND", NULL }, + { GIMP_OFFSET_COLOR, "GIMP_OFFSET_COLOR", NULL }, { GIMP_OFFSET_TRANSPARENT, "GIMP_OFFSET_TRANSPARENT", NULL }, { GIMP_OFFSET_WRAP_AROUND, "GIMP_OFFSET_WRAP_AROUND", NULL }, { 0, NULL, NULL } diff --git a/libgimpbase/gimpbaseenums.h b/libgimpbase/gimpbaseenums.h index 1ac739739c..33cbb6b192 100644 --- a/libgimpbase/gimpbaseenums.h +++ b/libgimpbase/gimpbaseenums.h @@ -750,7 +750,7 @@ typedef enum /** * GimpOffsetType: - * @GIMP_OFFSET_BACKGROUND: Background + * @GIMP_OFFSET_COLOR: Color * @GIMP_OFFSET_TRANSPARENT: Transparent * @GIMP_OFFSET_WRAP_AROUND: Wrap image around * @@ -762,7 +762,7 @@ GType gimp_offset_type_get_type (void) G_GNUC_CONST; typedef enum { - GIMP_OFFSET_BACKGROUND, + GIMP_OFFSET_COLOR, GIMP_OFFSET_TRANSPARENT, GIMP_OFFSET_WRAP_AROUND } GimpOffsetType; diff --git a/pdb/enums.pl b/pdb/enums.pl index 7884897929..623f059471 100644 --- a/pdb/enums.pl +++ b/pdb/enums.pl @@ -357,9 +357,9 @@ package Gimp::CodeGen::enums; GimpOffsetType => { contig => 1, header => 'libgimpbase/gimpbaseenums.h', - symbols => [ qw(GIMP_OFFSET_BACKGROUND GIMP_OFFSET_TRANSPARENT + symbols => [ qw(GIMP_OFFSET_COLOR GIMP_OFFSET_TRANSPARENT GIMP_OFFSET_WRAP_AROUND) ], - mapping => { GIMP_OFFSET_BACKGROUND => '0', + mapping => { GIMP_OFFSET_COLOR => '0', GIMP_OFFSET_TRANSPARENT => '1', GIMP_OFFSET_WRAP_AROUND => '2' } }, diff --git a/pdb/groups/drawable.pdb b/pdb/groups/drawable.pdb index 18ecb53fa2..71600fb34d 100644 --- a/pdb/groups/drawable.pdb +++ b/pdb/groups/drawable.pdb @@ -936,6 +936,9 @@ HELP { name => 'fill_type', type => 'enum GimpOffsetType', desc => 'fill vacated regions of drawable with background or transparent' }, + { name => 'color', type => 'geglcolor', + desc => 'fills in the background color when fill_type is + set to OFFSET-COLOR' }, { name => 'offset_x', type => 'int32', desc => 'offset by this amount in X direction' }, { name => 'offset_y', type => 'int32', @@ -949,7 +952,7 @@ HELP GIMP_PDB_ITEM_CONTENT, error) && gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error)) gimp_drawable_offset (drawable, context, wrap_around, fill_type, - offset_x, offset_y); + color, offset_x, offset_y); else success = FALSE; }