diff --git a/FreeTypeGL.cabal b/FreeTypeGL.cabal
--- a/FreeTypeGL.cabal
+++ b/FreeTypeGL.cabal
@@ -1,22 +1,22 @@
 Name:                FreeTypeGL
-Version:             0.0.1
-Synopsis:            Haskell fonts with OpenGL
+Version:             0.0.2
+Synopsis:            Loadable texture fonts for OpenGL.
 
 Description:         Based on the freetype-gl library, with large
                      modifications.
-
-                     This is similar to the FTGL library, but avoids
-                     C++, which makes it easier to wrap and work with
+                     .
+                     This is similar to the FTGL (<http://hackage.haskell.org/package/FTGL>)
+                     library, but avoids C++, which makes it easier to wrap and work with
                      in Haskell-land.
-
+                     .
                      This library is completely stand-alone (comes
                      with the required C sources), so you don't need
                      to install any C library prior to installing
                      this. cabal intall FreeTypeGL should work fine.
-
+                     .
                      Unfortunately, it seems not to perform as well as
                      FTGL on some setups.
-
+                     .
                      NOTE: Most of the demos and C-side documentation
                      are out-of-date, as the C side was heavily
                      modified, without updating many of the demos or
diff --git a/Graphics/Rendering/FreeTypeGL.hsc b/Graphics/Rendering/FreeTypeGL.hsc
--- a/Graphics/Rendering/FreeTypeGL.hsc
+++ b/Graphics/Rendering/FreeTypeGL.hsc
@@ -1,17 +1,32 @@
 {-# LANGUAGE ForeignFunctionInterface #-}
--- | A higher-level interface wrapping the low-level C API
 
+-------------------------------------------------------------------------------
+-- |
+-- Module      :  Graphics.Rendering.FreeTypeGL
+-- Copyright   :  (C) 2012 Eyal Lotem
+-- License     :  BSD-style (see the file LICENSE)
+-- Maintainer  :  Eyal Lotem <eyal.lotem@gmail.com>
+-- Stability   :  experimental
+-- Portability :  Haskell2010
+--
+-- FreeTypeGL lets one load and use texture fonts in an OpenGL
+-- context.  You can use it with GLFW-b
+-- (<http://hackage.haskell.org/package/GLFW-b>), GLUT
+-- (<http://hackage.haskell.org/package/GLUT>), or any other GL context
+-- you wish.  The main benefit of this library is that it can be
+-- installed with a pure "cabal install", no need to manually install
+-- any C bits.
+-------------------------------------------------------------------------------
+
 module Graphics.Rendering.FreeTypeGL
   ( FontDesc(..), fontDescFindFileName
   , Shader, newShader
   , Font, loadFont, textSize
-  , Vector2(..)
-  , Markup(..), noMarkup, Color4(..)
+  , Markup(..), noMarkup
   , TextRenderer, textRenderer, textRendererSize, renderText
-  , initialize
+  , Vector2(..), Color4(..)
   ) where
 
-import Control.Applicative
 import Foreign.C.String (withCString)
 import Foreign.C.Types (CInt(..))
 import Foreign.ForeignPtr (ForeignPtr)
@@ -31,6 +46,13 @@
 
 -- FontDesc:
 
+-- | A 'FontDesc' describes the desired properties of a system font.
+-- It's only purpose is querying the font_config library for the
+-- desired font.
+--
+-- NOTE: This functionality is only available if the
+-- package was configured with the use_font_config flag (e.g: cabal
+-- install -f use_font_config).
 data FontDesc = FontDesc
   { fdFamily :: String
   , fdSize :: Float
@@ -38,7 +60,12 @@
   , fdItalic :: Bool
   }
 
-fontDescFindFileName :: FontDesc -> IO String
+-- | Look up a system font file.
+--
+-- NOTE: This functionality is only available if the package was
+-- configured with the use_font_config flag
+-- (e.g: @cabal install -f use_font_config@).
+fontDescFindFileName :: FontDesc -> IO FilePath
 fontDescFindFileName (FontDesc family size bold italic) =
   withCString family $ \familyPtr ->
   IFD.fontDescFindFileName $ IFD.FontDesc familyPtr size bold italic
@@ -50,10 +77,11 @@
 foreign import ccall "freetypegl_init"
   c_freetypegl_init :: IO CInt
 
+
 initialize :: IO ()
 initialize = throwIf_ (/= 0) (("freetypegl_init returned" ++) . show) c_freetypegl_init
 
--- TODO: Use Paths_module
+-- | Make a 'Shader' needed for 'loadFont'.
 newShader :: IO Shader
 newShader = do
   initialize
@@ -63,38 +91,74 @@
 
 -- Font:
 
+-- | Represents a loaded font file with a configured face-size.
+--
+-- For different face sizes, you must load different fonts.
 data Font = Font
   { _fShader :: Shader
   , fFont :: ForeignPtr ITF.TextureFont
   }
 
-loadFont :: Shader -> FilePath -> Float -> IO Font
+-- | Load a 'Font' with a given size.
+loadFont
+  :: Shader   -- ^ A shader created with 'newShader'
+  -> FilePath -- ^ The font filename (e.g: \"foo.ttf\")
+  -> Float    -- ^ The desired face-size
+  -> IO Font  -- ^ The result loaded font
 loadFont shader fileName size = do
   textureFont <- ITF.new NotLCD fileName size
   return $ Font shader textureFont
 
+-- | A 'TextRenderer' is an intermediate representation of all font
+-- renderings. It represents the GL program to render the font, and
+-- may be re-used multiple times.  Re-using a TextRenderer is faster
+-- than computing the same renderer multiple times.
 data TextRenderer = TextRenderer
   { trBuffer :: ForeignPtr ITB.TextBuffer
   , trSize :: Vector2 Float
   }
 
-textRenderer :: Vector2 Float -> Markup -> Font -> String -> TextRenderer
-textRenderer pos markup (Font shader font) str = unsafePerformIO $
+-- | Make a 'TextRenderer' for a given font.
+textRenderer :: Markup -> Font -> String -> TextRenderer
+textRenderer markup (Font shader font) str = unsafePerformIO $
   alloca $ \pen ->
   alloca $ \markupPtr -> do
-    poke pen pos
+    poke pen (Vector2 0 0)
     poke markupPtr markup
     textBuffer <- ITB.new shader (Vector2 512 512) 1
     ITB.addText textBuffer markupPtr font pen str
     newPos <- peek pen
-    return $ TextRenderer textBuffer ((-) <$> newPos <*> pos)
+    return $ TextRenderer textBuffer newPos
 
+-- | Render a 'TextRenderer' to the GL context
+--
+-- NOTE: This will have the following side effects:
+--
+-- * GL's blend will be enabled
+--
+-- * GL's Texture2D will be enabled
+--
+-- * GL's color will be changed
+--
+-- * GL's color_material will be disabled
+--
+-- * GL's blend_func will be set to (SRC_ALPHA, ONE_MINUS_SRC_ALPHA)
+--
+-- * GL's blend_color will be modified
 renderText :: TextRenderer -> IO ()
 renderText = ITB.render . trBuffer
 
+-- | Get the size of a 'TextRenderer'
+--
+-- NOTE: If you don't need to also render the text, it is better to
+-- use the faster 'textSize' function.
 textRendererSize :: TextRenderer -> Vector2 Float
 textRendererSize = trSize
 
+-- | Compute the text size of a given text in a given font
+--
+-- NOTE: If you also need to render the text, it is better to make a
+-- 'TextRenderer'.
 textSize :: Font -> String -> Vector2 Float
 textSize font str =
   unsafePerformIO $ ITF.textSize (fFont font) str
diff --git a/Graphics/Rendering/FreeTypeGL/Internal/Markup.hsc b/Graphics/Rendering/FreeTypeGL/Internal/Markup.hsc
--- a/Graphics/Rendering/FreeTypeGL/Internal/Markup.hsc
+++ b/Graphics/Rendering/FreeTypeGL/Internal/Markup.hsc
@@ -17,27 +17,29 @@
   where
     p (off, val) = pokeElemOff ptr off val
 
-
+-- | A Markup record defines what text effects to combine when
+-- rendering text
 data Markup = Markup
-  { rise :: Float
-  , spacing :: Float
-  , gamma :: Float
+  { gamma :: Float
+    -- ^ Not implemented yet. Set to 1.0
   , foreground_color :: Color4 Float
+    -- ^ Foreground color
   , background_color :: Color4 Float
-  , outline :: Maybe (Color4 Float)
+    -- ^ Background color
   , underline :: Maybe (Color4 Float)
+    -- ^ Optional underline color
   , overline :: Maybe (Color4 Float)
+    -- ^ Optional overline color
   , strikethrough :: Maybe (Color4 Float)
+    -- ^ Optional strikethrough color
   }
 
+-- | Default no-markup (White text on transparent background)
 noMarkup :: Markup
 noMarkup = Markup
-  { rise = 0.0
-  , spacing = 0.0
-  , gamma = 1.0
+  { gamma = 1.0
   , foreground_color = Color4 1 1 1 1
   , background_color = Color4 0 0 0 0
-  , outline = Nothing
   , underline = Nothing
   , overline = Nothing
   , strikethrough = Nothing
@@ -48,9 +50,7 @@
 applyTuple :: (a -> b, a -> c) -> a -> (b, c)
 applyTuple (fx, fy) arg = (fx arg, fy arg)
 
-outlinePtrs, underlinePtrs, overlinePtrs, strikethroughPtrs ::
-  Ptr Markup -> (Ptr CInt, Ptr Float)
-outlinePtrs       = applyTuple ((#ptr markup_t, outline      ), (#ptr markup_t, outline_color))
+underlinePtrs, overlinePtrs, strikethroughPtrs :: Ptr Markup -> (Ptr CInt, Ptr Float)
 underlinePtrs     = applyTuple ((#ptr markup_t, underline    ), (#ptr markup_t, underline_color))
 overlinePtrs      = applyTuple ((#ptr markup_t, overline     ), (#ptr markup_t, overline_color))
 strikethroughPtrs = applyTuple ((#ptr markup_t, strikethrough), (#ptr markup_t, strikethrough_color))
@@ -61,8 +61,6 @@
   sizeOf _    = #size markup_t
   alignment _ = #alignment markup_t
   peek ptr = do
-    rise' <- (#peek markup_t, rise) ptr
-    spacing' <- (#peek markup_t, spacing) ptr
     gamma' <- (#peek markup_t, gamma) ptr
     foreground_color' <- peekColor $ (#ptr markup_t, foreground_color) ptr
     background_color' <- peekColor $ (#ptr markup_t, background_color) ptr
@@ -73,20 +71,17 @@
         case b of
           0 -> return Nothing
           _ -> Just <$> peekColor colorPtr
-    outline' <- peekAnnotation outlinePtrs
     underline' <- peekAnnotation underlinePtrs
     overline' <- peekAnnotation overlinePtrs
     strikethrough' <- peekAnnotation strikethroughPtrs
     return $
-      Markup rise' spacing' gamma'
+      Markup gamma'
       foreground_color' background_color'
-      outline' underline' overline' strikethrough'
+      underline' overline' strikethrough'
   poke ptr
-    (Markup rise' spacing' gamma'
+    (Markup gamma'
       foreground_color' background_color'
-      outline' underline' overline' strikethrough') = do
-    (#poke markup_t, rise) ptr rise'
-    (#poke markup_t, spacing) ptr spacing'
+      underline' overline' strikethrough') = do
     (#poke markup_t, gamma) ptr gamma'
     pokeColor ((#ptr markup_t, foreground_color) ptr) foreground_color'
     pokeColor ((#ptr markup_t, background_color) ptr) background_color'
@@ -99,7 +94,6 @@
             pokeColor colorPtr color
         where
           (boolPtr, colorPtr) = ptrs ptr
-    pokeAnnotation outlinePtrs outline'
     pokeAnnotation underlinePtrs underline'
     pokeAnnotation overlinePtrs overline'
     pokeAnnotation strikethroughPtrs strikethrough'
diff --git a/Graphics/Rendering/FreeTypeGL/Internal/Shader.hsc b/Graphics/Rendering/FreeTypeGL/Internal/Shader.hsc
--- a/Graphics/Rendering/FreeTypeGL/Internal/Shader.hsc
+++ b/Graphics/Rendering/FreeTypeGL/Internal/Shader.hsc
@@ -4,6 +4,9 @@
 import Foreign.C.String (CString, withCString)
 import Foreign.C.Types (CUInt(..))
 
+-- | A 'Shader' represents a GL program to render text. Needs to be
+-- loaded just once for all fonts. Use
+-- 'Graphics.Rendering.FreeTypeGL.newShader' to make one.
 newtype Shader = Shader CUInt
 
 foreign import ccall "shader_load"
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,30 +1,30 @@
-Copyright (c)2011, Jason Dagit <dagitj@gmail.com>
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-    * Redistributions of source code must retain the above copyright
-      notice, this list of conditions and the following disclaimer.
-
-    * Redistributions in binary form must reproduce the above
-      copyright notice, this list of conditions and the following
-      disclaimer in the documentation and/or other materials provided
-      with the distribution.
-
-    * Neither the name of Jason Dagit <dagitj@gmail.com> nor the names of other
-      contributors may be used to endorse or promote products derived
-      from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+Copyright (c)2011, Eyal Lotem <eyal.lotem@gmail.com>
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Eyal Lotem <eyal.lotem@gmail.com> nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/demos/hellobye.hs b/demos/hellobye.hs
--- a/demos/hellobye.hs
+++ b/demos/hellobye.hs
@@ -28,36 +28,45 @@
   GL.ortho 0 resX 0 resY (-1) 1
   GL.matrixMode $= GL.Modelview 0
 
-markup :: FGL.Markup
-markup = FGL.Markup
-  { FGL.rise = 0
-  , FGL.spacing = 0
-  , FGL.gamma = 1.0
+helloMarkup :: FGL.Markup
+helloMarkup = FGL.Markup
+  { FGL.gamma = 1.0
   , FGL.foreground_color = Color4 1 0 0 1
   , FGL.background_color = Color4 0.3 0.3 0.3 0.3
-  , FGL.outline = Just $ Color4 0.1 0.1 0.1 0.8
   , FGL.underline = Just $ Color4 0.8 0.3 0.2 0.3
   , FGL.overline = Just $ Color4 0.1 0.5 0.1 1
-  , FGL.strikethrough = Just $ Color4 0 0 0.8 1
+  , FGL.strikethrough = Nothing
   }
 
+byeMarkup :: FGL.Markup
+byeMarkup = FGL.noMarkup
+  { FGL.strikethrough = Just $ Color4 0 0 0.8 1
+  }
+
 main :: IO ()
 main = do
   [ttfFilename] <- getArgs
   initScreen
   GLFW.setWindowCloseCallback $ fail "Quit"
 
+  let
+    fontSize :: Fractional a => a
+    fontSize = 72.0
   shader <- FGL.newShader
-  font <- FGL.loadFont shader ttfFilename 72.0
-  let hello = FGL.textRenderer (GL.Vector2 100 100) markup font "Hello world"
-      bye = FGL.textRenderer (GL.Vector2 100 200) FGL.noMarkup font "Bye world"
+  font <- FGL.loadFont shader ttfFilename fontSize
+  let hello = FGL.textRenderer helloMarkup font "Hello world"
+      bye = FGL.textRenderer byeMarkup font "Bye world"
 
   forever $ do
     reshape
-    GL.clearColor $= GL.Color4 0.2 0 0 0
+    GL.clearColor $= GL.Color4 0 0 0 0
     GL.clear [GL.ColorBuffer, GL.DepthBuffer]
     GL.texture GL.Texture2D $= GL.Disabled
-    FGL.renderText hello
-    FGL.renderText bye
+    let
+      drawAt (GL.Vector2 x y) r = GL.preservingMatrix $ do
+        GL.translate (GL.Vector3 x y (0 :: GL.GLfloat))
+        FGL.renderText r
+    drawAt (GL.Vector2 0 (fontSize + 2)) hello
+    drawAt (GL.Vector2 0 resY) bye
     GLFW.swapBuffers
     GLFW.pollEvents
