コード例 #1
0
void
layer_add_gegl_node(GeglEditorLayer* layer, GeglNode* node)
{
  //get input pads
  //gegl_pad_is_output
  GSList	*pads	    = gegl_node_get_input_pads(node);
  guint		 num_inputs = g_slist_length(pads);
  gchar**	 inputs	    = malloc(sizeof(gchar*)*num_inputs);
  int		 i;
  for(i = 0; pads != NULL; pads = pads->next, i++)
    {
      inputs[i] = (gchar*)gegl_pad_get_name(pads->data);
    }

  gint	id;
  if(gegl_node_get_pad(node, "output") == NULL)
    {
      id = gegl_editor_add_node(layer->editor, gegl_node_get_operation(node), num_inputs, inputs, 0, NULL);
    }
  else
    {
      gchar*	output = "output";
      gchar* outputs[] = {output};
      id	       = gegl_editor_add_node(layer->editor, gegl_node_get_operation(node), num_inputs, inputs, 1, outputs);
    }

  node_id_pair* new_pair = malloc(sizeof(node_id_pair));
  new_pair->node	 = node;
  new_pair->id		 = id;
  layer->pairs		 = g_slist_append(layer->pairs, new_pair);
}
コード例 #2
0
gint layer_connected_pads (gpointer host, GeglEditor* editor, gint from, const gchar* output, gint to, const gchar* input)
{
  GeglEditorLayer*	self = (GeglEditorLayer*)host;

  GeglNode*	from_node = NULL;
  GeglNode*	to_node	  = NULL;
  GSList*	pair	  = self->pairs;
  for(;pair != NULL; pair = pair->next)
    {
      node_id_pair*	data = pair->data;
      if(data->id == from)
	from_node	     = data->node;
      if(data->id == to)
	to_node		     = data->node;
      if(from_node != NULL && to_node != NULL)
	break;
    }

  g_assert(from_node != NULL && to_node != NULL);
  g_assert(from_node != to_node);
  gboolean	success = gegl_node_connect_to(from_node, output, to_node, input);
  g_print("connected (%d): %s(%s) to %s(%s), %i\n", success, gegl_node_get_operation(from_node), output,
	  gegl_node_get_operation(to_node), input, success);
  refresh_images(self);
}
コード例 #3
0
ファイル: motion-blur.c プロジェクト: peixuan/GEGL-OpenCL
static void
prepare_cl (GeglOperation *operation)
{
    GeglOperationAreaFilter* op_area = GEGL_OPERATION_AREA_FILTER (operation);
    GeglChantO* o = GEGL_CHANT_PROPERTIES (operation);

    gdouble theta = o->angle * G_PI / 180.0;
    gdouble offset_x = fabs(o->length * cos(theta));
    gdouble offset_y = fabs(o->length * sin(theta));

    op_area->left   =
        op_area->right  = (gint)ceil(0.5 * offset_x);
    op_area->top    =
        op_area->bottom = (gint)ceil(0.5 * offset_y);

    GeglNode * self;
    GeglPad *pad;
    Babl * format=babl_format ("RaGaBaA float");
    self=gegl_operation_get_source_node(operation,"input");
    while(self) {
        if(strcmp(gegl_node_get_operation(self),"gimp:tilemanager-source")==0) {
            format=gegl_operation_get_format(self->operation,"output");
            break;
        }
        self=gegl_operation_get_source_node(self->operation,"input");
    }
    gegl_operation_set_format (operation, "output", format);
}
コード例 #4
0
ファイル: gimpwarptool.c プロジェクト: AjayRamanathan/gimp
gboolean
gimp_warp_tool_undo (GimpTool    *tool,
                     GimpDisplay *display)
{
  GimpWarpTool *wt = GIMP_WARP_TOOL (tool);
  GeglNode     *to_delete;
  GeglNode     *previous;
  const gchar  *type;

  if (! wt->render_node)
    return FALSE;

  to_delete = gegl_node_get_producer (wt->render_node, "aux", NULL);
  type = gegl_node_get_operation (to_delete);

  if (strcmp (type, "gegl:warp"))
    return FALSE;

  previous = gegl_node_get_producer (to_delete, "input", NULL);

  gegl_node_disconnect (to_delete,       "input");
  gegl_node_connect_to (previous,        "output",
                        wt->render_node, "aux");

  wt->redo_stack = g_list_prepend (wt->redo_stack, g_object_ref (to_delete));

  gegl_node_remove_child (wt->graph, to_delete);

  gimp_warp_tool_update_stroke (wt, to_delete);

  return TRUE;
}
コード例 #5
0
static void print_info(GeglNode* gegl)
{
  GSList *list = gegl_node_get_children(gegl);
  for(;list != NULL; list = list->next)
    {
      GeglNode* node = GEGL_NODE(list->data);
      g_print("Node %s\n", gegl_node_get_operation(node));

      if(gegl_node_get_pad(node, "output") == NULL) {
	g_print("Output pad is NULL\n");
      }

      /*      GeglNode** nodes;
      const gchar** pads;
      gint num = gegl_node_get_consumers(node, "output", &nodes, &pads);
      g_print("%s: %d consumer(s)\n", gegl_node_get_operation(node), num);

      int i;
      for(i = 0; i < num; i++)
	{
	  g_print("Connection: (%s to %s)\n", gegl_node_get_operation(node), gegl_node_get_operation(nodes[0]), pads[0]);
	}
	g_print("\n");*/
    }
}
コード例 #6
0
/* we replicate the process function from GeglOperationComposer3 to be
 * able to bail out earlier for some common processing time pitfalls
 */
static gboolean
gegl_operation_composer3_process2 (GeglOperation        *operation,
                                   GeglOperationContext *context,
                                   const gchar          *output_prop,
                                   const GeglRectangle  *result,
                                   gint                  level)
{
  GeglOperationComposer3Class *klass   = GEGL_OPERATION_COMPOSER3_GET_CLASS (operation);
  GeglBuffer                  *input;
  GeglBuffer                  *aux;
  GeglBuffer                  *aux2;
  GeglBuffer                  *output;
  gboolean                     success = FALSE;

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

  input = gegl_operation_context_get_source (context, "input");
  aux   = gegl_operation_context_get_source (context, "aux");
  aux2  = gegl_operation_context_get_source (context, "aux2");

  /* we could be even faster by not alway writing to this buffer, that
   * would potentially break other assumptions we want to make from the
   * GEGL core so we avoid doing that
   */
  output = gegl_operation_context_get_target (context, "output");


  if (input != NULL ||
      aux != NULL ||
      aux2 != NULL)
    {
      if (result->width == 0 || result->height == 0)
        success = TRUE;
      else
        success = klass->process (operation, input, aux, aux2, output, result, level);

      if (input)
         g_object_unref (input);
      if (aux)
         g_object_unref (aux);
      if (aux2)
         g_object_unref (aux2);
    }
  else
    {
      g_warning ("%s received NULL input, aux, and aux2",
                 gegl_node_get_operation (operation->node));
    }

  return success;
}
コード例 #7
0
void layer_set_graph(GeglEditorLayer* self, GeglNode* gegl)
{
  //properly dispose of old gegl graph
  self->gegl = gegl;
  gegl_editor_remove_all_nodes(self->editor);

  GSList *list = gegl_node_get_children(gegl);
  for(;list != NULL; list = list->next)
    {
      GeglNode* node = GEGL_NODE(list->data);
      g_print("Loading %s\n", gegl_node_get_operation(node));
      layer_add_gegl_node(self, node);
    }

  list = gegl_node_get_children(gegl);

  for(list = g_slist_reverse(list); list != NULL; list = list->next)
    {
      GeglNode* node = GEGL_NODE(list->data);
      gint from = get_editor_node_id(self, node);

      GeglNode** nodes;
      const gchar** pads;

      if(!gegl_node_has_pad(node, "output")) {
    	  break;}

      gint num = gegl_node_get_consumers(node, "output", &nodes, &pads);

      int i;
      g_print("%s: %d consumer(s)\n", gegl_node_get_operation(node), num);
      for(i = 0; i < num; i++)
	{
	  gint to = get_editor_node_id(self, nodes[i]);
	  g_print("Connecting to consumer (%s to %s): output->%s\n", gegl_node_get_operation(node), gegl_node_get_operation(nodes[0]), pads[0]);
	  gegl_editor_add_connection(self->editor, from, to, "output", pads[0]);
	}
    }
}
コード例 #8
0
/* sets up the node's bounding box */
static void
gegl_have_visitor_visit_node (GeglVisitor *self,
                              GeglNode    *node)
{
  GeglOperation *operation;
  glong          time = gegl_ticks ();

  GEGL_VISITOR_CLASS (gegl_have_visitor_parent_class)->visit_node (self, node);
  if (!node)
    return;
  operation = node->operation;
  g_mutex_lock (node->mutex);
  node->have_rect = gegl_operation_get_bounding_box (operation);

  GEGL_NOTE (GEGL_DEBUG_PROCESS,
             "For \"%s\" have_rect = %d,%d %d×%d",
             gegl_node_get_debug_name (node),
             node->have_rect.x, node->have_rect.y, node->have_rect.width, node->have_rect.height);
  g_mutex_unlock (node->mutex);

  time = gegl_ticks () - time;
  gegl_instrument ("process", gegl_node_get_operation (node), time);
  gegl_instrument (gegl_node_get_operation (node), "defined-region", time);
}
コード例 #9
0
void refresh_images(GeglEditorLayer* self)
{
  return;
  GSList*	pair = self->pairs;
  for(;pair != NULL; pair = pair->next)
    {
      node_id_pair	*data = pair->data;

      /*      if(node->image != NULL)
	      cairo_surface_destroy(node->image);	//TODO: only destory if it has changed*/

      const Babl	*cairo_argb32 = babl_format("cairo-ARGB32");

      const GeglRectangle	roi = gegl_node_get_bounding_box(GEGL_NODE(data->node));
      g_print("Rect: %dx%d\n", roi.x, roi.y);

      if(roi.width == 0 || roi.height == 0)
	{
	  g_print("Empty rectangle: %s\n", gegl_node_get_operation(GEGL_NODE(data->node)));
	  continue;		//skip
	}

      gegl_editor_show_node_image(self->editor, data->id);

      gint	stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, roi.width);
      guchar*	buf    = malloc(stride*roi.height);

      //make buffer in memory
      gegl_node_blit(GEGL_NODE(data->node),
		     1.0,
		     &roi,
		     cairo_argb32,
		     buf,
		     GEGL_AUTO_ROWSTRIDE,
		     GEGL_BLIT_CACHE);

      cairo_surface_t*	image =
	cairo_image_surface_create_for_data(buf, CAIRO_FORMAT_ARGB32,
				      roi.width, roi.height,
				      stride);
      //            free(buf);
      gegl_editor_set_node_image(self->editor, data->id, image);
    }
}
コード例 #10
0
ファイル: gimpwarptool.c プロジェクト: AjayRamanathan/gimp
const gchar *
gimp_warp_tool_get_undo_desc (GimpTool    *tool,
                              GimpDisplay *display)
{
  GimpWarpTool *wt = GIMP_WARP_TOOL (tool);
  GeglNode     *to_delete;
  const gchar  *type;

  if (! wt->render_node)
    return NULL;

  to_delete = gegl_node_get_producer (wt->render_node, "aux", NULL);
  type = gegl_node_get_operation (to_delete);

  if (strcmp (type, "gegl:warp"))
    return NULL;

  return _("Warp Tool Stroke");
}
コード例 #11
0
ファイル: crop.c プロジェクト: Distrotech/gegl
static gboolean
gegl_crop_process (GeglOperation        *operation,
                   GeglOperationContext *context,
                   const gchar          *output_prop,
                   const GeglRectangle  *result,
                   gint                  level)
{
  GeglProperties *o = GEGL_PROPERTIES (operation);
  GeglBuffer     *input;
  gboolean        success = FALSE;
  GeglRectangle   extent;

  extent.x      = o->x;
  extent.y      = o->y;
  extent.width  = o->width;
  extent.height = o->height;

  input = gegl_operation_context_get_source (context, "input");

  if (input)
    {
      GeglBuffer *output = gegl_buffer_create_sub_buffer (input, &extent);

      if (gegl_object_get_has_forked (G_OBJECT (input)))
        gegl_object_set_has_forked (G_OBJECT (output));

      gegl_operation_context_take_object (context, "output", G_OBJECT (output));

      g_object_unref (input);
      success = TRUE;
    }
  else
    {
      g_warning ("%s got NULL input pad", gegl_node_get_operation (operation->node));
    }

  return success;
}
コード例 #12
0
ファイル: gegl-eval-visitor.c プロジェクト: jcupitt/gegl-vips
/* this is the visitor that does the real computations for GEGL */
static void
gegl_eval_visitor_visit_pad (GeglVisitor *self,
                             GeglPad     *pad)
{
  GeglNode        *node       = gegl_pad_get_node (pad);
  gpointer         context_id = self->context_id;
  GeglOperationContext *context    = gegl_node_get_context (node, context_id);
  GeglOperation   *operation  = node->operation;

  GEGL_VISITOR_CLASS (gegl_eval_visitor_parent_class)->visit_pad (self, pad);

  if (gegl_pad_is_output (pad))
    {
      /* processing only really happens for output pads */
      if (context->cached)
        {
          GEGL_NOTE (GEGL_DEBUG_PROCESS, "Using cache for pad '%s' on \"%s\"", gegl_pad_get_name (pad), gegl_node_get_debug_name (node));
          gegl_operation_context_set_object (context,
                                             gegl_pad_get_name (pad),
                                             G_OBJECT (node->cache));
        }
      else
        {
          glong time      = gegl_ticks ();

          /* Make the operation do it's actual processing */
          GEGL_NOTE (GEGL_DEBUG_PROCESS, "For \"%s\" processing pad '%s' result_rect = %d, %d %d×%d",
                     gegl_pad_get_name (pad), gegl_node_get_debug_name (node),
                     context->result_rect.x, context->result_rect.y, context->result_rect.width, context->result_rect.height);
          gegl_operation_process (operation, context, gegl_pad_get_name (pad),
                                  &context->result_rect);
          time      = gegl_ticks () - time;

          gegl_instrument ("process", gegl_node_get_operation (node), time);

          if (gegl_pad_get_num_connections (pad) > 1)
            {
              /* Mark buffers that have been consumed by different parts of the
               * graph so that in-place processing can be avoided on them.
               */
              GValue *value;
              GeglBuffer *buffer;
              value = gegl_operation_context_get_value (context, gegl_pad_get_name (pad));
              if (value)
                {
                  buffer = g_value_get_object (value);
                  if (buffer)
                    gegl_object_set_has_forked (buffer);
                }
            }
        }
    }
  else if (gegl_pad_is_input (pad))
    {
      GeglPad *source_pad = gegl_pad_get_connected_to (pad);

      /* the work needed to be done on input pads is to set the
       * data from the corresponding output pad it is connected to
       */
      if (source_pad)
        {
          GValue           value          = { 0 };
          GParamSpec      *prop_spec      = gegl_pad_get_param_spec (pad);
          GeglNode        *source_node    = gegl_pad_get_node (source_pad);
          GeglOperationContext *source_context = gegl_node_get_context (source_node, context_id);

          g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop_spec));

          gegl_operation_context_get_property (source_context,
                                          gegl_pad_get_name (source_pad),
                                          &value);

          if (!g_value_get_object (&value) &&
              !g_object_get_data (G_OBJECT (source_node), "graph"))
            g_warning ("eval-visitor encountered a NULL buffer passed from: %s.%s-[%p]",
                       gegl_node_get_debug_name (source_node),
                       gegl_pad_get_name (source_pad),
                       g_value_get_object (&value));

          gegl_operation_context_set_property (context,
                                          gegl_pad_get_name (pad),
                                          &value);
          /* reference counting for this source dropped to zero, freeing up */
          if (-- gegl_node_get_context (
                     gegl_pad_get_node (source_pad), context_id)->refs == 0 &&
              g_value_get_object (&value))
            {
              gegl_operation_context_remove_property (
                 gegl_node_get_context (
                    gegl_pad_get_node (source_pad), context_id),
                    gegl_pad_get_name (source_pad));
            }

          g_value_unset (&value);

	  /* processing for sink operations that accepts partial consumption
             and thus probably are being processed by the processor from the
             this very operation.
           */
          if (GEGL_IS_OPERATION_SINK (operation) &&
              !gegl_operation_sink_needs_full (operation))
            {
              GEGL_NOTE (GEGL_DEBUG_PROCESS, "Processing pad '%s' on \"%s\"", gegl_pad_get_name (pad), gegl_node_get_debug_name (node));
              gegl_operation_process (operation, context, "output",
                &context->result_rect);
            }
        }
    }
}
コード例 #13
0
  static gboolean
gegl_operation_composer3_process (GeglOperation        *operation,
    GeglOperationContext *context,
    const gchar          *output_prop,
    const GeglRectangle  *result,
    gint                  level)
{
  GeglOperationComposer3Class *klass   = GEGL_OPERATION_COMPOSER3_GET_CLASS (operation);
  GeglBuffer                  *input;
  GeglBuffer                  *aux;
  GeglBuffer                  *aux2;
  GeglBuffer                  *output;
  gboolean                     success = FALSE;

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

  if (result->width == 0 || result->height == 0)
  {
    output = gegl_operation_context_get_target (context, "output");
    return TRUE;
  }

  input = gegl_operation_context_get_source (context, "input");
  output = gegl_operation_context_get_output_maybe_in_place (operation,
                                                             context,
                                                             input,
                                                             result);

  aux   = gegl_operation_context_get_source (context, "aux");
  aux2  = gegl_operation_context_get_source (context, "aux2");

  /* A composer with a NULL aux, can still be valid, the
   * subclass has to handle it.
   */
  if (input != NULL ||
      aux != NULL ||
      aux2 != NULL)
    {
      if (gegl_operation_use_threading (operation, result))
      {
        gint threads = gegl_config_threads ();
        GThreadPool *pool = thread_pool ();
        ThreadData thread_data[GEGL_MAX_THREADS];
        gint pending = threads;

        if (result->width > result->height)
        {
          gint bit = result->width / threads;
          for (gint j = 0; j < threads; j++)
          {
            thread_data[j].roi.y = result->y;
            thread_data[j].roi.height = result->height;
            thread_data[j].roi.x = result->x + bit * j;
            thread_data[j].roi.width = bit;
          }
          thread_data[threads-1].roi.width = result->width - (bit * (threads-1));
        }
        else
        {
          gint bit = result->height / threads;
          for (gint j = 0; j < threads; j++)
          {
            thread_data[j].roi.x = result->x;
            thread_data[j].roi.width = result->width;
            thread_data[j].roi.y = result->y + bit * j;
            thread_data[j].roi.height = bit;
          }
          thread_data[threads-1].roi.height = result->height - (bit * (threads-1));
        }
        for (gint i = 0; i < threads; i++)
        {
          thread_data[i].klass = klass;
          thread_data[i].operation = operation;
          thread_data[i].input = input;
          thread_data[i].aux = aux;
          thread_data[i].aux2 = aux2;
          thread_data[i].output = output;
          thread_data[i].pending = &pending;
          thread_data[i].level = level;
          thread_data[i].success = TRUE;
        }

        for (gint i = 1; i < threads; i++)
          g_thread_pool_push (pool, &thread_data[i], NULL);
        thread_process (&thread_data[0], NULL);

        while (g_atomic_int_get (&pending)) {};
        
        success = thread_data[0].success;
      }
      else
      {
        success = klass->process (operation, input, aux, aux2, output, result, level);
      }

      g_clear_object (&input);
      g_clear_object (&aux);
      g_clear_object (&aux2);
    }
  else
    {
      g_warning ("%s received NULL input, aux, and aux2",
                 gegl_node_get_operation (operation->node));
    }

  return success;
}
コード例 #14
0
ファイル: gegl-dot.c プロジェクト: AjayRamanathan/gegl
void
gegl_dot_util_add_node (GString  *string,
                        GeglNode *node)
{
  g_string_append_printf (string, "op_%p [fontsize=\"10\" label=\"", node);

  /* We build the record from top to bottom */
  g_string_append_printf (string, "{");

  /* The first row is a list of output pads */
  {
    GSList  *pads       = gegl_node_get_pads (node);
    GSList  *entry      = pads;
    gboolean got_output = FALSE;

    g_string_append_printf (string, "{");

    while (entry)
      {
        GeglPad *pad = entry->data;
        if (gegl_pad_is_output (pad))
          {
            if (got_output)
              {
                g_string_append (string, "|");
              }
            got_output = TRUE;
            g_string_append_printf (string, "<%s>%s",
                                    gegl_pad_get_name (pad),
                                    gegl_pad_get_name (pad));
          }
        entry = g_slist_next (entry);
      }

    g_string_append_printf (string, "}|");
  }

  /* The second row is the operation name such as gegl:translate */
  g_string_append_printf (string, "%s |", gegl_node_get_debug_name (node));

  /* The next rows are property names and their values */
  if (1)
    {
      guint        n_properties;
      GParamSpec **properties = gegl_operation_list_properties (gegl_node_get_operation (node), &n_properties);
      guint        i;
      for (i = 0; i < n_properties; i++)
        {
          const gchar *name   = properties[i]->name;
          GValue       tvalue = { 0, };
          GValue       svalue = { 0, };

          if (properties[i]->value_type == GEGL_TYPE_BUFFER)
            continue;

          g_value_init (&svalue, G_TYPE_STRING);
          g_value_init (&tvalue, properties[i]->value_type);

          gegl_node_get_property (node, name, &tvalue);

          if (g_value_transform (&tvalue, &svalue))
            {
              gchar *sval = g_value_dup_string (&svalue);
              if (sval && strlen (sval) > 30)
                {
                  sval[28] = '.';
                  sval[29] = '.';
                  sval[30] = '\0';
                }
              if (sval)
                {
                  g_string_append_printf (string, "%s=%s | ", name, sval);
                  g_free (sval);
                }
              g_value_unset (&svalue);
            }
          g_value_unset (&tvalue);
        }
      g_free (properties);
    }

  /* The last row is input pads */
  {
    GSList  *pads      = gegl_node_get_pads (node);
    GSList  *entry     = pads;
    gboolean got_input = FALSE;

    g_string_append_printf (string, "{");

    while (entry)
      {
        GeglPad *pad = entry->data;
        if (gegl_pad_is_input (pad))
          {
            if (got_input)
              {
                g_string_append (string, "|");
              }
            got_input = TRUE;
            g_string_append_printf (string, "<%s>%s",
                                    gegl_pad_get_name (pad),
                                    gegl_pad_get_name (pad));
          }
        entry = g_slist_next (entry);
      }

    g_string_append_printf (string, "}");
  }

  g_string_append_printf (string, "}\"");
  g_string_append_printf (string, "shape=\"record\"];\n");
}
コード例 #15
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;
}
コード例 #16
0
gint layer_node_selected (gpointer host, GeglEditor* editor, gint node_id)
{
  GeglEditorLayer*	self = (GeglEditorLayer*)host;
  GeglNode*		node = NULL;
  GSList*		pair = self->pairs;
  for(;pair != NULL; pair = pair->next)
    {
      node_id_pair*	data = pair->data;
      if(data->id == node_id)
	{
	  node = data->node;
	  break;
	}
    }

  g_assert(node != NULL);

  GeglNode** nodes;
  const gchar** pads;
  gint num = gegl_node_get_consumers(node, "output", &nodes, &pads);

  int i;
  g_print("%s: %d consumer(s)\n", gegl_node_get_operation(node), num);
  for(i = 0; i < num; i++)
    {
      g_print("Connection: (%s to %s)\n", gegl_node_get_operation(node), gegl_node_get_operation(nodes[0]), pads[0]);
    }
  g_print("Input from: %s\n", gegl_node_get_operation(gegl_node_get_producer(node, "input", NULL)));

  //  g_print("selected: %s\n", gegl_node_get_operation(node));

  guint		n_props;
  GParamSpec**	properties = gegl_operation_list_properties(gegl_node_get_operation(node), &n_props);

  //TODO: only create enough columns for the properties which will actually be included (i.e. ignoring GeglBuffer props)
  GtkTable	*prop_table = GTK_TABLE(gtk_table_new(2, n_props, FALSE));

  int d;
  for(d = 0, i = 0; i < n_props; i++, d++)
    {
      GParamSpec*	prop = properties[i];
      GType		type = prop->value_type;
      const gchar*		name = prop->name;

      GtkWidget*	name_label = gtk_label_new(name);
      gtk_misc_set_alignment(GTK_MISC(name_label), 0, 0.5);


      GtkWidget*	value_entry = gtk_entry_new();

      gchar buf[256] = "*";	//can probably be smaller; In fact, can probably do this without sprintf and a buffer. TODO: look at g_string

      gint	i_value;
      gdouble	d_value;
      gchar*	str_value;
      gboolean skip = FALSE;

      switch(type)
	{
	case G_TYPE_INT:
	  gegl_node_get(node, name, &i_value, NULL);
	  sprintf(buf, "%d", i_value);
	  break;
	case G_TYPE_DOUBLE:
	  gegl_node_get(node, name, &d_value, NULL);
	  sprintf(buf, "%.3f", d_value);
	  break;
	case G_TYPE_STRING:
	  gegl_node_get(node, name, &str_value, NULL);
	  sprintf(buf, "%s", str_value);
	  break;
	}

      if(type == GEGL_TYPE_BUFFER) {
	skip = TRUE;
	d--;
      } else if( type == GEGL_TYPE_COLOR) {
	skip = TRUE;
	GtkWidget *color_button = gtk_button_new_with_label("Select");

	select_color_info* info = malloc(sizeof(select_color_info));
	info->node = node;
	info->property = name;
	info->layer = self;

	g_signal_connect(color_button, "clicked", (GCallback)select_color, info);

	gtk_table_attach(prop_table, name_label, 0, 1, d, d+1, GTK_FILL, GTK_FILL, 1, 1);
	gtk_table_attach(prop_table, color_button, 1, 2, d, d+1, GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL, 1, 1);
      }

      if(!skip)
	{
	  gtk_entry_set_text(GTK_ENTRY(value_entry), buf);

	  gtk_entry_set_width_chars(GTK_ENTRY(value_entry), 2);
	  struct text_prop_data	*data = malloc(sizeof(struct text_prop_data));	//TODO store this in a list and free it when the node is deselected
	  data->node		      = node;
	  data->property		      = name;
	  data->prop_type		      = type;
	  data->layer		      = self;
	  g_signal_connect(value_entry, "activate", G_CALLBACK(text_property_changed), data);

	  gtk_table_attach(prop_table, name_label, 0, 1, d, d+1, GTK_FILL, GTK_FILL, 1, 1);
	  gtk_table_attach(prop_table, value_entry, 1, 2, d, d+1, GTK_EXPAND | GTK_FILL | GTK_SHRINK, GTK_FILL, 1, 1);
	}
    }

  //  gegl_node_process(node);
  GeglGtkView *gtk_view = gegl_gtk_view_new_for_node(node);

  GeglRectangle rect = gegl_node_get_bounding_box(node);

  if(gegl_rectangle_is_infinite_plane(&rect))
    {
      gegl_gtk_view_set_autoscale_policy(gtk_view, GEGL_GTK_VIEW_AUTOSCALE_DISABLED);
      gegl_gtk_view_set_scale(gtk_view, 1.0);
      g_print("Disable autoscale: scale=%f, x=%f, y=%f\n", gegl_gtk_view_get_scale(gtk_view),
      gegl_gtk_view_get_x(gtk_view), gegl_gtk_view_get_y(gtk_view));
    }

  gtk_widget_show(GTK_WIDGET(gtk_view));

  //TODO: draw checkerboard under preview to indicate transparency

  gtk_box_pack_start(GTK_BOX(self->prop_box), GTK_WIDGET(prop_table), FALSE, TRUE, 0);
  gtk_box_pack_start(GTK_BOX(self->prop_box), GTK_WIDGET(gtk_view), TRUE, TRUE, 10);

  GtkWidget* label = gtk_label_new("Click the image\nto open in a\nnew window");
  gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
  gtk_box_pack_start(GTK_BOX(self->prop_box), label, FALSE, TRUE, 10);

  gtk_widget_show_all(self->prop_box);
}