1 diff --git a/Makefile.am b/Makefile.am
2 index 3307e47..01a767f 100644
5 @@ -8,23 +8,13 @@ SUBDIRS=\
9 -pkgconfigdir = $(libdir)/pkgconfig
12 -pkgconfig_DATA = gegl-gtk2-0.1.pc
14 -pkgconfig_DATA = gegl-gtk3-0.1.pc
19 docs/reference/gegl-gtk-docs.xml.in \
21 - gegl-gtk2-0.1.pc.in \
22 - gegl-gtk3-0.1.pc.in \
25 -DISTCHECK_CONFIGURE_FLAGS = --disable-introspection --enable-gtk-doc
26 +DISTCHECK_CONFIGURE_FLAGS = --disable-introspection --enable-gtk-doc
30 diff --git a/README b/README
31 index b66e7f9..c19b182 100644
34 @@ -5,7 +5,7 @@ Maintainer: Jon Nordby <jononor@gmail.com>
35 Homepage: http://www.gegl.org
36 Code: http://git.gnome.org/browse/gegl-gtk/
37 Bugtracker: http://bugs.gnome.org, product GEGL, component gegl-gtk
38 -Mailinglist: http://blog.gmane.org/gmane.comp.video.gegl.devel
39 +Mailinglist: http://mail.gnome.org/mailman/listinfo/gegl-developer-list
42 gegl-gtk uses an autotools build system. To install do:
43 diff --git a/configure.ac b/configure.ac
44 index b5b7c67..16cd1da 100644
47 @@ -106,7 +106,7 @@ AC_SUBST(GTK3_REQUIRED_VERSION)
49 AC_SUBST(PACKAGE_NAME)
51 -GEGL_PLUGINS_DIR=`pkg-config gegl --variable=pluginsdir`
52 +GEGL_PLUGINS_DIR=`pkg-config gegl-0.2 --variable=pluginsdir`
53 if test -z $GEGL_PLUGINS_DIR; then
54 GEGL_PREFIX=`pkg-config gegl --variable=prefix`
55 GEGL_PLUGINS_DIR=$GEGL_PREFIX/lib/gegl-0.1
56 @@ -116,7 +116,10 @@ AC_SUBST(GEGL_PLUGINS_DIR)
57 dnl ==========================================================================
59 AM_INIT_AUTOMAKE(no-define no-dist-gzip foreign)
60 -AM_CONFIG_HEADER(config.h)
61 +AC_CONFIG_HEADERS(config.h)
63 +GEGL_GTK_SERVER=www.gegl.org
64 +AC_SUBST(GEGL_GTK_SERVER)
66 dnl Initialize libtool
68 @@ -181,19 +184,19 @@ PKG_CHECK_MODULES(BABL, babl >= babl_required_version)
69 ######################################
71 ######################################
72 -PKG_CHECK_MODULES(GEGL, gegl >= gegl_required_version)
73 +PKG_CHECK_MODULES(GEGL, gegl-0.2 >= gegl_required_version)
75 ######################################
76 # Checks for required deps
77 ######################################
78 AC_MSG_CHECKING([which gtk+ version to compile against])
80 - [AS_HELP_STRING([--with-gtk=2.0|3.0],[which gtk+ version to compile against (default: 2.0)])],
81 + [AS_HELP_STRING([--with-gtk=2.0|3.0],[which gtk+ version to compile against (default: 3.0)])],
84 *) AC_MSG_ERROR([invalid gtk version specified]) ;;
88 AC_MSG_RESULT([$with_gtk])
91 @@ -210,6 +213,8 @@ case "$with_gtk" in
95 +m4_define([gegl_gtk_gtk_version], [$GEGL_GTK_GTK_VERSION])
97 AC_SUBST(GEGL_GTK_GTK_VERSION)
99 AM_CONDITIONAL(HAVE_GTK2, test "$have_gtk" = "2.0")
100 @@ -248,6 +253,11 @@ fi
102 AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$enable_introspection" = "xyes")
104 +if test "x$GIRDIR" = "x"; then
105 + GIRDIR=$(datadir)/vala/vapi
109 ########################
111 ########################
112 @@ -269,6 +279,13 @@ fi
113 have_vala=$have_vapigen
114 AM_CONDITIONAL(HAVE_VALA, test "$have_vala" = "yes")
116 +if test "x$VAPIDIR" = "x"; then
117 + VAPIDIR=$(datadir)/vala/vapi
121 +# `$PKG_CONFIG --variable=vapidir $valapkg`
123 ######################################
124 # Checks for gtk-doc and docbook-tools
125 ######################################
126 @@ -318,17 +335,25 @@ if test -z "${MAINTAINER_MODE_TRUE}"; then
127 GTK_CFLAGS="-DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED $GTK_CFLAGS"
131 +# Files with versions in their names
134 +gegl_gtk_gtk_version-gegl_gtk_api_version.metadata:gegl-gtk/GeglGtk.metadata.in
135 +gegl-gtk/gegl-gtk2-gegl_gtk_api_version.pc:gegl-gtk/gegl-gtk2.pc.in
136 +gegl-gtk/gegl-gtk3-gegl_gtk_api_version.pc:gegl-gtk/gegl-gtk3.pc.in
145 +examples/vala/Makefile
147 docs/reference/Makefile
148 docs/reference/gegl-gtk-docs.xml
153 dnl Print a summary of features enabled/disabled:
154 #diff --git a/examples/.gitignore b/examples/.gitignore
155 #index 264e3fe..944a61e 100644
156 #--- a/examples/.gitignore
157 #+++ b/examples/.gitignore
161 # gegl-gtk-display-op
163 diff --git a/examples/Makefile.am b/examples/Makefile.am
164 index d080bd3..7e08a39 100644
165 --- a/examples/Makefile.am
166 +++ b/examples/Makefile.am
171 +if HAVE_INTROSPECTION
175 +endif # HAVE_INTROSPECTION
176 #diff --git a/examples/c/.gitignore b/examples/c/.gitignore
177 #index 54e0920..81c2fa4 100644
178 #--- a/examples/c/.gitignore
179 #+++ b/examples/c/.gitignore
183 diff --git a/examples/c/gegl-gtk-basic.c b/examples/c/gegl-gtk-basic.c
184 index 1c5c487..0188f57 100644
185 --- a/examples/c/gegl-gtk-basic.c
186 +++ b/examples/c/gegl-gtk-basic.c
187 @@ -32,7 +32,6 @@ main(gint argc,
188 GeglNode *graph = NULL;
189 GeglNode *node = NULL;
191 - g_thread_init(NULL);
192 gtk_init(&argc, &argv);
193 gegl_init(&argc, &argv);
195 diff --git a/examples/c/gegl-gtk-display-op.c b/examples/c/gegl-gtk-display-op.c
196 index 2c0ff72..12aa0d9 100644
197 --- a/examples/c/gegl-gtk-display-op.c
198 +++ b/examples/c/gegl-gtk-display-op.c
199 @@ -29,7 +29,6 @@ main(gint argc,
200 GeglNode *node = NULL;
201 GeglNode *display = NULL;
203 - g_thread_init(NULL);
204 gegl_init(&argc, &argv);
207 diff --git a/examples/c/gegl-gtk-paint.c b/examples/c/gegl-gtk-paint.c
208 index f71a9b7..eaab947 100644
209 --- a/examples/c/gegl-gtk-paint.c
210 +++ b/examples/c/gegl-gtk-paint.c
211 @@ -133,7 +133,7 @@ static gboolean paint_release(GtkWidget *widget,
212 processor = gegl_node_new_processor(writebuf, &roi);
213 while (gegl_processor_work(processor, NULL)) ;
215 - gegl_processor_destroy(processor);
216 + g_object_unref(processor);
217 g_object_unref(writebuf);
219 gegl_node_link_many(top, out, NULL);
220 @@ -176,7 +176,6 @@ gint
224 - g_thread_init(NULL);
225 gtk_init(&argc, &argv);
226 gegl_init(&argc, &argv);
228 @@ -241,7 +240,7 @@ main(gint argc,
231 g_object_unref(gegl);
232 - gegl_buffer_destroy(buffer);
233 + g_object_unref(buffer);
237 diff --git a/examples/c/gegl-gtk-scroll.c b/examples/c/gegl-gtk-scroll.c
238 index 367dd56..65f9620 100644
239 --- a/examples/c/gegl-gtk-scroll.c
240 +++ b/examples/c/gegl-gtk-scroll.c
241 @@ -33,7 +33,6 @@ main(gint argc,
242 GeglNode *graph = NULL;
243 GeglNode *node = NULL;
245 - g_thread_init(NULL);
246 gtk_init(&argc, &argv);
247 gegl_init(&argc, &argv);
249 diff --git a/examples/c/gegl-gtk-transform.c b/examples/c/gegl-gtk-transform.c
251 index 0000000..3e52eed
253 +++ b/examples/c/gegl-gtk-transform.c
255 +/* This file is part of GEGL-GTK
257 + * This program is free software; you can redistribute it and/or modify
258 + * it under the terms of the GNU General Public License as published by
259 + * the Free Software Foundation; either version 3 of the License, or
260 + * (at your option) any later version.
262 + * This program is distributed in the hope that it will be useful,
263 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
264 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
265 + * GNU General Public License for more details.
267 + * You should have received a copy of the GNU General Public License
268 + * along with this program; if not, see <http://www.gnu.org/licenses/>.
270 + * Copyright (C) 2011 Jon Nordby <jononor@gmail.com>
276 +#include <gtk/gtk.h>
277 +#include <gegl-gtk.h>
279 +static gboolean motion_event (GtkWidget *widget,
280 + GdkEventMotion *event,
284 + static gboolean has_last_pos = FALSE;
285 + static gfloat last_x, last_y;
287 + if (event->state & GDK_BUTTON1_MASK) {
288 + if (has_last_pos) {
290 + g_object_set (view, "x", -last_x, "y", -last_y, NULL);
295 + has_last_pos = TRUE;
306 + GtkWidget *window = NULL;
307 + GtkWidget *view = NULL;
308 + GtkWidget *eventbox = NULL;
309 + GeglNode *graph = NULL;
310 + GeglNode *node = NULL;
312 + gtk_init (&argc, &argv);
313 + gegl_init (&argc, &argv);
316 + g_print ("Usage: %s <FILENAME>\n", argv[0]);
320 + /* Build graph that loads an image */
321 + graph = gegl_node_new ();
322 + node = gegl_node_new_child (graph,
323 + "operation", "gegl:load",
324 + "path", argv[1], NULL);
326 + gegl_node_process (node);
329 + window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
330 + gtk_window_set_title (GTK_WINDOW (window), "GEGL-GTK transformation example");
332 + eventbox = gtk_event_box_new ();
333 + view = g_object_new (GEGL_GTK_TYPE_VIEW, "node", node, NULL);
335 + g_signal_connect (G_OBJECT (eventbox), "motion-notify-event",
336 + (GCallback) motion_event, (gpointer)view);
338 + gtk_container_add (GTK_CONTAINER (eventbox), view);
339 + gtk_container_add (GTK_CONTAINER (window), eventbox);
341 + g_signal_connect (G_OBJECT (window), "delete-event",
342 + G_CALLBACK (gtk_main_quit), window);
343 + gtk_widget_show_all (window);
349 + g_object_unref (graph);
350 + gtk_widget_destroy (window);
354 diff --git a/examples/c/gegl-gtk-warp.c b/examples/c/gegl-gtk-warp.c
356 index 0000000..1ec1d31
358 +++ b/examples/c/gegl-gtk-warp.c
360 +/* This file is part of GEGL-GTK
362 + * This program is free software; you can redistribute it and/or modify
363 + * it under the terms of the GNU General Public License as published by
364 + * the Free Software Foundation; either version 3 of the License, or
365 + * (at your option) any later version.
367 + * This program is distributed in the hope that it will be useful,
368 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
369 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
370 + * GNU General Public License for more details.
372 + * You should have received a copy of the GNU General Public License
373 + * along with this program; if not, see <http://www.gnu.org/licenses/>.
375 + * Copyright (C) 2011 Michael Muré <batolettre@gmail.com>
381 +#include <gtk/gtk.h>
382 +#include <gegl-gtk.h>
387 + GEGL_WARP_BEHAVIOR_MOVE,
388 + GEGL_WARP_BEHAVIOR_GROW,
389 + GEGL_WARP_BEHAVIOR_SHRINK,
390 + GEGL_WARP_BEHAVIOR_SWIRL_CW,
391 + GEGL_WARP_BEHAVIOR_SWIRL_CCW,
392 + GEGL_WARP_BEHAVIOR_ERASE,
393 + GEGL_WARP_BEHAVIOR_SMOOTH
394 +} GeglWarpBehavior; */
397 +static gdouble cursor_x; /* Hold the cursor x position */
398 +static gdouble cursor_y; /* Hold the cursor y position */
400 +static GeglBuffer *coords_buffer; /* Gegl buffer where coordinates are stored */
402 +static GeglNode *graph; /* Top level GeglNode. All others node are child of it */
403 +static GeglNode *read_coords_buffer_node; /* Gegl node that read in the coords buffer */
404 +static GeglNode *render_node; /* Gegl node to render the transformation */
406 +static GeglPath *current_stroke;
407 +static guint stroke_timer;
409 +#define STROKE_PERIOD 100
412 +static gdouble strength = 100;
413 +static gdouble size = 40;
414 +static gdouble hardness = 0.5;
415 +static GeglWarpBehavior behavior = GEGL_WARP_BEHAVIOR_MOVE;
417 +/* gegl-gtk stuff */
420 +GtkWidget *eventbox;
422 +static GeglRectangle rect; /* size for the view/window */
423 +static GeglBuffer *original_buffer = NULL; /* image to be warped */
424 +static GeglNode *readbuf; /* node to read this image */
427 +add_event_timer (gpointer data)
429 + gegl_path_append (current_stroke,
430 + 'L', cursor_x, cursor_y);
437 + GeglNode *new_op, *last_op;
439 + new_op = gegl_node_new_child (graph,
440 + "operation", "gegl:warp",
441 + "behavior", behavior,
442 + "strength", strength,
444 + "hardness", hardness,
445 + "stroke", current_stroke,
448 + last_op = gegl_node_get_producer (render_node, "aux", NULL);
450 + gegl_node_disconnect (render_node, "aux");
452 + gegl_node_connect_to (last_op, "output", new_op, "input");
453 + gegl_node_connect_to (new_op, "output", render_node, "aux");
456 +static gboolean paint_press (GtkWidget *widget,
457 + GdkEventButton *event)
459 + if (current_stroke)
460 + g_object_unref (current_stroke);
462 + current_stroke = gegl_path_new ();
463 + gegl_path_append (current_stroke,
464 + 'M', event->x, event->y);
466 + cursor_x = event->x;
467 + cursor_y = event->y;
471 + stroke_timer = g_timeout_add (STROKE_PERIOD, add_event_timer, NULL);
476 +static gboolean paint_motion (GtkWidget *widget,
477 + GdkEventMotion *event)
479 + cursor_x = event->x;
480 + cursor_y = event->y;
486 +static gboolean paint_release (GtkWidget *widget,
487 + GdkEventButton *event)
489 + g_source_remove (stroke_timer);
497 + printf ("Initialize coordinate buffer (%d,%d) at %d,%d\n", rect.width, rect.height, rect.x, rect.y);
498 + coords_buffer = gegl_buffer_new (&rect, babl_format_n (babl_type ("float"), 2));
500 + graph = gegl_node_new ();
502 + readbuf = gegl_node_new_child (graph,
503 + "operation", "gegl:buffer-source",
504 + "buffer", original_buffer,
507 + read_coords_buffer_node = gegl_node_new_child (graph,
508 + "operation", "gegl:buffer-source",
509 + "buffer", coords_buffer,
512 + render_node = gegl_node_new_child (graph,
513 + "operation", "gegl:map-relative",
517 + gegl_node_connect_to (readbuf, "output",
518 + render_node, "input");
520 + gegl_node_connect_to (read_coords_buffer_node, "output",
521 + render_node, "aux");
528 + if (argv[1] == NULL)
530 + printf("usage: %s filename.gegl\n", argv[0]);
531 + printf("filename.gegl must be a Gegl buffer file, for instance created with the 2geglbuffer example from Gegl.\n");
535 + gtk_init (&argc, &argv);
536 + gegl_init (&argc, &argv);
538 + window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
539 + gtk_window_set_title (GTK_WINDOW (window), "Warp example");
541 + original_buffer = gegl_buffer_open (argv[1]);
542 + rect = *gegl_buffer_get_extent(original_buffer);
546 + view = g_object_new (GEGL_GTK_TYPE_VIEW, "node", render_node, NULL);
548 + eventbox = gtk_event_box_new ();
550 + g_signal_connect (G_OBJECT (eventbox), "motion-notify-event",
551 + (GCallback) paint_motion, NULL);
552 + g_signal_connect (G_OBJECT (eventbox), "button-press-event",
553 + (GCallback) paint_press, NULL);
554 + g_signal_connect (G_OBJECT (eventbox), "button-release-event",
555 + (GCallback) paint_release, NULL);
556 + gtk_widget_add_events (eventbox, GDK_BUTTON_RELEASE_MASK);
558 + gtk_container_add (GTK_CONTAINER (eventbox), view);
559 + gtk_container_add (GTK_CONTAINER (window), eventbox);
560 + gtk_widget_set_size_request (view, rect.width, rect.height);
562 + g_signal_connect (G_OBJECT (window), "delete-event",
563 + G_CALLBACK (gtk_main_quit), window);
564 + gtk_widget_show_all (window);
567 + g_object_unref (graph);
568 + g_object_unref (original_buffer);
569 + g_object_unref (coords_buffer);
574 diff --git a/examples/vala/Makefile.am b/examples/vala/Makefile.am
576 index 0000000..1392955
578 +++ b/examples/vala/Makefile.am
583 +VALA_FILES = $(wildcard $(srcdir)/*.vala)
584 +EXTRA_DIST = $(VALA_FILES)
585 +bins = $(subst $(srcdir)/,,$(VALA_FILES:.vala=))
587 +vapi_dir = ../../gegl-gtk
588 +vala_pkg = gegl-gtk@GEGL_GTK_GTK_VERSION@-@GEGL_GTK_API_VERSION@
592 +gegl-gtk-basic: gegl-gtk-basic.vala $(vapi_dir)/$(vala_pkg).vapi
593 + valac --pkg $(vala_pkg) --vapidir=@VAPIDIR@ --vapidir=$(vapi_dir) -o $@ $<
599 diff --git a/examples/vala/gegl-gtk-basic.vala b/examples/vala/gegl-gtk-basic.vala
601 index 0000000..1a9882f
603 +++ b/examples/vala/gegl-gtk-basic.vala
606 +class Examples.Basic : GLib.Object {
608 + public static int main(string[] args) {
609 + Gtk.init(ref args);
612 + var graph = new Gegl.Node();
613 + var node = graph.create_child("gegl:load");
614 + node.set_property("path", args[1]);
616 + var window = new Gtk.Window();
617 + window.title = "GEGL GTK Basic Vala example";
618 + window.set_default_size(300, 300);
619 + window.destroy.connect(Gtk.main_quit);
621 + var node_view = new GeglGtk.View();
622 + node_view.set_node(node);
624 + window.add(node_view);
633 #diff --git a/gegl-gtk/.gitignore b/gegl-gtk/.gitignore
634 #index 95b99f3..9324c98 100644
635 #--- a/gegl-gtk/.gitignore
636 #+++ b/gegl-gtk/.gitignore
644 diff --git a/gegl-gtk/GeglGtk.metadata.in b/gegl-gtk/GeglGtk.metadata.in
646 index 0000000..7630a9e
648 +++ b/gegl-gtk/GeglGtk.metadata.in
650 +GeglGtk2 cheader_filename="gegl-gtk.h"
651 +GeglGtk3 cheader_filename="gegl-gtk.h"
652 diff --git a/gegl-gtk/Makefile.am b/gegl-gtk/Makefile.am
653 index 426acd8..d45b163 100644
654 --- a/gegl-gtk/Makefile.am
655 +++ b/gegl-gtk/Makefile.am
662 @@ -41,6 +43,19 @@ gegl-gtk-marshal.c: gegl-gtk-marshal.h
664 EXTRA_DIST += gegl-gtk-marshal.list
667 +pkgconfigdir = $(libdir)/pkgconfig
670 +pkgconfig_DATA = gegl-gtk2-0.1.pc
672 +pkgconfig_DATA = gegl-gtk3-0.1.pc
679 ### GObject introspection
680 -include $(INTROSPECTION_MAKEFILE)
682 @@ -56,7 +71,7 @@ GeglGtk@GEGL_GTK_GTK_VERSION@_0_1_gir_CFLAGS = $(INCLUDES)
683 GeglGtk@GEGL_GTK_GTK_VERSION@_0_1_gir_FILES = $(sources) $(headers)
684 GeglGtk@GEGL_GTK_GTK_VERSION@_0_1_gir_LIBS = libgegl-gtk@GEGL_GTK_GTK_VERSION@-@GEGL_GTK_API_VERSION@.la
686 -GeglGtk@GEGL_GTK_GTK_VERSION@_0_1_gir_INCLUDES = Gtk-@GEGL_GTK_GTK_VERSION@.0 Gegl-0.1 Babl-0.1
687 +GeglGtk@GEGL_GTK_GTK_VERSION@_0_1_gir_INCLUDES = Gtk-@GEGL_GTK_GTK_VERSION@.0 Gegl-0.2
689 INTROSPECTION_GIRS += GeglGtk@GEGL_GTK_GTK_VERSION@-@GEGL_GTK_API_VERSION@.gir
691 @@ -73,11 +88,12 @@ if HAVE_VALA
692 gegl-gtk@GEGL_GTK_GTK_VERSION@-@GEGL_GTK_API_VERSION@.vapi: \
693 GeglGtk@GEGL_GTK_GTK_VERSION@-@GEGL_GTK_API_VERSION@.gir
695 - $(VAPIGEN) --pkg gtk+-@GEGL_GTK_GTK_VERSION@.0 \
696 + $(VAPIGEN) --pkg gtk+-@GEGL_GTK_GTK_VERSION@.0 --pkg Gegl-0.2 \
697 --library=gegl-gtk@GEGL_GTK_GTK_VERSION@-@GEGL_GTK_API_VERSION@ \
698 + --vapidir=@VAPIDIR@ --girdir=@GIRDIR@ \
699 GeglGtk@GEGL_GTK_GTK_VERSION@-@GEGL_GTK_API_VERSION@.gir
701 -vapidir=$(datadir)/vala/vapi
704 gegl-gtk@GEGL_GTK_GTK_VERSION@-@GEGL_GTK_API_VERSION@.vapi \
705 gegl-gtk@GEGL_GTK_GTK_VERSION@-@GEGL_GTK_API_VERSION@.deps
706 @@ -91,3 +107,6 @@ endif # HAVE_INTROSPECTION
708 gegl-gtk2-@GEGL_GTK_API_VERSION@.deps \
709 gegl-gtk3-@GEGL_GTK_API_VERSION@.deps
712 + GeglGtk@GEGL_GTK_GTK_VERSION@-@GEGL_GTK_API_VERSION@.metadata
713 diff --git a/gegl-gtk/gegl-gtk-view.c b/gegl-gtk/gegl-gtk-view.c
714 index dd48323..e0007c1 100644
715 --- a/gegl-gtk/gegl-gtk-view.c
716 +++ b/gegl-gtk/gegl-gtk-view.c
717 @@ -462,6 +462,14 @@ gegl_gtk_view_new()
718 return GEGL_GTK_VIEW(g_object_new(GEGL_GTK_TYPE_VIEW, NULL));
722 +gegl_gtk_view_new_for_buffer(GeglBuffer *buffer)
724 + GeglNode *node = gegl_node("gegl:buffer-source",
725 + "buffer", buffer, NULL);
726 + return gegl_gtk_view_new_for_node(node);
730 * gegl_gtk_view_new_for_node:
731 * @node: The #GeglNode to display
732 diff --git a/gegl-gtk/gegl-gtk-view.h b/gegl-gtk/gegl-gtk-view.h
733 index 4642f6d..d6611c7 100644
734 --- a/gegl-gtk/gegl-gtk-view.h
735 +++ b/gegl-gtk/gegl-gtk-view.h
736 @@ -55,6 +55,7 @@ GType gegl_gtk_view_get_type(void) G_GNUC_CONST;
738 GeglGtkView *gegl_gtk_view_new(void);
739 GeglGtkView *gegl_gtk_view_new_for_node(GeglNode *node);
740 +GeglGtkView *gegl_gtk_view_new_for_buffer(GeglBuffer *buffer);
742 void gegl_gtk_view_set_node(GeglGtkView *self, GeglNode *node);
743 GeglNode *gegl_gtk_view_get_node(GeglGtkView *self);
744 diff --git a/gegl-gtk/gegl-gtk.h b/gegl-gtk/gegl-gtk.h
745 index 49d5b6b..b18d387 100644
746 --- a/gegl-gtk/gegl-gtk.h
747 +++ b/gegl-gtk/gegl-gtk.h
749 * For building GEGL-GTK, please refer to the README file included
750 * in the source code tarball.
752 - * GEGL-GTK supports both GTK+ 2 and 3, and
753 - * can be used directly as a C library, or in languages
754 - * with bindings provided by GObject Introspection.
755 + * GEGL-GTK supports both GTK+ 2 and 3. It can be used directly as a C library,
756 + * or in languages with bindings provided by GObject Introspection.
758 - * For usage examples, see http://git.gnome.org/browse/gegl-gtk/tree/examples
759 + * GEGL-GTK is licensed under the GNU LGPL v3+, and maintained by Jon Nordby
761 + * Homepage: <ulink url="http://www.gegl.org/gegl-gtk">http://www.gegl.org/gegl-gtk</ulink>
763 + * Code: <ulink url="http://git.gnome.org/browse/gegl-gtk/">http://git.gnome.org/browse/gegl-gtk/</ulink>
765 + * Bugtracker: <ulink url="http://bugs.gnome.org">http://bugs.gnome.org</ulink>, product GEGL, component gegl-gtk
767 + * Mailinglist: <ulink url="http://mail.gnome.org/mailman/listinfo/gegl-developer-list">gegl-developer@lists.gnome.org</ulink>
769 + * For usage examples, see <ulink url="http://git.gnome.org/browse/gegl-gtk/tree/examples">http://git.gnome.org/browse/gegl-gtk/tree/examples</ulink>
771 * GEGL-GTK provides one class: #GeglGtkView
773 diff --git a/gegl-gtk/gegl-gtk2-0.1.deps b/gegl-gtk/gegl-gtk2-0.1.deps
774 index d6fc3e2..f2ff21a 100644
775 --- a/gegl-gtk/gegl-gtk2-0.1.deps
776 +++ b/gegl-gtk/gegl-gtk2-0.1.deps
783 diff --git a/gegl-gtk/gegl-gtk2.pc.in b/gegl-gtk/gegl-gtk2.pc.in
785 index 0000000..80e288c
787 +++ b/gegl-gtk/gegl-gtk2.pc.in
790 +exec_prefix=@exec_prefix@
792 +includedir=@includedir@
795 +Description: GTK+ UI convenience library for GEGL
796 +Version: @GEGL_GTK_REAL_VERSION@
797 +Requires: gtk+-2.0 gegl-0.2 babl
798 +Libs: -L${libdir} -l@PACKAGE_NAME@2-@GEGL_GTK_API_VERSION@
799 +Cflags: -I${includedir}/@PACKAGE_NAME@2-@GEGL_GTK_API_VERSION@
800 diff --git a/gegl-gtk/gegl-gtk3-0.1.deps b/gegl-gtk/gegl-gtk3-0.1.deps
801 index 486d1eb..81b00cf 100644
802 --- a/gegl-gtk/gegl-gtk3-0.1.deps
803 +++ b/gegl-gtk/gegl-gtk3-0.1.deps
810 diff --git a/gegl-gtk/gegl-gtk3.pc.in b/gegl-gtk/gegl-gtk3.pc.in
812 index 0000000..d077ee1
814 +++ b/gegl-gtk/gegl-gtk3.pc.in
817 +exec_prefix=@exec_prefix@
819 +includedir=@includedir@
822 +Description: GTK+ UI convenience library for GEGL
823 +Version: @GEGL_GTK_REAL_VERSION@
824 +Requires: gtk+-3.0 gegl-0.2 babl
825 +Libs: -L${libdir} -l@PACKAGE_NAME@3-@GEGL_GTK_API_VERSION@
826 +Cflags: -I${includedir}/@PACKAGE_NAME@3-@GEGL_GTK_API_VERSION@
827 diff --git a/gegl-gtk/internal/view-helper.c b/gegl-gtk/internal/view-helper.c
828 index 71587cb..e6637c2 100644
829 --- a/gegl-gtk/internal/view-helper.c
830 +++ b/gegl-gtk/internal/view-helper.c
831 @@ -34,8 +34,14 @@ enum {
833 static guint view_helper_signals[N_SIGNALS] = { 0 };
837 finalize(GObject *gobject);
839 +trigger_processing(ViewHelper *self, GeglRectangle roi);
841 +trigger_redraw(ViewHelper *self, GeglRectangle *redraw_rect);
845 view_helper_class_init(ViewHelperClass *klass)
846 @@ -68,7 +74,6 @@ view_helper_class_init(ViewHelperClass *klass)
848 view_helper_init(ViewHelper *self)
850 - GeglRectangle invalid_rect = {0, 0, -1, -1};
851 GdkRectangle invalid_gdkrect = {0, 0, -1, -1};
854 @@ -76,9 +81,12 @@ view_helper_init(ViewHelper *self)
857 self->autoscale_policy = GEGL_GTK_VIEW_AUTOSCALE_CONTENT;
858 + self->block = FALSE;
860 self->monitor_id = 0;
861 - self->processor = NULL;
862 + self->processor = NULL;
863 + self->processing_queue = g_queue_new();
864 + self->currently_processed_rect = NULL;
866 self->widget_allocation = invalid_gdkrect;
868 @@ -98,6 +106,12 @@ finalize(GObject *gobject)
871 g_object_unref(self->processor);
873 + g_queue_free_full(self->processing_queue, g_free);
875 + if (self->currently_processed_rect) {
876 + g_free(self->currently_processed_rect);
880 /* Transform a rectangle from model to view coordinates. */
881 @@ -106,8 +120,8 @@ model_rect_to_view_rect(ViewHelper *self, GeglRectangle *rect)
885 - temp.x = self->scale * (rect->x) - rect->x;
886 - temp.y = self->scale * (rect->y) - rect->y;
887 + temp.x = self->scale * (rect->x) - self->x;
888 + temp.y = self->scale * (rect->y) - self->y;
889 temp.width = ceil(self->scale * rect->width);
890 temp.height = ceil(self->scale * rect->height);
892 @@ -148,21 +162,45 @@ invalidated_event(GeglNode *node,
896 - view_helper_repaint(self);
897 + trigger_processing(self, *rect);
901 task_monitor(ViewHelper *self)
903 - if (self->processor == NULL)
904 + if (!self->processor || !self->node) {
908 + // PERFORMANCE: combine all the rects added to the queue during a single
909 + // iteration of the main loop somehow
911 + if (!self->currently_processed_rect) {
913 + if (g_queue_is_empty(self->processing_queue)) {
914 + // Unregister worker
915 + self->monitor_id = 0;
919 + // Fetch next rect to process
920 + self->currently_processed_rect = (GeglRectangle *)g_queue_pop_tail(self->processing_queue);
921 + g_assert(self->currently_processed_rect);
922 + gegl_processor_set_rectangle(self->processor, self->currently_processed_rect);
926 - if (gegl_processor_work(self->processor, NULL))
928 + gboolean processing_done = !gegl_processor_work(self->processor, NULL);
930 - self->monitor_id = 0;
931 + if (processing_done) {
932 + // Go to next region
933 + if (self->currently_processed_rect) {
934 + g_free(self->currently_processed_rect);
936 + self->currently_processed_rect = NULL;
944 @@ -182,8 +220,7 @@ computed_event(GeglNode *node,
945 GeglRectangle redraw_rect = *rect;
946 model_rect_to_view_rect(self, &redraw_rect);
948 - g_signal_emit(self, view_helper_signals[SIGNAL_REDRAW_NEEDED],
949 - 0, &redraw_rect, NULL);
950 + trigger_redraw(self, &redraw_rect);
954 @@ -240,18 +277,23 @@ view_helper_set_allocation(ViewHelper *self, GdkRectangle *allocation)
956 /* Trigger processing of the GeglNode */
958 -view_helper_repaint(ViewHelper *self)
959 +trigger_processing(ViewHelper *self, GeglRectangle roi)
962 + //GeglRectangle roi;
964 + // PERFORMANCE: determine the area that the view widget is interested in,
965 + // and calculate the intersection with the invalidated rect
966 + // and only pass this value as the ROI
967 + // Would then also have to follow changes in view transformation
972 - roi.x = self->x / self->scale;
973 - roi.y = self->y / self->scale;
974 +// roi.x = self->x / self->scale;
975 +// roi.y = self->y / self->scale;
977 - roi.width = ceil(self->widget_allocation.width / self->scale + 1);
978 - roi.height = ceil(self->widget_allocation.height / self->scale + 1);
979 +// roi.width = ceil(self->widget_allocation.width / self->scale + 1);
980 +// roi.height = ceil(self->widget_allocation.height / self->scale + 1);
982 if (self->monitor_id == 0) {
983 self->monitor_id = g_idle_add_full(G_PRIORITY_LOW,
984 @@ -259,18 +301,25 @@ view_helper_repaint(ViewHelper *self)
988 - if (self->processor)
989 - gegl_processor_set_rectangle(self->processor, &roi);
991 - self->processor = gegl_node_new_processor(self->node, &roi);
992 + // Add the invalidated region to the dirty
993 + GeglRectangle *rect = g_new(GeglRectangle, 1);
996 + rect->width = roi.width;
997 + rect->height = roi.height;
998 + g_queue_push_head(self->processing_queue, rect);
1002 -invalidate(ViewHelper *self)
1003 +trigger_redraw(ViewHelper *self, GeglRectangle *redraw_rect)
1005 - GeglRectangle redraw_rect = {0, 0, -1, -1}; /* Indicates full redraw */
1006 + if (!redraw_rect) {
1007 + GeglRectangle invalid_rect = {0, 0, -1, -1}; /* Indicates full redraw */
1008 + redraw_rect = &invalid_rect;
1011 g_signal_emit(self, view_helper_signals[SIGNAL_REDRAW_NEEDED],
1012 - 0, &redraw_rect, NULL);
1013 + 0, redraw_rect, NULL);
1017 @@ -293,8 +342,14 @@ view_helper_set_node(ViewHelper *self, GeglNode *node)
1018 G_CALLBACK(invalidated_event),
1021 + if (self->processor)
1022 + g_object_unref(self->processor);
1024 + GeglRectangle bbox = gegl_node_get_bounding_box(self->node);
1025 + self->processor = gegl_node_new_processor(self->node, &bbox);
1027 update_autoscale(self);
1029 + trigger_processing(self, bbox);
1033 @@ -314,7 +369,7 @@ view_helper_set_scale(ViewHelper *self, float scale)
1035 self->scale = scale;
1036 update_autoscale(self);
1038 + trigger_redraw(self, NULL);
1042 @@ -331,7 +386,7 @@ view_helper_set_x(ViewHelper *self, float x)
1045 update_autoscale(self);
1047 + trigger_redraw(self, NULL);
1051 @@ -348,7 +403,7 @@ view_helper_set_y(ViewHelper *self, float y)
1054 update_autoscale(self);
1056 + trigger_redraw(self, NULL);
1060 @@ -366,7 +421,7 @@ void view_helper_get_transformation(ViewHelper *self, GeglMatrix3 *matrix)
1061 * GeglMatrix3 changed from float[3][3] to
1062 * struct with a float[3][3] coeff member */
1064 -#if GEGL_MINOR_VERSION == 1 && GEGL_MICRO_VERSION >= 7
1065 +#if GEGL_MINOR_VERSION == 1 && GEGL_MICRO_VERSION >= 7 || GEGL_MINOR_VERSION >= 2
1066 matrix->coeff [0][0] = self->scale; /* xx */
1067 matrix->coeff [0][1] = 0.0; /* xy */
1068 matrix->coeff [0][2] = -self->x; /* x0 */
1069 diff --git a/gegl-gtk/internal/view-helper.h b/gegl-gtk/internal/view-helper.h
1070 index 2c49299..022ac5e 100644
1071 --- a/gegl-gtk/internal/view-helper.h
1072 +++ b/gegl-gtk/internal/view-helper.h
1073 @@ -50,6 +50,9 @@ struct _ViewHelper {
1076 GeglProcessor *processor;
1077 + GQueue *processing_queue; /* Queue of rectangles that needs to be processed */
1078 + GeglRectangle *currently_processed_rect;
1080 GdkRectangle widget_allocation; /* The allocated size of the widget */
1083 @@ -61,8 +64,7 @@ struct _ViewHelperClass {
1084 GType view_helper_get_type(void) G_GNUC_CONST;
1086 ViewHelper *view_helper_new(void);
1087 -void view_helper_node_changed(ViewHelper *self);
1088 -void view_helper_repaint(ViewHelper *self);
1090 void view_helper_draw(ViewHelper *self, cairo_t *cr, GdkRectangle *rect);
1091 void view_helper_set_allocation(ViewHelper *self, GdkRectangle *allocation);
1093 diff --git a/gegl-gtk2-0.1.pc.in b/gegl-gtk2-0.1.pc.in
1094 deleted file mode 100644
1095 index c593480..0000000
1096 --- a/gegl-gtk2-0.1.pc.in
1100 -exec_prefix=@exec_prefix@
1102 -includedir=@includedir@
1105 -Description: GTK+ UI convenience library for GEGL
1106 -Version: @GEGL_GTK_REAL_VERSION@
1107 -Requires: gtk+-2.0 gegl babl
1108 -Libs: -L${libdir} -l@PACKAGE_NAME@2-@GEGL_GTK_API_VERSION@
1109 -Cflags: -I${includedir}/@PACKAGE_NAME@2-@GEGL_GTK_API_VERSION@
1110 diff --git a/gegl-gtk3-0.1.pc.in b/gegl-gtk3-0.1.pc.in
1111 deleted file mode 100644
1112 index 437b00a..0000000
1113 --- a/gegl-gtk3-0.1.pc.in
1117 -exec_prefix=@exec_prefix@
1119 -includedir=@includedir@
1122 -Description: GTK+ UI convenience library for GEGL
1123 -Version: @GEGL_GTK_REAL_VERSION@
1124 -Requires: gtk+-3.0 gegl babl
1125 -Libs: -L${libdir} -l@PACKAGE_NAME@3-@GEGL_GTK_API_VERSION@
1126 -Cflags: -I${includedir}/@PACKAGE_NAME@3-@GEGL_GTK_API_VERSION@
1127 diff --git a/operations/gegl-gtk-display.c b/operations/gegl-gtk-display.c
1128 index 2b8d342..d17576d 100644
1129 --- a/operations/gegl-gtk-display.c
1130 +++ b/operations/gegl-gtk-display.c
1131 @@ -145,13 +145,24 @@ gegl_chant_class_init(GeglChantClass *klass)
1132 G_OBJECT_CLASS(klass)->dispose = dispose;
1135 - operation_class->name = "gegl-gtk2:display";
1136 +#define OPERATION_NAME "gegl-gtk2:display"
1138 - operation_class->name = "gegl-gtk3:display";
1139 +#define OPERATION_NAME "gegl-gtk3:display"
1142 +#if GEGL_MINOR_VERSION >= 2 && GEGL_MICRO_VERSION >= 0
1143 + gegl_operation_class_set_keys (operation_class,
1144 + "name", OPERATION_NAME ,
1145 + "categories", "output",
1146 + "description", _("Displays the input buffer in an GTK window ."),
1148 +#else /* GEGL < 0.2.0 */
1149 + operation_class->name = OPERATION_NAME;
1150 operation_class->categories = "output";
1151 operation_class->description =
1152 _("Displays the input buffer in an GTK window .");
1158 diff --git a/tests/test-view-helper.c b/tests/test-view-helper.c
1159 index addb14c..f23cfa1 100644
1160 --- a/tests/test-view-helper.c
1161 +++ b/tests/test-view-helper.c
1162 @@ -61,11 +61,50 @@ static void
1163 teardown_helper_test(ViewHelperTest *test)
1165 g_object_unref(test->graph);
1166 - gegl_buffer_destroy(test->buffer);
1167 + g_object_unref(test->buffer);
1168 g_object_unref(test->helper);
1173 +computed_event(GeglNode *node,
1174 + GeglRectangle *rect,
1177 + gboolean *got_computed = (gboolean *)data;
1178 + *got_computed = TRUE;
1181 +/* Test that the GeglNode is processed when invalidated. */
1183 +test_processing(void)
1185 + ViewHelperTest test;
1186 + gboolean got_computed_event = FALSE;
1187 + GeglRectangle invalidated_rect = {0, 0, 128, 128};
1189 + setup_helper_test(&test);
1190 + /* Setup will invalidate the node, make sure those events are processed. */
1191 + while (gtk_events_pending()) {
1192 + gtk_main_iteration();
1194 + gegl_node_process(test.out);
1196 + g_signal_connect(test.out, "computed",
1197 + G_CALLBACK(computed_event),
1198 + &got_computed_event);
1200 + gegl_node_invalidated(test.out, &invalidated_rect, FALSE);
1202 + g_timeout_add(300, test_utils_quit_gtk_main, NULL);
1205 + /* FIXME: test that the computed events span the invalidated area */
1206 + g_assert(got_computed_event);
1208 + teardown_helper_test(&test);
1212 gboolean needs_redraw_called;
1213 GeglRectangle *expected_result;
1214 @@ -81,39 +120,37 @@ needs_redraw_event(ViewHelper *helper,
1215 g_assert(test_utils_compare_rect(rect, data->expected_result));
1219 /* Test that the redraw signal is emitted when the GeglNode has been computed.
1221 * NOTE: Does not test that the actual drawing happens, or even
1222 * that queue_redraw is called, as this is hard to observe reliably
1223 * Redraws can be triggered by other things, and the exposed events
1224 - * can be coalesced. */
1225 + * can be coalesced by GTK. */
1227 -test_redraw_on_computed(void)
1228 +test_redraw_on_computed (int x, int y, float scale,
1229 + GeglRectangle *input, GeglRectangle *output)
1231 ViewHelperTest test;
1232 - GeglRectangle computed_rect = {0, 0, 128, 128};
1233 RedrawTestState test_data;
1234 - test_data.needs_redraw_called = FALSE;
1235 - test_data.expected_result = &computed_rect;
1236 + test_data.expected_result = output;
1238 setup_helper_test(&test);
1239 /* Setup will invalidate the node, make sure those events are processed. */
1240 while (gtk_events_pending()) {
1241 gtk_main_iteration();
1243 - gegl_node_process(test.out);
1244 + gegl_node_process (test.out);
1246 - g_assert(IS_VIEW_HELPER(test.helper));
1247 + view_helper_set_x(test.helper, x);
1248 + view_helper_set_y(test.helper, y);
1249 + view_helper_set_scale(test.helper, scale);
1251 - /* TODO: when adding tests for transformed cases,
1252 - * split out a function for testing the redrawn area, given
1253 - * the input area and the transformation (translation, scaling, rotation) */
1254 g_signal_connect(G_OBJECT(test.helper), "redraw-needed",
1255 - G_CALLBACK(needs_redraw_event),
1257 + G_CALLBACK(needs_redraw_event),
1261 - g_signal_emit_by_name(test.out, "computed", &computed_rect, NULL);
1262 + g_signal_emit_by_name(test.out, "computed", input, NULL);
1264 g_timeout_add(300, test_utils_quit_gtk_main, NULL);
1266 @@ -123,17 +160,52 @@ test_redraw_on_computed(void)
1267 teardown_helper_test(&test);
1271 +test_redraw_basic()
1273 + GeglRectangle computed_rect = {0, 0, 128, 128};
1274 + GeglRectangle redraw_rect = {0, 0, 128, 128};
1275 + test_redraw_on_computed (0, 0, 1.0, &computed_rect, &redraw_rect);
1279 +test_redraw_translated()
1281 + GeglRectangle computed_rect = {0, 0, 128, 128};
1282 + GeglRectangle redraw_rect = {-11, -11, 128, 128};
1283 + test_redraw_on_computed (11, 11, 1.0, &computed_rect, &redraw_rect);
1287 +test_redraw_scaled()
1289 + GeglRectangle computed_rect = {0, 0, 128, 128};
1290 + GeglRectangle redraw_rect = {0, 0, 256, 256};
1291 + test_redraw_on_computed (0, 0, 2.0, &computed_rect, &redraw_rect);
1295 +test_redraw_combined()
1297 + GeglRectangle computed_rect = {0, 0, 128, 128};
1298 + GeglRectangle redraw_rect = {10, 10, 256, 256};
1299 + test_redraw_on_computed (-10, -10, 2.0, &computed_rect, &redraw_rect);
1303 main(int argc, char **argv)
1308 - g_thread_init(NULL);
1309 gegl_init(&argc, &argv);
1310 g_test_init(&argc, &argv, NULL);
1312 - g_test_add_func("/widgets/view/helper/redraw-on-computed", test_redraw_on_computed);
1313 + g_test_add_func("/widgets/view/helper/processing", test_processing);
1314 + g_test_add_func("/widgets/view/redraw-basic", test_redraw_basic);
1315 + g_test_add_func("/widgets/view/redraw-scaled", test_redraw_scaled);
1316 + g_test_add_func("/widgets/view/redraw-translated", test_redraw_translated);
1317 + g_test_add_func("/widgets/view/redraw-combined", test_redraw_combined);
1319 retval = g_test_run();
1321 diff --git a/tests/test-view.c b/tests/test-view.c
1322 index 8eee89f..e62a319 100644
1323 --- a/tests/test-view.c
1324 +++ b/tests/test-view.c
1325 @@ -63,7 +63,7 @@ static void
1326 teardown_widget_test(ViewWidgetTest *test)
1328 g_object_unref(test->graph);
1329 - gegl_buffer_destroy(test->buffer);
1330 + g_object_unref(test->buffer);
1331 gtk_widget_destroy(test->window);
1334 @@ -83,53 +83,7 @@ test_sanity(void)
1335 teardown_widget_test(&test);
1340 -computed_event(GeglNode *node,
1341 - GeglRectangle *rect,
1344 - gboolean *got_computed = (gboolean *)data;
1345 - *got_computed = TRUE;
1348 -/* Test that the GeglNode is processed when invalidated. */
1350 -test_processing(void)
1352 - ViewWidgetTest test;
1353 - gboolean got_computed_event = FALSE;
1354 - GeglRectangle invalidated_rect = {0, 0, 128, 128};
1356 - setup_widget_test(&test);
1357 - /* Setup will invalidate the node, make sure those events are processed. */
1358 - while (gtk_events_pending()) {
1359 - gtk_main_iteration();
1361 - gegl_node_process(test.out);
1363 - g_signal_connect(test.out, "computed",
1364 - G_CALLBACK(computed_event),
1365 - &got_computed_event);
1367 - g_signal_emit_by_name(test.out, "invalidated", &invalidated_rect, NULL);
1369 - g_timeout_add(300, test_utils_quit_gtk_main, NULL);
1372 - /* FIXME: test that the computed events span the invalidated area */
1373 - g_assert(got_computed_event);
1375 - teardown_widget_test(&test);
1381 - * - Test redraw with translation
1382 - * - Test redraw with scaling
1383 - * - Test redraw with rotation
1384 - * Benchmarks for cases above
1385 * Actual drawing tests, checking the output of the widget against a
1386 * well known reference. Ideally done with a fake/dummy windowing backend,
1387 * so it can be done quickly, without external influences.
1388 @@ -150,13 +104,11 @@ main(int argc, char **argv)
1392 - g_thread_init(NULL);
1393 gtk_init(&argc, &argv);
1394 gegl_init(&argc, &argv);
1395 g_test_init(&argc, &argv, NULL);
1397 g_test_add_func("/widgets/view/sanity", test_sanity);
1398 - g_test_add_func("/widgets/view/processing", test_processing);
1400 retval = g_test_run();