[goocanvas/new-api] Merged changes from 2.0.0 to 2.0.1.



commit c2bb809c64b792945cd35ea32ed8a2f999cceee8
Author: Damon Chaplin <damon gnome org>
Date:   Mon Oct 10 15:15:16 2011 +0100

    Merged changes from 2.0.0 to 2.0.1.

 Makefile.am                  |    4 +-
 NEWS                         |   11 ++
 bindings/Makefile.am         |    1 +
 bindings/gjs/demo.js         |  300 +++++++++++++++++++++++++++++++++++++++++
 bindings/python/GooCanvas.py |   39 ++++++
 bindings/python/Makefile.am  |    5 +
 bindings/python/demo.py      |  248 ++++++++++++++++++++++++++++++++++
 bindings/seed/demo.js        |  301 ++++++++++++++++++++++++++++++++++++++++++
 configure.in                 |   29 ++++
 src/Makefile.am              |   26 ++++
 src/goocanvas.c              |  168 +++++++++++++++++++-----
 src/goocanvas.h              |    7 +
 src/goocanvasellipse.c       |    4 +-
 src/goocanvasgrid.c          |   70 ++++++++++-
 src/goocanvasgroup.c         |    4 +-
 src/goocanvasimage.c         |   79 ++++++++++--
 src/goocanvasimage.h         |    1 +
 src/goocanvasitem.c          |   78 ++++++++---
 src/goocanvasitem.h          |   17 ++-
 src/goocanvasitemsimple.c    |   61 +++++++++
 src/goocanvaspath.c          |    4 +-
 src/goocanvaspolyline.c      |   54 +++++++-
 src/goocanvaspolyline.h      |    9 +-
 src/goocanvasprivate.h       |   10 +-
 src/goocanvasrect.c          |    4 +-
 src/goocanvastable.c         |   52 +++++++-
 src/goocanvastext.c          |  108 ++++++++++-----
 src/goocanvasutils.c         |   47 ++++++-
 src/goocanvaswidget.c        |    4 +-
 29 files changed, 1607 insertions(+), 138 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index ebf1ef7..273e4d3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,10 +1,12 @@
 ## Process this file with automake to produce Makefile.in
 
-SUBDIRS = src demo docs po
+SUBDIRS = src demo docs po bindings
 
 # require automake 1.7
 AUTOMAKE_OPTIONS = 1.7
 
+DISTCHECK_CONFIGURE_FLAGS = --enable-introspection
+
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = goocanvas-2.0.pc
 
diff --git a/NEWS b/NEWS
index c3ab61c..9e91cef 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,15 @@
 
+GooCanvas 2.0.1	(Oct 9 2011)
+===============
+
+ o Added GObject introspection support, though a few issues remain.
+   (e.g. cairo_transform_t hasn't been wrapped yet, so can't be used.)
+ o Fixed bounds calculation of text items in tables, when "height" is set.
+ o Fixed layout of center/right-aligned text in tables.
+ o Improved handling of image pixbuf sizes when using units other than pixels.
+ o Added GdkRGBA variants of all color properties, e.g. "stroke-color-gdk-rgba".
+
+
 GooCanvas 2.0.0	(Feb 27 2011)
 ===============
 
diff --git a/bindings/Makefile.am b/bindings/Makefile.am
new file mode 100644
index 0000000..96fcb3e
--- /dev/null
+++ b/bindings/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = python
diff --git a/bindings/gjs/demo.js b/bindings/gjs/demo.js
new file mode 100755
index 0000000..6319224
--- /dev/null
+++ b/bindings/gjs/demo.js
@@ -0,0 +1,300 @@
+#!/usr/bin/env gjs
+
+const Gtk = imports.gi.Gtk;
+const GdkPixbuf = imports.gi.GdkPixbuf;
+const GooCanvas = imports.gi.GooCanvas;
+const cairo = imports.cairo;
+
+
+let setup_polyline = function(c) {
+    let group = c.get_root_item();
+    
+    new GooCanvas.CanvasRect ({
+        parent: group,
+        x: 0,
+        y: 0,
+        width: 600,
+        height: 450,
+        line_width: 4.0
+    });
+
+    /* No way to do this in JS yet */
+    /*
+    GooCanvas.CanvasPolyline.new_line(group, 0, 150, 600, 150, line_width=4.0)
+
+    GooCanvas.CanvasPolyline.new_line(group, 0, 300, 600, 300, line_width=4.0)
+
+    GooCanvas.CanvasPolyline.new_line(group, 200, 0, 200, 450, line_width=4.0)
+
+    GooCanvas.CanvasPolyline.new_line(group, 400, 0, 400, 450, line_width=4.0)
+    */
+    
+    /* Or any of this */
+    /*
+    p_points = GooCanvas.CanvasPoints((
+                            (340.0, 170.0),
+                            (340.0, 230.0),
+                            (390.0, 230.0),
+                            (390.0, 170.0)))
+    GooCanvas.CanvasPolyline (parent=group, close_path=False,
+                       points=p_points,
+                       stroke_color="midnightblue",
+                       line_width=3.0,
+                       start_arrow=True,
+                       end_arrow=True,
+                       arrow_tip_length=3.0,
+                       arrow_length=4.0,
+                       arrow_width=3.5)
+
+    p_points = GooCanvas.CanvasPoints((
+                            (356.0, 180.0),
+                            (374.0, 220.0)))
+    GooCanvas.CanvasPolyline (parent=group, close_path=False,
+                       points=p_points,
+                       stroke_color="blue",
+                       line_width=1.0,
+                       start_arrow=True,
+                       end_arrow=True,
+                       arrow_tip_length=5.0,
+                       arrow_length=6.0,
+                       arrow_width=6.0)
+
+    GooCanvas.CanvasPolyline (parent=group, close_path=False,
+                       points=GooCanvas.CanvasPoints(((356.0, 220.0),)),
+                       start_arrow=True,
+                       end_arrow=True)
+    */
+};
+
+
+let setup_canvas = function(c) {
+    let root = c.get_root_item();
+    
+    // Test the simple commands like moveto and lineto: MmZzLlHhVv
+    new GooCanvas.CanvasPath({ parent:root, data:"M 20 20 L 40 40" });
+    new GooCanvas.CanvasPath({ parent:root, data:"M30 20 l20, 20"  });
+    new GooCanvas.CanvasPath({ parent:root, data:"M 60 20 H 80" });
+    new GooCanvas.CanvasPath({ parent:root, data:"M60 40 h20"});
+    new GooCanvas.CanvasPath({ parent:root, data:"M 100,20 V 40"});
+    
+    // Test empty
+    let p = new GooCanvas.CanvasPath({ parent: root, data:"" });
+    p.data = "M 120 20 v 20";
+    
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M 180 20 h20 v20 h-20 z m 5,5 h10 v10 h-10 z",
+        fill_color: "red",
+        //fill_rule: cairo.FILL_RULE_EVEN_ODD,
+    });
+    
+    new GooCanvas.CanvasPath({
+        parent:root,
+        data: "M 220 20 L 260 20 L 240 40 z",
+        fill_color: "red",
+        stroke_color: "blue",
+        line_width: 3.0
+    });
+    
+    //Test the bezier curve commands: CcSsQqTt.   
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M20,100 C20,50 100,50 100,100 S180,150 180,100"
+    });
+    
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M220,100 c0,-50 80,-50 80,0 s80,50 80,0"
+    });
+    
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M20,200 Q60,130 100,200 T180,200"
+    });
+    
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M220,200 q40,-70 80,0 t80,0"
+    });
+    
+    // Test the elliptical arc commands: Aa.
+    new GooCanvas.CanvasPath ({
+        parent: root,
+        data: "M200,500 h-150 a150,150 0 1,0 150,-150 z",
+        fill_color: "red",
+        stroke_color: "blue",
+        line_width: 5.0,
+    });
+    
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M175,475 v-150 a150,150 0 0,0 -150,150 z",
+        fill_color: "yellow",
+        stroke_color: "blue",
+        line_width: 5.0
+    });
+
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M400,600 l 50,-25 " +
+              "a25,25 -30 0,1 50,-25 l 50,-25" +
+              "a25,50 -30 0,1 50,-25 l 50,-25" +
+              "a25,75 -30 0,1 50,-25 l 50,-25" +
+              "a25,100 -30 0,1 50,-25 l 50,-25",
+        stroke_color: "red",
+        line_width: 5.0,
+    });
+
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M 725,75 a100,50 0 0,1 100,50",
+        stroke_color: "red",
+        line_width: 5.0,
+    });
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M 525,200 a100,50 0 1,0 100,50",
+        stroke_color: "red",
+        line_width: 5.0,
+    });
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M 725,200 a100,50 0 1,1 100,50",
+        stroke_color: "red",
+        line_width: 5.0,
+    });
+                  
+    let t = new GooCanvas.CanvasText ({
+        parent: root,
+        text: "Hello World!",
+        anchor: GooCanvas.CanvasAnchorType.CENTER
+    });
+    
+};
+
+let setup_scalability = function(c) {
+    const N_COLS = 5;
+    const N_ROWS = 20;
+    const PADDING = 10;
+    
+    let vbox = new Gtk.VBox({homogeneous: false, spacing: 4});
+    vbox.set_border_width(4);
+    vbox.show();
+    
+    let table = Gtk.Table.new(2, 2, false);
+    table.set_row_spacings(4);
+    table.set_col_spacings(4);
+    vbox.pack_start(table, true, true, 0);
+    table.show();
+    
+    let frame = new Gtk.Frame();
+    frame.set_shadow_type(Gtk.ShadowType.IN);
+    table.attach(frame, 0, 1, 0, 1,
+              Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK,
+              Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK,
+              0, 0);
+    frame.show();
+    
+    let pb;
+    let width;
+    let height;
+    
+    if (1) {
+        pb = GdkPixbuf.Pixbuf.new_from_file("../../demo/toroid.png");
+        width = pb.get_width();
+        height = pb.get_height();
+    } else {
+        pb = null;
+        width = 37;
+        height = 19;
+    }
+    
+    c.set_bounds (
+            0, 0,
+            N_COLS * (width + PADDING),
+            N_ROWS * (height + PADDING));
+    c.show ();
+
+    let scrolled_win = new Gtk.ScrolledWindow();
+    scrolled_win.show()
+    frame.add(scrolled_win)
+    scrolled_win.add(c)
+
+    let root = c.get_root_item()
+    for (let i=0; i<N_COLS; i++) {
+        for (let j=0; j<N_ROWS; j++) {
+            if (pb) {
+                new GooCanvas.CanvasImage ({
+                            parent: root,
+                            pixbuf: pb,
+                            x: i * (width + PADDING),
+                            y: j * (height + PADDING) });
+            } else {
+                let item = new GooCanvas.CanvasRect ({
+                            parent: root,
+                            x: i * (width + PADDING),
+                            y: j * (height + PADDING),
+                            width: width,
+                            height: height});
+                item.fill_color = (j % 2 === 0) ? "mediumseagreen" : "steelblue";
+            }
+        }           
+    }
+
+    return vbox;
+}
+
+let setup_widget = function(c) {
+    let root = c.get_root_item();
+    
+    new GooCanvas.CanvasWidget({
+        parent: root,
+        widget: Gtk.Label.new("Hello World"),
+        x: 50, y: 50, width: 200, height: 100
+    });
+    new GooCanvas.CanvasWidget({
+        parent: root,
+        widget: new Gtk.Entry(),
+        x: 50, y: 250, width: 200, height: 50
+    });
+    
+    let entry = new Gtk.Entry();
+    entry.set_text("Size: -1 x -1");
+    new GooCanvas.CanvasWidget({
+        parent: root,
+        widget: entry,
+        x: 50, y: 300, width: -1, height: -1
+    });
+    
+    entry = new Gtk.Entry();
+    entry.set_text("Size: 100 x -1");
+    new GooCanvas.CanvasWidget({
+        parent: root,
+        widget: entry,
+        x:50, y: 350, width: 100, height: -1
+    });
+}
+
+
+let demo_window = function(setup_func) {
+    let c = new GooCanvas.Canvas();
+    c.set_size_request(600, 450);
+    let widget = setup_func(c);
+    if (!widget) {
+        widget = c;
+    }
+    let w = new Gtk.Window();
+    w.set_size_request(600, 450);
+    w.add(widget);
+    w.show_all();
+    w.connect("destroy", Gtk.main_quit);
+}
+
+Gtk.init(null, null);
+
+demo_window(setup_canvas);
+demo_window(setup_polyline);
+demo_window(setup_scalability);
+demo_window(setup_widget);
+
+Gtk.main()
diff --git a/bindings/python/GooCanvas.py b/bindings/python/GooCanvas.py
new file mode 100644
index 0000000..c1b42fa
--- /dev/null
+++ b/bindings/python/GooCanvas.py
@@ -0,0 +1,39 @@
+from ..overrides import override
+from ..importer import modules
+
+GooCanvas = modules['GooCanvas']._introspection_module
+
+__all__ = []
+
+#We cant change the numner of points once constructed, and boxed types do not allow
+#arguments to constructors, so override __new__
+class CanvasPoints(GooCanvas.CanvasPoints):
+
+    def __new__(cls, points):
+
+        assert len(points)
+        assert len(points[0])
+
+        obj = cls.new(len(points))
+        i = 0
+        for p in points:
+            obj.set_point(i, p[0],p[1])
+            i += 1
+        return obj
+
+CanvasPoints = override(CanvasPoints)
+__all__.append('CanvasPoints')
+
+class CanvasPolyline(GooCanvas.CanvasPolyline):
+
+    @classmethod
+    def new_line(cls, parent, x1, y1, x2, y2, **props):
+        props.update(
+                parent=parent,
+                points=CanvasPoints(((x1,y1),(x2,y2))),
+                close_path=False)
+        return cls(**props)
+
+CanvasPolyline = override(CanvasPolyline)
+__all__.append('CanvasPolyline')
+
diff --git a/bindings/python/Makefile.am b/bindings/python/Makefile.am
new file mode 100644
index 0000000..5e260ec
--- /dev/null
+++ b/bindings/python/Makefile.am
@@ -0,0 +1,5 @@
+if ENABLE_PYTHON
+overridesdir = $(pyoverridesdir)
+overrides_PYTHON =			\
+	GooCanvas.py
+endif
diff --git a/bindings/python/demo.py b/bindings/python/demo.py
new file mode 100755
index 0000000..d641e21
--- /dev/null
+++ b/bindings/python/demo.py
@@ -0,0 +1,248 @@
+#!/usr/bin/env python
+
+from gi.repository import Gtk, GdkPixbuf, GooCanvas
+
+def setup_polyline(c):
+    group = c.get_root_item()
+
+    GooCanvas.CanvasRect (parent=group, x=0,y=0,width=600,height=450, line_width=4.0)
+
+    GooCanvas.CanvasPolyline.new_line(group, 0, 150, 600, 150, line_width=4.0)
+
+    GooCanvas.CanvasPolyline.new_line(group, 0, 300, 600, 300, line_width=4.0)
+
+    GooCanvas.CanvasPolyline.new_line(group, 200, 0, 200, 450, line_width=4.0)
+
+    GooCanvas.CanvasPolyline.new_line(group, 400, 0, 400, 450, line_width=4.0)
+
+    p_points = GooCanvas.CanvasPoints((
+                            (340.0, 170.0),
+                            (340.0, 230.0),
+                            (390.0, 230.0),
+                            (390.0, 170.0)))
+    GooCanvas.CanvasPolyline (parent=group, close_path=False,
+                       points=p_points,
+                       stroke_color="midnightblue",
+                       line_width=3.0,
+                       start_arrow=True,
+                       end_arrow=True,
+                       arrow_tip_length=3.0,
+                       arrow_length=4.0,
+                       arrow_width=3.5)
+
+    p_points = GooCanvas.CanvasPoints((
+                            (356.0, 180.0),
+                            (374.0, 220.0)))
+    GooCanvas.CanvasPolyline (parent=group, close_path=False,
+                       points=p_points,
+                       stroke_color="blue",
+                       line_width=1.0,
+                       start_arrow=True,
+                       end_arrow=True,
+                       arrow_tip_length=5.0,
+                       arrow_length=6.0,
+                       arrow_width=6.0)
+
+    GooCanvas.CanvasPolyline (parent=group, close_path=False,
+                       points=GooCanvas.CanvasPoints(((356.0, 220.0),)),
+                       start_arrow=True,
+                       end_arrow=True)
+
+def setup_canvas(c):
+    root = c.get_root_item()
+
+    #Test the simple commands like moveto and lineto: MmZzLlHhVv. */
+    GooCanvas.CanvasPath (parent=root, data="M 20 20 L 40 40")
+    GooCanvas.CanvasPath (parent=root, data="M30 20 l20, 20")
+    GooCanvas.CanvasPath (parent=root, data="M 60 20 H 80")
+    GooCanvas.CanvasPath (parent=root, data="M60 40 h20")
+    GooCanvas.CanvasPath (parent=root, data="M 100,20 V 40")
+
+    #test empty    
+    p = GooCanvas.CanvasPath (parent=root, data="")
+    p.props.data = "M 120 20 v 20"
+
+    GooCanvas.CanvasPath (parent=root,
+                  data="M 180 20 h20 v20 h-20 z m 5,5 h10 v10 h-10 z",
+                  fill_color="red",
+    #              "fill_rule", CAIRO_FILL_RULE_EVEN_ODD,
+                  )
+
+    GooCanvas.CanvasPath (parent=root,
+                  data="M 220 20 L 260 20 L 240 40 z",
+                  fill_color="red",
+                  stroke_color="blue",
+                  line_width=3.0,
+                  )
+
+    #Test the bezier curve commands: CcSsQqTt. */
+    GooCanvas.CanvasPath (parent=root,
+                  data="M20,100 C20,50 100,50 100,100 S180,150 180,100",
+                  )
+
+    GooCanvas.CanvasPath (parent=root,
+                  data="M220,100 c0,-50 80,-50 80,0 s80,50 80,0",
+                  )
+
+    GooCanvas.CanvasPath (parent=root,
+                  data="M20,200 Q60,130 100,200 T180,200",
+                  )
+
+    GooCanvas.CanvasPath (parent=root,
+                  data="M220,200 q40,-70 80,0 t80,0",
+                  )
+
+    # Test the elliptical arc commands: Aa. */
+    GooCanvas.CanvasPath (parent=root,
+                  data="M200,500 h-150 a150,150 0 1,0 150,-150 z",
+                  fill_color="red",
+                  stroke_color="blue",
+                  line_width=5.0,
+                  )
+
+    GooCanvas.CanvasPath (parent=root,
+                  data="M175,475 v-150 a150,150 0 0,0 -150,150 z",
+                  fill_color="yellow",
+                  stroke_color="blue",
+                  line_width=5.0,
+                  )
+
+    GooCanvas.CanvasPath (parent=root,
+                  data="""M400,600 l 50,-25
+                  a25,25 -30 0,1 50,-25 l 50,-25
+                  a25,50 -30 0,1 50,-25 l 50,-25
+                  a25,75 -30 0,1 50,-25 l 50,-25
+                  a25,100 -30 0,1 50,-25 l 50,-25""",
+                  stroke_color="red",
+                  line_width=5.0,
+                  )
+
+    GooCanvas.CanvasPath (parent=root,
+                  data="M 525,75 a100,50 0 0,0 100,50",
+                  stroke_color="red",
+                  line_width=5.0,
+                  )
+    GooCanvas.CanvasPath (parent=root,
+                  data="M 725,75 a100,50 0 0,1 100,50",
+                  stroke_color="red",
+                  line_width=5.0,
+                  )
+    GooCanvas.CanvasPath (parent=root,
+                  data="M 525,200 a100,50 0 1,0 100,50",
+                  stroke_color="red",
+                  line_width=5.0,
+                  )
+    GooCanvas.CanvasPath (parent=root,
+                  data="M 725,200 a100,50 0 1,1 100,50",
+                  stroke_color="red",
+                  line_width=5.0,
+                  )
+
+def setup_scalability(c):
+    N_COLS = 5
+    N_ROWS = 20
+    PADDING = 10
+
+    vbox = Gtk.VBox (homogeneous=False, spacing=4)
+    vbox.set_border_width (4)
+    vbox.show()
+
+    table = Gtk.Table (2, 2, False)
+    table.set_row_spacings (4)
+    table.set_col_spacings (4)
+    vbox.pack_start (table, True, True, 0)
+    table.show ()
+
+    frame = Gtk.Frame ()
+    frame.set_shadow_type (Gtk.ShadowType.IN)
+    table.attach (frame,
+              0, 1, 0, 1,
+              Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK,
+              Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK,
+              0, 0);
+    frame.show()
+
+    if 1:
+        pb = GdkPixbuf.Pixbuf.new_from_file("../../demo/toroid.png")
+        width = pb.get_width()
+        height = pb.get_height()
+    else:
+        pb = None
+        width = 37
+        height = 19
+
+    c.set_bounds (
+            0, 0,
+            N_COLS * (width + PADDING),
+            N_ROWS * (height + PADDING))
+    c.show ();
+
+    scrolled_win = Gtk.ScrolledWindow ()
+    scrolled_win.show()
+    frame.add(scrolled_win)
+    scrolled_win.add(c)
+
+    root = c.get_root_item()
+    for i in range(N_COLS):
+        for j in range(N_ROWS):
+            if pb:
+                GooCanvas.CanvasImage (
+                            parent=root,
+                            pixbuf=pb,
+                            x=i * (width + PADDING),
+                            y=j * (height + PADDING))
+            else:
+                item = GooCanvas.CanvasRect (
+                            parent=root,
+                            x=i * (width + PADDING),
+                            y=j * (height + PADDING),
+                            width=width,
+                            height=height)
+                item.props.fill_color = {True:"mediumseagreen",False:"steelblue"}[j % 2 == 0]
+
+    return vbox
+
+def setup_widget(c):
+    root = c.get_root_item()
+
+    #Add a few simple items. */
+    GooCanvas.CanvasWidget (
+                parent=root,
+                widget=Gtk.Label("Hello World"),
+                x=50, y=50, width=200, height=100)
+    GooCanvas.CanvasWidget (
+                parent=root,
+                widget=Gtk.Entry(),
+                x=50, y=250, width=200, height=50)
+
+    entry = Gtk.Entry ()
+    entry.set_text ("Size: -1 x -1")
+    GooCanvas.CanvasWidget (
+                parent=root,
+                widget=entry,
+                x=50, y=300, width=-1, height=-1)
+
+    entry = Gtk.Entry ()
+    entry.set_text ("Size: 100 x -1")
+    GooCanvas.CanvasWidget (
+                parent=root,
+                widget=entry,
+                x=50, y=350, width=100, height=-1)
+
+def demo_window(setup_func):
+    c = GooCanvas.Canvas()
+    c.set_size_request(600, 450)
+    widget = setup_func(c) or c
+    w = Gtk.Window()
+    w.set_size_request(600, 450)
+    w.add(widget)
+    w.show_all()
+    w.connect("destroy", Gtk.main_quit)
+
+if __name__ == "__main__":
+    demo_window(setup_canvas)
+    demo_window(setup_polyline)
+    demo_window(setup_scalability)
+    demo_window(setup_widget)
+
+    Gtk.main()
diff --git a/bindings/seed/demo.js b/bindings/seed/demo.js
new file mode 100755
index 0000000..3283172
--- /dev/null
+++ b/bindings/seed/demo.js
@@ -0,0 +1,301 @@
+#!/usr/bin/env seed
+
+const Gtk = imports.gi.Gtk;
+const GdkPixbuf = imports.gi.GdkPixbuf;
+const GooCanvas = imports.gi.GooCanvas;
+const cairo = imports.cairo;
+
+
+var setup_polyline = function(c) {
+    var group = c.get_root_item();
+    
+    new GooCanvas.CanvasRect ({
+        parent: group,
+        x: 0,
+        y: 0,
+        width: 600,
+        height: 450,
+        line_width: 4.0
+    });
+
+    /* No way to do this in JS yet */
+    /*
+    GooCanvas.CanvasPolyline.new_line(group, 0, 150, 600, 150, line_width=4.0)
+
+    GooCanvas.CanvasPolyline.new_line(group, 0, 300, 600, 300, line_width=4.0)
+
+    GooCanvas.CanvasPolyline.new_line(group, 200, 0, 200, 450, line_width=4.0)
+
+    GooCanvas.CanvasPolyline.new_line(group, 400, 0, 400, 450, line_width=4.0)
+    */
+    
+    /* This can be done in Seed but not GJS; very longwinded though */
+    var p_points = new GooCanvas.CanvasPoints.c_new(4);
+    p_points.set_point(0, 340.0, 170.0);
+    p_points.set_point(1, 340.0, 230.0);
+    p_points.set_point(2, 390.0, 230.0);
+    p_points.set_point(3, 390.0, 170.0);
+    
+    new GooCanvas.CanvasPolyline({
+        parent: group,
+        points: p_points,
+        stroke_color: "midnightblue",
+        start_arrow: true,
+        end_arrow: true,
+        arrow_tip_length: 3.0,
+        arrow_length: 4.0,
+        arrow_width: 3.5
+    });
+    
+    /* etc...
+    p_points = GooCanvas.CanvasPoints((
+                            (356.0, 180.0),
+                            (374.0, 220.0)))
+    GooCanvas.CanvasPolyline (parent=group, close_path=False,
+                       points=p_points,
+                       stroke_color="blue",
+                       line_width=1.0,
+                       start_arrow=True,
+                       end_arrow=True,
+                       arrow_tip_length=5.0,
+                       arrow_length=6.0,
+                       arrow_width=6.0)
+
+    GooCanvas.CanvasPolyline (parent=group, close_path=False,
+                       points=GooCanvas.CanvasPoints(((356.0, 220.0),)),
+                       start_arrow=True,
+                       end_arrow=True)
+    */
+};
+
+
+var setup_canvas = function(c) {
+    var root = c.get_root_item();
+    
+    // Test the simple commands like moveto and lineto: MmZzLlHhVv
+    new GooCanvas.CanvasPath({ parent:root, data:"M 20 20 L 40 40" });
+    new GooCanvas.CanvasPath({ parent:root, data:"M30 20 l20, 20"  });
+    new GooCanvas.CanvasPath({ parent:root, data:"M 60 20 H 80" });
+    new GooCanvas.CanvasPath({ parent:root, data:"M60 40 h20"});
+    new GooCanvas.CanvasPath({ parent:root, data:"M 100,20 V 40"});
+    
+    // Test empty
+    var p = new GooCanvas.CanvasPath({ parent: root, data:"" });
+    p.data = "M 120 20 v 20";
+    
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M 180 20 h20 v20 h-20 z m 5,5 h10 v10 h-10 z",
+        fill_color: "red",
+        //fill_rule: cairo.FILL_RULE_EVEN_ODD,
+    });
+    
+    new GooCanvas.CanvasPath({
+        parent:root,
+        data: "M 220 20 L 260 20 L 240 40 z",
+        fill_color: "red",
+        stroke_color: "blue",
+        line_width: 3.0
+    });
+    
+    //Test the bezier curve commands: CcSsQqTt.   
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M20,100 C20,50 100,50 100,100 S180,150 180,100"
+    });
+    
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M220,100 c0,-50 80,-50 80,0 s80,50 80,0"
+    });
+    
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M20,200 Q60,130 100,200 T180,200"
+    });
+    
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M220,200 q40,-70 80,0 t80,0"
+    });
+    
+    // Test the elliptical arc commands: Aa.
+    new GooCanvas.CanvasPath ({
+        parent: root,
+        data: "M200,500 h-150 a150,150 0 1,0 150,-150 z",
+        fill_color: "red",
+        stroke_color: "blue",
+        line_width: 5.0,
+    });
+    
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M175,475 v-150 a150,150 0 0,0 -150,150 z",
+        fill_color: "yellow",
+        stroke_color: "blue",
+        line_width: 5.0
+    });
+
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M400,600 l 50,-25 " +
+              "a25,25 -30 0,1 50,-25 l 50,-25" +
+              "a25,50 -30 0,1 50,-25 l 50,-25" +
+              "a25,75 -30 0,1 50,-25 l 50,-25" +
+              "a25,100 -30 0,1 50,-25 l 50,-25",
+        stroke_color: "red",
+        line_width: 5.0,
+    });
+
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M 725,75 a100,50 0 0,1 100,50",
+        stroke_color: "red",
+        line_width: 5.0,
+    });
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M 525,200 a100,50 0 1,0 100,50",
+        stroke_color: "red",
+        line_width: 5.0,
+    });
+    new GooCanvas.CanvasPath({
+        parent: root,
+        data: "M 725,200 a100,50 0 1,1 100,50",
+        stroke_color: "red",
+        line_width: 5.0,
+    });
+                  
+    var t = new GooCanvas.CanvasText ({
+        parent: root,
+        text: "Hello World!",
+        anchor: GooCanvas.CanvasAnchorType.CENTER
+    });
+};
+
+var setup_scalability = function(c) {
+    const N_COLS = 5;
+    const N_ROWS = 20;
+    const PADDING = 10;
+    
+    var vbox = new Gtk.VBox({homogeneous: false, spacing: 4});
+    vbox.set_border_width(4);
+    vbox.show();
+    
+    var table = new Gtk.Table.c_new(2, 2, false);
+    table.set_row_spacings(4);
+    table.set_col_spacings(4);
+    vbox.pack_start(table, true, true, 0);
+    table.show();
+    
+    var frame = new Gtk.Frame();
+    frame.set_shadow_type(Gtk.ShadowType.IN);
+    table.attach(frame, 0, 1, 0, 1,
+              Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK,
+              Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL | Gtk.AttachOptions.SHRINK,
+              0, 0);
+    frame.show();
+    
+    var pb;
+    var width;
+    var height;
+    
+    if (1) {
+        pb = new GdkPixbuf.Pixbuf.from_file("../../demo/toroid.png");
+        width = pb.get_width();
+        height = pb.get_height();
+    } else {
+        pb = null;
+        width = 37;
+        height = 19;
+    }
+    
+    c.set_bounds (
+            0, 0,
+            N_COLS * (width + PADDING),
+            N_ROWS * (height + PADDING));
+    c.show ();
+
+    var scrolled_win = new Gtk.ScrolledWindow();
+    scrolled_win.show()
+    frame.add(scrolled_win)
+    scrolled_win.add(c)
+
+    var root = c.get_root_item()
+    for (var i=0; i<N_COLS; i++) {
+        for (var j=0; j<N_ROWS; j++) {
+            if (pb) {
+                new GooCanvas.CanvasImage ({
+                            parent: root,
+                            pixbuf: pb,
+                            x: i * (width + PADDING),
+                            y: j * (height + PADDING) });
+            } else {
+                var item = new GooCanvas.CanvasRect ({
+                            parent: root,
+                            x: i * (width + PADDING),
+                            y: j * (height + PADDING),
+                            width: width,
+                            height: height});
+                item.fill_color = (j % 2 === 0) ? "mediumseagreen" : "steelblue";
+            }
+        }           
+    }
+
+    return vbox;
+}
+
+var setup_widget = function(c) {
+    var root = c.get_root_item();
+    
+    new GooCanvas.CanvasWidget({
+        parent: root,
+        widget: new Gtk.Label.c_new("Hello World"),
+        x: 50, y: 50, width: 200, height: 100
+    });
+    new GooCanvas.CanvasWidget({
+        parent: root,
+        widget: new Gtk.Entry(),
+        x: 50, y: 250, width: 200, height: 50
+    });
+    
+    var entry = new Gtk.Entry();
+    entry.set_text("Size: -1 x -1");
+    new GooCanvas.CanvasWidget({
+        parent: root,
+        widget: entry,
+        x: 50, y: 300, width: -1, height: -1
+    });
+    
+    entry = new Gtk.Entry();
+    entry.set_text("Size: 100 x -1");
+    new GooCanvas.CanvasWidget({
+        parent: root,
+        widget: entry,
+        x:50, y: 350, width: 100, height: -1
+    });
+}
+
+
+var demo_window = function(setup_func) {
+    var c = new GooCanvas.Canvas();
+    c.set_size_request(600, 450);
+    var widget = setup_func(c);
+    if (!widget) {
+        widget = c;
+    }
+    var w = new Gtk.Window();
+    w.set_size_request(600, 450);
+    w.add(widget);
+    w.show_all();
+    w.signal.destroy.connect(Gtk.main_quit);
+}
+
+Gtk.init(null, null);
+
+demo_window(setup_canvas);
+demo_window(setup_polyline);
+demo_window(setup_scalability);
+demo_window(setup_widget);
+
+Gtk.main()
diff --git a/configure.in b/configure.in
index 83bb875..d94c504 100644
--- a/configure.in
+++ b/configure.in
@@ -26,6 +26,10 @@ AC_PROG_CC
 AC_HEADER_STDC
 AM_PROG_LIBTOOL
 
+m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
+
+PYGOBJECT_REQUIRED=2.28
+
 pkg_modules="gtk+-3.0 >= 3.0.0 glib-2.0 >= 2.28.0 cairo >= 1.10.0"
 PKG_CHECK_MODULES(PACKAGE, [$pkg_modules])
 AC_SUBST(PACKAGE_CFLAGS)
@@ -45,6 +49,8 @@ AC_SUBST(GLIB_GENMARSHAL)
 GLIB_MKENUMS=`$PKG_CONFIG --variable=glib_mkenums glib-2.0`
 AC_SUBST(GLIB_MKENUMS)
 
+GOBJECT_INTROSPECTION_CHECK([0.6.7])
+
 AC_ARG_ENABLE(rebuilds,
               [AC_HELP_STRING([--disable-rebuilds],
                               [disable all source autogeneration rules])],,
@@ -73,6 +79,27 @@ esac
 AC_MSG_RESULT([$platform_win32])
 AM_CONDITIONAL(PLATFORM_WIN32, test "$platform_win32" = "yes")
 
+AM_PATH_PYTHON
+
+AC_ARG_ENABLE([python],
+              AS_HELP_STRING([--enable-python[=@<:@no/auto/yes@:>@]],[Build with python support]),
+              [enable_python=$enableval],
+              [enable_python="auto"])
+
+if test "x$enable_python" = "xauto"; then
+	PKG_CHECK_EXISTS([pygobject-2.0 >= $PYGOBJECT_REQUIRED],
+	                 [enable_python=yes],[enable_python=no])
+fi
+
+if test "x$enable_python" = "xyes"; then
+	PKG_CHECK_MODULES(PYTHON, [pygobject-2.0 >= $PYGOBJECT_REQUIRED])
+
+	pyoverridesdir=`$PKG_CONFIG --variable=overridesdir pygobject-2.0`
+	AC_SUBST(pyoverridesdir)
+fi
+
+AM_CONDITIONAL(ENABLE_PYTHON, test x"$enable_python" = "xyes")
+
 GTK_DOC_CHECK(1.8)
 
 AC_OUTPUT([
@@ -80,6 +107,8 @@ Makefile
 src/Makefile
 demo/Makefile
 docs/Makefile
+bindings/Makefile
+bindings/python/Makefile
 po/Makefile.in
 goocanvas-2.0.pc
 ])
diff --git a/src/Makefile.am b/src/Makefile.am
index 4fb8f25..6b856e5 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -143,3 +143,29 @@ CLEANFILES = $(gen_sources)
 BUILT_SOURCES = $(libgoocanvas_built_headers) $(libgoocanvas_built_sources)
 MAINTAINERCLEANFILES = $(BUILT_SOURCES) $(stamp_files)
 EXTRA_DIST = $(BUILT_SOURCES) $(libgoocanvas_extra_sources)
+
+-include $(INTROSPECTION_MAKEFILE)
+INTROSPECTION_GIRS =
+INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir)
+INTROSPECTION_COMPILER_ARGS = --includedir=$(srcdir)
+
+if HAVE_INTROSPECTION
+introspection_sources = $(libgoocanvas_2_0_la_SOURCES) $(libgoocanvasinclude_HEADERS)
+
+GooCanvas-2.0.gir: libgoocanvas-2.0.la
+GooCanvas_2_0_gir_SCANNERFLAGS = --identifier-prefix=Goo --symbol-prefix=goo --warn-all
+GooCanvas_2_0_gir_INCLUDES = Gtk-3.0
+GooCanvas_2_0_gir_CFLAGS = $(INCLUDES)
+GooCanvas_2_0_gir_LIBS = goocanvas-2.0
+GooCanvas_2_0_gir_FILES = $(introspection_sources)
+INTROSPECTION_GIRS += GooCanvas-2.0.gir
+
+girdir = $(datadir)/gir-1.0
+gir_DATA = $(INTROSPECTION_GIRS)
+
+typelibdir = $(libdir)/girepository-1.0
+typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+
+CLEANFILES += $(gir_DATA) $(typelib_DATA)
+endif
+
diff --git a/src/goocanvas.c b/src/goocanvas.c
index cc70963..7d5ece1 100644
--- a/src/goocanvas.c
+++ b/src/goocanvas.c
@@ -122,6 +122,7 @@ enum {
   PROP_RESOLUTION_Y,
   PROP_BACKGROUND_COLOR,
   PROP_BACKGROUND_COLOR_RGB,
+  PROP_BACKGROUND_COLOR_GDK_RGBA,
   PROP_INTEGER_LAYOUT, 
   PROP_CLEAR_BACKGROUND,
   PROP_REDRAW_WHEN_SCROLLED,
@@ -131,6 +132,8 @@ enum {
   PROP_VSCROLL_POLICY
 };
 
+static const double GOO_CANVAS_MM_PER_INCH =  25.4;
+static const double GOO_CANVAS_POINTS_PER_INCH = 72.0;
 
 static void     goo_canvas_dispose	   (GObject          *object);
 static void     goo_canvas_finalize	   (GObject          *object);
@@ -392,6 +395,20 @@ goo_canvas_class_init (GooCanvasClass *klass)
 						      0, G_MAXUINT, 0,
 						      G_PARAM_WRITABLE));
 
+  /**
+   * GooCanvas:background-color-gdk-rgba
+   *
+   * The color to use for the canvas background, specified as a GdkRGBA.
+   *
+   * Since: 2.0.1
+   */
+  g_object_class_install_property (gobject_class, PROP_BACKGROUND_COLOR_GDK_RGBA,
+                                   g_param_spec_boxed ("background-color-gdk-rgba",
+                                                       _("Background Color GdkRGBA"),
+                                                       _("The color to use for the canvas background, specified as a GdkRGBA"),
+                                                       GDK_TYPE_RGBA,
+                                                       G_PARAM_WRITABLE));
+
   g_object_class_install_property (gobject_class, PROP_INTEGER_LAYOUT,
                                    g_param_spec_boolean ("integer-layout",
 							 _("Integer Layout"),
@@ -583,7 +600,7 @@ goo_canvas_get_default_line_width (GooCanvas *canvas)
       line_width = 2.0;
       break;
     case GTK_UNIT_INCH:
-      line_width = 2.0 / 72.0;
+      line_width = 2.0 / GOO_CANVAS_POINTS_PER_INCH;
       break;
     case GTK_UNIT_MM:
       line_width = 0.7;
@@ -767,6 +784,8 @@ goo_canvas_set_property    (GObject            *object,
   gboolean need_reconfigure = FALSE;
   gboolean need_update_automatic_bounds = FALSE;
   guint rgb;
+  GdkRGBA rgba = { 0, 0, 0, 0 };
+  const char *color_string;
 
   switch (prop_id)
     {
@@ -829,12 +848,13 @@ goo_canvas_set_property    (GObject            *object,
       need_reconfigure = TRUE;
       break;
     case PROP_BACKGROUND_COLOR:
-      if (!g_value_get_string (value))
-	gtk_widget_modify_bg ((GtkWidget*) canvas, GTK_STATE_NORMAL, NULL);
-      else if (gdk_color_parse (g_value_get_string (value), &color))
-	gtk_widget_modify_bg ((GtkWidget*) canvas, GTK_STATE_NORMAL, &color);
+      color_string = g_value_get_string (value);
+      if (!color_string)
+	gtk_widget_override_background_color ((GtkWidget*) canvas, GTK_STATE_FLAG_NORMAL, NULL);
+      else if (gdk_rgba_parse (&rgba, color_string))
+        gtk_widget_override_background_color ((GtkWidget*) canvas, GTK_STATE_FLAG_NORMAL, &rgba);
       else
-	g_warning ("Unknown color: %s", g_value_get_string (value));
+	g_warning ("Unknown color: %s", color_string);
       break;
     case PROP_BACKGROUND_COLOR_RGB:
       rgb = g_value_get_uint (value);
@@ -843,6 +863,9 @@ goo_canvas_set_property    (GObject            *object,
       color.blue  = ((rgb)       & 0xFF) * 257;
       gtk_widget_modify_bg ((GtkWidget*) canvas, GTK_STATE_NORMAL, &color);
       break;
+    case PROP_BACKGROUND_COLOR_GDK_RGBA:
+      gtk_widget_override_background_color ((GtkWidget*) canvas, GTK_STATE_FLAG_NORMAL, g_value_get_boxed (value));
+      break;
     case PROP_INTEGER_LAYOUT:
       canvas->integer_layout = g_value_get_boolean (value);
       canvas->need_entire_subtree_update = TRUE;
@@ -893,7 +916,7 @@ goo_canvas_set_property    (GObject            *object,
  * 
  * Gets the root item of the canvas, usually a #GooCanvasGroup.
  * 
- * Returns: the root item, or %NULL if there is no root item.
+ * Returns: (transfer none): the root item, or %NULL if there is no root item.
  **/
 GooCanvasItem*
 goo_canvas_get_root_item (GooCanvas     *canvas)
@@ -949,7 +972,7 @@ goo_canvas_set_root_item    (GooCanvas		*canvas,
  * Static items are added to the static root item in exactly the same way that
  * ordinary items are added to the root item.
  *
- * Returns: the static root item, or %NULL.
+ * Returns: (transfer none): the static root item, or %NULL.
  **/
 GooCanvasItem*
 goo_canvas_get_static_root_item    (GooCanvas		*canvas)
@@ -1010,7 +1033,8 @@ goo_canvas_set_static_root_item    (GooCanvas		*canvas,
  * 
  * Gets the item at the given point.
  * 
- * Returns: the item found at the given point, or %NULL if no item was found.
+ * Returns: (transfer none): the item found at the given point, or %NULL if no
+ *  item was found.
  **/
 GooCanvasItem*
 goo_canvas_get_item_at (GooCanvas     *canvas,
@@ -1062,9 +1086,9 @@ goo_canvas_get_item_at (GooCanvas     *canvas,
  * 
  * Gets all items at the given point.
  * 
- * Returns: a list of items found at the given point, with the top item at
- *  the start of the list, or %NULL if no items were found. The list must be
- *  freed with g_list_free().
+ * Returns: (element-type GooCanvas.CanvasItem) (transfer container): a list of
+ *  items found at the given point, with the top item at the start of the list, 
+ *  or %NULL if no items were found. The list must be freed with g_list_free().
  **/
 GList*
 goo_canvas_get_items_at (GooCanvas     *canvas,
@@ -1176,7 +1200,8 @@ goo_canvas_get_items_in_area_recurse (GooCanvas		    *canvas,
  * 
  * Gets a list of items inside or outside a given area.
  * 
- * Returns: a list of items in the given area, or %NULL if no items are found.
+ * Returns: (element-type GooCanvas.CanvasItem) (transfer container): a list of
+ *  items in the given area, or %NULL if no items are found.
  *  The list should be freed with g_list_free().
  **/
 GList*
@@ -1467,32 +1492,45 @@ goo_canvas_configure_vadjustment (GooCanvas *canvas,
 
 
 static void
-recalculate_scales (GooCanvas *canvas)
+units_to_pixels_ratios (GooCanvas *canvas,
+			gdouble   *x_ratio,
+			gdouble   *y_ratio)
 {
   switch (canvas->units)
     {
     case GTK_UNIT_PIXEL:
-      canvas->device_to_pixels_x = canvas->scale_x;
-      canvas->device_to_pixels_y = canvas->scale_y;
+      *x_ratio = 1.0;
+      *y_ratio = *x_ratio;
       break;
     case GTK_UNIT_POINTS:
-      canvas->device_to_pixels_x = canvas->scale_x * (canvas->resolution_x / 72.0);
-      canvas->device_to_pixels_y = canvas->scale_y * (canvas->resolution_y / 72.0);
+      *x_ratio = canvas->resolution_x / GOO_CANVAS_POINTS_PER_INCH;
+      *y_ratio = canvas->resolution_y / GOO_CANVAS_POINTS_PER_INCH;
       break;
     case GTK_UNIT_INCH:
-      canvas->device_to_pixels_x = canvas->scale_x * canvas->resolution_x;
-      canvas->device_to_pixels_y = canvas->scale_y * canvas->resolution_y;
+      *x_ratio = canvas->resolution_x;
+      *y_ratio = canvas->resolution_y;
       break;
     case GTK_UNIT_MM:
-      /* There are 25.4 mm to an inch. */
-      canvas->device_to_pixels_x = canvas->scale_x * (canvas->resolution_x / 25.4);
-      canvas->device_to_pixels_y = canvas->scale_y * (canvas->resolution_y / 25.4);
+      *x_ratio = canvas->resolution_x / GOO_CANVAS_MM_PER_INCH;
+      *y_ratio = canvas->resolution_y / GOO_CANVAS_MM_PER_INCH;
       break;
     }
 }
 
 
 static void
+recalculate_scales (GooCanvas *canvas)
+{
+  gdouble x_ratio = 0;
+  gdouble y_ratio = 0;
+  units_to_pixels_ratios (canvas, &x_ratio, &y_ratio);
+ 
+  canvas->device_to_pixels_x = canvas->scale_x * x_ratio;
+  canvas->device_to_pixels_y = canvas->scale_y * y_ratio;
+}
+
+
+static void
 request_static_redraw (GooCanvas             *canvas,
 		       const GooCanvasBounds *bounds)
 {
@@ -2485,6 +2523,24 @@ goo_canvas_draw (GtkWidget      *widget,
  * have their visibility set to %GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD.
  * 
  * Renders all or part of a canvas to the given cairo context.
+ *
+ * This example code could be used in a #GtkPrintOperation
+ * #GtkPrintOperation::draw-page callback to print each page in a multi-page
+ * document (assuming the pages appear one after the other vertically in the
+ * canvas). Note the call to cairo_translate() to translate the output to
+ * the correct position on the printed page.
+ *
+ * <informalexample><programlisting>
+ *    GooCanvasBounds bounds;
+ *    bounds.x1 = 0;
+ *    bounds.x2 = A4_PAGE_WIDTH;
+ *    bounds.y1 = A4_PAGE_HEIGHT * page_num;
+ *    bounds.y2 = A4_PAGE_HEIGHT * (page_num + 1);
+ *
+ *    cr = gtk_print_context_get_cairo_context (print_context);
+ *    cairo_translate (cr, 0, -A4_PAGE_HEIGHT * page_num);
+ *    goo_canvas_render (GOO_CANVAS (canvas), cr, &bounds, 0.0);
+ * </programlisting></informalexample>
  **/
 void
 goo_canvas_render (GooCanvas             *canvas,
@@ -3268,8 +3324,8 @@ goo_canvas_keyboard_ungrab (GooCanvas     *canvas,
 /**
  * goo_canvas_convert_to_pixels:
  * @canvas: a #GooCanvas.
- * @x: a pointer to the x coordinate to convert.
- * @y: a pointer to the y coordinate to convert.
+ * @x: (inout): a pointer to the x coordinate to convert.
+ * @y: (inout): a pointer to the y coordinate to convert.
  * 
  * Converts a coordinate from the canvas coordinate space to pixels.
  *
@@ -3293,8 +3349,8 @@ goo_canvas_convert_to_pixels (GooCanvas     *canvas,
 /**
  * goo_canvas_convert_from_pixels:
  * @canvas: a #GooCanvas.
- * @x: a pointer to the x coordinate to convert.
- * @y: a pointer to the y coordinate to convert.
+ * @x: (inout): a pointer to the x coordinate to convert.
+ * @y: (inout): a pointer to the y coordinate to convert.
  * 
  * Converts a coordinate from pixels to the canvas coordinate space.
  *
@@ -3315,6 +3371,56 @@ goo_canvas_convert_from_pixels (GooCanvas     *canvas,
   *y = ((*y - canvas->canvas_y_offset) / canvas->device_to_pixels_y) + canvas->bounds.y1;
 }
 
+/**
+ * goo_canvas_convert_units_to_pixels:
+ * @canvas: a #GooCanvas.
+ * @x: (inout): a pointer to the x coordinate to convert.
+ * @y: (inout): a pointer to the y coordinate to convert.
+ *
+ * Converts a coordinate from the canvas's units to pixels,
+ * ignoring scaling and ignoring the coordinate space specified
+ * in the call to goo_canvas_set_bounds().
+ *
+ * Since: 2.0.1
+ **/
+void
+goo_canvas_convert_units_to_pixels (GooCanvas     *canvas,
+			      gdouble       *x,
+			      gdouble       *y)
+{
+  gdouble x_ratio = 0;
+  gdouble y_ratio = 0;
+  units_to_pixels_ratios (canvas, &x_ratio, &y_ratio);
+ 
+  *x = *x * x_ratio;
+  *y = *y * y_ratio;
+}
+
+
+/**
+ * goo_canvas_convert_units_from_pixels:
+ * @canvas: a #GooCanvas.
+ * @x: (inout): a pointer to the x coordinate to convert.
+ * @y: (inout): a pointer to the y coordinate to convert.
+ *
+ * Converts a coordinate from pixels to the canvas's units,
+ * ignoring scaling and ignoring the coordinate space specified
+ * in the call to goo_canvas_set_bounds().
+ *
+ * Since: 2.0.1
+ **/
+void
+goo_canvas_convert_units_from_pixels (GooCanvas     *canvas,
+				gdouble       *x,
+				gdouble       *y)
+{
+  gdouble x_ratio = 0;
+  gdouble y_ratio = 0;
+  units_to_pixels_ratios (canvas, &x_ratio, &y_ratio);
+ 
+  *x = *x / x_ratio;
+  *y = *y / y_ratio;
+}
 
 static void
 goo_canvas_convert_from_window_pixels (GooCanvas     *canvas,
@@ -3380,8 +3486,8 @@ get_transform_to_item_space (GooCanvasItem  *item,
  * goo_canvas_convert_to_item_space:
  * @canvas: a #GooCanvas.
  * @item: a #GooCanvasItem.
- * @x: a pointer to the x coordinate to convert.
- * @y: a pointer to the y coordinate to convert.
+ * @x: (inout): a pointer to the x coordinate to convert.
+ * @y: (inout): a pointer to the y coordinate to convert.
  * 
  * Converts a coordinate from the canvas coordinate space to the given
  * item's coordinate space, applying all transformation matrices including the
@@ -3404,8 +3510,8 @@ goo_canvas_convert_to_item_space (GooCanvas     *canvas,
  * goo_canvas_convert_from_item_space:
  * @canvas: a #GooCanvas.
  * @item: a #GooCanvasItem.
- * @x: a pointer to the x coordinate to convert.
- * @y: a pointer to the y coordinate to convert.
+ * @x: (inout): a pointer to the x coordinate to convert.
+ * @y: (inout): a pointer to the y coordinate to convert.
  * 
  * Converts a coordinate from the given item's coordinate space to the canvas
  * coordinate space, applying all transformation matrices including the
diff --git a/src/goocanvas.h b/src/goocanvas.h
index 18a2b11..56d8441 100644
--- a/src/goocanvas.h
+++ b/src/goocanvas.h
@@ -258,6 +258,13 @@ void		goo_canvas_convert_from_pixels	   (GooCanvas       *canvas,
 						    gdouble         *x,
 						    gdouble         *y);
 
+void goo_canvas_convert_units_to_pixels (GooCanvas *canvas,
+						    gdouble         *x,
+						    gdouble         *y);
+void goo_canvas_convert_units_from_pixels (GooCanvas *canvas,
+						    gdouble         *x,
+						    gdouble         *y);
+
 void		goo_canvas_convert_to_item_space   (GooCanvas	    *canvas,
 						    GooCanvasItem   *item,
 						    gdouble         *x,
diff --git a/src/goocanvasellipse.c b/src/goocanvasellipse.c
index e7ec438..f7966ee 100644
--- a/src/goocanvasellipse.c
+++ b/src/goocanvasellipse.c
@@ -62,7 +62,7 @@ goo_canvas_ellipse_init (GooCanvasEllipse *ellipse)
 
 /**
  * goo_canvas_ellipse_new:
- * @parent: the parent item, or %NULL. If a parent is specified, it will assume
+ * @parent: (skip): the parent item, or %NULL. If a parent is specified, it will assume
  *  ownership of the item, and the item will automatically be freed when it is
  *  removed from the parent. Otherwise call g_object_unref() to free it.
  * @center_x: the x coordinate of the center of the ellipse.
@@ -87,7 +87,7 @@ goo_canvas_ellipse_init (GooCanvasEllipse *ellipse)
  *                                                   NULL);
  * </programlisting></informalexample>
  * 
- * Returns: a new ellipse item.
+ * Returns: (transfer full): a new ellipse item.
  **/
 GooCanvasItem*
 goo_canvas_ellipse_new (GooCanvasItem *parent,
diff --git a/src/goocanvasgrid.c b/src/goocanvasgrid.c
index 7f12a54..0c18e71 100644
--- a/src/goocanvasgrid.c
+++ b/src/goocanvasgrid.c
@@ -80,12 +80,15 @@ enum {
   /* Convenience properties. */
   PROP_HORZ_GRID_LINE_COLOR,
   PROP_HORZ_GRID_LINE_COLOR_RGBA,
+  PROP_HORZ_GRID_LINE_COLOR_GDK_RGBA,
   PROP_HORZ_GRID_LINE_PIXBUF,
   PROP_VERT_GRID_LINE_COLOR,
   PROP_VERT_GRID_LINE_COLOR_RGBA,
+  PROP_VERT_GRID_LINE_COLOR_GDK_RGBA,
   PROP_VERT_GRID_LINE_PIXBUF,
   PROP_BORDER_COLOR,
   PROP_BORDER_COLOR_RGBA,
+  PROP_BORDER_COLOR_GDK_RGBA,
   PROP_BORDER_PIXBUF
 };
 
@@ -118,7 +121,7 @@ goo_canvas_grid_init (GooCanvasGrid *grid)
 
 /**
  * goo_canvas_grid_new:
- * @parent: the parent item, or %NULL. If a parent is specified, it will assume
+ * @parent: (skip): the parent item, or %NULL. If a parent is specified, it will assume
  *  ownership of the item, and the item will automatically be freed when it is
  *  removed from the parent. Otherwise call g_object_unref() to free it.
  * @x: the x coordinate of the left of the grid.
@@ -150,7 +153,7 @@ goo_canvas_grid_init (GooCanvasGrid *grid)
  *                                             NULL);
  * </programlisting></informalexample>
  * 
- * Returns: a new grid item.
+ * Returns: (transfer full): a new grid item.
  **/
 GooCanvasItem*
 goo_canvas_grid_new (GooCanvasItem      *parent,
@@ -263,12 +266,21 @@ goo_canvas_grid_get_property (GObject              *object,
     case PROP_HORZ_GRID_LINE_COLOR_RGBA:
       goo_canvas_get_rgba_value_from_pattern (grid->horz_grid_line_pattern, value);
       break;
+    case PROP_HORZ_GRID_LINE_COLOR_GDK_RGBA:
+      goo_canvas_get_gdk_rgba_value_from_pattern (grid->horz_grid_line_pattern, value);
+      break;
     case PROP_VERT_GRID_LINE_COLOR_RGBA:
       goo_canvas_get_rgba_value_from_pattern (grid->vert_grid_line_pattern, value);
       break;
+    case PROP_VERT_GRID_LINE_COLOR_GDK_RGBA:
+      goo_canvas_get_gdk_rgba_value_from_pattern (grid->vert_grid_line_pattern, value);
+      break;
     case PROP_BORDER_COLOR_RGBA:
       goo_canvas_get_rgba_value_from_pattern (grid->border_pattern, value);
       break;
+    case PROP_BORDER_COLOR_GDK_RGBA:
+      goo_canvas_get_gdk_rgba_value_from_pattern (grid->border_pattern, value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -354,6 +366,10 @@ goo_canvas_grid_set_property (GObject              *object,
       cairo_pattern_destroy (grid->horz_grid_line_pattern);
       grid->horz_grid_line_pattern = goo_canvas_create_pattern_from_rgba_value (value);
       break;
+    case PROP_HORZ_GRID_LINE_COLOR_GDK_RGBA:
+      cairo_pattern_destroy (grid->horz_grid_line_pattern);
+      grid->horz_grid_line_pattern = goo_canvas_create_pattern_from_gdk_rgba_value (value);
+      break;
     case PROP_HORZ_GRID_LINE_PIXBUF:
       cairo_pattern_destroy (grid->horz_grid_line_pattern);
       grid->horz_grid_line_pattern = goo_canvas_create_pattern_from_pixbuf_value (value);
@@ -367,6 +383,10 @@ goo_canvas_grid_set_property (GObject              *object,
       cairo_pattern_destroy (grid->vert_grid_line_pattern);
       grid->vert_grid_line_pattern = goo_canvas_create_pattern_from_rgba_value (value);
       break;
+    case PROP_VERT_GRID_LINE_COLOR_GDK_RGBA:
+      cairo_pattern_destroy (grid->vert_grid_line_pattern);
+      grid->vert_grid_line_pattern = goo_canvas_create_pattern_from_gdk_rgba_value (value);
+      break;
     case PROP_VERT_GRID_LINE_PIXBUF:
       cairo_pattern_destroy (grid->vert_grid_line_pattern);
       grid->vert_grid_line_pattern = goo_canvas_create_pattern_from_pixbuf_value (value);
@@ -380,6 +400,10 @@ goo_canvas_grid_set_property (GObject              *object,
       cairo_pattern_destroy (grid->border_pattern);
       grid->border_pattern = goo_canvas_create_pattern_from_rgba_value (value);
       break;
+    case PROP_BORDER_COLOR_GDK_RGBA:
+      cairo_pattern_destroy (grid->border_pattern);
+      grid->border_pattern = goo_canvas_create_pattern_from_gdk_rgba_value (value);
+      break;
     case PROP_BORDER_PIXBUF:
       cairo_pattern_destroy (grid->border_pattern);
       grid->border_pattern = goo_canvas_create_pattern_from_pixbuf_value (value);
@@ -773,6 +797,20 @@ goo_canvas_grid_class_init (GooCanvasGridClass *klass)
 						      0, G_MAXUINT, 0,
 						      G_PARAM_READWRITE));
 
+  /**
+   * GooCanvasGrid:horz-grid-line-color-gdk-rgba
+   *
+   * The color to use for the horizontal grid lines, specified as a GdkRGBA.
+   *
+   * Since: 2.0.1
+   */
+  g_object_class_install_property (gobject_class, PROP_HORZ_GRID_LINE_COLOR_GDK_RGBA,
+                                   g_param_spec_boxed ("horz-grid-line-color-gdk-rgba",
+                                                       _("Horizontal Grid Line Color GdkRGBA"),
+                                                       _("The color to use for the horizontal grid lines, specified as a GdkRGBA"),
+                                                       GDK_TYPE_RGBA,
+                                                       G_PARAM_READWRITE));
+
   g_object_class_install_property (gobject_class, PROP_HORZ_GRID_LINE_PIXBUF,
                                    g_param_spec_object ("horz-grid-line-pixbuf",
 							_("Horizontal Grid Line Pixbuf"),
@@ -794,6 +832,20 @@ goo_canvas_grid_class_init (GooCanvasGridClass *klass)
 						      0, G_MAXUINT, 0,
 						      G_PARAM_READWRITE));
 
+  /**
+   * GooCanvasGrid:vert-grid-line-color-gdk-rgba
+   *
+   * The color to use for the vertical grid lines, specified as a GdkRGBA.
+   *
+   * Since: 2.0.1
+   */
+  g_object_class_install_property (gobject_class, PROP_VERT_GRID_LINE_COLOR_GDK_RGBA,
+                                   g_param_spec_boxed ("vert-grid-line-color-gdk-rgba",
+                                                       _("Vertical Grid Line Color GdkRGBA"),
+                                                       _("The color to use for the vertical grid lines, specified as a GdkRGBA"),
+                                                       GDK_TYPE_RGBA,
+                                                       G_PARAM_READWRITE));
+
   g_object_class_install_property (gobject_class, PROP_VERT_GRID_LINE_PIXBUF,
                                    g_param_spec_object ("vert-grid-line-pixbuf",
 							_("Vertical Grid Line Pixbuf"),
@@ -815,6 +867,20 @@ goo_canvas_grid_class_init (GooCanvasGridClass *klass)
 						      0, G_MAXUINT, 0,
 						      G_PARAM_READWRITE));
 
+  /**
+   * GooCanvasGrid:border-color-gdk-rgba
+   *
+   * The color to use for the border, specified as a GdkRGBA.
+   *
+   * Since: 2.0.1
+   */
+  g_object_class_install_property (gobject_class, PROP_BORDER_COLOR_GDK_RGBA,
+                                   g_param_spec_boxed ("border-color-gdk-rgba",
+                                                       _("Border Color GdkRGBA"),
+                                                       _("The color to use for the border, specified as a GdkRGBA"),
+                                                       GDK_TYPE_RGBA,
+                                                       G_PARAM_READWRITE));
+
   g_object_class_install_property (gobject_class, PROP_BORDER_PIXBUF,
                                    g_param_spec_object ("border-pixbuf",
 							_("Border Pixbuf"),
diff --git a/src/goocanvasgroup.c b/src/goocanvasgroup.c
index 69712b3..ab5c8ab 100644
--- a/src/goocanvasgroup.c
+++ b/src/goocanvasgroup.c
@@ -68,14 +68,14 @@ goo_canvas_group_init (GooCanvasGroup *group)
 
 /**
  * goo_canvas_group_new:
- * @parent: the parent item, or %NULL. If a parent is specified, it will assume
+ * @parent: (skip): the parent item, or %NULL. If a parent is specified, it will assume
  *  ownership of the item, and the item will automatically be freed when it is
  *  removed from the parent. Otherwise call g_object_unref() to free it.
  * @...: optional pairs of property names and values, and a terminating %NULL.
  * 
  * Creates a new group item.
  * 
- * Return value: a new group item.
+ * Return value: (transfer full): a new group item.
  **/
 GooCanvasItem*
 goo_canvas_group_new (GooCanvasItem *parent,
diff --git a/src/goocanvasimage.c b/src/goocanvasimage.c
index fcc2a2c..6120297 100644
--- a/src/goocanvasimage.c
+++ b/src/goocanvasimage.c
@@ -12,6 +12,11 @@
  *
  * GooCanvasImage represents an image item.
  *
+ * <note><para>
+ * It is usually necessary to set the "scale-to-fit" property to %TRUE to
+ * scale the image to fit the given rectangle.
+ * </para></note>
+ *
  * It is a subclass of #GooCanvasItemSimple and so inherits all of the style
  * properties such as "operator" and "pointer-events".
  *
@@ -59,12 +64,36 @@ goo_canvas_image_init (GooCanvasImage *image)
 }
 
 
+/*
+ * Convert the width and height to the canvas's units, from the pixbuf's size 
+ * in pixels.
+ */
+static void
+goo_canvas_image_convert_pixbuf_sizes (GooCanvasImage *image)
+{
+  const double original_width = image->width;
+  
+  GooCanvas *canvas = goo_canvas_item_get_canvas (GOO_CANVAS_ITEM (item));
+  if (canvas)
+    {
+      goo_canvas_convert_units_from_pixels (canvas, 
+					    &(image->width),
+					    &(image->height));
+    }
+    
+  if (image->width) /* Avoid division by zero. */
+    image->scale_to_units = original_width / image->width;
+  else
+    image->scale_to_units = 1.0f;
+}
+
+
 /**
  * goo_canvas_image_new:
- * @parent: the parent item, or %NULL. If a parent is specified, it will assume
+ * @parent: (skip): the parent item, or %NULL. If a parent is specified, it will assume
  *  ownership of the item, and the item will automatically be freed when it is
  *  removed from the parent. Otherwise call g_object_unref() to free it.
- * @pixbuf: the #GdkPixbuf containing the image data, or %NULL.
+ * @pixbuf: (allow-none): the #GdkPixbuf containing the image data, or %NULL.
  * @x: the x coordinate of the image.
  * @y: the y coordinate of the image.
  * @...: optional pairs of property names and values, and a terminating %NULL.
@@ -81,7 +110,17 @@ goo_canvas_image_init (GooCanvasImage *image)
  *                                               NULL);
  * </programlisting></informalexample>
  *
- * Returns: a new image item.
+ * This example creates an image scaled to a size of 200x200:
+ *
+ * <informalexample><programlisting>
+ *  GooCanvasItem *image = goo_canvas_image_new (mygroup, pixbuf, 100.0, 100.0,
+ *                                               "width", 200.0,
+ *                                               "height", 200.0,
+ *                                               "scale-to-fit", TRUE,
+ *                                               NULL);
+ * </programlisting></informalexample>
+ *
+ * Returns: (transfer full): a new image item.
  **/
 GooCanvasItem*
 goo_canvas_image_new (GooCanvasItem *parent,
@@ -96,6 +135,16 @@ goo_canvas_image_new (GooCanvasItem *parent,
   va_list var_args;
 
   item = g_object_new (GOO_TYPE_CANVAS_IMAGE, NULL);
+
+  /* Put it in the parent first because other property setters might need
+   * access to the parent.
+   */  
+  if (parent)
+    {
+      goo_canvas_item_add_child (parent, item, -1);
+      g_object_unref (item);
+    }
+
   image = (GooCanvasImage*) item;
 
   image->x = x;
@@ -106,6 +155,8 @@ goo_canvas_image_new (GooCanvasItem *parent,
       image->pattern = goo_canvas_cairo_pattern_from_pixbuf (pixbuf);
       image->width = gdk_pixbuf_get_width (pixbuf);
       image->height = gdk_pixbuf_get_height (pixbuf);
+
+      goo_canvas_image_convert_pixbuf_sizes (image);
     }
 
   va_start (var_args, y);
@@ -114,12 +165,6 @@ goo_canvas_image_new (GooCanvasItem *parent,
     g_object_set_valist ((GObject*) item, first_property, var_args);
   va_end (var_args);
 
-  if (parent)
-    {
-      goo_canvas_item_add_child (parent, item, -1);
-      g_object_unref (item);
-    }
-
   return item;
 }
 
@@ -213,6 +258,7 @@ goo_canvas_image_set_property (GObject              *object,
       image->pattern = pixbuf ? goo_canvas_cairo_pattern_from_pixbuf (pixbuf) : NULL;
       image->width = pixbuf ? gdk_pixbuf_get_width (pixbuf) : 0;
       image->height = pixbuf ? gdk_pixbuf_get_height (pixbuf) : 0;
+      goo_canvas_image_convert_pixbuf_sizes (image);
       break;
     case PROP_ALPHA:
       image->alpha = g_value_get_double (value);
@@ -273,6 +319,9 @@ goo_canvas_image_paint (GooCanvasItemSimple   *simple,
     return;
 
 #if 1
+
+  /* scale-to-fit means a simple scale, not keeping the aspect ratio.
+     This does not need to consider the units used. */ 
   if (image->scale_to_fit)
     {
       if (cairo_pattern_get_surface (image->pattern, &surface)
@@ -284,8 +333,20 @@ goo_canvas_image_paint (GooCanvasItemSimple   *simple,
 	  cairo_matrix_scale (&matrix, width / image->width,
 			      height / image->height);
 	}
+    } else if (priv->scale_to_units && (priv->scale_to_units != 1.0f))
+   {
+      /* Scale the image to fit the size in units.
+         We have already scaled the width and height numbers. */
+      if (cairo_pattern_get_surface (image_data->pattern, &surface)
+	  == CAIRO_STATUS_SUCCESS
+	  && cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE)
+	{
+	  cairo_matrix_scale (&matrix, priv->scale_to_units,
+			      priv->scale_to_units);
+	}
     }
 
+
   cairo_matrix_translate (&matrix, -image->x, -image->y);
 
   cairo_pattern_set_matrix (image->pattern, &matrix);
diff --git a/src/goocanvasimage.h b/src/goocanvasimage.h
index c95ae37..e51633d 100644
--- a/src/goocanvasimage.h
+++ b/src/goocanvasimage.h
@@ -37,6 +37,7 @@ struct _GooCanvasImage
 
   gdouble x, y, width, height;
   gdouble alpha;
+  gdouble scale_to_units; /* How much to scale the image when the units are not pixels. */
   gboolean scale_to_fit;
 };
 
diff --git a/src/goocanvasitem.c b/src/goocanvasitem.c
index 2599965..880437d 100644
--- a/src/goocanvasitem.c
+++ b/src/goocanvasitem.c
@@ -369,7 +369,7 @@ goo_canvas_item_class_init (GooCanvasItemClass *klass)
   /**
    * GooCanvasItem::child-notify
    * @item: the item that received the signal.
-   * @pspec: the #GParamSpec of the changed child property.
+   * @pspec: (type GLib.ParamSpec): the #GParamSpec of the changed child property.
    *
    * Emitted for each child property that has changed.
    * The signal's detail holds the property name. 
@@ -443,7 +443,7 @@ goo_canvas_item_init (GooCanvasItem *canvas_item)
  * 
  * Returns the #GooCanvas containing the given #GooCanvasItem.
  * 
- * Returns: the #GooCanvas.
+ * Returns: (transfer none): the #GooCanvas.
  **/
 GooCanvas*
 goo_canvas_item_get_canvas (GooCanvasItem *item)
@@ -618,8 +618,8 @@ goo_canvas_item_get_n_children (GooCanvasItem       *item)
  * 
  * Gets the child item at the given stack position.
  * 
- * Returns: the child item at the given stack position, or %NULL if @child_num
- * is out of range.
+ * Returns: (transfer none): the child item at the given stack position, or
+ *  %NULL if @child_num is out of range.
  **/
 GooCanvasItem*
 goo_canvas_item_get_child (GooCanvasItem       *item,
@@ -637,7 +637,7 @@ goo_canvas_item_get_child (GooCanvasItem       *item,
  * 
  * Gets the parent of the given item.
  * 
- * Returns: the parent item, or %NULL if the item has no parent.
+ * Returns: (transfer none): the parent item, or %NULL if the item has no parent.
  **/
 GooCanvasItem*
 goo_canvas_item_get_parent  (GooCanvasItem *item)
@@ -830,7 +830,7 @@ goo_canvas_item_lower          (GooCanvasItem *item,
 /**
  * goo_canvas_item_get_transform:
  * @item: an item.
- * @transform: the place to store the transform.
+ * @transform: (out): the place to store the transform.
  * 
  * Gets the transformation matrix of an item.
  * 
@@ -850,7 +850,7 @@ goo_canvas_item_get_transform  (GooCanvasItem   *item,
  * goo_canvas_item_get_transform_for_child:
  * @item: an item.
  * @child: a child of @item.
- * @transform: the place to store the transform.
+ * @transform: (out): the place to store the transform.
  * 
  * Gets the transformation matrix of an item combined with any special
  * transform needed for the given child. These special transforms are used
@@ -879,7 +879,7 @@ goo_canvas_item_get_transform_for_child  (GooCanvasItem  *item,
 /**
  * goo_canvas_item_set_transform:
  * @item: an item.
- * @transform: the new transformation matrix, or %NULL to reset the
+ * @transform: (allow-none): the new transformation matrix, or %NULL to reset the
  *  transformation to the identity matrix.
  * 
  * Sets the transformation matrix of an item.
@@ -895,10 +895,10 @@ goo_canvas_item_set_transform  (GooCanvasItem        *item,
 /**
  * goo_canvas_item_get_simple_transform:
  * @item: an item.
- * @x: returns the x coordinate of the origin of the item's coordinate space.
- * @y: returns the y coordinate of the origin of the item's coordinate space.
- * @scale: returns the scale of the item.
- * @rotation: returns the clockwise rotation of the item, in degrees (0-360).
+ * @x: (out): returns the x coordinate of the origin of the item's coordinate space.
+ * @y: (out): returns the y coordinate of the origin of the item's coordinate space.
+ * @scale: (out): returns the scale of the item.
+ * @rotation: (out): returns the clockwise rotation of the item, in degrees (0-360).
  * 
  * This function can be used to get the position, scale and rotation of an
  * item, providing that the item has a simple transformation matrix
@@ -1361,7 +1361,7 @@ goo_canvas_item_request_update  (GooCanvasItem *item)
 /**
  * goo_canvas_item_get_bounds:
  * @item: a #GooCanvasItem.
- * @bounds: a #GooCanvasBounds to return the bounds in.
+ * @bounds: (out): a #GooCanvasBounds to return the bounds in.
  * 
  * Gets the bounds of the item.
  *
@@ -1388,14 +1388,15 @@ goo_canvas_item_get_bounds  (GooCanvasItem   *item,
  *  be used to determine which parts of the item are tested.
  * @parent_is_visible: %TRUE if the parent item is visible (which
  *  implies that all ancestors are also visible).
- * @found_items: the list of items found so far.
+ * @found_items: (element-type GooCanvas.CanvasItem): the list of items found so far.
  * 
  * This function is only intended to be used when implementing new canvas
  * items, specifically container items such as #GooCanvasGroup.
  *
  * It gets the items at the given point.
  * 
- * Returns: the @found_items list, with any more found items added onto
+ * Returns: (element-type GooCanvas.CanvasItem) (transfer none): the
+ *  @found_items list, with any more found items added onto
  *  the start of the list, leaving the top item first.
  **/
 GList*
@@ -1549,6 +1550,41 @@ goo_canvas_item_get_requested_area (GooCanvasItem    *item,
 
 
 /**
+ * goo_canvas_item_get_requested_area_for_width:
+ * @item: a #GooCanvasItem.
+ * @cr: a cairo context.
+ * @width: the allocated width.
+ * @requested_area: a #GooCanvasBounds to return the requested area in, in the
+ *  parent's coordinate space. If %FALSE is returned, this is undefined.
+ * 
+ * This function is only intended to be used when implementing new canvas
+ * items, specifically layout items such as #GooCanvasTable.
+ *
+ * It gets the requested area of a child item, assuming it is allocated the
+ * given width. This is useful for text items whose requested height may change
+ * depending on the allocated width.
+ * 
+ * Returns: %TRUE if the item's requested area changes due to the new allocated
+ * width.
+ *
+ * Since: 2.0.1
+ **/
+gboolean
+goo_canvas_item_get_requested_area_for_width (GooCanvasItem	*item,
+					      cairo_t          *cr,
+					      gdouble           width,
+					      GooCanvasBounds  *requested_area)
+{
+  GooCanvasItemClass *item_class = GOO_CANVAS_ITEM_GET_CLASS (item);
+
+  if (item_class->get_requested_area_for_width)
+    return item_class->get_requested_area_for_width (item, cr, width, requested_area);
+  else
+    return FALSE;
+}
+
+
+/**
  * goo_canvas_item_get_requested_height:
  * @item: a #GooCanvasItem.
  * @cr: a cairo context.
@@ -2059,13 +2095,14 @@ goo_canvas_item_class_install_child_property (GObjectClass *iclass,
  * goo_canvas_item_class_find_child_property:
  * @iclass: a #GObjectClass
  * @property_name: the name of the child property to find
- * @returns: the #GParamSpec of the child property or %NULL if @class has no
- *   child property with that name.
  *
  * This function is only intended to be used when implementing new canvas
  * items, specifically layout container items such as #GooCanvasTable.
  *
  * It finds a child property of a canvas item class by name.
+ *
+ * Returns: (type GObject.ParamSpec) (transfer none): the #GParamSpec of the
+ *  child property or %NULL if @class has no child property with that name.
  */
 GParamSpec*
 goo_canvas_item_class_find_child_property (GObjectClass *iclass,
@@ -2082,14 +2119,15 @@ goo_canvas_item_class_find_child_property (GObjectClass *iclass,
 /**
  * goo_canvas_item_class_list_child_properties:
  * @iclass: a #GObjectClass
- * @n_properties: location to return the number of child properties found
- * @returns: a newly allocated array of #GParamSpec*. The array must be 
- *           freed with g_free().
+ * @n_properties: (out): location to return the number of child properties found
  *
  * This function is only intended to be used when implementing new canvas
  * items, specifically layout container items such as #GooCanvasTable.
  *
  * It returns all child properties of a canvas item class.
+ *
+ * Returns: (array length=n_properties) (transfer full): a newly allocated
+ *  array of #GParamSpec*. The array must be freed with g_free().
  */
 GParamSpec**
 goo_canvas_item_class_list_child_properties (GObjectClass *iclass,
diff --git a/src/goocanvasitem.h b/src/goocanvasitem.h
index d49ac08..422b47c 100644
--- a/src/goocanvasitem.h
+++ b/src/goocanvasitem.h
@@ -63,6 +63,13 @@ struct _GooCanvasItem
  * @get_requested_area: returns the requested area of the item, in its parent's
  *  coordinate space. This is only used for items in layout containers such as
  *  #GooCanvasTable.
+ * @get_requested_height: returns the requested height of the item,
+ *  given a particular allocated width, using the parent's coordinate space.
+ *  Note that this method should only be used if the position of the item
+ *  remains unchanged. If the position might change use
+ *  get_requested_area_for_width() instead.
+ * @get_requested_area_for_width: returns the requested bounds of the item,
+ *  given a particular allocated width, using the parent's coordinate space.
  * @allocate_area: allocates the item's area, in its parent's coordinate space.
  *  The item must recalculate its bounds and request redraws of parts of the
  *  canvas if necessary. This is only used for items in layout containers such
@@ -74,8 +81,6 @@ struct _GooCanvasItem
  * @is_visible: returns %TRUE if the item is currently visible.
  * @get_is_static: returns %TRUE if the item is static.
  * @set_is_static: notifies the item whether it is static or not.
- * @get_requested_height: returns the requested height of the item,
- *  given a particular allocated width, using the parent's coordinate space.
  * @enter_notify_event: signal emitted when the mouse enters the item.
  * @leave_notify_event: signal emitted when the mouse leaves the item.
  * @motion_notify_event: signal emitted when the mouse moves within the item.
@@ -192,6 +197,10 @@ struct _GooCanvasItemClass
   gboolean		(* get_is_static)		(GooCanvasItem		*item);
   void			(* set_is_static)		(GooCanvasItem		*item,
 							 gboolean		 is_static);
+  gboolean              (* get_requested_area_for_width)(GooCanvasItem		*item,
+							 cairo_t		*cr,
+							 gdouble		 width,
+							 GooCanvasBounds	*requested_area);
   gdouble               (* get_requested_height)	(GooCanvasItem		*item,
 							 cairo_t		*cr,
 							 gdouble		 width);
@@ -392,6 +401,10 @@ void               goo_canvas_item_paint          (GooCanvasItem         *item,
 gboolean	   goo_canvas_item_get_requested_area (GooCanvasItem	*item,
 						       cairo_t          *cr,
 						       GooCanvasBounds  *requested_area);
+gboolean	   goo_canvas_item_get_requested_area_for_width (GooCanvasItem	*item,
+								 cairo_t          *cr,
+								 gdouble           width,
+								 GooCanvasBounds  *requested_area);
 gdouble            goo_canvas_item_get_requested_height (GooCanvasItem  *item,
 							 cairo_t	*cr,
 							 gdouble         width);
diff --git a/src/goocanvasitemsimple.c b/src/goocanvasitemsimple.c
index a17193c..08c03c3 100644
--- a/src/goocanvasitemsimple.c
+++ b/src/goocanvasitemsimple.c
@@ -65,9 +65,11 @@ enum {
   /* Convenience properties. */
   PROP_STROKE_COLOR,
   PROP_STROKE_COLOR_RGBA,
+  PROP_STROKE_COLOR_GDK_RGBA,
   PROP_STROKE_PIXBUF,
   PROP_FILL_COLOR,
   PROP_FILL_COLOR_RGBA,
+  PROP_FILL_COLOR_GDK_RGBA,
   PROP_FILL_PIXBUF,
 
   /* Other properties. Note that the order here is important PROP_TRANSFORM
@@ -248,9 +250,15 @@ goo_canvas_item_simple_get_property (GObject              *object,
     case PROP_STROKE_COLOR_RGBA:
       goo_canvas_get_rgba_value_from_pattern (style ? style->stroke_pattern : NULL, value);
       break;
+    case PROP_STROKE_COLOR_GDK_RGBA:
+      goo_canvas_get_gdk_rgba_value_from_pattern (style ? style->stroke_pattern : NULL, value);
+      break;
     case PROP_FILL_COLOR_RGBA:
       goo_canvas_get_rgba_value_from_pattern (style ? style->fill_pattern : NULL, value);
       break;
+    case PROP_FILL_COLOR_GDK_RGBA:
+      goo_canvas_get_gdk_rgba_value_from_pattern (style ? style->fill_pattern : NULL, value);
+      break;
 
       /* Other properties. */
     case PROP_TRANSFORM:
@@ -431,6 +439,11 @@ goo_canvas_item_simple_set_property (GObject              *object,
       goo_canvas_style_set_stroke_pattern (style, pattern);
       cairo_pattern_destroy (pattern);
       break;
+    case PROP_STROKE_COLOR_GDK_RGBA:
+      pattern = goo_canvas_create_pattern_from_gdk_rgba_value (value);
+      goo_canvas_style_set_stroke_pattern (style, pattern);
+      cairo_pattern_destroy (pattern);
+      break;
     case PROP_STROKE_PIXBUF:
       pattern = goo_canvas_create_pattern_from_pixbuf_value (value);
       goo_canvas_style_set_stroke_pattern (style, pattern);
@@ -447,6 +460,11 @@ goo_canvas_item_simple_set_property (GObject              *object,
       goo_canvas_style_set_fill_pattern (style, pattern);
       cairo_pattern_destroy (pattern);
       break;
+    case PROP_FILL_COLOR_GDK_RGBA:
+      pattern = goo_canvas_create_pattern_from_gdk_rgba_value (value);
+      goo_canvas_style_set_fill_pattern (style, pattern);
+      cairo_pattern_destroy (pattern);
+      break;
     case PROP_FILL_PIXBUF:
       pattern = goo_canvas_create_pattern_from_pixbuf_value (value);
       goo_canvas_style_set_fill_pattern (style, pattern);
@@ -1141,6 +1159,12 @@ goo_canvas_item_simple_allocate_area      (GooCanvasItem         *item,
   simple->bounds.x2 += x_offset;
   simple->bounds.y2 += y_offset;
 
+#if 0
+  g_print ("Offsets: %g, %g Allocated bounds: %g,%g - %g,%g\n",
+	   x_offset, y_offset, simple->bounds.x1,
+	   simple->bounds.y1, simple->bounds.x2, simple->bounds.y2);
+#endif
+
   /* Request a redraw of the new bounds. */
   goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple->is_static);
 
@@ -2049,6 +2073,20 @@ goo_canvas_item_simple_class_init (GooCanvasItemSimpleClass *klass)
 						      0, G_MAXUINT, 0,
 						      G_PARAM_READWRITE));
 
+  /**
+   * GooCanvasItemSimple:stroke-color-gdk-rgba
+   *
+   * The color to use for the item's perimeter, specified as a GdkRGBA. To disable painting set the 'stroke-pattern' property to NULL.
+   *
+   * Since: 2.0.1
+   */
+  g_object_class_install_property (gobject_class, PROP_STROKE_COLOR_GDK_RGBA,
+                                   g_param_spec_boxed ("stroke-color-gdk-rgba",
+                                                       _("Stroke Color GdkRGBA"),
+                                                       _("The color to use for the item's perimeter, specified as a GdkRGBA. To disable painting set the 'stroke-pattern' property to NULL"),
+                                                       GDK_TYPE_RGBA,
+                                                       G_PARAM_READWRITE));
+
   g_object_class_install_property (gobject_class, PROP_STROKE_PIXBUF,
                                    g_param_spec_object ("stroke-pixbuf",
 							_("Stroke Pixbuf"),
@@ -2070,6 +2108,20 @@ goo_canvas_item_simple_class_init (GooCanvasItemSimpleClass *klass)
 						      0, G_MAXUINT, 0,
 						      G_PARAM_READWRITE));
 
+  /**
+   * GooCanvasItemSimple:fill-color-gdk-rgba
+   *
+   * The color to use to paint the interior of the item, specified as a GdkRGBA. To disable painting set the 'fill-pattern' property to NULL.
+   *
+   * Since: 2.0.1
+   */
+  g_object_class_install_property (gobject_class, PROP_FILL_COLOR_GDK_RGBA,
+                                   g_param_spec_boxed ("fill-color-gdk-rgba",
+                                                       _("Fill Color GdkRGBA"),
+                                                       _("The color to use to paint the interior of the item, specified as a GdkRGBA. To disable painting set the 'fill-pattern' property to NULL"),
+                                                       GDK_TYPE_RGBA,
+                                                       G_PARAM_READWRITE));
+
   g_object_class_install_property (gobject_class, PROP_FILL_PIXBUF,
                                    g_param_spec_object ("fill-pixbuf",
 							_("Fill Pixbuf"),
@@ -2146,6 +2198,15 @@ goo_canvas_item_simple_class_init (GooCanvasItemSimpleClass *klass)
 							 FALSE,
 							 G_PARAM_READWRITE));
 
+  /**
+   * GooCanvasItemSimple:tooltip:
+   *
+   * The tooltip to display for the item, or %NULL to display no tooltip.
+   *
+   * Note that this property has no effect unless the
+   * #GtkWidget:has-tooltip property is set to %TRUE on the #GooCanvas
+   * containing this item.
+   */
   g_object_class_install_property (gobject_class,
 				   PROP_TOOLTIP,
 				   g_param_spec_string ("tooltip",
diff --git a/src/goocanvaspath.c b/src/goocanvaspath.c
index 713f4e8..49d02fb 100644
--- a/src/goocanvaspath.c
+++ b/src/goocanvaspath.c
@@ -60,7 +60,7 @@ goo_canvas_path_init (GooCanvasPath *path)
 
 /**
  * goo_canvas_path_new:
- * @parent: the parent item, or %NULL. If a parent is specified, it will assume
+ * @parent: (skip): the parent item, or %NULL. If a parent is specified, it will assume
  *  ownership of the item, and the item will automatically be freed when it is
  *  removed from the parent. Otherwise call g_object_unref() to free it.
  * @path_data: the sequence of path commands, specified as a string using the
@@ -103,7 +103,7 @@ goo_canvas_path_init (GooCanvasPath *path)
  *                                             NULL);
  * </programlisting></informalexample>
  * 
- * Returns: a new path item.
+ * Returns: (transfer full): a new path item.
  **/
 GooCanvasItem*
 goo_canvas_path_new               (GooCanvasItem *parent,
diff --git a/src/goocanvaspolyline.c b/src/goocanvaspolyline.c
index 3367dc6..3993de6 100644
--- a/src/goocanvaspolyline.c
+++ b/src/goocanvaspolyline.c
@@ -43,7 +43,7 @@
  * Creates a new #GooCanvasPoints struct with space for the given number of
  * points. It should be freed with goo_canvas_points_unref().
  * 
- * Returns: a new #GooCanvasPoints struct.
+ * Returns: (transfer full): a new #GooCanvasPoints struct.
  **/
 GooCanvasPoints*
 goo_canvas_points_new   (int    num_points)
@@ -93,6 +93,46 @@ goo_canvas_points_unref (GooCanvasPoints *points)
 }
 
 
+/**
+ * goo_canvas_points_set_point:
+ * @points: a #GooCanvasPoints struct.
+ * @idx: index of point to set.
+ * @x: x value to set point coordinate to.
+ * @y: y value to set point coordinate to.
+ * 
+ * Sets the coordinates of a point in the #GooCanvasPoints struct.
+ *
+ * Since: 2.0.1
+ **/
+void
+goo_canvas_points_set_point(GooCanvasPoints *points, int idx, double x, double y)
+{
+    g_return_if_fail(idx < points->num_points);
+    points->coords[2*idx] = x;
+    points->coords[2*idx + 1] = y;
+}
+
+/**
+ * goo_canvas_points_get_point:
+ * @points: a #GooCanvasPoints struct.
+ * @idx: index of point to get.
+ * @x: (out): location to store x coordinate.
+ * @y: (out): location to store y coordinate.
+ * 
+ * Gets the coordinates of a point in the #GooCanvasPoints struct.
+ *
+ * Since: 2.0.1
+ **/
+void
+goo_canvas_points_get_point(GooCanvasPoints *points, int idx, double *x, double *y)
+{
+    *x = 0; *y = 0;
+    g_return_if_fail(idx < points->num_points);
+    *x = points->coords[2*idx];
+    *y = points->coords[2*idx + 1];
+}
+
+
 GType
 goo_canvas_points_get_type (void)
 {
@@ -527,7 +567,7 @@ goo_canvas_polyline_set_property (GObject              *object,
 
 /**
  * goo_canvas_polyline_new:
- * @parent: the parent item, or %NULL. If a parent is specified, it will assume
+ * @parent: (skip): the parent item, or %NULL. If a parent is specified, it will assume
  *  ownership of the item, and the item will automatically be freed when it is
  *  removed from the parent. Otherwise call g_object_unref() to free it.
  * @close_path: if the last point should be connected to the first.
@@ -553,7 +593,7 @@ goo_canvas_polyline_set_property (GObject              *object,
  *                                                     NULL);
  * </programlisting></informalexample>
  * 
- * Returns: a new polyline item.
+ * Returns: (transfer full): a new polyline item.
  **/
 GooCanvasItem*
 goo_canvas_polyline_new               (GooCanvasItem *parent,
@@ -596,7 +636,7 @@ goo_canvas_polyline_new               (GooCanvasItem *parent,
 
 /**
  * goo_canvas_polyline_new_line:
- * @parent: the parent item, or %NULL.
+ * @parent: (skip): the parent item, or %NULL.
  * @x1: the x coordinate of the start of the line.
  * @y1: the y coordinate of the start of the line.
  * @x2: the x coordinate of the end of the line.
@@ -618,7 +658,7 @@ goo_canvas_polyline_new               (GooCanvasItem *parent,
  *                                                          NULL);
  * </programlisting></informalexample>
  * 
- * Returns: a new polyline item.
+ * Returns: (transfer full): a new polyline item.
  **/
 GooCanvasItem*
 goo_canvas_polyline_new_line          (GooCanvasItem *parent,
@@ -718,7 +758,7 @@ goo_canvas_polyline_create_start_arrow_path (GooCanvasPolyline *polyline,
 
   cairo_move_to (cr, arrow->start_arrow_coords[0],
 		 arrow->start_arrow_coords[1]);
-  for (i = 1; i < NUM_ARROW_POINTS; i++)
+  for (i = 1; i < GOO_CANVAS_POLYLINE_NUM_ARROW_POINTS; i++)
     {
       cairo_line_to (cr, arrow->start_arrow_coords[i * 2],
 		     arrow->start_arrow_coords[i * 2 + 1]);
@@ -741,7 +781,7 @@ goo_canvas_polyline_create_end_arrow_path (GooCanvasPolyline *polyline,
 
   cairo_move_to (cr, arrow->end_arrow_coords[0],
 		 arrow->end_arrow_coords[1]);
-  for (i = 1; i < NUM_ARROW_POINTS; i++)
+  for (i = 1; i < GOO_CANVAS_POLYLINE_NUM_ARROW_POINTS; i++)
     {
       cairo_line_to (cr, arrow->end_arrow_coords[i * 2],
 		     arrow->end_arrow_coords[i * 2 + 1]);
diff --git a/src/goocanvaspolyline.h b/src/goocanvaspolyline.h
index a038432..fb4721d 100644
--- a/src/goocanvaspolyline.h
+++ b/src/goocanvaspolyline.h
@@ -24,6 +24,7 @@ G_BEGIN_DECLS
 typedef struct _GooCanvasPoints GooCanvasPoints;
 struct _GooCanvasPoints
 {
+  /*< public >*/
   double *coords;
   int num_points;
   int ref_count;
@@ -34,9 +35,11 @@ GType            goo_canvas_points_get_type (void);
 GooCanvasPoints* goo_canvas_points_new      (int              num_points);
 GooCanvasPoints* goo_canvas_points_ref      (GooCanvasPoints *points);
 void             goo_canvas_points_unref    (GooCanvasPoints *points);
+void             goo_canvas_points_set_point(GooCanvasPoints *points, int idx, double x, double y);
+void             goo_canvas_points_get_point(GooCanvasPoints *points, int idx, double *x, double *y);
 
 
-#define NUM_ARROW_POINTS     5		/* number of points in an arrowhead */
+#define GOO_CANVAS_POLYLINE_NUM_ARROW_POINTS     5		/* number of points in an arrowhead */
 
 typedef struct _GooCanvasPolylineArrowData GooCanvasPolylineArrowData;
 struct _GooCanvasPolylineArrowData
@@ -46,8 +49,8 @@ struct _GooCanvasPolylineArrowData
   gdouble arrow_width, arrow_length, arrow_tip_length;
 
   gdouble line_start[2], line_end[2];
-  gdouble start_arrow_coords[NUM_ARROW_POINTS * 2];
-  gdouble end_arrow_coords[NUM_ARROW_POINTS * 2];
+  gdouble start_arrow_coords[GOO_CANVAS_POLYLINE_NUM_ARROW_POINTS * 2];
+  gdouble end_arrow_coords[GOO_CANVAS_POLYLINE_NUM_ARROW_POINTS * 2];
 };
 
 
diff --git a/src/goocanvasprivate.h b/src/goocanvasprivate.h
index 423f37e..b62c54a 100644
--- a/src/goocanvasprivate.h
+++ b/src/goocanvasprivate.h
@@ -39,13 +39,17 @@ guint goo_canvas_convert_colors_to_rgba (double red,
 void goo_canvas_get_rgba_value_from_pattern (cairo_pattern_t *pattern,
 					     GValue          *value);
 
+void goo_canvas_get_gdk_rgba_value_from_pattern (cairo_pattern_t *pattern,
+                                                 GValue          *value);
+
 void goo_canvas_set_style_property_from_pattern (GooCanvasStyle  *style,
 						 GQuark           property_id,
 						 cairo_pattern_t *pattern);
 
-cairo_pattern_t* goo_canvas_create_pattern_from_color_value  (const GValue *value);
-cairo_pattern_t* goo_canvas_create_pattern_from_rgba_value   (const GValue *value);
-cairo_pattern_t* goo_canvas_create_pattern_from_pixbuf_value (const GValue *value);
+cairo_pattern_t* goo_canvas_create_pattern_from_color_value    (const GValue *value);
+cairo_pattern_t* goo_canvas_create_pattern_from_rgba_value     (const GValue *value);
+cairo_pattern_t* goo_canvas_create_pattern_from_gdk_rgba_value (const GValue *value);
+cairo_pattern_t* goo_canvas_create_pattern_from_pixbuf_value   (const GValue *value);
 
 
 gboolean goo_canvas_boolean_handled_accumulator (GSignalInvocationHint *ihint,
diff --git a/src/goocanvasrect.c b/src/goocanvasrect.c
index 8257574..ce402ac 100644
--- a/src/goocanvasrect.c
+++ b/src/goocanvasrect.c
@@ -56,7 +56,7 @@ goo_canvas_rect_init (GooCanvasRect *rect)
 
 /**
  * goo_canvas_rect_new:
- * @parent: the parent item, or %NULL. If a parent is specified, it will assume
+ * @parent: (skip): the parent item, or %NULL. If a parent is specified, it will assume
  *  ownership of the item, and the item will automatically be freed when it is
  *  removed from the parent. Otherwise call g_object_unref() to free it.
  * @x: the x coordinate of the left of the rectangle.
@@ -80,7 +80,7 @@ goo_canvas_rect_init (GooCanvasRect *rect)
  *                                             NULL);
  * </programlisting></informalexample>
  * 
- * Returns: a new rectangle item.
+ * Returns: (transfer full): a new rectangle item.
  **/
 GooCanvasItem*
 goo_canvas_rect_new (GooCanvasItem *parent,
diff --git a/src/goocanvastable.c b/src/goocanvastable.c
index 9531fd2..3976304 100644
--- a/src/goocanvastable.c
+++ b/src/goocanvastable.c
@@ -414,7 +414,7 @@ goo_canvas_table_init (GooCanvasTable *table)
 
 /**
  * goo_canvas_table_new:
- * @parent: the parent item, or %NULL. If a parent is specified, it will assume
+ * @parent: (skip): the parent item, or %NULL. If a parent is specified, it will assume
  *  ownership of the item, and the item will automatically be freed when it is
  *  removed from the parent. Otherwise call g_object_unref() to free it.
  * @...: optional pairs of property names and values, and a terminating %NULL.
@@ -461,7 +461,7 @@ goo_canvas_table_init (GooCanvasTable *table)
  *                                        NULL);
  * </programlisting></informalexample>
  * 
- * Returns: a new table item.
+ * Returns: (transfer full): a new table item.
  **/
 GooCanvasItem*
 goo_canvas_table_new (GooCanvasItem  *parent,
@@ -1011,6 +1011,7 @@ goo_canvas_table_set_child_property (GooCanvasItem     *item,
   GooCanvasTable *table = (GooCanvasTable*) item;
   GooCanvasTableChild *table_child;
   gint child_num;
+  gboolean found = FALSE;
 
   for (child_num = 0; child_num < simple->children->len; child_num++)
     {
@@ -1023,11 +1024,16 @@ goo_canvas_table_set_child_property (GooCanvasItem     *item,
 						      table_child,
 						      property_id, value,
 						      pspec);
+          found = TRUE;
 	  break;
 	}
     }
 
-  goo_canvas_item_simple_changed (simple, TRUE);
+  if (!found) {
+    g_warning ("%s: child not found.", G_STRFUNC);
+  }
+  else
+    goo_canvas_item_simple_changed (simple, TRUE);
 }
 
 
@@ -1757,6 +1763,8 @@ goo_canvas_table_update_requested_heights (GooCanvasItem       *item,
   GooCanvasTableChildLayoutData *child_data;
   gint start_column, end_column, i, row, end;
   gdouble x, max_width, width, requested_width, requested_height, height = 0.0;
+  GooCanvasItemClass *item_class;
+  GooCanvasBounds bounds;
 
   /* Just return if we've already calculated requested heights for this exact
      width. */
@@ -1792,10 +1800,42 @@ goo_canvas_table_update_requested_heights (GooCanvasItem       *item,
       if (!(child->flags[HORZ] & GOO_CANVAS_TABLE_CHILD_FILL))
 	width = MIN (max_width, requested_width);
 
-      requested_height = goo_canvas_item_get_requested_height (child_item, cr,
+      item_class = GOO_CANVAS_ITEM_GET_CLASS (item);
+
+      /* See if the child supports the new get_requested_area_for_width()
+	 method, which can handles the bounds being changed by the change
+	 in width & height. */
+      if (item_class->get_requested_area_for_width)
+	{
+	  if (item_class->get_requested_area_for_width (child_item, cr, width,
+							&bounds))
+	    {
+	      /* Remember the requested position and size of the child. */
+	      child_data->requested_position[HORZ] = bounds.x1;
+	      child_data->requested_position[VERT] = bounds.y1;
+
+	      child_data->requested_size[HORZ] = bounds.x2 - bounds.x1;
+
+	      if (layout_data->integer_layout)
+		child_data->requested_size[VERT] = ceil (bounds.y2 - bounds.y1);
+	      else
+		child_data->requested_size[VERT] = bounds.y2 - bounds.y1;
+	    }
+	}
+      else if (item_class->get_requested_height)
+	{
+	  requested_height = item_class->get_requested_height (child_item, cr,
 							       width);
-      if (requested_height >= 0.0)
-	child_data->requested_size[VERT] = requested_height;
+	  if (requested_height >= 0.0)
+	    {
+	      child_data->requested_size[HORZ] = width;
+
+	      if (layout_data->integer_layout)
+		child_data->requested_size[VERT] = ceil (requested_height);
+	      else
+		child_data->requested_size[VERT] = requested_height;
+	    }
+	}
     }
 
   /* Now recalculate the requested heights of each row. */
diff --git a/src/goocanvastext.c b/src/goocanvastext.c
index 5c67a32..cf285f9 100644
--- a/src/goocanvastext.c
+++ b/src/goocanvastext.c
@@ -77,7 +77,7 @@ goo_canvas_text_init (GooCanvasText *text)
 
 /**
  * goo_canvas_text_new:
- * @parent: the parent item, or %NULL. If a parent is specified, it will assume
+ * @parent: (skip): the parent item, or %NULL. If a parent is specified, it will assume
  *  ownership of the item, and the item will automatically be freed when it is
  *  removed from the parent. Otherwise call g_object_unref() to free it.
  * @string: the text to display.
@@ -104,7 +104,7 @@ goo_canvas_text_init (GooCanvasText *text)
  *                                             NULL);
  * </programlisting></informalexample>
  * 
- * Returns: a new text item.
+ * Returns: (transfer full): a new text item.
  **/
 GooCanvasItem*
 goo_canvas_text_new (GooCanvasItem *parent,
@@ -317,8 +317,8 @@ goo_canvas_text_create_layout (GooCanvasText           *text,
 
       /* If the text width has been set, that width is used to do the alignment
 	 positioning. Otherwise the actual width is used. */
-      if (text->width > 0)
-	align_width = text->width;
+      if (layout_width > 0)
+	align_width = layout_width;
       else
 	align_width = logical_width;
 
@@ -369,7 +369,7 @@ goo_canvas_text_create_layout (GooCanvasText           *text,
       bounds->x1 = origin_x;
       bounds->y1 = origin_y;
 
-      if (text->width > 0)
+      if (layout_width > 0)
 	{
 	  /* If the text width has been set, and the alignment isn't
 	     PANGO_ALIGN_LEFT, we need to adjust for the difference between
@@ -611,59 +611,93 @@ goo_canvas_text_paint (GooCanvasItemSimple   *simple,
 }
 
 
-static gdouble
-goo_canvas_text_get_requested_height (GooCanvasItem	*item,
-				      cairo_t		*cr,
-				      gdouble            width)
+static gboolean
+goo_canvas_text_get_requested_area_for_width (GooCanvasItem	*item,
+					      cairo_t		*cr,
+					      gdouble            width,
+					      GooCanvasBounds	*requested_area)
 {
   GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
+  GooCanvasItemSimpleData *simple_data = simple->simple_data;
   GooCanvasText *text = (GooCanvasText*) item;
+  GooCanvasTextPrivate *priv = goo_canvas_text_get_private (text);
   PangoLayout *layout;
-  gdouble height;
+  cairo_matrix_t matrix;
+  double x_offset, y_offset;
 
   /* If we have a transformation besides a simple scale & translation, just
      return -1 as we can't adjust the height in that case. */
-  if (simple->clip_path_commands
-      || (simple->transform && (simple->transform->xy != 0.0
-				     || simple->transform->yx != 0.0)))
-    return -1;
+  if (simple_data->clip_path_commands
+      || (simple_data->transform && (simple_data->transform->xy != 0.0
+				     || simple_data->transform->yx != 0.0)))
+    return FALSE;
 
   cairo_save (cr);
-  if (simple->transform)
-    cairo_transform (cr, simple->transform);
+  if (simple_data->transform)
+    cairo_transform (cr, simple_data->transform);
+
+  /* Remove any current translation, to avoid the 16-bit cairo limit. */
+  cairo_get_matrix (cr, &matrix);
+  x_offset = matrix.x0;
+  y_offset = matrix.y0;
+  matrix.x0 = matrix.y0 = 0.0;
+  cairo_set_matrix (cr, &matrix);
 
   /* Convert the width from the parent's coordinate space. Note that we only
      need to support a simple scale operation here. */
   text->layout_width = width;
-  if (simple->transform)
-    text->layout_width /= simple->transform->xx;
+  if (simple_data->transform)
+    text->layout_width /= simple_data->transform->xx;
 
-  if (text->height < 0.0)
-    {
-     /* Create layout with given width. */
-      layout = goo_canvas_text_create_layout (text, text->layout_width, cr,
-					      &simple->bounds, NULL, NULL);
-      g_object_unref (layout);
+  /* Create layout with given width. */
+  layout = goo_canvas_text_create_layout (simple_data, text->text_data,
+					  text->layout_width, cr,
+					  &simple->bounds, NULL, NULL);
+  g_object_unref (layout);
 
-      height = simple->bounds.y2 - simple->bounds.y1;
-    }
-  else
-    {
-      height = text->height;
-    }
+  /* If the height is set, use that. */
+  if (priv->height > 0.0)
+    simple->bounds.y2 = simple->bounds.y1 + priv->height;
+
+
+  /* Convert to device space. */
+  cairo_user_to_device (cr, &simple->bounds.x1, &simple->bounds.y1);
+  cairo_user_to_device (cr, &simple->bounds.x2, &simple->bounds.y2);
+
+  /* Add the translation back to the bounds. */
+  simple->bounds.x1 += x_offset;
+  simple->bounds.y1 += y_offset;
+  simple->bounds.x2 += x_offset;
+  simple->bounds.y2 += y_offset;
 
-  /* Convert to the parent's coordinate space. As above, we only need to
-     support a simple scale operation here. */
-  if (simple->transform)
-    height *= simple->transform->yy;
+  /* Restore the item's proper transformation matrix. */
+  matrix.x0 = x_offset;
+  matrix.y0 = y_offset;
+  cairo_set_matrix (cr, &matrix);
+
+  /* Convert back to user space. */
+  cairo_device_to_user (cr, &simple->bounds.x1, &simple->bounds.y1);
+  cairo_device_to_user (cr, &simple->bounds.x2, &simple->bounds.y2);
+
+
+  /* Copy the user bounds to the requested area. */
+  *requested_area = simple->bounds;
+
+  /* Convert to the parent's coordinate space. */
+  goo_canvas_item_simple_user_bounds_to_parent (simple, cr, requested_area);
 
   /* Convert the item's bounds to device space. */
   goo_canvas_item_simple_user_bounds_to_device (simple, cr, &simple->bounds);
 
+#if 0
+  g_print ("Width: %g Requested bounds: %g,%g - %g,%g\n",
+	   width, simple->bounds.x1, simple->bounds.y1,
+	   simple->bounds.x2, simple->bounds.y2);
+#endif
+
   cairo_restore (cr);
 
-  /* Return the new requested height of the text. */
-  return height;
+  return TRUE;
 }
 
 
@@ -712,7 +746,7 @@ goo_canvas_text_class_init (GooCanvasTextClass *klass)
   gobject_class->get_property = goo_canvas_text_get_property;
   gobject_class->set_property = goo_canvas_text_set_property;
 
-  item_class->get_requested_height = goo_canvas_text_get_requested_height;
+  item_class->get_requested_area_for_width = goo_canvas_text_get_requested_area_for_width;
 
   simple_class->simple_update        = goo_canvas_text_update;
   simple_class->simple_paint         = goo_canvas_text_paint;
diff --git a/src/goocanvasutils.c b/src/goocanvasutils.c
index e938255..8d49e50 100644
--- a/src/goocanvasutils.c
+++ b/src/goocanvasutils.c
@@ -555,7 +555,7 @@ parse_flag (gchar    **pos,
  * 
  * Parses the given SVG path specification string.
  * 
- * Returns: a #GArray of #GooCanvasPathCommand elements.
+ * Returns: (element-type GooCanvasPathCommand) (transfer full): a #GArray of #GooCanvasPathCommand elements.
  **/
 GArray*
 goo_canvas_parse_path_data (const gchar       *path_data)
@@ -1229,17 +1229,35 @@ goo_canvas_get_rgba_value_from_pattern (cairo_pattern_t *pattern,
 }
 
 
+void
+goo_canvas_get_gdk_rgba_value_from_pattern (cairo_pattern_t *pattern,
+                                            GValue          *value)
+{
+  GdkRGBA rgba = {0, 0, 0, 0};
+
+  if (pattern && cairo_pattern_get_type (pattern) == CAIRO_PATTERN_TYPE_SOLID)
+    {
+      cairo_pattern_get_rgba (pattern, &rgba.red, &rgba.green, &rgba.blue, &rgba.alpha);
+    }
+  g_value_set_boxed (value, &rgba);
+}
+
+
 cairo_pattern_t*
 goo_canvas_create_pattern_from_color_value (const GValue *value)
 {
-  GdkColor color = { 0, 0, 0, 0 };
+  GdkRGBA rgba = { 0, 0, 0, 0 };
+  const char *color_string;
+
+  color_string = g_value_get_string (value);
 
-  if (g_value_get_string (value))
-    gdk_color_parse (g_value_get_string (value), &color);
+  if (color_string)
+    {
+      gdk_rgba_parse (&rgba, color_string);
+    }
 
-  return cairo_pattern_create_rgb (color.red / 65535.0,
-				   color.green / 65535.0,
-				   color.blue / 65535.0);
+  return cairo_pattern_create_rgba (rgba.red, rgba.green, rgba.blue,
+                                    rgba.alpha);
 }
   
 
@@ -1260,6 +1278,21 @@ goo_canvas_create_pattern_from_rgba_value (const GValue *value)
 
 
 cairo_pattern_t*
+goo_canvas_create_pattern_from_gdk_rgba_value (const GValue *value)
+{
+  GdkRGBA* rgba;
+
+  rgba = g_value_get_boxed (value);
+
+  if (rgba)
+    return cairo_pattern_create_rgba (rgba->red, rgba->green, rgba->blue,
+                                      rgba->alpha);
+  else
+    return cairo_pattern_create_rgba (0, 0, 0, 0);
+}
+
+
+cairo_pattern_t*
 goo_canvas_create_pattern_from_pixbuf_value (const GValue *value)
 {
   GdkPixbuf *pixbuf;
diff --git a/src/goocanvaswidget.c b/src/goocanvaswidget.c
index 6d1ceac..310318b 100644
--- a/src/goocanvaswidget.c
+++ b/src/goocanvaswidget.c
@@ -68,7 +68,7 @@ goo_canvas_widget_init (GooCanvasWidget *witem)
 
 /**
  * goo_canvas_widget_new:
- * @parent: the parent item, or %NULL. If a parent is specified, it will assume
+ * @parent: (skip): the parent item, or %NULL. If a parent is specified, it will assume
  *  ownership of the item, and the item will automatically be freed when it is
  *  removed from the parent. Otherwise call g_object_unref() to free it.
  * @widget: the widget.
@@ -93,7 +93,7 @@ goo_canvas_widget_init (GooCanvasWidget *witem)
  *                                                NULL);
  * </programlisting></informalexample>
  * 
- * Returns: a new widget item.
+ * Returns: (transfer full): a new widget item.
  **/
 GooCanvasItem*
 goo_canvas_widget_new               (GooCanvasItem    *parent,



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