1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
|
/* LIBGIMP - The GIMP Library
* Copyright (C) 1995-2003 Peter Mattis and Spencer Kimball
*
* gimpconfig-register.c
* Copyright (C) 2008-2019 Michael Natterer <mitch@gimp.org>
*
* This library is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <https://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gegl-paramspecs.h>
#include "libgimpbase/gimpbase.h"
#include "gimpconfig.h"
/* local function prototypes */
static void gimp_config_class_init (GObjectClass *klass,
GParamSpec **pspecs);
static void gimp_config_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
static void gimp_config_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);
static GValue * gimp_config_value_get (GObject *object,
GParamSpec *pspec);
static GValue * gimp_config_value_new (GParamSpec *pspec);
static void gimp_config_value_free (GValue *value);
/* public functions */
/**
* gimp_config_type_register:
* @parent_type: type from which this type will be derived
* @type_name: string used as the name of the new type
* @pspecs: (array length=n_pspecs): array of #GParamSpec to install as properties on the new type
* @n_pspecs: the number of param specs in @pspecs
*
* This function is a fancy wrapper around g_type_register_static().
* It creates a new object type as subclass of @parent_type, installs
* @pspecs on it and makes the new type implement the #GimpConfig
* interface.
*
* Returns: the newly registered #GType
*
* Since: 3.0
**/
GType
gimp_config_type_register (GType parent_type,
const gchar *type_name,
GParamSpec **pspecs,
gint n_pspecs)
{
GParamSpec **terminated_pspecs;
GTypeQuery query;
GType config_type;
g_return_val_if_fail (g_type_is_a (parent_type, G_TYPE_OBJECT), G_TYPE_NONE);
g_return_val_if_fail (type_name != NULL, G_TYPE_NONE);
g_return_val_if_fail (pspecs != NULL || n_pspecs == 0, G_TYPE_NONE);
terminated_pspecs = g_new0 (GParamSpec *, n_pspecs + 1);
memcpy (terminated_pspecs, pspecs, sizeof (GParamSpec *) * n_pspecs);
g_type_query (parent_type, &query);
{
GTypeInfo info =
{
query.class_size,
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) gimp_config_class_init,
NULL, /* class_finalize */
terminated_pspecs,
query.instance_size,
0, /* n_preallocs */
(GInstanceInitFunc) NULL,
};
config_type = g_type_register_static (parent_type, type_name,
&info, 0);
if (! g_type_is_a (parent_type, GIMP_TYPE_CONFIG))
{
const GInterfaceInfo config_info =
{
NULL, /* interface_init */
NULL, /* interface_finalize */
NULL /* interface_data */
};
g_type_add_interface_static (config_type, GIMP_TYPE_CONFIG,
&config_info);
}
}
return config_type;
}
/* private functions */
static void
gimp_config_class_init (GObjectClass *klass,
GParamSpec **pspecs)
{
gint i;
klass->set_property = gimp_config_set_property;
klass->get_property = gimp_config_get_property;
for (i = 0; pspecs[i] != NULL; i++)
{
GParamSpec *pspec = pspecs[i];
GParamSpec *copy = gimp_config_param_spec_duplicate (pspec);
if (copy)
{
g_object_class_install_property (klass, i + 1, copy);
/* If the original param spec was floating, this would unref
* it. Otherwise (e.g. it's a spec taken from another object),
* nothing happens.
*/
g_param_spec_sink (pspec);
}
else
{
GType value_type = G_PARAM_SPEC_VALUE_TYPE (pspec);
const gchar *type_name = g_type_name (value_type);
/* There are some properties that we don't care to copy because they
* are not serializable anyway (or we don't want them to be).
* GimpContext properties are one such property type. We can find them
* e.g. in some custom GEGL ops, such as "gimp:offset". So we silently
* ignore these.
* We might add more types of properties to the list as we discover
* more cases. We keep warnings for all the other types which we
* explicitly don't support.
*/
if (g_strcmp0 (type_name, "GimpContext") != 0 &&
/* Format specs are a GParamSpecPointer. There might be other
* pointer specs we might be able to serialize, but BablFormat are
* not one of these (there might be easy serializable formats, but
* many are not and anyway it's probably not a data which ops or
* plug-ins want to remember across run).
*/
! GEGL_IS_PARAM_SPEC_FORMAT (pspec))
g_warning ("%s: not supported: %s (%s | %s)\n", G_STRFUNC,
g_type_name (G_TYPE_FROM_INSTANCE (pspec)), pspec->name, type_name);
}
}
g_free (pspecs);
}
static void
gimp_config_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GValue *val = gimp_config_value_get (object, pspec);
g_value_copy (value, val);
}
static void
gimp_config_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GValue *val = gimp_config_value_get (object, pspec);
g_value_copy (val, value);
}
static GValue *
gimp_config_value_get (GObject *object,
GParamSpec *pspec)
{
GHashTable *properties;
GValue *value;
properties = g_object_get_data (object, "gimp-config-properties");
if (! properties)
{
properties =
g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) gimp_config_value_free);
g_object_set_data_full (object, "gimp-config-properties", properties,
(GDestroyNotify) g_hash_table_unref);
}
value = g_hash_table_lookup (properties, pspec->name);
if (! value)
{
value = gimp_config_value_new (pspec);
g_hash_table_insert (properties, g_strdup (pspec->name), value);
}
return value;
}
static GValue *
gimp_config_value_new (GParamSpec *pspec)
{
GValue *value = g_slice_new0 (GValue);
g_value_init (value, pspec->value_type);
g_param_value_set_default (pspec, value);
return value;
}
static void
gimp_config_value_free (GValue *value)
{
g_value_unset (value);
g_slice_free (GValue, value);
}
|