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; }
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; }
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); }
/* 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); }
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); } }
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"); }
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; }