1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimpparamspecs-duplicate.c
5  * Copyright (C) 2008-2014 Michael Natterer <mitch@gimp.org>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  */
20 
21 #include "config.h"
22 
23 #include <cairo.h>
24 #include <gegl.h>
25 #include <gegl-paramspecs.h>
26 #include <gdk-pixbuf/gdk-pixbuf.h>
27 
28 #include "libgimpcolor/gimpcolor.h"
29 #include "libgimpconfig/gimpconfig.h"
30 
31 #include "core-types.h"
32 
33 #include "gegl/gimp-gegl-utils.h"
34 
35 #include "gimpparamspecs.h"
36 #include "gimpparamspecs-duplicate.h"
37 
38 
39 /* FIXME: this code is not yet general as it should be (gegl tool only atm) */
40 
41 GParamSpec *
gimp_param_spec_duplicate(GParamSpec * pspec)42 gimp_param_spec_duplicate (GParamSpec *pspec)
43 {
44   GParamSpec  *copy = NULL;
45   GParamFlags  flags;
46 
47   g_return_val_if_fail (pspec != NULL, NULL);
48 
49   flags = pspec->flags;
50 
51   if (! gimp_gegl_param_spec_has_key (pspec, "role", "output-extent"))
52     flags |= GIMP_CONFIG_PARAM_SERIALIZE;
53 
54   if (G_IS_PARAM_SPEC_STRING (pspec))
55     {
56       GParamSpecString *spec = G_PARAM_SPEC_STRING (pspec);
57 
58       if (GEGL_IS_PARAM_SPEC_FILE_PATH (pspec))
59         {
60           copy = gimp_param_spec_config_path (pspec->name,
61                                               g_param_spec_get_nick (pspec),
62                                               g_param_spec_get_blurb (pspec),
63                                               GIMP_CONFIG_PATH_FILE,
64                                               spec->default_value,
65                                               flags);
66         }
67       else
68         {
69           copy = g_param_spec_string (pspec->name,
70                                       g_param_spec_get_nick (pspec),
71                                       g_param_spec_get_blurb (pspec),
72                                       spec->default_value,
73                                       flags);
74         }
75     }
76   else if (G_IS_PARAM_SPEC_BOOLEAN (pspec))
77     {
78       GParamSpecBoolean *spec = G_PARAM_SPEC_BOOLEAN (pspec);
79 
80       copy = g_param_spec_boolean (pspec->name,
81                                    g_param_spec_get_nick (pspec),
82                                    g_param_spec_get_blurb (pspec),
83                                    spec->default_value,
84                                    flags);
85     }
86   else if (G_IS_PARAM_SPEC_ENUM (pspec))
87     {
88       GParamSpecEnum *spec = G_PARAM_SPEC_ENUM (pspec);
89 
90       copy = g_param_spec_enum (pspec->name,
91                                 g_param_spec_get_nick (pspec),
92                                 g_param_spec_get_blurb (pspec),
93                                 G_TYPE_FROM_CLASS (spec->enum_class),
94                                 spec->default_value,
95                                 flags);
96     }
97   else if (GEGL_IS_PARAM_SPEC_DOUBLE (pspec))
98     {
99       GeglParamSpecDouble *gspec = GEGL_PARAM_SPEC_DOUBLE (pspec);
100       GParamSpecDouble    *spec  = G_PARAM_SPEC_DOUBLE (pspec);
101 
102       copy = gegl_param_spec_double (pspec->name,
103                                      g_param_spec_get_nick (pspec),
104                                      g_param_spec_get_blurb (pspec),
105                                      spec->minimum,
106                                      spec->maximum,
107                                      spec->default_value,
108                                      gspec->ui_minimum,
109                                      gspec->ui_maximum,
110                                      gspec->ui_gamma,
111                                      flags);
112       gegl_param_spec_double_set_steps (GEGL_PARAM_SPEC_DOUBLE (copy),
113                                         gspec->ui_step_small,
114                                         gspec->ui_step_big);
115       gegl_param_spec_double_set_digits (GEGL_PARAM_SPEC_DOUBLE (copy),
116                                          gspec->ui_digits);
117     }
118   else if (G_IS_PARAM_SPEC_DOUBLE (pspec))
119     {
120       GParamSpecDouble *spec = G_PARAM_SPEC_DOUBLE (pspec);
121 
122       copy = g_param_spec_double (pspec->name,
123                                   g_param_spec_get_nick (pspec),
124                                   g_param_spec_get_blurb (pspec),
125                                   spec->minimum,
126                                   spec->maximum,
127                                   spec->default_value,
128                                   flags);
129     }
130   else if (G_IS_PARAM_SPEC_FLOAT (pspec))
131     {
132       GParamSpecFloat *spec = G_PARAM_SPEC_FLOAT (pspec);
133 
134       copy = g_param_spec_float (pspec->name,
135                                  g_param_spec_get_nick (pspec),
136                                  g_param_spec_get_blurb (pspec),
137                                  spec->minimum,
138                                  spec->maximum,
139                                  spec->default_value,
140                                  flags);
141     }
142   else if (GEGL_IS_PARAM_SPEC_INT (pspec))
143     {
144       GeglParamSpecInt *gspec = GEGL_PARAM_SPEC_INT (pspec);
145       GParamSpecInt    *spec  = G_PARAM_SPEC_INT (pspec);
146 
147       copy = gegl_param_spec_int (pspec->name,
148                                   g_param_spec_get_nick (pspec),
149                                   g_param_spec_get_blurb (pspec),
150                                   spec->minimum,
151                                   spec->maximum,
152                                   spec->default_value,
153                                   gspec->ui_minimum,
154                                   gspec->ui_maximum,
155                                   gspec->ui_gamma,
156                                   flags);
157       gegl_param_spec_int_set_steps (GEGL_PARAM_SPEC_INT (copy),
158                                      gspec->ui_step_small,
159                                      gspec->ui_step_big);
160     }
161   else if (GEGL_IS_PARAM_SPEC_SEED (pspec))
162     {
163       GParamSpecUInt    *spec  = G_PARAM_SPEC_UINT (pspec);
164       GeglParamSpecSeed *gspec = GEGL_PARAM_SPEC_SEED (pspec);
165 
166       copy = gegl_param_spec_seed (pspec->name,
167                                    g_param_spec_get_nick (pspec),
168                                    g_param_spec_get_blurb (pspec),
169                                    pspec->flags |
170                                    GIMP_CONFIG_PARAM_SERIALIZE);
171 
172       G_PARAM_SPEC_UINT (copy)->minimum = spec->minimum;
173       G_PARAM_SPEC_UINT (copy)->maximum = spec->maximum;
174 
175       GEGL_PARAM_SPEC_SEED (copy)->ui_minimum = gspec->ui_minimum;
176       GEGL_PARAM_SPEC_SEED (copy)->ui_maximum = gspec->ui_maximum;
177     }
178   else if (G_IS_PARAM_SPEC_INT (pspec))
179     {
180       GParamSpecInt *spec = G_PARAM_SPEC_INT (pspec);
181 
182       copy = g_param_spec_int (pspec->name,
183                                g_param_spec_get_nick (pspec),
184                                g_param_spec_get_blurb (pspec),
185                                spec->minimum,
186                                spec->maximum,
187                                spec->default_value,
188                                flags);
189     }
190   else if (G_IS_PARAM_SPEC_UINT (pspec))
191     {
192       GParamSpecUInt *spec = G_PARAM_SPEC_UINT (pspec);
193 
194       copy = g_param_spec_uint (pspec->name,
195                                 g_param_spec_get_nick (pspec),
196                                 g_param_spec_get_blurb (pspec),
197                                 spec->minimum,
198                                 spec->maximum,
199                                 spec->default_value,
200                                 flags);
201     }
202   else if (GIMP_IS_PARAM_SPEC_RGB (pspec))
203     {
204       GValue  value = G_VALUE_INIT;
205       GimpRGB color;
206 
207       g_value_init (&value, GIMP_TYPE_RGB);
208       g_param_value_set_default (pspec, &value);
209       gimp_value_get_rgb (&value, &color);
210       g_value_unset (&value);
211 
212       copy = gimp_param_spec_rgb (pspec->name,
213                                   g_param_spec_get_nick (pspec),
214                                   g_param_spec_get_blurb (pspec),
215                                   gimp_param_spec_rgb_has_alpha (pspec),
216                                   &color,
217                                   flags);
218     }
219   else if (GEGL_IS_PARAM_SPEC_COLOR (pspec))
220     {
221       GeglColor *gegl_color;
222       GimpRGB    gimp_color;
223       gdouble    r = 0.0;
224       gdouble    g = 0.0;
225       gdouble    b = 0.0;
226       gdouble    a = 1.0;
227       GValue     value = G_VALUE_INIT;
228 
229       g_value_init (&value, GEGL_TYPE_COLOR);
230       g_param_value_set_default (pspec, &value);
231 
232       gegl_color = g_value_get_object (&value);
233       if (gegl_color)
234         gegl_color_get_rgba (gegl_color, &r, &g, &b, &a);
235 
236       gimp_rgba_set (&gimp_color, r, g, b, a);
237 
238       g_value_unset (&value);
239 
240       copy = gimp_param_spec_rgb (pspec->name,
241                                   g_param_spec_get_nick (pspec),
242                                   g_param_spec_get_blurb (pspec),
243                                   TRUE,
244                                   &gimp_color,
245                                   flags);
246     }
247   else if (G_IS_PARAM_SPEC_OBJECT (pspec) ||
248            G_IS_PARAM_SPEC_POINTER (pspec))
249     {
250       /*  silently ignore object properties  */
251     }
252   else
253     {
254       g_warning ("%s: not supported: %s (%s)\n", G_STRFUNC,
255                  g_type_name (G_TYPE_FROM_INSTANCE (pspec)), pspec->name);
256     }
257 
258   if (copy)
259     {
260       GQuark      quark = g_quark_from_static_string ("gegl-property-keys");
261       GHashTable *keys  = g_param_spec_get_qdata (pspec, quark);
262 
263       if (keys)
264         g_param_spec_set_qdata_full (copy, quark, g_hash_table_ref (keys),
265                                      (GDestroyNotify) g_hash_table_unref);
266     }
267 
268   return copy;
269 }
270