gegl r2305 - in branches/branch_zhangjb: . bin bindings/pygegl bindings/pygegl/samples bindings/rgegl bindings/rgegl/samples bindings/rgegl/src docs examples gegl gegl/buffer gegl/graph gegl/operation gegl/property-types operations/common operations/external operations/external/v4lutils operations/generated operations/workshop tools



Author: zhangjb
Date: Sat May 17 17:51:59 2008
New Revision: 2305
URL: http://svn.gnome.org/viewvc/gegl?rev=2305&view=rev

Log:
Merged this branch from the trunk 2304

Added:
   branches/branch_zhangjb/examples/
      - copied from r2304, /trunk/examples/
   branches/branch_zhangjb/operations/common/color-temperature.c
      - copied unchanged from r2304, /trunk/operations/common/color-temperature.c
   branches/branch_zhangjb/operations/common/open-buffer.c
      - copied unchanged from r2304, /trunk/operations/common/open-buffer.c
   branches/branch_zhangjb/operations/common/rectangle.c
      - copied unchanged from r2304, /trunk/operations/common/rectangle.c
   branches/branch_zhangjb/operations/common/write-buffer.c
      - copied unchanged from r2304, /trunk/operations/common/write-buffer.c
   branches/branch_zhangjb/operations/external/v4l.c
      - copied unchanged from r2304, /trunk/operations/external/v4l.c
   branches/branch_zhangjb/operations/external/v4lutils/
      - copied from r2304, /trunk/operations/external/v4lutils/
   branches/branch_zhangjb/operations/workshop/stroke.c
      - copied unchanged from r2304, /trunk/operations/workshop/stroke.c
Removed:
   branches/branch_zhangjb/docs/hello-world-video.c
   branches/branch_zhangjb/docs/hello-world.c
Modified:
   branches/branch_zhangjb/AUTHORS
   branches/branch_zhangjb/ChangeLog
   branches/branch_zhangjb/Makefile.am
   branches/branch_zhangjb/NEWS
   branches/branch_zhangjb/bin/gegl-bin-gui-types.h
   branches/branch_zhangjb/bin/gegl-view.c
   branches/branch_zhangjb/bin/gegl-view.h
   branches/branch_zhangjb/bin/gegl.c
   branches/branch_zhangjb/bindings/pygegl/ChangeLog
   branches/branch_zhangjb/bindings/pygegl/samples/render-test.py
   branches/branch_zhangjb/bindings/rgegl/ChangeLog
   branches/branch_zhangjb/bindings/rgegl/samples/render-test.rb
   branches/branch_zhangjb/bindings/rgegl/src/rgegl-node.c
   branches/branch_zhangjb/bindings/rgegl/src/rgegl.h
   branches/branch_zhangjb/configure.ac
   branches/branch_zhangjb/docs/ChangeLog
   branches/branch_zhangjb/docs/Makefile.am
   branches/branch_zhangjb/docs/index-static.txt.in
   branches/branch_zhangjb/gegl/Makefile.am
   branches/branch_zhangjb/gegl/buffer/Makefile.am
   branches/branch_zhangjb/gegl/buffer/gegl-buffer-access.c
   branches/branch_zhangjb/gegl/buffer/gegl-buffer-index.h
   branches/branch_zhangjb/gegl/buffer/gegl-buffer-load.c
   branches/branch_zhangjb/gegl/buffer/gegl-buffer-load.h
   branches/branch_zhangjb/gegl/buffer/gegl-buffer-private.h
   branches/branch_zhangjb/gegl/buffer/gegl-buffer-save.c
   branches/branch_zhangjb/gegl/buffer/gegl-buffer-share.c
   branches/branch_zhangjb/gegl/buffer/gegl-buffer.c
   branches/branch_zhangjb/gegl/buffer/gegl-buffer.h
   branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-file.c
   branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-file.h
   branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-ram.c
   branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-tiledir.c
   branches/branch_zhangjb/gegl/buffer/gegl-tile-backend.c
   branches/branch_zhangjb/gegl/buffer/gegl-tile-backend.h
   branches/branch_zhangjb/gegl/buffer/gegl-tile-handler-cache.c
   branches/branch_zhangjb/gegl/buffer/gegl-tile-handler-log.c
   branches/branch_zhangjb/gegl/buffer/gegl-tile-handler-zoom.c
   branches/branch_zhangjb/gegl/buffer/gegl-tile-source.h
   branches/branch_zhangjb/gegl/buffer/gegl-tile-storage.c
   branches/branch_zhangjb/gegl/buffer/gegl-tile.c
   branches/branch_zhangjb/gegl/buffer/gegl-tile.h
   branches/branch_zhangjb/gegl/gegl-chant.h
   branches/branch_zhangjb/gegl/gegl-config.c
   branches/branch_zhangjb/gegl/gegl-config.h
   branches/branch_zhangjb/gegl/gegl-init.c
   branches/branch_zhangjb/gegl/gegl.h.in
   branches/branch_zhangjb/gegl/graph/gegl-node-context.c
   branches/branch_zhangjb/gegl/graph/gegl-node.c
   branches/branch_zhangjb/gegl/graph/gegl-node.h
   branches/branch_zhangjb/gegl/operation/gegl-operation-area-filter.h
   branches/branch_zhangjb/gegl/operation/gegl-operation-filter.h
   branches/branch_zhangjb/gegl/operation/gegl-operation-point-filter.c
   branches/branch_zhangjb/gegl/operation/gegl-operation-processors.c
   branches/branch_zhangjb/gegl/operation/gegl-operation-sink.h
   branches/branch_zhangjb/gegl/operation/gegl-operation-source.h
   branches/branch_zhangjb/gegl/operation/gegl-operation.c
   branches/branch_zhangjb/gegl/operation/gegl-operation.h
   branches/branch_zhangjb/gegl/property-types/Makefile.am
   branches/branch_zhangjb/gegl/property-types/gegl-color.c
   branches/branch_zhangjb/gegl/property-types/gegl-color.h
   branches/branch_zhangjb/gegl/property-types/gegl-vector.c
   branches/branch_zhangjb/gegl/property-types/gegl-vector.h
   branches/branch_zhangjb/operations/common/brightness-contrast.c
   branches/branch_zhangjb/operations/common/invert.c
   branches/branch_zhangjb/operations/common/whitebalance.c
   branches/branch_zhangjb/operations/external/Makefile.am
   branches/branch_zhangjb/operations/generated/other-blend.rb
   branches/branch_zhangjb/operations/generated/svg-12-porter-duff.rb
   branches/branch_zhangjb/tools/create-reference.rb

Modified: branches/branch_zhangjb/AUTHORS
==============================================================================
--- branches/branch_zhangjb/AUTHORS	(original)
+++ branches/branch_zhangjb/AUTHORS	Sat May 17 17:51:59 2008
@@ -6,7 +6,7 @@
 Richard Kralovic, Kevin Cozens, Victor Bogado, Martin Nordholts, Geert
 Jordaens, Michael Schumacher, John Marshall, Ãtienne Bersac, Mark Probst, HÃkon
 Hitland, Tor Lillqvist, Hans Breuer, Deji Akingunola and Bradley Broom,
-Hans Petter Jansson.
+Hans Petter Jansson, Jan Heller.
 
 Documentation:
 ^^^^^^^^^^^^^^

Modified: branches/branch_zhangjb/Makefile.am
==============================================================================
--- branches/branch_zhangjb/Makefile.am	(original)
+++ branches/branch_zhangjb/Makefile.am	Sat May 17 17:51:59 2008
@@ -1,11 +1,17 @@
 AUTOMAKE_OPTIONS = dist-bzip2
 
-SUBDIRS= gegl operations bin tools tests/frequency
+SUBDIRS=\
+	gegl \
+	operations \
+	bin \
+	tools \
+	tests/frequency \
+	examples
+
 if ENABLE_DOCS
 SUBDIRS+= docs
 endif
 
-
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = gegl.pc
 
@@ -34,4 +40,4 @@
 dist-hook: dist-check-w3m
 
 website: all
-	$(MAKE) -C docs website
+	$(MAKE) -C docs website
\ No newline at end of file

Modified: branches/branch_zhangjb/NEWS
==============================================================================
--- branches/branch_zhangjb/NEWS	(original)
+++ branches/branch_zhangjb/NEWS	Sat May 17 17:51:59 2008
@@ -7,15 +7,27 @@
 
 Changes in GEGL 0.0.17
 ââââââââââââââââââââââ
- â Performance of GeglBuffer improved.
- â Handle optimized versions of innerloops for operations.
-   â SSE detection and optimization for some point ops.
+ â Configuration both from commandline arguments and at runtime.
+ â GeglBuffer
+   â Transparently sharable across processes.
+   â Fileformat compatible with swap format.
+   â Tunable cache size.
+ â Operations
+   â Handle variant implementations of GeglOperations.
+   â Optimized variants of some point and compositing operations reimplemented
+     using a new data type /g4float/ that allows writing cpu agnostic vectorized
+     code for GCC.
+   â New operations: write-buffer, v4l, color-temperature.
+
+Contributions from:
+  Ãyvind KolÃs, Kevin Cozens, Sven Neumann, Manish Singh, Martin Nordholts,
+  Ãtienne Bersac, Hans Petter Jansson, Jan Heller.
 
 Changes in GEGL 0.0.16
 ââââââââââââââââââââââ
  â Install headers for development of external operation plug-ins.
  â Added rowstride argument to gegl_buffer_set ()
- â Made it possible for sink operations to do cunkwise processing
+ â Made it possible for sink operations to do chunkwise processing
    through GeglProcessor.
    when processed using a GeglProcessor.
  â constification of GeglRectangles and babl formats.

Modified: branches/branch_zhangjb/bin/gegl-bin-gui-types.h
==============================================================================
--- branches/branch_zhangjb/bin/gegl-bin-gui-types.h	(original)
+++ branches/branch_zhangjb/bin/gegl-bin-gui-types.h	Sat May 17 17:51:59 2008
@@ -25,7 +25,6 @@
 typedef struct _Editor          Editor;
 typedef struct _GeglNodeEditor  GeglNodeEditor;
 typedef struct _GeglStore       GeglStore;
-typedef struct _GeglView        GeglView;
 
 
 #endif /* GEGL_EDITOR_TYPES_H */

Modified: branches/branch_zhangjb/bin/gegl-view.c
==============================================================================
--- branches/branch_zhangjb/bin/gegl-view.c	(original)
+++ branches/branch_zhangjb/bin/gegl-view.c	Sat May 17 17:51:59 2008
@@ -23,14 +23,8 @@
 #include <glib-object.h>
 #include <gtk/gtk.h>
 
-#include "gegl-bin-gui-types.h"
-
 #include "gegl.h"
-
 #include "gegl-view.h"
-#include "gegl-tree-editor.h"
-#include "editor.h"
-
 
 enum
 {
@@ -48,13 +42,13 @@
   gint           x;
   gint           y;
   gdouble        scale;
-  gint           screen_x;  /* coordinates of drag start */
+  gint           screen_x;    /* coordinates of drag start */
   gint           screen_y;
 
-  gint           orig_x;    /* coordinates of drag start */
+  gint           orig_x;      /* coordinates of drag start */
   gint           orig_y;
 
-  gint           start_buf_x;    /* coordinates of drag start */
+  gint           start_buf_x; /* coordinates of drag start */
   gint           start_buf_y;
 
   gint           prev_x;
@@ -317,7 +311,9 @@
         g_free (name);
         g_free (operation);
 #endif
+#if 0
         tree_editor_set_active (editor.tree_editor, detected);
+#endif
       }
   }
 

Modified: branches/branch_zhangjb/bin/gegl-view.h
==============================================================================
--- branches/branch_zhangjb/bin/gegl-view.h	(original)
+++ branches/branch_zhangjb/bin/gegl-view.h	Sat May 17 17:51:59 2008
@@ -28,6 +28,7 @@
 #define GEGL_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  GEGL_TYPE_VIEW))
 #define GEGL_VIEW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  GEGL_TYPE_VIEW, GeglViewClass))
 
+typedef struct _GeglView        GeglView;
 typedef struct _GeglViewClass   GeglViewClass;
 
 struct _GeglView

Modified: branches/branch_zhangjb/bin/gegl.c
==============================================================================
--- branches/branch_zhangjb/bin/gegl.c	(original)
+++ branches/branch_zhangjb/bin/gegl.c	Sat May 17 17:51:59 2008
@@ -100,9 +100,10 @@
         }
       else
         {
+          gchar real_path[PATH_MAX];
           gchar *temp1 = g_strdup (o->file);
           gchar *temp2 = g_path_get_dirname (temp1);
-          path_root = g_strdup (realpath (temp2, NULL));
+          path_root = g_strdup (realpath (temp2, real_path));
           g_free (temp1);
           g_free (temp2);
         }

Modified: branches/branch_zhangjb/bindings/pygegl/samples/render-test.py
==============================================================================
--- branches/branch_zhangjb/bindings/pygegl/samples/render-test.py	(original)
+++ branches/branch_zhangjb/bindings/pygegl/samples/render-test.py	Sat May 17 17:51:59 2008
@@ -13,7 +13,7 @@
 height = 40
 
 gegl    = Gegl.Node()
-fractal = gegl.new_child("FractalExplorer",
+fractal = gegl.new_child("fractal-explorer",
                          width=width,
                          height=height,
                          ncolors=3)
@@ -22,9 +22,8 @@
                          string="GEGL\n\n term",
                          size=height/4)
 over    = gegl.new_child("over")
-display = gegl.new_child("display")
 
-fractal >> contrast >> over >> display
+fractal >> contrast >> over
 text >> over["aux"]
 
 buffer = over.render((0,0,width,height), "Y u8")

Modified: branches/branch_zhangjb/bindings/rgegl/samples/render-test.rb
==============================================================================
--- branches/branch_zhangjb/bindings/rgegl/samples/render-test.rb	(original)
+++ branches/branch_zhangjb/bindings/rgegl/samples/render-test.rb	Sat May 17 17:51:59 2008
@@ -11,13 +11,12 @@
 height=40
 
 gegl    = Gegl::Node.new
-fractal = gegl.new_child :FractalExplorer,:width=>width,:height=>height, :ncolors=>3
+fractal = gegl.new_child :fractal_explorer, :width=>width, :height=>height, :ncolors=>3
 contrast= gegl.new_child :threshold, :value=>0.5
 text    = gegl.new_child :text, :string=>'GEGL\n\n term', :size=>height/4
 over    = gegl.new_child :over
-display = gegl.new_child :display
 
-fractal >> contrast >> over >> display
+fractal >> contrast >> over
 text >> over[:aux]
 
 x=0

Modified: branches/branch_zhangjb/bindings/rgegl/src/rgegl-node.c
==============================================================================
--- branches/branch_zhangjb/bindings/rgegl/src/rgegl-node.c	(original)
+++ branches/branch_zhangjb/bindings/rgegl/src/rgegl-node.c	Sat May 17 17:51:59 2008
@@ -357,6 +357,7 @@
     return CSTR2RVAL (xml);
 }
 
+#if 0
 gpointer gegl_node_get_cache (GeglNode *node);
 void gegl_buffer_save (gpointer buffer,
        const gchar *path,
@@ -364,13 +365,14 @@
 void gegl_buffer_load (gpointer buffer,
        const gchar *path);
 
+
 static VALUE
 cnode_save_cache (self,
                   path)
   VALUE self, path;
 {
-    gpointer cache = gegl_node_get_cache (_SELF (self));
-    gegl_buffer_save (cache, RVAL2CSTR(path), NULL);
+    /*gpointer cache = gegl_node_get_cache (_SELF (self));
+    gegl_buffer_save (cache, RVAL2CSTR(path), NULL);*/
     return Qnil;
 }
 
@@ -379,11 +381,12 @@
                   path)
   VALUE self, path;
 {
-    gpointer cache = gegl_node_get_cache (_SELF (self));
-    gegl_buffer_load (cache, RVAL2CSTR(path));
+    /*gpointer cache = gegl_node_get_cache (_SELF (self));
+    gegl_buffer_load (cache, RVAL2CSTR(path));*/
     /* FIXME: fix what is legal data for cache (or do it in load?)*/
     return Qnil;
 }
+#endif
 
 gchar *gegl_to_dot (GeglNode *self);
 
@@ -483,8 +486,8 @@
     rb_define_method(geglGeglNode, "set_property", cnode_set_property, 2);
     rb_define_method(geglGeglNode, "processor", cnode_new_processor, 1);
     rb_define_method(geglGeglNode, "xml", cnode_to_xml, 1);
-    rb_define_method(geglGeglNode, "save_cache", cnode_save_cache, 1);
-    rb_define_method(geglGeglNode, "load_cache", cnode_load_cache, 1);
+/*    rb_define_method(geglGeglNode, "save_cache", cnode_save_cache, 1);
+    rb_define_method(geglGeglNode, "load_cache", cnode_load_cache, 1);*/
 
     rb_define_module_function (mGegl, "init", c_gegl_init, 0);
     rb_define_module_function (mGegl, "exit", c_gegl_exit, 0);

Modified: branches/branch_zhangjb/bindings/rgegl/src/rgegl.h
==============================================================================
--- branches/branch_zhangjb/bindings/rgegl/src/rgegl.h	(original)
+++ branches/branch_zhangjb/bindings/rgegl/src/rgegl.h	Sat May 17 17:51:59 2008
@@ -24,7 +24,7 @@
 #include <gegl.h>
 #include "rbgtk.h"
 #include "rbgobject.h"
-#include "rbgeglversion.h"
+/*#include "rbgeglversion.h"*/
 
 extern void Init_gegl(void);
 extern void Init_gegl_buffer(VALUE);

Modified: branches/branch_zhangjb/configure.ac
==============================================================================
--- branches/branch_zhangjb/configure.ac	(original)
+++ branches/branch_zhangjb/configure.ac	Sat May 17 17:51:59 2008
@@ -845,6 +845,7 @@
 docs/index-static.txt
 docs/gallery/Makefile
 docs/gallery/data/Makefile
+examples/Makefile
 gegl.pc
 gegl-uninstalled.pc
 ])

Modified: branches/branch_zhangjb/docs/Makefile.am
==============================================================================
--- branches/branch_zhangjb/docs/Makefile.am	(original)
+++ branches/branch_zhangjb/docs/Makefile.am	Sat May 17 17:51:59 2008
@@ -34,8 +34,6 @@
 	gegl.css  		\
 	gegl.devhelp		\
 	devhelp.css		\
-	hello-world.c		\
-	hello-world-video.c	\
 	index-static.txt.in	\
 	$(HTML_FILES)
 
@@ -80,9 +78,9 @@
 	  $(top_srcdir)/gegl/operation/gegl-operation.h\
 	  $(top_srcdir)/tools/create-reference.rb
 if HAVE_RUBY
-	$(top_srcdir)/tools/create-reference.rb \
-	    $(top_srcdir)/gegl/gegl.h\
-	    $(top_srcdir)/gegl/buffer/gegl-buffer.h\
+	$(top_srcdir)/tools/create-reference.rb 	\
+	    $(top_srcdir)/gegl/gegl.h			\
+	    $(top_srcdir)/gegl/buffer/gegl-buffer.h	\
 	    $(top_srcdir)/gegl/operation/gegl-operation.h $@
 endif
 
@@ -90,9 +88,9 @@
 	$(top_srcdir)/AUTHORS		\
 	gegl.css			\
 	$(top_srcdir)/NEWS		\
+	$(top_srcdir)/examples/hello-world.c \
 	$(top_builddir)/bin/gegl	\
-	Makefile.am			\
-	$(srcdir)/hello-world.c
+	Makefile.am
 if HAVE_ASCIIDOC
 	@echo "HTML: $@"
 	cp $< $@ 
@@ -112,8 +110,8 @@
 	$(INSTALL) -d $(help_dir)
 if HAVE_ENSCRIPT
 	$(INSTALL) $(srcdir)/brightness-contrast.c.html \
-	    $(srcdir)/gegl.h.html \
-	    $(srcdir)/gegl-operation.h.html \
+	    $(srcdir)/gegl.h.html 			\
+	    $(srcdir)/gegl-operation.h.html 		\
 	    $(srcdir)/gegl-plugin.h.html $(help_dir)
 endif
 if HAVE_RUBY
@@ -132,13 +130,6 @@
 endif
 	rm -f $(help_dir)/gegl.devhelp $(help_dir)/gegl.css
 
-hello-world: hello-world.c
-	$(CC) $< -o $@ `pkg-config --cflags --libs gegl`
-
-hello-world-video: hello-world-video.c
-	$(CC) $< -o $@ `pkg-config --cflags --libs gegl`
-
-
 # require asciidoc when making dist
 #
 dist-check-asciidoc:

Modified: branches/branch_zhangjb/docs/index-static.txt.in
==============================================================================
--- branches/branch_zhangjb/docs/index-static.txt.in	(original)
+++ branches/branch_zhangjb/docs/index-static.txt.in	Sat May 17 17:51:59 2008
@@ -196,7 +196,7 @@
 fractal
 
 ---------------------------
-sys::[cat hello-world.c]
+sys::[cat ../examples/hello-world.c]
 ---------------------------
 
  $ gcc hello-world.c `pkg-config --libs --cflags gegl` -o hello-world
@@ -386,6 +386,9 @@
 GEGL dirs
 ^^^^^^^^^
 
+Directories marked with â use GNU make extensions to include any .c file
+dropped into the directory in the build.
+
  gegl-dist-root
   â
   â
@@ -409,23 +412,32 @@
   â   âââproperty-types specialized classes/paramspecs for GeglOperation
   â                     properties.
   â
+  âââexamples â        hello-world and other example uses of the GEGL API.
+  â
+  âââtests             various tests used to maintain stability when developing
+  â                    GEGL.
+  â
   âââoperations        Runtime loaded plug-ins for image processing operations.
   â   â
-  â   âââcore          Basic operations tightly coupled with GEGL.
+  â   âââcore â        Basic operations tightly coupled with GEGL.
   â   âââaffine        Transforming operations (rotate/scale/translate)
-  â   âââgenerated     Operations generated from scripts (currently
+  â   âââgenerated â   Operations generated from scripts (currently
   â   âââexternal      Operations with external dependencies.
-  â   âââcommon        Other operations (drop .c files in here and they are built.)
-  â   âââworkshop      Works in progress, (you must pass --enable-workshop to configure
-  â       â            for the ops in here to be built.
+  â   âââcommon â      Other operations. 
+  â   âââworkshop â    Works in progress, (you must pass --enable-workshop 
+  â       â            when configurig to build these by default, you can enter
+  â       â            the directory manually and type make && sudo make install
+  â       â            as well.
   â       â
   â       âââexternal  operations in the workshop with external dependencies.
   â       âââgenerated generated operations that are in the workshop.
   â
   â
-  âââdocs              A website for GEGL
+  âââdocs              The GEGL website (this documentation), built for your
+  â   â                the corresponding sourcetree with correct documentation
+  â   â                etc.
   â   â
-  â   âââgallery       A gallery of sample GEGL compositions, using the
+  â   âââgallery â     A gallery of sample GEGL compositions, using the
   â       â            (not yet stabilized) XML format.
   â       â
   â       âââdata      Image data used by the sample compositions.

Modified: branches/branch_zhangjb/gegl/Makefile.am
==============================================================================
--- branches/branch_zhangjb/gegl/Makefile.am	(original)
+++ branches/branch_zhangjb/gegl/Makefile.am	Sat May 17 17:51:59 2008
@@ -25,6 +25,7 @@
 	gegl-chant.h			\
 	gegl-config.h			\
 	gegl-cpuaccel.h			\
+	gegl-debug.h			\
 	gegl-dot.h			\
 	gegl-init.h			\
 	gegl-instrument.h		\

Modified: branches/branch_zhangjb/gegl/buffer/Makefile.am
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/Makefile.am	(original)
+++ branches/branch_zhangjb/gegl/buffer/Makefile.am	Sat May 17 17:51:59 2008
@@ -32,6 +32,7 @@
 BUFFER_headers = \
     gegl-buffer.h		\
     gegl-buffer-private.h	\
+    gegl-buffer-load.h		\
     gegl-buffer-save.h		\
     gegl-buffer-types.h		\
     gegl-cache.h		\
@@ -62,5 +63,6 @@
 INCLUDES = \
 	   -I$(top_srcdir)	\
 	   -I$(top_srcdir)/gegl	\
+	   -I$(top_srcdir)/gegl/buffer	\
 	   @DEP_CFLAGS@ @BABL_CFLAGS@
 

Modified: branches/branch_zhangjb/gegl/buffer/gegl-buffer-access.c
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-buffer-access.c	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-buffer-access.c	Sat May 17 17:51:59 2008
@@ -41,6 +41,226 @@
 #endif
 
 
+
+void gegl_buffer_tile_iterator_init (GeglBufferTileIterator *i,
+                                            GeglBuffer             *buffer,
+                                            GeglRectangle           roi,
+                                            gboolean                write)
+{
+  g_assert (i);
+  memset (i, 0, sizeof (GeglBufferTileIterator));
+  i->buffer = buffer;
+  i->roi = roi;
+  i->row    = 0;
+  i->col = 0;
+  i->tile = NULL;
+  i->write = write;
+}
+
+
+GeglBufferTileIterator *
+gegl_buffer_tile_iterator_new (GeglBuffer    *buffer,
+                               GeglRectangle  roi,
+                               gboolean       write)
+{
+  GeglBufferTileIterator *i = g_malloc (sizeof (GeglBufferTileIterator));
+  gegl_buffer_tile_iterator_init (i, buffer, roi, write);
+  return i; 
+}
+
+void gegl_buffer_scan_iterator_init (GeglBufferScanIterator *i,
+                                     GeglBuffer             *buffer,
+                                     GeglRectangle           roi,
+                                     gboolean                write)
+{
+  GeglBufferTileIterator *tile_i = (GeglBufferTileIterator*)i;
+  g_assert (i);
+  memset (i, 0, sizeof (GeglBufferScanIterator));
+  gegl_buffer_tile_iterator_init (tile_i, buffer, roi, write);
+  i->max_size = tile_i->buffer->tile_storage->tile_width *
+                tile_i->buffer->tile_storage->tile_height *
+                tile_i->buffer->format->format.bytes_per_pixel;
+}
+
+GeglBufferScanIterator *gegl_buffer_scan_iterator_new (GeglBuffer             *buffer,
+                                                       GeglRectangle           roi,
+                                                       gboolean                write)
+{
+  GeglBufferScanIterator *i = g_malloc (sizeof (GeglBufferScanIterator));
+  gegl_buffer_scan_iterator_init (i, buffer, roi, write);
+  return i;
+}
+
+gboolean
+gegl_buffer_scan_iterator_next (GeglBufferScanIterator *i)
+{
+  GeglBufferTileIterator *tile_i = (GeglBufferTileIterator*)i;
+
+  if (tile_i->tile==NULL)
+    {
+      gulp:
+      if (!gegl_buffer_tile_iterator_next (tile_i))
+        return FALSE;
+      i->width = tile_i->subrect.width;
+      i->row = 0;
+    }
+  /* we should now have a valid tile */
+
+  if (tile_i->subrect.width == tile_i->buffer->tile_storage->tile_width &&
+      i->row < tile_i->subrect.height)
+    /* the entire contents of the tile can be expressed as one long scan */
+    {
+      gint  px_size = tile_i->buffer->format->format.bytes_per_pixel;
+      guchar *data = tile_i->data;
+      i->width = tile_i->subrect.width * tile_i->subrect.height;
+      i->data = data + px_size * (tile_i->subrect.width * tile_i->subrect.y);
+      i->row = tile_i->subrect.height;
+      return TRUE;
+    }
+  else if (i->row < tile_i->subrect.height)
+    /* iterate thorugh the scanlines in the subrect */
+    {
+      guchar *data = tile_i->sub_data;
+      i->data = data + i->row * tile_i->rowstride;
+      i->row ++;
+      return TRUE;
+    }
+  else
+    { /* we're done with that tile go get another one if possible */
+      goto gulp;
+    }
+
+  return FALSE;
+}
+
+
+gboolean gegl_buffer_scan_compatible (GeglBuffer *input,
+                                      GeglBuffer *output)
+{
+  if (input->tile_storage->tile_width !=
+      output->tile_storage->tile_width)
+    return FALSE;
+  if (input->tile_storage->tile_height !=
+      output->tile_storage->tile_height)
+    return FALSE;
+  if (input->shift_x !=
+      output->shift_x)
+    return FALSE;
+  if (input->shift_y !=
+      output->shift_y)
+    return FALSE;
+  return TRUE;
+}
+
+gboolean
+gegl_buffer_tile_iterator_next (GeglBufferTileIterator *i)
+{
+  GeglBuffer *buffer = i->buffer;
+  gint  tile_width   = buffer->tile_storage->tile_width;
+  gint  tile_height  = buffer->tile_storage->tile_height;
+  gint  buffer_shift_x = buffer->shift_x;
+  gint  buffer_shift_y = buffer->shift_y;
+  gint  buffer_x       = buffer->extent.x + buffer_shift_x;
+  gint  buffer_y       = buffer->extent.y + buffer_shift_y;
+  gint  buffer_abyss_x = buffer->abyss.x + buffer_shift_x;
+  gint  abyss_x_total  = buffer_abyss_x + buffer->abyss.width;
+
+  if (i->roi.width == 0 || i->roi.height == 0)
+    return FALSE;
+
+gulp:
+
+  /* unref previous held tile */
+  if (i->tile)
+    {
+      if (i->write)
+        {
+          gegl_tile_unlock (i->tile);
+        }
+      g_object_unref (i->tile);
+      i->tile = NULL;
+    }
+
+  if (i->col < i->roi.width)
+    { /* return tile on this row */
+      gint tiledx = buffer_x + i->col;
+      gint tiledy = buffer_y + i->row;
+      gint offsetx = gegl_tile_offset (tiledx, tile_width);
+      gint offsety = gegl_tile_offset (tiledy, tile_height);
+      gint pixels; 
+
+      if (i->roi.width + offsetx - i->col < tile_width)
+        pixels = (i->roi.width + offsetx - i->col) - offsetx;
+      else
+        pixels = tile_width - offsetx;
+
+     if (!(buffer_x + i->col + tile_width >= buffer_abyss_x &&
+                      buffer_x + i->col < abyss_x_total))
+       { 
+          g_warning ("entire tile in abyss?");
+
+          i->col += tile_width - offsetx;
+       }
+     else
+       {
+         /* gap between left side of tile, and abyss */
+         i->subrect.x = offsetx;
+         i->subrect.y = offsety;
+         /* gap between right side of tile, and abyss */
+
+
+         i->subrect.width = (i->roi.width - i->col < tile_width) ?
+                             (i->roi.width - i->col) - i->subrect.x:
+                             tile_width - i->subrect.x;
+
+         i->subrect.height = (i->roi.height - i->row < tile_height) ?
+                             (i->roi.height - i->row) - i->subrect.y:
+                             tile_height - i->subrect.y;
+
+         i->tile = gegl_tile_source_get_tile ((GeglTileSource *) (buffer),
+                                               gegl_tile_indice (tiledx, tile_width),
+                                               gegl_tile_indice (tiledy, tile_height),
+                                               0);
+         if (i->write)
+           {
+             gegl_tile_lock (i->tile);
+           }
+         i->data = gegl_tile_get_data (i->tile);
+
+         {
+         gint bpp = i->buffer->format->format.bytes_per_pixel;
+         i->rowstride = bpp * tile_width;
+         i->sub_data = (guchar*)(i->data) + bpp * (i->subrect.y * tile_width + i->subrect.x);
+         }
+
+         /* update with new future position (note this means that the
+          * coordinates read from the iterator do not make full sense 
+          * */
+         i->col += tile_width - offsetx;
+
+         return TRUE;
+       }
+    }
+  else /* move down to next row */
+    {
+      gint tiledy = buffer_y + i->row;
+      gint offsety = gegl_tile_offset (tiledy, tile_height);
+
+      i->row += tile_height - offsety;
+      i->col=0;
+
+      if (i->row < i->roi.height)
+        {
+          goto gulp; /* return the first tile in the next row */
+        }
+
+      return FALSE;
+    }
+  return FALSE;
+}
+                                    
+
+
 #ifdef BABL
 #undef BABL
 #endif
@@ -164,8 +384,8 @@
         GeglTile *tile     = NULL;
 
         if (buffer->hot_tile &&
-            buffer->hot_tile->storage_x == indice_x &&
-            buffer->hot_tile->storage_y == indice_y)
+            buffer->hot_tile->x == indice_x &&
+            buffer->hot_tile->y == indice_y)
           {
             tile = buffer->hot_tile;
           }
@@ -249,8 +469,8 @@
         GeglTile *tile     = NULL;
 
         if (buffer->hot_tile &&
-            buffer->hot_tile->storage_x == indice_x &&
-            buffer->hot_tile->storage_y == indice_y)
+            buffer->hot_tile->x == indice_x &&
+            buffer->hot_tile->y == indice_y)
           {
             tile = buffer->hot_tile;
           }
@@ -310,6 +530,7 @@
 }
 
 
+
 static void inline
 gegl_buffer_iterate (GeglBuffer *buffer,
                      guchar     *buf,
@@ -579,6 +800,7 @@
 #if ENABLE_MP
   g_static_rec_mutex_lock (&mutex);
 #endif
+  gegl_buffer_lock (buffer);
 
   if (format == NULL)
     format = buffer->format;
@@ -602,6 +824,11 @@
       g_object_unref (sub_buf);
     }
 
+  if (gegl_buffer_is_shared(buffer))
+    {
+      gegl_buffer_flush (buffer);
+    }
+  gegl_buffer_unlock (buffer); /* XXX: should this happen before flush? */
 #if ENABLE_MP
   g_static_rec_mutex_unlock (&mutex);
 #endif
@@ -1138,3 +1365,102 @@
       buffer->sampler = NULL;
     }
 }
+
+
+void
+gegl_buffer_copy (GeglBuffer          *src,
+                  const GeglRectangle *src_rect,
+                  GeglBuffer          *dst,
+                  const GeglRectangle *dst_rect)
+{
+  /* FIXME: make gegl_buffer_copy work with COW shared tiles when possible */
+
+  GeglRectangle src_line;
+  GeglRectangle dst_line;
+  const Babl   *format;
+  guchar       *temp;
+  guint         i;
+  gint          pxsize;
+
+  g_return_if_fail (GEGL_IS_BUFFER (src));
+  g_return_if_fail (GEGL_IS_BUFFER (dst));
+
+  if (!src_rect)
+    {
+      src_rect = gegl_buffer_get_extent (src);
+    }
+
+  if (!dst_rect)
+    {
+      dst_rect = src_rect;
+    }
+
+  pxsize = src->tile_storage->px_size;
+  format = src->format;
+
+  src_line = *src_rect;
+  src_line.height = 1;
+
+  dst_line = *dst_rect;
+  dst_line.width = src_line.width;
+  dst_line.height = src_line.height;
+
+  temp = g_malloc (src_line.width * pxsize);
+
+  for (i=0; i<src_rect->height; i++)
+    {
+      gegl_buffer_get (src, 1.0, &src_line, format, temp, GEGL_AUTO_ROWSTRIDE);
+      gegl_buffer_set (dst, &dst_line, format, temp, GEGL_AUTO_ROWSTRIDE);
+      src_line.y++;
+      dst_line.y++;
+    }
+  g_free (temp);
+}
+
+void
+gegl_buffer_clear (GeglBuffer          *dst,
+                   const GeglRectangle *dst_rect)
+{
+  /* FIXME: make gegl_buffer_copy work with COW shared tiles when possible */
+
+  GeglRectangle dst_line;
+  const Babl   *format;
+  guchar       *temp;
+  guint         i;
+  gint          pxsize;
+
+  g_return_if_fail (GEGL_IS_BUFFER (dst));
+
+  if (!dst_rect)
+    {
+      dst_rect = gegl_buffer_get_extent (dst);
+    }
+
+  pxsize = dst->tile_storage->px_size;
+  format = dst->format;
+
+  dst_line = *dst_rect;
+  dst_line.height = 1;
+
+  temp = g_malloc0 (dst_line.width * pxsize);
+
+  for (i=0; i<dst_rect->height; i++)
+    {
+      gegl_buffer_set (dst, &dst_line, format, temp, GEGL_AUTO_ROWSTRIDE);
+      dst_line.y++;
+    }
+  g_free (temp);
+}
+
+GeglBuffer *
+gegl_buffer_dup (GeglBuffer *buffer)
+{
+  GeglBuffer *new;
+
+  g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL);
+
+  new = gegl_buffer_new (gegl_buffer_get_extent (buffer), buffer->format);
+  gegl_buffer_copy (buffer, gegl_buffer_get_extent (buffer),
+                    new, gegl_buffer_get_extent (buffer));
+  return new;
+}

Modified: branches/branch_zhangjb/gegl/buffer/gegl-buffer-index.h
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-buffer-index.h	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-buffer-index.h	Sat May 17 17:51:59 2008
@@ -9,18 +9,21 @@
 
 
 /* Increase this number when the structures change.*/
-#define GEGL_FILE_SPEC_REV     23
+#define GEGL_FILE_SPEC_REV     0
 #define GEGL_MAGIC             {'G','E','G','L'}
 
 #define GEGL_FLAG_TILE         1
-#define GEGL_FLAG_FREE_TILE    2
+#define GEGL_FLAG_FREE_TILE    0xf+2
+
+/* a VOID message, indicating that the specified tile has been rewritten */
+#define GEGL_FLAG_INVALIDATED  2
 
 /* these flags are used for the header, the lower bits of the
  * header store the revision
  */
-#define GEGL_FLAG_LOCKED       (0xff*(1<<0))
-#define GEGL_FLAG_FLUSHED      (0xff*(1<<1))
-#define GEGL_FLAG_IS_HEADER    (0xff*(1<<3))
+#define GEGL_FLAG_LOCKED       (1<<(8+0))
+#define GEGL_FLAG_FLUSHED      (1<<(8+1))
+#define GEGL_FLAG_IS_HEADER    (1<<(8+3))
 
 /* The default header we expect to see on a file is that it is
  * flushed, and has the revision the file conforms to written
@@ -34,28 +37,29 @@
  * This header is the first 256 bytes of the GEGL buffer.
  */
 typedef struct {
-  gchar     magic[4];    /* - a 4 byte identifier */
-  guint32   flags;       /* the header flags is used to encode state and revision 
+  gchar   magic[4];    /* - a 4 byte identifier */
+  guint32 flags;       /* the header flags is used to encode state and revision 
                           */
-  guint64   next;        /* offset to first GeglBufferBlock */
+  guint64 next;        /* offset to first GeglBufferBlock */
+
+  guint32 tile_width;       
+  guint32 tile_height;
+  guint16 bytes_per_pixel;
+
+  gchar   description[64]; /* GEGL stores the string of the babl format
+                            * here, as well as after the \0 a debug string
+                            * describing the buffer.
+                            */
+
+  /* the ROI could come as a separate block */
+  gint32  x;               /* indication of bounding box for tiles stored. */
+  gint32  y;               /* this isn't really needed as each GeglBuffer as */
+  guint32 width;           /* represented on disk doesn't really have any */
+  guint32 height;          /* dimension restriction. */
 
-  guint32   tile_width;       
-  guint32   tile_height;
-  guint16   bytes_per_pixel;
-
-  gchar     description[64]; /* GEGL stores the string of the babl format
-                              * here, as well as after the \0 a debug string
-                              * describing the buffer.
-                              */
-
-  /* the ROI should come as a separate block */
-  gint32    x;               /* indication of bounding box for tiles stored. */
-  gint32    y;               /* this isn't really needed as each GeglBuffer as */
-  guint32   width;           /* represented on disk doesn't really have any */
-  guint32   height;          /* dimension restriction. */
+  guint32 rev;             /* if it changes on disk it means the index has changed */
 
-  guint32   entry_count;     /* for integrity check. */
-  gint32    padding[36];     /* Pad the structure to be 256 bytes long */
+  gint32  padding[36];     /* Pad the structure to be 256 bytes long */
 } GeglBufferHeader;
 
 /* the revision of the format is stored in the flags of the header in the
@@ -86,14 +90,19 @@
   gint32  y;           
 
   gint32  z;             /* mipmap subdivision level of tile (0=100%)  */
+
+  guint32 rev;           /* revision, if a buffer is monitored for header
+                            revision changes, the existing loaded index
+                            can be compare the revision of tiles and update
+                            own state when revision differs. */
 } GeglBufferTile;
 
 /* A convenience union to allow quick and simple casting */
 typedef union {
-  guint32           length;
-  GeglBufferBlock   block;
-  GeglBufferHeader  header;
-  GeglBufferTile    tile;
+  guint32          length;
+  GeglBufferBlock  block;
+  GeglBufferHeader header;
+  GeglBufferTile   tile;
 } GeglBufferItem;
 
 /* functions to initialize data structures */
@@ -101,6 +110,10 @@
                                       gint y,
                                       gint z);
 
+/* intializing the header causes the format to be written out
+ * as well as a hidden comment after the zero terminated format
+ * with additional human readable information about the header.
+ */
 void gegl_buffer_header_init (GeglBufferHeader *header,
                               gint              tile_width,
                               gint              tile_height,
@@ -109,10 +122,10 @@
 
 void gegl_tile_entry_destroy (GeglBufferTile *entry);
 
-GeglBufferItem *gegl_buffer_read_header (GInputStream *i,
-                                         goffset      *offset);
-GList          *gegl_buffer_read_index  (GInputStream *i,
-                                         goffset      *offset);
+GeglBufferItem *gegl_buffer_read_header(GInputStream *i,
+                                        goffset      *offset);
+GList          *gegl_buffer_read_index (GInputStream *i,
+                                        goffset      *offset);
 
 #define struct_check_padding(type, size) \
   if (sizeof (type) != size) \
@@ -126,7 +139,7 @@
     }
 #define GEGL_BUFFER_STRUCT_CHECK_PADDING \
   {struct_check_padding (GeglBufferBlock, 16);\
-  struct_check_padding (GeglBufferHeader,   256);}
+  struct_check_padding (GeglBufferHeader, 256);}
 #define GEGL_BUFFER_SANITY {static gboolean done=FALSE;if(!done){GEGL_BUFFER_STRUCT_CHECK_PADDING;done=TRUE;}}
 
 #endif

Modified: branches/branch_zhangjb/gegl/buffer/gegl-buffer-load.c
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-buffer-load.c	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-buffer-load.c	Sat May 17 17:51:59 2008
@@ -27,7 +27,6 @@
 #include "gegl-types.h"
 #include "gegl-buffer-types.h"
 #include "gegl-buffer.h"
-#include "gegl-buffer-load.h"
 #include "gegl-tile-storage.h"
 #include "gegl-tile-backend.h"
 #include "gegl-tile-handler.h"
@@ -45,7 +44,6 @@
 
 #include <glib/gprintf.h>
 
-#if 0
 typedef struct
 {
   GeglBufferHeader header;
@@ -95,13 +93,14 @@
   g_slice_free (LoadInfo, info);
 }
 
-#endif
-
 GeglBufferItem *
 gegl_buffer_read_header (GInputStream *i,
                          goffset      *offset)
 {
+  goffset         placeholder;
   GeglBufferItem *ret;
+  if (offset==0)
+    offset = &placeholder;
 
   if(!g_seekable_seek (G_SEEKABLE (i), 0, G_SEEK_SET, NULL, NULL))
       g_warning ("failed seeking to %i", 0);
@@ -212,7 +211,6 @@
   GList          *ret = NULL;
   GeglBufferItem *item;
 
-  g_print ("%i\n", (gint)*offset); 
   for (item = read_block (i, offset); item; item = read_block (i, offset))
     {
       g_assert (item);
@@ -238,9 +236,11 @@
   sanity();
 
   return g_object_new (GEGL_TYPE_BUFFER, "path", path, NULL);
+}
 
-#if 0  /* old code that feeds tile by tile into the buffer */
-
+GeglBuffer *
+gegl_buffer_load (const gchar *path)
+{
   GeglBuffer *ret;
 
   LoadInfo *info = g_slice_new0 (LoadInfo);
@@ -333,5 +333,4 @@
 
   load_info_destroy (info);
   return ret;
-#endif
 }

Modified: branches/branch_zhangjb/gegl/buffer/gegl-buffer-load.h
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-buffer-load.h	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-buffer-load.h	Sat May 17 17:51:59 2008
@@ -23,7 +23,5 @@
 
 #include "gegl-buffer.h"
 
-void gegl_buffer_load (GeglBuffer    *buffer,
-                       const gchar   *path);
 
 #endif

Modified: branches/branch_zhangjb/gegl/buffer/gegl-buffer-private.h
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-buffer-private.h	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-buffer-private.h	Sat May 17 17:51:59 2008
@@ -63,6 +63,8 @@
   gint              tile_width;
   gint              tile_height;
   gchar            *path;
+
+  gint              lock_count;
 };
 
 struct _GeglBufferClass
@@ -91,4 +93,54 @@
 
 GeglTileBackend    * gegl_buffer_backend     (GeglBuffer *buffer);
 
+gboolean             gegl_buffer_is_shared   (GeglBuffer *buffer);
+
+gboolean             gegl_buffer_try_lock    (GeglBuffer *buffer);
+gboolean             gegl_buffer_lock        (GeglBuffer *buffer);
+gboolean             gegl_buffer_unlock      (GeglBuffer *buffer);
+
+
+typedef struct GeglBufferTileIterator
+{
+  GeglBuffer    *buffer;
+  GeglTile      *tile;
+  GeglRectangle  roi;
+  gint           col;
+  gint           row;
+  gboolean       write; /* perhaps in a subclass struct? */
+  GeglRectangle  subrect; /* has negative x when entire tile is valid */
+  gpointer       data;
+  gpointer       sub_data;
+  gint           rowstride;
+} GeglBufferTileIterator;
+
+typedef struct GeglBufferScanIterator {
+  GeglBufferTileIterator tile_iterator;
+  gint                   max_size; /*  in bytes */
+  gint                   width;
+  gint                   row;
+  gpointer               data;
+} GeglBufferScanIterator;
+
+gboolean                gegl_buffer_tile_iterator_next (GeglBufferTileIterator *i);
+gboolean                gegl_buffer_scan_iterator_next (GeglBufferScanIterator *i);
+GeglBufferTileIterator *gegl_buffer_tile_iterator_new  (GeglBuffer             *buffer,
+                                                        GeglRectangle           roi,
+                                                        gboolean                write);
+void                    gegl_buffer_tile_iterator_init (GeglBufferTileIterator *i,
+                                                        GeglBuffer             *buffer,
+                                                        GeglRectangle           roi,
+                                                        gboolean                write);
+
+void gegl_buffer_scan_iterator_init (GeglBufferScanIterator *i,
+                                     GeglBuffer             *buffer,
+                                     GeglRectangle           roi,
+                                     gboolean                write);
+GeglBufferScanIterator *gegl_buffer_scan_iterator_new (GeglBuffer             *buffer,
+                                                       GeglRectangle           roi,
+                                                       gboolean                write);
+gboolean                gegl_buffer_scan_compatible   (GeglBuffer *input,
+                                                       GeglBuffer *output);
+
+
 #endif

Modified: branches/branch_zhangjb/gegl/buffer/gegl-buffer-save.c
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-buffer-save.c	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-buffer-save.c	Sat May 17 17:51:59 2008
@@ -50,6 +50,7 @@
 
   gint             tile_size;
   gint             offset;
+  gint             entry_count;
   GeglBufferBlock *last_added;
   GeglBufferBlock *in_holding; /* we need to write one block added behind
                                 * to be able to recompute the forward pointing
@@ -63,7 +64,7 @@
                      gint y,
                      gint z)
 {
-  GeglBufferTile *entry = g_slice_new0 (GeglBufferTile);
+  GeglBufferTile *entry = g_malloc (sizeof(GeglBufferTile));
   entry->block.flags = GEGL_FLAG_TILE;
   entry->block.length = sizeof (GeglBufferTile);
 
@@ -76,7 +77,7 @@
 void
 gegl_tile_entry_destroy (GeglBufferTile *entry)
 {
-  g_slice_free (GeglBufferTile, entry);
+  g_free (entry);
 }
 
 static gsize write_block (SaveInfo        *info,
@@ -174,17 +175,18 @@
   strcpy (header->magic, "GEGL");
 
   header->flags = GEGL_FLAG_HEADER;
-
   header->tile_width  = tile_width;
   header->tile_height = tile_height;
   header->bytes_per_pixel = bpp;
   {
     gchar buf[64];
-    g_snprintf (buf, 64, "%s%c\n%iÃ%i %ibpp\n\n\n\n\n\n\n\n\n\n", 
+    g_snprintf (buf, 64, "%s%c\n%iÃ%i %ibpp\n%ix%i\n\n\n\n\n\n\n\n\n", 
           format->instance.name, 0,
           header->tile_width,
           header->tile_height,
-          header->bytes_per_pixel);
+          header->bytes_per_pixel,
+          (gint)header->width,
+          (gint)header->height);
     memcpy ((header->description), buf, 64);
   }
 }
@@ -211,6 +213,10 @@
   info->o    = G_OUTPUT_STREAM (g_file_replace (info->file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
 
   g_object_get (buffer, "px-size", &bpp, NULL);
+  info->header.x           = buffer->extent.x;
+  info->header.y           = buffer->extent.y;
+  info->header.width       = buffer->extent.width;
+  info->header.height      = buffer->extent.height;
   gegl_buffer_header_init (&info->header,
                            buffer->tile_storage->tile_width,
                            buffer->tile_storage->tile_height,
@@ -219,10 +225,6 @@
                            );
   info->header.next = (prediction += sizeof (GeglBufferHeader));
 
-  info->header.x           = buffer->extent.x;
-  info->header.y           = buffer->extent.y;
-  info->header.width       = buffer->extent.width;
-  info->header.height      = buffer->extent.height;
 
   info->tile_size = info->header.tile_width  *
                     info->header.tile_height *
@@ -275,7 +277,7 @@
 
                       entry = gegl_tile_entry_new (tx, ty, z);
                       info->tiles = g_list_prepend (info->tiles, entry);
-                      info->header.entry_count++;
+                      info->entry_count++;
                     }
                   bufx += (tile_width - offsetx) * factor;
                 }
@@ -298,7 +300,7 @@
   {
     GList *iter;
     gint   predicted_offset = sizeof (GeglBufferHeader) +
-                              sizeof (GeglBufferTile) * (info->header.entry_count);
+                              sizeof (GeglBufferTile) * (info->entry_count);
     for (iter = info->tiles; iter; iter = iter->next)
       {
         GeglBufferTile *entry = iter->data;
@@ -326,7 +328,9 @@
   }
   write_block (info, NULL); /* terminate the index */
 
-  /* update header to point to start of new index */
+  /* update header to point to start of new index (already done for
+   * this serial saver, and the header is already written.
+   */
 
   /* save each tile */
   {
@@ -351,7 +355,6 @@
         g_object_unref (G_OBJECT (tile));
         i++;
       }
-    g_assert (i == info->header.entry_count);
   }
   save_info_destroy (info);
 }

Modified: branches/branch_zhangjb/gegl/buffer/gegl-buffer-share.c
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-buffer-share.c	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-buffer-share.c	Sat May 17 17:51:59 2008
@@ -28,6 +28,7 @@
 #include "gegl-buffer-private.h"
 #include "gegl-id-pool.h"
 
+#if 0
 static GeglIDPool *pool = NULL;
 
 guint
@@ -43,44 +44,6 @@
   return id;
 }
 
-
-void
-gegl_buffer_make_uri (gchar       *buf_128,
-                      gchar       *host,
-                      gint         port,
-                      gint         process,
-                      gint         handle)
-{
-  gchar *p=buf_128;
-
-  g_sprintf (p, "buffer://%s", host?host:"");
-  p+=strlen (p);
-  if (port)
-    {
-      g_sprintf (p, ":%i", port);
-      p+=strlen (p);
-    }
-  g_sprintf (p, "/");
-  p+=strlen (p);
-  if (process)
-    {
-      g_sprintf (p, "%i", process);
-      p+=strlen (p);
-    }
-  g_sprintf (p, "/");
-  p+=strlen (p);
-  if (handle || 1)
-    {
-      g_sprintf (p, "%i", handle);
-      p+=strlen (p);
-    }
-  else
-    {
-      g_warning ("no handle provided when building uri:\n%s\n", buf_128);
-    }
-}
-
-#if 0
 GeglBuffer*
 gegl_buffer_open (const gchar *uri)
 {

Modified: branches/branch_zhangjb/gegl/buffer/gegl-buffer.c
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-buffer.c	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-buffer.c	Sat May 17 17:51:59 2008
@@ -68,7 +68,6 @@
 
 G_DEFINE_TYPE (GeglBuffer, gegl_buffer, GEGL_TYPE_TILE_HANDLER)
 
-
 static GObjectClass * parent_class = NULL;
 
 enum
@@ -92,13 +91,18 @@
   PROP_PATH
 };
 
+enum {
+  CHANGED,
+  LAST_SIGNAL
+};
+
+guint gegl_buffer_signals[LAST_SIGNAL] = { 0 };
+
 static GeglBuffer * gegl_buffer_new_from_format (const void *babl_format,
                                                  gint        x,
                                                  gint        y,
                                                  gint        width,
                                                  gint        height);
-static GeglBuffer *
-gegl_buffer_new_from_path (const gchar *path);
 
 static inline gint needed_tiles (gint w,
                                  gint stride)
@@ -275,6 +279,28 @@
 static gint allocated_buffers    = 0;
 static gint de_allocated_buffers = 0;
 
+  /* this should only be possible if this buffer matches all the buffers down to
+   * storage, all of those parent buffers would change size as well, no tiles
+   * would be voided as a result of changing the extent.
+   */
+gboolean
+gegl_buffer_set_extent (GeglBuffer          *buffer,
+                        const GeglRectangle *extent)
+{
+   (*(GeglRectangle*)gegl_buffer_get_extent (buffer))=*extent;
+
+  if ((GeglBufferHeader*)(gegl_buffer_backend (buffer)->header))
+    {   
+      GeglBufferHeader *header = ((GeglBufferHeader*)(gegl_buffer_backend (buffer)->header));
+      header->x = buffer->extent.x;
+      header->y = buffer->extent.x;
+      header->width = buffer->extent.width;
+      header->height = buffer->extent.height;
+    }
+
+  return TRUE;
+}
+
 void gegl_buffer_stats (void)
 {
   g_warning ("Buffer statistics: allocated:%i deallocated:%i balance:%i",
@@ -312,12 +338,17 @@
       buffer->hot_tile = NULL;
     }
 
-  de_allocated_buffers++; /* XXX: is it correct to count that, shouldn't that
-                             only be counted in finalize? */
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
 
+static void
+gegl_buffer_finalize (GObject *object)
+{
+  de_allocated_buffers++;
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
 GeglTileBackend *
 gegl_buffer_backend (GeglBuffer *buffer)
 {
@@ -356,6 +387,13 @@
 
 void babl_backtrack (void);
 
+static void storage_changed (GeglTileStorage     *storage,
+                             const GeglRectangle *rect,
+                             gpointer             userdata)
+{
+  g_signal_emit_by_name (GEGL_BUFFER (userdata), "changed", rect, NULL);
+}
+
 static GObject *
 gegl_buffer_constructor (GType                  type,
                          guint                  n_params,
@@ -369,6 +407,11 @@
   gint             tile_width;
   gint             tile_height;
 
+  gint width;
+  gint height;
+  gint x;
+  gint y;
+
   object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
 
   buffer    = GEGL_BUFFER (object);
@@ -376,6 +419,11 @@
   source  = handler->source;
   backend   = gegl_buffer_backend (buffer);
 
+  x=buffer->extent.x;
+  y=buffer->extent.y;
+  width=buffer->extent.width;
+  height=buffer->extent.height;
+
   if (source)
     {
       if (GEGL_IS_TILE_STORAGE (source))
@@ -388,13 +436,31 @@
     {
       /* if no source is specified if a format is specified, we
        * we need to create our own
-       * source (this adds a redirectin buffer in between for
+       * source (this adds a redirection buffer in between for
        * all "allocated from format", type buffers.
        */
       if (buffer->path)
         {
           GeglBufferHeader *header;
-          source = GEGL_TILE_SOURCE (gegl_buffer_new_from_path (buffer->path));
+          GeglTileSource   *storage;
+
+          if (buffer->format)
+            {
+              storage = GEGL_TILE_SOURCE (g_object_new (GEGL_TYPE_TILE_STORAGE,
+                                                       "path", buffer->path,
+                                                       "format", buffer->format,
+                                                       NULL));
+            }
+          else
+            {
+              storage = GEGL_TILE_SOURCE (g_object_new (GEGL_TYPE_TILE_STORAGE,
+                                                       "path", buffer->path,
+                                                       "format", babl_format ("RGBA float"),
+                                                       NULL));
+            }
+
+          source = g_object_new (GEGL_TYPE_BUFFER, "source", storage, NULL);
+                                                   
           /* after construction,. x and y should be set to reflect
            * the top level behavior exhibited by this buffer object.
            */
@@ -403,6 +469,9 @@
                         NULL);
           g_object_unref (source);
 
+          g_signal_connect (storage, "changed",
+                            G_CALLBACK(storage_changed), buffer);
+
           g_assert (source);
           backend = gegl_buffer_backend (GEGL_BUFFER (source));
           g_assert (backend);
@@ -437,6 +506,20 @@
         {
           g_warning ("not enough data to have a tile source for our buffer");
         }
+      {
+        /* we reset the size if it seems to have been set to 0 during a on
+         * disk buffer creation, nasty but it seems to do the job.
+         */
+
+        if (buffer->extent.width == 0 &&
+            buffer->extent.width == 0)
+          {
+            buffer->extent.width = width;
+            buffer->extent.height = height;
+            buffer->extent.x = x;
+            buffer->extent.y = y;
+          }
+      }
     }
 
   g_assert (backend);
@@ -556,6 +639,8 @@
   if (tile)
     {
       GeglBuffer *buffer = GEGL_BUFFER (handler);
+
+      /* not sure if this plays well with shifting */
       tile->x = x;
       tile->y = y;
       tile->z = z;
@@ -576,10 +661,10 @@
        * coordinates.
        */
       {
-        tile->tile_storage   = buffer->tile_storage;
-        tile->storage_x = x;
-        tile->storage_y = y;
-        tile->storage_z = z;
+        tile->tile_storage = buffer->tile_storage;
+        tile->x = x;
+        tile->y = y;
+        tile->z = z;
       }
     }
 
@@ -613,6 +698,7 @@
 
   parent_class                = g_type_class_peek_parent (class);
   gobject_class->dispose      = gegl_buffer_dispose;
+  gobject_class->finalize     = gegl_buffer_finalize;
   gobject_class->constructor  = gegl_buffer_constructor;
   gobject_class->set_property = set_property;
   gobject_class->get_property = get_property;
@@ -630,22 +716,22 @@
                                    g_param_spec_int ("width", "width", "pixel width of buffer",
                                                      -1, G_MAXINT, -1,
                                                      G_PARAM_READWRITE |
-                                                     G_PARAM_CONSTRUCT_ONLY));
+                                                     G_PARAM_CONSTRUCT));
   g_object_class_install_property (gobject_class, PROP_HEIGHT,
                                    g_param_spec_int ("height", "height", "pixel height of buffer",
                                                      -1, G_MAXINT, -1,
                                                      G_PARAM_READWRITE |
-                                                     G_PARAM_CONSTRUCT_ONLY));
+                                                     G_PARAM_CONSTRUCT));
   g_object_class_install_property (gobject_class, PROP_X,
                                    g_param_spec_int ("x", "x", "local origin's offset relative to source origin",
                                                      G_MININT, G_MAXINT, 0,
                                                      G_PARAM_READWRITE |
-                                                     G_PARAM_CONSTRUCT_ONLY));
+                                                     G_PARAM_CONSTRUCT));
   g_object_class_install_property (gobject_class, PROP_Y,
                                    g_param_spec_int ("y", "y", "local origin's offset relative to source origin",
                                                      G_MININT, G_MAXINT, 0,
                                                      G_PARAM_READWRITE |
-                                                     G_PARAM_CONSTRUCT_ONLY));
+                                                     G_PARAM_CONSTRUCT));
   g_object_class_install_property (gobject_class, PROP_ABYSS_WIDTH,
                                    g_param_spec_int ("abyss-width", "abyss-width", "pixel width of abyss",
                                                      -1, G_MAXINT, 0,
@@ -697,6 +783,17 @@
                                    g_param_spec_string ("path", "Path",
                                                         "URI to where the buffer is stored",
                                      NULL, G_PARAM_READWRITE|G_PARAM_CONSTRUCT));
+
+  gegl_buffer_signals[CHANGED] =
+        g_signal_new ("changed",
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
+                  0,
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__BOXED,
+                  G_TYPE_NONE, 1,
+                  GEGL_TYPE_RECTANGLE);
+
 }
 
 static void
@@ -778,69 +875,6 @@
                        NULL);
 }
 
-void
-gegl_buffer_copy (GeglBuffer          *src,
-                  const GeglRectangle *src_rect,
-                  GeglBuffer          *dst,
-                  const GeglRectangle *dst_rect)
-{
-  /* FIXME: make gegl_buffer_copy work with COW shared tiles when possible */
-
-  GeglRectangle src_line;
-  GeglRectangle dst_line;
-  const Babl   *format;
-  guchar       *temp;
-  guint         i;
-  gint          pxsize;
-
-  g_return_if_fail (GEGL_IS_BUFFER (src));
-  g_return_if_fail (GEGL_IS_BUFFER (dst));
-
-  if (!src_rect)
-    {
-      src_rect = gegl_buffer_get_extent (src);
-    }
-
-  if (!dst_rect)
-    {
-      dst_rect = src_rect;
-    }
-
-  pxsize = src->tile_storage->px_size;
-  format = src->format;
-
-  src_line = *src_rect;
-  src_line.height = 1;
-
-  dst_line = *dst_rect;
-  dst_line.width = src_line.width;
-  dst_line.height = src_line.height;
-
-  temp = g_malloc (src_line.width * pxsize);
-
-  for (i=0; i<src_rect->height; i++)
-    {
-      gegl_buffer_get (src, 1.0, &src_line, format, temp, GEGL_AUTO_ROWSTRIDE);
-      gegl_buffer_set (dst, &dst_line, format, temp, GEGL_AUTO_ROWSTRIDE);
-      src_line.y++;
-      dst_line.y++;
-    }
-  g_free (temp);
-}
-
-GeglBuffer *
-gegl_buffer_dup (GeglBuffer *buffer)
-{
-  GeglBuffer *new;
-
-  g_return_val_if_fail (GEGL_IS_BUFFER (buffer), NULL);
-
-  new = gegl_buffer_new (gegl_buffer_get_extent (buffer), buffer->format);
-  gegl_buffer_copy (buffer, gegl_buffer_get_extent (buffer),
-                    new, gegl_buffer_get_extent (buffer));
-  return new;
-}
-
 
 void
 gegl_buffer_destroy (GeglBuffer *buffer)
@@ -869,29 +903,6 @@
 
 
 static GeglBuffer *
-gegl_buffer_new_from_path (const gchar *path)
-{
-  GeglTileStorage *tile_storage;
-  GeglBuffer  *buffer;
-
-  tile_storage = g_object_new (GEGL_TYPE_TILE_STORAGE,
-                              "format", babl_format,
-                              "path",   path,
-                              NULL);
-  buffer = g_object_new (GEGL_TYPE_BUFFER,
-                                    "source", tile_storage,
-                                    /*"x", x,
-                                    "y", y,
-                                    "width", width,
-                                    "height", height,*/
-                                    NULL);
-  /* XXX: query backend about width/height? (this seems odd) */
-
-  g_object_unref (tile_storage);
-  return buffer;
-}
-
-static GeglBuffer *
 gegl_buffer_new_from_format (const void *babl_format,
                              gint        x,
                              gint        y,
@@ -1005,3 +1016,49 @@
       }
   }
 }
+
+gboolean gegl_buffer_is_shared (GeglBuffer *buffer)
+{
+  GeglTileBackend *backend = gegl_buffer_backend (buffer);
+  return backend->shared;
+}
+
+gboolean gegl_buffer_try_lock (GeglBuffer *buffer)
+{
+  GeglTileBackend *backend = gegl_buffer_backend (buffer);
+  gboolean ret;
+
+  if (buffer->lock_count>0)
+    {
+      buffer->lock_count++;
+      return TRUE;
+    }
+  if (gegl_buffer_is_shared(buffer))
+    ret =gegl_tile_backend_file_try_lock (GEGL_TILE_BACKEND_FILE (backend));
+  else
+    ret = TRUE;
+  if (ret)
+    buffer->lock_count++;
+  return TRUE;
+}
+
+gboolean gegl_buffer_lock (GeglBuffer *buffer)
+{
+  while (gegl_buffer_try_lock (buffer)==FALSE)
+    {
+      g_print ("failed to aquire lock blocking ..");
+        g_usleep (100000);
+    }
+  return TRUE;
+}
+
+gboolean gegl_buffer_unlock (GeglBuffer *buffer)
+{
+  GeglTileBackend *backend = gegl_buffer_backend (buffer);
+  g_assert (buffer->lock_count>=0);
+  buffer->lock_count--;
+  g_assert (buffer->lock_count>=0);
+  if (buffer->lock_count==0 && gegl_buffer_is_shared (buffer))
+    return gegl_tile_backend_file_unlock (GEGL_TILE_BACKEND_FILE (backend));
+  return TRUE;
+}

Modified: branches/branch_zhangjb/gegl/buffer/gegl-buffer.h
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-buffer.h	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-buffer.h	Sat May 17 17:51:59 2008
@@ -56,39 +56,54 @@
                                                const Babl          *format);
 
 
-/** 
- * gegl_buffer_share:
- * @buffer: a #GeglBuffer.
+/**
+ * gegl_buffer_open:
+ * @path: the path to a gegl buffer on disk.
+ * be opened.
  *
- * return a integer handle or 0 upon error, the handle returned is
- * unique for this process on this host,
+ * Open an existing on-disk GeglBuffer, this buffer is opened in a monitored
+ * state so multiple instances of gegl can share the same buffer. Sets on
+ * one buffer are reflected in the other.
  *
- * An uri for this buffer can be constructed by gegl_buffer_make_uri.
+ * Returns: a GeglBuffer object.
+ */
+GeglBuffer*     gegl_buffer_open              (const gchar         *path);
+
+/**
+ * gegl_buffer_save:
+ * @buffer: a #GeglBuffer.
+ * @path: the path where the gegl buffer will be saved, any writable GIO uri is valid.
+ * @roi: the region of interest to write, this is the tiles that will be collected and
+ * written to disk.
  *
- * Returns: an integer handle for referring to this buffer.
+ * Write a GeglBuffer to a file.
  */
-guint           gegl_buffer_share             (GeglBuffer          *buffer);
+void            gegl_buffer_save              (GeglBuffer          *buffer,
+                                               const gchar         *path,
+                                               const GeglRectangle *roi);
 
 /**
- * gegl_buffer_open:
- * @uri: a uri referring to a local, other process or other host buffer to
+ * gegl_buffer_load:
+ * @path: the path to a gegl buffer on disk.
  * be opened.
  *
- * buffer://host:port/process/handle
- * buffer:////42      handle 42 from same GEGL instance.
+ * Loads an existing GeglBuffer from disk, if it has previously been saved with
+ * gegl_buffer_save it should be possible to open through any GIO transport, buffers
+ * that have been used as swap needs random access to be opened.
  *
- * Returns: a GeglBuffer object.
+ * Returns: a #GeglBuffer object.
  */
+GeglBuffer     *gegl_buffer_load              (const gchar         *path);
 
-GeglBuffer*     gegl_buffer_open              (const gchar         *uri);
+/**
+ * gegl_buffer_flush:
+ * @buffer: a #GeglBuffer
+ *
+ * Flushes all unsaved data to disk, this is not neccesary for shared
+ * geglbuffers opened with gegl_buffer_open since they auto-sync on writes.
+ */
 void            gegl_buffer_flush             (GeglBuffer          *buffer);
 
-void
-gegl_buffer_make_uri (gchar       *buf_128,
-                      gchar       *host,
-                      gint         port,
-                      gint         process,
-                      gint         handle);
 
 /** 
  * gegl_buffer_create_sub_buffer:
@@ -120,6 +135,21 @@
  */
 const GeglRectangle * gegl_buffer_get_extent (GeglBuffer *buffer);
 
+
+/**
+ * gegl_buffer_set_extent:
+ * @buffer: the buffer to operate on.
+ * @extent: new extent.
+ *
+ * Changes the size and position that is considered active in a buffer, this
+ * operation is valid on any buffer, reads on subbuffers outside the master
+ * buffers extent are at the moment undefined.
+ *
+ * Returns TRUE if the change of extent was succesful.
+ */
+gboolean gegl_buffer_set_extent (GeglBuffer          *buffer,
+                                 const GeglRectangle *extent);
+
 /* convenience access macros */
 
 /**
@@ -158,7 +188,7 @@
  * gegl_buffer_get_pixel_count:
  * @buffer: a GeglBuffer
  *
- * Evaluates to the total number of pixels in a buffer.
+ * Returns the number of pixels of the extent of the buffer.
  */
 #define gegl_buffer_get_pixel_count(buffer) (gegl_buffer_get_width(buffer) * gegl_buffer_get_height(buffer))
 
@@ -210,6 +240,18 @@
 
 
 /**
+ * gegl_buffer_clear:
+ * @buffer: a #GeglBuffer
+ * @roi: a rectangular region
+ *
+ * Clears the provided rectangular region by setting all the associated memory
+ * to 0
+ */
+void            gegl_buffer_clear             (GeglBuffer          *buffer,
+                                               const GeglRectangle *roi);
+
+
+/**
  * gegl_buffer_copy:
  * @src: source buffer.
  * @src_rect: source rectangle (or NULL to copy entire source buffer)

Modified: branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-file.c
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-file.c	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-file.c	Sat May 17 17:51:59 2008
@@ -28,9 +28,8 @@
 #include "gegl-tile-backend.h"
 #include "gegl-tile-backend-file.h"
 #include "gegl-buffer-index.h"
-
 #include "gegl-debug.h"
-
+#include "gegl-types.h"
 
 struct _GeglTileBackendFile
 {
@@ -40,14 +39,17 @@
   GFile           *file;    /* gfile refering to our buffer */
   GOutputStream   *o;       /* for writing */
   GInputStream    *i;       /* for reading */
+  gboolean         exist;   /* the file exist (and we've thus been able
+                             * to initialize i and o, the utility_call ensure_exist
+                             * should be called before any code using i and o)
+                             */
 
-  /*gint             fd;*/
   GHashTable      *index;   /* hashtable containing all entries
-                               * of buffer, the index is
-                               * written to the swapfile conforming
-                               * to the structures laid out in
-                               * gegl-buffer-index.h
-                               */
+                             * of buffer, the index is
+                             * written to the swapfile conforming
+                             * to the structures laid out in
+                             * gegl-buffer-index.h
+                             */
 
   GSList          *free_list; /* list of offsets to tiles that are free */
 
@@ -74,8 +76,17 @@
   /* loading buffer */
 
   GList *tiles;
+
+  /* cooperative sharing of file */
+
+  GFileMonitor    *monitor; /* Before using mmap we'll use GIO's infrastructure
+                             * for monitoring the file for changes, this should
+                             * also be more portable.
+                             */
+  guint32          rev;     /* revision of last index sync */
 };
 
+static void ensure_exist (GeglTileBackendFile *self);
 
 static gboolean
 write_block (GeglTileBackendFile *self,
@@ -94,7 +105,9 @@
   gint     tile_size = GEGL_TILE_BACKEND (self)->tile_size;
   goffset  offset = entry->offset;
 
-  success = g_seekable_seek (G_SEEKABLE (self->i), 
+  ensure_exist (self);
+
+  success = g_seekable_seek (G_SEEKABLE (self->i),
                              offset, G_SEEK_SET,
                              NULL, NULL);
   if (success == FALSE)
@@ -120,7 +133,9 @@
         }
       to_be_read -= read;
     }
-   GEGL_NOTE (TILE_BACKEND, "read entry %i,%i,%i at %i", entry->x, entry->y, entry->z, (gint)offset);
+
+
+  GEGL_NOTE (TILE_BACKEND, "read entry %i,%i,%i at %i", entry->x, entry->y, entry->z, (gint)offset);
 }
 
 static void inline
@@ -133,7 +148,9 @@
   gint     tile_size = GEGL_TILE_BACKEND (self)->tile_size;
   goffset  offset = entry->offset;
 
-  success = g_seekable_seek (G_SEEKABLE (self->o), 
+  ensure_exist (self);
+
+  success = g_seekable_seek (G_SEEKABLE (self->o),
                              offset, G_SEEK_SET,
                              NULL, NULL);
   if (success == FALSE)
@@ -159,7 +176,7 @@
         }
       to_be_written -= wrote;
     }
-   GEGL_NOTE (TILE_BACKEND, "read entry %i,%i,%i at %i", entry->x, entry->y, entry->z, (gint)offset);
+   GEGL_NOTE (TILE_BACKEND, "wrote entry %i,%i,%i at %i", entry->x, entry->y, entry->z, (gint)offset);
 }
 
 static inline GeglBufferTile *
@@ -169,13 +186,15 @@
 
   GEGL_NOTE (TILE_BACKEND, "Creating new entry");
 
+  ensure_exist (self);
+
   if (self->free_list)
     {
       /* XXX: losing precision ? */
       gint offset = GPOINTER_TO_INT (self->free_list->data);
       entry->offset = offset;
       self->free_list = g_slist_remove (self->free_list, self->free_list->data);
-      
+
       GEGL_NOTE (TILE_BACKEND, "  set offset %i from free list", ((gint)entry->offset));
     }
   else
@@ -189,7 +208,7 @@
       if (self->next_pre_alloc >= self->total)
         {
           self->total = self->total + 32 * tile_size;
-        
+
           GEGL_NOTE (TILE_BACKEND, "growing file to %i bytes", (gint)self->total);
 
           g_assert (g_seekable_truncate (G_SEEKABLE (self->o),
@@ -211,12 +230,16 @@
   g_hash_table_remove (self->index, entry);
 
   dbg_dealloc (GEGL_TILE_BACKEND (self)->tile_size);
-  g_slice_free (GeglBufferTile, entry);
+  g_free (entry);
 }
 
-static gboolean write_header (GeglTileBackendFile *self)
+static gboolean
+write_header (GeglTileBackendFile *self)
 {
   gboolean success;
+
+  ensure_exist (self);
+
   success = g_seekable_seek (G_SEEKABLE (self->o), 0, G_SEEK_SET,
                              NULL, NULL);
   if (success == FALSE)
@@ -233,6 +256,7 @@
 write_block (GeglTileBackendFile *self,
              GeglBufferBlock     *block)
 {
+  ensure_exist (self);
    if (self->in_holding)
      {
        guint64 next_allocation = self->offset + self->in_holding->length;
@@ -256,7 +280,7 @@
              (gint)self->in_holding->next,
              (gint)self->offset);
        self->offset += g_output_stream_write (self->o, self->in_holding,
-                                              self->in_holding->length, 
+                                              self->in_holding->length,
                                               NULL, NULL);
 
        g_assert (next_allocation == self->offset); /* true as long as
@@ -274,7 +298,7 @@
                                               * header inside free list later
                                               */
 
-        if(!g_seekable_seek (G_SEEKABLE (self->o), 
+        if(!g_seekable_seek (G_SEEKABLE (self->o),
                              (goffset) self->offset, G_SEEK_SET,
                              NULL, NULL))
           goto fail;
@@ -362,8 +386,8 @@
     return NULL;
 
   tile             = gegl_tile_new (backend->tile_size);
-  tile->stored_rev = 1;
-  tile->rev        = 1;
+  tile->rev        = entry->rev;
+  tile->stored_rev = entry->rev;
 
   file_entry_read (tile_backend_file, entry, tile->data);
   return tile;
@@ -392,10 +416,8 @@
       entry->z = z;
       g_hash_table_insert (tile_backend_file->index, entry, entry);
     }
+  entry->rev = tile->rev;
 
-  g_assert (tile->flags == 0); /* when this one is triggered, dirty pyramid data
-                                  has been tried written to persistent tile_storage.
-                                */
   file_entry_write (tile_backend_file, entry, tile->data);
   tile->stored_rev = tile->rev;
   return NULL;
@@ -431,18 +453,17 @@
             gint            y,
             gint            z)
 {
-  GeglTileBackend         *backend;
+  GeglTileBackend     *backend;
   GeglTileBackendFile *tile_backend_file;
-  GeglBufferTile               *entry;
+  GeglBufferTile      *entry;
 
-  backend               = GEGL_TILE_BACKEND (self);
+  backend           = GEGL_TILE_BACKEND (self);
   tile_backend_file = GEGL_TILE_BACKEND_FILE (backend);
-  entry                 = lookup_entry (tile_backend_file, x, y, z);
+  entry             = lookup_entry (tile_backend_file, x, y, z);
 
   return entry!=NULL?((gpointer)0x1):NULL;
 }
 
-#include "gegl-buffer-index.h"
 
 static gpointer
 flush (GeglTileSource *source,
@@ -458,9 +479,12 @@
   backend  = GEGL_TILE_BACKEND (source);
   self     = GEGL_TILE_BACKEND_FILE (backend);
 
+  ensure_exist (self);
+
   GEGL_NOTE (TILE_BACKEND, "flushing %s", self->path);
 
 
+  self->header.rev ++;
   self->header.next = self->next_pre_alloc; /* this is the offset
                                                we start handing
                                                out headers from*/
@@ -578,23 +602,30 @@
 {
   GeglTileBackendFile *self = (GeglTileBackendFile *) object;
 
-  GEGL_NOTE (TILE_BACKEND, "finalizing buffer %s", self->path);
-
   if (self->index)
     g_hash_table_unref (self->index);
-  if (self->i)
-    g_object_unref (self->i);
-  if (self->o)
-    g_object_unref (self->o);
+
+  if (self->exist)
+    {
+      GEGL_NOTE (TILE_BACKEND, "finalizing buffer %s", self->path);
+
+      if (self->i)
+        g_object_unref (self->i);
+      if (self->o)
+        g_object_unref (self->o);
+
+      if (self->file)
+        {
+          g_file_delete  (self->file, NULL, NULL);
+          g_object_unref (self->file);
+        }
+    }
 
   if (self->path)
     g_free (self->path);
 
-  if (self->file)
-    {
-      g_file_delete  (self->file, NULL, NULL);
-      g_object_unref (self->file);
-    }
+  if (self->monitor)
+    g_object_unref (self->monitor);
 
   (*G_OBJECT_CLASS (parent_class)->finalize)(object);
 }
@@ -642,68 +673,212 @@
   return FALSE;
 }
 
+
+static void
+load_index (GeglTileBackendFile *self,
+            gboolean             block)
+{
+  GeglBufferHeader new_header;
+  GList           *iter;
+  GeglTileBackend *backend;
+  goffset offset = 0;
+  goffset max=0;
+
+/* compute total from and next pre alloc by monitoring tiles as they
+ * are added here
+ */
+  /* reload header */
+  new_header = gegl_buffer_read_header (self->i, &offset)->header;
+
+  while (new_header.flags & GEGL_FLAG_LOCKED)
+    {
+      g_usleep (50000);
+      new_header = gegl_buffer_read_header (self->i, &offset)->header;
+    }
+
+  if (new_header.rev == self->header.rev)
+    {
+      GEGL_NOTE(TILE_BACKEND, "header not changed: %s", self->path);
+      return;
+    }
+  else
+    {
+      self->header=new_header;
+      GEGL_NOTE(TILE_BACKEND, "loading index: %s", self->path);
+    }
+
+
+  offset      = self->header.next;
+  self->tiles = gegl_buffer_read_index (self->i, &offset);
+  backend     = GEGL_TILE_BACKEND (self);
+
+  for (iter = self->tiles; iter; iter=iter->next)
+    {
+      GeglBufferItem *item = iter->data;
+
+      GeglBufferItem *existing = g_hash_table_lookup (self->index, item);
+
+      if (item->tile.offset > max)
+        max = item->tile.offset + backend->tile_size;
+
+      if (existing)
+        {
+          if (existing->tile.rev == item->tile.rev)
+            {
+              g_assert (existing->tile.offset == item->tile.offset);
+              existing->tile = item->tile;
+              g_free (item);
+              continue;
+            }
+          else
+            {
+              GeglRectangle rect;
+              g_hash_table_remove (self->index, existing);
+              gegl_tile_source_refetch (GEGL_TILE_SOURCE (backend->storage),
+                                            existing->tile.x,
+                                            existing->tile.y,
+                                            existing->tile.z);
+
+              if (existing->tile.z == 0)
+                {
+                  rect.width = self->header.tile_width;
+                  rect.height = self->header.tile_height;
+                  rect.x = existing->tile.x * self->header.tile_width;
+                  rect.y = existing->tile.y * self->header.tile_height;
+                }
+              g_free (existing);
+              g_signal_emit_by_name (backend->storage, "changed", &rect, NULL);
+            }
+        }
+        g_hash_table_insert (self->index, iter->data, iter->data);
+    }
+  g_list_free (self->tiles);
+  g_slist_free (self->free_list);
+  self->free_list      = NULL;
+  self->next_pre_alloc = max; /* if bigger than own? */
+  self->total          = max;
+  self->tiles          = NULL;
+}
+
+static void
+file_changed (GFileMonitor        *monitor,
+              GFile               *file,
+              GFile               *other_file,
+              GFileMonitorEvent    event_type,
+              GeglTileBackendFile *self)
+{
+  if (event_type == G_FILE_MONITOR_EVENT_CHANGED)
+  /*if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)*/
+    {
+      load_index (self, TRUE);
+    }
+}
 static GObject *
 gegl_tile_backend_file_constructor (GType                  type,
                                     guint                  n_params,
                                     GObjectConstructParam *params)
 {
-  GObject      *object;
+  GObject             *object;
   GeglTileBackendFile *self;
-  GeglTileBackend *backend;
+  GeglTileBackend     *backend;
 
-  object = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
-  self   = GEGL_TILE_BACKEND_FILE (object);
+  object  = G_OBJECT_CLASS (parent_class)->constructor (type, n_params, params);
+  self    = GEGL_TILE_BACKEND_FILE (object);
   backend = GEGL_TILE_BACKEND (object);
 
   GEGL_NOTE (TILE_BACKEND, "constructing file backend: %s", self->path);
   self->file = g_file_new_for_commandline_arg (self->path);
-  
+
   self->index = g_hash_table_new (hashfunc, equalfunc);
 
-  /* if the file already exist we try to open it for appending instead of replacing */
+  /* If the file already exists open it, assuming it is a GeglBuffer. */
   if (g_file_query_exists (self->file, NULL))
     {
-      goffset offset;
+      goffset offset = 0;
 
-      self->i = G_INPUT_STREAM (g_file_read (self->file, NULL, NULL));
-      self->o = G_OUTPUT_STREAM (g_file_append_to (self->file, G_FILE_CREATE_NONE, NULL, NULL));
+      /* Install a monitor for changes to the file in case other applications
+       * might be writing to the buffer
+       */
+      self->monitor = g_file_monitor_file (self->file, G_FILE_MONITOR_NONE,
+                                           NULL, NULL);
+      g_signal_connect (self->monitor, "changed",
+                        G_CALLBACK (file_changed),
+                        self);
+
+#ifndef HACKED_GIO_WITH_READWRITE
+      g_error ("not able to open a file readwrite properly with GIO");
+#else
+      /* this construct uses a hacked up version of GIO that detects the
+       * createflag to be passed as G_FILE_CREATE_READWRITE for the append
+       * call on local files, and provides a suitable inputstream as istream
+       * data on the object.
+       */
+      self->o = G_OUTPUT_STREAM (g_file_append_to (self->file,
+                                                   G_FILE_CREATE_READWRITE,
+                                                   NULL, NULL));
+      self->i = g_object_get_data (G_OBJECT (self->o), "istream");
+#endif
+      /*self->i = G_INPUT_STREAM (g_file_read (self->file, NULL, NULL));*/
       self->header = gegl_buffer_read_header (self->i, &offset)->header;
+      self->header.rev = self->header.rev -1;
+
+      /* we are overriding all of the work of the actual constructor here */
       backend->tile_width = self->header.tile_width;
       backend->tile_height = self->header.tile_height;
       backend->format = babl_format (self->header.description);
-      /* we are overriding all of the work of the actual constructor here */
       backend->px_size = backend->format->format.bytes_per_pixel;
       backend->tile_size = backend->tile_width * backend->tile_height * backend->px_size;
 
-      offset = self->header.next;
-      self->tiles = gegl_buffer_read_index (self->i, &offset);
-
       /* insert each of the entries into the hash table */
-      {
-        /* compute total from and next pre alloc by monitoring tiles as they
-         * are added here
-         */
-        goffset max=0;
-        GList *iter;
-        for (iter = self->tiles; iter; iter=iter->next)
-          {
-            GeglBufferItem *item = iter->data;
-            if (item->tile.offset > max)
-              max = item->tile.offset + backend->tile_size;
-            g_hash_table_insert (self->index, iter->data, iter->data);
-          }
-        g_list_free (self->tiles);
-        self->next_pre_alloc = max;
-        self->total          = max;
-        self->tiles = NULL;
+      load_index (self, TRUE);
+      self->exist = TRUE;
+      g_assert (self->i);
+      g_assert (self->o);
 
-      }
+      /* to autoflush gegl_buffer_set */
+      backend->shared = TRUE;
     }
   else
     {
+      self->exist = FALSE; /* this is also the default, the file will be created on demand */
+    }
+
+  g_assert (self->file);
+
+  backend->header = &self->header;
+
+  return object;
+}
+
+static void
+ensure_exist (GeglTileBackendFile *self)
+{
+  if (!self->exist)
+    {
+      GeglTileBackend *backend;
+
+      self->exist = TRUE;
+      backend = GEGL_TILE_BACKEND (self);
+
+      GEGL_NOTE (TILE_BACKEND, "creating swapfile  %s", self->path);
+#ifdef HACKED_GIO_WITH_READWRITE
+
+      self->o = G_OUTPUT_STREAM (g_file_append_to (self->file,
+                                                   G_FILE_CREATE_READWRITE,
+                                                   NULL, NULL));
+      gegl_buffer_header_init (&self->header,
+                               backend->tile_width,
+                               backend->tile_height,
+                               backend->px_size,
+                               backend->format
+                             );
+      write_header (self);
+      g_output_stream_flush (self->o, NULL, NULL);
+      self->i = g_object_get_data (G_OBJECT (self->o), "istream");
+#else
       self->o = G_OUTPUT_STREAM (g_file_replace (self->file, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL));
       g_output_stream_flush (self->o, NULL, NULL);
-      self->i = G_INPUT_STREAM (g_file_read (self->file, NULL, NULL));
+
       self->next_pre_alloc = 256;  /* reserved space for header */
       self->total          = 256;  /* reserved space for header */
       g_assert(g_seekable_seek (G_SEEKABLE (self->o), 256, G_SEEK_SET, NULL, NULL));
@@ -714,17 +889,16 @@
                                backend->px_size,
                                backend->format
                                );
-      /* FIXME: should probably write an initial header */
+      write_header (self);
+      g_output_stream_flush (self->o, NULL, NULL);
+      self->i = G_INPUT_STREAM (g_file_read (self->file, NULL, NULL));
+#endif
+      /*self->i = G_INPUT_STREAM (g_file_read (self->file, NULL, NULL));*/
+      self->next_pre_alloc = 256;  /* reserved space for header */
+      self->total          = 256;  /* reserved space for header */
+      g_assert (self->i);
+      g_assert (self->o);
     }
-
-  g_assert (self->file);
-  g_assert (self->i);
-  g_assert (self->o);
-
-
-  backend->header = &self->header;
-
-  return object;
 }
 
 static void
@@ -742,6 +916,7 @@
 
   gegl_tile_source_class->command  = command;
 
+  GEGL_BUFFER_STRUCT_CHECK_PADDING;
 
   g_object_class_install_property (gobject_class, PROP_PATH,
                                    g_param_spec_string ("path",
@@ -764,3 +939,31 @@
   self->next_pre_alloc = 256;  /* reserved space for header */
   self->total          = 256;  /* reserved space for header */
 }
+
+gboolean
+gegl_tile_backend_file_try_lock (GeglTileBackendFile *self)
+{
+  GeglBufferHeader new_header;
+  new_header = gegl_buffer_read_header (self->i, NULL)->header;
+  if (new_header.flags & GEGL_FLAG_LOCKED)
+    {
+      return FALSE;
+    }
+  self->header.flags += GEGL_FLAG_LOCKED;
+  write_header (self);
+  g_output_stream_flush (self->o, NULL, NULL);
+  return TRUE;
+}
+
+gboolean gegl_tile_backend_file_unlock (GeglTileBackendFile *self)
+{
+  if (!(self->header.flags & GEGL_FLAG_LOCKED))
+    {
+      g_warning ("tried to unlock unlocked buffer");
+      return FALSE;
+    }
+  self->header.flags -= GEGL_FLAG_LOCKED;
+  write_header (self);
+  g_output_stream_flush (self->o, NULL, NULL);
+  return TRUE;
+}

Modified: branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-file.h
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-file.h	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-file.h	Sat May 17 17:51:59 2008
@@ -44,6 +44,9 @@
 
 void  gegl_tile_backend_file_stats    (void);
 
+gboolean gegl_tile_backend_file_try_lock (GeglTileBackendFile *file);
+gboolean gegl_tile_backend_file_unlock   (GeglTileBackendFile *file);
+
 G_END_DECLS
 
 #endif

Modified: branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-ram.c
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-ram.c	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-ram.c	Sat May 17 17:51:59 2008
@@ -179,9 +179,6 @@
       entry->z = z;
       g_hash_table_insert (tile_backend_ram->entries, entry, entry);
     }
-  g_assert (tile->flags == 0); /* when this one is triggered, dirty pyramid data
-                                  has been tried written to persistent tile_storage.
-                                */
   ram_entry_write (tile_backend_ram, entry, tile->data);
   tile->stored_rev = tile->rev;
   return TRUE;

Modified: branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-tiledir.c
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-tiledir.c	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-tile-backend-tiledir.c	Sat May 17 17:51:59 2008
@@ -170,9 +170,6 @@
 
   GioEntry       entry = {x,y,z};
 
-  g_assert (tile->flags == 0); /* when this one is triggered, dirty pyramid data
-                                  has been tried written to persistent tile_storage.
-                                */
   gio_entry_write (tile_backend_tiledir, &entry, tile->data);
   tile->stored_rev = tile->rev;
   return NULL;

Modified: branches/branch_zhangjb/gegl/buffer/gegl-tile-backend.c
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-tile-backend.c	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-tile-backend.c	Sat May 17 17:51:59 2008
@@ -159,4 +159,5 @@
 static void
 gegl_tile_backend_init (GeglTileBackend *self)
 {
+  self->shared = FALSE;
 }

Modified: branches/branch_zhangjb/gegl/buffer/gegl-tile-backend.h
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-tile-backend.h	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-tile-backend.h	Sat May 17 17:51:59 2008
@@ -42,6 +42,8 @@
 
   /* private */
   gpointer        header;
+  gpointer        storage;
+  gboolean        shared;
 };
 
 struct _GeglTileBackendClass

Modified: branches/branch_zhangjb/gegl/buffer/gegl-tile-handler-cache.c
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-tile-handler-cache.c	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-tile-handler-cache.c	Sat May 17 17:51:59 2008
@@ -35,18 +35,11 @@
 static gint    cache_misses = 0;
 
 static gint    cache_total = 0;  /* approximate amount of bytes stored */
-static gint    clones_ones = 0;  /* approximate amount of bytes stored */
 
 struct _GeglTileHandlerCache
 {
   GeglTileHandler parent_instance;
   GSList *free_list;
-
-/*  GQueue     *queue;
-  gint        size;
-  gint        wash_percentage;
-  gint        hits;
-  gint        misses;*/
 };
 
 void gegl_tile_cache_init (void)
@@ -82,6 +75,10 @@
                                                      gint              x,
                                                      gint              y,
                                                      gint              z);
+static void        gegl_tile_handler_cache_invalidate (GeglTileHandlerCache *cache,
+                                                     gint              x,
+                                                     gint              y,
+                                                     gint              z);
 
 G_DEFINE_TYPE (GeglTileHandlerCache, gegl_tile_handler_cache, GEGL_TYPE_TILE_HANDLER)
 
@@ -121,13 +118,12 @@
 dispose (GObject *object)
 {
   GeglTileHandlerCache *cache;
-  CacheItem        *item;
-  GSList *iter;
-  cache = (GeglTileHandlerCache *) object;
+  CacheItem            *item;
+  GSList               *iter;
 
+  cache = GEGL_TILE_HANDLER_CACHE (object);
 
-  /* only throw out items belonging to this cache instance
-     (XXX: should probably have a local list for that)*/
+  /* only throw out items belonging to this cache instance */
 
   cache->free_list = NULL;
   g_queue_foreach (cache_queue, queue_each, cache);
@@ -137,7 +133,6 @@
         if (item->tile)
           {
             cache_total -= item->tile->size;
-            clones_ones = 0; /* XXX */
             g_object_unref (item->tile);
           }
         g_queue_remove (cache_queue, item);
@@ -157,8 +152,7 @@
 {
   GeglTileHandlerCache *cache    = GEGL_TILE_HANDLER_CACHE (tile_store);
   GeglTileSource       *source = GEGL_HANDLER (tile_store)->source;
-  GeglTile         *tile     = NULL;
-
+  GeglTile             *tile     = NULL;
 
   tile = gegl_tile_handler_cache_get_tile (cache, x, y, z);
   if (tile)
@@ -191,9 +185,6 @@
   /* FIXME: replace with switch */
   switch (command)
     {
-      case GEGL_TILE_SET:
-        /* nothing to do */
-        break; /* chain up */
       case GEGL_TILE_FLUSH:
         {
           GList     *link;
@@ -210,7 +201,7 @@
                 }
             }
         }
-        break; /* chain up */
+        break;
       case GEGL_TILE_GET:
         /* XXX: we should perhaps store a NIL result, and place the empty
          * generator after the cache, this would have to be possible to disable
@@ -225,7 +216,7 @@
           if (exist)
             return (gpointer)TRUE;
         }
-        break; /* chain up */
+        break;
       case GEGL_TILE_IDLE:
         {
           gboolean action = gegl_tile_handler_cache_wash (cache);
@@ -233,14 +224,16 @@
             return (gpointer)action;
           break;
         }
+      case GEGL_TILE_REFETCH:
+        gegl_tile_handler_cache_invalidate (cache, x, y, z);
+        break;
       case GEGL_TILE_VOID:
         gegl_tile_handler_cache_void (cache, x, y, z);
-        if (z!=0)
-          return (void*)0xdead700;
-        /* fallthrough */
+        break;
       default:
         break;
     }
+
   return gegl_tile_handler_chain_up (handler, command, x, y, z, data);
 }
 
@@ -363,6 +356,36 @@
   return FALSE;
 }
 
+static void
+gegl_tile_handler_cache_invalidate (GeglTileHandlerCache *cache,
+                                    gint                  x,
+                                    gint                  y,
+                                    gint                  z)
+{
+  GList *link;
+
+  for (link = g_queue_peek_head_link (cache_queue); link; link = link->next)
+    {
+      CacheItem *item = link->data;
+      GeglTile  *tile = item->tile;
+
+      if (tile != NULL &&
+          item->x == x &&
+          item->y == y &&
+          item->z == z &&
+          item->handler == cache)
+        {
+          cache_total  -= item->tile->size;
+          tile->tile_storage = NULL;
+          tile->stored_rev = tile->rev; /* to cheat it out of being stored */
+          g_object_unref (tile);
+          g_slice_free (CacheItem, item);
+          g_queue_delete_link (cache_queue, link);
+          return;
+        }
+    }
+}
+
 
 static void
 gegl_tile_handler_cache_void (GeglTileHandlerCache *cache,
@@ -414,10 +437,10 @@
 
   count = g_queue_get_length (cache_queue);
 
-  if (cache_total > gegl_config()->cache_size)
+  while (cache_total > gegl_config()->cache_size)
     {
-      GEGL_NOTE(CACHE, "cache_total:%i > cache_size:%i\n", cache_total, gegl_config()->cache_size);
-      GEGL_NOTE(CACHE, "%f%% hit:%i miss:%i  %i]", cache_hits*100.0/(cache_hits+cache_misses), cache_hits, cache_misses, g_queue_get_length (cache_queue));
+      /*GEGL_NOTE(CACHE, "cache_total:%i > cache_size:%i", cache_total, gegl_config()->cache_size);
+      GEGL_NOTE(CACHE, "%f%% hit:%i miss:%i  %i]", cache_hits*100.0/(cache_hits+cache_misses), cache_hits, cache_misses, g_queue_get_length (cache_queue));*/
       gegl_tile_handler_cache_trim (cache);
     }
 }

Modified: branches/branch_zhangjb/gegl/buffer/gegl-tile-handler-log.c
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-tile-handler-log.c	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-tile-handler-log.c	Sat May 17 17:51:59 2008
@@ -33,12 +33,8 @@
   "is_cached",
   "exist",
   "-", /*void*/
-  "void tl", 
-  "void tr", 
-  "void bl",
-  "void br",
   "flush",
-  "invalidated",
+  "refetch",
   "last command",
   "eeek",
   NULL

Modified: branches/branch_zhangjb/gegl/buffer/gegl-tile-handler-zoom.c
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-tile-handler-zoom.c	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-tile-handler-zoom.c	Sat May 17 17:51:59 2008
@@ -215,15 +215,8 @@
       tile = gegl_tile_source_get_tile (source, x, y, z);
     }
 
-  if (tile != NULL)
-    {
-      /* Check that the tile is fully valid */
-      if (!(tile->flags & (GEGL_TILE_DIRT_TL |
-                           GEGL_TILE_DIRT_TR |
-                           GEGL_TILE_DIRT_BL |
-                           GEGL_TILE_DIRT_BR)))
-        return tile;
-    }
+  if (tile)
+    return tile;
 
   if (z == 0)/* at base level with no tile found->send null, and shared empty
                tile will be used instead */
@@ -240,38 +233,13 @@
   {
     gint      i, j;
     guchar   *data;
-    gboolean  had_tile          = tile != NULL;
     GeglTile *source_tile[2][2] = { { NULL, NULL }, { NULL, NULL } };
-    gboolean  fetch[2][2]       = { { FALSE, FALSE },
-                                    { FALSE, FALSE } };
-
-    if (had_tile)
-      {
-        if (tile->flags & GEGL_TILE_DIRT_TL)
-          fetch[0][0] = TRUE;
-        if (tile->flags & GEGL_TILE_DIRT_TR)
-          fetch[1][0] = TRUE;
-        if (tile->flags & GEGL_TILE_DIRT_BL)
-          fetch[0][1] = TRUE;
-        if (tile->flags & GEGL_TILE_DIRT_BR)
-          fetch[1][1] = TRUE;
-
-        tile->flags = 0;
-      }
-    else
-      {
-        fetch[0][0] = TRUE;
-        fetch[1][0] = TRUE;
-        fetch[0][1] = TRUE;
-        fetch[1][1] = TRUE;
-      }
 
     for (i = 0; i < 2; i++)
       for (j = 0; j < 2; j++)
         {
           /* we get the tile from ourselves, to make successive rescales work
            * correctly */
-          if (fetch[i][j])
             source_tile[i][j] = gegl_tile_source_get_tile (gegl_tile_source,
                                                           x * 2 + i, y * 2 + j, z - 1);
         }
@@ -281,33 +249,25 @@
         source_tile[1][0] == NULL &&
         source_tile[1][1] == NULL)
       {
-        if (had_tile)
-          {
-            g_object_unref (tile);
-          }
         return NULL;   /* no data from level below, return NULL and let GeglTileHandlerEmpty
                           fill in the shared empty tile */
       }
 
-    if (!had_tile)
+    g_assert (tile == NULL);
+    if (tile == NULL)
       {
         tile = gegl_tile_new (tile_size);
 
-        /* it is a bit hacky, but adding enough information (probably too much)
-         * enabling the tile_storage system to attempt swapping out of zoom tiles
-         */
-        tile->storage_x  = x;
-        tile->storage_y  = y;
-        tile->storage_z  = z;
         tile->x          = x;
         tile->y          = y;
         tile->z          = z;
-        tile->tile_storage    = zoom->tile_storage;
+        tile->tile_storage = zoom->tile_storage;
         tile->stored_rev = 1;
         tile->rev        = 1;
 
         {
-          GeglTileHandlerCache *cache = g_object_get_data (G_OBJECT (gegl_tile_source), "cache");
+          GeglTileHandlerCache *cache;
+          cache = g_object_get_data (G_OBJECT (gegl_tile_source), "cache");
           if (cache)
             {
               gegl_tile_handler_cache_insert (cache, tile, x, y, z);
@@ -325,20 +285,14 @@
               set_half (tile, source_tile[i][j], tile_width, tile_height, format, i, j);
               g_object_unref (source_tile[i][j]);
             }
-          else if (fetch[i][j])
+          else 
             {
               set_blank (tile, tile_width, tile_height, format, i, j);
             }
-          else
-            {
-              /* keep old data around */
-            }
         }
     gegl_tile_unlock (tile);
   }
 
-  tile->flags = 0;
-
   return tile;
 }
 
@@ -353,43 +307,14 @@
   GeglTileHandler *handler  = GEGL_HANDLER (tile_store);
   /*GeglTileSource *source = handler->source;*/
 
-  if (command == GEGL_TILE_GET)
-    return get_tile (tile_store, x, y, z);
-  if (command == GEGL_TILE_VOID_TL ||
-      command == GEGL_TILE_VOID_TR ||
-      command == GEGL_TILE_VOID_BL ||
-      command == GEGL_TILE_VOID_BR)
+  switch (command)
     {
-      GeglTile *tile = gegl_tile_source_get_tile (tile_store, x, y, z);
-
-      if (!tile)
-        return FALSE;
-      switch (command)
-        {
-          case GEGL_TILE_VOID_TL:
-            tile->flags |= GEGL_TILE_DIRT_TL;
-            break;
-
-          case GEGL_TILE_VOID_TR:
-            tile->flags |= GEGL_TILE_DIRT_TR;
-            break;
-
-          case GEGL_TILE_VOID_BL:
-            tile->flags |= GEGL_TILE_DIRT_BL;
-            break;
-
-          case GEGL_TILE_VOID_BR:
-            tile->flags |= GEGL_TILE_DIRT_BR;
-            break;
-
-          default:
-            break;
-        }
-      g_object_unref (tile);
-      return FALSE;
+      case GEGL_TILE_GET:
+        return get_tile (tile_store, x, y, z);
+      default:
+        /* pass the command on */
+        return gegl_tile_handler_chain_up (handler, command, x, y, z, data);
     }
-  /* pass the command on */
-  return gegl_tile_handler_chain_up (handler, command, x, y, z, data);
 }
 
 

Modified: branches/branch_zhangjb/gegl/buffer/gegl-tile-source.h
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-tile-source.h	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-tile-source.h	Sat May 17 17:51:59 2008
@@ -26,7 +26,7 @@
 
 G_BEGIN_DECLS
 
-#define GEGL_TYPE_TILE_SOURCE       (gegl_tile_source_get_type ())
+#define GEGL_TYPE_TILE_SOURCE            (gegl_tile_source_get_type ())
 #define GEGL_TILE_SOURCE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEGL_TYPE_TILE_SOURCE, GeglTileSource))
 #define GEGL_TILE_SOURCE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  GEGL_TYPE_TILE_SOURCE, GeglTileSourceClass))
 #define GEGL_IS_TILE_SOURCE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEGL_TYPE_TILE_SOURCE))
@@ -35,23 +35,6 @@
 
 typedef gint GeglTileCommand;
 
-enum _GeglTileCommand
-{
-  GEGL_TILE_IDLE = 0,
-  GEGL_TILE_SET,
-  GEGL_TILE_GET,
-  GEGL_TILE_IS_CACHED,
-  GEGL_TILE_EXIST,
-  GEGL_TILE_VOID,
-  GEGL_TILE_VOID_TL,
-  GEGL_TILE_VOID_TR,
-  GEGL_TILE_VOID_BL,
-  GEGL_TILE_VOID_BR,
-  GEGL_TILE_FLUSH,
-  GEGL_TILE_INVALIDATED,
-  GEGL_TILE_LAST_COMMAND
-};
-
 struct _GeglTileSource
 {
   GObject  parent_instance;
@@ -71,49 +54,154 @@
 
 GType      gegl_tile_source_get_type (void) G_GNUC_CONST;
 
+gpointer   gegl_tile_source_command  (GeglTileSource  *tile_source,
+                                      GeglTileCommand  command,
+                                      gint             x,
+                                      gint             y,
+                                      gint             z,
+                                      gpointer         data);
 
 
-gpointer   gegl_tile_source_command  (GeglTileSource    *gegl_tile_source,
-                                   GeglTileCommand  command,
-                                   gint             x,
-                                   gint             y,
-                                   gint             z,
-                                   gpointer         data);
 
-#define gegl_tile_source_idle(source) \
-   gegl_tile_source_command(source,GEGL_TILE_IDLE,0,0,0,NULL)
+/* All commands have the ability to pass commands to all tiles the handlers
+ * add abstraction to the commands the documentaiton given here is valid
+ * when the commands are issued to a full blown GeglBuffer instance.
+ */
+
+enum _GeglTileCommand
+{
+  GEGL_TILE_IDLE = 0,
+  GEGL_TILE_SET, 
+  GEGL_TILE_GET,
+  GEGL_TILE_IS_CACHED,
+  GEGL_TILE_EXIST,
+  GEGL_TILE_VOID,
+  GEGL_TILE_FLUSH,
+  GEGL_TILE_REFETCH,
+  GEGL_TILE_LAST_COMMAND
+};
+
+#ifdef NOT_REALLY_COS_THIS_IS_MACROS
+
+/**
+ * gegl_tile_source_get_tile:
+ * @source: a GeglTileSource *
+ * @x: x coordinate
+ * @y: y coordinate
+ * @z: tile zoom level
+ *
+ * Get a GeglTile *from the buffer, mipmap tiles for levels z!=0 will be
+ * created on the fly as needed, empty tiles returned are copy on write
+ * and must be locked before written to, and unlocked afterwards.
+ *
+ * Returns: the tile at x,y,z or NULL if the tile could not be provided.
+ */
+GeglTile *gegl_tile_source_get_tile  (GegTileSource *source,
+                                      gint           x,
+                                      gint           y,
+                                      gint           z);
+
+/**
+ * gegl_tile_source_set_tile:
+ * @source: a GeglTileSource *
+ * @x: x coordinate
+ * @y: y coordinate
+ * @z: tile zoom level
+ * @tile: a #GeglTile
+ *
+ * Get a GeglTile *from the buffer.
+ *
+ * Returns: the TRUE if the set was successful.
+ */
+gboolean  gegl_tile_source_set_tile  (GegTileSource *source,
+                                      gint           x,
+                                      gint           y,
+                                      gint           z,
+                                      GeglTile      *tile);
+/**
+ * gegl_tile_source_is_cached:
+ * @source: a GeglTileSource *
+ * @x: tile x coordinate
+ * @y: tile y coordinate
+ * @z: tile zoom level
+ *
+ * Checks if a tile is in cache and easily retrieved.
+ */
+gboolean  gegl_tile_source_is_cached (GegTileSource *source,
+                                      gint           x,
+                                      gint           y,
+                                      gint           z);
+/**
+ * gegl_tile_source_exist:
+ * @source: a GeglTileSource *
+ * @x: x coordinate
+ * @y: y coordinate
+ * @z: tile zoom level
+ *
+ * Checks if a tile exists, this check would not cause the tile to be swapped
+ * in.
+ */
+gboolean  gegl_tile_source_exist     (GegTileSource *source,
+                                      gint           x,
+                                      gint           y,
+                                      gint           z);
+/**
+ * gegl_tile_source_void:
+ * @source: a GeglTileSource *
+ * @x: x coordinate
+ * @y: y coordinate
+ * @z: tile zoom level
+ *
+ * Causes all references to a tile to be removed.
+ */
+void      gegl_tile_source_void      (GegTileSource *source,
+                                      gint           x,
+                                      gint           y,
+                                      gint           z);
+/*    INTERNAL API
+ * gegl_tile_source_refetch:
+ * @source: a GeglTileSource *
+ * @x: x coordinate
+ * @y: y coordinate
+ * @z: tile zoom level
+ *
+ * A message used internally when watching external buffers to indicate that
+ * a refresh of all data relating to the coordinates needs to be refetched.
+ * Subsequent get calls should get new and valid data for the tile coordinates.
+ */
+void      gegl_tile_source_refetch   (GegTileSource *source,
+                                      gint           x,
+                                      gint           y,
+                                      gint           z);
+/*   INTERNAL API
+ * gegl_tile_source_idle:
+ * @source: a GeglTileSource *
+ *
+ * Allow different parts of the buffer to do idle work (saving cached
+ * data lazily, perhaps prefetching in the future?), monitoring for
+ * changes or other tasks. Used internally by the buffer object.
+ *
+ * Returns: the TRUE if some work was done.
+ */
+gboolean  gegl_tile_source_idle      (GegTileSource *source);
+
+#endif
 
 #define gegl_tile_source_set_tile(source,x,y,z,tile) \
    (gboolean)gegl_tile_source_command(source,GEGL_TILE_SET,x,y,z,tile)
-
 #define gegl_tile_source_get_tile(source,x,y,z) \
    (GeglTile*)gegl_tile_source_command(source,GEGL_TILE_GET,x,y,z,NULL)
-
 #define gegl_tile_source_is_cached(source,x,y,z) \
    (gboolean)gegl_tile_source_command(source,GEGL_TILE_IS_CACHED,x,y,z,NULL)
-
 #define gegl_tile_source_exist(source,x,y,z) \
    (gboolean)gegl_tile_source_command(source,GEGL_TILE_EXIST,x,y,z,NULL)
-
 #define gegl_tile_source_void(source,x,y,z) \
    gegl_tile_source_command(source,GEGL_TILE_VOID,x,y,z,NULL)
+#define gegl_tile_source_refetch(source,x,y,z) \
+   gegl_tile_source_command(source,GEGL_TILE_REFETCH,x,y,z,NULL)
+#define gegl_tile_source_idle(source) \
+   (gboolean)gegl_tile_source_command(source,GEGL_TILE_IDLE,0,0,0,NULL)
 
-#define gegl_tile_source_void_tl(source,x,y,z) \
-   gegl_tile_source_command(source,GEGL_TILE_VOID_TL,x,y,z,NULL)
-
-#define gegl_tile_source_void_tr(source,x,y,z) \
-   gegl_tile_source_command(source,GEGL_TILE_VOID_TR,x,y,z,NULL)
-
-#define gegl_tile_source_void_bl(source,x,y,z) \
-   gegl_tile_source_command(source,GEGL_TILE_VOID_BL,x,y,z,NULL)
-
-#define gegl_tile_source_void_br(source,x,y,z) \
-   gegl_tile_source_command(source,GEGL_TILE_VOID_BR,x,y,z,NULL)
-
-#define gegl_tile_source_undo_start_group(source,x,y,z) \
-   gegl_tile_source_command(source,GEGL_TILE_UNDO_START_GROUP,x,y,z,NULL)
-
- 
 G_END_DECLS
 
 #endif

Modified: branches/branch_zhangjb/gegl/buffer/gegl-tile-storage.c
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-tile-storage.c	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-tile-storage.c	Sat May 17 17:51:59 2008
@@ -29,6 +29,8 @@
 #include "gegl-tile-handler-zoom.h"
 #include "gegl-tile-handler-cache.h"
 #include "gegl-tile-handler-log.h"
+#include "gegl-types.h"
+#include "gegl-utils.h"
 
 
 G_DEFINE_TYPE (GeglTileStorage, gegl_tile_storage, GEGL_TYPE_TILE_HANDLER_CHAIN)
@@ -51,6 +53,14 @@
   PROP_PATH
 };
 
+enum
+{
+  CHANGED,
+  LAST_SIGNAL
+};
+
+guint gegl_tile_storage_signals[LAST_SIGNAL] = { 0 };
+
 static void
 get_property (GObject    *gobject,
               guint       property_id,
@@ -160,11 +170,10 @@
       return FALSE;
     }
 
-  gegl_tile_source_idle (GEGL_TILE_SOURCE (tile_storage));                        
-
-  return TRUE;
+  return gegl_tile_source_idle (GEGL_TILE_SOURCE (tile_storage));                        
 }
 
+GeglTileBackend *gegl_buffer_backend (GObject *buffer);
 
 static GObject *
 gegl_tile_storage_constructor (GType                  type,
@@ -231,18 +240,20 @@
                       g_object_new (GEGL_TYPE_TILE_HANDLER_LOG, NULL));
 
 
-  cache = gegl_tile_handler_chain_add (tile_handler_chain,
-                          g_object_new (GEGL_TYPE_TILE_HANDLER_CACHE, NULL));
+  cache = g_object_new (GEGL_TYPE_TILE_HANDLER_CACHE,
+                        NULL);
+  empty = g_object_new (GEGL_TYPE_TILE_HANDLER_EMPTY,
+                        "backend", handler->source,
+                        NULL);
+  zoom = g_object_new (GEGL_TYPE_TILE_HANDLER_ZOOM,
+                       "backend", handler->source,
+                       "tile_storage", tile_storage,
+                       NULL);
+
+  gegl_tile_handler_chain_add (tile_handler_chain, cache);
+  gegl_tile_handler_chain_add (tile_handler_chain, zoom);
+  gegl_tile_handler_chain_add (tile_handler_chain, empty);
 
-  zoom = gegl_tile_handler_chain_add (tile_handler_chain,
-                                      g_object_new (GEGL_TYPE_TILE_HANDLER_ZOOM,
-                                                    "backend", handler->source,
-                                                    "tile_storage", tile_storage,
-                                                    NULL));
-  empty = gegl_tile_handler_chain_add (tile_handler_chain,
-                                     g_object_new (GEGL_TYPE_TILE_HANDLER_EMPTY,
-                                                   "backend", handler->source,
-                                                   NULL));
 
   if (g_getenv("GEGL_LOG_TILE_CACHE"))
     gegl_tile_handler_chain_add (tile_handler_chain,
@@ -250,6 +261,11 @@
   g_object_set_data (G_OBJECT (empty), "cache", cache);
   g_object_set_data (G_OBJECT (zoom), "cache", cache);
 
+  {
+    GeglTileBackend *backend;
+    backend = gegl_buffer_backend (object);
+    backend->storage = (gpointer)object;
+  }
 
   tile_storage->idle_swapper = g_timeout_add_full (G_PRIORITY_LOW,
                                               250,
@@ -323,6 +339,17 @@
                                    g_param_spec_pointer ("format", "format", "babl format",
                                                          G_PARAM_READWRITE |
                                                          G_PARAM_CONSTRUCT));
+
+  gegl_tile_storage_signals[CHANGED] =
+        g_signal_new ("changed",
+                  G_TYPE_FROM_CLASS (gobject_class),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
+                  0,
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__BOXED,
+                  G_TYPE_NONE, 1,
+                  GEGL_TYPE_RECTANGLE);
+
 }
 
 static void

Modified: branches/branch_zhangjb/gegl/buffer/gegl-tile.c
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-tile.c	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-tile.c	Sat May 17 17:51:59 2008
@@ -106,6 +106,8 @@
     }
 }
 
+#include "gegl-utils.h"
+
 static void
 dispose (GObject *object)
 {
@@ -118,7 +120,7 @@
     {
       if (tile->next_shared == tile)
         { /* no clones */
-          g_free (tile->data);
+          gegl_free (tile->data);
           tile->data = NULL;
         }
       else
@@ -178,7 +180,6 @@
   tile->rev        = 0;
   tile->lock       = 0;
   tile->data       = NULL;
-  tile->flags      = 0;
 
   tile->next_shared = tile;
   tile->prev_shared = tile;
@@ -212,7 +213,7 @@
 {
   GeglTile *tile = g_object_new (GEGL_TYPE_TILE, NULL);
 
-  tile->data       = g_malloc (size);
+  tile->data       = gegl_malloc (size);
   tile->size       = size;
   tile->stored_rev = 1;
 
@@ -220,6 +221,15 @@
   return tile;
 }
 
+static gpointer
+gegl_memdup (gpointer src, gsize size)
+{
+  gpointer ret;
+  ret = gegl_malloc (size);
+  memcpy (ret, src, size);
+  return ret;
+}
+
 static void
 gegl_tile_unclone (GeglTile *tile)
 {
@@ -228,7 +238,7 @@
       /* the tile data is shared with other tiles,
        * create a local copy
        */
-      tile->data                     = g_memdup (tile->data, tile->size);
+      tile->data                     = gegl_memdup (tile->data, tile->size);
       tile->prev_shared->next_shared = tile->next_shared;
       tile->next_shared->prev_shared = tile->prev_shared;
       tile->prev_shared              = tile;
@@ -244,7 +254,8 @@
 {
   if (tile->lock != 0)
     {
-      g_warning ("locking a tile for the second time");
+      g_print ("hm\n");
+      g_warning ("strange tile lock count: %i", tile->lock);
     }
   total_locks++;
 
@@ -260,56 +271,28 @@
 }
 
 static void
+_gegl_tile_void_pyramid (GeglTileSource *source,
+                         gint            x,
+                         gint            y,
+                         gint            z)
+{
+  if (z>10)
+    return;
+  gegl_tile_source_void (source, x, y, z);
+  _gegl_tile_void_pyramid (source, x/2, y/2, z+1);
+}
+
+static void
 gegl_tile_void_pyramid (GeglTile *tile)
 {
-  /* should, to tile->tile_storage, request it's toplevel tile, and mark
-   * it as dirty, to force a recomputation of it's toplevel at the
-   * next subdivision request. NB: a full voiding might not be neccesary,
-   * forcing a rerender of just the dirtied part might be better, more
-   * similar to how it was done in horizon, this will only work with 4->1 px
-   * averageing.
-   */
-  gint x, y, z;
-
-  x = tile->storage_x;
-  y = tile->storage_y;
-  z = 0;/*tile->storage_z;*/
-
-  for (z = 1; z < 10; z++)
+  if (tile->tile_storage && 
+      tile->z == 0) /* we only accepting voiding the base level */
     {
-#if 0
-      gint ver = (y % 2);
-      gint hor = (x % 2);
-#endif
-      x /= 2;
-      y /= 2;
-
-      gegl_tile_source_void (GEGL_TILE_SOURCE (tile->tile_storage), x, y, z);
-#if 0
-      /* FIXME: reenable this code */
-      if (!ver)
-        {
-          if (!hor)
-            {
-              gegl_tile_source_void_tl (GEGL_TILE_SOURCE (tile->tile_storage), x,y,z);
-            }
-          else
-            {
-              gegl_tile_source_void_tr (GEGL_TILE_SOURCE (tile->tile_storage), x,y,z);              
-            }
-        }
-      else
-        {
-          if (!hor)
-            {
-              gegl_tile_source_void_bl (GEGL_TILE_SOURCE (tile->tile_storage), x,y,z);              
-            }
-          else
-            {
-			  gegl_tile_source_void_br (GEGL_TILE_SOURCE (tile->tile_storage), x,y,z);
-            }
-        }
-#endif
+      _gegl_tile_void_pyramid (GEGL_TILE_SOURCE (tile->tile_storage), 
+                               tile->x/2,
+                               tile->y/2,
+                               tile->z+1);
+      return;
     }
 }
 
@@ -326,8 +309,9 @@
       tile->z == 0)
     {
       gegl_tile_void_pyramid (tile);
-      tile->rev++;
     }
+  if (tile->lock==0)
+    tile->rev++;
 #if ENABLE_MP
   g_mutex_unlock (tile->mutex);
 #endif
@@ -345,9 +329,8 @@
 {
   tile->stored_rev = tile->rev;
   tile->tile_storage = NULL;
-  /* FIXME: make sure the tile is evicted from any tile_storage/buffer caches
-   * as well
-   */
+  if (tile->z==0)
+    gegl_tile_void_pyramid (tile);
 }
 
 void
@@ -356,7 +339,7 @@
 {
   gegl_tile_lock (dst);
 
-  g_free (dst->data);
+  gegl_free (dst->data);
   dst->data = NULL;
 
   dst->next_shared              = src->next_shared;
@@ -401,9 +384,10 @@
   if (tile->tile_storage == NULL)
     return FALSE;
   return gegl_tile_source_set_tile (GEGL_TILE_SOURCE (tile->tile_storage),
-                                    tile->storage_x,
-                                    tile->storage_y,
-                                    tile->storage_z, tile);
+                                    tile->x,
+                                    tile->y,
+                                    tile->z,
+                                    tile);
 }
 
 /* compute the tile indice of a coordinate

Modified: branches/branch_zhangjb/gegl/buffer/gegl-tile.h
==============================================================================
--- branches/branch_zhangjb/gegl/buffer/gegl-tile.h	(original)
+++ branches/branch_zhangjb/gegl/buffer/gegl-tile.h	Sat May 17 17:51:59 2008
@@ -35,42 +35,33 @@
  */
 struct _GeglTile
 {
-  GObject        parent_instance;
+  GObject          parent_instance;
 
-  guchar        *data;        /* A small linear buffer for pixel data */
-  gint           size;        /* The size of the data element in bytes */
+  guchar          *data;        /* actual pixel data for tile, a linear buffer*/
+  gint             size;        /* The size of the linear buffer */
 
-  GeglTileStorage   *tile_storage;     /* the buffer from which this tile was retrieved
-                               * needed for the tile to be able to store itself
-                               * back when it is unreffed for the last time
-                               */
-  gint           storage_x, storage_y, storage_z;
-  gint           x, y, z;
-
-
-  guint          rev;         /* this tile revision */
-  guint          stored_rev;  /* what revision was we when we from tile_storage?
-                                 (currently set to 1 when loaded from disk */
-
-  guint          flags;       /* used to store zoom dirt info */
-
-  gchar          lock;        /* number of times the tile is write locked
-                               * should in theory just have the values 0/1
-                               */
+  GeglTileStorage *tile_storage; /* the buffer from which this tile was
+                                  * retrieved needed for the tile to be able to
+                                  * store itself back (for instance when it is
+                                  * unreffed for the last time)
+                                  */
+  gint             x, y, z;
+
+
+  guint            rev;         /* this tile revision */
+  guint            stored_rev;  /* what revision was we when we from tile_storage?
+                                   (currently set to 1 when loaded from disk */
+
+  gchar            lock;        /* number of times the tile is write locked
+                                 * should in theory just have the values 0/1
+                                 */
 #if ENABLE_MP
-  GMutex        *mutex;
+  GMutex          *mutex;
 #endif
 
   /* the shared list is a doubly linked circular list */
-  GeglTile      *next_shared;
-  GeglTile      *prev_shared;
-};
-
-enum {
-  GEGL_TILE_DIRT_TL = 1<<0,
-  GEGL_TILE_DIRT_TR = 1<<1,
-  GEGL_TILE_DIRT_BL = 1<<2,
-  GEGL_TILE_DIRT_BR = 1<<3
+  GeglTile        *next_shared;
+  GeglTile        *prev_shared;
 };
 
 struct _GeglTileClass
@@ -78,25 +69,44 @@
   GObjectClass  parent_class;
 };
 
-GType        gegl_tile_get_type        (void) G_GNUC_CONST;
+GType        gegl_tile_get_type   (void) G_GNUC_CONST;
+
+GeglTile   * gegl_tile_new        (gint     size);
+void       * gegl_tile_get_format (GeglTile *tile);
+
+
+/* lock a tile for writing, this would allow writing to buffers
+ * later gotten with get_data()
+ */
+void         gegl_tile_lock       (GeglTile *tile);
+/* get a pointer to the linear buffer of the tile.
+ */
+guchar     * gegl_tile_get_data   (GeglTile *tile);
+/* unlock the tile notifying the tile that we're done manipulating
+ * the data.
+ */
+void         gegl_tile_unlock     (GeglTile *tile);
+
+
+
+gboolean     gegl_tile_is_stored  (GeglTile *tile);
+gboolean     gegl_tile_store      (GeglTile *tile);
+void         gegl_tile_void       (GeglTile *tile);
+GeglTile    *gegl_tile_dup        (GeglTile *tile);
+
+
+/* helper functions to compute tile indices and offsets for coordinates
+ * based on a tile stride (tile_width or tile_height)
+ */
+gint         gegl_tile_indice     (gint      coordinate,
+                                   gint      stride);
+gint         gegl_tile_offset     (gint      coordinate,
+                                   gint      stride);
 
-GeglTile   * gegl_tile_new             (gint         size);
-guchar     * gegl_tile_get_data        (GeglTile    *tile);
-void       * gegl_tile_get_format      (GeglTile    *tile);
-void         gegl_tile_lock            (GeglTile    *tile);
-void         gegl_tile_unlock          (GeglTile    *tile);
-gboolean     gegl_tile_is_stored       (GeglTile    *tile);
-gboolean     gegl_tile_store           (GeglTile    *tile);
-void         gegl_tile_void            (GeglTile    *tile);
-GeglTile    *gegl_tile_dup             (GeglTile    *tile);
 /* utility low-level functions used by undo system */
-void         gegl_tile_swp             (GeglTile    *a,
-                                        GeglTile    *b);
-void         gegl_tile_cpy             (GeglTile    *src,
-                                        GeglTile    *dst);
-gint         gegl_tile_indice          (gint coordinate,
-                                        gint stride);
-gint         gegl_tile_offset          (gint coordinate,
-                                        gint stride);
+void         gegl_tile_swp        (GeglTile *a,
+                                   GeglTile *b);
+void         gegl_tile_cpy        (GeglTile *src,
+                                   GeglTile *dst);
 
 #endif

Modified: branches/branch_zhangjb/gegl/gegl-chant.h
==============================================================================
--- branches/branch_zhangjb/gegl/gegl-chant.h	(original)
+++ branches/branch_zhangjb/gegl/gegl-chant.h	Sat May 17 17:51:59 2008
@@ -493,7 +493,7 @@
         }                                                             \
       properties->name = g_value_dup_object (value);                  \
       g_signal_connect (G_OBJECT (properties->name), "changed",       \
-       G_CALLBACK(gegl_operation_vector_prop_changed), self);         \
+       G_CALLBACK(gegl_operation_vector_prop_changed), gobject);      \
       break; /*XXX*/
 
 #include GEGL_CHANT_C_FILE

Modified: branches/branch_zhangjb/gegl/gegl-config.c
==============================================================================
--- branches/branch_zhangjb/gegl/gegl-config.c	(original)
+++ branches/branch_zhangjb/gegl/gegl-config.c	Sat May 17 17:51:59 2008
@@ -31,7 +31,8 @@
   PROP_QUALITY,
   PROP_CACHE_SIZE,
   PROP_SWAP,
-  PROP_BABL_ERROR
+  PROP_BABL_ERROR,
+  PROP_NODE_CACHES
 };
 
 static void
@@ -60,6 +61,10 @@
         g_value_set_string (value, config->swap);
         break;
 
+      case PROP_NODE_CACHES:
+        g_value_set_boolean (value, config->node_caches);
+        break;
+
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
         break;
@@ -88,8 +93,9 @@
             config->babl_error = g_value_get_double (value);
             g_sprintf (buf, "%f", config->babl_error);
             g_setenv ("BABL_ERROR", buf, 0);
-            /* babl picks up the babl error through the environment,
-             * not sure if it is cached or not
+            /* babl picks up the babl error through the environment, babl
+             * caches valid conversions though so this needs to be set
+             * before any processing is done
              */
           }
         return;
@@ -98,7 +104,9 @@
          g_free (config->swap);
         config->swap = g_value_dup_string (value);
         break;
-
+      case PROP_NODE_CACHES:
+        config->node_caches  = g_value_get_boolean (value);
+        break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
         break;
@@ -127,6 +135,10 @@
   gobject_class->get_property = get_property;
   gobject_class->finalize = finalize;
 
+  g_object_class_install_property (gobject_class, PROP_NODE_CACHES,
+                                   g_param_spec_boolean ("node-caches", "Node caches", "Whether GEGL caches the results at each node in the graph.", TRUE,
+                                                     G_PARAM_READWRITE));
+
   g_object_class_install_property (gobject_class, PROP_CACHE_SIZE,
                                    g_param_spec_double ("cachei-size", "Cache size", "size of cache in bytes",
                                                      0.0, 1.0, 1.0,
@@ -153,4 +165,5 @@
   self->swap = NULL;
   self->quality = 1.0;
   self->cache_size = 256*1024*1024;
+  self->node_caches = TRUE;
 }

Modified: branches/branch_zhangjb/gegl/gegl-config.h
==============================================================================
--- branches/branch_zhangjb/gegl/gegl-config.h	(original)
+++ branches/branch_zhangjb/gegl/gegl-config.h	Sat May 17 17:51:59 2008
@@ -36,12 +36,13 @@
 
 struct _GeglConfig
 {
-  GObject         parent_instance;
+  GObject  parent_instance;
 
-  gchar          *swap;
-  gint            cache_size;
-  gdouble         quality;
-  gdouble         babl_error;
+  gchar   *swap;
+  gint     cache_size;
+  gdouble  quality;
+  gdouble  babl_error;
+  gboolean node_caches;
 };
 
 struct _GeglConfigClass
@@ -49,7 +50,6 @@
   GObjectClass parent_class;
 };
 
-
 GType gegl_config_get_type (void) G_GNUC_CONST;
 #ifndef __GEGL_INIT_H__
 GeglConfig   * gegl_config            (void);

Modified: branches/branch_zhangjb/gegl/gegl-init.c
==============================================================================
--- branches/branch_zhangjb/gegl/gegl-init.c	(original)
+++ branches/branch_zhangjb/gegl/gegl-init.c	Sat May 17 17:51:59 2008
@@ -164,6 +164,7 @@
 static gchar   *cmd_gegl_cache_size=NULL;
 static gchar   *cmd_gegl_quality=NULL;
 static gchar   *cmd_babl_error=NULL;
+static gboolean cmd_no_node_caches=FALSE;
 
 static const GOptionEntry cmd_entries[]=
 {
@@ -183,6 +184,11 @@
      N_("How much memory to (approximately) use for caching imagery"), "<megabytes>"
     },
     {
+     "gegl-no-node-caches", 0, 0, 
+     G_OPTION_ARG_NONE, &cmd_no_node_caches, 
+     N_("Don't use per node caches to speed up _re_evaluation of the graph"), 
+    },
+    {
      "gegl-quality", 0, 0, 
      G_OPTION_ARG_STRING, &cmd_gegl_quality, 
      N_("The quality of rendering a value between 0.0(fast) and 1.0(reference)"), "<quality>"
@@ -350,7 +356,9 @@
   if (g_getenv ("GEGL_CACHE_SIZE"))
     config->cache_size = atoi(g_getenv("GEGL_CACHE_SIZE"))* 1024*1024; 
 
-
+  config->node_caches = !cmd_no_node_caches;
+  if (g_getenv ("GEGL_NO_NODE_CACHES"))
+    g_object_set (config, "node-caches", FALSE, NULL);
   if (gegl_swap_dir())
     config->swap = g_strdup(gegl_swap_dir ());
   if (cmd_gegl_swap)

Modified: branches/branch_zhangjb/gegl/gegl.h.in
==============================================================================
--- branches/branch_zhangjb/gegl/gegl.h.in	(original)
+++ branches/branch_zhangjb/gegl/gegl.h.in	Sat May 17 17:51:59 2008
@@ -820,6 +820,16 @@
  */
 void           gegl_processor_destroy       (GeglProcessor *processor);
 
+/**
+ * gegl_config:
+ *
+ * Returns a GObject with properties that can be manipulated to control
+ * GEGLs behavior. Properties available on the object are:
+ *
+ * "cache-size" "quality" and "swap", the two first is an integer denoting
+ * number of bytes, the secons a double value between 0 and 1 and the last
+ * the path of the directory to swap to (or "ram" to not use diskbased swap)
+ */
 GObject      * gegl_config (void);
 
 

Modified: branches/branch_zhangjb/gegl/graph/gegl-node-context.c
==============================================================================
--- branches/branch_zhangjb/gegl/graph/gegl-node-context.c	(original)
+++ branches/branch_zhangjb/gegl/graph/gegl-node-context.c	Sat May 17 17:51:59 2008
@@ -30,6 +30,7 @@
 #include "gegl-node-context.h"
 #include "gegl-node.h"
 #include "gegl-pad.h"
+#include "gegl-config.h"
 
 #include "operation/gegl-operation.h"
 
@@ -272,9 +273,12 @@
   node = context->node;
   operation = node->operation;
   pspec = gegl_node_find_property (node, padname);
-  g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
-  g_value_set_object (&value, data);
-  gegl_node_context_set_property (context, padname, &value);
+  if (pspec)
+  {
+    g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+    g_value_set_object (&value, data);
+    gegl_node_context_set_property (context, padname, &value);
+  }
   g_value_unset (&value);
   g_object_unref (data); /* are we stealing the initial reference? */
 }
@@ -337,20 +341,18 @@
 
   result = &context->result_rect;
 
-#if 1 /* change to 0 to disable per node caches */
-  if (GEGL_OPERATION_CLASS (G_OBJECT_GET_CLASS (operation))->no_cache)
+  if (gegl_config()->node_caches &&
+      node->dont_cache == FALSE &&
+      ! GEGL_OPERATION_CLASS (G_OBJECT_GET_CLASS (operation))->no_cache)
     {
-      output = gegl_buffer_new (result, format);
+          GeglBuffer    *cache;
+          cache = GEGL_BUFFER (gegl_node_get_cache (node));
+          output = gegl_buffer_create_sub_buffer (cache, result);
     }
   else
     {
-      GeglBuffer    *cache;
-      cache = GEGL_BUFFER (gegl_node_get_cache (node));
-      output = gegl_buffer_create_sub_buffer (cache, result);
-    }
-#else
-  output = gegl_buffer_new (result, format);
-#endif
+      output = gegl_buffer_new (result, format);
+    }
 
   gegl_node_context_set_object (context, padname, G_OBJECT (output));
   return output;

Modified: branches/branch_zhangjb/gegl/graph/gegl-node.c
==============================================================================
--- branches/branch_zhangjb/gegl/graph/gegl-node.c	(original)
+++ branches/branch_zhangjb/gegl/graph/gegl-node.c	Sat May 17 17:51:59 2008
@@ -53,7 +53,8 @@
   PROP_0,
   PROP_OP_CLASS,
   PROP_OPERATION,
-  PROP_NAME
+  PROP_NAME,
+  PROP_DONT_CACHE
 };
 
 enum
@@ -149,6 +150,14 @@
                                                         G_PARAM_CONSTRUCT |
                                                         G_PARAM_READWRITE));
 
+  g_object_class_install_property (gobject_class, PROP_DONT_CACHE,
+                                   g_param_spec_boolean ("dont-cache",
+                                                         "Do not cache",
+                                                        "Do not cache the result of this operation, the property is inherithed by children created from a node.",
+                                                        TRUE, 
+                                                        G_PARAM_READWRITE));
+
+
   g_object_class_install_property (gobject_class, PROP_NAME,
                                    g_param_spec_string ("name",
                                                         "Name",
@@ -303,6 +312,10 @@
         gegl_node_set_name (node, g_value_get_string (value));
         break;
 
+      case PROP_DONT_CACHE:
+        node->dont_cache = g_value_get_boolean (value);
+        break;
+
       case PROP_OP_CLASS:
         gegl_node_set_op_class (node, g_value_get_string (value), NULL, NULL);
         break;
@@ -332,6 +345,9 @@
           g_value_set_string (value, GEGL_OPERATION_GET_CLASS (node->operation)->name);
         break;
 
+      case PROP_DONT_CACHE:
+        g_value_set_boolean (value, node->dont_cache);
+        break;
       case PROP_NAME:
         g_value_set_string (value, gegl_node_get_name (node));
         break;
@@ -1898,6 +1914,8 @@
   self->is_graph = TRUE;
   child_priv->parent  = self;
 
+  child->dont_cache = self->dont_cache;
+
   return child;
 }
 
@@ -2027,7 +2045,9 @@
 
   node = g_object_new (GEGL_TYPE_NODE, NULL);
   if (parent)
-    gegl_node_add_child (parent, node);
+    {
+      gegl_node_add_child (parent, node);
+    }
 
   name = first_property_name;
   va_start (var_args, first_property_name);
@@ -2043,9 +2063,15 @@
 gegl_node_create_child (GeglNode    *self,
                         const gchar *operation)
 {
+  GeglNode *ret;
   g_return_val_if_fail (operation != NULL, NULL);
 
-  return gegl_node_new_child (self, "operation", operation, NULL);
+  ret = gegl_node_new_child (self, "operation", operation, NULL);
+  if (ret && self)
+    {
+      ret->dont_cache = self->dont_cache;
+    }
+  return ret;
 }
 
 static void

Modified: branches/branch_zhangjb/gegl/graph/gegl-node.h
==============================================================================
--- branches/branch_zhangjb/gegl/graph/gegl-node.h	(original)
+++ branches/branch_zhangjb/gegl/graph/gegl-node.h	Sat May 17 17:51:59 2008
@@ -63,6 +63,8 @@
                              reused for all subsequent requests for the cache
                              object.*/
 
+  gboolean        dont_cache; /* whether result is cached or not, inherited
+                                 by children */
   GMutex          *mutex;
 
   /*< private >*/

Modified: branches/branch_zhangjb/gegl/operation/gegl-operation-area-filter.h
==============================================================================
--- branches/branch_zhangjb/gegl/operation/gegl-operation-area-filter.h	(original)
+++ branches/branch_zhangjb/gegl/operation/gegl-operation-area-filter.h	Sat May 17 17:51:59 2008
@@ -35,7 +35,7 @@
 {
   GeglOperationFilter parent_instance;
 
-  gint                left;
+  gint                left;   /* extra pixels needed in each direction */
   gint                right;
   gint                top;
   gint                bottom;

Modified: branches/branch_zhangjb/gegl/operation/gegl-operation-filter.h
==============================================================================
--- branches/branch_zhangjb/gegl/operation/gegl-operation-filter.h	(original)
+++ branches/branch_zhangjb/gegl/operation/gegl-operation-filter.h	Sat May 17 17:51:59 2008
@@ -44,7 +44,7 @@
   gboolean (* process) (GeglOperation       *self,
                         GeglBuffer          *input,
                         GeglBuffer          *output,
-                        const GeglRectangle *result);
+                        const GeglRectangle *roi);
 };
 
 GType gegl_operation_filter_get_type (void) G_GNUC_CONST;

Modified: branches/branch_zhangjb/gegl/operation/gegl-operation-point-filter.c
==============================================================================
--- branches/branch_zhangjb/gegl/operation/gegl-operation-point-filter.c	(original)
+++ branches/branch_zhangjb/gegl/operation/gegl-operation-point-filter.c	Sat May 17 17:51:59 2008
@@ -28,6 +28,9 @@
 #include "gegl-utils.h"
 #include <string.h>
 
+#include "gegl-buffer-private.h"
+#include "gegl-tile-storage.h"
+
 static gboolean process_inner (GeglOperation       *operation,
                                GeglBuffer          *input,
                                GeglBuffer          *output,
@@ -56,6 +59,7 @@
 {
 }
 
+
 static gboolean
 process_inner (GeglOperation       *operation,
                GeglBuffer          *input,
@@ -65,6 +69,9 @@
   GeglPad    *pad;
   const Babl *in_format;
   const Babl *out_format;
+  GeglOperationPointFilterClass *point_filter_class;
+
+  point_filter_class = GEGL_OPERATION_POINT_FILTER_GET_CLASS (operation);
 
   pad       = gegl_node_get_pad (operation->node, "input");
   in_format = gegl_pad_get_format (pad);
@@ -84,33 +91,99 @@
 
   if ((result->width > 0) && (result->height > 0))
     {
-    /* eek: this fails,..
-      if (!(input->width == output->width &&
-          input->height == output->height))
+      if (gegl_buffer_scan_compatible (input, output))
+        /* We can use the fastest possible path with the least possible
+         * copies using paralell scan iteratator with possibly direct
+         * read write access to buffers.
+         */
         {
-          g_warning ("%ix%i -> %ix%i", input->width, input->height, output->width, output->height);
-        }
-      g_assert (input->width == output->width &&
-                input->height == output->height);
-     */
-      if (in_format == out_format)
-        {
-          gfloat *buf;
-          buf = gegl_malloc (in_format->format.bytes_per_pixel *
-                          output->extent.width * output->extent.height);
-
-          gegl_buffer_get (input, 1.0, result, in_format, buf, GEGL_AUTO_ROWSTRIDE);
-
-          GEGL_OPERATION_POINT_FILTER_GET_CLASS (operation)->process (
-            operation,
-            buf,
-            buf,
-            output->extent.width * output->extent.height);
-
-          gegl_buffer_set (output, result, out_format, buf, GEGL_AUTO_ROWSTRIDE);
-          gegl_free (buf);
+          gint input_bpp  = in_format->format.bytes_per_pixel;
+          gint output_bpp = output->format->format.bytes_per_pixel;
+          gpointer     *in_buf = NULL;
+          gpointer     *out_buf = NULL;
+          Babl         *infish;
+          Babl         *outfish;
+
+          GeglBufferScanIterator read;
+          GeglBufferScanIterator write;
+          gegl_buffer_scan_iterator_init (&read,  input,  *result, FALSE);
+          gegl_buffer_scan_iterator_init (&write, output, *result, TRUE);
+
+          g_assert (input->tile_storage->tile_width == output->tile_storage->tile_width);
+
+
+          infish = babl_fish (input->format, in_format);
+          outfish = babl_fish (out_format, output->format);
+         
+          gegl_buffer_lock (output); 
+          {
+          gboolean a = FALSE, b = FALSE;
+          if (in_format == input->format &&
+              out_format == output->format)
+            {
+              while (  (a = gegl_buffer_scan_iterator_next (&read)) &&
+                       (b = gegl_buffer_scan_iterator_next (&write)))
+                {
+                  g_assert (read.width == write.width);
+                  point_filter_class->process (operation, read.data, write.data, write.width);
+                }
+            }
+          else if (in_format == input->format &&
+                   out_format != output->format)
+            {
+              out_buf = gegl_malloc (output_bpp * write.max_size);
+              while (  (a = gegl_buffer_scan_iterator_next (&read)) &&
+                       (b = gegl_buffer_scan_iterator_next (&write)))
+                {
+                  g_assert (read.width == write.width);
+                  point_filter_class->process (operation, read.data, out_buf, read.width);
+                  babl_process (outfish, out_buf, write.data, write.width);
+                }
+            }
+          else if (in_format != input->format &&
+                   out_format == output->format)
+            {
+              in_buf  = gegl_malloc (input_bpp * read.max_size);
+              while (  (a = gegl_buffer_scan_iterator_next (&read)) &&
+                       (b = gegl_buffer_scan_iterator_next (&write)))
+                {
+                  if (read.width < 0)
+                    continue;
+                  g_assert (read.width == write.width);
+                  babl_process (infish, read.data, in_buf, read.width);
+                  point_filter_class->process (operation, in_buf, write.data, read.width);
+                }
+            }
+          else if (in_format != input->format &&
+                   out_format != output->format)
+            {
+              in_buf  = gegl_malloc (input_bpp * read.max_size);
+              out_buf = gegl_malloc (output_bpp * write.max_size);
+              while (  (a = gegl_buffer_scan_iterator_next (&read)) &&
+                       (b = gegl_buffer_scan_iterator_next (&write)))
+                {
+                  g_assert (read.width == write.width);
+                  babl_process (infish, read.data, in_buf, read.width);
+                  point_filter_class->process (operation, in_buf, out_buf, read.width);
+                  babl_process (outfish, out_buf, write.data, write.width);
+                }
+            }
+
+          if (a)
+            while (gegl_buffer_scan_iterator_next (&read));
+          if (b)
+            while (gegl_buffer_scan_iterator_next (&write));
+          }
+
+          if (in_buf)
+            gegl_free (in_buf);
+          if (out_buf)
+            gegl_free (out_buf);
+          gegl_buffer_unlock (output); 
         }
+#if 0
       else
+        /* do the entire buffer */
         {
           gfloat *in_buf;
           gfloat *out_buf;
@@ -130,7 +203,42 @@
           gegl_buffer_set (output, result, out_format, out_buf, GEGL_AUTO_ROWSTRIDE);
           gegl_free (in_buf);
           gegl_free (out_buf);
+#else
+      else
+        /* do it in vertical chunks of 32 scanlines */
+        {
+          gfloat *in_buf;
+          GeglRectangle roi;
+          gint skip = 32;
+          gfloat *out_buf;
+          in_buf = gegl_malloc (in_format->format.bytes_per_pixel * result->width * skip);
+          out_buf = gegl_malloc (out_format->format.bytes_per_pixel * result->width * skip);
+
+
+          roi = *result;
+          while (roi.y < result->y + result->height && skip >0 )
+            {
+              for (roi.height=skip; (roi.y + skip <= result->y + result->height);
+                   roi.y+=skip)
+                {
+                  gegl_buffer_get (input, 1.0, &roi, in_format, in_buf, GEGL_AUTO_ROWSTRIDE);
+
+                  GEGL_OPERATION_POINT_FILTER_GET_CLASS (operation)->process (
+                    operation,
+                    in_buf,
+                    out_buf,
+                    result->width * skip);
+
+                  gegl_buffer_set (output, &roi, out_format, out_buf, GEGL_AUTO_ROWSTRIDE);
+                }
+                skip /= 2;
+              }
+
+
+          gegl_free (in_buf);
+          gegl_free (out_buf);
         }
+#endif
     }
   return TRUE;
 }

Modified: branches/branch_zhangjb/gegl/operation/gegl-operation-processors.c
==============================================================================
--- branches/branch_zhangjb/gegl/operation/gegl-operation-processors.c	(original)
+++ branches/branch_zhangjb/gegl/operation/gegl-operation-processors.c	Sat May 17 17:51:59 2008
@@ -48,16 +48,12 @@
 
 #include <glib/gprintf.h>
 
-/* FIXME:
- *
- *   pick the correct processor at runtime rather than at class init time
- *   to allow the gegl_config request to override the initial conditions
- */
-
 typedef struct VFuncData
 {
   GCallback callback[MAX_PROCESSOR];
   gchar    *string[MAX_PROCESSOR];
+  gdouble   cached_quality;
+  gint      cached;
 } VFuncData;
 
 void
@@ -66,6 +62,85 @@
                                      GCallback     process,
                                      const gchar  *string);
 
+/* this dispatcher allows overriding a callback without checking how many parameters
+ * are passed and how many parameters are needed, hopefully in a compiler/archi
+ * portable manner.
+ */
+static void
+dispatch (GObject *object,
+          gpointer arg1,
+          gpointer arg2,
+          gpointer arg3,
+          gpointer arg4,
+          gpointer arg5,
+          gpointer arg6,
+          gpointer arg7,
+          gpointer arg8,
+          gpointer arg9)
+{
+  void (*dispatch) (GObject *object,
+                    gpointer arg1,
+                    gpointer arg2,
+                    gpointer arg3,
+                    gpointer arg4,
+                    gpointer arg5,
+                    gpointer arg6,
+                    gpointer arg7,
+                    gpointer arg8,
+                    gpointer arg9)=NULL;
+  VFuncData *data;
+  gint fast      = 0;
+  gint good      = 0;
+  gint reference = 0;
+  gint simd      = 0;
+  gint i;
+  gint choice;
+
+
+  data = g_type_get_qdata (G_OBJECT_TYPE(object),
+                           g_quark_from_string("dispatch-data"));
+  if (!data)
+    {
+      g_error ("dispatch called on object without dispatch-data");
+    }
+
+  if (gegl_config()->quality == data->cached_quality)
+    {
+      dispatch = (void*)data->callback[data->cached];
+      dispatch (object, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+      return;
+    }
+
+  for (i=0;i<MAX_PROCESSOR;i++)
+    {
+      const gchar *string = data->string[i];
+      GCallback cb = data->callback[i];
+
+      if (string && cb!=NULL)
+        {
+          if (g_str_equal (string, "fast"))      fast = i;
+          if (g_str_equal (string, "simd"))      simd = i;
+          else if (g_str_equal (string, "good")) good = i;
+          else if (g_str_equal (string, "reference"))
+            reference = i;
+        }
+    }
+  reference = 0;
+  g_assert (data->callback[reference]);
+
+  choice = reference;
+  if (gegl_config()->quality <= 1.0  && simd) choice = simd;
+  if (gegl_config()->quality <= 0.75 && good) choice = good;
+  if (gegl_config()->quality <= 0.25 && fast) choice = fast;
+
+  GEGL_NOTE(PROCESSOR, "Using %s implementation for %s", data->string[choice], g_type_name (G_OBJECT_TYPE(object)));
+
+  data->cached = choice;
+  data->cached_quality = gegl_config()->quality;
+  dispatch = (void*)data->callback[data->cached];
+  dispatch (object, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
+}
+
 void
 gegl_class_register_alternate_vfunc (GObjectClass *cclass,
                                      gpointer      vfunc_ptr2,
@@ -85,7 +160,9 @@
   if (!data)
     {
       data = g_new0 (VFuncData, 1);
+      data->cached_quality = -1.0;
       g_type_set_qdata (type, quark, data);
+      g_type_set_qdata (type, g_quark_from_string("dispatch-data"), data);
     }
 
   /* Store the default implementation */
@@ -94,15 +171,21 @@
       if (*vfunc_ptr == NULL)
         g_error ("%s: No existing default () vfunc defined for %s",
                  G_STRFUNC, g_type_name (type));
-      data->callback[0]=callback;
+      data->callback[0]=*vfunc_ptr;
       data->string[0]=g_strdup ("reference");
     }
-
+  *vfunc_ptr = (void*)dispatch; /* make our bootstrap replacement for the
+                                 * reference implementation take over
+                                 * dispatching of arguments, not sure if
+                                 * this is portable C or not.
+                                 */
+  
   /* Find a free slot for this one */
   for (i=1; i<MAX_PROCESSOR; i++)
     {
       if (data->callback[i]==NULL)
         {
+          /* store the callback and it's given name */
           data->callback[i]=callback;
           data->string[i]=g_strdup (string);
           break;
@@ -113,50 +196,6 @@
       g_warning ("Too many callbacks added to %s",
                  g_type_name (G_TYPE_FROM_CLASS (cclass)));
     }
-
-    {
-      gint fast        = 0;
-      gint good        = 0;
-      gint reference   = 0;
-      gint g4f         = 0;
-
-      gint choice = 0;
-
-      for (i=0;i<MAX_PROCESSOR;i++)
-        {
-          const gchar *string = data->string[i];
-          GCallback cb = data->callback[i];
-
-          if (string && cb!=NULL)
-            {
-              if (g_str_equal (string, "fast"))
-                fast = i;
-              if (g_str_equal (string, "g4float"))
-                g4f = i;
-              else if (g_str_equal (string, "good"))
-                good = i;
-              else if (g_str_equal (string, "reference"))
-                reference = i;
-            }
-        }
-      reference = 0;
-      g_assert (data->callback[reference]);
-
-      if (gegl_config()->quality <= 0.5)
-        {
-          if (good) choice = good;
-          if (g4f) choice = g4f;
-        }
-      if (gegl_config()->quality <= 0.2)
-        {
-          if (good) choice = good;
-          if (g4f) choice = g4f;
-          if (fast) choice = fast;
-        }
-
-      GEGL_NOTE(PROCESSOR, "Using %s implementation for %s", data->string[choice], g_type_name (G_TYPE_FROM_CLASS (cclass)));
-      *vfunc_ptr = data->callback[choice];
-    }
 }
 
 void

Modified: branches/branch_zhangjb/gegl/operation/gegl-operation-sink.h
==============================================================================
--- branches/branch_zhangjb/gegl/operation/gegl-operation-sink.h	(original)
+++ branches/branch_zhangjb/gegl/operation/gegl-operation-sink.h	Sat May 17 17:51:59 2008
@@ -45,7 +45,7 @@
 
   gboolean (* process) (GeglOperation       *self,
                         GeglBuffer          *input,
-                        const GeglRectangle *result);
+                        const GeglRectangle *roi);
 };
 
 GType    gegl_operation_sink_get_type   (void) G_GNUC_CONST;

Modified: branches/branch_zhangjb/gegl/operation/gegl-operation-source.h
==============================================================================
--- branches/branch_zhangjb/gegl/operation/gegl-operation-source.h	(original)
+++ branches/branch_zhangjb/gegl/operation/gegl-operation-source.h	Sat May 17 17:51:59 2008
@@ -43,7 +43,7 @@
 
   gboolean (* process) (GeglOperation       *self,
                         GeglBuffer          *output,
-                        const GeglRectangle *result);
+                        const GeglRectangle *roi);
 };
 
 GType gegl_operation_source_get_type (void) G_GNUC_CONST;

Modified: branches/branch_zhangjb/gegl/operation/gegl-operation.c
==============================================================================
--- branches/branch_zhangjb/gegl/operation/gegl-operation.c	(original)
+++ branches/branch_zhangjb/gegl/operation/gegl-operation.c	Sat May 17 17:51:59 2008
@@ -406,3 +406,18 @@
   return pad->format;
 }
 
+
+void
+gegl_operation_invalidate (GeglOperation       *operation,
+                           const GeglRectangle *roi)
+{
+  GeglNode *node = NULL;
+
+  if (!operation)
+    return;
+
+  g_return_if_fail (GEGL_IS_OPERATION (operation));
+  node = operation->node;
+
+  gegl_node_invalidated (node, roi);
+}

Modified: branches/branch_zhangjb/gegl/operation/gegl-operation.h
==============================================================================
--- branches/branch_zhangjb/gegl/operation/gegl-operation.h	(original)
+++ branches/branch_zhangjb/gegl/operation/gegl-operation.h	Sat May 17 17:51:59 2008
@@ -138,15 +138,10 @@
   GeglNode*     (*detect)                    (GeglOperation       *operation,
                                               gint                 x,
                                               gint                 y);
-
-
-  GCallback      processor[MAX_PROCESSOR];
-  gchar          *processor_string[MAX_PROCESSOR];
 };
 
 
 
-
 GType           gegl_operation_get_type        (void) G_GNUC_CONST;
 
 GeglRectangle   gegl_operation_get_invalidated_by_change
@@ -217,10 +212,12 @@
 
 /* internal utility functions used by gegl, these should not be used
  * externally */
-gboolean gegl_operation_calc_source_regions  (GeglOperation *operation,
-                                              gpointer       context_id);
-void     gegl_operation_vector_prop_changed  (GeglVector    *vector,
-                                              GeglOperation *operation);
+gboolean gegl_operation_calc_source_regions  (GeglOperation       *operation,
+                                              gpointer             context_id);
+void     gegl_operation_vector_prop_changed  (GeglVector          *vector,
+                                              GeglOperation       *operation);
+void     gegl_operation_invalidate            (GeglOperation       *operation,
+                                               const GeglRectangle *roi);
 
 G_END_DECLS
 

Modified: branches/branch_zhangjb/gegl/property-types/Makefile.am
==============================================================================
--- branches/branch_zhangjb/gegl/property-types/Makefile.am	(original)
+++ branches/branch_zhangjb/gegl/property-types/Makefile.am	Sat May 17 17:51:59 2008
@@ -19,5 +19,6 @@
 INCLUDES = \
 	   -I$(top_srcdir)	\
 	   -I$(top_srcdir)/gegl	\
+	   -I$(top_srcdir)/gegl/buffer \
 	   @DEP_CFLAGS@ @BABL_CFLAGS@
 

Modified: branches/branch_zhangjb/gegl/property-types/gegl-color.c
==============================================================================
--- branches/branch_zhangjb/gegl/property-types/gegl-color.c	(original)
+++ branches/branch_zhangjb/gegl/property-types/gegl-color.c	Sat May 17 17:51:59 2008
@@ -249,6 +249,15 @@
   return FALSE;
 }
 
+const gfloat *
+gegl_color_float4 (GeglColor *self)
+{
+  GeglColorPrivate *priv;
+  /*g_return_val_if_fail (GEGL_IS_COLOR (self), NULL);*/
+  priv = GEGL_COLOR_GET_PRIVATE (self);
+  return &priv->rgba_color[0];
+}
+
 void
 gegl_color_get_rgba (GeglColor *self,
                      gfloat    *r,

Modified: branches/branch_zhangjb/gegl/property-types/gegl-color.h
==============================================================================
--- branches/branch_zhangjb/gegl/property-types/gegl-color.h	(original)
+++ branches/branch_zhangjb/gegl/property-types/gegl-color.h	Sat May 17 17:51:59 2008
@@ -58,6 +58,7 @@
                                                 gfloat       b,
                                                 gfloat       a);
 
+const gfloat*gegl_color_float4                 (GeglColor *color);
 
 #define GEGL_TYPE_PARAM_COLOR           (gegl_param_color_get_type ())
 #define GEGL_IS_PARAM_SPEC_COLOR(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), GEGL_TYPE_PARAM_COLOR))

Modified: branches/branch_zhangjb/gegl/property-types/gegl-vector.c
==============================================================================
--- branches/branch_zhangjb/gegl/property-types/gegl-vector.c	(original)
+++ branches/branch_zhangjb/gegl/property-types/gegl-vector.c	Sat May 17 17:51:59 2008
@@ -13,8 +13,8 @@
  * You should have received a copy of the GNU Lesser General Public
  * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
  *
+ * Copyright 2008 Ãyvind KolÃs <pippin gimp org>
  * Copyright 2006 Mark Probst <mark probst gmail com>
- * Spline Code Copyright 1997 David Mosberger
  */
 
 #include "config.h"
@@ -25,7 +25,11 @@
 
 #include "gegl-types.h"
 
+#include "gegl-buffer-private.h"
 #include "gegl-vector.h"
+#include "gegl-color.h"
+
+
 
 /* ###################################################################### */
 /* path code copied from horizon */
@@ -50,8 +54,8 @@
 
 typedef struct Point
 {
-  gint x;
-  gint y;
+  gfloat x;
+  gfloat y;
 } Point;
 
 struct _Path
@@ -61,45 +65,71 @@
   gchar  type;
 };
 
+
+
 typedef struct _Path Head;
 
+typedef struct _GeglVectorPrivate GeglVectorPrivate;
+typedef struct _VectorNameEntity  VectorNameEntity;
+
+struct _GeglVectorPrivate
+{
+  Path *path;
+
+  Path *axis[8];
+  gint  n_axes;
+};
+
+enum
+{
+  PROP_0,
+};
+
+
+enum
+{
+  GEGL_VECTOR_CHANGED,
+  GEGL_VECTOR_LAST_SIGNAL
+};
+
+guint gegl_vector_signals[GEGL_VECTOR_LAST_SIGNAL] = { 0 };
+
 
-/*** fixed point subdivision bezier ***/
+static void finalize     (GObject      *self);
+static void set_property (GObject      *gobject,
+                          guint         prop_id,
+                          const GValue *value,
+                          GParamSpec   *pspec);
+static void get_property (GObject      *gobject,
+                          guint         prop_id,
+                          GValue       *value,
+                          GParamSpec   *pspec);
+
+G_DEFINE_TYPE (GeglVector, gegl_vector, G_TYPE_OBJECT);
+
+#define GEGL_VECTOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o),\
+                                   GEGL_TYPE_VECTOR, GeglVectorPrivate))
+
+
+/*** subdivision bezier approximation: ***/
 
 /* linear interpolation between two point */
 static void
 lerp (Point *dest,
       Point *a,
       Point *b,
-      gint   t)
-{
-  dest->x = a->x + (b->x-a->x) * t / 65536;
-  dest->y = a->y + (b->y-a->y) * t / 65536;
-}
-
-#define iter1(N) \
-    try = root + (1 << (N)); \
-    if (n >= try << (N))   \
-    {   n -= try << (N);   \
-        root |= 2 << (N); \
-    }
-
-static inline guint isqrt (guint n)
+      gfloat   t)
 {
-    guint root = 0, try;
-    iter1 (15);    iter1 (14);    iter1 (13);    iter1 (12);
-    iter1 (11);    iter1 (10);    iter1 ( 9);    iter1 ( 8);
-    iter1 ( 7);    iter1 ( 6);    iter1 ( 5);    iter1 ( 4);
-    iter1 ( 3);    iter1 ( 2);    iter1 ( 1);    iter1 ( 0);
-    return root >> 1;
+  dest->x = a->x + (b->x-a->x) * t;
+  dest->y = a->y + (b->y-a->y) * t;
 }
 
-static gint
+static gfloat
 point_dist (Point *a,
             Point *b)
 {
-  return isqrt ((a->x-b->x)*(a->x-b->x) +
-                (a->y-b->y)*(a->y-b->y));
+  return sqrt ((a->x-b->x)*(a->x-b->x) +
+               (a->y-b->y)*(a->y-b->y));
 }
 
 
@@ -111,7 +141,7 @@
 static void
 bezier (Point **curve,
         Point *dest,
-        gint   t)
+        gfloat t)
 {
   Point ab,bc,cd,abbc,bccd;
 
@@ -123,8 +153,8 @@
   lerp (dest, &abbc, &bccd, t);
 }
 
-
-gint
+#if 0
+static gint
 path_last_x (Path   *path)
 {
   if (path)
@@ -132,13 +162,14 @@
   return 0;
 }
 
-gint
+static gint
 path_last_y (Path   *path)
 {
   if (path)
     return path->point.y;
   return 0;
 }
+#endif
 
 /* types:
  *   'u' : unitilitlalized state
@@ -151,10 +182,10 @@
  */
 
 static Path *
-path_add (Path *head,
-          gchar type,
-          gint  x,
-          gint  y)
+path_add (Path   *head,
+          gchar   type,
+          gfloat  x,
+          gfloat  y)
 {
   Path *iter = head;
   Path *prev = NULL;
@@ -260,8 +291,9 @@
         /* chop off unneeded elements */
         curve[0]->next = NULL;
 
-        { /* create piecevize linear approximation of bezier curve */
+        { /* create piecevise linear approximation of bezier curve */
            gint   i;
+           gfloat f;
            Point  foo[4];
            Point *pts[4];
 
@@ -272,11 +304,11 @@
                pts[i]->y = curve[i]->point.y;
              }
 
-           for (i=0;i<65536;i+=65536 / BEZIER_SEGMENTS)
+           for (f=0; f<1.0; f += 1.0 / BEZIER_SEGMENTS)
              {
                 Point iter;
 
-                bezier (pts, &iter, i);
+                bezier (pts, &iter, f);
 
                 head = path_add (head, 'l', iter.x, iter.y);
              }
@@ -303,13 +335,15 @@
   return head;
 }
 
-Path *
+#if 0
+static Path *
 path_new (void)
 {
   return path_add (NULL, 'u', 0, 0);
 }
+#endif
 
-Path *
+static Path *
 path_destroy (Path *path)
 {
   g_slice_free_chain (Path, path, next);
@@ -317,32 +351,32 @@
   return NULL;
 }
 
-Path *
-path_move_to (Path *path,
-              gint  x,
-              gint  y)
+static Path *
+path_move_to (Path   *path,
+              gfloat  x,
+              gfloat  y)
 {
   path = path_add (path, 'm', x, y);
   return path;
 }
 
-Path *
-path_line_to (Path *path,
-              gint  x,
-              gint  y)
+static Path *
+path_line_to (Path   *path,
+              gfloat  x,
+              gfloat  y)
 {
   path = path_add (path, 'l', x, y);
   return path;
 }
 
-Path *
-path_curve_to (Path *path,
-               gint  x1,
-               gint  y1,
-               gint  x2,
-               gint  y2,
-               gint  x3,
-               gint  y3)
+static Path *
+path_curve_to (Path   *path,
+               gfloat  x1,
+               gfloat  y1,
+               gfloat  x2,
+               gfloat  y2,
+               gfloat  x3,
+               gfloat  y3)
 {
   path = path_add (path, 'c', x1, y1);
   path = path_add (path, '.', x2, y2);
@@ -350,30 +384,30 @@
   return path;
 }
 
-Path *
-path_rel_move_to (Path *path,
-                  gint  x,
-                  gint  y)
+static Path *
+path_rel_move_to (Path   *path,
+                  gfloat  x,
+                  gfloat  y)
 {
   return path_move_to (path, path->point.x + x, path->point.y + y);
 }
 
-Path *
-path_rel_line_to (Path *path,
-                  gint  x,
-                  gint  y)
+static Path *
+path_rel_line_to (Path   *path,
+                  gfloat  x,
+                  gfloat  y)
 {
   return path_line_to (path, path->point.x + x, path->point.y + y);
 }
 
-Path *
-path_rel_curve_to (Path *path,
-                   gint  x1,
-                   gint  y1,
-                   gint  x2,
-                   gint  y2,
-                   gint  x3,
-                   gint  y3)
+static Path *
+path_rel_curve_to (Path   *path,
+                   gfloat  x1,
+                   gfloat  y1,
+                   gfloat  x2,
+                   gfloat  y2,
+                   gfloat  x3,
+                   gfloat  y3)
 {
   return path_curve_to (path,
                         path->point.x + x1, path->point.y + y1,
@@ -381,30 +415,271 @@
                         path->point.x + x3, path->point.y + y3);
 }
 
-#if 0
+#include <gegl-buffer.h>
 
-/* drawing code follows */
+static gint compare_ints (gconstpointer a,
+                          gconstpointer b)
+{
+  return GPOINTER_TO_INT (a)-GPOINTER_TO_INT (b);
+}
 
-#include "canvas/canvas.h"
-#include "brush.h"
-#include "tools/tool_library.h"
+/* speedy way of doing vectors on gegl, would be to build a runlength
+ * encoded instruction stream for fill n pixels which could be used on
+ * linear buffers.
+ */
 
-/* code to stroke with a specified tool */
 
-void
-path_stroke_tool (Path   *path,
-                  Canvas *canvas,
-                  Tool   *tool)
-{
-  Path *iter = path;
-  gint traveled_length = 0;
-  gint need_to_travel = 0;
-  gint x = 0,y = 0;
+void gegl_vector_fill (GeglBuffer *buffer,
+                       GeglVector *vector,
+                       GeglColor  *color,
+                       gboolean    winding)
+{
+  gdouble xmin, xmax, ymin, ymax;
+  GeglRectangle extent;
+  gint    samples = gegl_vector_get_length (vector);
+  gegl_vector_get_bounds (vector, &xmin, &xmax, &ymin, &ymax);
+
+  extent.x = floor (xmin);
+  extent.y = floor (ymin);
+  extent.width = ceil (xmax) - extent.x;
+  extent.height = ceil (ymax) - extent.y;
+
+  {
+    GSList *scanlines[extent.height];
+
+    gdouble xs[samples];
+    gdouble ys[samples];
+
+    gint i;
+    gdouble prev_x;
+    gint    prev_y;
+    gdouble first_x;
+    gint    first_y;
+    gint    lastline=-1;
+    gint    lastdir=-2;
+
+    gegl_vector_calc_values (vector, samples, xs, ys);
+
+    /* clear scanline intersection lists */
+    for (i=0; i < extent.height; i++)
+      scanlines[i]=NULL;
+
+    first_x = prev_x = xs[0];
+    first_y = prev_y = ys[0];
+    
+
+    /* saturate scanline intersection list */
+    for (i=1; i<samples; i++)
+      {
+        gint dest_x = xs[i];
+        gint dest_y = ys[i];
+        gint ydir;
+        gint dx;
+        gint dy;
+        gint y;
+fill_close:  /* label used for goto to close last segment */
+        dx = dest_x - prev_x;
+        dy = dest_y - prev_y;
+
+        if (dy < 0)
+          ydir = -1;
+        else
+          ydir = 1;
+
+        /* do linear interpolation between vertexes */
+        for (y=prev_y; y!= dest_y; y += ydir)
+          {
+            if (y-extent.y >= 0 &&
+                y-extent.y < extent.height &&
+                lastline != y)
+              {
+                gint x = prev_x + (dx * (y-prev_y)) / dy;
+
+                scanlines[ y - extent.y ]=
+                  g_slist_insert_sorted (scanlines[ y - extent.y],
+                                         GINT_TO_POINTER(x),
+                                         compare_ints);
+                if (ydir != lastdir &&
+                    lastdir != -2)
+                  scanlines[ y - extent.y ]=
+                    g_slist_insert_sorted (scanlines[ y - extent.y],
+                                           GINT_TO_POINTER(x),
+                                           compare_ints);
+                lastdir = ydir;
+                lastline = y;
+              }
+          }
+
+        prev_x = dest_x;
+        prev_y = dest_y;
+
+        /* if we're on the last knot, fake the first vertex being a next one */
+        if (i+1 == samples)
+          {
+            dest_x = first_x;
+            dest_y = first_y;
+            i++; /* to make the loop finally end */
+            goto fill_close;
+          }
+      }
+
+    /* for each scanline */
+{
+    gfloat *buf = NULL;
+    const gfloat *col = gegl_color_float4 (color);
+    Babl *format = babl_format ("RGBA float");
+    buf = g_malloc (extent.width * 4 *4);
+    for (i=0; i < extent.width; i++)
+      {
+        buf[i*4+0] = col[0];
+        buf[i*4+1] = col[1];
+        buf[i*4+2] = col[2];
+        buf[i*4+3] = col[3];
+      }
+
+    if (gegl_buffer_is_shared (buffer))
+    while (!gegl_buffer_try_lock (buffer));
+    for (i=0; i < extent.height; i++)
+      {
+        GSList *iter = scanlines[i];
+        while (iter)
+          {
+            GSList *next = iter->next;
+            gint startx, endx;
+            if (!next)
+              break;
 
-  if (!tool)
-    tool = lookup_tool ("Paint");
+            startx = GPOINTER_TO_INT (iter->data);
+            endx   = GPOINTER_TO_INT (next->data);
+
+            {
+              GeglRectangle roi={startx, extent.y + i, endx - startx, 1};
+              gegl_buffer_set (buffer, &roi, format, buf, 0);
+            }
+
+            iter = next->next;
+          }
+        if (scanlines[i])
+          g_slist_free (scanlines[i]);
+      }
+    if (gegl_buffer_is_shared (buffer))
+    gegl_buffer_unlock (buffer);
+    g_free (buf);
+}
+  }
+
+}
 
+typedef struct StampStatic {
+  gboolean  valid;
+  Babl     *format;
+  gfloat   *buf;
+  gdouble   radius;
+}StampStatic;
+
+void gegl_vector_stamp (GeglBuffer *buffer,
+                        gdouble     x,
+                        gdouble     y,
+                        gdouble     radius,
+                        gdouble     hardness,
+                        GeglColor  *color);
+
+void gegl_vector_stamp (GeglBuffer *buffer,
+                        gdouble     x,
+                        gdouble     y,
+                        gdouble     radius,
+                        gdouble     hardness,
+                        GeglColor  *color)
+{
+  const gfloat *col = gegl_color_float4 (color);
+  static StampStatic s = {FALSE,}; /* XXX: 
+                                      we will ultimately leak the last valid
+                                      cached brush. */
+
+  GeglRectangle roi = {floor(x-radius),
+                       floor(y-radius),
+                       ceil (x+radius) - floor (x-radius),
+                       ceil (y+radius) - floor (y-radius)};
+
+  if (s.format == NULL)
+    s.format = babl_format ("RGBA float");
+  if (s.buf == NULL ||
+      s.radius != radius)
+    {
+      if (s.buf != NULL)
+        g_free (s.buf);
+      /* allocate a little bit more, just in case due to rounding errors and
+       * such */
+      s.buf = g_malloc (4*4* (roi.width + 2 ) * (roi.height + 2));
+      s.radius = radius;
+      s.valid = TRUE;  
+    }
+  g_assert (s.buf);
+
+  gegl_buffer_get (buffer, 1.0, &roi, s.format, s.buf, 0);
+
+  {
+    gint u, v;
+    gint i=0;
+
+    gfloat radius_squared = radius * radius;
+    gfloat inner_radius_squared = (radius * hardness)*(radius * hardness);
+    gfloat soft_range = radius_squared - inner_radius_squared;
+
+    for (u= roi.x; u < roi.x + roi.width; u++)
+      for (v= roi.y; v < roi.y + roi.height ; v++)
+        {
+          gfloat o = (u-x) * (u-x) + (v-y) * (v-y);
+
+          if (o < inner_radius_squared)
+             o = col[3];
+          else if (o < radius_squared)
+            {
+              o = (1.0 - (o-inner_radius_squared) / (soft_range)) * col[3];
+            }
+          else
+            {
+              o=0.0;
+            }
+         if (o!=0.0)
+           {
+             gint c;
+             for (c=0;c<4;c++)
+               s.buf[i*4+c] = (s.buf[i*4+c] * (1.0-o) + col[c] * o);
+             /*s.buf[i*4+3] = s.buf[i*4+3] + o * (1.0-o);*/
+           }
+         i++;
+        }
+  }
+  gegl_buffer_set (buffer, &roi, s.format, s.buf, 0);
+}
+
+
+void gegl_vector_stroke (GeglBuffer *buffer,
+                         GeglVector *vector,
+                         GeglColor  *color,
+                         gdouble     linewidth,
+                         gdouble     hardness)
+{
+  GeglVectorPrivate *priv = GEGL_VECTOR_GET_PRIVATE (vector);
+  gfloat traveled_length = 0;
+  gfloat need_to_travel = 0;
+  gfloat x = 0,y = 0;
   gboolean had_move_to = FALSE;
+  Path *iter = priv->path;
+  gdouble       xmin, xmax, ymin, ymax;
+  GeglRectangle extent;
+
+  gegl_vector_get_bounds (vector, &xmin, &xmax, &ymin, &ymax);
+  extent.x = floor (xmin);
+  extent.y = floor (ymin);
+  extent.width = ceil (xmax) - extent.x;
+  extent.height = ceil (ymax) - extent.y;
+
+  if (gegl_buffer_is_shared (buffer))
+  while (!gegl_buffer_try_lock (buffer));
+
+  gegl_buffer_clear (buffer, &extent);
 
   while (iter)
     {
@@ -421,13 +696,13 @@
           case 'l':
             {
               Point a,b;
-              ToolSetting *ts = tool_with_brush_get_toolsetting (tool);
 
-              gint spacing;
-              gint local_pos;
-              gint distance;
-              gint offset;
-              gint leftover;
+              gfloat spacing;
+              gfloat local_pos;
+              gfloat distance;
+              gfloat offset;
+              gfloat leftover;
+              gfloat radius = linewidth / 2.0;
 
 
               a.x = x;
@@ -436,10 +711,7 @@
               b.x = iter->point.x;
               b.y = iter->point.y;
 
-              spacing = ts->spacing * (ts->radius * MAX_RADIUS / 65536) / 65536;
-
-              if (spacing < MIN_SPACING * SPP / 65536)
-                spacing = MIN_SPACING * SPP / 65536;
+              spacing = 0.2 * radius;
 
               distance = point_dist (&a, &b);
 
@@ -454,18 +726,17 @@
                      local_pos += spacing)
                   {
                     Point spot;
-                    gint ratio = 65536 * local_pos / distance;
-                    gint radius;
+                    gfloat ratio = local_pos / distance;
+                    gfloat radius = linewidth / 2;
+                                 /* horizon used to refetch the radius
+                                  * for each step from the tool, to be
+                                  * able to have variable line width
+                                  */
 
                     lerp (&spot, &a, &b, ratio);
 
-                    radius = ts->radius  * MAX_RADIUS  / 65536,
-
-                    canvas_stamp (canvas,
-                      spot.x, spot.y, radius,
-                      ts->opacity * MAX_OPACITY / 65536,
-                      ts->hardness,
-                      ts->red, ts->green, ts->blue);
+                    gegl_vector_stamp (buffer,
+                      spot.x, spot.y, radius, hardness, color);
 
                     traveled_length += spacing;
                   }
@@ -488,98 +759,11 @@
         }
       iter=iter->next;
     }
-}
-
-extern Tool *tool_paint_new ();
 
-static Tool *path_tool (Path *path)
-{
-  Head *head = (Head*)path;
-  if (!head)
-    return NULL;
-  if (head->tool == NULL)
-    head->tool = tool_paint_new ();
-  return head->tool;
-}
-
-void
-path_set_line_width (Path *path,
-                     gint  line_width)
-{
-  ToolSetting *ts = tool_with_brush_get_toolsetting (path_tool (path));
-  ts->radius = line_width / 2;
+  if (gegl_buffer_is_shared (buffer))
+  gegl_buffer_unlock (buffer);
 }
 
-void
-path_set_rgba (Path *path,
-               gint  red,
-               gint  green,
-               gint  blue,
-               gint  alpha)
-{
-  ToolSetting *ts = tool_with_brush_get_toolsetting (path_tool (path));
-  ts->red   = red;
-  ts->green = green;
-  ts->blue  = blue;
-  ts->opacity = alpha;
-}
-
-void
-path_set_hardness (Path *path,
-                   gint  hardness)
-{
-  ToolSetting *ts = tool_with_brush_get_toolsetting (path_tool (path));
-  ts->hardness = hardness;
-}
-
-void
-path_stroke (Path   *path,
-             Canvas *canvas)
-{
-  path_stroke_tool (path, canvas, path_tool (path));
-}
-#endif
-
-/* ###################################################################### */
-
-
-
-enum
-{
-  PROP_0,
-};
-
-typedef struct _GeglVectorPrivate GeglVectorPrivate;
-typedef struct _VectorNameEntity  VectorNameEntity;
-
-struct _GeglVectorPrivate
-{
-  Path *path;
-};
-
-enum
-{
-  GEGL_VECTOR_CHANGED,
-  GEGL_VECTOR_LAST_SIGNAL
-};
-
-guint gegl_vector_signals[GEGL_VECTOR_LAST_SIGNAL] = { 0 };
-
-
-static void finalize     (GObject      *self);
-static void set_property (GObject      *gobject,
-                          guint         prop_id,
-                          const GValue *value,
-                          GParamSpec   *pspec);
-static void get_property (GObject      *gobject,
-                          guint         prop_id,
-                          GValue       *value,
-                          GParamSpec   *pspec);
-
-G_DEFINE_TYPE (GeglVector, gegl_vector, G_TYPE_OBJECT);
-
-#define GEGL_VECTOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o),\
-                                   GEGL_TYPE_VECTOR, GeglVectorPrivate))
 
 static void
 gegl_vector_init (GeglVector *self)
@@ -623,6 +807,8 @@
   GeglVectorPrivate *priv = GEGL_VECTOR_GET_PRIVATE (self);
 
   self = NULL;
+  if (priv->path)
+    path_destroy (priv->path);
   priv = NULL;
 
   G_OBJECT_CLASS (gegl_vector_parent_class)->finalize (gobject);
@@ -679,13 +865,80 @@
   gegl_vector_emit_changed (self);
 }
 
+void
+gegl_vector_move_to (GeglVector *self,
+                     gdouble     x,
+                     gdouble     y)
+{
+  GeglVectorPrivate *priv;
+  priv = GEGL_VECTOR_GET_PRIVATE (self);
+  priv->path = path_move_to (priv->path, x, y);
+  gegl_vector_emit_changed (self);
+}
+
+void
+gegl_vector_curve_to (GeglVector *self,
+                      gdouble     x1,
+                      gdouble     y1,
+                      gdouble     x2,
+                      gdouble     y2,
+                      gdouble     x3,
+                      gdouble     y3)
+{
+  GeglVectorPrivate *priv;
+  g_print ("foo\n");
+  priv = GEGL_VECTOR_GET_PRIVATE (self);
+  priv->path = path_curve_to (priv->path, x1, y1, x2, y2, x3, y3);
+  gegl_vector_emit_changed (self);
+  g_print ("bar\n");
+}
+
+
+void
+gegl_vector_rel_line_to (GeglVector *self,
+                         gdouble     x,
+                         gdouble     y)
+{
+  GeglVectorPrivate *priv;
+  priv = GEGL_VECTOR_GET_PRIVATE (self);
+  priv->path = path_rel_line_to (priv->path, x, y);
+  gegl_vector_emit_changed (self);
+}
+
+void
+gegl_vector_rel_move_to (GeglVector *self,
+                         gdouble     x,
+                         gdouble     y)
+{
+  GeglVectorPrivate *priv;
+  priv = GEGL_VECTOR_GET_PRIVATE (self);
+  priv->path = path_rel_move_to (priv->path, x, y);
+  gegl_vector_emit_changed (self);
+}
+
+void
+gegl_vector_rel_curve_to (GeglVector *self,
+                          gdouble     x1,
+                          gdouble     y1,
+                          gdouble     x2,
+                          gdouble     y2,
+                          gdouble     x3,
+                          gdouble     y3)
+{
+  GeglVectorPrivate *priv;
+  priv = GEGL_VECTOR_GET_PRIVATE (self);
+  priv->path = path_rel_curve_to (priv->path, x1, y1, x2, y2, x3, y3);
+  gegl_vector_emit_changed (self);
+}
+
+
 gdouble
 gegl_vector_get_length (GeglVector *self)
 {
   GeglVectorPrivate *priv = GEGL_VECTOR_GET_PRIVATE (self);
   Path *iter = priv->path;
-  gint traveled_length = 0;
-  gint x = 0, y = 0;
+  gfloat traveled_length = 0;
+  gfloat x = 0, y = 0;
 
   while (iter)
     {
@@ -698,7 +951,7 @@
           case 'l':
             {
               Point a,b;
-              gint distance;
+              gfloat distance;
 
               a.x = x;
               a.y = y;
@@ -769,9 +1022,9 @@
 {
   GeglVectorPrivate *priv = GEGL_VECTOR_GET_PRIVATE (self);
   Path *iter = priv->path;
-  gint traveled_length = 0;
-  gint need_to_travel = 0;
-  gint x = 0, y = 0;
+  gfloat traveled_length = 0;
+  gfloat need_to_travel = 0;
+  gfloat x = 0, y = 0;
 
   gboolean had_move_to = FALSE;
 
@@ -791,11 +1044,11 @@
             {
               Point a,b;
 
-              gint spacing;
-              gint local_pos;
-              gint distance;
-              gint offset;
-              gint leftover;
+              gfloat spacing;
+              gfloat local_pos;
+              gfloat distance;
+              gfloat offset;
+              gfloat leftover;
 
 
               a.x = x;
@@ -804,7 +1057,7 @@
               b.x = iter->point.x;
               b.y = iter->point.y;
 
-              spacing = 10;
+              spacing = 0.2;
 
               distance = point_dist (&a, &b);
 
@@ -819,7 +1072,7 @@
                      local_pos += spacing)
                   {
                     Point spot;
-                    gint ratio = 65536 * local_pos / distance;
+                    gfloat ratio = local_pos / distance;
 
                     lerp (&spot, &a, &b, ratio);
 

Modified: branches/branch_zhangjb/gegl/property-types/gegl-vector.h
==============================================================================
--- branches/branch_zhangjb/gegl/property-types/gegl-vector.h	(original)
+++ branches/branch_zhangjb/gegl/property-types/gegl-vector.h	Sat May 17 17:51:59 2008
@@ -46,6 +46,39 @@
 
 GeglVector * gegl_vector_new            (void);
 
+
+void         gegl_vector_line_to        (GeglVector  *self,
+                                         gdouble      x,
+                                         gdouble      y);
+
+void         gegl_vector_move_to        (GeglVector *self,
+                                         gdouble     x,
+                                         gdouble     y);
+
+void         gegl_vector_curve_to       (GeglVector *self,
+                                         gdouble     x1,
+                                         gdouble     y1,
+                                         gdouble     x2,
+                                         gdouble     y2,
+                                         gdouble     x3,
+                                         gdouble     y3);
+
+void         gegl_vector_rel_line_to    (GeglVector  *self,
+                                         gdouble      x,
+                                         gdouble      y);
+
+void         gegl_vector_rel_move_to    (GeglVector *self,
+                                         gdouble     x,
+                                         gdouble     y);
+
+void         gegl_vector_rel_curve_to   (GeglVector *self,
+                                         gdouble     x1,
+                                         gdouble     y1,
+                                         gdouble     x2,
+                                         gdouble     y2,
+                                         gdouble     x3,
+                                         gdouble     y3);
+
 void         gegl_vector_get_bounds     (GeglVector   *self,
                                          gdouble      *min_x,
                                          gdouble      *max_x,
@@ -54,9 +87,6 @@
 
 gdouble      gegl_vector_get_length     (GeglVector  *self);
 
-void         gegl_vector_line_to        (GeglVector  *self,
-                                         gdouble      x,
-                                         gdouble      y);
 
 void         gegl_vector_calc           (GeglVector  *self,
                                          gdouble      pos,
@@ -80,6 +110,19 @@
                                          GeglVector  *default_vector,
                                          GParamFlags  flags);
 
+#include <gegl-buffer.h>
+
+void gegl_vector_fill (GeglBuffer *buffer,
+                       GeglVector *vector,
+                       GeglColor  *color,
+                       gboolean    winding);
+
+void gegl_vector_stroke (GeglBuffer *buffer,
+                         GeglVector *vector,
+                         GeglColor  *color,
+                         gdouble     linewidth,
+                         gdouble     hardness);
+
 G_END_DECLS
 
 #endif /* __GEGL_VECTOR_H__ */

Modified: branches/branch_zhangjb/operations/common/brightness-contrast.c
==============================================================================
--- branches/branch_zhangjb/operations/common/brightness-contrast.c	(original)
+++ branches/branch_zhangjb/operations/common/brightness-contrast.c	Sat May 17 17:51:59 2008
@@ -95,13 +95,13 @@
   for (i=0; i<n_pixels; i++)
     {
       gint component;
-      for (component=0; component<3; component++)
+      for (component=0; component <3 ; component++)
         {
           out_pixel[component] =
                 (in_pixel[component] - 0.5) * contrast + brightness + 0.5;
         }
       out_pixel[3] = in_pixel[3]; /* copy the alpha */
-      in_pixel += 4;
+      in_pixel  += 4;
       out_pixel += 4;
     }
   return TRUE;
@@ -109,12 +109,16 @@
 
 
 #ifdef HAS_G4FLOAT
+/* The compiler supports vector extensions allowing an version of
+ * the process code that produces more optimal instructions on the
+ * target platform.
+ */
 
 static gboolean
-process_gcc_vectors (GeglOperation *op,
-                     void          *in_buf,
-                     void          *out_buf,
-                     glong          samples)
+process_simd (GeglOperation *op,
+              void          *in_buf,
+              void          *out_buf,
+              glong          samples)
 {
   GeglChantO *o = GEGL_CHANT_PROPERTIES (op);
   g4float *in  = in_buf;
@@ -126,7 +130,7 @@
   g4float  contrast   = g4float_all(o->contrast);
   g4float  half       = g4float_half;
     
-  while (--samples)
+  while (samples--)
     {
       *out = (*in - half) * contrast + brightness;
       g4floatA(*out)=g4floatA(*in);
@@ -175,7 +179,7 @@
    * broken and not conforming to the reference implementation.
    */
   gegl_operation_class_add_processor (operation_class,
-                                      G_CALLBACK (process_gcc_vectors), "g4float");
+                                      G_CALLBACK (process_simd), "simd");
 #endif
 }
 

Modified: branches/branch_zhangjb/operations/common/invert.c
==============================================================================
--- branches/branch_zhangjb/operations/common/invert.c	(original)
+++ branches/branch_zhangjb/operations/common/invert.c	Sat May 17 17:51:59 2008
@@ -56,7 +56,7 @@
 
 #ifdef HAS_G4FLOAT
 static gboolean
-process_g4f (GeglOperation *op,
+process_simd (GeglOperation *op,
              void          *in_buf,
              void          *out_buf,
              glong          samples)
@@ -65,7 +65,7 @@
   g4float *out = out_buf;
   g4float  one = g4float_one;
 
-  while (--samples)
+  while (samples--)
     {
       gfloat a= g4float_a(*in)[3];
       *out = one - *in;
@@ -96,7 +96,7 @@
 
 #ifdef HAS_G4FLOAT
   gegl_operation_class_add_processor (operation_class,
-                                      G_CALLBACK (process_g4f), "g4float");
+                                      G_CALLBACK (process_simd), "simd");
 #endif
 }
 

Modified: branches/branch_zhangjb/operations/common/whitebalance.c
==============================================================================
--- branches/branch_zhangjb/operations/common/whitebalance.c	(original)
+++ branches/branch_zhangjb/operations/common/whitebalance.c	Sat May 17 17:51:59 2008
@@ -48,14 +48,16 @@
          glong          n_pixels)
 {
   GeglChantO *o = GEGL_CHANT_PROPERTIES (op);
-  gfloat     *pixel;
+  gfloat     *in_pixel;
+  gfloat     *out_pixel;
   gfloat      a_base;
   gfloat      a_scale;
   gfloat      b_base;
   gfloat      b_scale;
   glong       i;
 
-  pixel = in_buf;
+  in_pixel = in_buf;
+  out_pixel = out_buf;
 
   a_scale = (o->high_a_delta - o->low_a_delta);
   a_base = o->low_a_delta;
@@ -64,11 +66,16 @@
 
   for (i=0; i<n_pixels; i++)
     {
-      pixel[1] += pixel[0] * a_scale + a_base;
-      pixel[2] += pixel[0] * b_scale + b_base;
-      pixel[1] = pixel[1] * o->saturation;
-      pixel[2] = pixel[2] * o->saturation;
-      pixel += 4;
+      out_pixel[0] = in_pixel[0];
+      out_pixel[1] = in_pixel[1];
+      out_pixel[2] = in_pixel[2];
+      out_pixel[3] = in_pixel[3];
+      out_pixel[1] += in_pixel[0] * a_scale + a_base;
+      out_pixel[2] += in_pixel[0] * b_scale + b_base;
+      out_pixel[1] = out_pixel[1] * o->saturation;
+      out_pixel[2] = out_pixel[2] * o->saturation;
+      in_pixel += 4;
+      out_pixel += 4;
     }
   return TRUE;
 }

Modified: branches/branch_zhangjb/operations/external/Makefile.am
==============================================================================
--- branches/branch_zhangjb/operations/external/Makefile.am	(original)
+++ branches/branch_zhangjb/operations/external/Makefile.am	Sat May 17 17:51:59 2008
@@ -60,6 +60,14 @@
 display_la_CFLAGS = $(SDL_CFLAGS)
 endif
 
+#if HAVE_V4L
+ops += v4l.la
+v4l_la_SOURCES = v4l.c
+v4l_la_LIBADD = $(op_libs)
+#endif
+
+EXTRA_DIST=v4lutils/v4lutils.c v4lutils/v4lutils.h
+
 if HAVE_AVCODEC
 if HAVE_AVFORMAT
 ops += ff-load.la

Modified: branches/branch_zhangjb/operations/generated/other-blend.rb
==============================================================================
--- branches/branch_zhangjb/operations/generated/other-blend.rb	(original)
+++ branches/branch_zhangjb/operations/generated/other-blend.rb	Sat May 17 17:51:59 2008
@@ -92,7 +92,7 @@
 
 #ifdef HAS_G4FLOAT
   gegl_operation_class_add_processor (operation_class,
-                                      G_CALLBACK (process_gegl4float), "g4float");
+                                      G_CALLBACK (process_gegl4float), "simd");
 #endif
 
 '

Modified: branches/branch_zhangjb/operations/generated/svg-12-porter-duff.rb
==============================================================================
--- branches/branch_zhangjb/operations/generated/svg-12-porter-duff.rb	(original)
+++ branches/branch_zhangjb/operations/generated/svg-12-porter-duff.rb	Sat May 17 17:51:59 2008
@@ -121,7 +121,7 @@
 
 #ifdef HAS_G4FLOAT
   gegl_operation_class_add_processor (operation_class,
-                                      G_CALLBACK (process_gegl4float), "g4float");
+                                      G_CALLBACK (process_gegl4float), "simd");
 #endif
 
 '

Modified: branches/branch_zhangjb/tools/create-reference.rb
==============================================================================
--- branches/branch_zhangjb/tools/create-reference.rb	(original)
+++ branches/branch_zhangjb/tools/create-reference.rb	Sat May 17 17:51:59 2008
@@ -260,7 +260,7 @@
         display: block;
         font-style: italic;
         color: #22F;
-        width: 8em;
+        width: 10em;
         float: left;
   }
   div.arg_name{
@@ -538,6 +538,7 @@
          file.puts "<sub name='#{element.name}' link='api.html\##{element.name.gsub(' ','_')}'/>"
        end
     }
+    file.puts "<sub name='Operations' link='operations.html'/>"
     file.puts "</chapters>"
     file.puts "<functions>"
 
@@ -548,6 +549,15 @@
        if element.is_a? Section and !element.name.empty? and element.name=~ /^Gegl/
          file.puts "<function name='#{element.name}' link='api.html\##{element.name.gsub(' ','_')}'/>"
        end
+
+
+    }
+
+    IO.foreach("operations.html"){ |line|
+        if line =~ /^<li><a href='#op_.*'>.*<\/a><\/li>/
+            opname=line.gsub(/.*op_/,'').gsub(/'.*/,'').strip
+            file.puts "<function name='gegl-#{opname}' link='operations.html#op_#{opname}'/>"
+        end
     }
 
     file.puts "</functions>"



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]