app: add gimp_symmetry_get_transform()

Add a GimpSymmetry::get_transform() virtual function, and a
corresponding gimp_symmetry_get_transform() function, which return
the brush transform corresponding to a given symmetry stroke in
terms of the rotation angle and reflection flag (in contrast to
gimp_symmetry_get_operation() which returns the same transforation
in terms of a GeglNode).  This would allow us to simplify, fix, and
improve the painting-code perofmrnace in the next commits.

Implement GimpSymmetry::get_transform() in its various subclasses.

(cherry picked from commit e0f2a6f1be)
This commit is contained in:
Ell 2019-05-26 14:14:26 -04:00
parent 80e426b65b
commit 85340f4b30
5 changed files with 122 additions and 15 deletions

View file

@ -85,6 +85,10 @@ 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,
gboolean *reflect);
static void gimp_mandala_image_size_changed_cb (GimpImage *image,
gint previous_origin_x,
gint previous_origin_y,
@ -113,6 +117,7 @@ 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;
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_CENTER_X,
@ -552,6 +557,20 @@ gimp_mandala_get_operation (GimpSymmetry *sym,
return op;
}
static void
gimp_mandala_get_transform (GimpSymmetry *sym,
gint stroke,
gdouble *angle,
gboolean *reflect)
{
GimpMandala *mandala = GIMP_MANDALA (sym);
if (mandala->disable_transformation)
return;
*angle = 360.0 * stroke / mandala->size;
}
static void
gimp_mandala_image_size_changed_cb (GimpImage *image,
gint previous_origin_x,

View file

@ -78,6 +78,10 @@ static GeglNode * gimp_mirror_get_operation (GimpSymmetry *mirr
gint stroke,
gint paint_width,
gint paint_height);
static void gimp_mirror_get_transform (GimpSymmetry *mirror,
gint stroke,
gdouble *angle,
gboolean *reflect);
static void gimp_mirror_reset (GimpMirror *mirror);
static void gimp_mirror_add_guide (GimpMirror *mirror,
GimpOrientationType orientation);
@ -123,6 +127,7 @@ 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;
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_HORIZONTAL_SYMMETRY,
@ -439,6 +444,50 @@ gimp_mirror_get_operation (GimpSymmetry *sym,
return op;
}
static void
gimp_mirror_get_transform (GimpSymmetry *sym,
gint stroke,
gdouble *angle,
gboolean *reflect)
{
GimpMirror *mirror = GIMP_MIRROR (sym);
if (mirror->disable_transformation)
return;
if (! mirror->horizontal_mirror && stroke >= 1)
stroke++;
if (! mirror->vertical_mirror && stroke >= 2)
stroke++;
switch (stroke)
{
/* original */
case 0:
break;
/* horizontal */
case 1:
*angle = 180.0;
*reflect = TRUE;
break;
/* vertical */
case 2:
*reflect = TRUE;
break;
/* central */
case 3:
*angle = 180.0;
break;
default:
g_return_if_reached ();
}
}
static void
gimp_mirror_reset (GimpMirror *mirror)
{

View file

@ -70,10 +70,6 @@ static void gimp_tiling_get_property (GObject *object,
static void gimp_tiling_update_strokes (GimpSymmetry *tiling,
GimpDrawable *drawable,
GimpCoords *origin);
static GeglNode * gimp_tiling_get_operation (GimpSymmetry *tiling,
gint stroke,
gint paint_width,
gint paint_height);
static void gimp_tiling_image_size_changed_cb (GimpImage *image,
gint previous_origin_x,
gint previous_origin_y,
@ -101,7 +97,6 @@ gimp_tiling_class_init (GimpTilingClass *klass)
symmetry_class->label = _("Tiling");
symmetry_class->update_strokes = gimp_tiling_update_strokes;
symmetry_class->get_operation = gimp_tiling_get_operation;
GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_INTERVAL_X,
"interval-x",
@ -431,16 +426,6 @@ gimp_tiling_update_strokes (GimpSymmetry *sym,
g_signal_emit_by_name (sym, "strokes-updated", sym->image);
}
static GeglNode *
gimp_tiling_get_operation (GimpSymmetry *sym,
gint stroke,
gint paint_width,
gint paint_height)
{
/* No buffer transformation happens for tiling. */
return NULL;
}
static void
gimp_tiling_image_size_changed_cb (GimpImage *image,
gint previous_origin_x,

View file

@ -75,6 +75,10 @@ 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,
gboolean *reflect);
static gboolean gimp_symmetry_real_update_version (GimpSymmetry *sym);
@ -134,6 +138,7 @@ 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;
@ -246,6 +251,16 @@ gimp_symmetry_real_get_op (GimpSymmetry *sym,
return NULL;
}
static void
gimp_symmetry_real_get_transform (GimpSymmetry *sym,
gint stroke,
gdouble *angle,
gboolean *reflect)
{
/* The basic symmetry does nothing, since no transformation of the
* brush painting happen. */
}
static gboolean
gimp_symmetry_real_update_version (GimpSymmetry *symmetry)
{
@ -419,6 +434,37 @@ gimp_symmetry_get_operation (GimpSymmetry *sym,
paint_height);
}
/**
* gimp_symmetry_get_transform:
* @sym: the #GimpSymmetry
* @stroke: the stroke number
* @angle: output pointer to the transformation rotation angle,
* 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.
**/
void
gimp_symmetry_get_transform (GimpSymmetry *sym,
gint stroke,
gdouble *angle,
gboolean *reflect)
{
g_return_if_fail (GIMP_IS_SYMMETRY (sym));
g_return_if_fail (angle != NULL);
g_return_if_fail (reflect != NULL);
*angle = 0.0;
*reflect = FALSE;
GIMP_SYMMETRY_GET_CLASS (sym)->get_transform (sym,
stroke,
angle,
reflect);
}
/*
* gimp_symmetry_parasite_name:
* @type: the #GimpSymmetry's #GType

View file

@ -67,6 +67,10 @@ struct _GimpSymmetryClass
gint stroke,
gint paint_width,
gint paint_height);
void (* get_transform) (GimpSymmetry *symmetry,
gint stroke,
gdouble *angle,
gboolean *reflect);
void (* active_changed) (GimpSymmetry *symmetry);
gboolean (* update_version) (GimpSymmetry *symmetry);
@ -90,6 +94,10 @@ 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,
gboolean *reflect);
gchar * gimp_symmetry_parasite_name (GType type);
GimpParasite * gimp_symmetry_to_parasite (const GimpSymmetry *symmetry);