[gegl] A port of gegl-paint to vala



commit 625ef9a939004e4f0a4271b719a9a7e77fddac69
Author: Kao <angekao gmail com>
Date:   Fri May 21 18:27:48 2010 +0200

    A port of gegl-paint to vala

 bindings/vala/samples/Makefile.am |   26 +++++-
 bindings/vala/samples/paint.vala  |  143 ++++++++++++++++++++++++++
 bindings/vala/samples/view.vala   |  202 +++++++++++++++++++++++++++++++++++++
 3 files changed, 369 insertions(+), 2 deletions(-)
---
diff --git a/bindings/vala/samples/Makefile.am b/bindings/vala/samples/Makefile.am
index 9ca7e1e..018c57c 100644
--- a/bindings/vala/samples/Makefile.am
+++ b/bindings/vala/samples/Makefile.am
@@ -1,5 +1,5 @@
 
-noinst_PROGRAMS = format pipeline buffer
+noinst_PROGRAMS = format pipeline buffer paint
 
 BUILT_SOURCES = \
 	$(noinst_PROGRAMS:=.vala.stamp)
@@ -63,7 +63,29 @@ buffer.vala.stamp: $(buffer_VALASOURCES)
 	touch $@
 
 
+# PAINT
+paint_VALASOURCES = paint.vala view.vala
+paint_VALAPKGS = \
+	--pkg=gtk+-2.0	\
+	--vapidir=$(top_srcdir) --pkg=babl-0.0 --pkg=gegl-0.0
+
+paint_SOURCES = \
+	paint.vala.stamp \
+	$(paint_VALASOURCES:.vala=.c)
+
+paint_CFLAGS = \
+	$(VALA_TEST_CFLAGS)
+paint_LDFLAGS = \
+	$(VALA_TEST_LIBS) \
+	-lbabl-0.0 -lgegl-0.0
+
+paint.vala.stamp: $(paint_VALASOURCES)
+	valac -C $(paint_VALAPKGS) $^
+	touch $@
+
+
 EXTRA_DIST = \
 	$(format_VALASOURCES)	\
 	$(pipeline_VALASOURCES)	\
-	$(buffer_VALASOURCES)
+	$(buffer_VALASOURCES) \
+	$(paint_VALASOURCES)
diff --git a/bindings/vala/samples/paint.vala b/bindings/vala/samples/paint.vala
new file mode 100644
index 0000000..1b20a4b
--- /dev/null
+++ b/bindings/vala/samples/paint.vala
@@ -0,0 +1,143 @@
+const double LINEWIDTH = 60.0;
+const double HARDNESS = 0.2;
+const string COLOR = "rgba(0.0,0.0,0.0,0.4)";
+
+
+Gegl.Node n_gegl;
+weak Gegl.Node n_out;
+weak Gegl.Node n_top;
+weak Gegl.Node n_over;
+weak Gegl.Node n_stroke;
+
+bool pen_down = false;
+Gegl.Path vector;
+
+Gegl.Buffer buffer;
+
+
+public bool press (Gdk.EventButton event) 
+{
+    if (event.button == 1)
+    {
+        vector = new Gegl.Path();
+
+        n_over   = n_gegl.new_child("operation","gegl:over");
+
+        n_stroke = n_gegl.new_child("operation","gegl:path",
+                                   "d", vector,
+                                   "fill-opacity", 0.0,
+                                   "stroke", new Gegl.Color(COLOR),
+                                   "stroke-width", LINEWIDTH,
+                                   "stroke-hardness", HARDNESS);
+
+        n_top.link_many(n_over, n_out);
+        n_stroke.connect_to("output", n_over, "aux");
+        
+        vector.append('M', event.x, event.y);
+
+        pen_down = true;
+
+        return true;
+    }
+	return false;
+}
+public bool motion (Gdk.EventMotion event)
+{
+    if ((event.state & Gdk.ModifierType.BUTTON1_MASK) !=0)
+    {
+        if (!pen_down)
+        {
+            return true;
+        }
+        vector.append('L',event.x,event.y);
+        return true;
+    }
+	return false;
+}
+public bool release (Gdk.EventButton event)
+{      
+	if (event.button == 1)
+    {  
+        double x0,x1,y0,y1;
+        Gegl.Processor processor;
+        Gegl.Node writebuf;
+        Gegl.Rectangle roi = Gegl.Rectangle();
+
+        vector.get_bounds (out x0, out x1, out y0, out y1);
+
+        roi.x = (int)(x0 - LINEWIDTH);
+        roi.y = (int)(y0 - LINEWIDTH);
+        roi.width  = (int)(x1 -x0 + LINEWIDTH * 2);
+        roi.height = (int)(y1 -y0 + LINEWIDTH * 2);
+
+        writebuf = n_gegl.new_child("operation", "gegl:write-buffer",
+                                  "buffer", buffer);
+        n_over.link_many(writebuf);
+
+        processor = new Gegl.Processor(writebuf, roi);
+
+        while (processor.work(null));
+
+        n_top.link_many(n_out);
+
+        n_over = null;
+        n_stroke = null;
+        pen_down = false;
+
+        return true;
+    }
+    return false;
+}
+
+
+static int main (string[] args)
+{
+	Gtk.init (ref args);
+	Gegl.init (ref args);
+
+	Log.set_always_fatal (GLib.LogLevelFlags.LEVEL_CRITICAL);
+
+	// Setting up main window
+	Gtk.Window window = new Gtk.Window (Gtk.WindowType.TOPLEVEL);
+	window.title = "GPaint";
+	window.destroy.connect (Gtk.main_quit);
+
+
+	Gegl.Rectangle rect = {0,0,512,512};
+	void* buf;
+
+	buffer = new Gegl.Buffer(rect, Babl.format ("RGBA float"));
+	buf = buffer.linear_open (null, null, Babl.format("Y' u8"));
+	Memory.set (buf, 255, 512*512);
+	buffer.linear_close (buf);
+		
+	n_gegl = new Gegl.Node ();
+	Gegl.Node loadbuf = n_gegl.new_child ("operation","gegl:buffer-source",
+		                                  "buffer",buffer);
+		                                
+	n_out = n_gegl.new_child ("operation", "gegl:nop");
+	loadbuf.link_many (n_out);
+	n_top = loadbuf;
+
+	var view = new View (n_out);
+
+	view.button_press_event.connect (press);
+	view.motion_notify_event.connect (motion);
+	view.button_release_event.connect (release);
+	view.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK);
+
+	window.add (view);
+
+	window.show_all ();
+
+	Gtk.main ();
+
+	n_gegl = null;
+	buffer = null;
+	loadbuf = null;
+	view = null;
+
+	Gegl.exit ();
+	return 0;
+}
+
diff --git a/bindings/vala/samples/view.vala b/bindings/vala/samples/view.vala
new file mode 100644
index 0000000..142a9c7
--- /dev/null
+++ b/bindings/vala/samples/view.vala
@@ -0,0 +1,202 @@
+
+public class View : Gtk.DrawingArea 
+{	
+	private weak Gegl.Node _node;
+    public weak Gegl.Node node
+    {
+        get{ return _node;}
+        set
+        {
+            _node = (Gegl.Node)value;
+            _node.computed.connect((rect)=>
+                {
+                    int x = (int)(this.scale * rect.x - this.x);
+                    int y = (int)(this.scale * rect.y - this.y);
+                    int w = (int)Math.ceil(this.scale * rect.width  + 1);
+                    int h = (int)Math.ceil(this.scale * rect.height + 1);
+                    this.queue_draw_area (x,y,w,h);
+                }
+            );
+            this._node.invalidated.connect((rect)=>this.repaint());
+            this.repaint();
+        }
+    }
+    private uint monitor_id;
+    private Gegl.Processor processor;
+
+
+    /* Fields */
+    public int x {get; set; default = 0;}
+    public int y {get; set; default = 0;}
+    private int screen_x;
+    private int screen_y;
+    private int orig_x;
+    private int orig_y;
+    private int start_buf_x;
+    private int start_buf_y;    
+    private int prev_x;
+    private int prev_y;
+
+    	
+    private double _scale=1.0;
+    public double scale 
+    {
+        get{return _scale;}
+        construct set
+        {
+            if (value > 100) {_scale = double.MAX+1;}
+            if (value < 0) {_scale = double.MIN -1;}
+        }
+    }
+    private double prev_scale;
+
+    private bool drag_started;
+    public bool block {get; set; default = false;}
+
+
+    
+	public View(Gegl.Node node)
+	{
+		this.node = node;
+		this.set_size_request (300, 200);        
+		this.add_events (Gdk.EventMask.BUTTON_PRESS_MASK
+						| Gdk.EventMask.BUTTON_RELEASE_MASK
+             			| Gdk.EventMask.POINTER_MOTION_MASK);
+	}
+	public override bool button_press_event(Gdk.EventButton event) 
+    {
+        int x = (int)event.x;
+        int y = (int)event.y;
+
+        this.screen_x = x;
+        this.screen_y = y;
+        
+        this.orig_x = this.x;
+        this.orig_y = this.y;
+
+        this.start_buf_x = (int)((this.x + x)/this.scale);
+        this.start_buf_y = (int)((this.y + y)/this.scale);
+
+        this.prev_x = x;
+        this.prev_y = y;
+
+        x = (int)(x / this.scale + this.x);
+        y = (int)(y / this.scale + this.y);
+        
+        Gegl.Node detected = this.node.detect ((int)((this.x + event.x)/this.scale),
+                                               (int)((this.y + event.y)/this.scale));
+        if (detected != null)
+        {
+            this.detected(detected);
+        }
+    	this.drag_started = true;
+		return false;
+    }
+    public override bool button_release_event(Gdk.EventButton event) 
+    {
+    	this.drag_started = false;
+		return false;
+    }
+    public override bool motion_notify_event(Gdk.EventMotion event) 
+    {        
+        int x = (int)event.x;
+        int y = (int)event.y;
+
+        if (!this.drag_started) {return false;}
+        if ((event.state & Gdk.ModifierType.BUTTON2_MASK) != 0)
+        {
+            int diff_x = x - this.prev_x;
+            int diff_y = y - this.prev_y;
+
+            this.x -= diff_x;
+            this.y -= diff_y;
+
+            this.get_window().scroll(diff_x, diff_y);
+        }
+
+		this.prev_x = x;
+		this.prev_y = y;
+
+		return true;
+    }
+    public override bool expose_event (Gdk.EventExpose event) 
+    {    	
+    	if (this.node == null) {return false;}
+    	
+    	Gdk.Rectangle[] rectangles;
+        event.region.get_rectangles(out rectangles);
+
+        foreach (var rectangle in rectangles)
+        {
+            Gegl.Rectangle roi = Gegl.Rectangle();
+
+            roi.x = this.x + rectangle.x;
+            roi.y = this.y + rectangle.y;
+            roi.width  = rectangle.width;
+            roi.height = rectangle.height;
+            
+            uchar[] buf = new uchar[roi.width*roi.height*3];
+
+            //uchar *buf = (uchar*)malloc (roi.width * roi.height * 3);
+  
+            this.node.blit(this.scale,
+                           roi,
+                           Babl.format ("R'G'B' u8"),
+                           (void*)buf,
+                           Gegl.AUTO_ROWSTRIDE,
+                           Gegl.BlitFlags.CACHE|
+                           (this.block?0:Gegl.BlitFlags.DIRTY));
+
+            Gdk.draw_rgb_image(this.get_window(),
+                               this.get_style().black_gc,
+                               rectangle.x, rectangle.y,
+                               rectangle.width, rectangle.height,
+                               Gdk.RgbDither.NONE,
+                               buf, roi.width*3);
+        }    	
+		return false;
+    }
+    public void repaint()
+    {
+        Gegl.Rectangle roi = Gegl.Rectangle();
+        
+        roi.x = (int)(this.x / this.scale);
+        roi.y = (int)(this.y / this.scale);
+        roi.width = (int)Math.ceil(this.allocation.width / this.scale+1);
+        roi.height = (int)Math.ceil(this.allocation.height / this.scale+1);
+
+        if (this.monitor_id == 0) 
+        {
+            this.monitor_id = Idle.add_full(Priority.LOW,task_monitor);
+
+            if (this.processor == null)
+            {
+                if (this.node != null)
+                {
+                    this.processor = new Gegl.Processor(node, roi);
+                }
+            }
+        }
+
+        if (this.processor != null) 
+        {
+            processor.set_rectangle(roi);
+        }
+    }
+
+    private bool task_monitor ()
+    {
+        if (this.processor == null) 
+        {
+            return false;
+        }
+        if (this.processor.work(null)) 
+        {
+            return true;
+        }
+
+        this.monitor_id = 0;
+        return false;
+    }
+    public signal void detected(Gegl.Node node);
+}



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