示例#1
0
GeglNode *
gimp_projection_get_sink_node (GimpProjection *proj)
{
  GeglNode   *graph;
  GeglBuffer *buffer;

  g_return_val_if_fail (GIMP_IS_PROJECTION (proj), NULL);

  if (proj->sink_node)
    return proj->sink_node;

  proj->graph = gegl_node_new ();

  g_object_set (proj->graph,
                "dont-cache", TRUE,
                NULL);

  graph = gimp_projectable_get_graph (proj->projectable);
  gegl_node_add_child (proj->graph, graph);

  buffer = gimp_projection_get_buffer (GIMP_PICKABLE (proj));

  proj->sink_node =
    gegl_node_new_child (proj->graph,
                         "operation", "gegl:write-buffer",
                         "buffer",    buffer,
                         NULL);

  gegl_node_connect_to (graph,           "output",
                        proj->sink_node, "input");

  return proj->sink_node;
}
示例#2
0
GeglNode *
gimp_filter_stack_get_graph (GimpFilterStack *stack)
{
  GList    *list;
  GeglNode *first    = NULL;
  GeglNode *previous = NULL;
  GeglNode *input;
  GeglNode *output;

  g_return_val_if_fail (GIMP_IS_FILTER_STACK (stack), NULL);

  if (stack->graph)
    return stack->graph;

  stack->graph = gegl_node_new ();

  for (list = GIMP_LIST (stack)->queue->tail;
       list;
       list = g_list_previous (list))
    {
      GimpFilter *filter = list->data;
      GeglNode   *node   = gimp_filter_get_node (filter);

      if (! first)
        first = node;

      gegl_node_add_child (stack->graph, node);

      if (previous)
        gegl_node_connect_to (previous, "output",
                              node,     "input");

      previous = node;
    }

  input  = gegl_node_get_input_proxy  (stack->graph, "input");
  output = gegl_node_get_output_proxy (stack->graph, "output");

  if (first && previous)
    {
      gegl_node_connect_to (input, "output",
                            first, "input");
      gegl_node_connect_to (previous, "output",
                            output,   "input");
    }
  else
    {
      gegl_node_connect_to (input,  "output",
                            output, "input");
    }

  return stack->graph;
}
示例#3
0
static void
gimp_drawable_apply_operation_private (GimpDrawable       *drawable,
                                       GimpProgress       *progress,
                                       const gchar        *undo_desc,
                                       GeglNode           *operation,
                                       gboolean            linear,
                                       TileManager         *dest_tiles,
                                       const GeglRectangle *rect)
{
  GeglNode      *gegl;
  GeglNode      *input;
  GeglNode      *output;
  GeglProcessor *processor;
  gdouble        value;

  gegl = gegl_node_new ();

  /* Disable caching on all children of the node unless explicitly re-enabled.
   */
  g_object_set (gegl,
                "dont-cache", TRUE,
                NULL);

  input  = gegl_node_new_child (gegl,
                                "operation",    "gimp:tilemanager-source",
                                "tile-manager", gimp_drawable_get_tiles (drawable),
                                "linear",       linear,
                                NULL);
  output = gegl_node_new_child (gegl,
                                "operation",    "gimp:tilemanager-sink",
                                "tile-manager", dest_tiles,
                                "linear",       linear,
                                NULL);

  gegl_node_add_child (gegl, operation);

  gegl_node_link_many (input, operation, output, NULL);

  processor = gegl_node_new_processor (output, rect);

  if (progress)
    gimp_progress_start (progress, undo_desc, FALSE);

  while (gegl_processor_work (processor, &value))
    if (progress)
      gimp_progress_set_value (progress, value);

  g_object_unref (processor);

  g_object_unref (gegl);
}
示例#4
0
/* Test that saving a segment that is a subgraph works */
static void
test_save_segment_subgraph (void)
{
    const gchar * const expected_result = \
"<?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\
        <param name='reset-origin'>false</param>\n\
      </params>\n\
  </node>\n\
</gegl>\n";

    GeglNode *graph, *src, *subgraph;
    GeglNode *input, *op1, *op2, *output;
    gchar *xml;

    graph = gegl_node_new();
    src = gegl_node_new_child(graph, "operation", "gegl:checkerboard", NULL);

    subgraph = gegl_node_new();
    gegl_node_add_child(graph, subgraph);
    g_object_unref(subgraph);

    input = gegl_node_get_input_proxy(subgraph, "input");
    output = gegl_node_get_output_proxy(subgraph, "output");
    op1 = gegl_node_new_child(subgraph, "operation", "gegl:crop",
                              "x", 0.0, "y", 0.0,
                              "width", 0.0, "height", 0.0,
                              NULL);
    op2 = gegl_node_new_child(subgraph, "operation", "gegl:invert-linear", NULL);

    gegl_node_link_many(src, subgraph, NULL);
    gegl_node_link_many(input, op1, op2, output, NULL);

    xml = gegl_node_to_xml_full(subgraph, subgraph, "");

    assert_equivalent_xml(xml, expected_result);

    g_object_unref(graph);
    g_free(xml);
}
示例#5
0
static void
gimp_filter_stack_add (GimpContainer *container,
                       GimpObject    *object)
{
  GimpFilterStack *stack  = GIMP_FILTER_STACK (container);
  GimpFilter      *filter = GIMP_FILTER (object);

  GIMP_CONTAINER_CLASS (parent_class)->add (container, object);

  gimp_filter_stack_update_last_node (stack);

  if (stack->graph)
    {
      gegl_node_add_child (stack->graph, gimp_filter_get_node (filter));
      gimp_filter_stack_add_node (stack, filter);
    }
}
示例#6
0
static void
gimp_warp_tool_add_op (GimpWarpTool *wt,
                       GeglNode     *new_op)
{
  GeglNode *last_op;

  g_return_if_fail (GEGL_IS_NODE (wt->render_node));

  gegl_node_add_child (wt->graph, new_op);

  last_op = gegl_node_get_producer (wt->render_node, "aux", NULL);

  gegl_node_disconnect (wt->render_node, "aux");
  gegl_node_connect_to (last_op,         "output",
                        new_op,          "input");
  gegl_node_connect_to (new_op,          "output",
                        wt->render_node, "aux");
}
示例#7
0
void
gimp_gegl_apply_operation (GeglBuffer          *src_buffer,
                           GimpProgress        *progress,
                           const gchar         *undo_desc,
                           GeglNode            *operation,
                           GeglBuffer          *dest_buffer,
                           const GeglRectangle *dest_rect)
{
  GeglNode      *gegl;
  GeglNode      *dest_node;
  GeglRectangle  rect = { 0, };
  gdouble        value;
  gboolean       progress_active = FALSE;

  g_return_if_fail (src_buffer == NULL || GEGL_IS_BUFFER (src_buffer));
  g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
  g_return_if_fail (GEGL_IS_NODE (operation));
  g_return_if_fail (GEGL_IS_BUFFER (dest_buffer));

  if (dest_rect)
    {
      rect = *dest_rect;
    }
  else
    {
      rect = *GEGL_RECTANGLE (0, 0, gegl_buffer_get_width  (dest_buffer),
                                    gegl_buffer_get_height (dest_buffer));
    }

  gegl = gegl_node_new ();

  if (! gegl_node_get_parent (operation))
    gegl_node_add_child (gegl, operation);

  if (src_buffer && gegl_node_has_pad (operation, "input"))
    {
      GeglNode *src_node;

      /* dup() because reading and writing the same buffer doesn't
       * work with area ops when using a processor. See bug #701875.
       */
      if (progress && (src_buffer == dest_buffer))
        src_buffer = gegl_buffer_dup (src_buffer);
      else
        g_object_ref (src_buffer);

      src_node = gegl_node_new_child (gegl,
                                      "operation", "gegl:buffer-source",
                                      "buffer",    src_buffer,
                                      NULL);

      g_object_unref (src_buffer);

      gegl_node_connect_to (src_node,  "output",
                            operation, "input");
    }

  dest_node = gegl_node_new_child (gegl,
                                   "operation", "gegl:write-buffer",
                                   "buffer",    dest_buffer,
                                   NULL);


  gegl_node_connect_to (operation, "output",
                        dest_node, "input");

  if (progress)
    {
      GeglProcessor *processor;

      processor = gegl_node_new_processor (dest_node, &rect);

      progress_active = gimp_progress_is_active (progress);

      if (progress_active)
        {
          if (undo_desc)
            gimp_progress_set_text (progress, undo_desc);
        }
      else
        {
          gimp_progress_start (progress, undo_desc, FALSE);
        }

      while (gegl_processor_work (processor, &value))
        gimp_progress_set_value (progress, value);

      g_object_unref (processor);
    }
  else
    {
      gegl_node_blit (dest_node, 1.0, &rect,
                      NULL, NULL, 0, GEGL_BLIT_DEFAULT);
    }

  g_object_unref (gegl);

  if (progress && ! progress_active)
    gimp_progress_end (progress);
}
gboolean
gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
                                  GimpProgress        *progress,
                                  const gchar         *undo_desc,
                                  GeglNode            *operation,
                                  GeglBuffer          *dest_buffer,
                                  const GeglRectangle *dest_rect,
                                  GeglBuffer          *cache,
                                  const GeglRectangle *valid_rects,
                                  gint                 n_valid_rects,
                                  gboolean             cancellable)
{
  GeglNode      *gegl;
  GeglNode      *dest_node;
  GeglRectangle  rect = { 0, };
  GeglProcessor *processor        = NULL;
  gboolean       progress_started = FALSE;
  gdouble        value;
  gboolean       cancel           = FALSE;

  g_return_val_if_fail (src_buffer == NULL || GEGL_IS_BUFFER (src_buffer), FALSE);
  g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), FALSE);
  g_return_val_if_fail (GEGL_IS_NODE (operation), FALSE);
  g_return_val_if_fail (GEGL_IS_BUFFER (dest_buffer), FALSE);
  g_return_val_if_fail (cache == NULL || GEGL_IS_BUFFER (cache), FALSE);
  g_return_val_if_fail (valid_rects == NULL || cache != NULL, FALSE);
  g_return_val_if_fail (valid_rects == NULL || n_valid_rects != 0, FALSE);

  if (dest_rect)
    {
      rect = *dest_rect;
    }
  else
    {
      rect = *GEGL_RECTANGLE (0, 0, gegl_buffer_get_width  (dest_buffer),
                                    gegl_buffer_get_height (dest_buffer));
    }

  gegl = gegl_node_new ();

  if (! gegl_node_get_parent (operation))
    gegl_node_add_child (gegl, operation);

  if (src_buffer && gegl_node_has_pad (operation, "input"))
    {
      GeglNode *src_node;

      /* dup() because reading and writing the same buffer doesn't
       * work with area ops when using a processor. See bug #701875.
       */
      if (progress && (src_buffer == dest_buffer))
        src_buffer = gegl_buffer_dup (src_buffer);
      else
        g_object_ref (src_buffer);

      src_node = gegl_node_new_child (gegl,
                                      "operation", "gegl:buffer-source",
                                      "buffer",    src_buffer,
                                      NULL);

      g_object_unref (src_buffer);

      gegl_node_connect_to (src_node,  "output",
                            operation, "input");
    }

  dest_node = gegl_node_new_child (gegl,
                                   "operation", "gegl:write-buffer",
                                   "buffer",    dest_buffer,
                                   NULL);

  gegl_node_connect_to (operation, "output",
                        dest_node, "input");

  if (progress)
    {
      processor = gegl_node_new_processor (dest_node, &rect);

      if (gimp_progress_is_active (progress))
        {
          if (undo_desc)
            gimp_progress_set_text_literal (progress, undo_desc);

          progress_started = FALSE;
          cancellable      = FALSE;
        }
      else
        {
          gimp_progress_start (progress, cancellable, "%s", undo_desc);

          if (cancellable)
            g_signal_connect (progress, "cancel",
                              G_CALLBACK (gimp_gegl_apply_operation_cancel),
                              &cancel);

          progress_started = TRUE;
        }
    }

  if (cache)
    {
      cairo_region_t *region;
      gint            all_pixels;
      gint            done_pixels = 0;
      gint            n_rects;
      gint            i;

      region = cairo_region_create_rectangle ((cairo_rectangle_int_t *) &rect);

      all_pixels = rect.width * rect.height;

      for (i = 0; i < n_valid_rects; i++)
        {
          gegl_buffer_copy (cache,       valid_rects + i, GEGL_ABYSS_NONE,
                            dest_buffer, valid_rects + i);

          cairo_region_subtract_rectangle (region,
                                           (cairo_rectangle_int_t *)
                                           valid_rects + i);

          done_pixels += valid_rects[i].width * valid_rects[i].height;

          if (progress)
            gimp_progress_set_value (progress,
                                     (gdouble) done_pixels /
                                     (gdouble) all_pixels);
        }

      n_rects = cairo_region_num_rectangles (region);

      for (i = 0; ! cancel && (i < n_rects); i++)
        {
          cairo_rectangle_int_t render_rect;

          cairo_region_get_rectangle (region, i, &render_rect);

          if (progress)
            {
              gint rect_pixels = render_rect.width * render_rect.height;

#ifdef REUSE_PROCESSOR
              gegl_processor_set_rectangle (processor,
                                            (GeglRectangle *) &render_rect);
#else
              g_object_unref (processor);
              processor = gegl_node_new_processor (dest_node,
                                                   (GeglRectangle *) &render_rect);
#endif

              while (! cancel && gegl_processor_work (processor, &value))
                {
                  gimp_progress_set_value (progress,
                                           ((gdouble) done_pixels +
                                            value * rect_pixels) /
                                           (gdouble) all_pixels);

                  if (cancellable)
                    while (! cancel && g_main_context_pending (NULL))
                      g_main_context_iteration (NULL, FALSE);
                }

              done_pixels += rect_pixels;
            }
          else
            {
              gegl_node_blit (dest_node, 1.0, (GeglRectangle *) &render_rect,
                              NULL, NULL, 0, GEGL_BLIT_DEFAULT);
            }
        }

      cairo_region_destroy (region);
    }
  else
    {
      if (progress)
        {
          while (! cancel && gegl_processor_work (processor, &value))
            {
              gimp_progress_set_value (progress, value);

              if (cancellable)
                while (! cancel && g_main_context_pending (NULL))
                  g_main_context_iteration (NULL, FALSE);
            }
        }
      else
        {
          gegl_node_blit (dest_node, 1.0, &rect,
                          NULL, NULL, 0, GEGL_BLIT_DEFAULT);
        }
    }

  if (processor)
    g_object_unref (processor);

  g_object_unref (gegl);

  if (progress_started)
    {
      gimp_progress_end (progress);

      if (cancellable)
        g_signal_handlers_disconnect_by_func (progress,
                                              gimp_gegl_apply_operation_cancel,
                                              &cancel);
    }

  return ! cancel;
}