diff --git a/CHANGES b/CHANGES
--- a/CHANGES
+++ b/CHANGES
@@ -24,3 +24,16 @@
   * New features:
     + simple text support
     + simple support for external PNG images
+
+0.4: 22 October 2011
+
+  * New features:
+    + Support for drawing directly to Gtk widgets
+    + Support for path fill rule attribute
+
+  * New/improved examples
+
+  * Improved documentation
+
+  * Bug fixes:
+    + Warning for unsupported image types (#41)
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,7 @@
 Copyright 2011 diagrams-cairo team:
 
   Sam Griffin <sam.griffin@gmail.com>
+  John Lato <jwlato@gmail.com>
   Luite Stegeman <stegeman@gmail.com>
   Kanchalai Suveepattananont <ksuvee@seas.upenn.edu>
   Ryan Yates <fryguybob@gmail.com>
diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,17 @@
+A rendering backend for diagrams, a Haskell embedded domain-specific
+language for compositional, declarative drawing.  See
+
+  http://projects.haskell.org/diagrams/
+
+for more information about the project, including installation
+instructions, tutorials, a user manual, a gallery of example images,
+and links to the mailing list, IRC channel, developer wiki and bug
+tracker.
+
+The source repository is mirrored on both patch-tag (darcs) and github
+(git):
+
+  http://patch-tag.com/r/byorgey/diagrams-cairo
+  https://github.com/byorgey/diagrams-cairo
+
+Patches/pull requests welcome in either place.
diff --git a/diagrams-cairo.cabal b/diagrams-cairo.cabal
--- a/diagrams-cairo.cabal
+++ b/diagrams-cairo.cabal
@@ -1,9 +1,9 @@
 Name:                diagrams-cairo
-Version:             0.3
+Version:             0.4
 Synopsis:            Cairo backend for diagrams drawing EDSL
-Description:         This package provides a modular backend for rendering
-                     diagrams created with the diagrams EDSL using the 
-                     Cairo library.
+Description:         A full-featured backend for rendering
+                     diagrams using the cairo rendering engine.
+                     To get started, see "Diagrams.Backend.Cairo.CmdLine".
 Homepage:            http://projects.haskell.org/diagrams
 License:             BSD3
 License-file:        LICENSE
@@ -12,8 +12,8 @@
 Category:            Graphics
 Build-type:          Simple
 Cabal-version:       >=1.6
-Extra-source-files:  CHANGES
-Tested-with:         GHC == 6.12.3, GHC >= 7.0.2 && <= 7.0.3
+Extra-source-files:  CHANGES, README
+Tested-with:         GHC == 6.12.3, GHC >= 7.0.2 && <= 7.0.4, GHC == 7.2.1
 Extra-source-files:  example/*.hs, example/tic-tac-toe/*.hs
 Source-repository head
   type:     darcs
@@ -22,17 +22,23 @@
 Library
   Exposed-modules:     Diagrams.Backend.Cairo
                        Diagrams.Backend.Cairo.CmdLine
+                       Diagrams.Backend.Cairo.Gtk
   Hs-source-dirs:      src
-  Build-depends:       base >= 4.2 && < 4.4,
+  Build-depends:       base >= 4.2 && < 4.5,
                        mtl >= 2.0 && < 2.1,
-                       process >= 1.0 && < 1.1,
+                       process >= 1.0 && < 1.2,
                        directory >= 1.0 && < 1.2,
                        old-time >= 1.0 && < 1.1,
-                       diagrams-core >= 0.3 && < 0.4,
-                       diagrams-lib >= 0.3 && < 0.4,
+                       diagrams-core >= 0.4 && < 0.5,
+                       diagrams-lib >= 0.4 && < 0.5,
                        cairo >= 0.10.1 && < 0.13,
-                       cmdargs >= 0.6 && < 0.8,
+                       cmdargs >= 0.6 && < 0.9,
+                       gtk >= 0.12.0  && < 0.13.0,
                        split >= 0.1.2 && < 0.2
   if !os(windows)
     cpp-options: -DCMDLINELOOP
-    Build-depends:     unix >= 2.4 && < 2.5
+    Build-depends:     unix >= 2.4 && < 2.6
+
+  if impl(ghc >= 7.2.1)
+    Build-depends:     cairo >= 0.12.1,
+                       gtk   >= 0.12.1
diff --git a/example/Apollonius.hs b/example/Apollonius.hs
new file mode 100644
--- /dev/null
+++ b/example/Apollonius.hs
@@ -0,0 +1,22 @@
+import Diagrams.Prelude
+import Diagrams.Backend.Cairo.CmdLine
+
+import Test.QuickCheck
+
+-- Center and signed radius
+data Circle = Circle { center :: P2, sRadius :: Double }
+
+descartesR sgn r1 r2 r3 =
+  (r1 * r2 * r3) /
+    (r1*r2 + r1*r3 + r2*r3 + sgn * 2 * sqrt(r1*r2*r3*(r1+r2+r3)))
+
+prop_descartes (NonZero r1) (NonZero r2) (NonZero r3) = abs (2*(e1*e1 + e2*e2 + e3*e3 + e4*e4) - (e1+e2+e3+e4)^2) < 1e-10
+  where [e1,e2,e3,e4] = map (1/) [r1,r2,r3,r4]
+        r4 = descartesInR r1 r2 r3
+
+descartesOutR = descartesR (-1)
+descartesInR  = descartesR 1
+
+main = defaultMain (circle (descartesInR 1 1 1) <> circle (descartesOutR 1 1 1) <> circles)
+
+circles = decoratePath (polygon with {sides=3} # scale (2/sqrt 3)) (repeat unitCircle)
diff --git a/example/Fractal.hs b/example/Fractal.hs
--- a/example/Fractal.hs
+++ b/example/Fractal.hs
@@ -12,7 +12,7 @@
                (s ||| s)
   where s = sierpinski (n-1)
 
-t = polygon with { sides = 3, orientation = OrientToX }
+t = regPoly 3 1
     # lw 0
     # fc black
 
@@ -28,7 +28,6 @@
 
 pentaflake' n = pentaflake n # fc (colors !! n)
 
-p = polygon with { sides = 5, orientation = OrientToX }
-    # lw 0
+p = regPoly 5 1 # lw 0
 
 main = defaultMain (pad 1.1 $ pentaflake' 4)
diff --git a/example/Fun.hs b/example/Fun.hs
new file mode 100644
--- /dev/null
+++ b/example/Fun.hs
@@ -0,0 +1,25 @@
+{-# LANGUAGE NoMonomorphismRestriction #-}
+
+import Diagrams.Prelude
+import Diagrams.Backend.Cairo.CmdLine
+
+{-
+pts = [origin, P (1,0), P (1,1), P (2,1), P (2,2), P (3,2), P (3,3)]
+
+curve = cubicSpline False pts
+
+dot = circle 0.05 # fc black
+dots = position (zip pts (repeat dot))
+-}
+
+circleP = arc (0::Rad) (tau::Rad)
+
+d = stroke $ circleP <> reversePath circleP # scale 0.8
+
+infVertices = map P [ (0,0), (0.3, 0.2), (0.6, 0), (0.3, -0.2)
+                    , (0,0), (-0.3, 0.2), (-0.6, 0), (-0.3, -0.2)
+                    ]
+
+inf = cubicSpline True infVertices # lw 0.05
+
+main = defaultMain ((d # fc grey) <> inf)
diff --git a/example/Hasse.hs b/example/Hasse.hs
--- a/example/Hasse.hs
+++ b/example/Hasse.hs
@@ -44,9 +44,11 @@
                                                   , s2 <- subs2
                                                   , s1 `isSubset` s2 ]
         connect (Subset _ elts1) (Subset _ elts2) =
-          withANameB elts1 $ \p1 b1 ->
-          withANameB elts2 $ \p2 b2 ->
-          (<> (boundaryFrom p1 unitY b1 ~~ boundaryFrom p2 unit_Y b2) # lw 0.03)
+          withNames [elts1, elts2] $ \[(p1,b1), (p2,b2)] ->
+            (<> (boundaryFrom p1 unitY b1 ~~ boundaryFrom p2 unit_Y b2) # lw 0.03)
         subsets = subsetsBySize n
 
-main = defaultMain (pad 1.1 $ hasseDiagram 4)
+d1 =|= d2 = d1 === strutY 3 === d2
+
+-- main = defaultMain (pad 1.1 $ foldr1 (=|=) (map hasseDiagram [1..4]))
+main = defaultMain (pad 1.1 $ hasseDiagram 5)
diff --git a/example/Logo.hs b/example/Logo.hs
--- a/example/Logo.hs
+++ b/example/Logo.hs
@@ -2,10 +2,51 @@
 
 import Diagrams.Prelude
 import Diagrams.Backend.Cairo.CmdLine
+import Diagrams.TwoD.Path
 
 import qualified Data.Colour as C
 
+d = (stroke $
+   circlePath 2 # alignBR # translateX (-0.5)
+   <> (hcat' with { sep = 0.2 } . map (vcat' with {sep = 0.2})
+        $ (replicate 2 (replicate 9 (reversePath $ circlePath 0.3)))) # alignBR)
+    # fc red
+    # lw 0
+
 {-
+dAngle :: Rad
+dAngle = tau / 6
+
+dHeight = 5
+dWidth  = 1
+
+dRad = 1.5
+
+dPath = pathFromTrail . close $
+        arc dAngle (tau - dAngle) # scale dRad
+     <> fromOffsets [ (0, -(1 - cos (tau/4 - getRad dAngle)) * dRad)
+                    , (dWidth, 0)
+                    , (0, dHeight)
+                    , (-dWidth, 0)
+                    ]
+
+dotMatrix d path
+  = mconcat [ if (isInsideWinding p path)
+                 then circle (d / 2 - d/10) # fc red # lw 0 # moveTo p
+                 else mempty
+            | x <- [ xlo, xlo + d .. xhi ]
+            , y <- [ ylo, ylo + d .. yhi ]
+            , let p = P (x,y)
+            ]
+  where (xlo, xhi) = extentX path
+        (ylo, yhi) = extentY path
+
+matrixAng = 1/20
+
+d = dotMatrix 0.09 (dPath # rotateBy matrixAng) # rotateBy (-matrixAng)
+-}
+
+{-
 d = mconcat . map alignBR
   $ [ dBody
     , rect 0.5 6.5 # fc black
@@ -27,30 +68,45 @@
     # lc blue
     # fc yellow
 
-sierpinski 1 = polygon with { sides = 3, orientation = OrientToX }
+sierpinski 1 = polygon with { polyType = PolyRegular 3 1 }
 sierpinski n = s === (s ||| s)
   where s = sierpinski (n-1)
 
-a = sierpinski 4
-    # fc black
-    # scale (1/2)
+a1 = sierpinski 4
+     # fc black
+     # scale (1/2)
 
 grid = verts # centerXY <> horiz # centerXY
   where verts = hcat' with {sep=0.5} $ replicate 20 (vrule 10)
         horiz = rotateBy (1/4) verts
 
-g = grid
+gbkg = grid
     # lc gray
     # rotateBy (-1/20)
     # clipBy p
     # withBounds (p :: Path R2)
-  where p = polygon with {sides = 4, orientation = OrientToX} # scaleToX 5 # scaleToY 5
+  where p = square 5
 
+g = (text "G" # fontSize 4 # rotateBy (-1/20)) <> gbkg
+
+r = text "r" # fontSize 5
+  <> square 1 # lw 0 # scale 5
+
+a2 = text "a" # fontSize 5
+  <> square 1 # lw 0 # scale 5
+
 m = square 5.5 <>
     text "m"
       # fontSize 6 # italic # font "freeserif" # fc green
 
-logo = (hcat' with {sep = 0.5} . map alignB $ [ i, a, g, m ])
+vs = [(5,5), (3,6), (1,5), (1,4), (3,3), (5,2), (4,0), (0,0.5)]
+s = (mconcat (map (\v -> translate v (dot blue)) vs) <>
+    cubicSpline False (map P vs) # lw 0.20)
+    # scale 0.8
+
+dot c = circle 0.4 # fc c # lw 0
+
+logo = (hcat' with {sep = 0.5} . map alignB $ [ d, i, a1, g, r, a2, m, s ])
        # centerXY
 
 main = defaultMain (pad 1.1 logo)
diff --git a/example/Star.hs b/example/Star.hs
--- a/example/Star.hs
+++ b/example/Star.hs
@@ -8,8 +8,7 @@
         h = stroke' with {vertexNames = [map ("x",) [0..n]]} (p unitX)
         v = stroke' with {vertexNames = [map ("y",) [0..n]]} (p unitY)
 
-connect n i = withAName ("x",i) $ \x ->
-              withAName ("y", n - i) $ \y ->
+connect n i = withNames [("x",i), ("y", n - i)] $ \[(x,_), (y,_)] ->
                 drawConnect [x,y]
   where drawConnect = atop . fromVertices
 
diff --git a/example/cubicSpline.hs b/example/cubicSpline.hs
new file mode 100644
--- /dev/null
+++ b/example/cubicSpline.hs
@@ -0,0 +1,25 @@
+import Diagrams.Prelude
+import Diagrams.Backend.Cairo.CmdLine
+
+import Diagrams.CubicSpline.Internal
+
+import Control.Newtype
+
+
+poly cs t = foldr mul 0 cs
+  where mul a b = a + b * t
+
+-- Interpolate directly on the spline coefficents
+interpolate closed vs = concatMap (\c -> map (poly c) (map fromRational [0.0,0.01..1.0])) cs
+  where
+    cs = solveCubicSplineCoefficients closed vs
+
+
+main = defaultMain (pad 1.1 (mconcat [a,b,c]))
+  where 
+    vs = map P [(0,10),(2,2),(3.5,8),(4.5,6)]
+    closed = True
+    
+    a = (lc blue  . lw 0.05 . stroke . fromVertices) (overF P (interpolate closed) vs)
+    b = (lc red   . lw 0.07 . stroke)                (cubicSpline closed vs)
+    c = (lc green . lw 0.1  . stroke . fromVertices) vs
diff --git a/src/Diagrams/Backend/Cairo.hs b/src/Diagrams/Backend/Cairo.hs
--- a/src/Diagrams/Backend/Cairo.hs
+++ b/src/Diagrams/Backend/Cairo.hs
@@ -2,6 +2,7 @@
            , MultiParamTypeClasses
            , FlexibleInstances
            , FlexibleContexts
+           , ExistentialQuantification
            , TypeSynonymInstances
            , DeriveDataTypeable
            , ViewPatterns
@@ -14,26 +15,35 @@
 -- License     :  BSD-style (see LICENSE)
 -- Maintainer  :  diagrams-discuss@googlegroups.com
 --
--- A full-featured rendering backend for diagrams using Cairo.
+-- A full-featured rendering backend for diagrams using the
+-- cairo rendering engine.
 --
 -----------------------------------------------------------------------------
 module Diagrams.Backend.Cairo
 
-  ( Cairo(..)        -- rendering token
+  ( -- * Cairo-supported output formats
+    OutputFormat(..)
 
-  , Options(..)      -- for CairoOptions, rendering options specific to Cairo
-  , OutputFormat(..) -- output format options
+    -- * Cairo-specific options
+    -- $CairoOptions
+  , Options(..)
+
+    -- * Backend token
+  , Cairo(..)
   ) where
 
 import Graphics.Rendering.Diagrams.Transform
 
 import Diagrams.Prelude
 import Diagrams.TwoD.Ellipse
-import Diagrams.TwoD.Path (Clip(..))
+import Diagrams.TwoD.Path (Clip(..), getFillRule)
 import Diagrams.TwoD.Text
 import Diagrams.TwoD.Image
 import Diagrams.TwoD.Adjust (adjustDia2D, adjustSize)
 
+import Graphics.UI.Gtk (DrawableClass)
+import qualified Graphics.UI.Gtk.Cairo as CG
+
 import qualified Graphics.Rendering.Cairo as C
 import qualified Graphics.Rendering.Cairo.Matrix as CM
 
@@ -42,7 +52,6 @@
 import Data.Maybe (catMaybes, fromMaybe)
 import Data.List (isSuffixOf)
 
-import Data.Monoid
 import qualified Data.Foldable as F
 
 import Data.Typeable
@@ -55,13 +64,28 @@
 -- | Cairo is able to output to several file formats, which each have
 --   their own associated properties that affect the output.
 data OutputFormat =
-    -- | PNG is unique, in that it is not a vector format
-    PNG { pngSize :: (Int, Int)       -- ^ the size of the output is given in pixels
+    -- | Output directly to a Gtk window.  See "Diagrams.Backends.Cairo.Gtk".
+    forall dw. (DrawableClass dw) =>
+    GTK { gtkWindow :: dw
+          -- ^ The window on which to draw.
+
+        , gtkSize   :: Maybe (Int, Int)
+          -- ^ The size of the output is given in pixels. If @Nothing@,
+          --   rescaling should not be performed.
+
+        , gtkBypass :: Bool
+          -- ^ Should the 'adjustDia' step be bypassed during rendering?
         }
+    -- | PNG is unique, in that it is not a vector format.
+  | PNG { pngSize :: (Int, Int)       -- ^ the size of the output is given in pixels
+        }
+    -- | PostScript output.
   | PS  { psSize  :: (Double, Double) -- ^ the size of the output is given in points
         }
+    -- | Portable Document Format (PDF) output.
   | PDF { pdfSize :: (Double, Double) -- ^ the size of the output is given in points
         }
+    -- | Scalable Vector Graphics (SVG) output.
   | SVG { svgSize :: (Double, Double) -- ^ the size of the output is given in points
         }
 
@@ -83,6 +107,22 @@
 restore :: RenderM ()
 restore = lift C.restore
 
+-- $CairoOptions
+--
+-- Unfortunately, Haddock does not yet support documentation for
+-- associated data families, so we must just provide it manually.
+-- This module defines
+--
+-- > data family Options Cairo R2 = CairoOptions
+-- >               { fileName     :: String       -- ^ the name of the file you want generated
+-- >               , outputFormat :: OutputFormat -- ^ the output format and associated options
+-- >               }
+--
+-- So, for example, you could call the 'renderDia' function (from
+-- "Graphics.Rendering.Diagrams.Core") like this:
+--
+-- > renderDia Cairo (CairoOptions "foo.png" (PNG (100,100))) myDiagram
+
 instance Backend Cairo R2 where
   data Render  Cairo R2 = C (RenderM ())
   type Result  Cairo R2 = (IO (), C.Render ())
@@ -107,6 +147,7 @@
             let surfaceF s = C.renderWith s r'
                 file = fileName options
             case outputFormat options of
+              GTK win _ _ -> CG.renderWithDrawable win r'
               PNG (w,h) ->
                 C.withImageSurface C.FormatARGB32 w h $ \surface -> do
                   surfaceF surface
@@ -115,11 +156,17 @@
               PDF (w,h) -> C.withPDFSurface file w h surfaceF
               SVG (w,h) -> C.withSVGSurface file w h surfaceF
 
-  adjustDia c opts d = adjustDia2D (getSize . outputFormat) c opts (d # reflectY)
-    where getSize (PNG (pw,ph)) = (fromIntegral pw, fromIntegral ph)
+  adjustDia c opts d = if bypass (outputFormat opts)
+                         then d
+                         else adjustDia2D (getSize . outputFormat) c opts (d # reflectY)
+    where getSize (GTK _ (Just (pw,ph)) _) = (fromIntegral pw, fromIntegral ph)
+          getSize (GTK _ Nothing _)        = size2D d
+          getSize (PNG (pw,ph)) = (fromIntegral pw, fromIntegral ph)
           getSize (PS  sz) = sz
           getSize (PDF sz) = sz
           getSize (SVG sz) = sz
+          bypass  (GTK _ _ x)   = x
+          bypass  _             = False
 
 renderC :: (Renderable a Cairo, V a ~ R2) => a -> RenderM ()
 renderC a = case (render Cairo a) of C r -> r
@@ -131,6 +178,7 @@
                 , handle fSize
                 , handleFontFace
                 , handle fColor
+                , handle lFillRule
                 ]
   where handle :: AttributeClass a => (a -> RenderM ()) -> Maybe (RenderM ())
         handle f = f `fmap` getAttr s
@@ -143,6 +191,7 @@
                  $ getFontWeight <$> getAttr s
         handleFontFace = Just . lift $ C.selectFontFace fFace fSlant fWeight
         fColor c = lift $ setSource (getFillColor c) s
+        lFillRule = lift . C.setFillRule . fromFillRule . getFillRule
 
 fromFontSlant :: FontSlant -> C.FontSlant
 fromFontSlant FontSlantNormal   = C.FontSlantNormal
@@ -167,9 +216,9 @@
         handle f = f `fmap` getAttr s
         fColor c = setSource (getFillColor c) s >> C.fillPreserve
         lColor c = setSource (getLineColor c) s
-        lWidth = C.setLineWidth . getLineWidth
-        lCap   = C.setLineCap . fromLineCap . getLineCap
-        lJoin  = C.setLineJoin . fromLineJoin . getLineJoin
+        lWidth   = C.setLineWidth . getLineWidth
+        lCap     = C.setLineCap . fromLineCap . getLineCap
+        lJoin    = C.setLineJoin . fromLineJoin . getLineJoin
         lDashing (getDashing -> Dashing ds offs) =
           C.setDash ds offs
 
@@ -205,6 +254,10 @@
 fromLineJoin LineJoinRound = C.LineJoinRound
 fromLineJoin LineJoinBevel = C.LineJoinBevel
 
+fromFillRule :: FillRule -> C.FillRule
+fromFillRule Winding = C.FillRuleWinding
+fromFillRule EvenOdd = C.FillRuleEvenOdd
+
 instance Renderable Ellipse Cairo where
   render _ ell = C . lift $ do
     let P (xc,yc) = ellipseCenter ell
@@ -215,7 +268,7 @@
     C.translate xc yc
     C.rotate th
     C.scale xs ys
-    C.arc 0 0 1 0 (2*pi)
+    C.arc 0 0 1 0 tau
     C.closePath
     C.restore
 
@@ -234,20 +287,27 @@
             lift $ uncurry C.moveTo p
             renderC tr
 
+
 -- Can only do PNG files at the moment...
 instance Renderable Image Cairo where
-  render _ (Image file sz tr) = C . lift . when (".png" `isSuffixOf` file) $ do
-    C.save
-    cairoTransf (tr <> reflectionY)
-    pngSurf <- liftIO $ C.imageSurfaceCreateFromPNG file
-    w <- C.imageSurfaceGetWidth pngSurf
-    h <- C.imageSurfaceGetHeight pngSurf
-    let s = (adjustSize sz (fromIntegral w, fromIntegral h))
-    cairoTransf s
-    C.setSourceSurface pngSurf (-fromIntegral w / 2)
-                               (-fromIntegral h / 2)
-    C.paint
-    C.restore
+  render _ (Image file sz tr) = C . lift $ do
+    if ".png" `isSuffixOf` file
+      then do
+        C.save
+        cairoTransf (tr <> reflectionY)
+        pngSurf <- liftIO $ C.imageSurfaceCreateFromPNG file
+        w <- C.imageSurfaceGetWidth pngSurf
+        h <- C.imageSurfaceGetHeight pngSurf
+        cairoTransf $ adjustSize sz (fromIntegral w, fromIntegral h)
+        C.setSourceSurface pngSurf (-fromIntegral w / 2)
+                                   (-fromIntegral h / 2)
+        C.paint
+        C.restore
+      else
+        liftIO . putStr . unlines $
+          [ "Warning: Cairo backend can currently only render embedded"
+          , "  images in .png format.  Ignoring <" ++ file ++ ">."
+          ]
 
 -- see http://www.cairographics.org/tutorial/#L1understandingtext
 instance Renderable Text Cairo where
diff --git a/src/Diagrams/Backend/Cairo/CmdLine.hs b/src/Diagrams/Backend/Cairo/CmdLine.hs
--- a/src/Diagrams/Backend/Cairo/CmdLine.hs
+++ b/src/Diagrams/Backend/Cairo/CmdLine.hs
@@ -7,7 +7,7 @@
 -- Maintainer  :  diagrams-discuss@googlegroups.com
 --
 -- Convenient creation of command-line-driven executables for
--- rendering diagrams using the Cairo backend.
+-- rendering diagrams using the cairo backend.
 --
 -----------------------------------------------------------------------------
 
@@ -87,6 +87,24 @@
   &= summary "Command-line diagram generation."
   &= program prog
 
+-- | This is the simplest way to render diagrams, and is intended to
+--   be used like so:
+--
+-- > ... definitions ...
+-- >
+-- > main = defaultMain myDiagram
+--
+--   Compiling this file will result in an executable which takes
+--   various command-line options for setting the size, output file,
+--   and so on, and renders @myDiagram@ with the specified options.
+--
+--   On Unix systems, the generated executable also supports a
+--   rudimentary \"looped\" mode, which watches the source file for
+--   changes and recompiles itself on the fly.
+--
+--   Pass @--help@ to the generated executable to see all available
+--   options.
+
 defaultMain :: Diagram Cairo R2 -> IO ()
 defaultMain d = do
   prog <- getProgName
@@ -111,6 +129,13 @@
            fst $ renderDia Cairo (CairoOptions (output opts) outfmt) d
        | otherwise -> putStrLn $ "Unknown file type: " ++ last ps
 
+-- | @multiMain@ is like 'defaultMain', except instead of a single
+--   diagram it takes a list of diagrams paired with names as input.
+--   The generated executable then takes an argument specifying the
+--   name of the diagram that should be rendered.  This is a
+--   convenient way to create an executable that can render many
+--   different diagrams without modifying the source code in between
+--   each one.
 multiMain :: [(String, Diagram Cairo R2)] -> IO ()
 multiMain ds = do
   prog <- getProgName
diff --git a/src/Diagrams/Backend/Cairo/Gtk.hs b/src/Diagrams/Backend/Cairo/Gtk.hs
new file mode 100644
--- /dev/null
+++ b/src/Diagrams/Backend/Cairo/Gtk.hs
@@ -0,0 +1,60 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Diagrams.Backend.Cairo.Gtk
+-- Copyright   :  (c) 2011 Diagrams-cairo team (see LICENSE)
+-- License     :  BSD-style (see LICENSE)
+-- Maintainer  :  diagrams-discuss@googlegroups.com
+--
+-- Convenient interface to rendering diagrams directly
+-- on Gtk widgets using the Cairo backend.
+--
+-----------------------------------------------------------------------------
+
+module Diagrams.Backend.Cairo.Gtk
+       ( defaultRender
+       , toGtkCoords
+       , renderToGtk
+       ) where
+
+import Diagrams.Prelude hiding (width, height)
+import Diagrams.Backend.Cairo
+
+import Graphics.UI.Gtk
+
+-- | Convert a Diagram to the backend coordinates.
+-- 
+-- Provided to Query the diagram with coordinates from a mouse click
+-- event.
+-- 
+-- > widget `on` buttonPressEvent $ tryEvent $ do
+-- >   click <- eventClick
+-- >   (x,y) <- eventCoordinates
+-- >   let result = runQuery (query $ toGtkCoords myDiagram) (P (x,y))
+-- >   do_something_with result
+-- 
+-- `toGtkCoords` does no rescaling of the diagram, however it is centered in
+-- the window.
+toGtkCoords :: Monoid m => AnnDiagram Cairo R2 m -> AnnDiagram Cairo R2 m
+toGtkCoords d =
+  adjustDia Cairo
+            (CairoOptions "" (GTK (undefined :: DrawWindow) Nothing False))
+            d
+
+-- | Render a diagram to a DrawingArea, rescaling to fit the full area.
+defaultRender :: Monoid m => DrawingArea -> AnnDiagram Cairo R2 m -> IO ()
+defaultRender da d = do
+  sz <- widgetGetSize da
+  dw <- widgetGetDrawWindow da
+  fst $ renderDia Cairo (CairoOptions "" (GTK dw (Just sz) False)) d
+
+-- | Render a diagram to a DrawableClass.  No rescaling or transformations
+-- will be performed.
+-- 
+-- Typically the diagram will already have been transformed by `toGtkCoords`.
+renderToGtk ::
+  (DrawableClass dc, Monoid m)
+  => dc                     -- ^ widget to render onto
+  -> AnnDiagram Cairo R2 m  -- ^ Diagram
+  -> IO ()
+renderToGtk dc d =
+  fst $ renderDia Cairo (CairoOptions "" (GTK dc Nothing True)) d
