diff --git a/example/Main.hs b/example/Main.hs
deleted file mode 100644
--- a/example/Main.hs
+++ /dev/null
@@ -1,190 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-module Main where
-import Control.Monad (unless)
-import Control.Monad.State (lift)
-
-import SDL hiding (point, rotate)
-import Linear.V2 (V2(..))
-import Linear.Affine (Point(..))
-
-import SDL.Cairo
-import SDL.Cairo.Canvas
-import qualified Graphics.Rendering.Cairo as C
-
-main :: IO ()
-main = do
-  initializeAll
-  window <- createWindow "SDL2 Cairo Canvas" defaultWindow
-  renderer <- createRenderer window (-1) defaultRenderer
-
-  -- create a texture suitable to use cairo on
-  texture <- createCairoTexture' renderer window
-
-  appLoop renderer texture 0 (V2 0 0)
-
-  -- clean up
-  destroyTexture texture
-  destroyRenderer renderer
-  destroyWindow window
-  return ()
-
-appLoop :: Renderer -> Texture -> Int -> V2 Double -> IO ()
-appLoop renderer texture framecount mousepos = do
-  events <- pollEvents
-  let quitEvent event = case eventPayload event of
-                          QuitEvent -> True
-                          _ -> False
-      mouseMoveEvent e = case eventPayload e of
-                          MouseMotionEvent _ -> True
-                          _ -> False
-      getMousePos (MouseMotionEvent (MouseMotionEventData _ _ _ (P p) _)) = fromIntegral <$> p
-      getMousePos _ = V2 0 0
-      mousePositions = map getMousePos $ map eventPayload $ filter mouseMoveEvent events
-      quit = any quitEvent events
-      mousepos' = if null mousePositions then mousepos else head mousePositions
-
-  -- draw on the texture
-  withCanvas texture $ do
-    drawExample
-    drawRndCircle
-    drawStars (fromIntegral framecount)
-    drawTriangleStrip mousepos'
-    drawBezierTest
-
-  -- apply texture and show on screen
-  copy renderer texture Nothing Nothing
-  present renderer
-
-  delay $ 1000 `div` 60     -- slow down to approx. 60 FPS
-
-  unless quit (appLoop renderer texture (framecount+1) mousepos')
-
--- | draw a circle in a random color
-drawRndCircle :: Canvas ()
-drawRndCircle = do
-    rnd <- random (0,255)
-    fill $ gray rnd
-    circle (V2 700 500) 100
-    fill $ gray 255
-
--- | some shapes, show some features
-drawExample :: Canvas ()
-drawExample = do
-    background $ gray 102
-
-    stroke $ blue 255
-    point $ V2 500 10
-
-    line (V2 0 0) (V2 100 100)
-    line (V2 100 0) (V2 0 100)
-    fill $ red 255 !@ 128
-    noStroke
-    rect $ D 200 200 100 100
-    stroke $ green 255 !@ 128
-    fill $ blue 255 !@ 128
-    rect $ centered $ D 200 200 100 100
-    triangle (V2 700 300) (V2 750 400) (V2 700 400)
-
-    strokeWeight 5
-    strokeJoin LineJoinRound
-    stroke $ (blue 255 + red 255) !@ 128
-    fill $ rgb 0 255 255 !@ 128
-    polygon [V2 600 500,V2 610 505,V2 620 530, V2 600 530]
-
-    circle (V2 200 500) 30
-
-    strokeWeight 1
-    ellipse $ D 100 500 30 50
-
-    pushMatrix
-    translate $ V2 350 350
-    rotate $ pi/4
-    ellipse $ D 0 0 100 50
-    popMatrix
-    ellipse $ D 0 0 100 50
-
-    -- render some text
-    let txtpos = V2 100 50
-    textFont $ Font "Monospace" 30 False True
-    offset <- text "sdl2-cairo " txtpos
-    textFont $ Font "" 30 True False
-    text "is AWESOME." $ txtpos + offset
-    return ()
-
-    -- use Cairo Render API directly
-    lift $ do
-      C.setSourceRGB 1 1 0
-      C.moveTo 100 300
-      C.lineTo 200 400
-      C.stroke
-
--- | ported star example from Processing home page
-drawStars :: Double -> Canvas ()
-drawStars frameCount = do
-  (V2 w h) <- getCanvasSize
-  stroke $ gray 0
-
-  pushMatrix
-  translate $ V2 (0.2*w) (0.3*h)
-  rotate $ frameCount / 200
-  star 0 0 5 70 3
-  popMatrix
-
-  pushMatrix
-  translate $ V2 (0.5*w) (0.3*h)
-  rotate $ frameCount / 400
-  star 0 0 80 100 40
-  popMatrix
-
-  pushMatrix
-  translate $ V2 (0.8*w) (0.3*h)
-  rotate $ frameCount / (-100)
-  star 0 0 30 70 5
-  popMatrix
-
-star :: Double -> Double -> Double -> Double -> Double -> Canvas ()
-star x y r1 r2 n = do
-  let angle = 2*pi/n
-      halfAngle = angle/2
-      p1 a = V2 (x+cos a*r2) (y+sin a*r2)
-      p2 a = V2 (x+cos (a+halfAngle)*r1) (y+sin (a+halfAngle)*r1)
-      vertices = concatMap snd $ takeWhile (\(a, _) -> a<2*pi+angle)
-               $ iterate (\(a, _) -> (a+angle,[p1 a, p2 a])) (0,[])
-  polygon vertices
-
--- | ported triangle strip example from Processing homepage
-drawTriangleStrip :: V2 Double -> Canvas ()
-drawTriangleStrip mousePos = do
-  (V2 w h) <- getCanvasSize
-  let (V2 mouseX mouseY) = mousePos
-      pos = V2 (w/2) (h/4*3)
-      n = fromIntegral $ round $ mapRange mouseX (0,w) (6,60)
-      astep = 180/n
-      insideRadius = 100
-      outsideRadius = 150
-      cossin a = V2 (cos a) (sin a)
-      makeVert a = [ pos+cossin (radians a) * outsideRadius
-                   , pos+cossin (radians $ a+astep)*insideRadius
-                   ]
-      vertices = concatMap makeVert $ map (2*astep*) [0..n]
-  shape ShapeTriangleStrip vertices
-  return ()
-
--- | draw bezier curve examples
-drawBezierTest :: Canvas ()
-drawBezierTest = do
-  pushMatrix
-  translate $ V2 600 0
-  stroke $ rgb 255 102 0
-  line (V2 85 20) (V2 10 10)
-  line (V2 90 90) (V2 15 80)
-  stroke $ gray 0
-  bezier (V2 85 20) (V2 10 10) (V2 90 90) (V2 15 80)
-  translate $ V2 100 0
-  stroke $ rgb 255 102 0
-  noFill
-  line (V2 30 20) (V2 80 5)
-  line (V2 80 75) (V2 30 75)
-  stroke $ gray 0
-  bezier (V2 30 20) (V2 80 5) (V2 80 75) (V2 30 75)
-  popMatrix
diff --git a/sdl2-cairo.cabal b/sdl2-cairo.cabal
--- a/sdl2-cairo.cabal
+++ b/sdl2-cairo.cabal
@@ -2,14 +2,13 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                sdl2-cairo
-version:             0.1.1.0
-synopsis:            Render with Cairo on SDL textures. Includes optional convenience drawing API.
-description:         This small library provides convenience functions to draw
-                     on SDL2 textures with Cairo. As Cairo is complicated, it also
-                     provides a drawing API, which is heavily inspired by Processing and
-                     is much more user-friendly. If it does not support something,
-                     you can always embed direct Cairo commands, so you do not have
-                     to decide!
+version:             0.2
+synopsis:            Render with Cairo on SDL textures.
+description:         This small library provides glue functions to draw
+                     on SDL2 textures with Cairo.
+
+                     NOTE: The Processing-style drawing API has been moved
+                     to a separate the package cairo-canvas.
 license:             MIT
 license-file:        LICENSE
 author:              Anton Pirogov
@@ -22,36 +21,13 @@
 library
   hs-source-dirs:      src
   default-language:    Haskell2010
-  exposed-modules:     SDL.Cairo, SDL.Cairo.Canvas, SDL.Cairo.Canvas.Interactive
+  exposed-modules:     SDL.Cairo
   --other-modules:
   build-depends:       base >=4.7 && <5
                      , sdl2 >=2.1.0
                      , cairo >=0.13
                      , linear
-                     , mtl
-                     , random
-                     , time
 
-flag builddemo
-  description:       Build the little demo
-  default:           False
-
-executable sdl2-cairo-test
-  hs-source-dirs:      example
-  main-is:             Main.hs
-  default-language:    Haskell2010
-  default-extensions:  OverloadedStrings
-  if flag(builddemo)
-    build-depends:     base >=4 && <5
-                     , sdl2 >=2.1.0
-                     , cairo >=0.13
-                     , sdl2-cairo
-                     , linear
-                     , mtl
-                     , random
-                     , time
-  else
-    buildable:         False
 
 source-repository head
   type:     git
diff --git a/src/SDL/Cairo/Canvas.hs b/src/SDL/Cairo/Canvas.hs
deleted file mode 100644
--- a/src/SDL/Cairo/Canvas.hs
+++ /dev/null
@@ -1,555 +0,0 @@
-{-# LANGUAGE CPP,GeneralizedNewtypeDeriving #-}
-{-|
-Module      : SDL.Cairo.Canvas
-Copyright   : Copyright (c) 2015 Anton Pirogov
-License     : MIT
-Maintainer  : anton.pirogov@gmail.com
-
-This module defines the 'Canvas' monad, which is a convenience wrapper around
-the underlying Cairo rendering and can be used with the same textures
-created by 'createCairoTexture'. You can also mix both, if the need arises.
-
-The Canvas API imitates most of the drawing functions
-of the Processing language. See <http://processing.org/reference> for comparison.
-While having the Processing spirit, this module does not aim for a perfect mapping and
-deviates where necessary or appropriate. Nevertheless most Processing examples should be
-trivial to port to the Canvas API. Example:
-
-@
-\{\-\# LANGUAGE OverloadedStrings \#\-\}
-import SDL
-import Linear.V2 (V2(..))
-import SDL.Cairo
-import SDL.Cairo.Canvas
-
-main :: IO ()
-main = do
-  initializeAll
-  window <- createWindow "SDL2 Cairo Canvas" defaultWindow
-  renderer <- createRenderer window (-1) defaultRenderer
-  texture <- createCairoTexture' renderer window
-
-  withCanvas texture $ do
-    background $ gray 102
-    fill $ red 255 !\@ 128
-    noStroke
-    rect $ D 200 200 100 100
-    stroke $ green 255 !\@ 128
-    fill $ blue 255 !\@ 128
-    rect $ D 250 250 100 100
-    triangle (V2 400 300) (V2 350 400) (V2 400 400)
-
-  copy renderer texture Nothing Nothing
-  present renderer
-  delay 5000
-@
-
--}
-module SDL.Cairo.Canvas (
-  -- * Entry point
-  Canvas, withCanvas, getCanvasSize,
-  -- * Color and Style
-  Color, Byte, gray, red, green, blue, rgb, (!@),
-  stroke, fill, noStroke, noFill, strokeWeight, strokeJoin, strokeCap,
-  -- * Coordinates
-  Dim(..), toD, dimPos, dimSize, Anchor(..), aligned, centered, corners,
-  -- * Primitives
-  background, point, line, triangle, rect, polygon, shape, ShapeMode(..),
-  -- * Arcs and Curves
-  circle, circle', arc, ellipse, bezier, bezierQ,
-  -- * Transformations
-  resetMatrix, pushMatrix, popMatrix, translate, rotate, scale,
-  -- * Images
-  Image(imageSize), createImage, loadImagePNG, saveImagePNG, image, image', blend, grab,
-  -- * Text
-  Font(..), textFont, textSize, textExtents, text, text',
-  -- * Math
-  mapRange, radians, degrees,
-  -- * Misc
-  randomSeed, random, getTime, Time(..),
-  LineCap(..), LineJoin(..)
-) where
-
-#if __GLASGOW_HASKELL__ < 710
-import Control.Applicative
-#endif
-
-import Control.Monad.State
-import Data.Word (Word8)
-
-import Data.Time.Clock (UTCTime(..),getCurrentTime)
-import Data.Time.LocalTime (timeToTimeOfDay,TimeOfDay(..))
-import Data.Time.Calendar (toGregorian)
-
-import System.Random (mkStdGen,setStdGen,randomRIO,Random)
-
-import Linear.V2 (V2(..))
-import Linear.V4 (V4(..))
-
-import SDL (Texture,TextureInfo(..),queryTexture)
-import qualified Graphics.Rendering.Cairo as C
-import Graphics.Rendering.Cairo (Render,LineJoin(..),LineCap(..),Format(..),Operator(..))
-
-import SDL.Cairo (withCairoTexture')
-
--- | For values from 0 to 255
-type Byte = Word8
-
--- | RGBA Color is just a byte vector. Colors can be added, subtracted, etc.
-type Color = V4 Byte
-
-data CanvasState = CanvasState{ csSize :: V2 Double,    -- ^ texture size
-                                csSurface :: C.Surface, -- ^ Cairo surface
-                                csFG :: Maybe Color,    -- ^ stroke color
-                                csBG :: Maybe Color,    -- ^ fill color
-                                csImages :: [Image]     -- ^ keep track of images to free later
-                              }
-
--- | get size of the canvas (Processing: @width(), height()@)
-getCanvasSize :: Canvas (V2 Double)
-getCanvasSize = gets csSize
-
-newtype RenderWrapper m a = Canvas { unCanvas :: StateT CanvasState m a }
-  deriving (Functor, Applicative, Monad, MonadTrans, MonadIO, MonadState CanvasState)
-
--- | wrapper around the Cairo 'Render' monad, providing a Processing-style API
-type Canvas = RenderWrapper Render
-
--- | draw on a SDL texture using the 'Canvas' monad
-withCanvas :: Texture -> Canvas a -> IO a
-withCanvas t c = withCairoTexture' t $ \s -> do
-  (TextureInfo _ _ w h) <- queryTexture t
-  let defaults  = strokeWeight 1 >> strokeCap C.LineCapRound
-      initstate = CanvasState{ csSize = V2 (fromIntegral w) (fromIntegral h)
-                             , csSurface = s
-                             , csFG = Just $ gray 0
-                             , csBG = Just $ gray 255
-                             , csImages = []
-                             }
-  (ret, result) <- C.renderWith s $ runStateT (unCanvas $ defaults >> c) initstate
-  forM_ (csImages result) $ \(Image s _ _) -> C.surfaceFinish s
-  return ret
-
-----
-
--- | set current stroke color
-stroke :: Color -> Canvas ()
-stroke clr = modify $ \cs -> cs{csFG=Just clr}
--- | set current fill color
-fill :: Color -> Canvas ()
-fill clr   = modify $ \cs -> cs{csBG=Just clr}
--- | disable stroke (-> shapes without borders!), reenabled by using 'stroke'
-noStroke :: Canvas ()
-noStroke   = modify $ \cs -> cs{csFG=Nothing}
--- | disable fill (-> shapes are not filled!), reenabled by using 'fill'
-noFill :: Canvas ()
-noFill     = modify $ \cs -> cs{csBG=Nothing}
-
--- | create opaque gray color
-gray :: Byte -> Color
-gray c = V4 c c c 255
--- | create opaque red color
-red :: Byte -> Color
-red c = V4 c 0 0 255
--- | create opaque green color
-green :: Byte -> Color
-green c = V4 0 c 0 255
--- | create opaque blue color
-blue :: Byte -> Color
-blue c = V4 0 0 c 255
--- | create opaque mixed color
-rgb :: Byte -> Byte -> Byte -> Color
-rgb r g b = V4 r g b 255
--- | set transparency of color (half red would be: @red 255 !\@ 128@)
-(!@) :: Color -> Byte -> Color
-(V4 r g b _) !@ a = V4 r g b a
-
--- | set line width for shape borders etc.
-strokeWeight :: Double -> Canvas ()
-strokeWeight d = lift $ C.setLineWidth d
-
--- | set the style of connections between lines of shapes
-strokeJoin :: C.LineJoin -> Canvas ()
-strokeJoin l = lift $ C.setLineJoin l
--- | set the style of the line caps
-strokeCap :: C.LineCap -> Canvas ()
-strokeCap l = lift $ C.setLineCap l
-
-----
-
--- | position (canonically, top-left corner) and size representation (X Y W H)
-data Dim = D Double Double Double Double deriving (Show,Eq)
-
--- | indicates where a position coordinate is located in a rectangle
-data Anchor = NW | N | NE | E | SE | S | SW | W | Center | Baseline deriving (Show,Eq)
-
--- | create dimensions from position and size vector
-toD (V2 a b) (V2 c d) = D a b c d
--- | get position vector from dimensions
-dimPos  (D a b _ _) = V2 a b
--- | get size vector from dimensions
-dimSize (D _ _ c d) = V2 c d
-
--- | takes dimensions with bottom-right corner instead of size, returns normalized (with size)
-corners (D xl yl xh yh) = D xl yl (xh-xl) (yh-yl)
-
--- | takes dimensions with centered position, returns normalized (top-left corner)
-centered = aligned Center
-
--- | takes dimensions with non-standard position coordinate,
--- returns dimensions normalized to top-left corner coordinate
-aligned :: Anchor -> Dim -> Dim
-aligned NW dim = dim
-aligned NE (D x y w h) = D (x-w) y      w h
-aligned SW (D x y w h) = D x     (y-h)  w h
-aligned SE (D x y w h) = D (x-w) (y-h)  w h
-aligned Baseline dim = aligned SW dim
-aligned N (D x y w h) = D (x-w/2) y       w h
-aligned W (D x y w h) = D x       (y-h/2) w h
-aligned S (D x y w h) = D (x-w/2) (y-h)   w h
-aligned E (D x y w h) = D (x-w)   (y-h/2) w h
-aligned Center (D x y w h) = D (x-w/2) (y-h/2) w h
-
-----
-
--- | replace current matrix with identity
-resetMatrix :: Canvas ()
-resetMatrix = lift C.identityMatrix
-
--- | push current matrix onto the stack
-pushMatrix :: Canvas ()
-pushMatrix = lift C.save
-
--- | pop a matrix
-popMatrix :: Canvas ()
-popMatrix = lift C.restore
-
--- | translate coordinate system
-translate :: V2 Double -> Canvas ()
-translate (V2 x y) = lift $ C.translate x y
-
--- | scale coordinate system
-scale :: V2 Double -> Canvas ()
-scale (V2 x y) = lift $ C.scale x y
-
--- | rotate coordinate system
-rotate :: Double -> Canvas ()
-rotate a = lift $ C.rotate a
-
-----
-
--- | clear the canvas with given color
-background :: Color -> Canvas ()
-background c = do
-  (V2 w h) <- gets csSize
-  lift $ setColor c >> C.rectangle 0 0 w h >> C.fill
-
--- | draw a point with stroke color (cairo emulates this with 1x1 rects!)
-point :: V2 Double -> Canvas ()
-point (V2 x y) = ifColor csFG $ \c -> do
-  C.rectangle x y 1 1
-  setColor c
-  C.fill
-
--- | draw a line between two points with stroke color
-line :: V2 Double -> V2 Double -> Canvas ()
-line (V2 x1 y1) (V2 x2 y2) = ifColor csFG $ \c -> do
-  C.moveTo x1 y1
-  C.lineTo x2 y2
-  setColor c
-  C.stroke
-
--- | draw a triangle connecting three points
-triangle :: V2 Double -> V2 Double -> V2 Double -> Canvas ()
-triangle (V2 x1 y1) (V2 x2 y2) (V2 x3 y3) = drawShape $ do
-  C.moveTo x1 y1
-  C.lineTo x2 y2
-  C.lineTo x3 y3
-  C.lineTo x1 y1
-
--- | draw a rectangle
-rect :: Dim -> Canvas ()
-rect (D x y w h) = drawShape $ C.rectangle x y w h
-
--- | draw a polygon connecting given points (equivalent to @'shape' ('ShapeRegular' True)@)
-polygon :: [V2 Double] -> Canvas ()
-polygon = shape (ShapeRegular True)
-
--- | Shape mode to use
-data ShapeMode = ShapeRegular Bool  -- ^regular path. flag decides whether the first and last point are connected
-               | ShapePoints -- ^just draw the points, no lines
-               | ShapeLines -- ^interpret points as pairs, draw lines
-               | ShapeTriangles -- ^interpret points as triples, draw triangles
-               | ShapeTriangleStrip -- ^draw triangle for every neighborhood of 3 points
-               | ShapeTriangleFan -- ^fix first point, draw triangles with every neighboring pair and first point
-               deriving (Show,Eq)
-
--- | draw shape along a given path using given @'ShapeMode'@.
--- (Processing: @beginShape(),vertex(),endShape()@)
-shape :: ShapeMode -> [V2 Double] -> Canvas ()
-shape (ShapeRegular closed) ((V2 x y):ps) = drawShape $ do
-  C.moveTo x y
-  forM_ ps $ \(V2 x' y') -> C.lineTo x' y'
-  when closed $ C.closePath
-shape (ShapeRegular _) _ = return ()
-shape ShapePoints ps = forM_ ps point
-shape ShapeLines (p1:p2:ps) = do
-  line p1 p2
-  shape ShapeLines ps
-shape ShapeLines _ = return ()
-shape ShapeTriangles (p1:p2:p3:ps) = do
-  triangle p1 p2 p3
-  shape ShapeTriangles ps
-shape ShapeTriangles _ = return ()
-shape ShapeTriangleStrip (p1:p2:p3:ps) = do
-  triangle p1 p2 p3
-  shape ShapeTriangleStrip (p2:p3:ps)
-shape ShapeTriangleStrip _ = return ()
-shape ShapeTriangleFan (p1:p2:p3:ps) = do
-  triangle p1 p2 p3
-  shape ShapeTriangleFan (p1:p3:ps)
-shape ShapeTriangleFan _ = return ()
-
-----
-
--- | draw arc: @arc dimensions startAngle endAngle@
-arc :: Dim -> Double -> Double -> Canvas ()
-arc (D x y w h) sa ea = drawShape $ do
-  C.save
-  C.translate (x+(w/2)) (y+(h/2))
-  C.scale (w/2) (h/2)
-  C.arc 0 0 1 sa ea
-  C.restore
-
--- | draw ellipse
-ellipse :: Dim -> Canvas ()
-ellipse dim = arc dim 0 (2*pi)
-
--- | draw circle: @circle leftCorner diameter@
-circle :: V2 Double -> Double -> Canvas ()
-circle (V2 x y) d = ellipse (D x y d d)
-
--- | draw circle: @circle centerPoint diameter@
-circle' :: V2 Double -> Double -> Canvas ()
-circle' (V2 x y) d = ellipse $ centered (D x y d d)
-
--- | draw cubic bezier spline: @bezier fstAnchor fstControl sndControl sndAnchor@
-bezier :: V2 Double -> V2 Double -> V2 Double -> V2 Double -> Canvas ()
-bezier (V2 x1 y1) (V2 x2 y2) (V2 x3 y3) (V2 x4 y4) = drawShape $ do
-  C.moveTo x1 y1
-  C.curveTo x2 y2 x3 y3 x4 y4
-
--- | draw quadratic bezier spline: @bezier fstAnchor control sndAnchor@
-bezierQ :: V2 Double -> V2 Double -> V2 Double -> Canvas ()
-bezierQ p0 p12 p3 = bezier p0 p1 p2 p3
-  where p1 = p0 + 2/3*(p12-p0)
-        p2 = p3 + 2/3*(p12-p3)
-
-----
-
--- | map a value from one range onto another
-mapRange :: Double -> (Double,Double) -> (Double,Double) -> Double
-mapRange v (l1,r1) (l2,r2) = (v-l1)*fac + l2
-  where fac = (r2-l2)/(r1-l1)
-
--- | convert degrees to radians
-radians :: Double -> Double
-radians d = d*pi/180
--- | convert radians to degrees
-degrees :: Double -> Double
-degrees r = r/pi*180
--- | force value v into given range
-constrain :: Double -> (Double,Double) -> Double
-constrain v (l,h) = max l $ min h v
-
--- | set new random seed
-randomSeed :: Int -> Canvas ()
-randomSeed s = liftIO $ setStdGen $ mkStdGen s
-
--- | get new random number
-random :: (Random a) => (a,a) -> Canvas a
-random = liftIO . randomRIO
-
--- | date and time as returned by getTime
-data Time = Time { year :: Int, month :: Int, day :: Int
-                 , hour :: Int, minute :: Int, second :: Int } deriving (Show,Eq)
-
--- | get current system time. Use the 'Time' accessors for specific components.
--- (Processing: @year(),month(),day(),hour(),minute(),second()@)
-getTime :: IO Time
-getTime = do
-  (UTCTime day time) <- getCurrentTime
-  let (y,m,d) = toGregorian day
-      (TimeOfDay h mins s) = timeToTimeOfDay time
-  return $ Time (fromIntegral y::Int) m d h mins (round s :: Int)
-
-----
-
--- | Stores an image surface with additional information
-data Image = Image {imageSurface::C.Surface, imageSize::V2 Int, imageFormat::Format}
-
--- | create a new empty image of given size
-createImage :: V2 Int -> Canvas Image
-createImage (V2 w h) = do
-  s <- liftIO $ C.createImageSurface FormatARGB32 w h
-  let img = Image s (V2 w h) FormatARGB32
-  track img
-  return img
-
---TODO: add checks (file exists, correct format, etc.)
--- | load a PNG image from given path.
-loadImagePNG :: FilePath -> Canvas Image
-loadImagePNG path = do
-  s <- liftIO $ C.imageSurfaceCreateFromPNG path
-  w <- C.imageSurfaceGetWidth s
-  h <- C.imageSurfaceGetHeight s
-  f <- C.imageSurfaceGetFormat s
-  let img = Image s (V2 w h) f
-  track img
-  return img
-
--- | Save an image as PNG to given file path
-saveImagePNG :: Image -> FilePath -> Canvas ()
-saveImagePNG (Image s _ _) fp = liftIO (C.surfaceWriteToPNG s fp)
-
--- | Render complete image on given coordinates
-image :: Image -> V2 Double -> Canvas ()
-image img@(Image _ (V2 w h) _) (V2 x y) =
-  image' img (D x y (fromIntegral w) (fromIntegral h))
-
--- | Render complete image inside given dimensions
-image' :: Image -> Dim -> Canvas ()
-image' img@(Image _ (V2 ow oh) _) =
-  blend OperatorSource img (D 0 0 (fromIntegral ow) (fromIntegral oh))
-
--- | Copy given part of image to given part of screen, using given blending
--- operator and resizing when necessary. Use 'OperatorSource' to copy without
--- blending effects. (Processing: @copy(),blend()@)
-blend :: Operator -> Image -> Dim -> Dim -> Canvas ()
-blend op (Image s _ _) sdim ddim = do
-  surf <- gets csSurface
-  lift $ copyFromToSurface op s sdim surf ddim
-
--- | get a copy of the image from current window (Processing: @get()@)
-grab :: Dim -> Canvas Image
-grab dim@(D _ _ w h) = do
-  surf <- gets csSurface
-  i@(Image s _ _) <- createImage (V2 (round w) (round h))
-  lift $ copyFromToSurface OperatorSource surf dim s (D 0 0 w h)
-  return i
-
-----
-
--- | Font definition
-data Font = Font{fontFace::String
-                ,fontSize::Double
-                ,fontBold::Bool
-                ,fontItalic::Bool} deriving (Show,Eq)
-
--- | set current font for text rendering
-textFont :: Font -> Canvas ()
-textFont f = lift $ setFont f
-
--- | get the size of the text when rendered in current font
-textSize :: String -> Canvas (V2 Double)
-textSize = return . dimSize . fst <=< textExtents
-
--- | get information about given text when rendered in current font.
--- returns tuple with location of top-left corner relative to
--- the origin and size of rendered text in the first component,
--- cursor advancement relative to origin in the second component
--- (also see 'Graphics.Rendering.Cairo.TextExtents').
-textExtents :: String -> Canvas (Dim, V2 Double)
-textExtents s = do
-  (C.TextExtents xb yb w h xa ya) <- lift $ C.textExtents s
-  return ((D xb yb w h),(V2 xa ya))
-
--- | render text. returns cursor advancement (@text = text' Baseline@)
-text :: String -> V2 Double -> Canvas (V2 Double)
-text = text' Baseline
-
--- | render text with specified alignment. returns cursor advancement
-text' :: Anchor -> String -> V2 Double -> Canvas (V2 Double)
-text' a str pos = do
-  (C.TextExtents xb yb w h xa ya) <- lift $ C.textExtents str
-  let (D xn yn _ _) = (if a==Baseline then id else aligned a) $ toD pos $ V2 w h
-      (V2 x' y') = (V2 xn yn) - if a/=Baseline then (V2 xb yb) else 0
-  ifColor csFG $ \c -> C.moveTo x' y' >> setColor c >> C.showText str
-  return $ V2 xa ya
-
--- helpers --
-
--- | draw a shape - first fill with bg color, then draw border with stroke color
-drawShape :: Render a -> Canvas ()
-drawShape m = do
- ifColor csBG $ \c -> m >> setColor c >> C.fill
- ifColor csFG $ \c -> m >> setColor c >> C.stroke
-
--- | if color (csFG/csBG) is set, perform given render block
-ifColor :: (CanvasState -> Maybe Color) -> (Color -> Render a) -> Canvas ()
-ifColor cf m = get >>= \cs -> case cf cs of
-                                Just c -> lift (m c) >> return ()
-                                Nothing -> return ()
-
--- | convert from 256-value RGBA to Double representation, set color
-setColor :: Color -> Render ()
-setColor (V4 r g b a) = C.setSourceRGBA (conv r) (conv g) (conv b) (conv a)
-  where conv = ((1.0/256)*).fromIntegral
-
--- | Add to garbage collection list
-track :: Image -> Canvas ()
-track img = modify $ \cs -> cs{csImages=img:csImages cs}
-
--- cairo helpers --
-
--- | helper: returns new surface with scaled content. does NOT cleanup!
-createScaledSurface :: C.Surface -> (V2 Double) -> Render C.Surface
-createScaledSurface s (V2 w h) = do
-  ow <- C.imageSurfaceGetWidth s
-  oh <- C.imageSurfaceGetHeight s
-  s' <- liftIO $ C.createSimilarSurface s C.ContentColorAlpha (round w) (round h)
-  C.renderWith s' $ do
-    C.scale (w/fromIntegral ow) (h/fromIntegral oh)
-    C.setSourceSurface s 0 0
-    pat <- C.getSource
-    C.patternSetExtend pat C.ExtendPad
-    C.setOperator C.OperatorSource
-    C.paint
-  return s'
-
--- | helper: returns new surface with only part of original content. does NOT cleanup!
-createTrimmedSurface :: C.Surface -> Dim -> Render C.Surface
-createTrimmedSurface s (D x y w h) = do
-  s' <- liftIO $ C.createSimilarSurface s C.ContentColorAlpha (round w) (round h)
-  C.renderWith s' $ do
-    C.setSourceSurface s (-x) (-y)
-    C.setOperator C.OperatorSource
-    C.rectangle 0 0 w h
-    C.fill
-  return s'
-
-copyFromToSurface :: Operator -> C.Surface -> Dim -> C.Surface -> Dim -> Render ()
-copyFromToSurface op src sdim@(D sx sy sw sh) dest (D x y w h) = do
-  ow <- C.imageSurfaceGetWidth src
-  oh <- C.imageSurfaceGetHeight src
-  let needsTrim = sx/=0 || sy/=0 || round sw/=ow || round sh/=oh
-      needsRescale = round sw/=round w || round sh/=round h
-  s' <- if needsTrim then createTrimmedSurface src sdim else return src
-  s'' <- if needsRescale then createScaledSurface s' (V2 w h) else return s'
-  C.renderWith dest $ do
-    C.save
-    C.setSourceSurface s'' x y
-    C.setOperator op
-    C.rectangle x y w h
-    C.fill
-    C.restore
-  when needsTrim $ C.surfaceFinish s'
-  when needsRescale $ C.surfaceFinish s''
-
--- | Set the current font
-setFont :: Font -> Render ()
-setFont (Font face sz bold italic) = do
-  C.selectFontFace face
-    (if italic then C.FontSlantItalic else C.FontSlantNormal )
-    (if bold   then C.FontWeightBold  else C.FontWeightNormal)
-  C.setFontSize sz
diff --git a/src/SDL/Cairo/Canvas/Interactive.hs b/src/SDL/Cairo/Canvas/Interactive.hs
deleted file mode 100644
--- a/src/SDL/Cairo/Canvas/Interactive.hs
+++ /dev/null
@@ -1,34 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-{-|
-Module      : SDL.Cairo
-Copyright   : Copyright (c) 2015 Anton Pirogov
-License     : MIT
-Maintainer  : anton.pirogov@gmail.com
-
-This module provides convenience functions for interactive development with ghci.
--}
-module SDL.Cairo.Canvas.Interactive (getInteractive) where
-
-import Control.Monad (forever)
-import Control.Concurrent (forkIO)
-
-import SDL
-
-import SDL.Cairo (createCairoTexture')
-import SDL.Cairo.Canvas (Canvas, withCanvas, background, gray)
-
--- |for testing and debugging usage with ghci. Starts up an SDL window,
--- forks a rendering loop and returns a function to draw in this window.
-getInteractive :: IO (Canvas () -> IO ())
-getInteractive = do
-  initializeAll
-  w <- createWindow "SDL2 Cairo Canvas Interactive" defaultWindow
-  r <- createRenderer w (-1) defaultRenderer
-  t <- createCairoTexture' r w
-  withCanvas t $ background $ gray 255
-  forkIO $ forever $ do
-    lockTexture t Nothing
-    copy r t Nothing Nothing
-    unlockTexture t
-    present r
-  return $ withCanvas t
