static gboolean
gimp_operation_mask_components_parent_process (GeglOperation        *operation,
                                               GeglOperationContext *context,
                                               const gchar          *output_prop,
                                               const GeglRectangle  *result,
                                               gint                  level)
{
  GimpOperationMaskComponents *self = GIMP_OPERATION_MASK_COMPONENTS (operation);

  if (self->mask == 0)
    {
      GObject *input = gegl_operation_context_get_object (context, "input");

      gegl_operation_context_set_object (context, "output", input);

      return TRUE;
    }
  else if (self->mask == GIMP_COMPONENT_ALL)
    {
      GObject *aux = gegl_operation_context_get_object (context, "aux");

      gegl_operation_context_set_object (context, "output", aux);

      return TRUE;
    }

  return GEGL_OPERATION_CLASS (parent_class)->process (operation, context,
                                                       output_prop, result,
                                                       level);
}
Ejemplo n.º 2
0
/* Fast path when opacity is a no-op
 */
static gboolean operation_process (GeglOperation        *operation,
                                   GeglOperationContext *context,
                                   const gchar          *output_prop,
                                   const GeglRectangle  *result,
                                   gint                  level)
{
  GeglOperationClass  *operation_class;
  gpointer in, aux;
  operation_class = GEGL_OPERATION_CLASS (gegl_chant_parent_class);

  /* get the raw values this does not increase the reference count */
  in = gegl_operation_context_get_object (context, "input");
  aux = gegl_operation_context_get_object (context, "aux");

  if (in && !aux && GEGL_CHANT_PROPERTIES (operation)->value == 1.0)
    {
      gegl_operation_context_take_object (context, "output",
                                          g_object_ref (G_OBJECT (in)));
      return TRUE;
    }
  /* chain up, which will create the needed buffers for our actual
   * process function
   */
  return operation_class->process (operation, context, output_prop, result,
                                  gegl_operation_context_get_level (context));
}
Ejemplo n.º 3
0
static gboolean
gimp_operation_normal_parent_process (GeglOperation        *operation,
                                      GeglOperationContext *context,
                                      const gchar          *output_prop,
                                      const GeglRectangle  *result,
                                      gint                  level)
{
#if 0
  /*  this code tries to be smart but is in fact just a too stupid
   *  copy from gegl's normal mode. to fix it, it needs to take
   *  mask and opacity into account
   */
  const GeglRectangle *in_extent  = NULL;
  const GeglRectangle *aux_extent = NULL;
  GObject             *input;
  GObject             *aux;

  /* get the raw values this does not increase the reference count */
  input = gegl_operation_context_get_object (context, "input");
  aux   = gegl_operation_context_get_object (context, "aux");

  /* pass the input/aux buffers directly through if they are not
   * overlapping
   */
  if (input)
    in_extent = gegl_buffer_get_abyss (GEGL_BUFFER (input));

  if (! input ||
      (aux && ! gegl_rectangle_intersect (NULL, in_extent, result)))
    {
      gegl_operation_context_set_object (context, "output", aux);
      return TRUE;
    }

  if (aux)
    aux_extent = gegl_buffer_get_abyss (GEGL_BUFFER (aux));

  if (! aux ||
      (input && ! gegl_rectangle_intersect (NULL, aux_extent, result)))
    {
      gegl_operation_context_set_object (context, "output", input);
      return TRUE;
    }
#endif

  /* chain up, which will create the needed buffers for our actual
   * process function
   */
  return GEGL_OPERATION_CLASS (parent_class)->process (operation, context,
                                                       output_prop, result,
                                                       level);
}
Ejemplo n.º 4
0
static gboolean
gegl_nop_process (GeglOperation        *operation,
                  GeglOperationContext *context,
                  const gchar          *output_prop,
                  const GeglRectangle  *result,
                  gint                  level)
{
  GeglBuffer *input;

  if (strcmp (output_prop, "output"))
    {
      g_warning ("requested processing of %s pad on a nop", output_prop);
      return FALSE;
    }

  input = GEGL_BUFFER (gegl_operation_context_get_object (context, "input"));
  if (!input)
    {
      g_warning ("nop received NULL input");
      return FALSE;
    }

  gegl_operation_context_take_object (context, "output", g_object_ref (G_OBJECT (input)));
  return TRUE;
}
Ejemplo n.º 5
0
static gboolean
operation_process (GeglOperation        *operation,
                   GeglOperationContext *context,
                   const gchar          *output_prop,
                   const GeglRectangle  *result,
                   gint                  level)
{
  GeglOperationClass  *operation_class;
  GeglProperties      *o = GEGL_PROPERTIES (operation);

  operation_class = GEGL_OPERATION_CLASS (gegl_op_parent_class);

  if (!o->clip_high && !o->clip_low)
    {
      gpointer in = gegl_operation_context_get_object (context, "input");
      gegl_operation_context_take_object (context, "output",
                                              g_object_ref (G_OBJECT (in)));
      return TRUE;
    }

  /* chain up, which will create the needed buffers for our actual
   * process function
   */
  return operation_class->process (operation, context, output_prop, result,
                                   gegl_operation_context_get_level (context));
}
Ejemplo n.º 6
0
/* Pass-through when trying to perform IIR on an infinite plane
 */
static gboolean
operation_process (GeglOperation        *operation,
                   GeglOperationContext *context,
                   const gchar          *output_prop,
                   const GeglRectangle  *result,
                   gint                  level)
{
  GeglOperationClass  *operation_class;
  GeglProperties          *o = GEGL_PROPERTIES (operation);
  GeglGblur1dFilter    filter  = filter_disambiguation (o->filter, o->std_dev);

  operation_class = GEGL_OPERATION_CLASS (gegl_op_parent_class);

  if (filter == GEGL_GBLUR_1D_IIR)
    {
      const GeglRectangle *in_rect =
        gegl_operation_source_get_bounding_box (operation, "input");

      if (in_rect && gegl_rectangle_is_infinite_plane (in_rect))
        {
          gpointer in = gegl_operation_context_get_object (context, "input");
          gegl_operation_context_take_object (context, "output",
                                              g_object_ref (G_OBJECT (in)));
          return TRUE;
        }
    }
  /* chain up, which will create the needed buffers for our actual
   * process function
   */
  return operation_class->process (operation, context, output_prop, result,
                                   gegl_operation_context_get_level (context));
}
Ejemplo n.º 7
0
static gboolean
operation_process (GeglOperation        *operation,
                   GeglOperationContext *context,
                   const gchar          *output_prop,
                   const GeglRectangle  *result,
                   gint                  level)
{
  GeglOperationClass  *operation_class;

  const GeglRectangle *in_rect =
    gegl_operation_source_get_bounding_box (operation, "input");

  operation_class = GEGL_OPERATION_CLASS (gegl_op_parent_class);

  if (in_rect && gegl_rectangle_is_infinite_plane (in_rect))
    {
      gpointer in = gegl_operation_context_get_object (context, "input");
      gegl_operation_context_take_object (context, "output",
                                          g_object_ref (G_OBJECT (in)));
      return TRUE;
    }

  return operation_class->process (operation, context, output_prop, result,
                                   gegl_operation_context_get_level (context));
}
Ejemplo n.º 8
0
/* Fast paths */
static gboolean operation_process (GeglOperation        *operation,
                                   GeglOperationContext *context,
                                   const gchar          *output_prop,
                                   const GeglRectangle  *result,
                                   gint                  level)
{
  GeglOperationClass  *operation_class;
  gpointer input, aux;
  operation_class = GEGL_OPERATION_CLASS (gegl_chant_parent_class);

  /* get the raw values this does not increase the reference count */
  input = gegl_operation_context_get_object (context, "input");
  aux = gegl_operation_context_get_object (context, "aux");

  /* pass the input/aux buffers directly through if they are alone*/
  {
    const GeglRectangle *in_extent = NULL;
    const GeglRectangle *aux_extent = NULL;

    if (input)
      in_extent = gegl_buffer_get_abyss (input);

    if ((!input ||
        (aux && !gegl_rectangle_intersect (NULL, in_extent, result))))
      {
         gegl_operation_context_take_object (context, "output",
                                             g_object_ref (aux));
         return TRUE;
      }
    if (aux)
      aux_extent = gegl_buffer_get_abyss (aux);

    if (!aux ||
        (input && !gegl_rectangle_intersect (NULL, aux_extent, result)))
      {
        gegl_operation_context_take_object (context, "output",
                                            g_object_ref (input));
        return TRUE;
      }
  }
  /* chain up, which will create the needed buffers for our actual
   * process function
   */
  return operation_class->process (operation, context, output_prop, result, level);
}
static gboolean
photos_operation_svg_multiply_operation_process (GeglOperation *operation,
                                                 GeglOperationContext *context,
                                                 const gchar *output_pad,
                                                 const GeglRectangle *roi,
                                                 gint level)
{
  GObject *aux;
  GObject *input;
  const GeglRectangle *aux_bbox = NULL;
  const GeglRectangle *in_bbox = NULL;
  gboolean ret_val = TRUE;

  aux = gegl_operation_context_get_object (context, "aux");
  if (aux != NULL)
    aux_bbox = gegl_buffer_get_abyss (GEGL_BUFFER (aux));

  input = gegl_operation_context_get_object (context, "input");
  if (input != NULL)
    in_bbox = gegl_buffer_get_abyss (GEGL_BUFFER (input));

  if (aux == NULL || (input != NULL && !gegl_rectangle_intersect (NULL, aux_bbox, roi)))
    {
      gegl_operation_context_set_object (context, "output", input);
      goto out;
    }

  if (input == NULL || (aux != NULL && !gegl_rectangle_intersect (NULL, in_bbox, roi)))
    {
      gegl_operation_context_set_object (context, "output", aux);
      goto out;
    }

  ret_val = GEGL_OPERATION_CLASS (photos_operation_svg_multiply_parent_class)->process (operation,
                                                                                        context,
                                                                                        output_pad,
                                                                                        roi,
                                                                                        level);

 out:
  return ret_val;
}
Ejemplo n.º 10
0
GObject *
gegl_operation_context_dup_object (GeglOperationContext *context,
                                   const gchar          *padname)
{
  GObject *ret;

  ret = gegl_operation_context_get_object (context, padname);
  if (ret != NULL)
    g_object_ref (ret);

  return ret;
}
Ejemplo n.º 11
0
GeglBuffer *
gegl_operation_context_get_source (GeglOperationContext *context,
                                   const gchar          *padname)
{
  GeglBuffer     *real_input;
  GeglBuffer     *input;

  real_input = GEGL_BUFFER (gegl_operation_context_get_object (context, padname));
  if (!real_input)
    return NULL;
  input = g_object_ref (real_input);
  return input;
}
Ejemplo n.º 12
0
static gboolean
operation_process (GeglOperation        *operation,
                   GeglOperationContext *context,
                   const gchar          *output_prop,
                   const GeglRectangle  *result,
                   gint                  level)
{
  GeglOperationClass  *operation_class;
  GeglProperties      *o = GEGL_PROPERTIES (operation);

  operation_class = GEGL_OPERATION_CLASS (gegl_op_parent_class);

  if (! o->radius)
    {
      gpointer in = gegl_operation_context_get_object (context, "input");
      gegl_operation_context_take_object (context, "output",
                                          g_object_ref (G_OBJECT (in)));
      return TRUE;
    }

  return operation_class->process (operation, context, output_prop, result,
                                   gegl_operation_context_get_level (context));
}
Ejemplo n.º 13
0
static gboolean
parent_process (GeglOperation        *operation,
                GeglOperationContext *context,
                const gchar          *output_prop,
                const GeglRectangle  *result,
                gint                  level)
{
  if (is_nop (operation))
    {
      GObject *input;

      input = gegl_operation_context_get_object (context, "input");

      gegl_operation_context_set_object (context, "output", input);

      return TRUE;
    }

  return GEGL_OPERATION_CLASS (gegl_op_parent_class)->process (operation,
                                                               context,
                                                               output_prop,
                                                               result, level);
}
Ejemplo n.º 14
0
static gboolean
operation_process (GeglOperation        *operation,
                   GeglOperationContext *context,
                   const gchar          *output_prop,
                   const GeglRectangle  *result,
                   gint                  level)
{
  GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
  GeglOperationClass  *operation_class;

  operation_class = GEGL_OPERATION_CLASS (gegl_chant_parent_class);

  /* If the profile is NULL, simply become a nop */
  if (!o->src_profile)
    {
      gpointer input = gegl_operation_context_get_object (context, "input");
      gegl_operation_context_take_object (context, "output",
                                          g_object_ref (input));
      return TRUE;
    }

  return operation_class->process (operation, context,
                                   output_prop, result, level);
}
Ejemplo n.º 15
0
static gboolean
process (GeglOperation        *operation,
         GeglOperationContext *context,
         const gchar          *output_prop,
         const GeglRectangle  *result,
         gint                  level)
{
  GeglProperties  *o    = GEGL_PROPERTIES (operation);
  WarpPrivate     *priv = (WarpPrivate*) o->user_data;

  GeglBuffer      *input;

  gdouble          spacing = MAX (o->size * o->spacing, 0.5);
  gdouble          dist;
  gint             stamps;
  gint             i;
  gdouble          t;

  GeglPathPoint    prev, next, lerp;
  GeglPathList    *event;
  WarpPointList   *processed_event;
  WarpPointList  **processed_event_ptr;

  if (!o->stroke || strcmp (output_prop, "output"))
    return FALSE;

  /* if the previously processed stroke is valid, the cached buffer can be
   * passed as output right away.
   */
  if (priv->processed_stroke_valid)
    {
      g_assert (priv->buffer != NULL);

      gegl_operation_context_set_object (context,
                                         "output", G_OBJECT (priv->buffer));

      return TRUE;
    }

  /* ... otherwise, we need to check if the previously processed stroke is an
   * initial segment of the current stroke ...
   */

  event               = gegl_path_get_path (o->stroke);
  processed_event     = priv->processed_stroke;
  processed_event_ptr = &priv->processed_stroke;

  while (event && processed_event)
    {
      if (event->d.point[0].x != processed_event->point.x ||
          event->d.point[0].y != processed_event->point.y)
        {
          break;
        }

      processed_event_ptr = &processed_event->next;

      event           = event->next;
      processed_event = processed_event->next;
    }

  /* if the loop stopped before we reached the last event of the processed
   * stroke, it's not an initial segment, and we need to clear the cache, and
   * process the entire stroke.
   */
  if (processed_event)
    {
      clear_cache (o);

      event               = gegl_path_get_path (o->stroke);
      processed_event_ptr = &priv->processed_stroke;
    }
  /* otherwise, we simply continue processing remaining stroke on top of the
   * previously processed buffer.
   */

  /* intialize the cached buffer if we don't already have one. */
  if (! priv->buffer)
    {
      input = GEGL_BUFFER (gegl_operation_context_get_object (context,
                                                              "input"));

      priv->buffer = gegl_buffer_dup (input);

      /* we pass the buffer as output directly while keeping it cached, so mark
       * it as forked.
       */
      gegl_object_set_has_forked (G_OBJECT (priv->buffer));
    }

  if (event)
    {
      /* is this the first event of the stroke? */
      if (! priv->processed_stroke)
        {
          prev = *(event->d.point);

          priv->last_x = prev.x;
          priv->last_y = prev.y;
        }
      else
        {
          prev.x = priv->last_x;
          prev.y = priv->last_y;
        }

      for (; event; event = event->next)
        {
          next = *(event->d.point);
          dist = gegl_path_point_dist (&next, &prev);
          stamps = floor (dist / spacing) + 1;

          /* stroke the current segment, such that there's always a stamp at
           * its final endpoint, and at positive integer multiples of
           * `spacing` away from it.
           */

          if (stamps == 1)
            {
              stamp (o, next.x, next.y);
            }
          else
            {
              for (i = 0; i < stamps; i++)
                {
                  t = 1.0 - ((stamps - i - 1) * spacing) / dist;

                  gegl_path_point_lerp (&lerp, &prev, &next, t);
                  stamp (o, lerp.x, lerp.y);
                }
            }

          prev = next;

          /* append the current event to the processed path. */
          processed_event        = g_slice_new (WarpPointList);
          processed_event->point = next;

          *processed_event_ptr = processed_event;
          processed_event_ptr  = &processed_event->next;
        }

      *processed_event_ptr = NULL;
    }

  priv->processed_stroke_valid = TRUE;

  /* pass the processed buffer as output */
  gegl_operation_context_set_object (context,
                                     "output", G_OBJECT (priv->buffer));

  return TRUE;
}
Ejemplo n.º 16
0
/**
 * gegl_graph_process:
 * @path: The traversal path
 *
 * Process the prepared request. This will return the
 * resulting buffer from the final node, or NULL if
 * that node is a sink.
 *
 * If gegl_graph_prepare_request has not been called
 * the behavior of this function is undefined.
 *
 * Return value: (transfer full): The result of the graph, or NULL if
 * there is no output pad.
 */
GeglBuffer *
gegl_graph_process (GeglGraphTraversal *path,
                    gint                level)
{
  GList *list_iter = NULL;
  GeglBuffer *result = NULL;
  GeglOperationContext *context = NULL;
  GeglOperationContext *last_context = NULL;
  GeglBuffer *operation_result = NULL;

  for (list_iter = path->dfs_path; list_iter; list_iter = list_iter->next)
    {
      GeglNode *node = GEGL_NODE (list_iter->data);
      GeglOperation *operation = node->operation;
      g_return_val_if_fail (node, NULL);
      g_return_val_if_fail (operation, NULL);
      
      GEGL_INSTRUMENT_START();

      operation_result = NULL;

      if (last_context)
        gegl_operation_context_purge (last_context);
      
      context = g_hash_table_lookup (path->contexts, node);
      g_return_val_if_fail (context, NULL);

      GEGL_NOTE (GEGL_DEBUG_PROCESS,
                 "Will process %s result_rect = %d, %d %d×%d",
                 gegl_node_get_debug_name (node),
                 context->result_rect.x, context->result_rect.y, context->result_rect.width, context->result_rect.height);
      
      if (context->need_rect.width > 0 && context->need_rect.height > 0)
        {
          if (context->cached)
            {
              GEGL_NOTE (GEGL_DEBUG_PROCESS,
                         "Using cached result for %s",
                         gegl_node_get_debug_name (node));
              operation_result = GEGL_BUFFER (node->cache);
            }
          else
            {
              /* provide something on input pad, always - this makes having
                 behavior depending on it not being set.. not work, is
                 sacrifising that worth it?
               */
              if (gegl_node_has_pad (node, "input") &&
                  !gegl_operation_context_get_object (context, "input"))
                {
                  gegl_operation_context_set_object (context, "input", G_OBJECT (gegl_graph_get_shared_empty(path)));
                }

              context->level = level;

              /* note: this hard-coding of "output" makes some more custom
               * graph topologies harder than neccesary.
               */
              gegl_operation_process (operation, context, "output", &context->need_rect, context->level);
              operation_result = GEGL_BUFFER (gegl_operation_context_get_object (context, "output"));

              if (operation_result && operation_result == (GeglBuffer *)operation->node->cache)
                gegl_cache_computed (operation->node->cache, &context->need_rect, level);
            }
        }
      else
        {
          operation_result = NULL;
        }

      if (operation_result)
        {
          GeglPad *output_pad = gegl_node_get_pad (node, "output");
          GList   *targets = gegl_graph_get_connected_output_contexts (path, output_pad);
          GList   *targets_iter;

          GEGL_NOTE (GEGL_DEBUG_PROCESS,
                     "Will deliver the results of %s:%s to %d targets",
                     gegl_node_get_debug_name (node),
                     "output",
                     g_list_length (targets));

          if (g_list_length (targets) > 1)
            gegl_object_set_has_forked (G_OBJECT (operation_result));

          for (targets_iter = targets; targets_iter; targets_iter = g_list_next (targets_iter))
            {
              ContextConnection *target_con = targets_iter->data;
              gegl_operation_context_set_object (target_con->context, target_con->name, G_OBJECT (operation_result));
            }
          g_list_free_full (targets, free_context_connection);
        }
      last_context = context;

      GEGL_INSTRUMENT_END ("process", gegl_node_get_operation (node));
    }
  if (last_context)
    {
      if (operation_result)
        result = g_object_ref (operation_result);
      else if (gegl_node_has_pad (last_context->operation->node, "output"))
        result = g_object_ref (gegl_graph_get_shared_empty (path));
      gegl_operation_context_purge (last_context);
    }

  return result;
}
Ejemplo n.º 17
0
GeglBuffer *
gegl_operation_context_dup_input_maybe_copy (GeglOperationContext *context,
                                             const gchar          *padname,
                                             const GeglRectangle  *roi)
{
  GeglBuffer    *input;
  GeglBuffer    *output;
  GeglBuffer    *result;
  GeglRectangle  required;
  GeglRectangle  temp;
  gint           shift_x;
  gint           shift_y;
  gint           tile_width;
  gint           tile_height;

  input = GEGL_BUFFER (gegl_operation_context_get_object (context, padname));

  if (! input)
    return NULL;

  /* return input directly when processing a level greater than 0, since
   * gegl_buffer_copy() only copies level-0 tiles
   */
  if (context->level > 0)
    return g_object_ref (input);

  output = GEGL_BUFFER (gegl_operation_context_get_object (context, "output"));

  /* return input directly when processing in-place, otherwise, the copied
   * input buffer will occupy space in the cache after the original is modified
   */
  if (input == output)
    return g_object_ref (input);

  /* get required region to copy */
  required = gegl_operation_get_required_for_output (context->operation,
                                                     padname, roi);

  /* return input directly if the required rectangle is infinite, so that we
   * don't attempt to copy an infinite region
   */
  if (gegl_rectangle_is_infinite_plane (&required))
    return g_object_ref (input);

  /* align required region to the tile grid */
  shift_x     = input->shift_x;
  shift_y     = input->shift_y;
  tile_width  = input->tile_width;
  tile_height = input->tile_height;

  temp.x      = (gint) floor ((gdouble) (required.x                   + shift_x) / tile_width)  * tile_width;
  temp.y      = (gint) floor ((gdouble) (required.y                   + shift_y) / tile_height) * tile_height;
  temp.width  = (gint) ceil  ((gdouble) (required.x + required.width  + shift_x) / tile_width)  * tile_width  - temp.x;
  temp.height = (gint) ceil  ((gdouble) (required.y + required.height + shift_y) / tile_height) * tile_height - temp.y;

  temp.x -= shift_x;
  temp.y -= shift_y;

  required = temp;

  /* intersect required region with input abyss */
  gegl_rectangle_intersect (&required, &required, &input->abyss);

  /* create new buffer with similar characteristics to the input buffer */
  result = g_object_new (GEGL_TYPE_BUFFER,
                         "format",       input->soft_format,
                         "x",            input->extent.x,
                         "y",            input->extent.y,
                         "width",        input->extent.width,
                         "height",       input->extent.height,
                         "abyss-x",      input->abyss.x,
                         "abyss-y",      input->abyss.y,
                         "abyss-width",  input->abyss.width,
                         "abyss-height", input->abyss.height,
                         "shift-x",      shift_x,
                         "shift-y",      shift_y,
                         "tile-width",   tile_width,
                         "tile-height",  tile_height,
                         NULL);

  /* if the tile size doesn't match, bail */
  if (result->tile_width != tile_width || result->tile_height != tile_height)
    {
      g_object_unref (result);

      return g_object_ref (input);
    }

  /* copy required region from input to result -- tiles will generally be COWed */
  gegl_buffer_copy (input,  &required, GEGL_ABYSS_NONE,
                    result, &required);

  return result;
}