diff --git a/app/plug-in/plug-in-rc.c b/app/plug-in/plug-in-rc.c index b9e71b9e77..56930cdefa 100644 --- a/app/plug-in/plug-in-rc.c +++ b/app/plug-in/plug-in-rc.c @@ -928,6 +928,58 @@ plug_in_proc_arg_deserialize (GScanner *scanner, } break; + case GP_PARAM_DEF_TYPE_GEGL_COLOR: + { + GPParamColor *default_val = NULL; + gint bpp = 0; + guint8 *data = NULL; + gchar *encoding = NULL; + gint profile_size = 0; + guint8 *profile_data = NULL; + + if (! gimp_scanner_parse_int (scanner, + ¶m_def.meta.m_gegl_color.has_alpha)) + { + token = G_TOKEN_INT; + goto error; + } + + if (! gimp_scanner_parse_int (scanner, &bpp) || + bpp > 40 || + ! gimp_scanner_parse_data (scanner, bpp, &data) || + ! gimp_scanner_parse_string (scanner, &encoding) || + ! gimp_scanner_parse_int (scanner, &profile_size) || + ! gimp_scanner_parse_data (scanner, profile_size, &profile_data)) + { + g_free (data); + g_free (encoding); + g_free (profile_data); + + token = G_TOKEN_INT; + goto error; + } + + if (bpp > 0) + { + default_val = g_new0 (GPParamColor, 1); + + memcpy (default_val->data, data, bpp); + default_val->size = bpp; + default_val->encoding = encoding; + default_val->profile_size = profile_size; + default_val->profile_data = profile_data; + } + else + { + g_free (encoding); + g_free (profile_data); + } + g_free (data); + + param_def.meta.m_gegl_color.default_val = default_val; + } + break; + case GP_PARAM_DEF_TYPE_ID: if (! gimp_scanner_parse_int (scanner, ¶m_def.meta.m_id.none_ok)) @@ -986,6 +1038,15 @@ plug_in_proc_arg_deserialize (GScanner *scanner, g_free (param_def.meta.m_string.default_val); break; + case GP_PARAM_DEF_TYPE_GEGL_COLOR: + if (param_def.meta.m_gegl_color.default_val) + { + g_free (param_def.meta.m_gegl_color.default_val->encoding); + g_free (param_def.meta.m_gegl_color.default_val->profile_data); + g_free (param_def.meta.m_gegl_color.default_val); + } + break; + case GP_PARAM_DEF_TYPE_COLOR: case GP_PARAM_DEF_TYPE_ID: break; @@ -1149,6 +1210,41 @@ plug_in_rc_write_proc_arg (GimpConfigWriter *writer, buf[0], buf[1], buf[2], buf[3]); break; + case GP_PARAM_DEF_TYPE_GEGL_COLOR: + { + gint bpp = 0; + guint8 *data = NULL; + gchar *encoding = NULL; + guint32 profile_size = 0; + guint8 *profile_data = NULL; + + gimp_config_writer_printf (writer, "%d", + param_def.meta.m_gegl_color.has_alpha); + + if (param_def.meta.m_gegl_color.default_val && + param_def.meta.m_gegl_color.default_val->size > 0) + { + bpp = param_def.meta.m_gegl_color.default_val->size; + data = param_def.meta.m_gegl_color.default_val->data; + encoding = param_def.meta.m_gegl_color.default_val->encoding; + profile_size = param_def.meta.m_gegl_color.default_val->profile_size; + profile_data = param_def.meta.m_gegl_color.default_val->profile_data; + + gimp_config_writer_printf (writer, "%d", bpp); + gimp_config_writer_data (writer, bpp, data); + gimp_config_writer_string (writer, encoding); + + gimp_config_writer_printf (writer, "%d", profile_size); + if (profile_size > 0) + gimp_config_writer_data (writer, profile_size, profile_data); + } + else + { + gimp_config_writer_printf (writer, "%s", "NULL"); + } + } + break; + case GP_PARAM_DEF_TYPE_ID: gimp_config_writer_printf (writer, "%d", param_def.meta.m_id.none_ok); diff --git a/libgimp/gimpgpparams-body.c b/libgimp/gimpgpparams-body.c index 71b002b334..876cf9fa48 100644 --- a/libgimp/gimpgpparams-body.c +++ b/libgimp/gimpgpparams-body.c @@ -163,6 +163,59 @@ _gimp_gp_param_def_to_param_spec (const GPParamDef *param_def) flags); break; + case GP_PARAM_DEF_TYPE_GEGL_COLOR: + if (! strcmp (param_def->type_name, "GeglParamColor")) + { + GeglColor *default_color = NULL; + + if (param_def->meta.m_gegl_color.default_val) + { + GPParamColor *default_val = param_def->meta.m_gegl_color.default_val; + const Babl *format = NULL; + const Babl *space = NULL; + gint bpp; + + default_color = gegl_color_new ("black"); + + if (default_val->profile_data) + { + GimpColorProfile *profile; + + profile = gimp_color_profile_new_from_icc_profile (default_val->profile_data, + default_val->profile_size, + NULL); + if (profile) + { + GError *error = NULL; + + space = gimp_color_profile_get_space (profile, + GIMP_COLOR_RENDERING_INTENT_RELATIVE_COLORIMETRIC, + &error); + + if (! space) + { + g_printerr ("%s: failed to create Babl space from profile: %s\n", + G_STRFUNC, error->message); + g_clear_error (&error); + } + g_object_unref (profile); + } + } + + format = babl_format_with_space (default_val->encoding, space); + bpp = babl_format_get_bytes_per_pixel (format); + + if (bpp != default_val->size) + g_printerr ("%s: encoding \"%s\" expects %d bpp but data size is %d bpp.\n", + G_STRFUNC, default_val->encoding, bpp, default_val->size); + else + gegl_color_set_pixel (default_color, format, default_val->data); + } + + return gegl_param_spec_color (name, nick, blurb, default_color, flags); + } + break; + case GP_PARAM_DEF_TYPE_ID: if (! strcmp (param_def->type_name, "GimpParamDisplay")) return gimp_param_spec_display (name, nick, blurb, @@ -365,6 +418,45 @@ _gimp_param_spec_to_gp_param_def (GParamSpec *pspec, gimp_param_spec_rgb_get_default (pspec, ¶m_def->meta.m_color.default_val); } + else if (GEGL_IS_PARAM_SPEC_COLOR (pspec)) + { + GPParamColor *default_val = NULL; + GeglColor *default_color; + + param_def->param_def_type = GP_PARAM_DEF_TYPE_GEGL_COLOR; + /* TODO: no no-alpha support for the time being. */ + param_def->meta.m_color.has_alpha = TRUE; + + default_color = gegl_param_spec_color_get_default (pspec); + if (default_color != NULL) + { + const Babl *format; + + format = gegl_color_get_format (default_color); + default_val = g_new0 (GPParamColor, 1); + + default_val->size = babl_format_get_bytes_per_pixel (format); + default_val->encoding = (gchar *) g_strdup (babl_format_get_encoding (format)); + + default_val->profile_data = NULL; + default_val->profile_size = 0; + if (babl_format_get_space (format) != babl_space ("sRGB")) + { + const char *icc; + int icc_length; + + icc = babl_space_get_icc (babl_format_get_space (format), &icc_length); + + if (icc_length > 0) + { + default_val->profile_data = g_new0 (guint8, icc_length); + memcpy (default_val->profile_data, icc, icc_length); + } + default_val->profile_size = icc_length; + } + } + param_def->meta.m_gegl_color.default_val = default_val; + } else if (pspec_type == GIMP_TYPE_PARAM_IMAGE) { GimpParamSpecImage *ispec = GIMP_PARAM_SPEC_IMAGE (pspec); diff --git a/libgimpbase/gimpprotocol.c b/libgimpbase/gimpprotocol.c index 07a6d9dcbb..c19fd5075f 100644 --- a/libgimpbase/gimpprotocol.c +++ b/libgimpbase/gimpprotocol.c @@ -1226,6 +1226,55 @@ _gp_param_def_read (GIOChannel *channel, return FALSE; break; + case GP_PARAM_DEF_TYPE_GEGL_COLOR: + { + GPParamColor *default_val = NULL; + GBytes *pixel_data = NULL; + GBytes *icc_data = NULL; + gchar *encoding = NULL; + + if (! _gimp_wire_read_int32 (channel, + (guint32 *) ¶m_def->meta.m_gegl_color.has_alpha, 1, + user_data) || + ! _gimp_wire_read_gegl_color (channel, &pixel_data, &icc_data, &encoding, + 1, user_data)) + return FALSE; + + if (pixel_data != NULL) + { + default_val = g_new0 (GPParamColor, 1); + + default_val->encoding = encoding; + default_val->size = g_bytes_get_size (pixel_data); + if (default_val->size > 40) + { + g_free (default_val); + g_free (encoding); + g_bytes_unref (pixel_data); + g_bytes_unref (icc_data); + return FALSE; + } + memcpy (default_val->data, g_bytes_get_data (pixel_data, NULL), + default_val->size); + g_bytes_unref (pixel_data); + if (icc_data) + { + gsize profile_size; + + default_val->profile_data = g_bytes_unref_to_data (icc_data, + &profile_size); + default_val->profile_size = (guint32) profile_size; + } + else + { + default_val->profile_data = NULL; + default_val->profile_size = 0; + } + } + param_def->meta.m_gegl_color.default_val = default_val; + } + break; + case GP_PARAM_DEF_TYPE_ID: if (! _gimp_wire_read_int32 (channel, (guint32 *) ¶m_def->meta.m_id.none_ok, 1, @@ -1274,6 +1323,15 @@ _gp_param_def_destroy (GPParamDef *param_def) g_free (param_def->meta.m_string.default_val); break; + case GP_PARAM_DEF_TYPE_GEGL_COLOR: + if (param_def->meta.m_gegl_color.default_val) + { + g_free (param_def->meta.m_gegl_color.default_val->encoding); + g_free (param_def->meta.m_gegl_color.default_val->profile_data); + } + g_free (param_def->meta.m_gegl_color.default_val); + break; + case GP_PARAM_DEF_TYPE_COLOR: case GP_PARAM_DEF_TYPE_ID: break; @@ -1518,6 +1576,42 @@ _gp_param_def_write (GIOChannel *channel, return FALSE; break; + case GP_PARAM_DEF_TYPE_GEGL_COLOR: + { + GBytes *pixel_data = NULL; + GBytes *icc_data = NULL; + gchar *encoding = ""; + + if (! _gimp_wire_write_int32 (channel, + (guint32 *) ¶m_def->meta.m_gegl_color.has_alpha, 1, + user_data)) + return FALSE; + + if (param_def->meta.m_gegl_color.default_val) + { + pixel_data = g_bytes_new_static (param_def->meta.m_gegl_color.default_val->data, + param_def->meta.m_gegl_color.default_val->size); + icc_data = g_bytes_new_static (param_def->meta.m_gegl_color.default_val->profile_data, + param_def->meta.m_gegl_color.default_val->profile_size); + encoding = param_def->meta.m_gegl_color.default_val->encoding; + } + + if (! _gimp_wire_write_gegl_color (channel, + &pixel_data, + &icc_data, + &encoding, + 1, user_data)) + { + g_bytes_unref (pixel_data); + g_bytes_unref (icc_data); + return FALSE; + } + + g_bytes_unref (pixel_data); + g_bytes_unref (icc_data); + } + break; + case GP_PARAM_DEF_TYPE_ID: if (! _gimp_wire_write_int32 (channel, (guint32 *) ¶m_def->meta.m_id.none_ok, 1, diff --git a/libgimpbase/gimpprotocol.h b/libgimpbase/gimpprotocol.h index eaf2a7a56b..653e2d8450 100644 --- a/libgimpbase/gimpprotocol.h +++ b/libgimpbase/gimpprotocol.h @@ -57,6 +57,7 @@ typedef enum GP_PARAM_DEF_TYPE_FLOAT, GP_PARAM_DEF_TYPE_STRING, GP_PARAM_DEF_TYPE_COLOR, + GP_PARAM_DEF_TYPE_GEGL_COLOR, GP_PARAM_DEF_TYPE_ID, GP_PARAM_DEF_TYPE_ID_ARRAY } GPParamDefType; @@ -79,31 +80,32 @@ typedef enum } GPParamType; -typedef struct _GPConfig GPConfig; -typedef struct _GPTileReq GPTileReq; -typedef struct _GPTileAck GPTileAck; -typedef struct _GPTileData GPTileData; -typedef struct _GPParamDef GPParamDef; -typedef struct _GPParamDefInt GPParamDefInt; -typedef struct _GPParamDefUnit GPParamDefUnit; -typedef struct _GPParamDefEnum GPParamDefEnum; -typedef struct _GPParamDefBoolean GPParamDefBoolean; -typedef struct _GPParamDefFloat GPParamDefFloat; -typedef struct _GPParamDefString GPParamDefString; -typedef struct _GPParamDefChoice GPParamDefChoice; -typedef struct _GPParamStrv GPParamStrv; -typedef struct _GPParamDefColor GPParamDefColor; -typedef struct _GPParamDefID GPParamDefID; -typedef struct _GPParamDefIDArray GPParamDefIDArray; -typedef struct _GPParam GPParam; -typedef struct _GPParamArray GPParamArray; -typedef struct _GPParamIDArray GPParamIDArray; -typedef struct _GPParamColor GPParamColor; -typedef struct _GPParamColorArray GPParamColorArray; -typedef struct _GPProcRun GPProcRun; -typedef struct _GPProcReturn GPProcReturn; -typedef struct _GPProcInstall GPProcInstall; -typedef struct _GPProcUninstall GPProcUninstall; +typedef struct _GPConfig GPConfig; +typedef struct _GPTileReq GPTileReq; +typedef struct _GPTileAck GPTileAck; +typedef struct _GPTileData GPTileData; +typedef struct _GPParamDef GPParamDef; +typedef struct _GPParamDefInt GPParamDefInt; +typedef struct _GPParamDefUnit GPParamDefUnit; +typedef struct _GPParamDefEnum GPParamDefEnum; +typedef struct _GPParamDefBoolean GPParamDefBoolean; +typedef struct _GPParamDefFloat GPParamDefFloat; +typedef struct _GPParamDefString GPParamDefString; +typedef struct _GPParamDefChoice GPParamDefChoice; +typedef struct _GPParamStrv GPParamStrv; +typedef struct _GPParamDefColor GPParamDefColor; +typedef struct _GPParamDefGeglColor GPParamDefGeglColor; +typedef struct _GPParamDefID GPParamDefID; +typedef struct _GPParamDefIDArray GPParamDefIDArray; +typedef struct _GPParam GPParam; +typedef struct _GPParamArray GPParamArray; +typedef struct _GPParamIDArray GPParamIDArray; +typedef struct _GPParamColor GPParamColor; +typedef struct _GPParamColorArray GPParamColorArray; +typedef struct _GPProcRun GPProcRun; +typedef struct _GPProcReturn GPProcReturn; +typedef struct _GPProcInstall GPProcInstall; +typedef struct _GPProcUninstall GPProcUninstall; struct _GPConfig @@ -208,6 +210,12 @@ struct _GPParamDefColor GimpRGB default_val; }; +struct _GPParamDefGeglColor +{ + gint32 has_alpha; + GPParamColor *default_val; +}; + struct _GPParamDefID { gint32 none_ok; @@ -236,16 +244,17 @@ struct _GPParamDef union { - GPParamDefInt m_int; - GPParamDefUnit m_unit; - GPParamDefEnum m_enum; - GPParamDefBoolean m_boolean; - GPParamDefFloat m_float; - GPParamDefString m_string; - GPParamDefColor m_color; - GPParamDefID m_id; - GPParamDefIDArray m_id_array; - GPParamDefChoice m_choice; + GPParamDefInt m_int; + GPParamDefUnit m_unit; + GPParamDefEnum m_enum; + GPParamDefBoolean m_boolean; + GPParamDefFloat m_float; + GPParamDefString m_string; + GPParamDefColor m_color; + GPParamDefGeglColor m_gegl_color; + GPParamDefID m_id; + GPParamDefIDArray m_id_array; + GPParamDefChoice m_choice; } meta; }; diff --git a/libgimpbase/gimpwire.c b/libgimpbase/gimpwire.c index d22036ec2f..1779c57a80 100644 --- a/libgimpbase/gimpwire.c +++ b/libgimpbase/gimpwire.c @@ -513,7 +513,6 @@ _gimp_wire_read_gegl_color (GIOChannel *channel, if (! _gimp_wire_read_int32 (channel, &size, 1, user_data) || - size == 0 || size > 40 || ! _gimp_wire_read_int8 (channel, pixel, size, user_data) || ! _gimp_wire_read_string (channel, &(encoding[i]), 1, user_data) || @@ -522,6 +521,7 @@ _gimp_wire_read_gegl_color (GIOChannel *channel, g_clear_pointer (&(encoding[i]), g_free); return FALSE; } + pixel_data[i] = (size > 0 ? g_bytes_new (pixel, size) : NULL); /* Read space (profile data). */ @@ -539,10 +539,8 @@ _gimp_wire_read_gegl_color (GIOChannel *channel, return FALSE; } - icc_data[i] = g_bytes_new_take (icc, size); + icc_data[i] = g_bytes_new_take (icc, icc_length); } - - pixel_data[i] = g_bytes_new (pixel, size); } return TRUE; @@ -743,19 +741,27 @@ _gimp_wire_write_gegl_color (GIOChannel *channel, for (i = 0; i < count; i++) { - const guint8 *pixel; - gsize bpp; - const guint8 *icc; - gsize icc_length; + const guint8 *pixel = NULL; + gsize bpp = 0; + const guint8 *icc = NULL; + gsize icc_length = 0; - pixel = g_bytes_get_data (pixel_data[i], &bpp); - icc = g_bytes_get_data (pixel_data[i], &icc_length); + if (pixel_data[i]) + pixel = g_bytes_get_data (pixel_data[i], &bpp); + if (icc_data[i]) + icc = g_bytes_get_data (icc_data[i], &icc_length); - if (! _gimp_wire_write_int32 (channel, (const guint32 *) &bpp, 1, user_data) || - ! _gimp_wire_write_int8 (channel, pixel, bpp, user_data) || - ! _gimp_wire_write_string (channel, &(encoding[i]), 1, user_data) || - ! _gimp_wire_write_int32 (channel, (const guint32 *) &icc_length, 1, user_data) || - ! _gimp_wire_write_int8 (channel, icc, icc_length, user_data)) + if (! _gimp_wire_write_int32 (channel, (const guint32 *) &bpp, 1, user_data)) + return FALSE; + + if (bpp > 0 && ! _gimp_wire_write_int8 (channel, pixel, bpp, user_data)) + return FALSE; + + if (! _gimp_wire_write_string (channel, &(encoding[i]), 1, user_data) || + ! _gimp_wire_write_int32 (channel, (const guint32 *) &icc_length, 1, user_data)) + return FALSE; + + if (icc_length > 0 && ! _gimp_wire_write_int8 (channel, icc, icc_length, user_data)) return FALSE; } diff --git a/libgimpconfig/gimpconfig-params.c b/libgimpconfig/gimpconfig-params.c index b6a350eaf1..fa2ebc5610 100644 --- a/libgimpconfig/gimpconfig-params.c +++ b/libgimpconfig/gimpconfig-params.c @@ -291,7 +291,7 @@ gimp_config_param_spec_duplicate (GParamSpec *pspec) copy = gegl_param_spec_color (name, nick, blurb, /*TRUE,*/ color, flags); - g_object_unref (color); + g_clear_object (&color); } else if (G_IS_PARAM_SPEC_PARAM (pspec)) {