app, libgimp, pdb, plug-ins: add a few Script-fu wrapper of libgimp filter API.

In particular (gimp-drawable-filter-configure),
(gimp-drawable-merge-filter) and (gimp-drawable-append-filter) are
proper Script-fu methods.

I had to rename the PDB procedures for the 2 latter because they were
clashing with these wrapper. I had not realized that private PDB
procedures are still visible by Script-fu. This is not so glop. :-/

Right now, it doesn't look so useful compared to the -new- one-liner
variant procedures. But it will make sense when I will add aux input C
procedure wrappers.
This commit is contained in:
Jehan 2024-12-16 23:11:06 +01:00
parent 6480ba2ad6
commit a6392ed84a
6 changed files with 392 additions and 219 deletions

View file

@ -605,7 +605,7 @@ drawable_mask_intersect_invoker (GimpProcedure *procedure,
}
static GimpValueArray *
drawable_append_filter_invoker (GimpProcedure *procedure,
drawable_append_filter_private_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
@ -666,7 +666,7 @@ drawable_append_filter_invoker (GimpProcedure *procedure,
}
static GimpValueArray *
drawable_merge_filter_invoker (GimpProcedure *procedure,
drawable_merge_filter_private_invoker (GimpProcedure *procedure,
Gimp *gimp,
GimpContext *context,
GimpProgress *progress,
@ -1711,16 +1711,17 @@ register_drawable_procs (GimpPDB *pdb)
g_object_unref (procedure);
/*
* gimp-drawable-append-filter
* gimp-drawable-append-filter-private
*/
procedure = gimp_procedure_new (drawable_append_filter_invoker);
procedure = gimp_procedure_new (drawable_append_filter_private_invoker);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-drawable-append-filter");
"gimp-drawable-append-filter-private");
gimp_procedure_set_static_help (procedure,
"Append the specified effect to the top of the list of drawable effects.",
"This procedure adds the specified drawable effect at the top of the effect list of @drawable.\n"
"The @drawable argument must be the same as the one used when you created the effect with [ctor@Gimp.DrawableFilter.new].\n"
"Some effects may be slower than others to render. In order to minimize processing time, it is preferred to customize the operation's arguments as received with [method@Gimp.DrawableFilter.get_config] then sync them to the application with [method@Gimp.DrawableFilter.update] before adding the effect.",
"Some effects may be slower than others to render. In order to minimize processing time, it is preferred to customize the operation's arguments as received with [method@Gimp.DrawableFilter.get_config] then sync them to the application with [method@Gimp.DrawableFilter.update] before adding the effect.\n"
"This function is private and should not be used. Use [method@Gimp.Drawable.append_filter] instead.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Jehan",
@ -1742,16 +1743,17 @@ register_drawable_procs (GimpPDB *pdb)
g_object_unref (procedure);
/*
* gimp-drawable-merge-filter
* gimp-drawable-merge-filter-private
*/
procedure = gimp_procedure_new (drawable_merge_filter_invoker);
procedure = gimp_procedure_new (drawable_merge_filter_private_invoker);
gimp_object_set_static_name (GIMP_OBJECT (procedure),
"gimp-drawable-merge-filter");
"gimp-drawable-merge-filter-private");
gimp_procedure_set_static_help (procedure,
"Apply the specified effect directly to the drawable.",
"This procedure applies the specified drawable effect on @drawable and merge it (therefore before non-destructive effects are computed).\n"
"The @drawable argument must be the same as the one used when you created the effect with [ctor@Gimp.DrawableFilter.new].\n"
"Once this is run, @filter is not valid anymore and you should not try to do anything with it. In particular, you must customize the operation's arguments as received with [method@Gimp.DrawableFilter.get_config] then sync them to the application with [method@Gimp.DrawableFilter.update] before merging the effect.",
"Once this is run, @filter is not valid anymore and you should not try to do anything with it. In particular, you must customize the operation's arguments as received with [method@Gimp.DrawableFilter.get_config] then sync them to the application with [method@Gimp.DrawableFilter.update] before merging the effect.\n"
"This function is private and should not be used. Use [method@Gimp.Drawable.merge_filter] instead.",
NULL);
gimp_procedure_set_static_attribution (procedure,
"Jehan",

View file

@ -461,7 +461,7 @@ gimp_drawable_append_filter (GimpDrawable *drawable,
g_return_if_fail (GIMP_IS_DRAWABLE_FILTER (filter));
gimp_drawable_filter_update (filter);
_gimp_drawable_append_filter (drawable, filter);
_gimp_drawable_append_filter_private (drawable, filter);
}
/**
@ -491,7 +491,7 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
g_return_if_fail (GIMP_IS_DRAWABLE_FILTER (filter));
gimp_drawable_filter_update (filter);
_gimp_drawable_merge_filter (drawable, filter);
_gimp_drawable_merge_filter_private (drawable, filter);
}
/**

View file

@ -677,7 +677,7 @@ gimp_drawable_mask_intersect (GimpDrawable *drawable,
}
/**
* _gimp_drawable_append_filter:
* _gimp_drawable_append_filter_private:
* @drawable: The drawable.
* @filter: The drawable filter to append.
*
@ -694,13 +694,15 @@ gimp_drawable_mask_intersect (GimpDrawable *drawable,
* [method@Gimp.DrawableFilter.get_config] then sync them to the
* application with [method@Gimp.DrawableFilter.update] before adding
* the effect.
* This function is private and should not be used. Use
* [method@Gimp.Drawable.append_filter] instead.
*
* Returns: TRUE on success.
*
* Since: 3.0
**/
gboolean
_gimp_drawable_append_filter (GimpDrawable *drawable,
_gimp_drawable_append_filter_private (GimpDrawable *drawable,
GimpDrawableFilter *filter)
{
GimpValueArray *args;
@ -713,7 +715,7 @@ _gimp_drawable_append_filter (GimpDrawable *drawable,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-drawable-append-filter",
"gimp-drawable-append-filter-private",
args);
gimp_value_array_unref (args);
@ -725,7 +727,7 @@ _gimp_drawable_append_filter (GimpDrawable *drawable,
}
/**
* _gimp_drawable_merge_filter:
* _gimp_drawable_merge_filter_private:
* @drawable: The drawable.
* @filter: The drawable filter to merge.
*
@ -742,13 +744,15 @@ _gimp_drawable_append_filter (GimpDrawable *drawable,
* [method@Gimp.DrawableFilter.get_config] then sync them to the
* application with [method@Gimp.DrawableFilter.update] before merging
* the effect.
* This function is private and should not be used. Use
* [method@Gimp.Drawable.merge_filter] instead.
*
* Returns: TRUE on success.
*
* Since: 3.0
**/
gboolean
_gimp_drawable_merge_filter (GimpDrawable *drawable,
_gimp_drawable_merge_filter_private (GimpDrawable *drawable,
GimpDrawableFilter *filter)
{
GimpValueArray *args;
@ -761,7 +765,7 @@ _gimp_drawable_merge_filter (GimpDrawable *drawable,
G_TYPE_NONE);
return_vals = _gimp_pdb_run_procedure_array (gimp_get_pdb (),
"gimp-drawable-merge-filter",
"gimp-drawable-merge-filter-private",
args);
gimp_value_array_unref (args);

View file

@ -63,9 +63,9 @@ gboolean gimp_drawable_mask_intersect (GimpDrawable
gint *y,
gint *width,
gint *height);
G_GNUC_INTERNAL gboolean _gimp_drawable_append_filter (GimpDrawable *drawable,
G_GNUC_INTERNAL gboolean _gimp_drawable_append_filter_private (GimpDrawable *drawable,
GimpDrawableFilter *filter);
G_GNUC_INTERNAL gboolean _gimp_drawable_merge_filter (GimpDrawable *drawable,
G_GNUC_INTERNAL gboolean _gimp_drawable_merge_filter_private (GimpDrawable *drawable,
GimpDrawableFilter *filter);
GimpDrawableFilter** gimp_drawable_get_filters (GimpDrawable *drawable);
gboolean gimp_drawable_merge_filters (GimpDrawable *drawable);

View file

@ -111,7 +111,7 @@ CODE
);
}
sub drawable_append_filter {
sub drawable_append_filter_private {
$blurb = 'Append the specified effect to the top of the list of drawable effects.';
$help = <<'HELP';
@ -125,6 +125,9 @@ processing time, it is preferred to customize the operation's arguments
as received with [method@Gimp.DrawableFilter.get_config] then sync them
to the application with [method@Gimp.DrawableFilter.update] before
adding the effect.
This function is private and should not be used. Use
[method@Gimp.Drawable.append_filter] instead.
HELP
&jehan_pdb_misc('2024', '3.0');
@ -182,7 +185,7 @@ HELP
CODE
}
sub drawable_merge_filter {
sub drawable_merge_filter_private {
$blurb = 'Apply the specified effect directly to the drawable.';
$help = <<'HELP';
@ -197,6 +200,9 @@ do anything with it. In particular, you must customize the operation's
arguments as received with [method@Gimp.DrawableFilter.get_config] then
sync them to the application with [method@Gimp.DrawableFilter.update]
before merging the effect.
This function is private and should not be used. Use
[method@Gimp.Drawable.merge_filter] instead.
HELP
&jehan_pdb_misc('2024', '3.0');
@ -1225,8 +1231,8 @@ CODE
drawable_get_offsets
drawable_mask_bounds
drawable_mask_intersect
drawable_append_filter
drawable_merge_filter
drawable_append_filter_private
drawable_merge_filter_private
drawable_get_filters
drawable_merge_filters
drawable_merge_shadow

View file

@ -88,10 +88,16 @@ static pointer script_fu_marshal_drawable_create_filter (scheme
const gchar *proc_name,
GimpDrawable **drawable,
GimpDrawableFilter **filter);
static pointer script_fu_marshal_drawable_filter_configure_call (scheme *sc,
pointer a);
static pointer script_fu_marshal_drawable_merge_filter_call (scheme *sc,
pointer a);
static pointer script_fu_marshal_drawable_append_filter_call (scheme *sc,
pointer a);
static pointer script_fu_marshal_drawable_merge_new_filter_call (scheme *sc,
pointer a);
static pointer script_fu_marshal_drawable_append_new_filter_call (scheme *sc,
pointer a);
static pointer script_fu_register_call (scheme *sc,
pointer a);
@ -562,8 +568,11 @@ ts_define_procedure (sc, "load-extension", scm_load_ext);
ts_define_procedure (sc, "-gimp-proc-db-call", script_fu_marshal_procedure_call_permissive);
ts_define_procedure (sc, "--gimp-proc-db-call", script_fu_marshal_procedure_call_deprecated);
ts_define_procedure (sc, "gimp-drawable-merge-new-filter", script_fu_marshal_drawable_merge_filter_call);
ts_define_procedure (sc, "gimp-drawable-append-new-filter", script_fu_marshal_drawable_append_filter_call);
ts_define_procedure (sc, "gimp-drawable-filter-configure", script_fu_marshal_drawable_filter_configure_call);
ts_define_procedure (sc, "gimp-drawable-merge-filter", script_fu_marshal_drawable_merge_filter_call);
ts_define_procedure (sc, "gimp-drawable-append-filter", script_fu_marshal_drawable_append_filter_call);
ts_define_procedure (sc, "gimp-drawable-merge-new-filter", script_fu_marshal_drawable_merge_new_filter_call);
ts_define_procedure (sc, "gimp-drawable-append-new-filter", script_fu_marshal_drawable_append_new_filter_call);
/* Define each PDB procedure as a scheme func.
* Each call passes through one of the wrapper funcs.
@ -1583,6 +1592,74 @@ script_fu_marshal_procedure_call_deprecated (scheme *sc,
return script_fu_marshal_procedure_call (sc, a, TRUE, TRUE);
}
static pointer
script_fu_marshal_drawable_filter_configure (scheme *sc,
pointer a,
const gchar *proc_name,
GimpDrawableFilter *filter)
{
pointer return_val = sc->NIL;
GimpLayerMode mode = GIMP_LAYER_MODE_REPLACE;
gdouble opacity = 1.0;
GimpDrawableFilterConfig *config;
gint arg_index;
gchar error_str[1024];
if (sc->vptr->list_length (sc, a) > 0)
{
mode = sc->vptr->ivalue (sc->vptr->pair_car (a));
a = sc->vptr->pair_cdr (a);
}
if (sc->vptr->list_length (sc, a) > 0)
{
opacity = sc->vptr->rvalue (sc->vptr->pair_car (a));
a = sc->vptr->pair_cdr (a);
}
gimp_drawable_filter_set_opacity (filter, opacity);
gimp_drawable_filter_set_blend_mode (filter, mode);
config = gimp_drawable_filter_get_config (filter);
arg_index = 3;
while (sc->vptr->list_length (sc, a) > 1)
{
gchar *argname;
GParamSpec *arg_spec;
GValue value = G_VALUE_INIT;
argname = g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
arg_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), argname);
if (arg_spec == NULL)
{
g_snprintf (error_str, sizeof (error_str),
"Invalid argument name: %s", argname);
g_free (argname);
gimp_drawable_filter_delete (filter);
return script_error (sc, error_str, 0);
}
g_value_init (&value, arg_spec->value_type);
a = sc->vptr->pair_cdr (a);
return_val = script_fu_marshal_arg_to_value (sc, a, proc_name, arg_index, arg_spec, &value);
if (return_val != sc->NIL)
{
g_value_unset (&value);
g_free (argname);
gimp_drawable_filter_delete (filter);
return return_val;
}
g_object_set_property (G_OBJECT (config), argname, &value);
g_value_unset (&value);
a = sc->vptr->pair_cdr (a);
arg_index += 2;
}
return sc->NIL;
}
static pointer
script_fu_marshal_drawable_create_filter (scheme *sc,
pointer a,
@ -1590,13 +1667,8 @@ script_fu_marshal_drawable_create_filter (scheme *sc,
GimpDrawable **drawable,
GimpDrawableFilter **filter)
{
pointer return_val = sc->NIL;
gchar *operation_name;
gchar *filter_name = NULL;
GimpLayerMode mode = GIMP_LAYER_MODE_REPLACE;
gdouble opacity = 1.0;
GimpDrawableFilterConfig *config;
gint arg_index;
gchar error_str[1024];
if (sc->vptr->list_length (sc, a) < 2)
@ -1605,7 +1677,7 @@ script_fu_marshal_drawable_create_filter (scheme *sc,
"Drawable Filter marshaller was called with missing arguments. "
"The drawable ID, the GEGL operation, filter name, blend mode, opacity "
"and the arguments' names and values it requires (possibly none) must be specified: "
"(%s drawable op title mode arg1 val1 arg2 val2...)",
"(%s drawable op title mode opacity arg1 val1 arg2 val2...)",
proc_name);
return implementation_error (sc, error_str, 0);
}
@ -1615,7 +1687,7 @@ script_fu_marshal_drawable_create_filter (scheme *sc,
"Drawable Filter marshaller was called with an even number of arguments. "
"The drawable ID, the GEGL operation, filter name, blend mode, opacity "
"and the arguments' names and values it requires (possibly none) must be specified: "
"(%s drawable op title mode arg1 val1 arg2 val2...)",
"(%s drawable op title mode opacity arg1 val1 arg2 val2...)",
proc_name);
return implementation_error (sc, error_str, 0);
}
@ -1652,18 +1724,6 @@ script_fu_marshal_drawable_create_filter (scheme *sc,
a = sc->vptr->pair_cdr (a);
}
if (sc->vptr->list_length (sc, a) > 0)
{
mode = sc->vptr->ivalue (sc->vptr->pair_car (a));
a = sc->vptr->pair_cdr (a);
}
if (sc->vptr->list_length (sc, a) > 0)
{
opacity = sc->vptr->rvalue (sc->vptr->pair_car (a));
a = sc->vptr->pair_cdr (a);
}
*filter = gimp_drawable_filter_new (*drawable, operation_name, filter_name);
g_free (filter_name);
@ -1676,52 +1736,153 @@ script_fu_marshal_drawable_create_filter (scheme *sc,
}
g_free (operation_name);
gimp_drawable_filter_set_opacity (*filter, opacity);
gimp_drawable_filter_set_blend_mode (*filter, mode);
return script_fu_marshal_drawable_filter_configure (sc, a, proc_name, *filter);
}
config = gimp_drawable_filter_get_config (*filter);
arg_index = 5;
while (sc->vptr->list_length (sc, a) > 1)
{
gchar *argname;
GParamSpec *arg_spec;
GValue value = G_VALUE_INIT;
static pointer
script_fu_marshal_drawable_filter_configure_call (scheme *sc,
pointer a)
{
GimpDrawableFilter *filter = NULL;
const gchar *proc_name = "gimp-drawable-filter-configure";
gchar error_str[1024];
argname = g_strdup (sc->vptr->string_value (sc->vptr->pair_car (a)));
arg_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), argname);
if (arg_spec == NULL)
if (sc->vptr->list_length (sc, a) < 3)
{
g_snprintf (error_str, sizeof (error_str),
"Invalid argument name: %s", argname);
g_free (argname);
gimp_drawable_filter_delete (*filter);
"Drawable Filter marshaller was called with missing arguments. "
"The filter ID, blend mode, opacity and the arguments' names "
"and values it requires (possibly none) must be specified: "
"(%s mode opacity arg1 val1 arg2 val2...)",
proc_name);
return implementation_error (sc, error_str, 0);
}
else if (sc->vptr->list_length (sc, a) > 3 && sc->vptr->list_length (sc, a) % 2 != 1)
{
g_snprintf (error_str, sizeof (error_str),
"Drawable Filter marshaller was called with an even number of arguments. "
"The drawable ID, the GEGL operation, filter name, blend mode, opacity "
"and the arguments' names and values it requires (possibly none) must be specified: "
"(%s mode opacity arg1 val1 arg2 val2...)",
proc_name);
return implementation_error (sc, error_str, 0);
}
else if (! sc->vptr->is_number (sc->vptr->pair_car (a)))
{
return script_type_error (sc, "numeric", 0, proc_name);
}
else
{
gint id;
id = sc->vptr->ivalue (sc->vptr->pair_car (a));
filter = gimp_drawable_filter_get_by_id (id);
if (filter == NULL || ! GIMP_IS_DRAWABLE_FILTER (filter))
{
g_snprintf (error_str, sizeof (error_str),
"Invalid Drawable Filter ID: %d", id);
return script_error (sc, error_str, 0);
}
g_value_init (&value, arg_spec->value_type);
a = sc->vptr->pair_cdr (a);
}
return_val = script_fu_marshal_arg_to_value (sc, a, proc_name, arg_index, arg_spec, &value);
return script_fu_marshal_drawable_filter_configure (sc, a, proc_name, filter);
}
if (return_val != sc->NIL)
static pointer
script_fu_marshal_drawable_merge_filter_call (scheme *sc,
pointer a)
{
const gchar *proc_name = "gimp-drawable-merge-filter";
GimpItem *item;
GimpDrawableFilter *filter;
gint id;
gchar error_str[1024];
if (sc->vptr->list_length (sc, a) != 2)
{
g_value_unset (&value);
g_free (argname);
gimp_drawable_filter_delete (*filter);
return return_val;
g_snprintf (error_str, sizeof (error_str),
"Drawable Filter marshaller was called with missing arguments. "
"The drawable and filter IDs are required: "
"(%s mode opacity arg1 val1 arg2 val2...)",
proc_name);
return implementation_error (sc, error_str, 0);
}
g_object_set_property (G_OBJECT (config), argname, &value);
g_value_unset (&value);
id = sc->vptr->ivalue (sc->vptr->pair_car (a));
item = gimp_item_get_by_id (id);
if (item == NULL || ! GIMP_IS_DRAWABLE (item))
{
g_snprintf (error_str, sizeof (error_str),
"Invalid Drawable ID: %d", id);
return script_error (sc, error_str, 0);
}
a = sc->vptr->pair_cdr (a);
arg_index += 2;
id = sc->vptr->ivalue (sc->vptr->pair_car (a));
filter = gimp_drawable_filter_get_by_id (id);
if (filter == NULL || ! GIMP_IS_DRAWABLE_FILTER (filter))
{
g_snprintf (error_str, sizeof (error_str),
"Invalid Drawable Filter ID: %d", id);
return script_error (sc, error_str, 0);
}
gimp_drawable_merge_filter (GIMP_DRAWABLE (item), filter);
return sc->NIL;
}
static pointer
script_fu_marshal_drawable_merge_filter_call (scheme *sc,
script_fu_marshal_drawable_append_filter_call (scheme *sc,
pointer a)
{
const gchar *proc_name = "gimp-drawable-append-filter";
GimpItem *item;
GimpDrawableFilter *filter;
gint id;
gchar error_str[1024];
if (sc->vptr->list_length (sc, a) != 2)
{
g_snprintf (error_str, sizeof (error_str),
"Drawable Filter marshaller was called with missing arguments. "
"The drawable and filter IDs are required: "
"(%s mode opacity arg1 val1 arg2 val2...)",
proc_name);
return implementation_error (sc, error_str, 0);
}
id = sc->vptr->ivalue (sc->vptr->pair_car (a));
item = gimp_item_get_by_id (id);
if (item == NULL || ! GIMP_IS_DRAWABLE (item))
{
g_snprintf (error_str, sizeof (error_str),
"Invalid Drawable ID: %d", id);
return script_error (sc, error_str, 0);
}
a = sc->vptr->pair_cdr (a);
id = sc->vptr->ivalue (sc->vptr->pair_car (a));
filter = gimp_drawable_filter_get_by_id (id);
if (filter == NULL || ! GIMP_IS_DRAWABLE_FILTER (filter))
{
g_snprintf (error_str, sizeof (error_str),
"Invalid Drawable Filter ID: %d", id);
return script_error (sc, error_str, 0);
}
gimp_drawable_append_filter (GIMP_DRAWABLE (item), filter);
return sc->NIL;
}
static pointer
script_fu_marshal_drawable_merge_new_filter_call (scheme *sc,
pointer a)
{
GimpDrawable *drawable = NULL;
@ -1740,7 +1901,7 @@ script_fu_marshal_drawable_merge_filter_call (scheme *sc,
}
static pointer
script_fu_marshal_drawable_append_filter_call (scheme *sc,
script_fu_marshal_drawable_append_new_filter_call (scheme *sc,
pointer a)
{
GimpDrawable *drawable = NULL;