app: implement gimp_symmetry_get_operation() in terms of gimp_symmetry_get_matrix()

Remove the GimpSymmetry::get_operation() virtual function, and
instead implement gimp_symmetry_get_operation() by returning an
appropriate gegl:transform node based on the matrix returned by
gimp_symmetry_get_matrix().  The returned node is owned by the
caller; since we no longer use the node's identity for caching
trnasformed brushes, we no longer cache the transformation nodes.

Remove the function's paint_width and paint_height parameters, and
instead return a transformation that should be applied at the
center of the brush.  This simplifies the application of the
transformation in the Clone and Heal tools, as per the next commit.

Remove the implementation of GimpSymmetry::get_operation() from all
its subclasses, which should now only implement
GimpSymmetry::get_transform().
This commit is contained in:
Ell 2019-05-29 04:46:21 -04:00
parent 3895dc07a9
commit 60a3965020
6 changed files with 43 additions and 241 deletions

View File

@ -81,10 +81,6 @@ static void gimp_mandala_guide_position_cb (GObject *object,
static void gimp_mandala_update_strokes (GimpSymmetry *mandala,
GimpDrawable *drawable,
GimpCoords *origin);
static GeglNode * gimp_mandala_get_operation (GimpSymmetry *mandala,
gint stroke,
gint paint_width,
gint paint_height);
static void gimp_mandala_get_transform (GimpSymmetry *mandala,
gint stroke,
gdouble *angle,
@ -116,7 +112,6 @@ gimp_mandala_class_init (GimpMandalaClass *klass)
symmetry_class->label = _("Mandala");
symmetry_class->update_strokes = gimp_mandala_update_strokes;
symmetry_class->get_operation = gimp_mandala_get_operation;
symmetry_class->get_transform = gimp_mandala_get_transform;
symmetry_class->active_changed = gimp_mandala_active_changed;
@ -184,20 +179,6 @@ gimp_mandala_finalize (GObject *object)
g_clear_object (&mandala->horizontal_guide);
g_clear_object (&mandala->vertical_guide);
if (mandala->ops)
{
GList *iter;
for (iter = mandala->ops; iter; iter = g_list_next (iter))
{
if (iter->data)
g_object_unref (G_OBJECT (iter->data));
}
g_list_free (mandala->ops);
mandala->ops = NULL;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -495,68 +476,6 @@ gimp_mandala_update_strokes (GimpSymmetry *sym,
g_signal_emit_by_name (sym, "strokes-updated", sym->image);
}
static GeglNode *
gimp_mandala_get_operation (GimpSymmetry *sym,
gint stroke,
gint paint_width,
gint paint_height)
{
GimpMandala *mandala = GIMP_MANDALA (sym);
GeglNode *op = NULL;
gint i;
if (! mandala->disable_transformation &&
stroke != 0 &&
paint_width != 0 &&
paint_height != 0)
{
if (mandala->size != mandala->cached_size ||
mandala->cached_paint_width != paint_width ||
mandala->cached_paint_height != paint_height)
{
GList *iter;
if (mandala->ops)
{
for (iter = mandala->ops; iter; iter = g_list_next (iter))
{
if (iter->data)
g_object_unref (G_OBJECT (iter->data));
}
g_list_free (mandala->ops);
mandala->ops = NULL;
}
mandala->ops = g_list_prepend (mandala->ops, NULL);
for (i = 1; i < mandala->size; i++)
{
op = gegl_node_new_child (NULL,
"operation", "gegl:rotate",
"origin-x",
(gdouble) paint_width / 2.0,
"origin-y",
(gdouble) paint_height / 2.0,
"degrees",
i * 360.0 / (gdouble) mandala->size,
NULL);
mandala->ops = g_list_prepend (mandala->ops, op);
}
mandala->ops = g_list_reverse (mandala->ops);
mandala->cached_size = mandala->size;
mandala->cached_paint_width = paint_width;
mandala->cached_paint_height = paint_height;
}
op = g_list_nth_data (mandala->ops, stroke);
}
return op;
}
static void
gimp_mandala_get_transform (GimpSymmetry *sym,
gint stroke,

View File

@ -46,11 +46,6 @@ struct _GimpMandala
GimpGuide *horizontal_guide;
GimpGuide *vertical_guide;
GList *ops;
gint cached_size;
gint cached_paint_width;
gint cached_paint_height;
};
struct _GimpMandalaClass

View File

@ -71,13 +71,6 @@ static void gimp_mirror_get_property (GObject *obje
static void gimp_mirror_update_strokes (GimpSymmetry *mirror,
GimpDrawable *drawable,
GimpCoords *origin);
static void gimp_mirror_prepare_operations (GimpMirror *mirror,
gint paint_width,
gint paint_height);
static GeglNode * gimp_mirror_get_operation (GimpSymmetry *mirror,
gint stroke,
gint paint_width,
gint paint_height);
static void gimp_mirror_get_transform (GimpSymmetry *mirror,
gint stroke,
gdouble *angle,
@ -126,7 +119,6 @@ gimp_mirror_class_init (GimpMirrorClass *klass)
symmetry_class->label = _("Mirror");
symmetry_class->update_strokes = gimp_mirror_update_strokes;
symmetry_class->get_operation = gimp_mirror_get_operation;
symmetry_class->get_transform = gimp_mirror_get_transform;
symmetry_class->active_changed = gimp_mirror_active_changed;
@ -210,10 +202,6 @@ gimp_mirror_finalize (GObject *object)
g_clear_object (&mirror->horizontal_guide);
g_clear_object (&mirror->vertical_guide);
g_clear_object (&mirror->horizontal_op);
g_clear_object (&mirror->vertical_op);
g_clear_object (&mirror->central_op);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -369,81 +357,6 @@ gimp_mirror_update_strokes (GimpSymmetry *sym,
g_signal_emit_by_name (sym, "strokes-updated", sym->image);
}
static void
gimp_mirror_prepare_operations (GimpMirror *mirror,
gint paint_width,
gint paint_height)
{
if (paint_width == mirror->last_paint_width &&
paint_height == mirror->last_paint_height)
return;
mirror->last_paint_width = paint_width;
mirror->last_paint_height = paint_height;
if (mirror->horizontal_op)
g_object_unref (mirror->horizontal_op);
mirror->horizontal_op = gegl_node_new_child (NULL,
"operation", "gegl:reflect",
"origin-x", 0.0,
"origin-y", paint_height / 2.0,
"x", 1.0,
"y", 0.0,
NULL);
if (mirror->vertical_op)
g_object_unref (mirror->vertical_op);
mirror->vertical_op = gegl_node_new_child (NULL,
"operation", "gegl:reflect",
"origin-x", paint_width / 2.0,
"origin-y", 0.0,
"x", 0.0,
"y", 1.0,
NULL);
if (mirror->central_op)
g_object_unref (mirror->central_op);
mirror->central_op = gegl_node_new_child (NULL,
"operation", "gegl:rotate",
"origin-x", paint_width / 2.0,
"origin-y", paint_height / 2.0,
"degrees", 180.0,
NULL);
}
static GeglNode *
gimp_mirror_get_operation (GimpSymmetry *sym,
gint stroke,
gint paint_width,
gint paint_height)
{
GimpMirror *mirror = GIMP_MIRROR (sym);
GeglNode *op;
g_return_val_if_fail (stroke >= 0 &&
stroke < g_list_length (sym->strokes), NULL);
gimp_mirror_prepare_operations (mirror, paint_width, paint_height);
if (mirror->disable_transformation || stroke == 0 ||
paint_width == 0 || paint_height == 0)
op = NULL;
else if (stroke == 1 && mirror->horizontal_mirror)
op = g_object_ref (mirror->horizontal_op);
else if ((stroke == 2 && mirror->horizontal_mirror &&
mirror->vertical_mirror) ||
(stroke == 1 && mirror->vertical_mirror &&
! mirror->horizontal_mirror))
op = g_object_ref (mirror->vertical_op);
else
op = g_object_ref (mirror->central_op);
return op;
}
static void
gimp_mirror_get_transform (GimpSymmetry *sym,
gint stroke,

View File

@ -48,13 +48,6 @@ struct _GimpMirror
gdouble mirror_position_x;
GimpGuide *horizontal_guide;
GimpGuide *vertical_guide;
/* Cached data */
gint last_paint_width;
gint last_paint_height;
GeglNode *horizontal_op;
GeglNode *vertical_op;
GeglNode *central_op;
};
struct _GimpMirrorClass

View File

@ -31,6 +31,8 @@
#include "core-types.h"
#include "gegl/gimp-gegl-nodes.h"
#include "gimpdrawable.h"
#include "gimpimage.h"
#include "gimpimage-symmetry.h"
@ -72,10 +74,6 @@ static void gimp_symmetry_get_property (GObject *object,
static void gimp_symmetry_real_update_strokes (GimpSymmetry *sym,
GimpDrawable *drawable,
GimpCoords *origin);
static GeglNode * gimp_symmetry_real_get_op (GimpSymmetry *sym,
gint stroke,
gint paint_width,
gint paint_height);
static void gimp_symmetry_real_get_transform (GimpSymmetry *sym,
gint stroke,
gdouble *angle,
@ -138,7 +136,6 @@ gimp_symmetry_class_init (GimpSymmetryClass *klass)
klass->label = _("None");
klass->update_strokes = gimp_symmetry_real_update_strokes;
klass->get_operation = gimp_symmetry_real_get_op;
klass->get_transform = gimp_symmetry_real_get_transform;
klass->active_changed = NULL;
klass->update_version = gimp_symmetry_real_update_version;
@ -241,17 +238,6 @@ gimp_symmetry_real_update_strokes (GimpSymmetry *sym,
g_memdup (origin, sizeof (GimpCoords)));
}
static GeglNode *
gimp_symmetry_real_get_op (GimpSymmetry *sym,
gint stroke,
gint paint_width,
gint paint_height)
{
/* The basic symmetry just returns NULL, since no transformation of the
* brush painting happen. */
return NULL;
}
static void
gimp_symmetry_real_get_transform (GimpSymmetry *sym,
gint stroke,
@ -411,30 +397,6 @@ gimp_symmetry_get_coords (GimpSymmetry *sym,
return g_list_nth_data (sym->strokes, stroke);
}
/**
* gimp_symmetry_get_operation:
* @sym: the #GimpSymmetry
* @stroke: the stroke number
* @paint_width: the width of the painting area
* @paint_height: the height of the painting area
*
* Returns: the operation to apply to the paint buffer for stroke number @stroke.
* NULL means to copy the original stroke as-is.
**/
GeglNode *
gimp_symmetry_get_operation (GimpSymmetry *sym,
gint stroke,
gint paint_width,
gint paint_height)
{
g_return_val_if_fail (GIMP_IS_SYMMETRY (sym), NULL);
return GIMP_SYMMETRY_GET_CLASS (sym)->get_operation (sym,
stroke,
paint_width,
paint_height);
}
/**
* gimp_symmetry_get_transform:
* @sym: the #GimpSymmetry
@ -443,9 +405,9 @@ gimp_symmetry_get_operation (GimpSymmetry *sym,
* in degrees (ccw)
* @reflect: output pointer to the transformation reflection flag
*
* Returns the transformation to apply to the paint buffer for stroke
* number @stroke. The transformation is comprised of rotation around the
* center, possibly followed by horizontal reflection around the center.
* Returns: the transformation to apply to the paint content for stroke
* number @stroke. The transformation is comprised of rotation, possibly
* followed by horizontal reflection, around the stroke coordinates.
**/
void
gimp_symmetry_get_transform (GimpSymmetry *sym,
@ -472,7 +434,7 @@ gimp_symmetry_get_transform (GimpSymmetry *sym,
* @stroke: the stroke number
* @matrix: output pointer to the transformation matrix
*
* Returns the transformation matrix to apply to the paint buffer for stroke
* Returns: the transformation matrix to apply to the paint content for stroke
* number @stroke.
**/
void
@ -494,6 +456,32 @@ gimp_symmetry_get_matrix (GimpSymmetry *sym,
gimp_matrix3_scale (matrix, -1.0, 1.0);
}
/**
* gimp_symmetry_get_operation:
* @sym: the #GimpSymmetry
* @stroke: the stroke number
*
* Returns: the transformation operation to apply to the paint content for
* stroke number @stroke, or NULL for the identity transformation.
*
* The returned #GeglNode should be freed by the caller.
**/
GeglNode *
gimp_symmetry_get_operation (GimpSymmetry *sym,
gint stroke)
{
GimpMatrix3 matrix;
g_return_val_if_fail (GIMP_IS_SYMMETRY (sym), NULL);
gimp_symmetry_get_matrix (sym, stroke, &matrix);
if (gimp_matrix3_is_identity (&matrix))
return NULL;
return gimp_gegl_create_transform_node (&matrix);
}
/*
* gimp_symmetry_parasite_name:
* @type: the #GimpSymmetry's #GType

View File

@ -63,10 +63,6 @@ struct _GimpSymmetryClass
void (* update_strokes) (GimpSymmetry *symmetry,
GimpDrawable *drawable,
GimpCoords *origin);
GeglNode * (* get_operation) (GimpSymmetry *symmetry,
gint stroke,
gint paint_width,
gint paint_height);
void (* get_transform) (GimpSymmetry *symmetry,
gint stroke,
gdouble *angle,
@ -90,10 +86,6 @@ GimpCoords * gimp_symmetry_get_origin (GimpSymmetry *symmetry);
gint gimp_symmetry_get_size (GimpSymmetry *symmetry);
GimpCoords * gimp_symmetry_get_coords (GimpSymmetry *symmetry,
gint stroke);
GeglNode * gimp_symmetry_get_operation (GimpSymmetry *symmetry,
gint stroke,
gint paint_width,
gint paint_height);
void gimp_symmetry_get_transform (GimpSymmetry *symmetry,
gint stroke,
gdouble *angle,
@ -101,6 +93,8 @@ void gimp_symmetry_get_transform (GimpSymmetry *symmetry,
void gimp_symmetry_get_matrix (GimpSymmetry *symmetry,
gint stroke,
GimpMatrix3 *matrix);
GeglNode * gimp_symmetry_get_operation (GimpSymmetry *symmetry,
gint stroke);
gchar * gimp_symmetry_parasite_name (GType type);
GimpParasite * gimp_symmetry_to_parasite (const GimpSymmetry *symmetry);