diff --git a/Graphics/PDF.hs b/Graphics/PDF.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/PDF.hs
@@ -0,0 +1,66 @@
+---------------------------------------------------------
+-- |
+-- Copyright   : (c) alpha 2006
+-- License     : BSD-style
+--
+-- Maintainer  : misc@NOSPAMalpheccar.org
+-- Stability   : experimental
+-- Portability : portable
+--
+-- PDF API for Haskell
+---------------------------------------------------------
+module Graphics.PDF
+  (-- * HPDF
+   -- ** The PDF type
+    PDF
+   -- ** PDF Operator used to build a PDF document (in addition to the Monoid ones)
+   ,withContext, (<>), emptyPdf, PdfCmd
+   -- ** PDF Transformations
+   , module Graphics.PDF.Geometry
+    -- ** PDF Text
+   , module Graphics.PDF.Text
+   -- ** PDF Shapes
+   , module Graphics.PDF.Shape
+   -- ** PDF Colors
+   , module Graphics.PDF.Color
+   -- ** PDF Shadings
+   , module Graphics.PDF.Shading
+    -- ** PDF Font
+   , module Graphics.PDF.Font
+   -- ** PDF File
+   , module Graphics.PDF.File
+   -- * Example
+   -- $example
+  ) where
+  
+
+import Graphics.PDF.LowLevel
+import Graphics.PDF.Geometry
+import Graphics.PDF.Shape
+import Graphics.PDF.Color
+import Graphics.PDF.Shading
+import Graphics.PDF.File
+import Graphics.PDF.Text
+import Graphics.PDF.Font
+
+
+-- $example
+-- > test :: IO ()
+-- > test = let document = rgbSpace <>
+-- >                       chooseFont Helvetica 70 <> 
+-- >                       applyMatrix (translate 50 0) <>
+-- >                       applyMatrix (rotate (Degree 45)) <>
+-- >                       clipText 0 0 "HPDF" <> 
+-- >                       applyMatrix (rotate (Degree (-45))) <>
+-- >                       applyMatrix (translate (-50) 0) <>
+-- >                       fillColor (Rgb 0 0 1) <>
+-- >                       fillRectangle 0 0 100 100 <>
+-- >                       fillColor (Rgb 1 0 0) <>
+-- >                       setAlpha 0.4 <>
+-- >                       fillRectangle 50 50 100 100 <>
+-- >                       resetAlpha <>
+-- >                       fillColor (Rgb 0 1 0) <>
+-- >                       fillRectangle 80 80 100 100 <>
+-- >                       emptyPdf 180 180
+-- >        in
+-- >        writePdf "test.pdf" document 
diff --git a/Graphics/PDF/Color.hs b/Graphics/PDF/Color.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/PDF/Color.hs
@@ -0,0 +1,60 @@
+-- | Functions used to control the colors in a PDF document
+
+module Graphics.PDF.Color 
+ (-- * Colors
+  -- ** Data types
+  Color(..)
+  -- ** Operators
+  , strokeColor,fillColor,rgbSpace, setAlpha,resetAlpha
+ )
+ where
+ 
+import Graphics.PDF.LowLevel
+import Text.Printf
+  
+-- | Color data type
+data Color = Rgb Float Float Float -- ^ RGB Color
+
+instance Show Color where
+  show (Rgb r g b) = "rgb" ++ (show r) ++ (show g) ++ (show b)
+
+-- | Create a new state dictionary for an alpha value           
+newState :: Float -> PdfObject
+newState a =  pdfDictionary [("Type",PdfName "ExtGState"),
+                         ("CA",PdfFloat a),
+                         ("ca",PdfFloat a)
+                 ]
+                     
+
+                        
+-- | Change the stroke color in a PDF document                    
+strokeColor :: Color -> PdfCmd
+strokeColor c  = case c of
+                    Rgb r g b -> (PdfSC r g b,[])
+                   
+    
+                            
+-- | Change the fill color in a PDF document                    
+fillColor :: Color -> PdfCmd
+fillColor c  =  case c of
+                    Rgb r g b -> (PdfSF r g b,[])
+                   
+                              
+-- | Change the alpha setting for transparency in the document                  
+setAlpha :: Float -> PdfCmd
+setAlpha a  =  (PdfAlpha dictName,[(PdfState,dictName,PdfUnknownPointer dictName),
+                (PdfAnyObject,dictName,newState a)]) 
+                where
+                    dictName = printf "alpha%f" a
+                            
+
+       
+-- | Reset alpha value to opaque for stroke and fill colors                       
+resetAlpha :: PdfCmd
+resetAlpha = (PdfResetAlpha,[])
+                            
+-- | Set color space to RGB. Must always be used before starting to use any color.            
+rgbSpace :: PdfCmd
+rgbSpace  = (PdfRgbSpace,[])
+
+    
diff --git a/Graphics/PDF/File.hs b/Graphics/PDF/File.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/PDF/File.hs
@@ -0,0 +1,174 @@
+module Graphics.PDF.File
+  (-- * PDF generation
+   writePdf
+  ) where
+  
+import System.IO
+import Control.Monad
+import Control.Monad.State
+import Graphics.PDF.LowLevel
+import Text.Printf
+import qualified Data.Map as Map
+import Data.List
+import System.Mem
+
+-- writeSome text and increment the size counter
+writeText :: Handle -> String -> StateT (Int,String) IO ()
+writeText f text = do (s,t) <- get
+                      put (s + (length text),t)
+                      lift $ hPutStr f (seq s text)
+                      
+    
+writeStream :: Handle -> [Cmd] -> StateT (Int,String) IO ()                  
+writeStream f c = mapM_ (drawAction f) c
+
+drawAction :: Handle -> Cmd -> StateT (Int,String) IO ()   
+drawAction f  (PdfQ actions)  = do writeText f "\nq"
+                                   writeStream f actions
+                                   writeText f "\nQ"
+                                   
+                                      
+drawAction f  action  = writeText f (show action)
+
+class PdfWrite a where 
+  writePdfObject :: Handle -> a -> Int -> StateT (Int,String) IO Int
+  
+instance PdfWrite PdfDictionary where
+  writePdfObject f (PdfDictionary d) k = do writeText f "<<\n" 
+                                            Map.foldWithKey item (return ()) d
+                                            writeText f ">>"  
+                                            return 0
+                                         where
+                                            item key itm m = do m
+                                                                writeText f ("/" ++ key ++ " " )
+                                                                writePdfObject f itm k
+                                                                writeText f "\n"
+
+instance PdfWrite PdfObject where
+  writePdfObject f (PdfInt a) k = do writeText f (show a) 
+                                     return 0
+  writePdfObject f (PdfFloat a) k = do writeText f (show a) 
+                                       return 0
+  writePdfObject f (PdfUnknownPointer s) k = error ("The object " ++ s ++ " has not been found or defined")
+  writePdfObject f (PdfPointer a) k = do writeText f $ (show a) ++ " 0 R"
+                                         return 0
+  writePdfObject f (PdfString a) k = do writeText f $ "(" ++ a ++ ")"
+                                        return 0
+  writePdfObject f (PdfBool a) k =  if a then do writeText f $ "true"
+                                                 return 0
+                                         else do writeText f $ "false"
+                                                 return 0
+  writePdfObject f (PdfName a) k = do writeText f $ "/" ++ a
+                                      return 0
+  writePdfObject f (PdfDict d) k | pdfDictionaryEmpty d = do writeText f "<< >>" 
+                                                             return 0
+                                 | otherwise =  do writePdfObject f d k
+                                                   return 0
+  writePdfObject f (PdfArray []) k = do writeText f "[]" 
+                                        return 0 
+  writePdfObject f (PdfArray l) k = do writeText f "["
+                                       mapM_ (\x -> writePdfObject f x k >> writeText f " ") $ l 
+                                       writeText f " ]"
+                                       return 0
+                                      
+  writePdfObject f (PdfStream c) k = do  writeText f "<<\n"
+                                         writeText f ("/Length " ++ (show (k+1)) ++ " 0 R")
+                                         writeText f "\n>>\n"
+                                         writeText f "stream"
+                                         (before,_)  <- get
+                                         writeStream f (stream c)
+                                         (after,_)  <- get
+                                         writeText f "\nendstream"
+                                         return (after-before)
+                       where
+                         stream (Content(s)) = s
+                         
+                         
+
+resources = pdfDictionary [("ExtGState",PdfUnknownPointer "ExtGState"),
+                                         ("XObject",PdfUnknownPointer "XObject"),
+                                         ("Font",PdfUnknownPointer "Font"),
+                                         ("Pattern",PdfUnknownPointer "Pattern"),
+                                         ("Shading",PdfUnknownPointer "Shading"),
+                                         ("ProcSet",PdfUnknownPointer "ProcSet")
+                                     ]
+header = "%PDF-1.4\n"
+obj1   = pdfDictionary  [("Type", PdfName "Catalog"),
+                  ("Outlines",PdfUnknownPointer "Obj2"),
+                  ("Pages",PdfUnknownPointer "Obj3")
+                 ]
+obj2  =  pdfDictionary [("Type",PdfName "Outlines"),
+                  ("Count", PdfInt 0)
+                ]
+obj3  =  pdfDictionary  [("Type", PdfName "Pages"),
+                  ("Kids",PdfArray [PdfUnknownPointer "Obj4"]),
+                  ("Count",PdfInt 1)
+                 ]
+obj4 pdf = pdfDictionary [("Type",PdfName "Page"),
+                             ("Parent",PdfUnknownPointer "Obj3"),
+                             ("MediaBox",PdfArray [PdfInt 0,PdfInt 0,PdfInt (round (x pdf)),PdfInt (round (y pdf))]),
+                             ("Contents",PdfUnknownPointer "Main"),
+                             ("Resources",resources)
+               ]
+obj6  =  PdfArray [PdfName "PDF"]
+beginxref nb = ("xref\n" ++ printf "0 %d\n" (nb+1))
+trailer np = ("trailer\n" ++
+              (printf "  << /Size %d\n" ((nbObjects np)+1)) ++
+              (printf "     /Root %d 0 R\n" (objectIndex "Obj1" np) ) ++
+              "  >>\n\
+              \startxref\n")
+eof = "%%EOF"
+
+                        
+standardAlpha = pdfDictionary [("Type",PdfName "ExtGState"),
+                         ("ca",PdfFloat 1.0),
+                         ("CA",PdfFloat 1.0)
+                        ]
+                 
+-- write and object, increment the size counter and the object number
+writeObj f k o maxnb = do (s,t) <- get
+                          put (s,t ++ printf "%010d 00000 n \n" (s::Int) )
+                          writeText f (printf "%d 0 obj\n"  k)
+                          len <- writePdfObject f o maxnb
+                          writeText f ("\nendobj\n\n")
+                          return len
+                 
+ -- Write the xref table
+writeXref f p = do (_,t) <- get
+                   writeText f (beginxref (nbObjects p))
+                   writeText f t
+                   writeText f ("\n")
+ -- write all pending objects
+writeObjects f thepdf = do len <- foldM write 0 (allObjects thepdf)
+                           return len
+                        where
+                          write old (k,s) =  do len <- writeObj f k s maxnb
+                                                return(len+old)
+                          maxnb = nbObjects thepdf
+                      
+-- Write the PDF document to file
+writePdf :: String -> PDF -> IO ()
+writePdf fileName pdf = 
+                     -- New pdf with object describing a one page PDF
+                 let newpdf = computeObjectPos .
+                              addObject "Obj1" obj1 .
+                              addObject "Obj2" obj2 .
+                              addObject "Obj3" obj3 .
+                              addObject "Obj4" (obj4 pdf) .
+                              addObject "ProcSet" obj6 .
+                              addState "standardAlpha" standardAlpha $ pdf
+                 in
+                 do f <- lift $ openBinaryFile fileName WriteMode
+                    writeText f header
+                    len <- writeObjects f newpdf
+                    writeEndPdf f len (addObject "ZZZ" (PdfInt len) newpdf)
+                 `evalStateT` (0,"0000000000 65535 f \n")
+                 where
+                    writeEndPdf f len epdf = do writeObj f (nbObjects epdf) (PdfInt len) (nbObjects epdf)
+                                                (xrefStart,_) <- get
+                                                writeXref f epdf
+                                                writeText f (trailer epdf)
+                                                writeText f (printf "%d\n" (xrefStart::Int))
+                                                writeText f eof
+                                                lift $ hClose f
+ 
diff --git a/Graphics/PDF/Font.hs b/Graphics/PDF/Font.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/PDF/Font.hs
@@ -0,0 +1,61 @@
+-- | Function used to control the fonts in a PDF document
+
+module Graphics.PDF.Font
+ (-- * Font
+  -- * Font type
+  Font(..)
+  -- ** Font selection
+  ,chooseFont
+ )
+ where
+ 
+import Graphics.PDF.LowLevel
+
+
+-- | List of supported fonts
+data Font = TimesRoman
+          | TimesBold
+          | TimesItalic
+          | Helvetica
+          | HelveticaBold
+          | HelveticaOblique
+          | HelveticaBoldOblique
+          | Courier
+          | CourierBold
+          | CourierOblique
+          | CourierBoldOblique
+          | Symbol
+          | ZapfDingbats
+          
+instance Show Font where
+ show TimesRoman = "Times-Roman"
+ show TimesBold = "Times-Bold"
+ show TimesItalic = "Times-Italic"
+ show Helvetica = "Helvetica"
+ show HelveticaBold = "Helvetica-Bold"
+ show HelveticaOblique = "Helvetica-Oblique"
+ show HelveticaBoldOblique = "Helvetica-BoldOblique"
+ show Courier = "Courier"
+ show CourierBold = "Courier-Bold"
+ show CourierOblique = "Courier-Oblique"
+ show CourierBoldOblique = "Courier-BoldOblique"
+ show Symbol = "Symbol"
+ show ZapfDingbats = "ZapfDingbats"
+ 
+type Size = Int
+
+-- | Create a new font dictionary
+newFont :: String -> PdfObject
+newFont name= pdfDictionary [("Type",PdfName "FontDescriptor"),
+                         ("Subtype",PdfName "Type1"),
+                         ("BaseFont",PdfName name)
+                        ]
+
+-- | Select new font in the document             
+chooseFont :: Font -> Size -> PdfCmd
+chooseFont font fontSize  = (PdfBT fontName fontSize,[(PdfFont,fontName,PdfUnknownPointer fontName),
+                              (PdfAnyObject, fontName, newFont fontName)
+                              ]) 
+                            where
+                              fontName = show font
+                                
diff --git a/Graphics/PDF/Geometry.hs b/Graphics/PDF/Geometry.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/PDF/Geometry.hs
@@ -0,0 +1,71 @@
+-- | Transformations of a PDF document
+
+module Graphics.PDF.Geometry 
+ (-- * Geometry
+  -- ** Units
+  Angle(..)
+  -- ** Data types
+  , Matrix
+  -- ** Transformations
+  , rotate, translate, scale, applyMatrix, identity
+ )
+ where
+ 
+import Graphics.PDF.LowLevel
+
+
+-- | Angle 
+data Angle = Degree Float -- ^ Angle in degrees
+           | Radian Float -- ^ Angle in radians
+
+-- | A transformation matrix  (affine transformation)         
+newtype Matrix = Matrix(Float,Float,Float,Float,Float,Float) deriving (Eq)
+
+-- | Identity matrix
+identity :: Matrix
+identity = Matrix(1.0,0,0,1.0,0,0)
+
+instance Show Matrix where
+ show (Matrix(ma,mb,mc,md,me,mf)) = "Matrix " ++ (unwords [(show ma),(show mb),(show mc),(show md),(show me),(show mf)])
+   
+instance Num Matrix where
+  --  Matrix addition
+  (+) (Matrix(ma,mb,mc,md,me,mf)) (Matrix(na,nb,nc,nd,ne,nf)) = 
+        Matrix( (ma+na), (mb+nb), (mc+nc), (md+nd), (me+ne), (mf+nf)) 
+  --  Matrix multiplication
+  --  ma mb 0   na nb 0
+  --  mc md 0   nc nd 0
+  --  me mf 1   ne nf 1
+  (*) (Matrix(ma,mb,mc,md,me,mf)) (Matrix(na,nb,nc,nd,ne,nf)) = 
+        Matrix( (ma*na+mb*nc), (ma*nb + mb*nd ), (mc*na+md*nc), (mc*nb +md*nd), (me*na+mf*nc+ne), (me*nb+mf*nd+nf)) 
+  negate (Matrix(ma,mb,mc,md,me,mf))  =
+        Matrix( (-ma), (-mb), (-mc), (-md), (-me), (-mf))
+  abs m = m
+  signum _ = identity
+  fromInteger i = Matrix(r,0,0,r, 0, 0)
+                  where
+                   r = fromInteger i
+
+
+-- | Apply a transformation matrix to the current coordinate frame
+applyMatrix :: Matrix -> PdfCmd
+applyMatrix (Matrix(a,b,c,d,e,f))  = (PdfCM a b c d e f,[])
+
+-- | Rotation matrix
+rotate :: Angle -> Matrix
+rotate r = Matrix ((cos(radian)), (sin(radian)), (-sin(radian)) ,(cos(radian)), 0, 0)
+              where
+                radian = case r of
+                         Degree angle -> angle / 180 *  pi
+                         Radian angle -> angle
+            
+ 
+-- | Translation matrix            
+translate :: Float -> Float -> Matrix
+translate tx ty  = Matrix( 1, 0, 0, 1 ,tx ,ty)
+              
+
+-- | Scaling matrix          
+scale :: Float -> Float -> Matrix
+scale sx sy  = Matrix (sx, 0, 0, sy, 0 ,0 )
+             
diff --git a/Graphics/PDF/LowLevel.hs b/Graphics/PDF/LowLevel.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/PDF/LowLevel.hs
@@ -0,0 +1,308 @@
+{-# OPTIONS_GHC -fglasgow-exts #-}
+-- #hide
+module Graphics.PDF.LowLevel
+ (-- * PDF low level operators
+  -- ** Data types
+   PdfObject(..),PdfDictionary(..),PDF(..),Content(..),PdfCmd,CreatedObject,ObjectKind(..), Cmd(..), PdfString(..),TextRendering(..)
+  -- ** Data type support functions
+  ,dictionaryExtract, pdfDictionaryEmpty, emptyDictionary, emptyPdf
+  -- ** Low level object operators
+  ,nbObjects, objectIndex, allObjects,pdfDictionary
+  -- ** Low level PDF operators
+  ,addObject, addFont, addState, addNewContent, applyCommand,computeObjectPos,(<>),withContext
+  ) where
+  
+import qualified Data.Map as Map
+import Data.Monoid
+import Text.Printf
+import Text.Show
+
+-- | A PDF string
+newtype PdfString = S String
+
+data TextRendering = TextStroke 
+                   | TextFill
+                   | TextFillStroke
+                   | TextClip
+
+data Cmd =  PdfRgbSpace
+          | PdfSC Float Float Float
+          | PdfSF Float Float Float
+          | PdfBT String Int
+          | PdfCM Float Float Float Float Float Float 
+          | PdfL Float Float Float Float
+          | PdfW Float
+          | PdfRect Float Float Float Float
+          | PdfFillRect Float Float Float Float
+          | PdfDash [Float] Float
+          | PdfStartPath Float Float
+          | PdfAddLineToPath Float Float
+          | PdfAddRectangleToPath Float Float Float Float
+          | PdfText TextRendering Float Float [PdfString]
+          | PdfStroke
+          | PdfFill
+          | PdfClip
+          | PdfFillAndStroke
+          | PdfClosePath
+          | PdfAlpha String
+          | PdfQ [Cmd] 
+          | PdfResetAlpha
+          | PdfCharSpacing Float
+          | PdfWordSpacing Float
+          | PdfLeading Float
+          | PdfStrokePattern String
+          | PdfFillPattern String
+          | PdfNone
+          
+-- | Escape character whose meaning is special in a PDF String
+instance Show PdfString where
+  show (S a) = "("++a++")"
+  showList l = \s -> r ++ s
+               where
+                 r = case l of
+                       [] -> ""
+                       (a:l) -> (show a) ++ " Tj " ++ concat (zipWith (++) (map show l) (repeat " ' "))
+          
+instance Show Cmd where
+  show (PdfQ l) = error "Require a special processing"
+  show PdfNone = ""
+  show PdfClip = "\nW"
+  show PdfResetAlpha = "\n/standardAlpha gs"
+  show (PdfAlpha s) = printf "\n/%s gs" s
+  show (PdfStrokePattern s) = printf "\n/Pattern CS /%s SCN" s
+  show (PdfFillPattern s) = printf "\n/Pattern cs /%s scn" s
+  show PdfRgbSpace = "\n/DeviceRGB CS\n/DeviceRGB cs\n/standardAlpha gs"
+  show (PdfSC r g b) = printf "\n%f %f %f SC" r g b
+  show (PdfSF r g b) = printf "\n%f %f %f sc" r g b
+  show (PdfBT fontName fontSize) = printf "\nBT /%s %d Tf ET" fontName fontSize
+  show (PdfCM a b c d e f) = printf "\n%f %f %f %f %f %f cm" a b c d e f
+  show (PdfL xa ya xb yb) = printf "\nh %f %f m %f %f l S" xa ya xb yb
+  show (PdfW w) = printf "\n%f w" w
+  show (PdfRect xa ya width height) = printf "\nh %f %f %f %f re S" xa ya width height
+  show (PdfFillRect xa ya width height) = printf "\nh %f %f %f %f re f" xa ya width height
+  show (PdfDash a phase) = printf "\n[%s] %f d" (unwords . map show $ a) phase
+  show (PdfStartPath xa ya) = printf "\nh %f %f m" xa ya
+  show (PdfClosePath) = "\nh"
+  show (PdfAddLineToPath xa ya) = printf "\n%f %f l" xa ya
+  show (PdfAddRectangleToPath xa ya width height) = printf "\n%f %f %f %f re" xa ya width height
+  show PdfStroke = "\nS"
+  show PdfFill = "\nf"
+  show PdfFillAndStroke = "\nB"
+  show (PdfText TextStroke px py s) = printf "\n1 Tr BT %f %f Td %s ET" px py (show s)
+  show (PdfText TextFill px py s) = printf "\n0 Tr BT %f %f Td %s ET" px py (show s)
+  show (PdfText TextFillStroke px py s) = printf "\n2 Tr BT %f %f Td %s ET" px py (show s)
+  show (PdfText TextClip px py s) = printf "\n7 Tr BT %f %f Td %s ET" px py (show s)
+  show (PdfCharSpacing x) = printf "\n%f Tc" x
+  show (PdfWordSpacing x) = printf "\n%f Tw" x
+  show (PdfLeading x) = printf "\n%f TL" x
+  
+-- | PDF commands for a picture
+newtype Content = Content ([Cmd])
+
+instance Monoid Content where
+  mempty = Content ([])
+  mappend (Content(ca)) (Content(cb)) = Content(ca ++ cb)
+  
+-- | A PDF object as defined in PDF specification
+data PdfObject = PdfInt Int 
+               | PdfFloat Float 
+               | PdfString String 
+               | PdfName String 
+               | PdfDict PdfDictionary 
+               | PdfUnknownPointer String 
+               | PdfPointer Int 
+               | PdfBool Bool
+               | PdfArray [PdfObject]
+               | PdfStream Content
+               
+-- | A dictionary of objects
+newtype PdfDictionary = PdfDictionary (Map.Map String PdfObject)
+
+dictionaryExtract :: PdfDictionary -> Map.Map String PdfObject
+dictionaryExtract (PdfDictionary a) = a
+
+-- | Kind of created object
+data ObjectKind = PdfAnyObject | PdfFont | PdfState | PdfShading | PdfPatternObject
+
+-- | Object created by a command
+type CreatedObject = (ObjectKind,String,PdfObject)
+
+-- | Type returned by a PDF command creator
+type PdfCmd = (Cmd,[CreatedObject])
+
+-- | Number of objects in the PDF
+nbObjects :: PDF -> Int
+nbObjects p = let PdfDictionary d = (objects p) 
+              in
+               Map.size d
+               
+                          
+ 
+-- | Object index in the PDF              
+objectIndex :: String -> PDF -> Int
+objectIndex s p = let PdfDictionary d = (objects p) 
+                  in
+                   (Map.findIndex s d) + 1
+
+-- | List of object contents with their index
+allObjects :: PDF -> [(Int,PdfObject)]
+allObjects p = let d = dictionaryExtract (objects p)
+               in
+                   map createItem . Map.toAscList $ d
+                  where
+                    createItem (k,s) = ((objectIndex k p),s)
+
+-- Name of PDF object containing the content
+contentName :: String
+contentName = "Main"
+
+-- | PDF data with its state, xobject and font dictionary
+data PDF = PDF {content :: Content,
+                objects :: PdfDictionary,
+                extgstate :: PdfDictionary,
+                xobject :: PdfDictionary,
+                font :: PdfDictionary,
+                pattern :: PdfDictionary,
+                shading :: PdfDictionary,
+                x :: Float,
+                y :: Float
+               }
+               
+
+-- | Check is a dictionary is empty
+pdfDictionaryEmpty :: PdfDictionary -> Bool
+pdfDictionaryEmpty (PdfDictionary m) | Map.null m = True
+                                     | otherwise  = False     
+                                     
+emptyDictionary :: PdfDictionary
+emptyDictionary = PdfDictionary Map.empty
+
+-- | Create a new empty document of given width and height
+emptyPdf :: Float -> Float -> PDF
+emptyPdf width height = PDF {
+    objects = emptyDictionary,
+    content = mempty, 
+    extgstate=emptyDictionary,
+    xobject=emptyDictionary,
+    font=emptyDictionary,
+    pattern=emptyDictionary,
+    shading=emptyDictionary,
+    x = width,
+    y = height
+ }
+ 
+-- | Insert an object into a PdfDictionary
+insertObject :: String -> PdfObject -> PdfDictionary -> PdfDictionary
+insertObject name object (PdfDictionary d) = PdfDictionary (Map.insert name object d)
+
+-- | Add an object of a PDF
+addObject :: String -> PdfObject -> PDF -> PDF
+addObject name object p = p {objects = insertObject name object (objects p)}
+                                         
+-- | Add a font object of a PDF
+addFont :: String -> PdfObject -> PDF -> PDF
+addFont name object p  = p {font=insertObject name object (font p)}
+ 
+-- | Add a font object of a PDF
+addState :: String -> PdfObject -> PDF -> PDF
+addState name object p  = p {extgstate=insertObject name object (extgstate p)}
+
+-- | Add a shading object of a PDF
+addShading :: String -> PdfObject -> PDF -> PDF
+addShading name object p  = p {shading=insertObject name object (shading p)}
+
+-- | Add a pattern object of a PDF
+addPattern :: String -> PdfObject -> PDF -> PDF
+addPattern name object p  = p {pattern=insertObject name object (pattern p)}
+
+                                                                           
+-- | Add a created object     
+addCreatedObject :: CreatedObject -> PDF -> PDF
+addCreatedObject (PdfFont,name,object) p =  addFont name object p
+addCreatedObject (PdfState,name,object) p = addState name object p
+addCreatedObject (PdfShading,name,object) p = addShading name object p
+addCreatedObject (PdfPatternObject,name,object) p = addPattern name object p
+addCreatedObject (_,name,object) p = addObject name object p
+                                                                   
+pdfDictionary :: [(String,PdfObject)] -> PdfObject
+pdfDictionary l = PdfDict (PdfDictionary(Map.fromList l))
+ 
+
+-- PDF document can be concatenated              
+instance Monoid PDF where
+  mempty = emptyPdf 0 0
+  mappend pdfa pdfb = PDF {objects = union (objects pdfa) (objects pdfb),
+     content = (content pdfa) `mappend` (content pdfb),
+     extgstate = union (extgstate pdfa) (extgstate pdfb),
+     xobject = union (xobject pdfa) (xobject pdfb),
+     font = union (font pdfa) (font pdfb),
+     pattern = union (pattern pdfa) (pattern pdfb),
+     shading = union (shading pdfa) (shading pdfb),
+     x = max (x pdfa) (x pdfb),
+     y = max (y pdfa) (y pdfb)
+   } where
+     union (PdfDictionary a) (PdfDictionary b) = PdfDictionary (Map.union a b)
+     
+
+-- | Generate a new PDF with an updated content
+addNewContent :: Cmd -> PDF -> PDF
+addNewContent s p =   p {content = Content(s : c)} 
+                      where
+                        Content(c) = content p
+                     
+-- | Generate a new PDF with an updated content
+replaceContent :: Content -> PDF -> PDF
+replaceContent s p = p {content = s}
+                     
+-- | Create a new PDF graphic where the graphic context is saved\/restored and thus isolated
+-- from additional modifications that could be applied to this PDF document
+withContext :: PDF -> PdfCmd
+withContext f =  (PdfQ l,newobjs)
+                 where
+                   Content(l) = content f 
+                   newobjs = listOfObjects PdfState (extgstate f) ++ listOfObjects PdfFont (font f)
+                   listOfObjects s d = map tag (Map.toList (dictionaryExtract d))
+                                       where
+                                         tag (n,o) = (s,n,o)
+
+--addNewContent "\nq"  (f `mappend` (addNewContent "\nQ"  mempty))
+
+                
+
+-- | add a PDF command to the current PDF content                     
+applyCommand :: Cmd -> PDF -> PDF
+applyCommand cmd p = addNewContent cmd  p
+
+-- | Update the pointer value of the PDF dictionary given element of list objects.
+-- The specific dictionary extgstate, xobject and font are merged with the generic dictionary
+computeObjectPos :: PDF -> PDF
+computeObjectPos p = p {content = mempty,
+                        objects = renumber newobjects,
+                        extgstate= emptyDictionary,
+                        xobject= emptyDictionary,
+                        font= emptyDictionary,
+                        pattern= emptyDictionary,
+                        shading= emptyDictionary
+                       } 
+                       where
+                        newobjects = foldl insertObjs (objects p) [(contentName,(PdfStream (content p))),
+                               ("ExtGState",PdfDict (extgstate p)),
+                               ("XObject",PdfDict (xobject p)),
+                               ("Font",PdfDict (font p)),
+                               ("Pattern",PdfDict (pattern p)),
+                               ("Shading",PdfDict (shading p))
+                            ]
+                        insertObjs dict (s,o) = insertObject s o dict
+                        renumber (PdfDictionary objs) = PdfDictionary(Map.map (setNumber objs) objs) 
+                        setNumber objs (PdfUnknownPointer s) = PdfPointer ((Map.findIndex s objs)+1)
+                        setNumber objs (PdfDict (PdfDictionary d)) = PdfDict . PdfDictionary . Map.map (setNumber objs)  $ d
+                        setNumber objs (PdfArray l) = PdfArray . map (setNumber objs) $ l
+                        setNumber _ a = a
+                          
+infixr 9 <>
+-- | Combine two PDF actions
+(<>) :: PdfCmd -> PDF -> PDF
+(<>) (c,l) p = addNewContent c (foldr addCreatedObject p l)
+               
+
+
diff --git a/Graphics/PDF/Shading.hs b/Graphics/PDF/Shading.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/PDF/Shading.hs
@@ -0,0 +1,80 @@
+-- | Function used to create shading patterns
+module Graphics.PDF.Shading
+ (-- * Shading
+  -- ** Data types
+  Shading(..)
+  -- ** Operators
+  , createShading, strokeShading, fillShading
+ )
+ where
+ 
+import Graphics.PDF.LowLevel
+import Text.Printf
+import Graphics.PDF.Color
+
+-- | Axial or radial shading
+data Shading = Axial Color Color Float Float Float Float -- ^ Axial shading with start end color and the start and ending points
+             | Radial Color Color Float Float Float Float Float Float -- ^ Radial shading with start and end color, center and radius of start and end circle
+
+instance Show Shading where
+  show (Axial a b x0 y0 x1 y1) =  printf "axial%s%s%f%f%f%f" (show a) (show b) x0 y0 x1 y1
+  show (Radial a b x0 y0 r0 x1 y1 r1) =  printf "axial%s%s%f%f%f%f%f%f" (show a) (show b) x0 y0 r0 x1 y1 r1
+  
+-- | Interpolation function
+interpole :: Int -> Float -> Float -> PdfObject
+interpole n x y = pdfDictionary [
+                                 ("FunctionType", PdfInt 2),
+                                 ("Domain", PdfArray [PdfFloat 0,PdfFloat 1]),
+                                 ("C0", PdfArray [PdfFloat x]),
+                                 ("C1", PdfArray [PdfFloat y]),
+                                 ("N", PdfInt n)
+                              ]
+  
+-- | Create a shading dictionary
+createShadingObject :: Shading -> CreatedObject
+createShadingObject a@(Axial (Rgb ra ga ba) (Rgb rb gb bb)  x0 y0 x1 y1) = (PdfAnyObject,(show a),pdfDictionary [("Type",PdfName "Shading"),
+                         ("ShadingType",PdfInt 2),
+                         ("ColorSpace",PdfName "DeviceRGB"),
+                         ("Coords",PdfArray (map PdfFloat [x0,y0,x1,y1])),
+                         ("Function",PdfArray [interpole 1 ra rb,interpole 1 ga gb,interpole 1 ba bb])
+                         ]
+                  )
+createShadingObject a@(Radial (Rgb ra ga ba) (Rgb rb gb bb)  x0 y0 r0 x1 y1 r1) = (PdfAnyObject,(show a),pdfDictionary [("Type",PdfName "Shading"),
+                         ("ShadingType",PdfInt 3),
+                         ("ColorSpace",PdfName "DeviceRGB"),
+                         ("Coords",PdfArray (map PdfFloat [x0,y0,r0,x1,y1,r1])),
+                         ("Function",PdfArray [interpole 1 ra rb,interpole 1 ga gb,interpole 1 ba bb])
+                         ]
+                  )
+createShadingObject _ = error "Shading object only with RGB colors"                  
+
+-- Name of a pattern
+patternName :: Shading -> String
+patternName s = "pattern" ++ (show s)
+
+-- | Create a new shading made of several dictionaries     
+newPattern :: Shading -> [CreatedObject]
+newPattern a =  [(PdfAnyObject,patternName a,pdfDictionary [("Type",PdfName "Pattern"),
+                         ("PatternType",PdfInt 2),
+                         ("Shading",PdfUnknownPointer (show a))
+                         ]
+                  ),
+                  createShadingObject a,
+                  (PdfPatternObject,patternName a, PdfUnknownPointer (patternName a)),
+                  (PdfShading,show a, PdfUnknownPointer (show a))
+                 ]
+                 
+-- | Create a new kind of shading
+createShading :: Shading -> PdfCmd
+createShading s = (PdfNone,newPattern s) 
+          
+                 
+-- | Select a shading for stroking (it must have been created before)
+strokeShading :: Shading -> PdfCmd
+strokeShading s = (PdfStrokePattern  (patternName s),[]) 
+
+-- | Select a shading for filling (it must have been created before)
+fillShading :: Shading -> PdfCmd
+fillShading s = (PdfFillPattern  (patternName s),[]) 
+    
+                          
diff --git a/Graphics/PDF/Shape.hs b/Graphics/PDF/Shape.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/PDF/Shape.hs
@@ -0,0 +1,75 @@
+-- | Functions used to add shapes to a PDF documents
+
+module Graphics.PDF.Shape 
+ (-- * Shapes
+  -- ** Drawing operators
+  line, rectangle, fillRectangle
+  -- ** Path operators
+  ,startPathAt,closePath,addLineToPath,addRectangleToPath,strokePath,fillPath, fillAndStrokePath, clipPath
+  -- ** Shape settings
+  , lineWidth, dashPattern
+ )
+ where
+ 
+import Graphics.PDF.LowLevel
+
+-- | Add a line to a PDF document                            
+line :: Float -> Float -> Float -> Float -> PdfCmd
+line xa ya xb yb  = (PdfL xa ya xb yb,[])
+                    
+
+-- | Change the line width used in a PDF document                  
+lineWidth :: Float -> PdfCmd
+lineWidth w  = (PdfW w,[])
+                
+-- | Add a rectangle to the PDF
+rectangle :: Float -> Float -> Float -> Float -> PdfCmd
+rectangle xa ya width height  = (PdfRect xa ya width height,[])
+                                 
+  
+-- | Add a filled a rectangle to the PDF
+fillRectangle :: Float -> Float -> Float -> Float -> PdfCmd
+fillRectangle xa ya width height  = (PdfFillRect xa ya width height,[])
+                                    
+                                   
+-- | Set the dash array and phase
+dashPattern :: [Float] -> Float -> PdfCmd
+dashPattern a phase  =  (PdfDash a phase,[])
+                        
+                         
+-- | Start a new path
+startPathAt :: Float -> Float -> PdfCmd
+startPathAt xa ya  = (PdfStartPath xa ya,[])
+                     
+                    
+-- | Close path
+closePath :: PdfCmd
+closePath  = (PdfClosePath,[])
+              
+              
+-- | Add a line to the current path
+addLineToPath :: Float -> Float -> PdfCmd
+addLineToPath xa ya  = (PdfAddLineToPath xa ya,[])
+                        
+                         
+-- | Add a rectangle to the PDF
+addRectangleToPath :: Float -> Float -> Float -> Float -> PdfCmd
+addRectangleToPath xa ya width height  = (PdfAddRectangleToPath xa ya width height,[])
+                                          
+                                        
+-- | Stroke path
+strokePath :: PdfCmd
+strokePath  = (PdfStroke,[])
+               
+-- | Fill path
+fillPath :: PdfCmd
+fillPath  = (PdfFill,[])
+            
+
+-- | Fill and stroke path
+fillAndStrokePath :: PdfCmd
+fillAndStrokePath  = (PdfFillAndStroke,[])
+
+-- | Clip path
+clipPath :: PdfCmd
+clipPath  = (PdfClip,[])
diff --git a/Graphics/PDF/Text.hs b/Graphics/PDF/Text.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/PDF/Text.hs
@@ -0,0 +1,50 @@
+-- | Function used to draw text
+
+module Graphics.PDF.Text
+ (-- * Text 
+  drawText, clipText,fillAndDrawText,fillText,charSpacing,wordSpacing,textLeading
+  , pdfString
+ )
+ where
+ 
+import Graphics.PDF.LowLevel
+import Text.Regex
+
+leftPar = mkRegex "[(]"
+rightPar = mkRegex "[)]"
+backslash = mkRegex "[\\]"
+
+-- | Create a pdf string
+pdfString :: String -> [PdfString]
+pdfString s = map (S . escape) . lines $ s
+              where
+                escape s =  replace rightPar "\\)" . replace leftPar "\\(" . replace backslash "\\\\\\\\" $ s
+                replace reg repl s = subRegex reg s repl
+   
+-- | Stroke text at a given position and use the current font settings            
+drawText :: Float -> Float -> String -> PdfCmd
+drawText px py s  = (PdfText TextStroke px py (pdfString s),[])
+
+-- | Fill and stroke text at a given position and use the current font settings            
+fillAndDrawText :: Float -> Float -> String -> PdfCmd
+fillAndDrawText px py s  = (PdfText TextFillStroke px py (pdfString s),[])
+
+-- | Fill text at a given position and use the current font settings            
+fillText :: Float -> Float -> String -> PdfCmd
+fillText px py s  = (PdfText TextFill px py (pdfString s),[])
+    
+-- | Intersect clip region with text shape        
+clipText :: Float -> Float -> String -> PdfCmd
+clipText px py s  = (PdfText TextClip px py (pdfString s),[])
+    
+-- | Set char spacing value       
+charSpacing :: Float -> PdfCmd
+charSpacing value  = (PdfCharSpacing value,[])
+
+-- | Set word spacing value       
+wordSpacing :: Float -> PdfCmd
+wordSpacing value  = (PdfWordSpacing value,[])
+
+-- | Set text leading value (used for line separation when text is containing a \\n)     
+textLeading :: Float -> PdfCmd
+textLeading value  = (PdfLeading value,[])
diff --git a/HPDF.cabal b/HPDF.cabal
new file mode 100644
--- /dev/null
+++ b/HPDF.cabal
@@ -0,0 +1,20 @@
+Name: HPDF
+Version: 0.3
+License: LGPL
+Copyright: Copyright (c) 2006, alpha
+category: Graphics
+synopsis: PDF API for Haskell
+maintainer: misc@NOSPAMalpheccar.org
+homepage: http://www.alpheccar.org
+exposed-Modules: 
+   Graphics.PDF,
+   Graphics.PDF.Geometry,
+   Graphics.PDF.Shape,
+   Graphics.PDF.Text,
+   Graphics.PDF.Font,
+   Graphics.PDF.Color,
+   Graphics.PDF.Shading,
+   Graphics.PDF.File,
+   Graphics.PDF.LowLevel
+build-depends: base, haskell98,mtl,regex-compat
+ghc-options:         -Wall -O2
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+module Main where
+import Distribution.Simple( defaultMain )
+main = defaultMain
