packages feed

Rasterific 0.5.0.3 → 0.5.1

raw patch · 8 files changed

+184/−94 lines, 8 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Graphics.Rasterific: class Geometry a where listToPrims = concatMap toPrimitives . toList
+ Graphics.Rasterific: class Primitivable a
+ Graphics.Rasterific: listToPrims :: (Geometry a, Foldable f) => f a -> [Primitive]
+ Graphics.Rasterific: toPrim :: Primitivable a => a -> Primitive
+ Graphics.Rasterific: toPrimitives :: Geometry a => a -> [Primitive]
- Graphics.Rasterific: dashedStroke :: DashPattern -> Float -> Join -> (Cap, Cap) -> [Primitive] -> Drawing px ()
+ Graphics.Rasterific: dashedStroke :: Geometry geom => DashPattern -> Float -> Join -> (Cap, Cap) -> geom -> Drawing px ()
- Graphics.Rasterific: dashedStrokeWithOffset :: Float -> DashPattern -> Float -> Join -> (Cap, Cap) -> [Primitive] -> Drawing px ()
+ Graphics.Rasterific: dashedStrokeWithOffset :: Geometry geom => Float -> DashPattern -> Float -> Join -> (Cap, Cap) -> geom -> Drawing px ()
- Graphics.Rasterific: fill :: [Primitive] -> Drawing px ()
+ Graphics.Rasterific: fill :: Geometry geom => geom -> Drawing px ()
- Graphics.Rasterific: fillWithMethod :: FillMethod -> [Primitive] -> Drawing px ()
+ Graphics.Rasterific: fillWithMethod :: Geometry geom => FillMethod -> geom -> Drawing px ()
- Graphics.Rasterific: stroke :: Float -> Join -> (Cap, Cap) -> [Primitive] -> Drawing px ()
+ Graphics.Rasterific: stroke :: Geometry geom => Float -> Join -> (Cap, Cap) -> geom -> Drawing px ()
- Graphics.Rasterific.Outline: dashedStrokize :: Float -> DashPattern -> StrokeWidth -> Join -> (Cap, Cap) -> [Primitive] -> [[Primitive]]
+ Graphics.Rasterific.Outline: dashedStrokize :: Geometry geom => Float -> DashPattern -> StrokeWidth -> Join -> (Cap, Cap) -> geom -> [[Primitive]]
- Graphics.Rasterific.Outline: strokize :: StrokeWidth -> Join -> (Cap, Cap) -> [Primitive] -> [Primitive]
+ Graphics.Rasterific.Outline: strokize :: Geometry geom => StrokeWidth -> Join -> (Cap, Cap) -> geom -> [Primitive]

Files

Rasterific.cabal view
@@ -1,7 +1,7 @@ -- Initial Rasterific.cabal generated by cabal init.  For further 
 -- documentation, see http://haskell.org/cabal/users-guide/
 name:                Rasterific
-version:             0.5.0.3
+version:             0.5.1
 synopsis:            A pure haskell drawing engine.
 -- A longer description of the package.
 description:
@@ -37,7 +37,7 @@ Source-Repository this
     Type:      git
     Location:  git://github.com/Twinside/Rasterific.git
-    Tag:       v0.5.0.3
+    Tag:       v0.5.1
 
 flag embed_linear
   description: Embed a reduced version of Linear avoiding a (huge) dep
@@ -69,7 +69,7 @@ 
   ghc-options: -O3 -Wall 
   -- -ddump-simpl -ddump-to-file -dsuppress-module-prefixes -dsuppress-uniques
-  ghc-prof-options: -Wall -prof -auto-all
+  ghc-prof-options: -Wall -prof
   default-language: Haskell2010
   build-depends: base        >= 4.6     && < 4.9
                , free        >= 4.7
changelog view
@@ -1,5 +1,10 @@ -*-change-log-*-
 
+v0.5.1 March 2015
+ * Enhancement: Generalizing geometry description, with automatic
+   conversion, reducing the need of type constructor from Primitive,
+   and directly filling Path.
+
 v0.5.0.3 February 2015
  * Fix: hackage documentation
 
docimages/sampled_texture_reflect.png view

binary file changed (64682 → 64813 bytes)

exec-src/docImageGenerator.hs view
@@ -24,7 +24,7 @@ 
 logo :: Int -> Bool -> Vector -> [Primitive]
 logo size inv offset =
-    map BezierPrim . bezierFromPath . way $ map (^+^ offset)
+    toPrimitives . bezierFromPath . way $ map (^+^ offset)
     [ (V2   0  is)
     , (V2   0   0)
     , (V2  is   0)
@@ -71,7 +71,7 @@         withTexture accentTexture $
             stroke 2 join (CapRound, CapRound) base_stroke
   where 
-    base_stroke = LinePrim <$>
+    base_stroke =
         [ Line (V2 0 200) (V2 100 100)
         , Line (V2 100 100) (V2 200 200)
         ]
@@ -104,10 +104,25 @@ 
   writePng (outFolder </> "module_example.png") img
 
+arialFont :: FilePath
+arialFont =
+#ifdef __WIN32__
+  "C:/Windows/Fonts/arial.ttf"
+#else
+  "/usr/share/fonts/truetype/msttcorefonts/arial.ttf"
+#endif
 
+monospaceFont :: FilePath
+monospaceFont =
+#ifdef __WIN32__
+  "C:/Windows/Fonts/consola.ttf"
+#else
+  "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf"
+#endif
+
 textOnPathExample :: IO ()
 textOnPathExample = do
-  fontErr <- loadFontFile "C:/Windows/Fonts/arial.ttf"
+  fontErr <- loadFontFile arialFont
   case fontErr of
     Left err -> putStrLn err
     Right font ->
@@ -115,8 +130,7 @@                       [PathCubicBezierCurveTo (V2 20 20) (V2 170 20) (V2 300 200)]
       in
       produceDocImage (outFolder </> "text_on_path.png") $ do
-        stroke 3 JoinRound (CapStraight 0, CapStraight 0) $
-            pathToPrimitives path
+        stroke 3 JoinRound (CapStraight 0, CapStraight 0) path
 
         withTexture (uniformTexture $ PixelRGBA8 0 0 0 255) $ do
           withPathOrientation path 0 $
@@ -124,7 +138,7 @@ 
 geometryOnPath :: IO ()
 geometryOnPath = do
-  fontErr <- loadFontFile "C:/Windows/Fonts/arial.ttf"
+  fontErr <- loadFontFile arialFont
   case fontErr of
     Left err -> putStrLn err
     Right font ->
@@ -132,8 +146,7 @@         let path = Path (V2 100 180) False
                         [PathCubicBezierCurveTo (V2 20 20) (V2 170 20) (V2 300 200)]
         withTexture (uniformTexture $ PixelRGBA8 0 0 0 255) $
-          stroke 3 JoinRound (CapStraight 0, CapStraight 0) $
-              pathToPrimitives path
+          stroke 3 JoinRound (CapStraight 0, CapStraight 0) path
      
         withPathOrientation path 0 $ do
           printTextAt font (PointSize 24) (V2 0 0) "TX"
@@ -144,7 +157,7 @@ 
 textExample :: IO ()
 textExample = do
-  fontErr <- loadFontFile "C:/Windows/Fonts/arial.ttf"
+  fontErr <- loadFontFile arialFont
   case fontErr of
     Left err -> putStrLn err
     Right font ->
@@ -155,8 +168,8 @@ 
 textMultipleExample :: IO ()
 textMultipleExample = do
-  eitherFont1 <- loadFontFile "C:/Windows/Fonts/arial.ttf"
-  eitherFont2 <- loadFontFile "C:/Windows/Fonts/consola.ttf"
+  eitherFont1 <- loadFontFile arialFont
+  eitherFont2 <- loadFontFile monospaceFont
   case (,) <$> eitherFont1 <*> eitherFont2 of
     Left err -> putStrLn err
     Right (font1, font2) ->
@@ -175,7 +188,7 @@ 
 coordinateSystem :: IO ()
 coordinateSystem = do
-    fontErr <- loadFontFile "C:/Windows/Fonts/arial.ttf"
+    fontErr <- loadFontFile arialFont
     case fontErr of
         Left err -> putStrLn err
         Right font -> 
@@ -186,23 +199,21 @@     white = PixelRGBA8 255 255 255 255
     black = PixelRGBA8   0   0   0 255
     stroker = stroke 4 JoinRound (CapStraight 0, CapStraight 0)
-    filler = fill . pathToPrimitives
     create font = withTexture (uniformTexture black) $ do
         stroker $ line (V2 10 40) (V2 190 40)
         stroker $ line (V2 40 10) (V2 40 190)
         printTextAt font (PointSize 12) (V2 4 37) "(0,0)"
         printTextAt font (PointSize 12) (V2 100 37) "(width, 0)"
         printTextAt font (PointSize 12) (V2 57 190) "(0, height)"
-        filler $ Path (V2 170 30) True
+        fill $ Path (V2 170 30) True
             [PathLineTo (V2 195 40), PathLineTo (V2 170 50)]
-        filler $ Path (V2 30 170) True
+        fill $ Path (V2 30 170) True
             [PathLineTo (V2 40 195), PathLineTo (V2 50 170)]
 
 fillingSample :: FillMethod -> Drawing px ()
 fillingSample fillMethod = fillWithMethod fillMethod geometry where
   geometry = transform (applyTransformation $ scale 0.35 0.4
                                            <> translate (V2 (-80) (-180)))
-           $ concatMap pathToPrimitives
      [ Path (V2 484 499) True
          [ PathCubicBezierCurveTo (V2 681 452) (V2 639 312) (V2 541 314)
          , PathCubicBezierCurveTo (V2 327 337) (V2 224 562) (V2 484 499)
@@ -298,18 +309,16 @@ 
     produceDocImage (outFolder </> "strokize_path.png") $
       stroke 3 (JoinMiter 0) (CapStraight 0, CapStraight 0) $
-          strokize 40 JoinRound (CapRound, CapRound)
-            [CubicBezierPrim $
-                 CubicBezier (V2  40 160) (V2 40   40)
-                             (V2 160  40) (V2 160 160)]
+          strokize 40 JoinRound (CapRound, CapRound) $
+            CubicBezier (V2  40 160) (V2 40   40)
+                        (V2 160  40) (V2 160 160)
 
     produceDocImage (outFolder </> "strokize_dashed_path.png") $
       mapM_ (stroke 3 (JoinMiter 0) (CapStraight 0, CapStraight 0)) $
           dashedStrokize 0 [10, 5]
                          40 JoinRound (CapStraight 0, CapStraight 0)
-            [CubicBezierPrim $
-                 CubicBezier (V2  40 160) (V2 40   40)
-                             (V2 160  40) (V2 160 160)]
+            [CubicBezier (V2  40 160) (V2 40   40)
+                         (V2 160  40) (V2 160 160)]
 
     produceDocImage (outFolder </> "with_clipping.png") $
       withClipping (fill $ circle (V2 100 100) 75) $
@@ -356,28 +365,28 @@ 
     produceDocImage (outFolder </> "cubic_bezier.png") $
         stroke 5 JoinRound (CapRound, CapRound) $
-            [CubicBezierPrim $ CubicBezier (V2 0 10) (V2 205 250)
-                                           (V2 (-10) 250) (V2 160 35)]
+            CubicBezier (V2 0 10) (V2 205 250)
+                        (V2 (-10) 250) (V2 160 35)
 
     produceDocImage (outFolder </> "quadratic_bezier.png") $
-        fill $ BezierPrim <$> [Bezier (V2 10 10) (V2 200 50) (V2 200 100)
-                            ,Bezier (V2 200 100) (V2 150 200) (V2 120 175)
-                            ,Bezier (V2 120 175) (V2 30 100) (V2 10 10)]
+        fill [ Bezier (V2 10 10) (V2 200 50) (V2 200 100)
+             , Bezier (V2 200 100) (V2 150 200) (V2 120 175)
+             , Bezier (V2 120 175) (V2 30 100) (V2 10 10)]
 
     produceDocImage (outFolder </> "simple_line.png") $
-        fill $ LinePrim <$> [ Line (V2 10 10) (V2 190 10)
-                            , Line (V2 190 10) (V2 95 170)
-                            , Line (V2 95 170) (V2 10 10)]
+        fill [ Line (V2 10 10) (V2 190 10)
+             , Line (V2 190 10) (V2 95 170)
+             , Line (V2 95 170) (V2 10 10) ]
 
     produceDocImage (outFolder </> "primitive_mixed.png") $
         fill
-            [ CubicBezierPrim $ CubicBezier (V2 50 20) (V2 90 60)
-                                            (V2  5 100) (V2 50 140)
-            , LinePrim $ Line (V2 50 140) (V2 120 80)
-            , LinePrim $ Line (V2 120 80) (V2 50 20) ]
+            [ toPrim $ CubicBezier (V2 50 20) (V2 90 60)
+                                   (V2  5 100) (V2 50 140)
+            , toPrim $ Line (V2 50 140) (V2 120 80)
+            , toPrim $ Line (V2 120 80) (V2 50 20) ]
 
     produceDocImage (outFolder </> "path_example.png") $
-       fill . pathToPrimitives $ Path (V2 50 20) True
+       fill $ Path (V2 50 20) True
           [ PathCubicBezierCurveTo (V2 90 60) (V2  5 100) (V2 50 140)
           , PathLineTo (V2 120 80) ]
 
src/Graphics/Rasterific.hs view
@@ -77,6 +77,12 @@     , Primitive( .. )
     , Path( .. )
     , PathCommand( .. )
+
+      -- * Generic geometry description
+    , Primitivable( .. )
+    , Geometry( .. )
+
+      -- * Generic geometry manipulation
     , Transformable( .. )
     , PointFoldable( .. )
     , PlaneBoundable( .. )
@@ -116,7 +122,6 @@ 
       -- * Debugging helper
     , dumpDrawing
-
     ) where
 
 #if !MIN_VERSION_base(4,8,0)
@@ -188,8 +193,7 @@ --
 -- > let path = Path (V2 100 180) False
 -- >                 [PathCubicBezierCurveTo (V2 20 20) (V2 170 20) (V2 300 200)] in
--- > stroke 3 JoinRound (CapStraight 0, CapStraight 0) $
--- >     pathToPrimitives path
+-- > stroke 3 JoinRound (CapStraight 0, CapStraight 0) path
 -- > withTexture (uniformTexture $ PixelRGBA8 0 0 0 255) $
 -- >   withPathOrientation path 0 $
 -- >     printTextAt font (PointSize 24) (V2 0 0) "Text on path"
@@ -205,8 +209,7 @@ -- > let path = Path (V2 100 180) False
 -- >                 [PathCubicBezierCurveTo (V2 20 20) (V2 170 20) (V2 300 200)]
 -- > withTexture (uniformTexture $ PixelRGBA8 0 0 0 255) $
--- >   stroke 3 JoinRound (CapStraight 0, CapStraight 0) $
--- >       pathToPrimitives path
+-- >   stroke 3 JoinRound (CapStraight 0, CapStraight 0) path
 -- > 
 -- > withPathOrientation path 0 $ do
 -- >   printTextAt font (PointSize 24) (V2 0 0) "TX"
@@ -234,15 +237,16 @@ --
 -- <<docimages/fill_circle.png>>
 --
-fill :: [Primitive] -> Drawing px ()
-fill prims = liftF $ Fill FillWinding prims ()
+fill :: Geometry geom => geom -> Drawing px ()
+fill prims = liftF $ Fill FillWinding (toPrimitives prims) ()
 
 -- | This function let you choose how to fill the primitives
 -- in case of self intersection. See `FillMethod` documentation
 -- for more information.
-fillWithMethod :: FillMethod -> [Primitive] -> Drawing px ()
+fillWithMethod :: Geometry geom
+               => FillMethod -> geom -> Drawing px ()
 fillWithMethod method prims =
-    liftF $ Fill method prims ()
+    liftF $ Fill method (toPrimitives prims) ()
 
 -- | Draw some geometry using a clipping path.
 --
@@ -268,13 +272,14 @@ --
 -- <<docimages/stroke_circle.png>>
 --
-stroke :: Float       -- ^ Stroke width
+stroke :: (Geometry geom)
+       => Float       -- ^ Stroke width
        -> Join        -- ^ Which kind of join will be used
        -> (Cap, Cap)  -- ^ Start and end capping.
-       -> [Primitive] -- ^ List of elements to render
+       -> geom        -- ^ List of elements to render
        -> Drawing px ()
 stroke width join caping prims =
-    liftF $ Stroke width join caping prims ()
+    liftF $ Stroke width join caping (toPrimitives prims) ()
 
 -- | Draw a string at a given position.
 -- Text printing imply loading a font, there is no default
@@ -490,17 +495,18 @@ -- | With stroke geometry with a given stroke width, using
 -- a dash pattern.
 --
--- > dashedStroke [5, 10, 5] 3 JoinRound (CapRound, CapStraight 0)
--- >        [line (V2 0 100) (V2 200 100)]
+-- > dashedStroke [5, 10, 5] 3 JoinRound (CapRound, CapStraight 0) $
+-- >     line (V2 0 100) (V2 200 100)
 --
 -- <<docimages/dashed_stroke.png>>
 --
 dashedStroke
-    :: DashPattern -- ^ Dashing pattern to use for stroking
+    :: Geometry geom
+    => DashPattern -- ^ Dashing pattern to use for stroking
     -> Float       -- ^ Stroke width
     -> Join        -- ^ Which kind of join will be used
     -> (Cap, Cap)  -- ^ Start and end capping.
-    -> [Primitive] -- ^ List of elements to render
+    -> geom        -- ^ List of elements to render
     -> Drawing px ()
 dashedStroke = dashedStrokeWithOffset 0.0
 
@@ -508,23 +514,24 @@ -- a dash pattern. The offset is there to specify the starting
 -- point into the pattern, the value can be negative.
 --
--- > dashedStrokeWithOffset 3 [5, 10, 5] 3 JoinRound (CapRound, CapStraight 0)
--- >        [line (V2 0 100) (V2 200 100)]
+-- > dashedStrokeWithOffset 3 [5, 10, 5] 3 JoinRound (CapRound, CapStraight 0) $
+-- >     line (V2 0 100) (V2 200 100)
 --
 -- <<docimages/dashed_stroke_with_offset.png>>
 --
 dashedStrokeWithOffset
-    :: Float       -- ^ Starting offset
+    :: Geometry geom
+    => Float       -- ^ Starting offset
     -> DashPattern -- ^ Dashing pattern to use for stroking
     -> Float       -- ^ Stroke width
     -> Join        -- ^ Which kind of join will be used
     -> (Cap, Cap)  -- ^ Start and end capping.
-    -> [Primitive] -- ^ List of elements to render
+    -> geom        -- ^ List of elements to render
     -> Drawing px ()
 dashedStrokeWithOffset _ [] width join caping prims =
     stroke width join caping prims
 dashedStrokeWithOffset offset dashing width join caping prims =
-    liftF $ DashedStroke offset dashing width join caping prims ()
+    liftF $ DashedStroke offset dashing width join caping (toPrimitives prims) ()
 
 -- | Generate a list of primitive representing a circle.
 --
src/Graphics/Rasterific/Outline.hs view
@@ -14,17 +14,17 @@ -- given a path. You can then stroke it.
 --
 -- > stroke 3 (JoinMiter 0) (CapStraight 0, CapStraight 0) $
--- >     strokize 40 JoinRound (CapRound, CapRound)
--- >       [CubicBezierPrim $
--- >            CubicBezier (V2  40 160) (V2 40   40)
--- >                        (V2 160  40) (V2 160 160)]
+-- >     strokize 40 JoinRound (CapRound, CapRound) $
+-- >         CubicBezier (V2  40 160) (V2 40   40)
+-- >                     (V2 160  40) (V2 160 160)
 --
 -- <<docimages/strokize_path.png>>
 --
-strokize :: StrokeWidth -- ^ Stroke width
+strokize :: Geometry geom
+         => StrokeWidth -- ^ Stroke width
          -> Join        -- ^ Which kind of join will be used
          -> (Cap, Cap)  -- ^ Start and end capping.
-         -> [Primitive] -- ^ List of elements to strokize
+         -> geom        -- ^ List of elements to strokize
          -> [Primitive]
 strokize w j c = listOfContainer . S.strokize w j c
 
src/Graphics/Rasterific/StrokeInternal.hs view
@@ -189,13 +189,14 @@ sanitize (BezierPrim b) = sanitizeBezier b
 sanitize (CubicBezierPrim c) = sanitizeCubicBezier c
 
-strokize :: StrokeWidth -> Join -> (Cap, Cap) -> [Primitive]
+strokize :: Geometry geom
+         => StrokeWidth -> Join -> (Cap, Cap) -> geom
          -> Container Primitive
-strokize width join (capStart, capEnd) beziers =
+strokize width join (capStart, capEnd) geom =
     offseter capEnd sanitized <>
         offseter capStart (reverse $ reversePrimitive <$> sanitized)
   where 
-        sanitized = foldMap (listOfContainer . sanitize) beziers
+        sanitized = foldMap (listOfContainer . sanitize) $ toPrimitives geom
         offseter = offsetAndJoin (width / 2) join
 
 flattenPrimitive :: Primitive -> Container Primitive
@@ -280,21 +281,20 @@ --
 -- > mapM_ (stroke 3 (JoinMiter 0) (CapStraight 0, CapStraight 0)) $
 -- >     dashedStrokize 0 [10, 5]
--- >                    40 JoinRound (CapStraight 0, CapStraight 0)
--- >       [CubicBezierPrim $
--- >            CubicBezier (V2  40 160) (V2 40   40)
--- >                        (V2 160  40) (V2 160 160)]
+-- >                    40 JoinRound (CapStraight 0, CapStraight 0) $
+-- >         CubicBezier (V2  40 160) (V2 40   40) (V2 160  40) (V2 160 160)
 --
 -- <<docimages/strokize_dashed_path.png>>
 --
-dashedStrokize :: Float       -- ^ Starting offset
+dashedStrokize :: Geometry geom
+               => Float       -- ^ Starting offset
                -> DashPattern -- ^ Dashing pattern to use for stroking
                -> StrokeWidth -- ^ Stroke width
                -> Join        -- ^ Which kind of join will be used
                -> (Cap, Cap)  -- ^ Start and end capping.
-               -> [Primitive] -- ^ List of elements to transform
+               -> geom        -- ^ Elements to transform
                -> [[Primitive]]
-dashedStrokize offset dashPattern width join capping beziers =
+dashedStrokize offset dashPattern width join capping geom =
     listOfContainer . strokize width join capping
-        <$> dashize offset dashPattern beziers
+        <$> dashize offset dashPattern (toPrimitives geom)
 
src/Graphics/Rasterific/Types.hs view
@@ -12,6 +12,10 @@     , Bezier( .. )
     , CubicBezier( .. )
     , Primitive( .. )
+
+    , Primitivable( .. )
+    , Geometry( .. )
+
     , Producer
     , Container
     , containerOfList
@@ -39,14 +43,16 @@     , lastTangeantOf
     , firstPointOf
     , lastPointOf
+
     ) where
 
-import Data.DList( DList, fromList, toList  )
+import Data.DList( DList, fromList )
 
 #if !MIN_VERSION_base(4,8,0)
 import Data.Foldable( Foldable )
 #endif
-import Data.Foldable( foldl' )
+import Data.Foldable( foldl', toList )
+import qualified Data.Foldable as F
 import Graphics.Rasterific.Linear( V2( .. ), (^-^), nearZero )
 
 import Foreign.Ptr( castPtr )
@@ -116,7 +122,6 @@ -- > fillingSample fillMethod = fillWithMethod fillMethod geometry where
 -- >   geometry = transform (applyTransformation $ scale 0.35 0.4
 -- >                                            <> translate (V2 (-80) (-180)))
--- >            $ concatMap pathToPrimitives
 -- >      [ Path (V2 484 499) True
 -- >          [ PathCubicBezierCurveTo (V2 681 452) (V2 639 312) (V2 541 314)
 -- >          , PathCubicBezierCurveTo (V2 327 337) (V2 224 562) (V2 484 499)
@@ -213,19 +218,21 @@     -- the primitive.
     foldPoints :: (b -> Point -> b) -> b -> a -> b
 
+-- | Just apply the function
 instance Transformable Point where
     {-# INLINE transform #-}
     transform f = f
 
+-- | Just apply the function
 instance PointFoldable Point where
     {-# INLINE foldPoints #-}
     foldPoints f = f
 
 -- | Describe a simple 2D line between two points.
 --
--- > fill $ LinePrim <$> [ Line (V2 10 10) (V2 190 10)
--- >                     , Line (V2 190 10) (V2 95 170)
--- >                     , Line (V2 95 170) (V2 10 10)]
+-- > fill [ Line (V2 10 10) (V2 190 10)
+-- >      , Line (V2 190 10) (V2 95 170)
+-- >      , Line (V2 95 170) (V2 10 10)]
 --
 -- <<docimages/simple_line.png>>
 --
@@ -251,9 +258,9 @@ -- | Describe a quadratic bezier spline, described
 -- using 3 points.
 --
--- > fill $ BezierPrim <$> [Bezier (V2 10 10) (V2 200 50) (V2 200 100)
--- >                       ,Bezier (V2 200 100) (V2 150 200) (V2 120 175)
--- >                       ,Bezier (V2 120 175) (V2 30 100) (V2 10 10)]
+-- > fill [Bezier (V2 10 10) (V2 200 50) (V2 200 100)
+-- >      ,Bezier (V2 200 100) (V2 150 200) (V2 120 175)
+-- >      ,Bezier (V2 120 175) (V2 30 100) (V2 10 10)]
 --
 -- <<docimages/quadratic_bezier.png>>
 --
@@ -286,8 +293,7 @@ -- using 4 points.
 --
 -- > stroke 4 JoinRound (CapRound, CapRound) $
--- >    [CubicBezierPrim $ CubicBezier (V2 0 10) (V2 205 250)
--- >                                   (V2 (-10) 250) (V2 160 35)]
+-- >    CubicBezier (V2 0 10) (V2 205 250) (V2 (-10) 250) (V2 160 35)
 --
 -- <<docimages/cubic_bezier.png>>
 --
@@ -325,11 +331,10 @@ -- on some specific algorithms. You can mix the different
 -- primitives in a single call :
 --
--- > fill
--- >    [ CubicBezierPrim $ CubicBezier (V2 50 20) (V2 90 60)
--- >                                    (V2  5 100) (V2 50 140)
--- >    , LinePrim $ Line (V2 50 140) (V2 120 80)
--- >    , LinePrim $ Line (V2 120 80) (V2 50 20) ]
+-- > fill [ toPrim $ CubicBezier (V2 50 20) (V2 90 60)
+-- >                             (V2  5 100) (V2 50 140)
+-- >      , toPrim $ Line (V2 50 140) (V2 120 80)
+-- >      , toPrim $ Line (V2 120 80) (V2 50 20) ]
 --
 -- <<docimages/primitive_mixed.png>>
 --
@@ -339,6 +344,70 @@   | CubicBezierPrim !CubicBezier -- ^ Primitive used for cubic bezier curve
   deriving (Eq, Show)
 
+-- | Generalizing constructors of the `Primitive` type to work
+-- generically.
+class Primitivable a where
+  toPrim :: a -> Primitive
+
+-- | @toPrim = id@
+instance Primitivable Primitive where toPrim = id
+
+-- | @toPrim = LinePrim@
+instance Primitivable Line where toPrim = LinePrim
+
+-- | @toPrim = BezierPrim@
+instance Primitivable Bezier where toPrim = BezierPrim
+
+-- | @toPrim = CubicBezierPrim@
+instance Primitivable CubicBezier where toPrim = CubicBezierPrim
+
+-- | All the rasterization works on lists of primitives,
+-- in order to ease the use of the library, the Geometry
+-- type class provides conversion facility, which help
+-- generalising the geometry definition and avoid applying
+-- Primitive constructor.
+--
+-- Also streamline the Path conversion.
+class Geometry a where
+  -- | Convert an element to a list of primitives
+  -- to be rendered.
+  toPrimitives :: a -> [Primitive]
+
+  -- | Helper method to avoid overlaping instances.
+  -- You shouldn't use it directly.
+  listToPrims :: (Foldable f) => f a -> [Primitive]
+  {-# INLINE listToPrims #-}
+  listToPrims = F.concatMap toPrimitives . F.toList
+
+instance Geometry Path where
+  {-# INLINE toPrimitives #-}
+  toPrimitives = pathToPrimitives
+
+instance Geometry Primitive where
+  toPrimitives e = [e]
+  {-# INLINE listToPrims #-}
+  listToPrims = F.toList -- Open question, is it optimised as `id`?
+
+instance Geometry Line where
+  {-# INLINE toPrimitives #-}
+  toPrimitives e = [toPrim e]
+
+instance Geometry Bezier where
+  {-# INLINE toPrimitives #-}
+  toPrimitives e = [toPrim e]
+
+instance Geometry CubicBezier where
+  {-# INLINE toPrimitives #-}
+  toPrimitives e = [toPrim e]
+
+-- | Generalize the geometry to any foldable container,
+-- so you can throw any container to the the 'fill' or
+-- 'stroke' function.
+instance (Foldable f, Geometry a) => Geometry (f a) where
+  {-# INLINE toPrimitives #-}
+  toPrimitives = listToPrims
+
+
 instance Transformable Primitive where
     {-# INLINE transform #-}
     transform f (LinePrim l) = LinePrim $ transform f l
@@ -378,7 +447,7 @@ -- it for the next "move"
 -- For example the example from Primitive could be rewritten:
 --
--- > fill . pathToPrimitives $ Path (V2 50 20) True
+-- > fill $ Path (V2 50 20) True
 -- >    [ PathCubicBezierCurveTo (V2 90 60) (V2  5 100) (V2 50 140)
 -- >    , PathLineTo (V2 120 80) ]
 --