예제 #1
0
static void
set_property(GObject      *gobject,
             guint         property_id,
             const GValue *value,
             GParamSpec   *pspec)
{
    GeglGtkView *self = GEGL_GTK_VIEW(gobject);
    ViewHelper *priv = GET_PRIVATE(self);

    switch (property_id) {
    case PROP_NODE:
        gegl_gtk_view_set_node(self, GEGL_NODE(g_value_get_object(value)));
        break;
    case PROP_BLOCK:
        priv->block = g_value_get_boolean(value);
        break;
    case PROP_SCALE:
        gegl_gtk_view_set_scale(self, g_value_get_double(value));
        break;
    case PROP_AUTOSCALE_POLICY:
        gegl_gtk_view_set_autoscale_policy(self, g_value_get_enum(value));
        break;
    default:

        G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, property_id, pspec);
        break;
    }
}
예제 #2
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");*/
    }
}
예제 #3
0
static void
photos_print_setup_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
    PhotosPrintSetup *self = PHOTOS_PRINT_SETUP (object);
    PhotosPrintSetupPrivate *priv = self->priv;

    switch (prop_id)
    {
    case PROP_NODE:
    {
        GdkPixbuf *pixbuf;

        priv->node = GEGL_NODE (g_value_dup_object (value));
        pixbuf = photos_utils_create_pixbuf_from_node (priv->node);
        if (pixbuf != NULL)
        {
            g_object_set (priv->preview, "pixbuf", pixbuf, NULL);
            g_object_unref (pixbuf);
        }
    }
    break;
    case PROP_PAGE_SETUP:
        priv->page_setup = GTK_PAGE_SETUP (g_value_get_object (value));
        break;
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}
예제 #4
0
/**
 * gegl_graph_prepare:
 * @path: The traversal path
 * 
 * Prepare all nodes, initializing their output formats and have rects.
 */
void
gegl_graph_prepare (GeglGraphTraversal *path)
{
  GList *list_iter = 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_mutex_lock (&node->mutex);

    gegl_operation_prepare (operation);
    node->have_rect = gegl_operation_get_bounding_box (operation);
    node->valid_have_rect = TRUE;

    if (node->cache)
      {
        gegl_buffer_set_extent (GEGL_BUFFER (node->cache),
                                &node->have_rect);
      }

    g_mutex_unlock (&node->mutex);
    
    if (!g_hash_table_contains (path->contexts, node))
      {
        GeglOperationContext *context = gegl_operation_context_new (node->operation);
        
        g_hash_table_insert (path->contexts,
                             node,
                             context);
      }
  }
}
예제 #5
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);
    }
}
예제 #6
0
/**
 * gegl_graph_get_bounding_box:
 * @path: The traversal path
 * 
 * Get output bounding box for this graph, which is the
 * have rect of the final node.
 *
 * Return value: Output rect of @path
 */
GeglRectangle
gegl_graph_get_bounding_box (GeglGraphTraversal *path)
{
  GeglNode *node = GEGL_NODE (g_list_last (path->dfs_path)->data);
  if (node->valid_have_rect)
    {
      return node->have_rect;
    }
  return *GEGL_RECTANGLE(0, 0, 0, 0);
}
예제 #7
0
static void
set_property (GObject      *gobject,
              guint         property_id,
              const GValue *value,
              GParamSpec   *pspec)
{
    GeglCache *self = GEGL_CACHE (gobject);

    switch (property_id)
    {
    case PROP_NODE:
        g_mutex_lock (self->mutex);
        if (self->node)
        {
            gulong handler;
            handler = g_signal_handler_find (self->node, G_SIGNAL_MATCH_DATA,
                                             g_signal_lookup ("invalidated",
                                                     GEGL_TYPE_NODE),
                                             0, NULL, NULL, self);
            if (handler)
            {
                g_signal_handler_disconnect (self->node, handler);
            }
        }
        /* just getting the node, the cache holds no reference on the node,
         * it is the node that holds reference on the cache
         */
        self->node = GEGL_NODE (g_value_get_object (value));
        g_signal_connect (G_OBJECT (self->node), "invalidated",
                          G_CALLBACK (node_invalidated), self);
        g_mutex_unlock (self->mutex);
        break;

    case PROP_X:
        g_object_set_property (gobject, "GeglBuffer::x", value);
        break;

    case PROP_Y:
        g_object_set_property (gobject, "GeglBuffer::y", value);
        break;

    case PROP_WIDTH:
        g_object_set_property (gobject, "GeglBuffer::width", value);
        break;

    case PROP_HEIGHT:
        g_object_set_property (gobject, "GeglBuffer::height", value);
        break;

    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
        break;
    }
}
예제 #8
0
/* Loading a graph with X child nodes should result in
 * a GeglNode with X children, where the bottom-most node
 * is child 0.
 *
 * Note: Properties are not tested. */
static void
test_load_multiple_nodes (void)
{
    const gchar * const xml = \
"<?xml version='1.0' encoding='UTF-8'?>\n\
<gegl>\n\
  <node operation='gegl:invert-linear'>\n\
  </node>\n\
  <node operation='gegl:crop'>\n\
      <params>\n\
        <param name='x'>0</param>\n\
        <param name='y'>0</param>\n\
        <param name='width'>0</param>\n\
        <param name='height'>0</param>\n\
      </params>\n\
  </node>\n\
</gegl>\n";

    GeglNode *graph, *node;
	GSList *children;
    gchar *op_name;

    graph = gegl_node_new_from_xml(xml, "");
    g_assert(graph);

    children = gegl_node_get_children(graph);
    g_assert_cmpuint(g_slist_length(children), ==, 2);

    node = GEGL_NODE(g_slist_nth_data(children, 0));
    gegl_node_get(node, "operation", &op_name, NULL);
    g_assert_cmpstr(op_name, ==, "gegl:crop");
    g_free(op_name);

    node = GEGL_NODE(g_slist_nth_data(children, 1));
    gegl_node_get(node, "operation", &op_name, NULL);
    g_assert_cmpstr(op_name, ==, "gegl:invert-linear");
    g_free(op_name);

	g_slist_free(children);
    g_object_unref(graph);
}
예제 #9
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]);
	}
    }
}
예제 #10
0
static void
gegl_introspect_load_cache (GeglProperties *op_introspect)
{
  GeglBuffer *new_buffer   = NULL;
  GeglNode   *png_load     = NULL;
  GeglNode   *buffer_sink  = NULL;
  gchar      *dot_string   = NULL;
  gchar      *png_filename = NULL;
  gchar      *dot_filename = NULL;
  gchar      *dot_cmd      = NULL;

  if (op_introspect->user_data || op_introspect->node == NULL)
    return;

  /* Construct temp filenames */
  dot_filename = g_build_filename (g_get_tmp_dir (), "gegl-introspect.dot", NULL);
  png_filename = g_build_filename (g_get_tmp_dir (), "gegl-introspect.png", NULL);

  /* Construct the .dot source */
  dot_string = gegl_to_dot (GEGL_NODE (op_introspect->node));
  g_file_set_contents (dot_filename, dot_string, -1, NULL);

  /* Process the .dot to a .png */
  dot_cmd = g_strdup_printf ("dot -o %s -Tpng %s", png_filename, dot_filename);
  if (system (dot_cmd) == -1)
    g_warning ("Error executing GraphViz dot program");

  /* Create a graph that loads the png into a GeglBuffer and process
   * it
   */
  png_load = gegl_node_new_child (NULL,
                                  "operation", "gegl:png-load",
                                  "path",      png_filename,
                                  NULL);
  buffer_sink = gegl_node_new_child (NULL,
                                     "operation", "gegl:buffer-sink",
                                     "buffer",    &new_buffer,
                                     NULL);
  gegl_node_link_many (png_load, buffer_sink, NULL);
  gegl_node_process (buffer_sink);

  op_introspect->user_data= new_buffer;

  /* Cleanup */
  g_object_unref (buffer_sink);
  g_object_unref (png_load);
  g_free (dot_string);
  g_free (dot_cmd);
  g_free (dot_filename);
  g_free (png_filename);
}
static void
photos_print_operation_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
  PhotosPrintOperation *self = PHOTOS_PRINT_OPERATION (object);

  switch (prop_id)
    {
    case PROP_ITEM:
      self->item = PHOTOS_BASE_ITEM (g_value_dup_object (value));
      break;

    case PROP_NODE:
      self->node = GEGL_NODE (g_value_dup_object (value));
      break;

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}
예제 #12
0
static void
photos_image_view_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
  PhotosImageView *self = PHOTOS_IMAGE_VIEW (object);

  switch (prop_id)
    {
    case PROP_NODE:
      {
        GeglNode *node;

        node = GEGL_NODE (g_value_get_object (value));
        photos_image_view_set_node (self, node);
        break;
      }

    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}
예제 #13
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;
}
예제 #14
0
void
gegl_graph_prepare_request (GeglGraphTraversal  *path,
                            const GeglRectangle *request_roi,
                            gint                 level)
{
  GList *list_iter = NULL;
  static const GeglRectangle empty_rect = {0, 0, 0, 0};

  g_return_if_fail (path->bfs_path);

  if (path->rects_dirty)
    {
      /* Zero all the needs rects so we can intersect with them below */
      for (list_iter = path->bfs_path; list_iter; list_iter = list_iter->next)
        {
          GeglNode *node = GEGL_NODE (list_iter->data);
          GeglOperationContext *context = g_hash_table_lookup (path->contexts, node);

          /* We only need to reset the need rect, result will always get overwritten */
          gegl_operation_context_set_need_rect (context, &empty_rect);

          /* Reset cached status, because the rect we need may have changed */
          context->cached = FALSE;
        }
    }

  path->rects_dirty = TRUE;

  {
    /* Prep the first node */
    GeglNode *node = GEGL_NODE (path->bfs_path->data);
    GeglOperationContext *context = g_hash_table_lookup (path->contexts, node);
    GeglRectangle new_need;

    g_return_if_fail (context);

    gegl_rectangle_intersect (&new_need, &node->have_rect, request_roi);

    gegl_operation_context_set_need_rect (context, &new_need);
    gegl_operation_context_set_result_rect (context, &new_need);
  }
  
  /* Iterate over all the nodes and propagate the requested rectangle */
  for (list_iter = path->bfs_path; list_iter; list_iter = list_iter->next)
    {
      GeglNode             *node      = GEGL_NODE (list_iter->data);
      GeglOperation        *operation = node->operation;
      GeglOperationContext *context;
      GeglRectangle        *request;
      GSList               *input_pads;
      
      context = g_hash_table_lookup (path->contexts, node);
      g_return_if_fail (context);
      
      request = gegl_operation_context_get_need_rect (context);

      if (request->width == 0 || request->height == 0)
        {
          gegl_operation_context_set_result_rect (context, &empty_rect);
          continue;
        }
      
      if (node->cache)
        {
          gint i;
          for (i = level; i >=0 && !context->cached; i--)
          {
            if (gegl_region_rect_in (node->cache->valid_region[level], request) == GEGL_OVERLAP_RECTANGLE_IN)
            {
              /* This node is cached and the cache fulfills our need rect */
              context->cached = TRUE;
              gegl_operation_context_set_result_rect (context, &empty_rect);
            }
          }
          if (context->cached)
            continue;
        }

      {
        /* Expand request if the operation has a minimum processing requirement */
        GeglRectangle full_request = gegl_operation_get_cached_region (operation, request);

        gegl_operation_context_set_need_rect (context, &full_request);

        /* FIXME: We could trim this down based on the cache, instead of being all or nothing */
        gegl_operation_context_set_result_rect (context, request);

        for (input_pads = node->input_pads; input_pads; input_pads = input_pads->next)
          {
            GeglPad *source_pad = gegl_pad_get_connected_to (input_pads->data);

            if (source_pad)
              {
                GeglNode             *source_node    = gegl_pad_get_node (source_pad);
                GeglOperationContext *source_context = g_hash_table_lookup (path->contexts, source_node);
                const gchar          *pad_name       = gegl_pad_get_name (input_pads->data);

                GeglRectangle rect, current_need, new_need;

                /* Combine this need rect with any existing request */
                rect = gegl_operation_get_required_for_output (operation, pad_name, &full_request);
                current_need = *gegl_operation_context_get_need_rect (source_context);

                gegl_rectangle_bounding_box (&new_need, &rect, &current_need);

                /* Limit request to the nodes output */
                gegl_rectangle_intersect (&new_need, &source_node->have_rect, &new_need);

                gegl_operation_context_set_need_rect (source_context, &new_need);
              }
          }
      }
    }
}