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 <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <gegl.h>
|
||||
#include <gegl-plugin.h>
|
||||
#include <gegl-paramspecs.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_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,
|
||||
"name", undo_desc,
|
||||
"icon-name", icon_name,
|
||||
|
|
|
@ -279,6 +279,15 @@ goat_run (GimpProcedure *procedure,
|
|||
gimp_displays_flush ();
|
||||
|
||||
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);
|
||||
|
|
|
@ -262,6 +262,7 @@ EXPORTS
|
|||
gimp_drawable_mask_intersect
|
||||
gimp_drawable_merge_filter
|
||||
gimp_drawable_merge_filters
|
||||
gimp_drawable_merge_new_filter
|
||||
gimp_drawable_merge_shadow
|
||||
gimp_drawable_offset
|
||||
gimp_drawable_posterize
|
||||
|
|
|
@ -512,7 +512,95 @@ gimp_drawable_append_new_filter (GimpDrawable *drawable,
|
|||
}
|
||||
va_end (va_args);
|
||||
|
||||
gimp_drawable_filter_update (filter);
|
||||
gimp_drawable_append_filter (drawable, 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 *name,
|
||||
...) 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
|
||||
|
|
Loading…
Reference in New Issue