Blame gegl/operation/gegl-operation.c

Packit Service 2781ba
/* This file is part of GEGL
Packit Service 2781ba
 *
Packit Service 2781ba
 * GEGL is free software; you can redistribute it and/or
Packit Service 2781ba
 * modify it under the terms of the GNU Lesser General Public
Packit Service 2781ba
 * License as published by the Free Software Foundation; either
Packit Service 2781ba
 * version 3 of the License, or (at your option) any later version.
Packit Service 2781ba
 *
Packit Service 2781ba
 * GEGL is distributed in the hope that it will be useful,
Packit Service 2781ba
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 2781ba
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 2781ba
 * Lesser General Public License for more details.
Packit Service 2781ba
 *
Packit Service 2781ba
 * You should have received a copy of the GNU Lesser General Public
Packit Service 2781ba
 * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
Packit Service 2781ba
 *
Packit Service 2781ba
 * Copyright 2003      Calvin Williamson
Packit Service 2781ba
 *           2005-2008 Øyvind Kolås
Packit Service 2781ba
 */
Packit Service 2781ba
Packit Service 2781ba
#include "config.h"
Packit Service 2781ba
Packit Service 2781ba
#include <glib-object.h>
Packit Service 2781ba
#include <string.h>
Packit Service 2781ba
Packit Service 2781ba
#include "gegl.h"
Packit Service 2781ba
#include "gegl-types-internal.h"
Packit Service 2781ba
#include "gegl-operation.h"
Packit Service 2781ba
#include "gegl-utils.h"
Packit Service 2781ba
#include "graph/gegl-node.h"
Packit Service 2781ba
#include "graph/gegl-connection.h"
Packit Service 2781ba
#include "graph/gegl-pad.h"
Packit Service 2781ba
#include "buffer/gegl-region.h"
Packit Service 2781ba
#include "buffer/gegl-buffer.h"
Packit Service 2781ba
#include "gegl-operations.h"
Packit Service 2781ba
Packit Service 2781ba
static void         attach                    (GeglOperation       *self);
Packit Service 2781ba
Packit Service 2781ba
static GeglRectangle get_bounding_box          (GeglOperation       *self);
Packit Service 2781ba
static GeglRectangle get_invalidated_by_change (GeglOperation       *self,
Packit Service 2781ba
                                                const gchar         *input_pad,
Packit Service 2781ba
                                                const GeglRectangle *input_region);
Packit Service 2781ba
static GeglRectangle get_required_for_output   (GeglOperation       *self,
Packit Service 2781ba
                                                const gchar         *input_pad,
Packit Service 2781ba
                                                const GeglRectangle *region);
Packit Service 2781ba
Packit Service 2781ba
static void gegl_operation_class_init     (GeglOperationClass *klass);
Packit Service 2781ba
static void gegl_operation_base_init      (GeglOperationClass *klass);
Packit Service 2781ba
static void gegl_operation_init           (GeglOperation      *self);
Packit Service 2781ba
Packit Service 2781ba
GType
Packit Service 2781ba
gegl_operation_get_type (void)
Packit Service 2781ba
{
Packit Service 2781ba
  static GType type = 0;
Packit Service 2781ba
Packit Service 2781ba
  if (! type)
Packit Service 2781ba
    {
Packit Service 2781ba
      const GTypeInfo info =
Packit Service 2781ba
      {
Packit Service 2781ba
        sizeof (GeglOperationClass),
Packit Service 2781ba
        (GBaseInitFunc)      gegl_operation_base_init,
Packit Service 2781ba
        (GBaseFinalizeFunc) NULL,
Packit Service 2781ba
        (GClassInitFunc)     gegl_operation_class_init,
Packit Service 2781ba
        NULL,           /* class_finalize */
Packit Service 2781ba
        NULL,           /* class_data */
Packit Service 2781ba
        sizeof (GeglOperation),
Packit Service 2781ba
        0,              /* n_preallocs */
Packit Service 2781ba
        (GInstanceInitFunc) gegl_operation_init,
Packit Service 2781ba
      };
Packit Service 2781ba
Packit Service 2781ba
      type = g_type_register_static (G_TYPE_OBJECT,
Packit Service 2781ba
                                     "GeglOperation",
Packit Service 2781ba
                                     &info, 0);
Packit Service 2781ba
    }
Packit Service 2781ba
  return type;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
gegl_operation_class_init (GeglOperationClass *klass)
Packit Service 2781ba
{
Packit Service 2781ba
  klass->name                      = NULL;  /* an operation class with
Packit Service 2781ba
                                             * name == NULL is not
Packit Service 2781ba
                                             * included when doing
Packit Service 2781ba
                                             * operation lookup by
Packit Service 2781ba
                                             * name
Packit Service 2781ba
                                             */
Packit Service 2781ba
  klass->compat_name               = NULL;
Packit Service 2781ba
  klass->attach                    = attach;
Packit Service 2781ba
  klass->prepare                   = NULL;
Packit Service 2781ba
  klass->no_cache                  = FALSE;
Packit Service 2781ba
  klass->opencl_support            = FALSE;
Packit Service 2781ba
  klass->get_bounding_box          = get_bounding_box;
Packit Service 2781ba
  klass->get_invalidated_by_change = get_invalidated_by_change;
Packit Service 2781ba
  klass->get_required_for_output   = get_required_for_output;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
gegl_operation_base_init  (GeglOperationClass *klass)
Packit Service 2781ba
{
Packit Service 2781ba
  /* XXX: leaked for now, should replace G_DEFINE_TYPE with the expanded one */
Packit Service 2781ba
  klass->keys = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
gegl_operation_init (GeglOperation *self)
Packit Service 2781ba
{
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
/**
Packit Service 2781ba
 * gegl_operation_create_pad:
Packit Service 2781ba
 * @self: a #GeglOperation.
Packit Service 2781ba
 * @param_spec:
Packit Service 2781ba
 *
Packit Service 2781ba
 * Create a property.
Packit Service 2781ba
 **/
Packit Service 2781ba
void
Packit Service 2781ba
gegl_operation_create_pad (GeglOperation *self,
Packit Service 2781ba
                           GParamSpec    *param_spec)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglPad *pad;
Packit Service 2781ba
Packit Service 2781ba
  g_return_if_fail (GEGL_IS_OPERATION (self));
Packit Service 2781ba
  g_return_if_fail (param_spec != NULL);
Packit Service 2781ba
Packit Service 2781ba
  if (!self->node)
Packit Service 2781ba
    {
Packit Service 2781ba
      g_warning ("%s: aborting, no associated node. "
Packit Service 2781ba
                 "This method should only be called after the operation is "
Packit Service 2781ba
                 "associated with a node.", G_STRFUNC);
Packit Service 2781ba
      return;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  pad = g_object_new (GEGL_TYPE_PAD, NULL);
Packit Service 2781ba
  gegl_pad_set_param_spec (pad, param_spec);
Packit Service 2781ba
  gegl_pad_set_node (pad, self->node);
Packit Service 2781ba
  gegl_node_add_pad (self->node, pad);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void gegl_node_emit_computed (GeglNode *node, const GeglRectangle *rect);
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
gboolean
Packit Service 2781ba
gegl_operation_process (GeglOperation        *operation,
Packit Service 2781ba
                        GeglOperationContext *context,
Packit Service 2781ba
                        const gchar          *output_pad,
Packit Service 2781ba
                        const GeglRectangle  *result,
Packit Service 2781ba
                        gint                  level)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglOperationClass  *klass;
Packit Service 2781ba
Packit Service 2781ba
  g_return_val_if_fail (GEGL_IS_OPERATION (operation), FALSE);
Packit Service 2781ba
Packit Service 2781ba
  klass = GEGL_OPERATION_GET_CLASS (operation);
Packit Service 2781ba
Packit Service 2781ba
  if (!strcmp (output_pad, "output") &&
Packit Service 2781ba
      (result->width == 0 || result->height == 0))
Packit Service 2781ba
    {
Packit Service 2781ba
      GeglBuffer *output = gegl_buffer_new (NULL, NULL);
Packit Service 2781ba
      g_warning ("%s Eeek: processing 0px rectangle", G_STRLOC);
Packit Service 2781ba
      /* when this case is hit.. we've done something bad.. */
Packit Service 2781ba
      gegl_operation_context_take_object (context, "output", G_OBJECT (output));
Packit Service 2781ba
      return TRUE;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  return klass->process (operation, context, output_pad, result, level);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
/* Calls an extending class' get_bound_box method if defined otherwise
Packit Service 2781ba
 * just returns a zero-initiliased bouding box
Packit Service 2781ba
 */
Packit Service 2781ba
GeglRectangle
Packit Service 2781ba
gegl_operation_get_bounding_box (GeglOperation *self)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglOperationClass *klass = GEGL_OPERATION_GET_CLASS (self);
Packit Service 2781ba
  GeglRectangle       rect  = { 0, 0, 0, 0 };
Packit Service 2781ba
Packit Service 2781ba
  if (klass->get_bounding_box)
Packit Service 2781ba
    return klass->get_bounding_box (self);
Packit Service 2781ba
Packit Service 2781ba
  return rect;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
GeglRectangle
Packit Service 2781ba
gegl_operation_get_invalidated_by_change (GeglOperation        *self,
Packit Service 2781ba
                                          const gchar         *input_pad,
Packit Service 2781ba
                                          const GeglRectangle *input_region)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglOperationClass *klass;
Packit Service 2781ba
  GeglRectangle       retval = { 0, };
Packit Service 2781ba
Packit Service 2781ba
  g_return_val_if_fail (GEGL_IS_OPERATION (self), retval);
Packit Service 2781ba
  g_return_val_if_fail (input_pad != NULL, retval);
Packit Service 2781ba
  g_return_val_if_fail (input_region != NULL, retval);
Packit Service 2781ba
Packit Service 2781ba
  klass = GEGL_OPERATION_GET_CLASS (self);
Packit Service 2781ba
Packit Service 2781ba
  if (input_region->width  == 0 ||
Packit Service 2781ba
      input_region->height == 0)
Packit Service 2781ba
    return *input_region;
Packit Service 2781ba
Packit Service 2781ba
  if (klass->get_invalidated_by_change)
Packit Service 2781ba
    return klass->get_invalidated_by_change (self, input_pad, input_region);
Packit Service 2781ba
Packit Service 2781ba
  return *input_region;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static GeglRectangle
Packit Service 2781ba
get_required_for_output (GeglOperation        *operation,
Packit Service 2781ba
                         const gchar         *input_pad,
Packit Service 2781ba
                         const GeglRectangle *roi)
Packit Service 2781ba
{
Packit Service 2781ba
  if (operation->node->is_graph)
Packit Service 2781ba
    {
Packit Service 2781ba
      return gegl_operation_get_required_for_output (operation, input_pad, roi);
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  return *roi;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
GeglRectangle
Packit Service 2781ba
gegl_operation_get_required_for_output (GeglOperation        *operation,
Packit Service 2781ba
                                        const gchar         *input_pad,
Packit Service 2781ba
                                        const GeglRectangle *roi)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglOperationClass *klass = GEGL_OPERATION_GET_CLASS (operation);
Packit Service 2781ba
Packit Service 2781ba
  if (roi->width == 0 ||
Packit Service 2781ba
      roi->height == 0)
Packit Service 2781ba
    return *roi;
Packit Service 2781ba
Packit Service 2781ba
  g_assert (klass->get_required_for_output);
Packit Service 2781ba
Packit Service 2781ba
  return klass->get_required_for_output (operation, input_pad, roi);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
GeglRectangle
Packit Service 2781ba
gegl_operation_get_cached_region (GeglOperation        *operation,
Packit Service 2781ba
                                  const GeglRectangle *roi)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglOperationClass *klass = GEGL_OPERATION_GET_CLASS (operation);
Packit Service 2781ba
Packit Service 2781ba
  if (!klass->get_cached_region)
Packit Service 2781ba
    {
Packit Service 2781ba
      return *roi;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  return klass->get_cached_region (operation, roi);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static void
Packit Service 2781ba
attach (GeglOperation *self)
Packit Service 2781ba
{
Packit Service 2781ba
  g_warning ("kilroy was at What The Hack (%p, %s)\n", (void *) self,
Packit Service 2781ba
             G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (self)));
Packit Service 2781ba
  return;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_operation_attach (GeglOperation *self,
Packit Service 2781ba
                       GeglNode      *node)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglOperationClass *klass;
Packit Service 2781ba
Packit Service 2781ba
  g_return_if_fail (GEGL_IS_OPERATION (self));
Packit Service 2781ba
  g_return_if_fail (GEGL_IS_NODE (node));
Packit Service 2781ba
Packit Service 2781ba
  klass = GEGL_OPERATION_GET_CLASS (self);
Packit Service 2781ba
Packit Service 2781ba
  g_assert (klass->attach);
Packit Service 2781ba
  self->node = node;
Packit Service 2781ba
  klass->attach (self);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
/* Calls the prepare function on the operation that extends this base class */
Packit Service 2781ba
void
Packit Service 2781ba
gegl_operation_prepare (GeglOperation *self)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglOperationClass *klass;
Packit Service 2781ba
Packit Service 2781ba
  g_return_if_fail (GEGL_IS_OPERATION (self));
Packit Service 2781ba
Packit Service 2781ba
  klass = GEGL_OPERATION_GET_CLASS (self);
Packit Service 2781ba
Packit Service 2781ba
  if (klass->prepare)
Packit Service 2781ba
    klass->prepare (self);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
GeglNode *
Packit Service 2781ba
gegl_operation_get_source_node (GeglOperation *operation,
Packit Service 2781ba
                                const gchar   *input_pad_name)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglPad *pad;
Packit Service 2781ba
Packit Service 2781ba
  g_assert (operation &&
Packit Service 2781ba
            operation->node &&
Packit Service 2781ba
            input_pad_name);
Packit Service 2781ba
  pad = gegl_node_get_pad (operation->node, input_pad_name);
Packit Service 2781ba
Packit Service 2781ba
  if (!pad)
Packit Service 2781ba
    return NULL;
Packit Service 2781ba
Packit Service 2781ba
  pad = gegl_pad_get_connected_to (pad);
Packit Service 2781ba
Packit Service 2781ba
  if (!pad)
Packit Service 2781ba
    return NULL;
Packit Service 2781ba
Packit Service 2781ba
  g_assert (gegl_pad_get_node (pad));
Packit Service 2781ba
Packit Service 2781ba
  return gegl_pad_get_node (pad);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
GeglRectangle *
Packit Service 2781ba
gegl_operation_source_get_bounding_box (GeglOperation  *operation,
Packit Service 2781ba
                                        const gchar   *input_pad_name)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglNode *node = gegl_operation_get_source_node (operation, input_pad_name);
Packit Service 2781ba
Packit Service 2781ba
  if (node)
Packit Service 2781ba
    {
Packit Service 2781ba
      GeglRectangle *ret;
Packit Service 2781ba
      g_mutex_lock (node->mutex);
Packit Service 2781ba
      ret = &node->have_rect;
Packit Service 2781ba
      g_mutex_unlock (node->mutex);
Packit Service 2781ba
      return ret;
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  return NULL;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static GeglRectangle
Packit Service 2781ba
get_bounding_box (GeglOperation *self)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglRectangle rect = { 0, 0, 0, 0 };
Packit Service 2781ba
Packit Service 2781ba
  if (self->node->is_graph)
Packit Service 2781ba
    {
Packit Service 2781ba
      GeglOperation *operation;
Packit Service 2781ba
Packit Service 2781ba
      operation = gegl_node_get_output_proxy (self->node, "output")->operation;
Packit Service 2781ba
      rect      = gegl_operation_get_bounding_box (operation);
Packit Service 2781ba
    }
Packit Service 2781ba
  else
Packit Service 2781ba
    {
Packit Service 2781ba
      g_warning ("Operation '%s' has no get_bounding_box() method",
Packit Service 2781ba
                 G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (self)));
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  return rect;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
static GeglRectangle
Packit Service 2781ba
get_invalidated_by_change (GeglOperation        *self,
Packit Service 2781ba
                           const gchar         *input_pad,
Packit Service 2781ba
                           const GeglRectangle *input_region)
Packit Service 2781ba
{
Packit Service 2781ba
#if 0
Packit Service 2781ba
  /* FIXME: this seems to sometimes go into an infinite loop, the
Packit Service 2781ba
   * current workaround of passing the rectangle straight through
Packit Service 2781ba
   * isn't even true for unsharp-mask/drop-shadow/difference of gaussians,
Packit Service 2781ba
   * but it stops a crasher bug.
Packit Service 2781ba
   *
Packit Service 2781ba
   * This needs to be revisited as part of the core processing revisit
Packit Service 2781ba
   * (perhaps together with a meta-op framework revwrite).
Packit Service 2781ba
   */
Packit Service 2781ba
  if (self->node->is_graph)
Packit Service 2781ba
    {
Packit Service 2781ba
      return gegl_operation_get_invalidated_by_change (
Packit Service 2781ba
               gegl_node_get_output_proxy (self->node, "output")->operation,
Packit Service 2781ba
               input_pad,
Packit Service 2781ba
               input_region);
Packit Service 2781ba
    }
Packit Service 2781ba
#endif
Packit Service 2781ba
  return *input_region;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
/* returns a freshly allocated list of the properties of the object, does not list
Packit Service 2781ba
 * the regular gobject properties of GeglNode ('name' and 'operation') */
Packit Service 2781ba
GParamSpec **
Packit Service 2781ba
gegl_operation_list_properties (const gchar *operation_type,
Packit Service 2781ba
                                guint       *n_properties_p)
Packit Service 2781ba
{
Packit Service 2781ba
  GParamSpec  **pspecs;
Packit Service 2781ba
  GType         type;
Packit Service 2781ba
  GObjectClass *klass;
Packit Service 2781ba
Packit Service 2781ba
  type = gegl_operation_gtype_from_name (operation_type);
Packit Service 2781ba
  if (!type)
Packit Service 2781ba
    {
Packit Service 2781ba
      if (n_properties_p)
Packit Service 2781ba
        *n_properties_p = 0;
Packit Service 2781ba
      return NULL;
Packit Service 2781ba
    }
Packit Service 2781ba
  klass  = g_type_class_ref (type);
Packit Service 2781ba
  pspecs = g_object_class_list_properties (klass, n_properties_p);
Packit Service 2781ba
  g_type_class_unref (klass);
Packit Service 2781ba
  return pspecs;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
GeglNode *
Packit Service 2781ba
gegl_operation_detect (GeglOperation *operation,
Packit Service 2781ba
                       gint           x,
Packit Service 2781ba
                       gint           y)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglNode           *node = NULL;
Packit Service 2781ba
  GeglOperationClass *klass;
Packit Service 2781ba
Packit Service 2781ba
  if (!operation)
Packit Service 2781ba
    return NULL;
Packit Service 2781ba
Packit Service 2781ba
  g_return_val_if_fail (GEGL_IS_OPERATION (operation), NULL);
Packit Service 2781ba
  node = operation->node;
Packit Service 2781ba
Packit Service 2781ba
  klass = GEGL_OPERATION_GET_CLASS (operation);
Packit Service 2781ba
Packit Service 2781ba
  if (klass->detect)
Packit Service 2781ba
    {
Packit Service 2781ba
      return klass->detect (operation, x, y);
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  if (x >= node->have_rect.x &&
Packit Service 2781ba
      x < node->have_rect.x + node->have_rect.width &&
Packit Service 2781ba
      y >= node->have_rect.y &&
Packit Service 2781ba
      y < node->have_rect.y + node->have_rect.height)
Packit Service 2781ba
    {
Packit Service 2781ba
      return node;
Packit Service 2781ba
    }
Packit Service 2781ba
  return NULL;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_operation_set_format (GeglOperation *self,
Packit Service 2781ba
                           const gchar   *pad_name,
Packit Service 2781ba
                           const Babl    *format)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglPad *pad;
Packit Service 2781ba
Packit Service 2781ba
  g_return_if_fail (GEGL_IS_OPERATION (self));
Packit Service 2781ba
  g_return_if_fail (pad_name != NULL);
Packit Service 2781ba
Packit Service 2781ba
  pad = gegl_node_get_pad (self->node, pad_name);
Packit Service 2781ba
Packit Service 2781ba
  g_return_if_fail (pad != NULL);
Packit Service 2781ba
Packit Service 2781ba
  pad->format = format;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
const Babl *
Packit Service 2781ba
gegl_operation_get_format (GeglOperation *self,
Packit Service 2781ba
                           const gchar   *pad_name)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglPad *pad;
Packit Service 2781ba
Packit Service 2781ba
  g_return_val_if_fail (GEGL_IS_OPERATION (self), NULL);
Packit Service 2781ba
  g_return_val_if_fail (pad_name != NULL, NULL);
Packit Service 2781ba
Packit Service 2781ba
  pad = gegl_node_get_pad (self->node, pad_name);
Packit Service 2781ba
Packit Service 2781ba
  if (pad == NULL || pad->format == NULL)
Packit Service 2781ba
    {
Packit Service 2781ba
      g_warning ("%s: returns NULL", G_STRFUNC);
Packit Service 2781ba
    }
Packit Service 2781ba
  g_return_val_if_fail (pad != NULL, NULL);
Packit Service 2781ba
Packit Service 2781ba
  return pad->format;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
const gchar *
Packit Service 2781ba
gegl_operation_get_name (GeglOperation *operation)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglOperationClass *klass;
Packit Service 2781ba
Packit Service 2781ba
  g_return_val_if_fail (GEGL_IS_OPERATION (operation), NULL);
Packit Service 2781ba
Packit Service 2781ba
  klass = GEGL_OPERATION_GET_CLASS (operation);
Packit Service 2781ba
Packit Service 2781ba
  return klass->name;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_operation_invalidate (GeglOperation       *operation,
Packit Service 2781ba
                           const GeglRectangle *roi,
Packit Service 2781ba
                           gboolean             clear_cache)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglNode *node = NULL;
Packit Service 2781ba
Packit Service 2781ba
  if (!operation)
Packit Service 2781ba
    return;
Packit Service 2781ba
Packit Service 2781ba
  g_return_if_fail (GEGL_IS_OPERATION (operation));
Packit Service 2781ba
  node = operation->node;
Packit Service 2781ba
Packit Service 2781ba
  gegl_node_invalidated (node, roi, TRUE);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
gchar **
Packit Service 2781ba
gegl_operation_list_keys (const gchar *operation_name,
Packit Service 2781ba
                          guint       *n_keys)
Packit Service 2781ba
{
Packit Service 2781ba
  GType         type;
Packit Service 2781ba
  GObjectClass *klass;
Packit Service 2781ba
  GList        *list, *l;
Packit Service 2781ba
  gchar       **ret;
Packit Service 2781ba
  int count;
Packit Service 2781ba
  int i;
Packit Service 2781ba
  type = gegl_operation_gtype_from_name (operation_name);
Packit Service 2781ba
  if (!type)
Packit Service 2781ba
    {
Packit Service 2781ba
      if (n_keys)
Packit Service 2781ba
        *n_keys = 0;
Packit Service 2781ba
      return NULL;
Packit Service 2781ba
    }
Packit Service 2781ba
  klass  = g_type_class_ref (type);
Packit Service 2781ba
  count = g_hash_table_size (GEGL_OPERATION_CLASS (klass)->keys);
Packit Service 2781ba
  ret = g_malloc0 (sizeof (gpointer) * (count + 1));
Packit Service 2781ba
  list = g_hash_table_get_keys (GEGL_OPERATION_CLASS (klass)->keys);
Packit Service 2781ba
  for (i = 0, l = list; l; l = l->next)
Packit Service 2781ba
    {
Packit Service 2781ba
      ret[i] = l->data;
Packit Service 2781ba
    }
Packit Service 2781ba
  g_list_free (list);
Packit Service 2781ba
  if (n_keys)
Packit Service 2781ba
    *n_keys = count;
Packit Service 2781ba
  g_type_class_unref (klass);
Packit Service 2781ba
  return ret;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_operation_class_set_key (GeglOperationClass *klass,
Packit Service 2781ba
                              const gchar        *key_name,
Packit Service 2781ba
                              const gchar        *key_value)
Packit Service 2781ba
{
Packit Service 2781ba
  if (!key_value)
Packit Service 2781ba
    {
Packit Service 2781ba
      g_hash_table_remove (klass->keys, key_name);
Packit Service 2781ba
      return;
Packit Service 2781ba
    }
Packit Service 2781ba
  else
Packit Service 2781ba
    {
Packit Service 2781ba
      key_value = g_strdup (key_value);
Packit Service 2781ba
      g_hash_table_insert (klass->keys, g_strdup (key_name),
Packit Service 2781ba
                           (void*)key_value);
Packit Service 2781ba
    }
Packit Service 2781ba
  if (!strcmp (key_name, "name"))
Packit Service 2781ba
    {
Packit Service 2781ba
      klass->name = key_value;
Packit Service 2781ba
    }
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_operation_class_set_keys (GeglOperationClass *klass,
Packit Service 2781ba
                               const gchar        *key_name,
Packit Service 2781ba
                                ...)
Packit Service 2781ba
{
Packit Service 2781ba
  va_list var_args;
Packit Service 2781ba
Packit Service 2781ba
  va_start (var_args, key_name);
Packit Service 2781ba
  while (key_name)
Packit Service 2781ba
    {
Packit Service 2781ba
      const char *value = va_arg (var_args, char *);
Packit Service 2781ba
Packit Service 2781ba
      gegl_operation_class_set_key (klass, key_name, value);
Packit Service 2781ba
Packit Service 2781ba
      key_name = va_arg (var_args, char *);
Packit Service 2781ba
    }
Packit Service 2781ba
  va_end (var_args);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_operation_set_key (const gchar *operation_name,
Packit Service 2781ba
                        const gchar *key_name,
Packit Service 2781ba
                        const gchar *key_value)
Packit Service 2781ba
{
Packit Service 2781ba
  GType         type;
Packit Service 2781ba
  GObjectClass *klass;
Packit Service 2781ba
  type = gegl_operation_gtype_from_name (operation_name);
Packit Service 2781ba
  if (!type)
Packit Service 2781ba
    return;
Packit Service 2781ba
  klass  = g_type_class_ref (type);
Packit Service 2781ba
  gegl_operation_class_set_key (GEGL_OPERATION_CLASS (klass), key_name, key_value);
Packit Service 2781ba
  g_type_class_unref (klass);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
const gchar *
Packit Service 2781ba
gegl_operation_class_get_key (GeglOperationClass *operation_class,
Packit Service 2781ba
                              const gchar        *key_name)
Packit Service 2781ba
{
Packit Service 2781ba
  const gchar  *ret = NULL;
Packit Service 2781ba
  ret = g_hash_table_lookup (GEGL_OPERATION_CLASS (operation_class)->keys, key_name);
Packit Service 2781ba
  return ret;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
const gchar *
Packit Service 2781ba
gegl_operation_get_key (const gchar *operation_name,
Packit Service 2781ba
                        const gchar *key_name)
Packit Service 2781ba
{
Packit Service 2781ba
  GType         type;
Packit Service 2781ba
  GObjectClass *klass;
Packit Service 2781ba
  const gchar  *ret = NULL;
Packit Service 2781ba
  type = gegl_operation_gtype_from_name (operation_name);
Packit Service 2781ba
  if (!type)
Packit Service 2781ba
    {
Packit Service 2781ba
      return NULL;
Packit Service 2781ba
    }
Packit Service 2781ba
  klass  = g_type_class_ref (type);
Packit Service 2781ba
  ret = gegl_operation_class_get_key (GEGL_OPERATION_CLASS (klass), key_name);
Packit Service 2781ba
  g_type_class_unref (klass);
Packit Service 2781ba
  return ret;
Packit Service 2781ba
}