gimp/app/tools/gimpfiltertool-widgets.c
Alx Sa a9056419ce app/tools: Use NDE filter's drawable for on-canvas transform grid
Resolves #12403
gimp_filter_tool_set_transform_grid () is used to draw the on-canvas
transform grid for filters. It always assumes that the tool's selected
layer should be used to define these boundaries.
With NDE filters, you might be editing a filter on a different layer than
the actively selected one. This patch checks if an existing filter is being
edited, and if so, we grab the drawable from the filter rather than from
the tool.
2024-11-18 15:02:47 +00:00

970 lines
33 KiB
C

/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpfiltertool-widgets.c
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <string.h>
#include <gegl.h>
#include <gtk/gtk.h>
#include "libgimpmath/gimpmath.h"
#include "tools-types.h"
#include "core/gimpcontainer.h"
#include "core/gimpdrawablefilter.h"
#include "core/gimpitem.h"
#include "display/gimpdisplay.h"
#include "display/gimptoolfocus.h"
#include "display/gimptoolgyroscope.h"
#include "display/gimptoolline.h"
#include "display/gimptooltransformgrid.h"
#include "display/gimptoolwidgetgroup.h"
#include "gimpfilteroptions.h"
#include "gimpfiltertool.h"
#include "gimpfiltertool-widgets.h"
typedef struct _Controller Controller;
struct _Controller
{
GimpFilterTool *filter_tool;
GimpControllerType controller_type;
GimpToolWidget *widget;
GCallback creator_callback;
gpointer creator_data;
};
/* local function prototypes */
static Controller * gimp_filter_tool_controller_new (void);
static void gimp_filter_tool_controller_free (Controller *controller);
static void gimp_filter_tool_set_line (Controller *controller,
GeglRectangle *area,
gdouble x1,
gdouble y1,
gdouble x2,
gdouble y2);
static void gimp_filter_tool_line_changed (GimpToolWidget *widget,
Controller *controller);
static void gimp_filter_tool_set_slider_line (Controller *controller,
GeglRectangle *area,
gdouble x1,
gdouble y1,
gdouble x2,
gdouble y2,
const GimpControllerSlider *sliders,
gint n_sliders);
static void gimp_filter_tool_slider_line_changed (GimpToolWidget *widget,
Controller *controller);
static void gimp_filter_tool_set_transform_grid (Controller *controller,
GeglRectangle *area,
const GimpMatrix3 *transform);
static void gimp_filter_tool_transform_grid_changed (GimpToolWidget *widget,
Controller *controller);
static void gimp_filter_tool_set_transform_grids (Controller *controller,
GeglRectangle *area,
const GimpMatrix3 *transforms,
gint n_transforms);
static void gimp_filter_tool_transform_grids_changed (GimpToolWidget *widget,
Controller *controller);
static void gimp_filter_tool_set_gyroscope (Controller *controller,
GeglRectangle *area,
gdouble yaw,
gdouble pitch,
gdouble roll,
gdouble zoom,
gboolean invert);
static void gimp_filter_tool_gyroscope_changed (GimpToolWidget *widget,
Controller *controller);
static void gimp_filter_tool_set_focus (Controller *controller,
GeglRectangle *area,
GimpLimitType type,
gdouble x,
gdouble y,
gdouble radius,
gdouble aspect_ratio,
gdouble angle,
gdouble inner_limit,
gdouble midpoint);
static void gimp_filter_tool_focus_changed (GimpToolWidget *widget,
Controller *controller);
/* public functions */
GimpToolWidget *
gimp_filter_tool_create_widget (GimpFilterTool *filter_tool,
GimpControllerType controller_type,
const gchar *status_title,
GCallback callback,
gpointer callback_data,
GCallback *set_func,
gpointer *set_func_data)
{
GimpTool *tool;
GimpDisplayShell *shell;
Controller *controller;
g_return_val_if_fail (GIMP_IS_FILTER_TOOL (filter_tool), NULL);
g_return_val_if_fail (filter_tool->config != NULL, NULL);
tool = GIMP_TOOL (filter_tool);
g_return_val_if_fail (tool->display != NULL, NULL);
shell = gimp_display_get_shell (tool->display);
controller = gimp_filter_tool_controller_new ();
controller->filter_tool = filter_tool;
controller->controller_type = controller_type;
controller->creator_callback = callback;
controller->creator_data = callback_data;
switch (controller_type)
{
case GIMP_CONTROLLER_TYPE_LINE:
controller->widget = gimp_tool_line_new (shell, 100, 100, 500, 500);
g_object_set (controller->widget,
"status-title", status_title,
NULL);
g_signal_connect (controller->widget, "changed",
G_CALLBACK (gimp_filter_tool_line_changed),
controller);
*set_func = (GCallback) gimp_filter_tool_set_line;
*set_func_data = controller;
break;
case GIMP_CONTROLLER_TYPE_SLIDER_LINE:
controller->widget = gimp_tool_line_new (shell, 100, 100, 500, 500);
g_object_set (controller->widget,
"status-title", status_title,
NULL);
g_signal_connect (controller->widget, "changed",
G_CALLBACK (gimp_filter_tool_slider_line_changed),
controller);
*set_func = (GCallback) gimp_filter_tool_set_slider_line;
*set_func_data = controller;
break;
case GIMP_CONTROLLER_TYPE_TRANSFORM_GRID:
{
GimpMatrix3 transform;
gint off_x, off_y;
GeglRectangle area;
gdouble x1, y1;
gdouble x2, y2;
gimp_matrix3_identity (&transform);
gimp_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
x1 = off_x + area.x;
y1 = off_y + area.y;
x2 = x1 + area.width;
y2 = y1 + area.height;
controller->widget = gimp_tool_transform_grid_new (shell, &transform,
x1, y1, x2, y2);
g_object_set (controller->widget,
"pivot-x", (x1 + x2) / 2.0,
"pivot-y", (y1 + y2) / 2.0,
"inside-function", GIMP_TRANSFORM_FUNCTION_MOVE,
"outside-function", GIMP_TRANSFORM_FUNCTION_ROTATE,
"use-corner-handles", TRUE,
"use-perspective-handles", TRUE,
"use-side-handles", TRUE,
"use-shear-handles", TRUE,
"use-pivot-handle", TRUE,
NULL);
g_signal_connect (controller->widget, "changed",
G_CALLBACK (gimp_filter_tool_transform_grid_changed),
controller);
*set_func = (GCallback) gimp_filter_tool_set_transform_grid;
*set_func_data = controller;
}
break;
case GIMP_CONTROLLER_TYPE_TRANSFORM_GRIDS:
{
controller->widget = gimp_tool_widget_group_new (shell);
gimp_tool_widget_group_set_auto_raise (
GIMP_TOOL_WIDGET_GROUP (controller->widget), TRUE);
g_signal_connect (controller->widget, "changed",
G_CALLBACK (gimp_filter_tool_transform_grids_changed),
controller);
*set_func = (GCallback) gimp_filter_tool_set_transform_grids;
*set_func_data = controller;
}
break;
case GIMP_CONTROLLER_TYPE_GYROSCOPE:
{
GeglRectangle area;
gint off_x, off_y;
gimp_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
controller->widget = gimp_tool_gyroscope_new (shell);
g_object_set (controller->widget,
"speed", 1.0 / MAX (area.width, area.height),
"pivot-x", off_x + area.x + area.width / 2.0,
"pivot-y", off_y + area.y + area.height / 2.0,
NULL);
g_signal_connect (controller->widget, "changed",
G_CALLBACK (gimp_filter_tool_gyroscope_changed),
controller);
*set_func = (GCallback) gimp_filter_tool_set_gyroscope;
*set_func_data = controller;
}
break;
case GIMP_CONTROLLER_TYPE_FOCUS:
controller->widget = gimp_tool_focus_new (shell);
g_signal_connect (controller->widget, "changed",
G_CALLBACK (gimp_filter_tool_focus_changed),
controller);
*set_func = (GCallback) gimp_filter_tool_set_focus;
*set_func_data = controller;
break;
}
g_object_add_weak_pointer (G_OBJECT (controller->widget),
(gpointer) &controller->widget);
g_object_set_data_full (filter_tool->config,
"gimp-filter-tool-controller", controller,
(GDestroyNotify) gimp_filter_tool_controller_free);
return controller->widget;
}
static void
gimp_filter_tool_reset_transform_grid (GimpToolWidget *widget,
GimpFilterTool *filter_tool)
{
GimpMatrix3 *transform;
gint off_x, off_y;
GeglRectangle area;
gdouble x1, y1;
gdouble x2, y2;
gdouble pivot_x, pivot_y;
g_object_get (widget,
"transform", &transform,
NULL);
gimp_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
x1 = off_x + area.x;
y1 = off_y + area.y;
x2 = x1 + area.width;
y2 = y1 + area.height;
gimp_matrix3_transform_point (transform,
(x1 + x2) / 2.0, (y1 + y2) / 2.0,
&pivot_x, &pivot_y);
g_object_set (widget,
"pivot-x", pivot_x,
"pivot-y", pivot_y,
NULL);
g_free (transform);
}
void
gimp_filter_tool_reset_widget (GimpFilterTool *filter_tool,
GimpToolWidget *widget)
{
Controller *controller;
g_return_if_fail (GIMP_IS_FILTER_TOOL (filter_tool));
g_return_if_fail (GIMP_IS_TOOL_WIDGET (widget));
g_return_if_fail (filter_tool->config != NULL);
controller = g_object_get_data (filter_tool->config,
"gimp-filter-tool-controller");
g_return_if_fail (controller != NULL);
switch (controller->controller_type)
{
case GIMP_CONTROLLER_TYPE_TRANSFORM_GRID:
{
g_signal_handlers_block_by_func (controller->widget,
gimp_filter_tool_transform_grid_changed,
controller);
gimp_filter_tool_reset_transform_grid (controller->widget, filter_tool);
g_signal_handlers_unblock_by_func (controller->widget,
gimp_filter_tool_transform_grid_changed,
controller);
}
break;
case GIMP_CONTROLLER_TYPE_TRANSFORM_GRIDS:
{
g_signal_handlers_block_by_func (controller->widget,
gimp_filter_tool_transform_grids_changed,
controller);
gimp_container_foreach (
gimp_tool_widget_group_get_children (
GIMP_TOOL_WIDGET_GROUP (controller->widget)),
(GFunc) gimp_filter_tool_reset_transform_grid,
filter_tool);
g_signal_handlers_unblock_by_func (controller->widget,
gimp_filter_tool_transform_grids_changed,
controller);
}
break;
default:
break;
}
}
/* private functions */
static Controller *
gimp_filter_tool_controller_new (void)
{
return g_slice_new0 (Controller);
}
static void
gimp_filter_tool_controller_free (Controller *controller)
{
if (controller->widget)
{
g_signal_handlers_disconnect_by_data (controller->widget, controller);
g_clear_weak_pointer (&controller->widget);
}
g_slice_free (Controller, controller);
}
static void
gimp_filter_tool_set_line (Controller *controller,
GeglRectangle *area,
gdouble x1,
gdouble y1,
gdouble x2,
gdouble y2)
{
GimpTool *tool;
GimpDrawable *drawable;
if (! controller->widget)
return;
tool = GIMP_TOOL (controller->filter_tool);
drawable = tool->drawables->data;
if (drawable)
{
gint off_x, off_y;
gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
x1 += off_x + area->x;
y1 += off_y + area->y;
x2 += off_x + area->x;
y2 += off_y + area->y;
}
g_signal_handlers_block_by_func (controller->widget,
gimp_filter_tool_line_changed,
controller);
g_object_set (controller->widget,
"x1", x1,
"y1", y1,
"x2", x2,
"y2", y2,
NULL);
g_signal_handlers_unblock_by_func (controller->widget,
gimp_filter_tool_line_changed,
controller);
}
static void
gimp_filter_tool_line_changed (GimpToolWidget *widget,
Controller *controller)
{
GimpFilterTool *filter_tool = controller->filter_tool;
GimpControllerLineCallback line_callback;
gdouble x1, y1, x2, y2;
gint off_x, off_y;
GeglRectangle area;
line_callback = (GimpControllerLineCallback) controller->creator_callback;
g_object_get (widget,
"x1", &x1,
"y1", &y1,
"x2", &x2,
"y2", &y2,
NULL);
gimp_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
x1 -= off_x + area.x;
y1 -= off_y + area.y;
x2 -= off_x + area.x;
y2 -= off_y + area.y;
line_callback (controller->creator_data,
&area, x1, y1, x2, y2);
}
static void
gimp_filter_tool_set_slider_line (Controller *controller,
GeglRectangle *area,
gdouble x1,
gdouble y1,
gdouble x2,
gdouble y2,
const GimpControllerSlider *sliders,
gint n_sliders)
{
GimpTool *tool;
GimpDrawable *drawable;
if (! controller->widget)
return;
tool = GIMP_TOOL (controller->filter_tool);
drawable = tool->drawables->data;
if (drawable)
{
gint off_x, off_y;
gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
x1 += off_x + area->x;
y1 += off_y + area->y;
x2 += off_x + area->x;
y2 += off_y + area->y;
}
g_signal_handlers_block_by_func (controller->widget,
gimp_filter_tool_slider_line_changed,
controller);
g_object_set (controller->widget,
"x1", x1,
"y1", y1,
"x2", x2,
"y2", y2,
NULL);
gimp_tool_line_set_sliders (GIMP_TOOL_LINE (controller->widget),
sliders, n_sliders);
g_signal_handlers_unblock_by_func (controller->widget,
gimp_filter_tool_slider_line_changed,
controller);
}
static void
gimp_filter_tool_slider_line_changed (GimpToolWidget *widget,
Controller *controller)
{
GimpFilterTool *filter_tool = controller->filter_tool;
GimpControllerSliderLineCallback slider_line_callback;
gdouble x1, y1, x2, y2;
const GimpControllerSlider *sliders;
gint n_sliders;
gint off_x, off_y;
GeglRectangle area;
slider_line_callback =
(GimpControllerSliderLineCallback) controller->creator_callback;
g_object_get (widget,
"x1", &x1,
"y1", &y1,
"x2", &x2,
"y2", &y2,
NULL);
sliders = gimp_tool_line_get_sliders (GIMP_TOOL_LINE (controller->widget),
&n_sliders);
gimp_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
x1 -= off_x + area.x;
y1 -= off_y + area.y;
x2 -= off_x + area.x;
y2 -= off_y + area.y;
slider_line_callback (controller->creator_data,
&area, x1, y1, x2, y2, sliders, n_sliders);
}
static void
gimp_filter_tool_set_transform_grid (Controller *controller,
GeglRectangle *area,
const GimpMatrix3 *transform)
{
GimpTool *tool;
GimpFilterTool *filter_tool;
GimpDrawable *drawable;
gdouble x1 = area->x;
gdouble y1 = area->y;
gdouble x2 = area->x + area->width;
gdouble y2 = area->y + area->height;
GimpMatrix3 matrix;
if (! controller->widget)
return;
tool = GIMP_TOOL (controller->filter_tool);
filter_tool = controller->filter_tool;
if (filter_tool->existing_filter)
drawable = gimp_drawable_filter_get_drawable (filter_tool->existing_filter);
else
drawable = tool->drawables->data;
if (drawable)
{
gint off_x, off_y;
gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
x1 += off_x;
y1 += off_y;
x2 += off_x;
y2 += off_y;
}
gimp_matrix3_identity (&matrix);
gimp_matrix3_translate (&matrix, -x1, -y1);
gimp_matrix3_mult (transform, &matrix);
gimp_matrix3_translate (&matrix, +x1, +y1);
g_signal_handlers_block_by_func (controller->widget,
gimp_filter_tool_transform_grid_changed,
controller);
g_object_set (controller->widget,
"transform", &matrix,
"x1", x1,
"y1", y1,
"x2", x2,
"y2", y2,
NULL);
g_signal_handlers_unblock_by_func (controller->widget,
gimp_filter_tool_transform_grid_changed,
controller);
}
static void
gimp_filter_tool_transform_grid_changed (GimpToolWidget *widget,
Controller *controller)
{
GimpFilterTool *filter_tool = controller->filter_tool;
GimpControllerTransformGridCallback transform_grid_callback;
gint off_x, off_y;
GeglRectangle area;
GimpMatrix3 *transform;
GimpMatrix3 matrix;
transform_grid_callback =
(GimpControllerTransformGridCallback) controller->creator_callback;
g_object_get (widget,
"transform", &transform,
NULL);
gimp_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
gimp_matrix3_identity (&matrix);
gimp_matrix3_translate (&matrix, +(off_x + area.x), +(off_y + area.y));
gimp_matrix3_mult (transform, &matrix);
gimp_matrix3_translate (&matrix, -(off_x + area.x), -(off_y + area.y));
transform_grid_callback (controller->creator_data,
&area, &matrix);
g_free (transform);
}
static void
gimp_filter_tool_set_transform_grids (Controller *controller,
GeglRectangle *area,
const GimpMatrix3 *transforms,
gint n_transforms)
{
GimpTool *tool;
GimpDisplayShell *shell;
GimpDrawable *drawable;
GimpContainer *grids;
GimpToolWidget *grid = NULL;
gdouble x1 = area->x;
gdouble y1 = area->y;
gdouble x2 = area->x + area->width;
gdouble y2 = area->y + area->height;
GimpMatrix3 matrix;
gint i;
if (! controller->widget)
return;
tool = GIMP_TOOL (controller->filter_tool);
shell = gimp_display_get_shell (tool->display);
drawable = tool->drawables->data;
g_signal_handlers_block_by_func (controller->widget,
gimp_filter_tool_transform_grids_changed,
controller);
if (drawable)
{
gint off_x, off_y;
gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
x1 += off_x;
y1 += off_y;
x2 += off_x;
y2 += off_y;
}
grids = gimp_tool_widget_group_get_children (
GIMP_TOOL_WIDGET_GROUP (controller->widget));
if (n_transforms > gimp_container_get_n_children (grids))
{
gimp_matrix3_identity (&matrix);
for (i = gimp_container_get_n_children (grids); i < n_transforms; i++)
{
gdouble pivot_x;
gdouble pivot_y;
grid = gimp_tool_transform_grid_new (shell, &matrix, x1, y1, x2, y2);
if (i > 0 && ! memcmp (&transforms[i], &transforms[i - 1],
sizeof (GimpMatrix3)))
{
g_object_get (gimp_container_get_last_child (grids),
"pivot-x", &pivot_x,
"pivot-y", &pivot_y,
NULL);
}
else
{
pivot_x = (x1 + x2) / 2.0;
pivot_y = (y1 + y2) / 2.0;
gimp_matrix3_transform_point (&transforms[i],
pivot_x, pivot_y,
&pivot_x, &pivot_y);
}
g_object_set (grid,
"pivot-x", pivot_x,
"pivot-y", pivot_y,
"inside-function", GIMP_TRANSFORM_FUNCTION_MOVE,
"outside-function", GIMP_TRANSFORM_FUNCTION_ROTATE,
"use-corner-handles", TRUE,
"use-perspective-handles", TRUE,
"use-side-handles", TRUE,
"use-shear-handles", TRUE,
"use-pivot-handle", TRUE,
NULL);
gimp_container_add (grids, GIMP_OBJECT (grid));
g_object_unref (grid);
}
gimp_tool_widget_set_focus (grid, TRUE);
}
else
{
while (gimp_container_get_n_children (grids) > n_transforms)
gimp_container_remove (grids, gimp_container_get_last_child (grids));
}
for (i = 0; i < n_transforms; i++)
{
gimp_matrix3_identity (&matrix);
gimp_matrix3_translate (&matrix, -x1, -y1);
gimp_matrix3_mult (&transforms[i], &matrix);
gimp_matrix3_translate (&matrix, +x1, +y1);
g_object_set (gimp_container_get_child_by_index (grids, i),
"transform", &matrix,
"x1", x1,
"y1", y1,
"x2", x2,
"y2", y2,
NULL);
}
g_signal_handlers_unblock_by_func (controller->widget,
gimp_filter_tool_transform_grids_changed,
controller);
}
static void
gimp_filter_tool_transform_grids_changed (GimpToolWidget *widget,
Controller *controller)
{
GimpFilterTool *filter_tool = controller->filter_tool;
GimpControllerTransformGridsCallback transform_grids_callback;
GimpContainer *grids;
gint off_x, off_y;
GeglRectangle area;
GimpMatrix3 *transforms;
gint n_transforms;
gint i;
transform_grids_callback =
(GimpControllerTransformGridsCallback) controller->creator_callback;
grids = gimp_tool_widget_group_get_children (
GIMP_TOOL_WIDGET_GROUP (controller->widget));
gimp_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
n_transforms = gimp_container_get_n_children (grids);
transforms = g_new (GimpMatrix3, n_transforms);
for (i = 0; i < n_transforms; i++)
{
GimpMatrix3 *transform;
g_object_get (gimp_container_get_child_by_index (grids, i),
"transform", &transform,
NULL);
gimp_matrix3_identity (&transforms[i]);
gimp_matrix3_translate (&transforms[i],
+(off_x + area.x), +(off_y + area.y));
gimp_matrix3_mult (transform, &transforms[i]);
gimp_matrix3_translate (&transforms[i],
-(off_x + area.x), -(off_y + area.y));
g_free (transform);
}
transform_grids_callback (controller->creator_data,
&area, transforms, n_transforms);
g_free (transforms);
}
static void
gimp_filter_tool_set_gyroscope (Controller *controller,
GeglRectangle *area,
gdouble yaw,
gdouble pitch,
gdouble roll,
gdouble zoom,
gboolean invert)
{
if (! controller->widget)
return;
g_signal_handlers_block_by_func (controller->widget,
gimp_filter_tool_gyroscope_changed,
controller);
g_object_set (controller->widget,
"yaw", yaw,
"pitch", pitch,
"roll", roll,
"zoom", zoom,
"invert", invert,
NULL);
g_signal_handlers_unblock_by_func (controller->widget,
gimp_filter_tool_gyroscope_changed,
controller);
}
static void
gimp_filter_tool_gyroscope_changed (GimpToolWidget *widget,
Controller *controller)
{
GimpFilterTool *filter_tool = controller->filter_tool;
GimpControllerGyroscopeCallback gyroscope_callback;
gint off_x, off_y;
GeglRectangle area;
gdouble yaw;
gdouble pitch;
gdouble roll;
gdouble zoom;
gboolean invert;
gyroscope_callback =
(GimpControllerGyroscopeCallback) controller->creator_callback;
gimp_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
g_object_get (widget,
"yaw", &yaw,
"pitch", &pitch,
"roll", &roll,
"zoom", &zoom,
"invert", &invert,
NULL);
gyroscope_callback (controller->creator_data,
&area, yaw, pitch, roll, zoom, invert);
}
static void
gimp_filter_tool_set_focus (Controller *controller,
GeglRectangle *area,
GimpLimitType type,
gdouble x,
gdouble y,
gdouble radius,
gdouble aspect_ratio,
gdouble angle,
gdouble inner_limit,
gdouble midpoint)
{
GimpTool *tool;
GimpDrawable *drawable;
if (! controller->widget)
return;
tool = GIMP_TOOL (controller->filter_tool);
drawable = tool->drawables->data;
if (drawable)
{
gint off_x, off_y;
gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
x += off_x + area->x;
y += off_y + area->y;
}
g_signal_handlers_block_by_func (controller->widget,
gimp_filter_tool_focus_changed,
controller);
g_object_set (controller->widget,
"type", type,
"x", x,
"y", y,
"radius", radius,
"aspect-ratio", aspect_ratio,
"angle", angle,
"inner-limit", inner_limit,
"midpoint", midpoint,
NULL);
g_signal_handlers_unblock_by_func (controller->widget,
gimp_filter_tool_focus_changed,
controller);
}
static void
gimp_filter_tool_focus_changed (GimpToolWidget *widget,
Controller *controller)
{
GimpFilterTool *filter_tool = controller->filter_tool;
GimpControllerFocusCallback focus_callback;
GimpLimitType type;
gdouble x, y;
gdouble radius;
gdouble aspect_ratio;
gdouble angle;
gdouble inner_limit;
gdouble midpoint;
gint off_x, off_y;
GeglRectangle area;
focus_callback = (GimpControllerFocusCallback) controller->creator_callback;
g_object_get (widget,
"type", &type,
"x", &x,
"y", &y,
"radius", &radius,
"aspect-ratio", &aspect_ratio,
"angle", &angle,
"inner-limit", &inner_limit,
"midpoint", &midpoint,
NULL);
gimp_filter_tool_get_drawable_area (filter_tool, &off_x, &off_y, &area);
x -= off_x + area.x;
y -= off_y + area.y;
focus_callback (controller->creator_data,
&area,
type,
x,
y,
radius,
aspect_ratio,
angle,
inner_limit,
midpoint);
}