mirror of https://github.com/GNOME/gimp.git
app, extensions, libgimp: new convenient function gimp_drawable_merge_new_filter().
Also adding an example of using it in the C goat exercise, though I leave it commented out because showing code for direct GEGL usage is also of interest. As a side update, I am adding proper support of the NULL or empty string value for the filter name. In this case, the default human-readable title of the operation will be used instead.
This commit is contained in:
parent
0223694583
commit
58b11d9d98
|
@ -30,6 +30,7 @@
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||||
#include <gegl.h>
|
#include <gegl.h>
|
||||||
|
#include <gegl-plugin.h>
|
||||||
#include <gegl-paramspecs.h>
|
#include <gegl-paramspecs.h>
|
||||||
|
|
||||||
#include "libgimpbase/gimpbase.h"
|
#include "libgimpbase/gimpbase.h"
|
||||||
|
@ -307,6 +308,16 @@ gimp_drawable_filter_new (GimpDrawable *drawable,
|
||||||
g_return_val_if_fail (GEGL_IS_NODE (operation), NULL);
|
g_return_val_if_fail (GEGL_IS_NODE (operation), NULL);
|
||||||
g_return_val_if_fail (gegl_node_has_pad (operation, "output"), NULL);
|
g_return_val_if_fail (gegl_node_has_pad (operation, "output"), NULL);
|
||||||
|
|
||||||
|
if (undo_desc == NULL || strlen (undo_desc) == 0)
|
||||||
|
{
|
||||||
|
GeglOperation *op;
|
||||||
|
GeglOperationClass *opclass;
|
||||||
|
|
||||||
|
op = gegl_node_get_gegl_operation (operation);
|
||||||
|
opclass = GEGL_OPERATION_GET_CLASS (op);
|
||||||
|
undo_desc = gegl_operation_class_get_key (opclass, "title");
|
||||||
|
}
|
||||||
|
|
||||||
filter = g_object_new (GIMP_TYPE_DRAWABLE_FILTER,
|
filter = g_object_new (GIMP_TYPE_DRAWABLE_FILTER,
|
||||||
"name", undo_desc,
|
"name", undo_desc,
|
||||||
"icon-name", icon_name,
|
"icon-name", icon_name,
|
||||||
|
|
|
@ -279,6 +279,15 @@ goat_run (GimpProcedure *procedure,
|
||||||
gimp_displays_flush ();
|
gimp_displays_flush ();
|
||||||
|
|
||||||
gegl_exit ();
|
gegl_exit ();
|
||||||
|
#if 0
|
||||||
|
/* Above is an example of using GEGL API directly within the
|
||||||
|
* plug-in process. Below is a variant using drawable filters. The
|
||||||
|
* operation rendering is done core process side.
|
||||||
|
*/
|
||||||
|
gimp_drawable_merge_new_filter (drawable, "gegl:invert", NULL,
|
||||||
|
GIMP_LAYER_MODE_REPLACE, 1.0,
|
||||||
|
NULL);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return gimp_procedure_new_return_values (procedure, status, NULL);
|
return gimp_procedure_new_return_values (procedure, status, NULL);
|
||||||
|
|
|
@ -262,6 +262,7 @@ EXPORTS
|
||||||
gimp_drawable_mask_intersect
|
gimp_drawable_mask_intersect
|
||||||
gimp_drawable_merge_filter
|
gimp_drawable_merge_filter
|
||||||
gimp_drawable_merge_filters
|
gimp_drawable_merge_filters
|
||||||
|
gimp_drawable_merge_new_filter
|
||||||
gimp_drawable_merge_shadow
|
gimp_drawable_merge_shadow
|
||||||
gimp_drawable_offset
|
gimp_drawable_offset
|
||||||
gimp_drawable_posterize
|
gimp_drawable_posterize
|
||||||
|
|
|
@ -512,7 +512,95 @@ gimp_drawable_append_new_filter (GimpDrawable *drawable,
|
||||||
}
|
}
|
||||||
va_end (va_args);
|
va_end (va_args);
|
||||||
|
|
||||||
|
gimp_drawable_filter_update (filter);
|
||||||
gimp_drawable_append_filter (drawable, filter);
|
gimp_drawable_append_filter (drawable, filter);
|
||||||
|
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gimp_drawable_merge_new_filter: (skip)
|
||||||
|
* @drawable: The #GimpDrawable.
|
||||||
|
* @operation_name: The GEGL operation's name.
|
||||||
|
* @name: The effect name which will show in undo step.
|
||||||
|
* @mode: The blend mode.
|
||||||
|
* @opacity: The opacity from 0.0 (transparent) to 1.0 (opaque).
|
||||||
|
* @...: a %NULL-terminated list of operation argument names
|
||||||
|
* and values.
|
||||||
|
*
|
||||||
|
* Utility function which combines [ctor@Gimp.DrawableFilter.new]
|
||||||
|
* followed by setting arguments for the
|
||||||
|
* [class@Gimp.DrawableFilterConfig] returned by
|
||||||
|
* [method@Gimp.DrawableFilter.get_config], and finally applying the
|
||||||
|
* effect to @drawable with [method@Gimp.Drawable.merge_filter]
|
||||||
|
*
|
||||||
|
* The variable arguments are couples of an argument name followed by a
|
||||||
|
* value, NULL-terminated, such as:
|
||||||
|
*
|
||||||
|
* ```C
|
||||||
|
* filter = gimp_drawable_merge_new_filter (drawable,
|
||||||
|
* GIMP_LAYER_MODE_REPLACE, 1.0,
|
||||||
|
* "gegl:gaussian-blur", "My Gaussian Blur",
|
||||||
|
* "std-dev-x", 2.5,
|
||||||
|
* "std-dev-y", 2.5,
|
||||||
|
* "abyss-policy", "clamp",
|
||||||
|
* NULL);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
gimp_drawable_merge_new_filter (GimpDrawable *drawable,
|
||||||
|
const gchar *operation_name,
|
||||||
|
const gchar *name,
|
||||||
|
GimpLayerMode mode,
|
||||||
|
gdouble opacity,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
GimpDrawableFilter *filter;
|
||||||
|
GimpDrawableFilterConfig *config;
|
||||||
|
const gchar *arg_name;
|
||||||
|
va_list va_args;
|
||||||
|
|
||||||
|
g_return_if_fail (opacity >= 0.0 && opacity <= 1.0);
|
||||||
|
|
||||||
|
filter = gimp_drawable_filter_new (drawable, operation_name, name);
|
||||||
|
|
||||||
|
g_return_if_fail (filter != NULL);
|
||||||
|
|
||||||
|
config = gimp_drawable_filter_get_config (filter);
|
||||||
|
|
||||||
|
va_start (va_args, opacity);
|
||||||
|
while ((arg_name = va_arg (va_args, const gchar *)))
|
||||||
|
{
|
||||||
|
GParamSpec *pspec;
|
||||||
|
gchar *error = NULL;
|
||||||
|
GValue value = G_VALUE_INIT;
|
||||||
|
|
||||||
|
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (config), arg_name);
|
||||||
|
if (pspec == NULL)
|
||||||
|
{
|
||||||
|
g_warning ("%s: %s has no property named '%s'",
|
||||||
|
G_STRFUNC,
|
||||||
|
g_type_name (G_TYPE_FROM_INSTANCE (config)),
|
||||||
|
arg_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_value_init (&value, pspec->value_type);
|
||||||
|
G_VALUE_COLLECT (&value, va_args, G_VALUE_NOCOPY_CONTENTS, &error);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
g_warning ("%s: %s", G_STRFUNC, error);
|
||||||
|
g_free (error);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_set_property (G_OBJECT (config), arg_name, &value);
|
||||||
|
g_value_unset (&value);
|
||||||
|
}
|
||||||
|
va_end (va_args);
|
||||||
|
|
||||||
|
gimp_drawable_filter_set_blend_mode (filter, mode);
|
||||||
|
gimp_drawable_filter_set_opacity (filter, opacity);
|
||||||
|
gimp_drawable_filter_update (filter);
|
||||||
|
gimp_drawable_merge_filter (drawable, filter);
|
||||||
|
}
|
||||||
|
|
|
@ -97,6 +97,12 @@ GimpDrawableFilter * gimp_drawable_append_new_filter (GimpDrawable *drawab
|
||||||
const gchar *operation_name,
|
const gchar *operation_name,
|
||||||
const gchar *name,
|
const gchar *name,
|
||||||
...) G_GNUC_NULL_TERMINATED;
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
void gimp_drawable_merge_new_filter (GimpDrawable *drawable,
|
||||||
|
const gchar *operation_name,
|
||||||
|
const gchar *name,
|
||||||
|
GimpLayerMode mode,
|
||||||
|
gdouble opacity,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
Loading…
Reference in New Issue