diff --git a/Data/Font.hs b/Data/Font.hs
--- a/Data/Font.hs
+++ b/Data/Font.hs
@@ -1,15 +1,15 @@
 {-# LANGUAGE TupleSections, GeneralizedNewtypeDeriving #-}
 module Data.Font (
   Font,
-  font,glyph
+  font,glyph,glyph'
   ) where
 
-import Algebra
+import Definitive
 import Data.Raster
 import Graphics.Rendering.TrueType.STB hiding (Font,findGlyph)
 import qualified Graphics.Rendering.TrueType.STB as TT
 import Control.Exception (SomeException)
-import Data.Vector.Storable (unsafeFromForeignPtr0)
+import qualified Data.Vector.Storable as V
 import Codec.Picture
 
 newtype Font = Font [TT.Font]
@@ -26,6 +26,11 @@
           where scl = scaleForPixelHeight (getFontVerticalMetrics f^.thunk)
         fg = map2 (by thunk) TT.findGlyph
         bm = map3 (fst.by thunk) TT.newGlyphBitmap
+glyph' :: Font -> (Char,Float) -> Raster
+glyph' = map2 (maybe undefined id) glyph
 bitmap2Image :: Bitmap -> Raster
-bitmap2Image (Bitmap (w,h) p) = ImageY8 (Image w h (unsafeFromForeignPtr0 p (w*h)))^.raster
-
+bitmap2Image (Bitmap (w,h) p) = ImageY8 (Image w h v')^.raster
+  where v' = V.concat (reverse $ zipWith mkSlice posts (tail posts))
+        v = V.unsafeFromForeignPtr0 p (w*h)
+        posts = [0,w..V.length v]
+        mkSlice a b = V.slice a (b-a) v
diff --git a/Data/Input/Button.hs b/Data/Input/Button.hs
new file mode 100644
--- /dev/null
+++ b/Data/Input/Button.hs
@@ -0,0 +1,12 @@
+module Data.Input.Button (
+  ButtonState,KeyButtonState(Press,Release), Button(..)
+  ) where
+
+import Definitive
+import Graphics.UI.GLFW
+
+data Button = CharKey Char
+            | SpecialKey SpecialKey
+            | MouseButton MouseButton
+            deriving (Eq,Show)
+type ButtonState = KeyButtonState
diff --git a/Data/Raster.hs b/Data/Raster.hs
--- a/Data/Raster.hs
+++ b/Data/Raster.hs
@@ -3,7 +3,7 @@
   Raster,PNG,BMP,JPG,bmp,jpg,png,raster,
   ) where
 
-import Algebra
+import Definitive
 import Data.Serialize
 import Codec.Picture
 
diff --git a/Data/Scene.hs b/Data/Scene.hs
new file mode 100644
--- /dev/null
+++ b/Data/Scene.hs
@@ -0,0 +1,68 @@
+module Data.Scene where
+
+import Definitive
+import Data.Vertex
+import Data.Texture
+
+type Scene t = [Widget t]
+data Widget t = Shape [ShapeProp] (Shape t)
+              | SubScene [Transform t] (Scene t)
+              | Cached (IO ())
+data Shape t = Polygon [Vertex t]
+             | Quads [V4 (Vertex t)]
+             | Triangles [V3 (Vertex t)]
+             | TriangleStrip [Vertex t]
+data Vertex t = Vertex [VertexProp t] !t !t !t
+data VertexProp t = Color (V4 t)
+                  | TexCoord (V2 t)
+data ShapeProp = Texture Texture
+data Transform t = Translate !t !t !t
+                 | Rotate !t (V3 t)
+                 | Zoom !t !t !t
+
+_Vertex :: Iso ([VertexProp t],t,t,t) ([VertexProp t'],t',t',t') (Vertex t) (Vertex t')
+_Vertex = iso (\(Vertex ps x y z) -> (ps,x,y,z)) (\(ps,x,y,z) -> Vertex ps x y z)
+
+vert = Vertex []
+cvert c = Vertex [c]
+
+vProps :: Lens' (Vertex t) [VertexProp t]
+vProps = _Vertex.l'1
+
+pQuad p a b c d = V4 a b c d <&> \c@(x,y,z) -> Vertex (p c) x y z 
+pSquare p (x,y) w = pQuad p (x,y,0) (x',y,0) (x',y',0) (x,y',0)
+  where x' = x+w ; y' = y+w
+quad = pQuad (const [])
+square = pSquare (const [])
+
+textured = liftA2 f texMap
+  where texMap = V4 (txc 0 0) (txc 1 0) (txc 1 1) (txc 0 1)
+        txc = map2 TexCoord V2
+        f c v = v & vProps%~(c:)
+
+cube (x,y,z) (w,h,j) = [
+  quad a b c d,
+  quad a b b' a',
+  quad b' b c c',
+  quad d' c' c d,
+  quad a a' d' d,
+  quad d' c' b' a'
+  ]
+  where x' = x+w ; y' = y+h ; z' = z+j
+        [a,a',b,b',d,d',c,c'] = liftA3 (,,) [x,x'] [y,y'] [z,z']
+
+rgb r g b = V4 r g b 1
+grey g = rgb g g g
+gray = grey
+black = grey 0
+white = grey 1
+
+red = rgb 1 0 0
+green = rgb 0 1 0
+blue = rgb 0 0 1
+yellow = green+red
+magenta = red+blue
+cyan = green+blue
+
+zoom = (join.join) Zoom
+
diff --git a/Data/Texture.hs b/Data/Texture.hs
new file mode 100644
--- /dev/null
+++ b/Data/Texture.hs
@@ -0,0 +1,7 @@
+module Data.Texture (
+  module Data.Texture.Core,
+  module Data.Font,
+  ) where
+
+import Data.Texture.Core
+import Data.Font
diff --git a/Data/Texture/Core.hs b/Data/Texture/Core.hs
new file mode 100644
--- /dev/null
+++ b/Data/Texture/Core.hs
@@ -0,0 +1,63 @@
+{-# LANGUAGE RankNTypes #-}
+module Data.Texture.Core (
+  Texture,
+  texture,texture',readTexture,readTextures,readTextures'
+  ) where
+
+import Definitive
+import Data.Serialize
+import Codec.Picture
+import Codec.Picture.Types (convertImage)
+import qualified Graphics.Rendering.OpenGL as GL
+import Data.Vertex
+import Data.Raster
+
+-- |The abstract Texture type
+data Texture = Texture GL.TextureObject
+             deriving Show
+
+data TextureFormat = RGB | RGBA | Greyscale | GreyscaleA
+
+pixelFormats RGBA = (GL.RGBA',GL.RGBA)
+pixelFormats RGB = (GL.RGB',GL.RGB)
+pixelFormats Greyscale = (GL.SLuminance8,GL.Luminance)
+pixelFormats GreyscaleA = (GL.SLuminance8Alpha8,GL.LuminanceAlpha)
+
+-- |Convert a Raster to a texture
+texture (yb raster -> i) = by thunk $ yb _eitherT $ do
+  let conv (ImageRGB8 (Image w h d))  = return (pixelFormats RGB,w,h,d)
+      conv (ImageY8 (Image w h d))    = return (pixelFormats Greyscale,w,h,d)
+      conv (ImageRGBA8 (Image w h d)) = return (pixelFormats RGBA,w,h,d)
+      conv (ImageYA8 (Image w h d))   = return (pixelFormats GreyscaleA,w,h,d)
+      conv (ImageYCbCr8 i)            = conv (ImageRGB8 (convertImage i))
+      conv _                          = throw "Unhandled image format"
+
+  ((f,f'),w,h,d) <- by _eitherT $ pure $ conv i 
+
+  lift $ do
+    [tex] <- GL.genObjectNames 1
+    GL.textureBinding GL.Texture2D GL.$= Just tex
+    unsafeWith d $ GL.build2DMipmaps GL.Texture2D f (fromIntegral w) (fromIntegral h)
+      . GL.PixelData f' GL.UnsignedByte
+    GL.textureFilter  GL.Texture2D GL.$= ((GL.Linear', Just GL.Nearest), GL.Linear')
+    GL.textureFunction GL.$= GL.Modulate
+    return (Texture tex)
+texture' = (error<|>id).texture
+
+listToEither [] = Left zero
+listToEither (~(_,a):_) = Right a
+
+-- |Read a texture from a file.
+readTexture name = (readBytes name <&> joinMap texture . listToEither . yb parser image)
+  where image = yb jpg<$>serializable
+                <+>yb png<$>serializable
+                <+>yb bmp<$>serializable
+-- |Try to read a structure of files into a structure of textures.
+readTextures = map sequence . traverse readTexture
+-- |Read a structure of files into a structure of textures, raising an error
+-- if it fails.
+readTextures' = map2 (error<|>id) readTextures
+
+instance Graphics Texture where
+  draw (Texture t) = GL.textureBinding GL.Texture2D GL.$= Just t
+
diff --git a/Data/Vertex.hs b/Data/Vertex.hs
new file mode 100644
--- /dev/null
+++ b/Data/Vertex.hs
@@ -0,0 +1,90 @@
+module Data.Vertex where
+
+import Definitive
+
+-- |A two-element vector
+data V2 t = V2 !t !t
+          deriving Show
+instance Semigroup a => Semigroup (V2 a) where (+) = plusA
+instance Monoid a => Monoid (V2 a) where zero = zeroA
+instance Functor V2 where map f (V2 x y) = V2 (f x) (f y)
+instance Unit V2 where pure = join V2
+instance Applicative V2 where
+  V2 fx fy <*> V2 x y = V2 (fx x) (fy y)
+instance Foldable V2 where
+  fold (V2 a b) = a+b
+instance Traversable V2 where
+  sequence (V2 a b) = V2<$>a<*>b
+instance Ord t => Eq (V2 t) where
+  a == b = compare a b == EQ
+instance Ord t => Ord (V2 t) where
+  compare (V2 x y) (V2 x' y')
+    | x<x' && y<y' = LT
+    | x>x' && y>y' = GT
+    | otherwise = EQ
+instance Lens1 a a (V2 a) (V2 a) where
+  l'1 = lens (\(V2 a _) -> a) (\ (V2 _ c) b -> V2 b c)
+instance Lens2 a a (V2 a) (V2 a) where
+  l'2 = lens (\(V2 _ a) -> a) (\ (V2 c _) b -> V2 c b)
+
+-- |A three-element vector
+data V3 t = V3 !t !t !t
+          deriving Show
+instance Semigroup a => Semigroup (V3 a) where (+) = plusA
+instance Monoid a => Monoid (V3 a) where zero = zeroA
+instance Functor V3 where map f (V3 x y z) = V3 (f x) (f y) (f z)
+instance Unit V3 where pure = (join.join) V3
+instance Applicative V3 where
+  V3 fx fy fz <*> V3 x y z = V3 (fx x) (fy y) (fz z)
+instance Foldable V3 where
+  fold (V3 a b c) = a+b+c
+instance Traversable V3 where
+  sequence (V3 a b c) = V3<$>a<*>b<*>c
+instance Ord t => Eq (V3 t) where
+  a == b = compare a b == EQ
+instance Ord t => Ord (V3 t) where
+  compare (V3 x y z) (V3 x' y' z')
+    | x<x' && y<y' && z<z' = LT
+    | x>x' && y>y' && z>z' = GT
+    | otherwise = EQ
+instance Lens1 x x (V3 x) (V3 x) where
+  l'1 = lens (\(V3 x _ _) -> x) (\(V3 _ y z) x -> V3 x y z)
+instance Lens2 y y (V3 y) (V3 y) where
+  l'2 = lens (\(V3 _ y _) -> y) (\(V3 x _ z) y -> V3 x y z)
+instance Lens3 z z (V3 z) (V3 z) where
+  l'3 = lens (\(V3 _ _ z) -> z) (\(V3 x y _) z -> V3 x y z)
+
+-- |A three-element vector
+data V4 t = V4 !t !t !t !t
+          deriving Show
+instance Semigroup a => Semigroup (V4 a) where (+) = plusA
+instance Monoid a => Monoid (V4 a) where zero = zeroA
+instance Functor V4 where map f (V4 x y z w) = V4 (f x) (f y) (f z) (f w)
+instance Unit V4 where pure = (join.join.join) V4
+instance Applicative V4 where
+  V4 fx fy fz fw <*> V4 x y z w = V4 (fx x) (fy y) (fz z) (fw w)
+instance Foldable V4 where
+  fold (V4 a b c d) = a+b+c+d
+instance Traversable V4 where
+  sequence (V4 a b c d) = V4<$>a<*>b<*>c<*>d
+instance Ord t => Eq (V4 t) where
+  a == b = compare a b == EQ
+instance Ord t => Ord (V4 t) where
+  compare (V4 x y z w) (V4 x' y' z' w')
+    | x<x' && y<y' && z<z' && w<w' = LT
+    | x>x' && y>y' && z>z' && w>w'= GT
+    | otherwise = EQ
+instance Lens1 x x (V4 x) (V4 x) where
+  l'1 = lens (\(V4 x _ _ _) -> x) (\(V4 _ y z t) x -> V4 x y z t)
+instance Lens2 y y (V4 y) (V4 y) where
+  l'2 = lens (\(V4 _ y _ _) -> y) (\(V4 x _ z t) y -> V4 x y z t)
+instance Lens3 z z (V4 z) (V4 z) where
+  l'3 = lens (\(V4 _ _ z _) -> z) (\(V4 x y _ t) z -> V4 x y z t)
+instance Lens4 t t (V4 t) (V4 t) where
+  l'4 = lens (\(V4 _ _ _ t) -> t) (\(V4 x y z _) t -> V4 x y z t)
+    
+class Graphics g where
+  draw :: g -> IO ()
+
+_V4 :: Iso (t,t,t,t) (u,u,u,u) (V4 t) (V4 u)
+_V4 = iso (\(V4 x y z t) -> (x,y,t,z)) (\(x,y,z,t) -> V4 x y z t)
diff --git a/IO/Graphics.hs b/IO/Graphics.hs
new file mode 100644
--- /dev/null
+++ b/IO/Graphics.hs
@@ -0,0 +1,182 @@
+{-# LANGUAGE FlexibleInstances, ViewPatterns, ImplicitParams, RankNTypes #-}
+module IO.Graphics (
+  module Data.Reactive,module Definitive,module Data.Vertex,module Data.Scene,module Data.Input.Button,
+  
+  -- * Creating windows & Handling events
+  EventHandler,Coord,Position,Title,Size(..),
+  spawnWindow,
+  
+  -- * Examining and modifying the window
+  GettableStateVar,SettableStateVar,
+    
+  -- * Drawing the scene
+  drawScene,
+  ) where
+
+import Definitive
+import Data.Reactive 
+import Data.Scene
+import Data.Input.Button
+import qualified Graphics.UI.GLFW as GLFW
+import qualified Graphics.Rendering.OpenGL.GL.Texturing.Application as GL (texture)
+import qualified Graphics.Rendering.OpenGL.GL.CoordTrans as GL (Position(..))
+import qualified Graphics.Rendering.OpenGL.GL.BeginEnd as GL (PrimitiveMode(..))
+import qualified Graphics.Rendering.OpenGL.GL.StateVar as GL (get)
+import Graphics.Rendering.OpenGL.Raw.Core31.Types (GLdouble,GLfloat)
+import Graphics.Rendering.OpenGL.GL.StateVar (($=),GettableStateVar,SettableStateVar)
+import Graphics.Rendering.OpenGL.GL.Texturing.Specification (TextureTarget2D(Texture2D))
+import Graphics.Rendering.OpenGL.GL.VertexArrays (Capability(Enabled))
+import Graphics.Rendering.OpenGL.GL.Texturing.Parameters (generateMipmap)
+import Graphics.Rendering.OpenGL.GL.Colors (shadeModel,ShadingModel(Smooth))
+import Graphics.Rendering.OpenGL.GL.LineSegments (lineSmooth)
+import Graphics.Rendering.OpenGL.GL.PerFragment (blend,blendFunc,BlendingFactor(..),depthFunc,ComparisonFunction(..))
+import Graphics.Rendering.OpenGL.GL.LineSegments (lineWidth)
+import Graphics.Rendering.OpenGL.GL.Framebuffer (clearColor,clear,ClearBuffer(..))
+import Graphics.Rendering.OpenGL.GL.VertexSpec (Color4(..),TexCoord2(..),texCoord,vertex,color)
+import Graphics.Rendering.OpenGL.GL.CoordTrans (Size(..),viewport,matrix,matrixMode,MatrixMode(Modelview,Projection),GLmatrix,loadIdentity,translate,rotate,scale)
+import Graphics.Rendering.OpenGL.GLU.Matrix (perspective)
+import Graphics.Rendering.OpenGL.GL.Tensor (Vector3(..),Vertex3(..))
+import Graphics.Rendering.OpenGL.GL.BeginEnd (renderPrimitive)
+import Control.Concurrent
+import Data.Vertex
+
+type Coord = GLfloat
+type Position = V2 Coord
+
+instance Semigroup GLdouble
+instance Monoid GLdouble
+instance Negative GLdouble
+instance Disjonctive GLdouble
+instance Semiring GLdouble
+instance Ring GLdouble
+
+instance Semigroup Coord
+instance Monoid Coord
+instance Negative Coord
+instance Disjonctive Coord
+instance Semiring Coord
+instance Ring Coord
+
+-- |A function from the a window's inputs to a frame event
+type EventHandler = ( ?mousePosition :: Event Seconds Position
+                    , ?buttonChanges :: Event Seconds (Button,ButtonState) ) => IO (Event Seconds (IO ()))
+type Title = String
+
+-- |Create an OpenGL window and sinks all events into the given handler. 
+spawnWindow :: ( ?birthTime :: Seconds ) => Title -> EventHandler -> IO ()
+spawnWindow title sink = between GLFW.initialize GLFW.terminate $ between openWindow GLFW.closeWindow $ do
+  -- This code was partially stolen from http://www.haskell.org/haskellwiki/GLFW
+  sizes <- newChan
+  refreshes <- newChan
+  
+  -- open window
+  GLFW.windowTitle $= title
+
+  -- enable 2D texturing
+  GL.texture Texture2D $= Enabled 
+  generateMipmap Texture2D $= Enabled
+  
+  shadeModel $= Smooth
+  -- enable antialiasing
+  lineSmooth $= Enabled
+  blend      $= Enabled
+  blendFunc  $= (SrcAlpha, OneMinusSrcAlpha)
+  lineWidth  $= 1.5
+  -- The clear color is black
+  clearColor $= Color4 0 0 0 0
+  -- enable the depth buffer for correct 3D rendering
+  depthFunc $= Just Less
+
+  -- set 2D orthogonal view inside windowSizeCallback because
+  -- any change to the Window size should result in different
+  -- OpenGL Viewport.
+  GLFW.windowSizeCallback $= \ size@(Size w h) -> do
+    writeChan sizes size
+    viewport $= (GL.Position 0 0, size)
+    between (matrixMode $= Projection) (matrixMode $= Modelview 0) $ do
+      loadIdentity
+      let aov = 45 -- the angle of view
+          ratio = fromIntegral w/fromIntegral h
+      perspective aov ratio 0.1 100
+      translate (Vector3 0 (0::GLdouble) (-max (1/ratio) 1/tan (aov*pi/360)))
+
+  GLFW.windowRefreshCallback $= writeChan refreshes ()
+    
+  -- Now we define our own little stuff
+  -- It doesn't seem very logical to poll events when swapping buffers. 
+  GLFW.disableSpecial GLFW.AutoPollEvent
+  let callbackE c f = do
+        ch <- newChan
+        c $= f (writeChan ch)
+        event (readChan ch)
+  _keyboard <- callbackE GLFW.keyCallback curry
+  _mousePos <- callbackE GLFW.mousePosCallback (promap (\(GL.Position x y) -> V2 x y))
+  _mouseButton <- callbackE GLFW.mouseButtonCallback curry
+  _size <- event (readChan sizes)
+  t'refresh <- event (readChan refreshes)
+  let _button = (l'1%~fromK<$>_keyboard) + (l'1%~MouseButton<$>_mouseButton)
+      fromK (GLFW.CharKey c) = CharKey c
+      fromK (GLFW.SpecialKey k) = SpecialKey k
+      relative (Size w h) (V2 x y) = V2 ((x'-xc)/m) ((yc-y')/m)
+        where [x',y',w',h'] = realToFrac<$>[x,y,w,h]
+              xc = w'/2 ; yc = h'/2 ; m = min w' h'/2
+  
+  ev <- let ?mousePosition = relative<$>Reactive (Size 1 1) _size<|*>_mousePos
+            ?buttonChanges = _button
+        in sink
+
+  -- GLFW doesn't handle multithreading nicely, so we have to
+  -- manually interleave polling events and rendering within
+  -- the main thread. And since waiting for events may block
+  -- while the rendering might occur, we have to poll regularly.
+  -- I chose a 15ms polling period because it was both reactive
+  -- enough for keyboard and mouse events and not too heavy on
+  -- the CPU. 
+  let period = ms 15
+      poll = GLFW.pollEvents <$ atTimes [?birthTime,?birthTime+period..]
+  try unit $ realize $ realtime (ev + (const<$>Reactive unit ev<|*>(void _size+t'refresh))) + poll
+  where openWindow = GLFW.openWindow (Size 400 400) [GLFW.DisplayDepthBits 16,GLFW.DisplayAlphaBits 8] GLFW.Window
+
+clearScreen = clear [ColorBuffer,DepthBuffer]
+
+instance Graphics (Widget Coord) where 
+  draw (Shape ps s) = traverse_ draw ps >> draw s
+  draw (SubScene trs s) = preservingMatrix $ (traverse_ draw (reverse trs) >> drawScene s)
+    where draw (Translate dx dy dz) = translate (Vector3 dx dy dz)
+          draw (Rotate a (V3 ax ay az)) = rotate a (Vector3 ax ay az)
+          draw (Zoom zx zy zz) = scale zx zy zz
+  draw (Cached c) = c
+instance Graphics (Shape Coord) where
+  draw (Polygon p) = renderPrimitive GL.Polygon $ traverse_ draw p
+  draw (Quads sqs) = renderPrimitive GL.Quads $ traverse_ draw (Compose sqs)
+  draw (Triangles trs) = renderPrimitive GL.Triangles $ traverse_ draw (Compose trs)
+  draw (TriangleStrip s) = renderPrimitive GL.TriangleStrip $ traverse_ draw s
+instance Graphics (Vertex Coord) where
+  draw (Vertex ps x y z) = traverse_ draw ps >> vertex (Vertex3 x y z)
+instance Graphics (VertexProp Coord) where
+  draw (Color (V4 r g b a)) = color (Color4 r g b a)
+  draw (TexCoord (V2 x y)) = texCoord (TexCoord2 x y)
+instance Graphics ShapeProp where
+  draw (Texture t) = draw t
+
+withMatrix f = GL.get (matrix Nothing) >>= f
+preservingMatrix ma = withMatrix $ \old ->
+  ma <* (matrix Nothing $= (old :: GLmatrix Coord))
+
+drawScene :: Scene Coord -> IO ()
+drawScene = between clearScreen GLFW.swapBuffers . traverse_ draw
+
+instance Functor Vector3 where
+  map f (Vector3 x y z) = Vector3 (f x) (f y) (f z)
+instance Unit Vector3 where pure = join (join Vector3)
+instance Applicative Vector3 where
+  Vector3 fx fy fz <*> Vector3 x y z = Vector3 (fx x) (fy y) (fz z)
+
+instance Functor Vertex3 where
+  map f (Vertex3 x y z) = Vertex3 (f x) (f y) (f z)
+instance Unit Vertex3 where pure = join (join Vertex3)
+instance Applicative Vertex3 where
+  Vertex3 fx fy fz <*> Vertex3 x y z = Vertex3 (fx x) (fy y) (fz z)
+instance Traversable Vertex3 where
+  sequence (Vertex3 a b c) = liftA3 Vertex3 a b c
+
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,69 +1,39 @@
-Bill and Ted's Public License
-=============================
-
-Everyone is permitted to copy and distribute verbatim or modified
-copies of this license document, and changing it is allowed as long as
-the name of the license is changed.
-
-PREAMBLE
+THE FREE BEER PUBLIC LICENSE
 --------
 
-The “Greater Lunduke License” is inspired, in part, by the wisdom of
-the Two Great Ones, Bill S. Preston, Esq. and Ted “Theodore” Logan.
-Namely that we should all “be excellent to each other”, that being
-“bogus” is “most non-triumphant” and that all dudes should “party on”.
+The Free Beer Public License is designed to provide free (as in beer,
+hence the name), unlimited access to any content for anyone who wishes
+it, without restrictions such as property rights or affordability.
 
-This license applies those concepts in such a way that it is
-applicable to all forms of content, including, but not limited to:
-software, books, music, movies and various works of art.
+This license embodies the philosophy that all software (and more
+generally all good ideas) is designed to solve a particular problem,
+and that the only way to judge its quality is by how well it solves
+that problem, rather than other unrelated criteria such as sellability
+or merchandability.
 
+All kinds of works may be licensed under the FBPL, as long as the
+aforementioned works are within the legal rights of the provider to
+give.
+
 TERMS AND CONDITIONS
 --------------------
 
-### 1. Be Excellent To Each Other.
-
-The consumer of this work is granted the right to utilize this work in
-conjunction with any mechanism that is capable of utilizing it, in the
-form supplied by the content creator, without limitation as to
-specific hardware or software.
-
-The consumer of this work may make copies of this work (physical or
-otherwise) for backup purposes.
-
-The consumer of this work may lend this work to another individual
-provided that the following two conditions are met :
-  
-  1. the lender no longer utilizes or possesses the work
-  2. the work is not presently lent to another individual
-
-The consumer of this work may sell this work to another individual
-provided that the following two conditions are met :
-
-  1. the seller no longer utilizes or possesses the work 
-  2. once the work is sold, the seller relinquishes all rights and
-      copies of the work to the buyer.
+### 1. Free as in Beer
 
-### 2. Don’t Be Bogus.
+The provider of this work shall make it available, free of any charge,
+monetary or otherwise, to the consumer, to use without restrictions or
+any kind of supervision.
 
-The consumer of this work shall not redistribute modified, or
-unmodified, copies of this work without explicit written permission
-from the creator of this work.  The only exceptions allowed to this
-rule are the provisions outlined in section 1 of this license
+### 2. Freely taken is freely given
 
-The consumer of this work shall not hold the creator of this work
-liable for anything the consumer does, or does not, do, or the results
-of utilizing this work.
+The consumer of this work may redistribute it as well as derived works
+in any way he or she chooses, as long as the work itself and any
+derived work remain Free as in Beer, as per the first clause.
 
-### 3. Party On, Dudes!
+### 3. The Burden of Proof
 
-The creator of this work provides the work in a form that contains no
-mechanism to disable the utilization of the work after a specific
-date, period of time or number of uses.
+The provider of this work shall also supply explanations for how the
+work was realized if requested, in the form of source code for example, or
+supply the means to access such explanations.
 
-If additional works, which are created and wholly owned by the work’s
-creator, are required to utilize this work, those additional works
-must also be made available to the consumer so long as the following
-conditions are met :
-  
-  1. doing so is possible
-  2. doing so does not cause harm to the creator of the work.
+Every such explanation shall be Free as in Beer, as per the first clause.
diff --git a/definitive-graphics.cabal b/definitive-graphics.cabal
--- a/definitive-graphics.cabal
+++ b/definitive-graphics.cabal
@@ -1,19 +1,23 @@
+-- content information
 name:          definitive-graphics
-version:       1.0
-
+category:      Graphics
 synopsis:      A definitive package allowing you to open windows, read image files and render text to be displayed or saved
 description:   
+
+-- meta-information
 author:        Marc Coiffier
 maintainer:    marc.coiffier@gmail.com
+version:       1.2
 license:       OtherLicense
 license-file:  LICENSE
 
+-- build information
 build-type:    Simple
 cabal-version: >=1.10
 
 library
-  exposed-modules: Data.Raster Data.Font
-  build-depends: base (== 4.6.*), definitive-base (== 1.0.*), containers (== 0.5.*), deepseq (== 1.3.*), array (== 0.5.*), bytestring (== 0.10.*), definitive-parser (== 1.0.*), vector (== 0.10.*), primitive (== 0.5.*), cpu (== 0.1.*), utf8-string (== 0.3.*), JuicyPixels (== 3.1.*), binary (== 0.7.*), mtl (== 2.1.*), transformers (== 0.3.*), zlib (== 0.5.*), stb-truetype (== 0.1.*)
+  exposed-modules: IO.Graphics Data.Scene Data.Vertex Data.Texture Data.Texture.Core Data.Raster Data.Font Data.Input.Button
+  build-depends: base (== 4.6.*), definitive-base (== 1.2.*), containers (== 0.5.*), deepseq (== 1.3.*), array (== 0.5.*), bytestring (== 0.10.*), vector (== 0.10.*), primitive (== 0.5.*), definitive-reactive (== 1.0.*), clock (== 0.4.*), definitive-parser (== 1.2.*), cpu (== 0.1.*), utf8-string (== 0.3.*), JuicyPixels (== 3.1.*), binary (== 0.7.*), mtl (== 2.1.*), transformers (== 0.3.*), zlib (== 0.5.*), stb-truetype (== 0.1.*), GLFW (== 0.5.*)
   default-extensions: RebindableSyntax NoMonomorphismRestriction TypeOperators ViewPatterns FlexibleInstances MultiParamTypeClasses
   ghc-options: -W -threaded
   default-language: Haskell2010
