1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
16  */
17 
18 #include "config.h"
19 
20 #include <gdk-pixbuf/gdk-pixbuf.h>
21 #include <gegl.h>
22 
23 #include "libgimpmath/gimpmath.h"
24 #include "libgimpconfig/gimpconfig.h"
25 
26 #include "core-types.h"
27 
28 #include "gimpcurve.h"
29 #include "gimpdynamics.h"
30 #include "gimpdynamics-load.h"
31 #include "gimpdynamics-save.h"
32 #include "gimpdynamicsoutput.h"
33 
34 #include "gimp-intl.h"
35 
36 
37 #define DEFAULT_NAME "Nameless dynamics"
38 
39 enum
40 {
41   PROP_0,
42 
43   PROP_NAME,
44 
45   PROP_OPACITY_OUTPUT,
46   PROP_SIZE_OUTPUT,
47   PROP_ANGLE_OUTPUT,
48   PROP_COLOR_OUTPUT,
49   PROP_FORCE_OUTPUT,
50   PROP_HARDNESS_OUTPUT,
51   PROP_ASPECT_RATIO_OUTPUT,
52   PROP_SPACING_OUTPUT,
53   PROP_RATE_OUTPUT,
54   PROP_FLOW_OUTPUT,
55   PROP_JITTER_OUTPUT
56 };
57 
58 
59 typedef struct _GimpDynamicsPrivate GimpDynamicsPrivate;
60 
61 struct _GimpDynamicsPrivate
62 {
63   GimpDynamicsOutput *opacity_output;
64   GimpDynamicsOutput *hardness_output;
65   GimpDynamicsOutput *force_output;
66   GimpDynamicsOutput *rate_output;
67   GimpDynamicsOutput *flow_output;
68   GimpDynamicsOutput *size_output;
69   GimpDynamicsOutput *aspect_ratio_output;
70   GimpDynamicsOutput *color_output;
71   GimpDynamicsOutput *angle_output;
72   GimpDynamicsOutput *jitter_output;
73   GimpDynamicsOutput *spacing_output;
74 };
75 
76 #define GET_PRIVATE(output) \
77         ((GimpDynamicsPrivate *) gimp_dynamics_get_instance_private ((GimpDynamics *) (output)))
78 
79 
80 static void          gimp_dynamics_finalize      (GObject      *object);
81 static void          gimp_dynamics_set_property  (GObject      *object,
82                                                   guint         property_id,
83                                                   const GValue *value,
84                                                   GParamSpec   *pspec);
85 static void          gimp_dynamics_get_property  (GObject      *object,
86                                                   guint         property_id,
87                                                   GValue       *value,
88                                                   GParamSpec   *pspec);
89 static void
90        gimp_dynamics_dispatch_properties_changed (GObject      *object,
91                                                   guint         n_pspecs,
92                                                   GParamSpec  **pspecs);
93 
94 static const gchar * gimp_dynamics_get_extension (GimpData     *data);
95 static void          gimp_dynamics_copy          (GimpData     *data,
96                                                   GimpData     *src_data);
97 
98 static GimpDynamicsOutput *
99                      gimp_dynamics_create_output (GimpDynamics           *dynamics,
100                                                   const gchar            *name,
101                                                   GimpDynamicsOutputType  type);
102 static void          gimp_dynamics_output_notify (GObject          *output,
103                                                   const GParamSpec *pspec,
104                                                   GimpDynamics     *dynamics);
105 
106 
G_DEFINE_TYPE_WITH_PRIVATE(GimpDynamics,gimp_dynamics,GIMP_TYPE_DATA)107 G_DEFINE_TYPE_WITH_PRIVATE (GimpDynamics, gimp_dynamics, GIMP_TYPE_DATA)
108 
109 #define parent_class gimp_dynamics_parent_class
110 
111 
112 static void
113 gimp_dynamics_class_init (GimpDynamicsClass *klass)
114 {
115   GObjectClass      *object_class   = G_OBJECT_CLASS (klass);
116   GimpDataClass     *data_class     = GIMP_DATA_CLASS (klass);
117   GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
118 
119   object_class->finalize                    = gimp_dynamics_finalize;
120   object_class->set_property                = gimp_dynamics_set_property;
121   object_class->get_property                = gimp_dynamics_get_property;
122   object_class->dispatch_properties_changed = gimp_dynamics_dispatch_properties_changed;
123 
124   viewable_class->default_icon_name         = "gimp-dynamics";
125 
126   data_class->save                          = gimp_dynamics_save;
127   data_class->get_extension                 = gimp_dynamics_get_extension;
128   data_class->copy                          = gimp_dynamics_copy;
129 
130   GIMP_CONFIG_PROP_STRING (object_class, PROP_NAME,
131                            "name",
132                            NULL, NULL,
133                            DEFAULT_NAME,
134                            GIMP_PARAM_STATIC_STRINGS);
135 
136   GIMP_CONFIG_PROP_OBJECT (object_class, PROP_OPACITY_OUTPUT,
137                            "opacity-output",
138                            NULL, NULL,
139                            GIMP_TYPE_DYNAMICS_OUTPUT,
140                            GIMP_CONFIG_PARAM_AGGREGATE);
141 
142   GIMP_CONFIG_PROP_OBJECT (object_class, PROP_FORCE_OUTPUT,
143                            "force-output",
144                            NULL, NULL,
145                            GIMP_TYPE_DYNAMICS_OUTPUT,
146                            GIMP_CONFIG_PARAM_AGGREGATE);
147 
148   GIMP_CONFIG_PROP_OBJECT (object_class, PROP_HARDNESS_OUTPUT,
149                            "hardness-output",
150                            NULL, NULL,
151                            GIMP_TYPE_DYNAMICS_OUTPUT,
152                            GIMP_CONFIG_PARAM_AGGREGATE);
153 
154   GIMP_CONFIG_PROP_OBJECT (object_class, PROP_RATE_OUTPUT,
155                            "rate-output",
156                            NULL, NULL,
157                            GIMP_TYPE_DYNAMICS_OUTPUT,
158                            GIMP_CONFIG_PARAM_AGGREGATE);
159 
160   GIMP_CONFIG_PROP_OBJECT (object_class, PROP_FLOW_OUTPUT,
161                            "flow-output",
162                            NULL, NULL,
163                            GIMP_TYPE_DYNAMICS_OUTPUT,
164                            GIMP_CONFIG_PARAM_AGGREGATE);
165 
166   GIMP_CONFIG_PROP_OBJECT (object_class, PROP_SIZE_OUTPUT,
167                            "size-output",
168                            NULL, NULL,
169                            GIMP_TYPE_DYNAMICS_OUTPUT,
170                            GIMP_CONFIG_PARAM_AGGREGATE);
171 
172   GIMP_CONFIG_PROP_OBJECT (object_class, PROP_ASPECT_RATIO_OUTPUT,
173                            "aspect-ratio-output",
174                            NULL, NULL,
175                            GIMP_TYPE_DYNAMICS_OUTPUT,
176                            GIMP_CONFIG_PARAM_AGGREGATE);
177 
178   GIMP_CONFIG_PROP_OBJECT (object_class, PROP_COLOR_OUTPUT,
179                            "color-output",
180                            NULL, NULL,
181                            GIMP_TYPE_DYNAMICS_OUTPUT,
182                            GIMP_CONFIG_PARAM_AGGREGATE);
183 
184   GIMP_CONFIG_PROP_OBJECT (object_class, PROP_ANGLE_OUTPUT,
185                            "angle-output",
186                            NULL, NULL,
187                            GIMP_TYPE_DYNAMICS_OUTPUT,
188                            GIMP_CONFIG_PARAM_AGGREGATE);
189 
190   GIMP_CONFIG_PROP_OBJECT (object_class, PROP_JITTER_OUTPUT,
191                            "jitter-output",
192                            NULL, NULL,
193                            GIMP_TYPE_DYNAMICS_OUTPUT,
194                            GIMP_CONFIG_PARAM_AGGREGATE);
195 
196   GIMP_CONFIG_PROP_OBJECT (object_class, PROP_SPACING_OUTPUT,
197                            "spacing-output",
198                            NULL, NULL,
199                            GIMP_TYPE_DYNAMICS_OUTPUT,
200                            GIMP_CONFIG_PARAM_AGGREGATE);
201 }
202 
203 static void
gimp_dynamics_init(GimpDynamics * dynamics)204 gimp_dynamics_init (GimpDynamics *dynamics)
205 {
206   GimpDynamicsPrivate *private = GET_PRIVATE (dynamics);
207 
208   private->opacity_output =
209     gimp_dynamics_create_output (dynamics,
210                                  "opacity-output",
211                                  GIMP_DYNAMICS_OUTPUT_OPACITY);
212 
213   private->force_output =
214     gimp_dynamics_create_output (dynamics,
215                                  "force-output",
216                                  GIMP_DYNAMICS_OUTPUT_FORCE);
217 
218   private->hardness_output =
219     gimp_dynamics_create_output (dynamics,
220                                  "hardness-output",
221                                  GIMP_DYNAMICS_OUTPUT_HARDNESS);
222 
223   private->rate_output =
224     gimp_dynamics_create_output (dynamics,
225                                  "rate-output",
226                                  GIMP_DYNAMICS_OUTPUT_RATE);
227 
228   private->flow_output =
229     gimp_dynamics_create_output (dynamics,
230                                  "flow-output",
231                                  GIMP_DYNAMICS_OUTPUT_FLOW);
232 
233   private->size_output =
234     gimp_dynamics_create_output (dynamics,
235                                  "size-output",
236                                  GIMP_DYNAMICS_OUTPUT_SIZE);
237 
238   private->aspect_ratio_output =
239     gimp_dynamics_create_output (dynamics,
240                                  "aspect-ratio-output",
241                                  GIMP_DYNAMICS_OUTPUT_ASPECT_RATIO);
242 
243   private->color_output =
244     gimp_dynamics_create_output (dynamics,
245                                  "color-output",
246                                  GIMP_DYNAMICS_OUTPUT_COLOR);
247 
248   private->angle_output =
249     gimp_dynamics_create_output (dynamics,
250                                  "angle-output",
251                                  GIMP_DYNAMICS_OUTPUT_ANGLE);
252 
253   private->jitter_output =
254     gimp_dynamics_create_output (dynamics,
255                                  "jitter-output",
256                                  GIMP_DYNAMICS_OUTPUT_JITTER);
257 
258   private->spacing_output =
259     gimp_dynamics_create_output (dynamics,
260                                  "spacing-output",
261                                  GIMP_DYNAMICS_OUTPUT_SPACING);
262 }
263 
264 static void
gimp_dynamics_finalize(GObject * object)265 gimp_dynamics_finalize (GObject *object)
266 {
267   GimpDynamicsPrivate *private = GET_PRIVATE (object);
268 
269   g_clear_object (&private->opacity_output);
270   g_clear_object (&private->force_output);
271   g_clear_object (&private->hardness_output);
272   g_clear_object (&private->rate_output);
273   g_clear_object (&private->flow_output);
274   g_clear_object (&private->size_output);
275   g_clear_object (&private->aspect_ratio_output);
276   g_clear_object (&private->color_output);
277   g_clear_object (&private->angle_output);
278   g_clear_object (&private->jitter_output);
279   g_clear_object (&private->spacing_output);
280 
281   G_OBJECT_CLASS (parent_class)->finalize (object);
282 }
283 
284 static void
gimp_dynamics_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)285 gimp_dynamics_set_property (GObject      *object,
286                             guint         property_id,
287                             const GValue *value,
288                             GParamSpec   *pspec)
289 {
290   GimpDynamicsPrivate *private     = GET_PRIVATE (object);
291   GimpDynamicsOutput  *src_output  = NULL;
292   GimpDynamicsOutput  *dest_output = NULL;
293 
294   switch (property_id)
295     {
296     case PROP_NAME:
297       gimp_object_set_name (GIMP_OBJECT (object), g_value_get_string (value));
298       break;
299 
300     case PROP_OPACITY_OUTPUT:
301       src_output  = g_value_get_object (value);
302       dest_output = private->opacity_output;
303       break;
304 
305     case PROP_FORCE_OUTPUT:
306       src_output  = g_value_get_object (value);
307       dest_output = private->force_output;
308       break;
309 
310     case PROP_HARDNESS_OUTPUT:
311       src_output  = g_value_get_object (value);
312       dest_output = private->hardness_output;
313       break;
314 
315     case PROP_RATE_OUTPUT:
316       src_output  = g_value_get_object (value);
317       dest_output = private->rate_output;
318       break;
319 
320     case PROP_FLOW_OUTPUT:
321       src_output  = g_value_get_object (value);
322       dest_output = private->flow_output;
323       break;
324 
325     case PROP_SIZE_OUTPUT:
326       src_output  = g_value_get_object (value);
327       dest_output = private->size_output;
328       break;
329 
330     case PROP_ASPECT_RATIO_OUTPUT:
331       src_output  = g_value_get_object (value);
332       dest_output = private->aspect_ratio_output;
333       break;
334 
335     case PROP_COLOR_OUTPUT:
336       src_output  = g_value_get_object (value);
337       dest_output = private->color_output;
338       break;
339 
340     case PROP_ANGLE_OUTPUT:
341       src_output  = g_value_get_object (value);
342       dest_output = private->angle_output;
343       break;
344 
345     case PROP_JITTER_OUTPUT:
346       src_output  = g_value_get_object (value);
347       dest_output = private->jitter_output;
348       break;
349 
350     case PROP_SPACING_OUTPUT:
351       src_output  = g_value_get_object (value);
352       dest_output = private->spacing_output;
353       break;
354 
355     default:
356       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
357       break;
358     }
359 
360   if (src_output && dest_output)
361     {
362       gimp_config_copy (GIMP_CONFIG (src_output),
363                         GIMP_CONFIG (dest_output),
364                         GIMP_CONFIG_PARAM_SERIALIZE);
365     }
366 }
367 
368 static void
gimp_dynamics_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)369 gimp_dynamics_get_property (GObject    *object,
370                             guint       property_id,
371                             GValue     *value,
372                             GParamSpec *pspec)
373 {
374   GimpDynamicsPrivate *private = GET_PRIVATE (object);
375 
376   switch (property_id)
377     {
378     case PROP_NAME:
379       g_value_set_string (value, gimp_object_get_name (object));
380       break;
381 
382     case PROP_OPACITY_OUTPUT:
383       g_value_set_object (value, private->opacity_output);
384       break;
385 
386     case PROP_FORCE_OUTPUT:
387       g_value_set_object (value, private->force_output);
388       break;
389 
390     case PROP_HARDNESS_OUTPUT:
391       g_value_set_object (value, private->hardness_output);
392       break;
393 
394     case PROP_RATE_OUTPUT:
395       g_value_set_object (value, private->rate_output);
396       break;
397 
398     case PROP_FLOW_OUTPUT:
399       g_value_set_object (value, private->flow_output);
400       break;
401 
402     case PROP_SIZE_OUTPUT:
403       g_value_set_object (value, private->size_output);
404       break;
405 
406     case PROP_ASPECT_RATIO_OUTPUT:
407       g_value_set_object (value, private->aspect_ratio_output);
408       break;
409 
410     case PROP_COLOR_OUTPUT:
411       g_value_set_object (value, private->color_output);
412       break;
413 
414     case PROP_ANGLE_OUTPUT:
415       g_value_set_object (value, private->angle_output);
416       break;
417 
418     case PROP_JITTER_OUTPUT:
419       g_value_set_object (value, private->jitter_output);
420       break;
421 
422     case PROP_SPACING_OUTPUT:
423       g_value_set_object (value, private->spacing_output);
424       break;
425 
426     default:
427       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
428       break;
429     }
430 }
431 
432 static void
gimp_dynamics_dispatch_properties_changed(GObject * object,guint n_pspecs,GParamSpec ** pspecs)433 gimp_dynamics_dispatch_properties_changed (GObject     *object,
434                                            guint        n_pspecs,
435                                            GParamSpec **pspecs)
436 {
437   gint i;
438 
439   G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object,
440                                                               n_pspecs, pspecs);
441 
442   for (i = 0; i < n_pspecs; i++)
443     {
444       if (pspecs[i]->flags & GIMP_CONFIG_PARAM_SERIALIZE)
445         {
446           gimp_data_dirty (GIMP_DATA (object));
447           break;
448         }
449     }
450 }
451 
452 static const gchar *
gimp_dynamics_get_extension(GimpData * data)453 gimp_dynamics_get_extension (GimpData *data)
454 {
455   return GIMP_DYNAMICS_FILE_EXTENSION;
456 }
457 
458 static void
gimp_dynamics_copy(GimpData * data,GimpData * src_data)459 gimp_dynamics_copy (GimpData *data,
460                     GimpData *src_data)
461 {
462   gimp_data_freeze (data);
463 
464   gimp_config_copy (GIMP_CONFIG (src_data),
465                     GIMP_CONFIG (data), 0);
466 
467   gimp_data_thaw (data);
468 }
469 
470 
471 /*  public functions  */
472 
473 GimpData *
gimp_dynamics_new(GimpContext * context,const gchar * name)474 gimp_dynamics_new (GimpContext *context,
475                    const gchar *name)
476 {
477   g_return_val_if_fail (name != NULL, NULL);
478   g_return_val_if_fail (name[0] != '\0', NULL);
479 
480   return g_object_new (GIMP_TYPE_DYNAMICS,
481                        "name", name,
482                        NULL);
483 }
484 
485 GimpData *
gimp_dynamics_get_standard(GimpContext * context)486 gimp_dynamics_get_standard (GimpContext *context)
487 {
488   static GimpData *standard_dynamics = NULL;
489 
490   if (! standard_dynamics)
491     {
492       standard_dynamics = gimp_dynamics_new (context, "Standard dynamics");
493 
494       gimp_data_clean (standard_dynamics);
495       gimp_data_make_internal (standard_dynamics, "gimp-dynamics-standard");
496 
497       g_object_add_weak_pointer (G_OBJECT (standard_dynamics),
498                                  (gpointer *) &standard_dynamics);
499     }
500 
501   return standard_dynamics;
502 }
503 
504 GimpDynamicsOutput *
gimp_dynamics_get_output(GimpDynamics * dynamics,GimpDynamicsOutputType type_id)505 gimp_dynamics_get_output (GimpDynamics           *dynamics,
506                           GimpDynamicsOutputType  type_id)
507 {
508   GimpDynamicsPrivate *private;
509 
510   g_return_val_if_fail (GIMP_IS_DYNAMICS (dynamics), NULL);
511 
512   private = GET_PRIVATE (dynamics);
513 
514   switch (type_id)
515     {
516     case GIMP_DYNAMICS_OUTPUT_OPACITY:
517       return private->opacity_output;
518       break;
519 
520     case GIMP_DYNAMICS_OUTPUT_FORCE:
521       return private->force_output;
522       break;
523 
524     case GIMP_DYNAMICS_OUTPUT_HARDNESS:
525       return private->hardness_output;
526       break;
527 
528     case GIMP_DYNAMICS_OUTPUT_RATE:
529       return private->rate_output;
530       break;
531 
532     case GIMP_DYNAMICS_OUTPUT_FLOW:
533       return private->flow_output;
534       break;
535 
536     case GIMP_DYNAMICS_OUTPUT_SIZE:
537       return private->size_output;
538       break;
539 
540     case GIMP_DYNAMICS_OUTPUT_ASPECT_RATIO:
541       return private->aspect_ratio_output;
542       break;
543 
544     case GIMP_DYNAMICS_OUTPUT_COLOR:
545       return private->color_output;
546       break;
547 
548     case GIMP_DYNAMICS_OUTPUT_ANGLE:
549       return private->angle_output;
550       break;
551 
552     case GIMP_DYNAMICS_OUTPUT_JITTER:
553       return private->jitter_output;
554       break;
555 
556     case GIMP_DYNAMICS_OUTPUT_SPACING:
557       return private->spacing_output;
558       break;
559 
560     default:
561       g_return_val_if_reached (NULL);
562       break;
563     }
564 }
565 
566 gboolean
gimp_dynamics_is_output_enabled(GimpDynamics * dynamics,GimpDynamicsOutputType type)567 gimp_dynamics_is_output_enabled (GimpDynamics           *dynamics,
568                                  GimpDynamicsOutputType  type)
569 {
570   GimpDynamicsOutput *output;
571 
572   g_return_val_if_fail (GIMP_IS_DYNAMICS (dynamics), FALSE);
573 
574   output = gimp_dynamics_get_output (dynamics, type);
575 
576   return gimp_dynamics_output_is_enabled (output);
577 }
578 
579 gdouble
gimp_dynamics_get_linear_value(GimpDynamics * dynamics,GimpDynamicsOutputType type,const GimpCoords * coords,GimpPaintOptions * options,gdouble fade_point)580 gimp_dynamics_get_linear_value (GimpDynamics           *dynamics,
581                                 GimpDynamicsOutputType  type,
582                                 const GimpCoords       *coords,
583                                 GimpPaintOptions       *options,
584                                 gdouble                 fade_point)
585 {
586   GimpDynamicsOutput *output;
587 
588   g_return_val_if_fail (GIMP_IS_DYNAMICS (dynamics), 0.0);
589 
590   output = gimp_dynamics_get_output (dynamics, type);
591 
592   return gimp_dynamics_output_get_linear_value (output, coords,
593                                                 options, fade_point);
594 }
595 
596 gdouble
gimp_dynamics_get_angular_value(GimpDynamics * dynamics,GimpDynamicsOutputType type,const GimpCoords * coords,GimpPaintOptions * options,gdouble fade_point)597 gimp_dynamics_get_angular_value (GimpDynamics           *dynamics,
598                                  GimpDynamicsOutputType  type,
599                                  const GimpCoords       *coords,
600                                  GimpPaintOptions       *options,
601                                  gdouble                 fade_point)
602 {
603   GimpDynamicsOutput *output;
604 
605   g_return_val_if_fail (GIMP_IS_DYNAMICS (dynamics), 0.0);
606 
607   output = gimp_dynamics_get_output (dynamics, type);
608 
609   return gimp_dynamics_output_get_angular_value (output, coords,
610                                                  options, fade_point);
611 }
612 
613 gdouble
gimp_dynamics_get_aspect_value(GimpDynamics * dynamics,GimpDynamicsOutputType type,const GimpCoords * coords,GimpPaintOptions * options,gdouble fade_point)614 gimp_dynamics_get_aspect_value (GimpDynamics           *dynamics,
615                                 GimpDynamicsOutputType  type,
616                                 const GimpCoords       *coords,
617                                 GimpPaintOptions       *options,
618                                 gdouble                 fade_point)
619 {
620   GimpDynamicsOutput *output;
621 
622   g_return_val_if_fail (GIMP_IS_DYNAMICS (dynamics), 0.0);
623 
624   output = gimp_dynamics_get_output (dynamics, type);
625 
626   return gimp_dynamics_output_get_aspect_value (output, coords,
627                                                 options, fade_point);
628 }
629 
630 
631 /*  private functions  */
632 
633 static GimpDynamicsOutput *
gimp_dynamics_create_output(GimpDynamics * dynamics,const gchar * name,GimpDynamicsOutputType type)634 gimp_dynamics_create_output (GimpDynamics           *dynamics,
635                              const gchar            *name,
636                              GimpDynamicsOutputType  type)
637 {
638   GimpDynamicsOutput *output = gimp_dynamics_output_new (name, type);
639 
640   g_signal_connect (output, "notify",
641                     G_CALLBACK (gimp_dynamics_output_notify),
642                     dynamics);
643 
644   return output;
645 }
646 
647 static void
gimp_dynamics_output_notify(GObject * output,const GParamSpec * pspec,GimpDynamics * dynamics)648 gimp_dynamics_output_notify (GObject          *output,
649                              const GParamSpec *pspec,
650                              GimpDynamics     *dynamics)
651 {
652   g_object_notify (G_OBJECT (dynamics), gimp_object_get_name (output));
653 }
654