diff options
Diffstat (limited to '')
-rw-r--r-- | app/core/gimpdynamics.c | 653 |
1 files changed, 653 insertions, 0 deletions
diff --git a/app/core/gimpdynamics.c b/app/core/gimpdynamics.c new file mode 100644 index 0000000..a1fb0ef --- /dev/null +++ b/app/core/gimpdynamics.c @@ -0,0 +1,653 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995-1999 Spencer Kimball and Peter Mattis + * + * 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 <gdk-pixbuf/gdk-pixbuf.h> +#include <gegl.h> + +#include "libgimpmath/gimpmath.h" +#include "libgimpconfig/gimpconfig.h" + +#include "core-types.h" + +#include "gimpcurve.h" +#include "gimpdynamics.h" +#include "gimpdynamics-load.h" +#include "gimpdynamics-save.h" +#include "gimpdynamicsoutput.h" + +#include "gimp-intl.h" + + +#define DEFAULT_NAME "Nameless dynamics" + +enum +{ + PROP_0, + + PROP_NAME, + + PROP_OPACITY_OUTPUT, + PROP_SIZE_OUTPUT, + PROP_ANGLE_OUTPUT, + PROP_COLOR_OUTPUT, + PROP_FORCE_OUTPUT, + PROP_HARDNESS_OUTPUT, + PROP_ASPECT_RATIO_OUTPUT, + PROP_SPACING_OUTPUT, + PROP_RATE_OUTPUT, + PROP_FLOW_OUTPUT, + PROP_JITTER_OUTPUT +}; + + +typedef struct _GimpDynamicsPrivate GimpDynamicsPrivate; + +struct _GimpDynamicsPrivate +{ + GimpDynamicsOutput *opacity_output; + GimpDynamicsOutput *hardness_output; + GimpDynamicsOutput *force_output; + GimpDynamicsOutput *rate_output; + GimpDynamicsOutput *flow_output; + GimpDynamicsOutput *size_output; + GimpDynamicsOutput *aspect_ratio_output; + GimpDynamicsOutput *color_output; + GimpDynamicsOutput *angle_output; + GimpDynamicsOutput *jitter_output; + GimpDynamicsOutput *spacing_output; +}; + +#define GET_PRIVATE(output) \ + ((GimpDynamicsPrivate *) gimp_dynamics_get_instance_private ((GimpDynamics *) (output))) + + +static void gimp_dynamics_finalize (GObject *object); +static void gimp_dynamics_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_dynamics_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); +static void + gimp_dynamics_dispatch_properties_changed (GObject *object, + guint n_pspecs, + GParamSpec **pspecs); + +static const gchar * gimp_dynamics_get_extension (GimpData *data); +static void gimp_dynamics_copy (GimpData *data, + GimpData *src_data); + +static GimpDynamicsOutput * + gimp_dynamics_create_output (GimpDynamics *dynamics, + const gchar *name, + GimpDynamicsOutputType type); +static void gimp_dynamics_output_notify (GObject *output, + const GParamSpec *pspec, + GimpDynamics *dynamics); + + +G_DEFINE_TYPE_WITH_PRIVATE (GimpDynamics, gimp_dynamics, GIMP_TYPE_DATA) + +#define parent_class gimp_dynamics_parent_class + + +static void +gimp_dynamics_class_init (GimpDynamicsClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpDataClass *data_class = GIMP_DATA_CLASS (klass); + GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass); + + object_class->finalize = gimp_dynamics_finalize; + object_class->set_property = gimp_dynamics_set_property; + object_class->get_property = gimp_dynamics_get_property; + object_class->dispatch_properties_changed = gimp_dynamics_dispatch_properties_changed; + + viewable_class->default_icon_name = "gimp-dynamics"; + + data_class->save = gimp_dynamics_save; + data_class->get_extension = gimp_dynamics_get_extension; + data_class->copy = gimp_dynamics_copy; + + GIMP_CONFIG_PROP_STRING (object_class, PROP_NAME, + "name", + NULL, NULL, + DEFAULT_NAME, + GIMP_PARAM_STATIC_STRINGS); + + GIMP_CONFIG_PROP_OBJECT (object_class, PROP_OPACITY_OUTPUT, + "opacity-output", + NULL, NULL, + GIMP_TYPE_DYNAMICS_OUTPUT, + GIMP_CONFIG_PARAM_AGGREGATE); + + GIMP_CONFIG_PROP_OBJECT (object_class, PROP_FORCE_OUTPUT, + "force-output", + NULL, NULL, + GIMP_TYPE_DYNAMICS_OUTPUT, + GIMP_CONFIG_PARAM_AGGREGATE); + + GIMP_CONFIG_PROP_OBJECT (object_class, PROP_HARDNESS_OUTPUT, + "hardness-output", + NULL, NULL, + GIMP_TYPE_DYNAMICS_OUTPUT, + GIMP_CONFIG_PARAM_AGGREGATE); + + GIMP_CONFIG_PROP_OBJECT (object_class, PROP_RATE_OUTPUT, + "rate-output", + NULL, NULL, + GIMP_TYPE_DYNAMICS_OUTPUT, + GIMP_CONFIG_PARAM_AGGREGATE); + + GIMP_CONFIG_PROP_OBJECT (object_class, PROP_FLOW_OUTPUT, + "flow-output", + NULL, NULL, + GIMP_TYPE_DYNAMICS_OUTPUT, + GIMP_CONFIG_PARAM_AGGREGATE); + + GIMP_CONFIG_PROP_OBJECT (object_class, PROP_SIZE_OUTPUT, + "size-output", + NULL, NULL, + GIMP_TYPE_DYNAMICS_OUTPUT, + GIMP_CONFIG_PARAM_AGGREGATE); + + GIMP_CONFIG_PROP_OBJECT (object_class, PROP_ASPECT_RATIO_OUTPUT, + "aspect-ratio-output", + NULL, NULL, + GIMP_TYPE_DYNAMICS_OUTPUT, + GIMP_CONFIG_PARAM_AGGREGATE); + + GIMP_CONFIG_PROP_OBJECT (object_class, PROP_COLOR_OUTPUT, + "color-output", + NULL, NULL, + GIMP_TYPE_DYNAMICS_OUTPUT, + GIMP_CONFIG_PARAM_AGGREGATE); + + GIMP_CONFIG_PROP_OBJECT (object_class, PROP_ANGLE_OUTPUT, + "angle-output", + NULL, NULL, + GIMP_TYPE_DYNAMICS_OUTPUT, + GIMP_CONFIG_PARAM_AGGREGATE); + + GIMP_CONFIG_PROP_OBJECT (object_class, PROP_JITTER_OUTPUT, + "jitter-output", + NULL, NULL, + GIMP_TYPE_DYNAMICS_OUTPUT, + GIMP_CONFIG_PARAM_AGGREGATE); + + GIMP_CONFIG_PROP_OBJECT (object_class, PROP_SPACING_OUTPUT, + "spacing-output", + NULL, NULL, + GIMP_TYPE_DYNAMICS_OUTPUT, + GIMP_CONFIG_PARAM_AGGREGATE); +} + +static void +gimp_dynamics_init (GimpDynamics *dynamics) +{ + GimpDynamicsPrivate *private = GET_PRIVATE (dynamics); + + private->opacity_output = + gimp_dynamics_create_output (dynamics, + "opacity-output", + GIMP_DYNAMICS_OUTPUT_OPACITY); + + private->force_output = + gimp_dynamics_create_output (dynamics, + "force-output", + GIMP_DYNAMICS_OUTPUT_FORCE); + + private->hardness_output = + gimp_dynamics_create_output (dynamics, + "hardness-output", + GIMP_DYNAMICS_OUTPUT_HARDNESS); + + private->rate_output = + gimp_dynamics_create_output (dynamics, + "rate-output", + GIMP_DYNAMICS_OUTPUT_RATE); + + private->flow_output = + gimp_dynamics_create_output (dynamics, + "flow-output", + GIMP_DYNAMICS_OUTPUT_FLOW); + + private->size_output = + gimp_dynamics_create_output (dynamics, + "size-output", + GIMP_DYNAMICS_OUTPUT_SIZE); + + private->aspect_ratio_output = + gimp_dynamics_create_output (dynamics, + "aspect-ratio-output", + GIMP_DYNAMICS_OUTPUT_ASPECT_RATIO); + + private->color_output = + gimp_dynamics_create_output (dynamics, + "color-output", + GIMP_DYNAMICS_OUTPUT_COLOR); + + private->angle_output = + gimp_dynamics_create_output (dynamics, + "angle-output", + GIMP_DYNAMICS_OUTPUT_ANGLE); + + private->jitter_output = + gimp_dynamics_create_output (dynamics, + "jitter-output", + GIMP_DYNAMICS_OUTPUT_JITTER); + + private->spacing_output = + gimp_dynamics_create_output (dynamics, + "spacing-output", + GIMP_DYNAMICS_OUTPUT_SPACING); +} + +static void +gimp_dynamics_finalize (GObject *object) +{ + GimpDynamicsPrivate *private = GET_PRIVATE (object); + + g_clear_object (&private->opacity_output); + g_clear_object (&private->force_output); + g_clear_object (&private->hardness_output); + g_clear_object (&private->rate_output); + g_clear_object (&private->flow_output); + g_clear_object (&private->size_output); + g_clear_object (&private->aspect_ratio_output); + g_clear_object (&private->color_output); + g_clear_object (&private->angle_output); + g_clear_object (&private->jitter_output); + g_clear_object (&private->spacing_output); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_dynamics_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpDynamicsPrivate *private = GET_PRIVATE (object); + GimpDynamicsOutput *src_output = NULL; + GimpDynamicsOutput *dest_output = NULL; + + switch (property_id) + { + case PROP_NAME: + gimp_object_set_name (GIMP_OBJECT (object), g_value_get_string (value)); + break; + + case PROP_OPACITY_OUTPUT: + src_output = g_value_get_object (value); + dest_output = private->opacity_output; + break; + + case PROP_FORCE_OUTPUT: + src_output = g_value_get_object (value); + dest_output = private->force_output; + break; + + case PROP_HARDNESS_OUTPUT: + src_output = g_value_get_object (value); + dest_output = private->hardness_output; + break; + + case PROP_RATE_OUTPUT: + src_output = g_value_get_object (value); + dest_output = private->rate_output; + break; + + case PROP_FLOW_OUTPUT: + src_output = g_value_get_object (value); + dest_output = private->flow_output; + break; + + case PROP_SIZE_OUTPUT: + src_output = g_value_get_object (value); + dest_output = private->size_output; + break; + + case PROP_ASPECT_RATIO_OUTPUT: + src_output = g_value_get_object (value); + dest_output = private->aspect_ratio_output; + break; + + case PROP_COLOR_OUTPUT: + src_output = g_value_get_object (value); + dest_output = private->color_output; + break; + + case PROP_ANGLE_OUTPUT: + src_output = g_value_get_object (value); + dest_output = private->angle_output; + break; + + case PROP_JITTER_OUTPUT: + src_output = g_value_get_object (value); + dest_output = private->jitter_output; + break; + + case PROP_SPACING_OUTPUT: + src_output = g_value_get_object (value); + dest_output = private->spacing_output; + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } + + if (src_output && dest_output) + { + gimp_config_copy (GIMP_CONFIG (src_output), + GIMP_CONFIG (dest_output), + GIMP_CONFIG_PARAM_SERIALIZE); + } +} + +static void +gimp_dynamics_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpDynamicsPrivate *private = GET_PRIVATE (object); + + switch (property_id) + { + case PROP_NAME: + g_value_set_string (value, gimp_object_get_name (object)); + break; + + case PROP_OPACITY_OUTPUT: + g_value_set_object (value, private->opacity_output); + break; + + case PROP_FORCE_OUTPUT: + g_value_set_object (value, private->force_output); + break; + + case PROP_HARDNESS_OUTPUT: + g_value_set_object (value, private->hardness_output); + break; + + case PROP_RATE_OUTPUT: + g_value_set_object (value, private->rate_output); + break; + + case PROP_FLOW_OUTPUT: + g_value_set_object (value, private->flow_output); + break; + + case PROP_SIZE_OUTPUT: + g_value_set_object (value, private->size_output); + break; + + case PROP_ASPECT_RATIO_OUTPUT: + g_value_set_object (value, private->aspect_ratio_output); + break; + + case PROP_COLOR_OUTPUT: + g_value_set_object (value, private->color_output); + break; + + case PROP_ANGLE_OUTPUT: + g_value_set_object (value, private->angle_output); + break; + + case PROP_JITTER_OUTPUT: + g_value_set_object (value, private->jitter_output); + break; + + case PROP_SPACING_OUTPUT: + g_value_set_object (value, private->spacing_output); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_dynamics_dispatch_properties_changed (GObject *object, + guint n_pspecs, + GParamSpec **pspecs) +{ + gint i; + + G_OBJECT_CLASS (parent_class)->dispatch_properties_changed (object, + n_pspecs, pspecs); + + for (i = 0; i < n_pspecs; i++) + { + if (pspecs[i]->flags & GIMP_CONFIG_PARAM_SERIALIZE) + { + gimp_data_dirty (GIMP_DATA (object)); + break; + } + } +} + +static const gchar * +gimp_dynamics_get_extension (GimpData *data) +{ + return GIMP_DYNAMICS_FILE_EXTENSION; +} + +static void +gimp_dynamics_copy (GimpData *data, + GimpData *src_data) +{ + gimp_data_freeze (data); + + gimp_config_copy (GIMP_CONFIG (src_data), + GIMP_CONFIG (data), 0); + + gimp_data_thaw (data); +} + + +/* public functions */ + +GimpData * +gimp_dynamics_new (GimpContext *context, + const gchar *name) +{ + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (name[0] != '\0', NULL); + + return g_object_new (GIMP_TYPE_DYNAMICS, + "name", name, + NULL); +} + +GimpData * +gimp_dynamics_get_standard (GimpContext *context) +{ + static GimpData *standard_dynamics = NULL; + + if (! standard_dynamics) + { + standard_dynamics = gimp_dynamics_new (context, "Standard dynamics"); + + gimp_data_clean (standard_dynamics); + gimp_data_make_internal (standard_dynamics, "gimp-dynamics-standard"); + + g_object_add_weak_pointer (G_OBJECT (standard_dynamics), + (gpointer *) &standard_dynamics); + } + + return standard_dynamics; +} + +GimpDynamicsOutput * +gimp_dynamics_get_output (GimpDynamics *dynamics, + GimpDynamicsOutputType type_id) +{ + GimpDynamicsPrivate *private; + + g_return_val_if_fail (GIMP_IS_DYNAMICS (dynamics), NULL); + + private = GET_PRIVATE (dynamics); + + switch (type_id) + { + case GIMP_DYNAMICS_OUTPUT_OPACITY: + return private->opacity_output; + break; + + case GIMP_DYNAMICS_OUTPUT_FORCE: + return private->force_output; + break; + + case GIMP_DYNAMICS_OUTPUT_HARDNESS: + return private->hardness_output; + break; + + case GIMP_DYNAMICS_OUTPUT_RATE: + return private->rate_output; + break; + + case GIMP_DYNAMICS_OUTPUT_FLOW: + return private->flow_output; + break; + + case GIMP_DYNAMICS_OUTPUT_SIZE: + return private->size_output; + break; + + case GIMP_DYNAMICS_OUTPUT_ASPECT_RATIO: + return private->aspect_ratio_output; + break; + + case GIMP_DYNAMICS_OUTPUT_COLOR: + return private->color_output; + break; + + case GIMP_DYNAMICS_OUTPUT_ANGLE: + return private->angle_output; + break; + + case GIMP_DYNAMICS_OUTPUT_JITTER: + return private->jitter_output; + break; + + case GIMP_DYNAMICS_OUTPUT_SPACING: + return private->spacing_output; + break; + + default: + g_return_val_if_reached (NULL); + break; + } +} + +gboolean +gimp_dynamics_is_output_enabled (GimpDynamics *dynamics, + GimpDynamicsOutputType type) +{ + GimpDynamicsOutput *output; + + g_return_val_if_fail (GIMP_IS_DYNAMICS (dynamics), FALSE); + + output = gimp_dynamics_get_output (dynamics, type); + + return gimp_dynamics_output_is_enabled (output); +} + +gdouble +gimp_dynamics_get_linear_value (GimpDynamics *dynamics, + GimpDynamicsOutputType type, + const GimpCoords *coords, + GimpPaintOptions *options, + gdouble fade_point) +{ + GimpDynamicsOutput *output; + + g_return_val_if_fail (GIMP_IS_DYNAMICS (dynamics), 0.0); + + output = gimp_dynamics_get_output (dynamics, type); + + return gimp_dynamics_output_get_linear_value (output, coords, + options, fade_point); +} + +gdouble +gimp_dynamics_get_angular_value (GimpDynamics *dynamics, + GimpDynamicsOutputType type, + const GimpCoords *coords, + GimpPaintOptions *options, + gdouble fade_point) +{ + GimpDynamicsOutput *output; + + g_return_val_if_fail (GIMP_IS_DYNAMICS (dynamics), 0.0); + + output = gimp_dynamics_get_output (dynamics, type); + + return gimp_dynamics_output_get_angular_value (output, coords, + options, fade_point); +} + +gdouble +gimp_dynamics_get_aspect_value (GimpDynamics *dynamics, + GimpDynamicsOutputType type, + const GimpCoords *coords, + GimpPaintOptions *options, + gdouble fade_point) +{ + GimpDynamicsOutput *output; + + g_return_val_if_fail (GIMP_IS_DYNAMICS (dynamics), 0.0); + + output = gimp_dynamics_get_output (dynamics, type); + + return gimp_dynamics_output_get_aspect_value (output, coords, + options, fade_point); +} + + +/* private functions */ + +static GimpDynamicsOutput * +gimp_dynamics_create_output (GimpDynamics *dynamics, + const gchar *name, + GimpDynamicsOutputType type) +{ + GimpDynamicsOutput *output = gimp_dynamics_output_new (name, type); + + g_signal_connect (output, "notify", + G_CALLBACK (gimp_dynamics_output_notify), + dynamics); + + return output; +} + +static void +gimp_dynamics_output_notify (GObject *output, + const GParamSpec *pspec, + GimpDynamics *dynamics) +{ + g_object_notify (G_OBJECT (dynamics), gimp_object_get_name (output)); +} |