mirror of https://github.com/GNOME/gimp.git
app: add "Composited preview" option to transform tools
Add a "Composited preview" option to all transform-grid tools, which displays the transform preview as part of the image composition (i.e., as it would actually look when applying the transformation, keeping the layer at the right position in the stack, and with the right layer mode), instead of using an overlay. This option is off by default, since it's generally slower to render than an overlay, due to the lack of mipmap rendering. We're also still using an overlay when transfoming a selection, and not a whole layer.
This commit is contained in:
parent
2e26603a55
commit
a335827896
|
@ -50,6 +50,7 @@ enum
|
|||
PROP_DIRECTION,
|
||||
PROP_DIRECTION_LINKED,
|
||||
PROP_SHOW_PREVIEW,
|
||||
PROP_COMPOSITED_PREVIEW,
|
||||
PROP_PREVIEW_OPACITY,
|
||||
PROP_GRID_TYPE,
|
||||
PROP_GRID_SIZE,
|
||||
|
@ -111,6 +112,13 @@ gimp_transform_grid_options_class_init (GimpTransformGridOptionsClass *klass)
|
|||
TRUE,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
|
||||
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_COMPOSITED_PREVIEW,
|
||||
"composited-preview",
|
||||
_("Composited preview"),
|
||||
_("Show preview as part of the image composition"),
|
||||
FALSE,
|
||||
GIMP_PARAM_STATIC_STRINGS);
|
||||
|
||||
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_PREVIEW_OPACITY,
|
||||
"preview-opacity",
|
||||
_("Image opacity"),
|
||||
|
@ -228,6 +236,9 @@ gimp_transform_grid_options_set_property (GObject *object,
|
|||
case PROP_SHOW_PREVIEW:
|
||||
options->show_preview = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_COMPOSITED_PREVIEW:
|
||||
options->composited_preview = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_PREVIEW_OPACITY:
|
||||
options->preview_opacity = g_value_get_double (value);
|
||||
break;
|
||||
|
@ -293,6 +304,9 @@ gimp_transform_grid_options_get_property (GObject *object,
|
|||
case PROP_SHOW_PREVIEW:
|
||||
g_value_set_boolean (value, options->show_preview);
|
||||
break;
|
||||
case PROP_COMPOSITED_PREVIEW:
|
||||
g_value_set_boolean (value, options->composited_preview);
|
||||
break;
|
||||
case PROP_PREVIEW_OPACITY:
|
||||
g_value_set_double (value, options->preview_opacity);
|
||||
break;
|
||||
|
@ -352,6 +366,8 @@ gimp_transform_grid_options_gui (GimpToolOptions *tool_options)
|
|||
GObject *config = G_OBJECT (tool_options);
|
||||
GimpTransformGridToolClass *tg_class;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *vbox2;
|
||||
GtkWidget *button;
|
||||
GtkWidget *frame;
|
||||
GtkWidget *combo;
|
||||
GtkWidget *scale;
|
||||
|
@ -367,9 +383,7 @@ gimp_transform_grid_options_gui (GimpToolOptions *tool_options)
|
|||
if (tg_class->matrix_to_info)
|
||||
{
|
||||
GimpTransformOptions *tr_options = GIMP_TRANSFORM_OPTIONS (tool_options);
|
||||
GtkWidget *vbox2;
|
||||
GtkWidget *hbox;
|
||||
GtkWidget *button;
|
||||
|
||||
vbox2 = gtk_bin_get_child (GTK_BIN (tr_options->direction_frame));
|
||||
g_object_ref (vbox2);
|
||||
|
@ -397,12 +411,25 @@ gimp_transform_grid_options_gui (GimpToolOptions *tool_options)
|
|||
g_type_class_unref (tg_class);
|
||||
|
||||
/* the preview frame */
|
||||
vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
||||
|
||||
button = gimp_prop_check_button_new (config, "composited-preview", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), button, FALSE, FALSE, 0);
|
||||
gtk_widget_show (button);
|
||||
|
||||
scale = gimp_prop_spin_scale_new (config, "preview-opacity", NULL,
|
||||
0.01, 0.1, 0);
|
||||
gimp_prop_widget_set_factor (scale, 100.0, 0.0, 0.0, 1);
|
||||
gtk_box_pack_start (GTK_BOX (vbox2), scale, FALSE, FALSE, 0);
|
||||
gtk_widget_show (scale);
|
||||
|
||||
g_object_bind_property (config, "composited-preview",
|
||||
scale, "sensitive",
|
||||
G_BINDING_SYNC_CREATE |
|
||||
G_BINDING_INVERT_BOOLEAN);
|
||||
|
||||
frame = gimp_prop_expanding_frame_new (config, "show-preview", NULL,
|
||||
scale, NULL);
|
||||
vbox2, NULL);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||
|
||||
/* the guides frame */
|
||||
|
@ -431,8 +458,7 @@ gimp_transform_grid_options_gui (GimpToolOptions *tool_options)
|
|||
|
||||
if (tool_options->tool_info->tool_type == GIMP_TYPE_ROTATE_TOOL)
|
||||
{
|
||||
GtkWidget *button;
|
||||
gchar *label;
|
||||
gchar *label;
|
||||
|
||||
label = g_strdup_printf (_("15 degrees (%s)"),
|
||||
gimp_get_mod_string (extend_mask));
|
||||
|
@ -447,8 +473,7 @@ gimp_transform_grid_options_gui (GimpToolOptions *tool_options)
|
|||
}
|
||||
else if (tool_options->tool_info->tool_type == GIMP_TYPE_SCALE_TOOL)
|
||||
{
|
||||
GtkWidget *button;
|
||||
gchar *label;
|
||||
gchar *label;
|
||||
|
||||
label = g_strdup_printf (_("Keep aspect (%s)"),
|
||||
gimp_get_mod_string (extend_mask));
|
||||
|
@ -474,8 +499,7 @@ gimp_transform_grid_options_gui (GimpToolOptions *tool_options)
|
|||
}
|
||||
else if (tool_options->tool_info->tool_type == GIMP_TYPE_PERSPECTIVE_TOOL)
|
||||
{
|
||||
GtkWidget *button;
|
||||
gchar *label;
|
||||
gchar *label;
|
||||
|
||||
label = g_strdup_printf (_("Constrain handles (%s)"),
|
||||
gimp_get_mod_string (extend_mask));
|
||||
|
@ -541,9 +565,8 @@ gimp_transform_grid_options_gui (GimpToolOptions *tool_options)
|
|||
N_("Lock pivot position to canvas") },
|
||||
};
|
||||
|
||||
GtkWidget *button;
|
||||
gchar *label;
|
||||
gint i;
|
||||
gchar *label;
|
||||
gint i;
|
||||
|
||||
frame = NULL;
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ struct _GimpTransformGridOptions
|
|||
|
||||
gboolean direction_linked;
|
||||
gboolean show_preview;
|
||||
gboolean composited_preview;
|
||||
gdouble preview_opacity;
|
||||
GimpGuidesType grid_type;
|
||||
gint grid_size;
|
||||
|
|
|
@ -26,9 +26,19 @@
|
|||
|
||||
#include "tools-types.h"
|
||||
|
||||
#include "gegl/gimpapplicator.h"
|
||||
#include "gegl/gimp-gegl-nodes.h"
|
||||
#include "gegl/gimp-gegl-utils.h"
|
||||
|
||||
#include "core/gimp.h"
|
||||
#include "core/gimp-transform-resize.h"
|
||||
#include "core/gimp-transform-utils.h"
|
||||
#include "core/gimpboundary.h"
|
||||
#include "core/gimpcontainer.h"
|
||||
#include "core/gimpdrawablefilter.h"
|
||||
#include "core/gimperror.h"
|
||||
#include "core/gimpfilter.h"
|
||||
#include "core/gimpgrouplayer.h"
|
||||
#include "core/gimpimage.h"
|
||||
#include "core/gimpimage-undo.h"
|
||||
#include "core/gimpimage-undo-push.h"
|
||||
|
@ -68,6 +78,22 @@
|
|||
#define UNDO_COMPRESS_TIME (0.5 * G_TIME_SPAN_SECOND)
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GimpTransformGridTool *tg_tool;
|
||||
|
||||
GimpDrawable *drawable;
|
||||
GimpDrawableFilter *filter;
|
||||
|
||||
GimpDrawable *clip_drawable;
|
||||
|
||||
GeglNode *transform_node;
|
||||
GeglNode *crop_node;
|
||||
|
||||
GimpMatrix3 transform;
|
||||
GeglRectangle bounds;
|
||||
} Filter;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gint64 time;
|
||||
|
@ -155,6 +181,9 @@ static void gimp_transform_grid_tool_widget_response (GimpToolWidget
|
|||
gint response_id,
|
||||
GimpTransformGridTool *tg_tool);
|
||||
|
||||
static void gimp_transform_grid_tool_filter_flush (GimpDrawableFilter *filter,
|
||||
GimpTransformGridTool *tg_tool);
|
||||
|
||||
static void gimp_transform_grid_tool_halt (GimpTransformGridTool *tg_tool);
|
||||
static void gimp_transform_grid_tool_commit (GimpTransformGridTool *tg_tool);
|
||||
|
||||
|
@ -169,12 +198,27 @@ static void gimp_transform_grid_tool_response (GimpToolGui
|
|||
gint response_id,
|
||||
GimpTransformGridTool *tg_tool);
|
||||
|
||||
static gboolean gimp_transform_grid_tool_composited_preview (GimpTransformGridTool *tg_tool);
|
||||
static void gimp_transform_grid_tool_update_sensitivity (GimpTransformGridTool *tg_tool);
|
||||
static void gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool);
|
||||
static void gimp_transform_grid_tool_hide_active_object (GimpTransformGridTool *tg_tool,
|
||||
GimpObject *object);
|
||||
static void gimp_transform_grid_tool_show_active_object (GimpTransformGridTool *tg_tool);
|
||||
|
||||
static void gimp_transform_grid_tool_add_filter (GimpDrawable *drawable,
|
||||
GimpTransformGridTool *tg_tool);
|
||||
static void gimp_transform_grid_tool_remove_filter (GimpDrawable *drawable,
|
||||
GimpTransformGridTool *tg_tool);
|
||||
|
||||
static void gimp_transform_grid_tool_effective_mode_changed
|
||||
(GimpLayer *layer,
|
||||
GimpTransformGridTool *tg_tool);
|
||||
|
||||
static Filter * filter_new (GimpTransformGridTool *tg_tool,
|
||||
GimpDrawable *drawable,
|
||||
gboolean add_filter);
|
||||
static void filter_free (Filter *filter);
|
||||
|
||||
static UndoInfo * undo_info_new (void);
|
||||
static void undo_info_free (UndoInfo *info);
|
||||
|
||||
|
@ -242,9 +286,10 @@ gimp_transform_grid_tool_init (GimpTransformGridTool *tg_tool)
|
|||
gimp_tool_control_set_scroll_lock (tool->control, TRUE);
|
||||
gimp_tool_control_set_preserve (tool->control, FALSE);
|
||||
gimp_tool_control_set_dirty_mask (tool->control,
|
||||
GIMP_DIRTY_IMAGE_SIZE |
|
||||
GIMP_DIRTY_DRAWABLE |
|
||||
GIMP_DIRTY_SELECTION |
|
||||
GIMP_DIRTY_IMAGE_SIZE |
|
||||
GIMP_DIRTY_IMAGE_STRUCTURE |
|
||||
GIMP_DIRTY_DRAWABLE |
|
||||
GIMP_DIRTY_SELECTION |
|
||||
GIMP_DIRTY_ACTIVE_DRAWABLE);
|
||||
gimp_tool_control_set_active_modifiers (tool->control,
|
||||
GIMP_TOOL_ACTIVE_MODIFIERS_SAME);
|
||||
|
@ -618,32 +663,35 @@ gimp_transform_grid_tool_options_notify (GimpTool *tool,
|
|||
/* recalculate the tool's transformation matrix */
|
||||
gimp_transform_tool_recalc_matrix (tr_tool, tool->display);
|
||||
}
|
||||
else if (! strcmp (pspec->name, "show-preview"))
|
||||
else if (! strcmp (pspec->name, "show-preview") ||
|
||||
! strcmp (pspec->name, "composited-preview"))
|
||||
{
|
||||
if (tg_tool->preview)
|
||||
{
|
||||
GimpDisplay *display;
|
||||
GimpObject *object;
|
||||
gboolean show_preview;
|
||||
|
||||
show_preview = gimp_transform_grid_options_show_preview (tg_options) &&
|
||||
tr_tool->transform_valid;
|
||||
|
||||
gimp_canvas_item_set_visible (tg_tool->preview, show_preview);
|
||||
|
||||
display = tool->display;
|
||||
object = gimp_transform_tool_get_active_object (tr_tool, display);
|
||||
|
||||
if (object)
|
||||
{
|
||||
if (gimp_transform_grid_options_show_preview (tg_options))
|
||||
gimp_transform_grid_tool_hide_active_object (tg_tool, object);
|
||||
if (tg_options->show_preview &&
|
||||
! gimp_transform_grid_tool_composited_preview (tg_tool))
|
||||
{
|
||||
gimp_transform_grid_tool_hide_active_object (tg_tool, object);
|
||||
}
|
||||
else
|
||||
gimp_transform_grid_tool_show_active_object (tg_tool);
|
||||
{
|
||||
gimp_transform_grid_tool_show_active_object (tg_tool);
|
||||
}
|
||||
}
|
||||
|
||||
gimp_transform_grid_tool_update_preview (tg_tool);
|
||||
}
|
||||
}
|
||||
else if (! strcmp (pspec->name, "clip") ||
|
||||
else if (! strcmp (pspec->name, "interpolation") ||
|
||||
! strcmp (pspec->name, "clip") ||
|
||||
! strcmp (pspec->name, "preview-opacity"))
|
||||
{
|
||||
gimp_transform_grid_tool_update_preview (tg_tool);
|
||||
|
@ -673,10 +721,10 @@ gimp_transform_grid_tool_draw (GimpDrawTool *draw_tool)
|
|||
if (tr_options->direction == GIMP_TRANSFORM_BACKWARD)
|
||||
gimp_matrix3_invert (&matrix);
|
||||
|
||||
if (tg_tool->widget)
|
||||
if (tr_options->type == GIMP_TRANSFORM_TYPE_LAYER ||
|
||||
tr_options->type == GIMP_TRANSFORM_TYPE_IMAGE)
|
||||
{
|
||||
GimpPickable *pickable;
|
||||
gboolean show_preview;
|
||||
|
||||
if (tr_options->type == GIMP_TRANSFORM_TYPE_IMAGE)
|
||||
{
|
||||
|
@ -690,9 +738,6 @@ gimp_transform_grid_tool_draw (GimpDrawTool *draw_tool)
|
|||
pickable = GIMP_PICKABLE (tool->drawable);
|
||||
}
|
||||
|
||||
show_preview = gimp_transform_grid_options_show_preview (options) &&
|
||||
tr_tool->transform_valid;
|
||||
|
||||
tg_tool->preview =
|
||||
gimp_draw_tool_add_transform_preview (draw_tool,
|
||||
pickable,
|
||||
|
@ -703,10 +748,6 @@ gimp_transform_grid_tool_draw (GimpDrawTool *draw_tool)
|
|||
tr_tool->y2);
|
||||
g_object_add_weak_pointer (G_OBJECT (tg_tool->preview),
|
||||
(gpointer) &tg_tool->preview);
|
||||
|
||||
gimp_canvas_item_set_visible (tg_tool->preview, show_preview);
|
||||
|
||||
GIMP_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool);
|
||||
}
|
||||
|
||||
if (tr_options->type == GIMP_TRANSFORM_TYPE_SELECTION)
|
||||
|
@ -786,6 +827,8 @@ gimp_transform_grid_tool_draw (GimpDrawTool *draw_tool)
|
|||
}
|
||||
}
|
||||
|
||||
GIMP_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool);
|
||||
|
||||
gimp_transform_grid_tool_update_preview (tg_tool);
|
||||
}
|
||||
|
||||
|
@ -1058,6 +1101,16 @@ gimp_transform_grid_tool_widget_response (GimpToolWidget *widget,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_transform_grid_tool_filter_flush (GimpDrawableFilter *filter,
|
||||
GimpTransformGridTool *tg_tool)
|
||||
{
|
||||
GimpTool *tool = GIMP_TOOL (tg_tool);
|
||||
GimpImage *image = gimp_display_get_image (tool->display);
|
||||
|
||||
gimp_projection_flush (gimp_image_get_projection (image));
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_transform_grid_tool_halt (GimpTransformGridTool *tg_tool)
|
||||
{
|
||||
|
@ -1070,6 +1123,8 @@ gimp_transform_grid_tool_halt (GimpTransformGridTool *tg_tool)
|
|||
gimp_draw_tool_set_widget (GIMP_DRAW_TOOL (tg_tool), NULL);
|
||||
g_clear_object (&tg_tool->widget);
|
||||
|
||||
g_clear_pointer (&tg_tool->filters, g_hash_table_unref);
|
||||
|
||||
if (tg_tool->gui)
|
||||
gimp_tool_gui_hide (tg_tool->gui);
|
||||
|
||||
|
@ -1405,6 +1460,19 @@ gimp_transform_grid_tool_response (GimpToolGui *gui,
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_transform_grid_tool_composited_preview (GimpTransformGridTool *tg_tool)
|
||||
{
|
||||
GimpTool *tool = GIMP_TOOL (tg_tool);
|
||||
GimpTransformOptions *tr_options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tg_tool);
|
||||
GimpTransformGridOptions *tg_options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tg_tool);
|
||||
GimpImage *image = gimp_display_get_image (tool->display);
|
||||
|
||||
return tg_options->composited_preview &&
|
||||
tr_options->type == GIMP_TRANSFORM_TYPE_LAYER &&
|
||||
gimp_channel_is_empty (gimp_image_get_mask (image));
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_transform_grid_tool_update_sensitivity (GimpTransformGridTool *tg_tool)
|
||||
{
|
||||
|
@ -1432,26 +1500,127 @@ gimp_transform_grid_tool_update_sensitivity (GimpTransformGridTool *tg_tool)
|
|||
static void
|
||||
gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool)
|
||||
{
|
||||
GimpTool *tool = GIMP_TOOL (tg_tool);
|
||||
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
|
||||
GimpTransformOptions *tr_options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tg_tool);
|
||||
GimpTransformGridOptions *tg_options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tg_tool);
|
||||
gint i;
|
||||
|
||||
if (tg_options->show_preview &&
|
||||
gimp_transform_grid_tool_composited_preview (tg_tool) &&
|
||||
tr_tool->transform_valid)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
GimpDrawable *drawable;
|
||||
Filter *filter;
|
||||
|
||||
if (! tg_tool->filters)
|
||||
{
|
||||
tg_tool->filters = g_hash_table_new_full (
|
||||
g_direct_hash, g_direct_equal,
|
||||
NULL, (GDestroyNotify) filter_free);
|
||||
|
||||
gimp_transform_grid_tool_add_filter (tool->drawable, tg_tool);
|
||||
}
|
||||
|
||||
g_hash_table_iter_init (&iter, tg_tool->filters);
|
||||
|
||||
while (g_hash_table_iter_next (&iter,
|
||||
(gpointer *) &drawable,
|
||||
(gpointer *) &filter))
|
||||
{
|
||||
GimpMatrix3 transform;
|
||||
GeglRectangle bounds;
|
||||
gint offset_x;
|
||||
gint offset_y;
|
||||
gint x1, y1;
|
||||
gint x2, y2;
|
||||
gboolean update = FALSE;
|
||||
|
||||
if (! filter->filter)
|
||||
continue;
|
||||
|
||||
gimp_item_get_offset (GIMP_ITEM (drawable), &offset_x, &offset_y);
|
||||
|
||||
gimp_matrix3_identity (&transform);
|
||||
gimp_matrix3_translate (&transform, +offset_x, +offset_y);
|
||||
gimp_matrix3_mult (&tr_tool->transform, &transform);
|
||||
gimp_matrix3_translate (&transform, -offset_x, -offset_y);
|
||||
|
||||
gimp_transform_resize_boundary (&tr_tool->transform,
|
||||
gimp_item_get_clip (
|
||||
GIMP_ITEM (filter->clip_drawable),
|
||||
tr_options->clip),
|
||||
tr_tool->x1, tr_tool->y1,
|
||||
tr_tool->x2, tr_tool->y2,
|
||||
&x1, &y1,
|
||||
&x2, &y2);
|
||||
|
||||
bounds.x = x1 - offset_x;
|
||||
bounds.y = y1 - offset_y;
|
||||
bounds.width = x2 - x1;
|
||||
bounds.height = y2 - y1;
|
||||
|
||||
if (! gimp_matrix3_equal (&transform, &filter->transform))
|
||||
{
|
||||
filter->transform = transform;
|
||||
|
||||
gimp_gegl_node_set_matrix (filter->transform_node, &transform);
|
||||
|
||||
update = TRUE;
|
||||
}
|
||||
|
||||
if (! gegl_rectangle_equal (&bounds, &filter->bounds))
|
||||
{
|
||||
filter->bounds = bounds;
|
||||
|
||||
gegl_node_set (filter->crop_node,
|
||||
"x", (gdouble) bounds.x,
|
||||
"y", (gdouble) bounds.y,
|
||||
"width", (gdouble) bounds.width,
|
||||
"height", (gdouble) bounds.height,
|
||||
NULL);
|
||||
|
||||
update = TRUE;
|
||||
}
|
||||
|
||||
if (GIMP_IS_LAYER (drawable))
|
||||
{
|
||||
gimp_drawable_filter_set_add_alpha (
|
||||
filter->filter,
|
||||
tr_options->interpolation != GIMP_INTERPOLATION_NONE);
|
||||
}
|
||||
|
||||
if (update)
|
||||
gimp_drawable_filter_apply (filter->filter, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_clear_pointer (&tg_tool->filters, g_hash_table_unref);
|
||||
}
|
||||
|
||||
if (tg_tool->preview)
|
||||
{
|
||||
gboolean show_preview;
|
||||
|
||||
show_preview = gimp_transform_grid_options_show_preview (tg_options) &&
|
||||
tr_tool->transform_valid;
|
||||
|
||||
gimp_canvas_item_begin_change (tg_tool->preview);
|
||||
gimp_canvas_item_set_visible (tg_tool->preview, show_preview);
|
||||
g_object_set (tg_tool->preview,
|
||||
"transform", &tr_tool->transform,
|
||||
"clip", tr_options->clip,
|
||||
"opacity", tg_options->preview_opacity,
|
||||
NULL);
|
||||
gimp_canvas_item_end_change (tg_tool->preview);
|
||||
if (tg_options->show_preview &&
|
||||
! gimp_transform_grid_tool_composited_preview (tg_tool) &&
|
||||
tr_tool->transform_valid)
|
||||
{
|
||||
gimp_canvas_item_begin_change (tg_tool->preview);
|
||||
gimp_canvas_item_set_visible (tg_tool->preview, TRUE);
|
||||
g_object_set (
|
||||
tg_tool->preview,
|
||||
"transform", &tr_tool->transform,
|
||||
"clip", gimp_item_get_clip (GIMP_ITEM (tool->drawable),
|
||||
tr_options->clip),
|
||||
"opacity", tg_options->preview_opacity,
|
||||
NULL);
|
||||
gimp_canvas_item_end_change (tg_tool->preview);
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_canvas_item_set_visible (tg_tool->preview, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (tg_tool->boundary_in)
|
||||
|
@ -1502,6 +1671,7 @@ gimp_transform_grid_tool_hide_active_object (GimpTransformGridTool *tg_tool,
|
|||
{
|
||||
/* hide only complete layers and channels, not layer masks */
|
||||
if (tr_options->type == GIMP_TRANSFORM_TYPE_LAYER &&
|
||||
! options->composited_preview &&
|
||||
GIMP_IS_DRAWABLE (object) &&
|
||||
! GIMP_IS_LAYER_MASK (object) &&
|
||||
gimp_item_get_visible (GIMP_ITEM (object)) &&
|
||||
|
@ -1550,6 +1720,197 @@ gimp_transform_grid_tool_show_active_object (GimpTransformGridTool *tg_tool)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_transform_grid_tool_add_filter (GimpDrawable *drawable,
|
||||
GimpTransformGridTool *tg_tool)
|
||||
{
|
||||
Filter *filter;
|
||||
GimpLayerMode mode = GIMP_LAYER_MODE_NORMAL;
|
||||
|
||||
if (GIMP_IS_LAYER (drawable))
|
||||
{
|
||||
gimp_layer_get_effective_mode (GIMP_LAYER (drawable),
|
||||
&mode, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
if (mode != GIMP_LAYER_MODE_PASS_THROUGH)
|
||||
{
|
||||
filter = filter_new (tg_tool, drawable, TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
GimpContainer *container;
|
||||
|
||||
filter = filter_new (tg_tool, drawable, FALSE);
|
||||
|
||||
container = gimp_viewable_get_children (GIMP_VIEWABLE (drawable));
|
||||
|
||||
gimp_container_foreach (container,
|
||||
(GFunc) gimp_transform_grid_tool_add_filter,
|
||||
tg_tool);
|
||||
}
|
||||
|
||||
filter->clip_drawable = drawable;
|
||||
|
||||
g_hash_table_insert (tg_tool->filters, drawable, filter);
|
||||
|
||||
if (GIMP_IS_LAYER (drawable))
|
||||
{
|
||||
GimpLayerMask *mask = gimp_layer_get_mask (GIMP_LAYER (drawable));
|
||||
|
||||
if (mask)
|
||||
{
|
||||
Filter *mask_filter;
|
||||
|
||||
gimp_transform_grid_tool_add_filter (GIMP_DRAWABLE (mask), tg_tool);
|
||||
|
||||
mask_filter = g_hash_table_lookup (tg_tool->filters, mask);
|
||||
|
||||
mask_filter->clip_drawable = drawable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_transform_grid_tool_remove_filter (GimpDrawable *drawable,
|
||||
GimpTransformGridTool *tg_tool)
|
||||
{
|
||||
Filter *filter = g_hash_table_lookup (tg_tool->filters, drawable);
|
||||
|
||||
if (GIMP_IS_LAYER (drawable))
|
||||
{
|
||||
GimpLayerMask *mask = gimp_layer_get_mask (GIMP_LAYER (drawable));
|
||||
|
||||
if (mask)
|
||||
gimp_transform_grid_tool_remove_filter (GIMP_DRAWABLE (mask), tg_tool);
|
||||
}
|
||||
|
||||
if (! filter->filter)
|
||||
{
|
||||
GimpContainer *container;
|
||||
|
||||
container = gimp_viewable_get_children (GIMP_VIEWABLE (drawable));
|
||||
|
||||
gimp_container_foreach (container,
|
||||
(GFunc) gimp_transform_grid_tool_remove_filter,
|
||||
tg_tool);
|
||||
}
|
||||
|
||||
g_hash_table_remove (tg_tool->filters, drawable);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_transform_grid_tool_effective_mode_changed (GimpLayer *layer,
|
||||
GimpTransformGridTool *tg_tool)
|
||||
{
|
||||
Filter *filter = g_hash_table_lookup (tg_tool->filters, layer);
|
||||
GimpLayerMode mode;
|
||||
gboolean old_pass_through;
|
||||
gboolean new_pass_through;
|
||||
|
||||
gimp_layer_get_effective_mode (layer, &mode, NULL, NULL, NULL);
|
||||
|
||||
old_pass_through = ! filter->filter;
|
||||
new_pass_through = mode == GIMP_LAYER_MODE_PASS_THROUGH;
|
||||
|
||||
if (old_pass_through != new_pass_through)
|
||||
{
|
||||
gimp_transform_grid_tool_remove_filter (GIMP_DRAWABLE (layer), tg_tool);
|
||||
gimp_transform_grid_tool_add_filter (GIMP_DRAWABLE (layer), tg_tool);
|
||||
|
||||
gimp_transform_grid_tool_update_preview (tg_tool);
|
||||
}
|
||||
}
|
||||
|
||||
static Filter *
|
||||
filter_new (GimpTransformGridTool *tg_tool,
|
||||
GimpDrawable *drawable,
|
||||
gboolean add_filter)
|
||||
{
|
||||
Filter *filter = g_slice_new0 (Filter);
|
||||
GeglNode *node;
|
||||
GeglNode *input_node;
|
||||
GeglNode *output_node;
|
||||
|
||||
filter->tg_tool = tg_tool;
|
||||
filter->drawable = drawable;
|
||||
|
||||
if (add_filter)
|
||||
{
|
||||
node = gegl_node_new ();
|
||||
|
||||
input_node = gegl_node_get_input_proxy (node, "input");
|
||||
output_node = gegl_node_get_input_proxy (node, "output");
|
||||
|
||||
filter->transform_node = gegl_node_new_child (
|
||||
node,
|
||||
"operation", "gegl:transform",
|
||||
"near-z", GIMP_TRANSFORM_NEAR_Z,
|
||||
"sampler", GEGL_SAMPLER_NEAREST,
|
||||
NULL);
|
||||
|
||||
filter->crop_node = gegl_node_new_child (
|
||||
node,
|
||||
"operation", "gegl:crop",
|
||||
NULL);
|
||||
|
||||
gegl_node_link_many (input_node,
|
||||
filter->transform_node,
|
||||
filter->crop_node,
|
||||
output_node,
|
||||
NULL);
|
||||
|
||||
gimp_gegl_node_set_underlying_operation (node, filter->transform_node);
|
||||
|
||||
filter->filter = gimp_drawable_filter_new (
|
||||
drawable,
|
||||
GIMP_TRANSFORM_TOOL_GET_CLASS (tg_tool)->undo_desc,
|
||||
node,
|
||||
gimp_tool_get_icon_name (GIMP_TOOL (tg_tool)));
|
||||
|
||||
gimp_drawable_filter_set_clip (filter->filter, FALSE);
|
||||
gimp_drawable_filter_set_override_constraints (filter->filter, TRUE);
|
||||
|
||||
g_signal_connect (
|
||||
filter->filter, "flush",
|
||||
G_CALLBACK (gimp_transform_grid_tool_filter_flush),
|
||||
tg_tool);
|
||||
|
||||
g_object_unref (node);
|
||||
}
|
||||
|
||||
if (GIMP_IS_GROUP_LAYER (drawable))
|
||||
{
|
||||
g_signal_connect (
|
||||
drawable, "effective-mode-changed",
|
||||
G_CALLBACK (gimp_transform_grid_tool_effective_mode_changed),
|
||||
tg_tool);
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
static void
|
||||
filter_free (Filter *filter)
|
||||
{
|
||||
if (filter->filter)
|
||||
{
|
||||
gimp_drawable_filter_abort (filter->filter);
|
||||
|
||||
g_object_unref (filter->filter);
|
||||
}
|
||||
|
||||
if (GIMP_IS_GROUP_LAYER (filter->drawable))
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
filter->drawable,
|
||||
gimp_transform_grid_tool_effective_mode_changed,
|
||||
filter->tg_tool);
|
||||
}
|
||||
|
||||
g_slice_free (Filter, filter);
|
||||
}
|
||||
|
||||
static UndoInfo *
|
||||
undo_info_new (void)
|
||||
{
|
||||
|
|
|
@ -45,28 +45,29 @@ typedef struct _GimpTransformGridToolClass GimpTransformGridToolClass;
|
|||
|
||||
struct _GimpTransformGridTool
|
||||
{
|
||||
GimpTransformTool parent_instance;
|
||||
GimpTransformTool parent_instance;
|
||||
|
||||
TransInfo init_trans_info; /* initial transformation info */
|
||||
TransInfo trans_infos[2]; /* forward/backward transformation info */
|
||||
gdouble *trans_info; /* current transformation info */
|
||||
GList *undo_list; /* list of all states,
|
||||
head is current == prev_trans_info,
|
||||
tail is original == old_trans_info */
|
||||
GList *redo_list; /* list of all undone states,
|
||||
NULL when nothing undone */
|
||||
TransInfo init_trans_info; /* initial transformation info */
|
||||
TransInfo trans_infos[2]; /* forward/backward transformation info */
|
||||
gdouble *trans_info; /* current transformation info */
|
||||
GList *undo_list; /* list of all states,
|
||||
head is current == prev_trans_info,
|
||||
tail is original == old_trans_info */
|
||||
GList *redo_list; /* list of all undone states,
|
||||
NULL when nothing undone */
|
||||
|
||||
GimpObject *hidden_object; /* the object that was hidden during
|
||||
the transform */
|
||||
GimpObject *hidden_object; /* the object that was hidden during
|
||||
the transform */
|
||||
|
||||
GimpToolWidget *widget;
|
||||
GimpToolWidget *grab_widget;
|
||||
GimpCanvasItem *preview;
|
||||
GimpCanvasItem *boundary_in;
|
||||
GimpCanvasItem *boundary_out;
|
||||
GPtrArray *strokes;
|
||||
GimpToolWidget *widget;
|
||||
GimpToolWidget *grab_widget;
|
||||
GHashTable *filters;
|
||||
GimpCanvasItem *preview;
|
||||
GimpCanvasItem *boundary_in;
|
||||
GimpCanvasItem *boundary_out;
|
||||
GPtrArray *strokes;
|
||||
|
||||
GimpToolGui *gui;
|
||||
GimpToolGui *gui;
|
||||
};
|
||||
|
||||
struct _GimpTransformGridToolClass
|
||||
|
|
Loading…
Reference in New Issue