diff --git a/CHANGES b/CHANGES
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,44 @@
 
+0.40.0 to 0.41.0:
+
+  * Changed PostScript output to use pre-defined procedures for 
+    circles and ellipses. This should be a significant 
+    optimization for drawings that have many circles or ellipses.
+    For drawings that do not use circles or ellipses, it adds 
+    circa. 75 lines to the generated PostScript which is 
+    tolerable.
+
+  * API change - @Core.Text.Base@ no longer exports the 
+    constructor and field label for @EscapedText@, it is now an 
+    opaque type. For a building @EscapedText@ either the existing 
+    /safe/constructor @escapeString@ or the new function 
+    @wrapEscChar@ should be used. For destructing @EscapedText@ 
+    there is a new function @destrEscapedText@.
+
+  * API change - the argument order of the functions @rtextlabel@ 
+    and @rescapedlabel@ in @Core.Picture@ has changed. The order 
+    of angle of rotation and the baseline-left has been swapped so 
+    that angle of rotation is first. This matches the other 
+    rotated graphics in @Core.Picture@.
+
+  * Upper bounds of Cabal build depends relaxed a bit.
+ 
+  * Added the @UNil@ type to @Core.Geometry@ and added affine 
+    instances for the UNil type, plus Maybe and Pair. @UNil@ is
+    useful for higher-level drawing (it is used extensively in
+    Wumpus-Basic).
+
+  * Added the function @emptyPath@ to @Core.Picture@. This creates 
+    a /null path/ with an empty list of path segments. Null paths 
+    still need a start point - this is minimum needed for bounding 
+    box calculation. Improved the PostScript and SVG output so 
+    there is no code generated for empty paths and textlabels.
+
+  * Added @vectorPath@ to @Core.Picture@.
+
+  * Added @boundaryCenter@ to @Core.BoundingBox@.
+
+  * Improved generated SVG code generation for ellipses / circles.
 
 0.37.0 to 0.40.0: 
 
diff --git a/doc-src/Guide.lhs b/doc-src/Guide.lhs
--- a/doc-src/Guide.lhs
+++ b/doc-src/Guide.lhs
@@ -31,9 +31,10 @@
 SVG (Scalable Vector Graphics) is supported. 
 
 \wumpuscore is rather primitive, the basic drawing objects are 
-paths and text labels. A second library \texttt{wumpus-basic}
-contains code for higher level drawing but it is experimental and 
-the APIs are a long way from stable (it should probably be 
+paths and text labels. A two additional libraries 
+\texttt{wumpus-basic} and \texttt{wumpus-drawing} contain code for 
+higher level drawing but they are experimental and the APIs they 
+present are a long way from stable (they should probably be 
 considered a \emph{technology preview}).
 
 Although \wumpuscore is heavily inspired by PostScript it avoids 
@@ -327,11 +328,13 @@
 of text label is only estimated - based on the length of the 
 label's string rather than the metrics of the individual letters 
 encoded in the font. Accessing the glyph metrics in a font 
-requires a font loader - work has been done on this for 
-\texttt{wumpus-basic} but this is considered a special requirement
-and adds a lot of code. As \wumpuscore is considered to be a 
-fairly minimal system for generating pictures it can live without
-font metrics.
+requires a font loader - \texttt{wumpus-basic} has a font loader 
+for the simple AFM font format but this is considered a special 
+requirement and adds a lot of code\footnote{Also, although it is 
+still useful, the AFM format is out-of-date, supporting the more 
+universal TrueType / OpenType formats would be a great deal of 
+work.}. As \wumpuscore is considered to be a fairly minimal system 
+for generating pictures it can live without font metrics.
 
 In PostScript, mis-named fonts can cause somewhat inscrutable 
 printing anomalies depending on the implementation. At worst, 
diff --git a/doc/Guide.pdf b/doc/Guide.pdf
Binary files a/doc/Guide.pdf and b/doc/Guide.pdf differ
diff --git a/src/Wumpus/Core/BoundingBox.hs b/src/Wumpus/Core/BoundingBox.hs
--- a/src/Wumpus/Core/BoundingBox.hs
+++ b/src/Wumpus/Core/BoundingBox.hs
@@ -4,7 +4,7 @@
 --------------------------------------------------------------------------------
 -- |
 -- Module      :  Wumpus.Core.BoundingBox
--- Copyright   :  (c) Stephen Tetley 2009-2010
+-- Copyright   :  (c) Stephen Tetley 2009-2011
 -- License     :  BSD3
 --
 -- Maintainer  :  stephen.tetley@gmail.com
@@ -13,8 +13,9 @@
 --
 -- Bounding box with no notion of \'empty\'.
 --
--- Empty pictures cannot be created with Wumpus. This greatly 
--- simplifies the implementation of pictures and bounding boxes.
+-- Empty pictures cannot be created with Wumpus. This 
+-- significantly simplifies the implementation of pictures and 
+-- bounding boxes.
 --
 -- Note - some of the functions exposed by this module are 
 -- expected to be pertinent only to Wumpus-Core itself.
@@ -33,7 +34,6 @@
   
   -- * Constructors
   , boundingBox
-  , oboundingBox
   
   -- * Operations
   , destBoundingBox
@@ -58,11 +58,12 @@
 import Wumpus.Core.Utils.FormatCombinators
 
 
--- | Bounding box of a picture, represented by the lower left and
--- upper right corners.
+-- | Bounding box of a picture, path, etc. represented by the 
+-- lower-left and upper-right corners.
 -- 
--- We cannot construct empty pictures - so bounding boxes are 
--- spared the obligation to be /empty/. 
+-- Wumpus cannot construct empty pictures - so bounding boxes are 
+-- spared the obligation to be /empty/. This greatly helps keep 
+-- the implementation relatively simple.
 -- 
 -- BoundingBox operates as a semigroup where @boundaryUnion@ is the
 -- addition.
@@ -142,20 +143,7 @@
     | otherwise            = error "Wumpus.Core.boundingBox - malformed."
 
 
--- | 'oboundingBbox' : @width * height -> BoundingBox@
---
--- Create a BoundingBox with bottom left corner at the origin,
--- and dimensions @w@ and @h@.
---
--- 'oboundingBox' throws an error if either the suppplied width 
--- or height is negative.
--- 
-oboundingBox :: (Num u, Ord u) => u -> u -> BoundingBox u
-oboundingBox w h 
-    | h >= 0 && w >= 0 = BBox zeroPt (P2 w h)
-    | otherwise        = error "Wumpus.Core.oboundingBox - malformed."
-
--- | 'destBoundingBox' : @ bbox -> (lower_left_x, lower_lefy_y, 
+-- | 'destBoundingBox' : @ bbox -> (lower_left_x, lower_left_y, 
 --      upper_right_x, upper_right_y)@
 --
 -- Destructor for BoundingBox, assembles a four-tuple of the x 
@@ -173,23 +161,28 @@
 boundaryUnion :: Ord u => BoundingBox u -> BoundingBox u -> BoundingBox u
 BBox ll ur `boundaryUnion` BBox ll' ur' = BBox (minPt ll ll') (maxPt ur ur')
 
--- | Trace a list of points, retuning the BoundingBox that 
--- includes them.
+
+-- | 'traceBoundary' : @ points -> BoundingBox @
 --
--- 'trace' throws a run-time error when supplied with the empty 
--- list.
+-- Trace a list of points, retuning the BoundingBox of their
+-- boundary.
 --
+-- \*\* WARNING \*\* - 'trace' throws a run-time error when 
+-- supplied with the empty list.
+--
 traceBoundary :: (Num u, Ord u) => [Point2 u] -> BoundingBox u
 traceBoundary (p:ps) = 
     uncurry BBox $ foldr (\z (a,b) -> (minPt z a, maxPt z b) ) (p,p) ps
 traceBoundary []     = error $ "BoundingBox.trace called in empty list"
 
+
 -- | Perform the supplied transformation on the four corners of 
 -- the bounding box. Trace the new corners to calculate the 
 -- resulting bounding box.
 -- 
--- This helper function can be used to re-calculate a bounding 
--- box after a rotation for example.
+-- NOTE - this helper function is used within Wumpus-Core to 
+-- re-calculate a bounding box after a rotation for example. It is 
+-- probably useful only to Wumpus-Core.
 --
 retraceBoundary :: (Num u, Ord u) 
         => (Point2 u -> Point2 u) -> BoundingBox u -> BoundingBox u
@@ -239,17 +232,26 @@
     x = x0 + (0.5*(x1-x0))
     y = y0 + (0.5*(y1-y0))
 
--- | Within test - is the supplied point within the bounding box?
+
+-- | 'withinBoundary' : @ point * bbox -> Bool @
+-- 
+-- Within test - is the supplied point within the bounding box?
 --
 withinBoundary :: Ord u => Point2 u -> BoundingBox u -> Bool
 withinBoundary p (BBox ll ur) = (minPt p ll) == ll && (maxPt p ur) == ur
 
--- | Extract the width of a bounding box.
+
+-- | 'boundaryWidth' : @ bbox -> Width @
 --
+-- Extract the width of a bounding box.
+--
 boundaryWidth :: Num u => BoundingBox u -> u
 boundaryWidth (BBox (P2 xmin _) (P2 xmax _)) = xmax - xmin
 
--- | Extract the height of a bounding box.
+
+-- | 'boundaryHeight' : @ bbox -> Height @
+--
+-- Extract the height of a bounding box.
 --
 boundaryHeight :: Num u => BoundingBox u -> u
 boundaryHeight (BBox (P2 _ ymin) (P2 _ ymax)) = ymax - ymin
diff --git a/src/Wumpus/Core/FontSize.hs b/src/Wumpus/Core/FontSize.hs
--- a/src/Wumpus/Core/FontSize.hs
+++ b/src/Wumpus/Core/FontSize.hs
@@ -4,7 +4,7 @@
 --------------------------------------------------------------------------------
 -- |
 -- Module      :  Wumpus.Core.FontSize
--- Copyright   :  (c) Stephen Tetley 2009-2010
+-- Copyright   :  (c) Stephen Tetley 2009-2011
 -- License     :  BSD3
 --
 -- Maintainer  :  stephen.tetley@gmail.com
@@ -86,6 +86,11 @@
 instance Show PtScale where
   showsPrec p d = showsPrec p (getPtScale d)
 
+
+-- | 'ptSizeScale' : @ scale_factor -> pt_size -> PTSize @
+--
+-- Scale the point size by the scale factor.
+--
 ptSizeScale :: PtScale -> PtSize -> PtSize 
 ptSizeScale sc sz = sz * realToFrac sc
 
@@ -183,13 +188,14 @@
 
 
 
--- | Text width at @sz@ point size of the string @s@. All
--- characters are counted literally - it is expected that 
--- @CharCount@ has been calculated with the @charCount@ function.
+-- | 'textWidth' : @ font_size * char_count -> PtSize @
 --
--- Note - this does not account for left and right margins around
--- the printed text.
+-- Text width at the supplied font_size. It is expected that the
+-- @char_ount@ has been calculated with the @charCount@ function.
 --
+-- NOTE - this does not account for any left and right margins 
+-- around the printed text.
+--
 textWidth :: FontSize -> CharCount -> PtSize
 textWidth _  n | n <= 0 = 0
 textWidth sz n          = fromIntegral n * charWidth sz
@@ -231,7 +237,7 @@
 descenderDepth = ptSizeScale mono_descender . fromIntegral 
 
 
--- | 'textBounds' : @ font_size * baseline_left * text -> BBox@
+-- | 'textBounds' : @ font_size * baseline_left * text -> BBox @
 --
 -- Find the bounding box for the character count at the 
 -- supplied font-size.
@@ -249,9 +255,9 @@
 textBounds sz pt ss = textBoundsBody sz pt (charCount ss) 
 
 
--- | 'textBoundsEnc' : @ font_size * baseline_left * escaped_text -> BBox@
+-- | 'textBoundsEsc' : @ font_size * baseline_left * escaped_text -> BBox @
 -- 
---  Version of textBounds for EscapedText.
+--  Version of textBounds for already escaped text.
 --
 textBoundsEsc :: (Num u, Ord u, FromPtSize u) 
            => FontSize -> Point2 u -> EscapedText -> BoundingBox u
@@ -274,11 +280,14 @@
 
 
 
--- | Count the charcters in the supplied string.
+-- | 'charCount' : @ string -> CharCount @
 --
--- Note escapes count as one character - for instance the length 
--- of this string:
+-- Count the characters in the supplied string, escaping the 
+-- string as necessary.
 --
+-- Escapes count as one character - for instance, the length of 
+-- this string:
+--
 -- > abcd&#egrave;f
 --
 -- ... is 6.
@@ -296,4 +305,5 @@
 
 -- Note - the last case of instep indicates a malformed string, 
 -- but there is nothing that can be done. Promoting to Maybe or 
--- Either would complicated the interface.
+-- Either would complicated the interface and doesn\'t seem worth
+-- it. 
diff --git a/src/Wumpus/Core/Geometry.hs b/src/Wumpus/Core/Geometry.hs
--- a/src/Wumpus/Core/Geometry.hs
+++ b/src/Wumpus/Core/Geometry.hs
@@ -7,7 +7,7 @@
 --------------------------------------------------------------------------------
 -- |
 -- Module      :  Wumpus.Core.Geometry
--- Copyright   :  (c) Stephen Tetley 2009-2010
+-- Copyright   :  (c) Stephen Tetley 2009-2011
 -- License     :  BSD3
 --
 -- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>
@@ -53,14 +53,14 @@
   , avec
   , pvec
   , vreverse
-  , direction
+  , vdirection
   , vlength
   , vangle
 
   -- * Point operations
   , zeroPt
-  , maxPt
   , minPt
+  , maxPt
   , lineDirection
 
   -- * Matrix contruction
@@ -127,10 +127,10 @@
 -- This newtype is Haskell\'s @()@ with unit of dimension @u@ as
 -- a phantom type.
 -- 
--- This has no use in @wumpus-core@, but it has affine instances 
--- which cannot be written for @()@. By supporting affine 
--- instances it becomes useful to higher-level software 
--- (@wumpus-basic@ employs it for the @Graphic@ type.) 
+-- This type has no direct use in Wumpus-Core, but it is useful 
+-- for higher-level software a - it has instances of the affine 
+-- classes which cannot be written for @()@ (Wumpus-Basic 
+-- uses it for the @Graphic@ type.) 
 -- 
 newtype UNil u = UNil ()
   deriving (Bounded,Enum,Eq,Ord)
@@ -397,12 +397,14 @@
 -- Vectors
 
 
--- | 'vec' - a synonym for the constructor 'V2' with a Num 
--- constraint on the arguments.
+-- | 'vec' : @ x_component * y_component -> Vec2 @
 --
--- Essentially superfluous, but it can be slightly more 
--- typographically pleasant when used in lists of vectors:
+-- A synonym for the constructor 'V2' with a Num constraint on 
+-- the arguments.
 --
+-- Essentially this function is superfluous, but it is slightly 
+-- more pleasant typographically when used in lists of vectors:
+--
 -- > [ vec 2 2, vvec 4, hvec 4, vec 2 2 ]
 --
 -- Versus:
@@ -413,19 +415,25 @@
 vec = V2
 
 
--- | Construct a vector with horizontal displacement.
+-- | 'hvec' : @ x_component -> Vec2 @
 --
+-- Construct a vector with horizontal displacement.
+--
 hvec :: Num u => u -> Vec2 u
 hvec d = V2 d 0
 
--- | Construct a vector with vertical displacement.
+-- | 'vvec' @ y_component -> Vec2 @ 
 --
+-- Construct a vector with vertical displacement.
+--
 vvec :: Num u => u -> Vec2 u
 vvec d = V2 0 d
 
 
--- | Construct a vector from an angle and magnitude.
+-- | 'avec' : @ angle * distance -> Vec2 @
 --
+-- Construct a vector from an angle and magnitude.
+--
 avec :: Floating u => Radian -> u -> Vec2 u
 avec theta d = V2 x y 
   where
@@ -433,32 +441,46 @@
     x   = d * cos ang
     y   = d * sin ang
 
--- | The vector between two points
+
+-- | 'pvec' : @ point_from * point_to -> Vec2 @
 --
+-- The vector between two points
+--
 -- > pvec = flip (.-.)
 --
 pvec :: Num u => Point2 u -> Point2 u -> Vec2 u
 pvec = flip (.-.)
 
 
--- | Reverse a vector.
+-- | 'vreverse' : @ vec -> Vec2 @
 --
+-- Reverse a vector.
+--
 vreverse :: Num u => Vec2 u -> Vec2 u
 vreverse (V2 x y) = V2 (-x) (-y)
 
--- | Direction of a vector - i.e. the counter-clockwise angle 
+
+-- | 'vdirection' : @ vec -> Radian @
+-- 
+-- Direction of a vector - i.e. the counter-clockwise angle 
 -- from the x-axis.
 --
-direction :: (Floating u, Real u) => Vec2 u -> Radian
-direction (V2 x y) = lineDirection (P2 0 0) (P2 x y)
+vdirection :: (Floating u, Real u) => Vec2 u -> Radian
+vdirection (V2 x y) = lineDirection (P2 0 0) (P2 x y)
 
--- | Length of a vector.
+
+-- | 'vlength' : @ vec -> Length @
 --
+-- Length of a vector.
+--
 vlength :: Floating u => Vec2 u -> u
 vlength (V2 x y) = sqrt $ x*x + y*y
 
--- | Extract the angle between two vectors.
+
+-- | 'vangle' : @ vec1 * vec2 -> Radian @
 --
+-- Extract the angle between two vectors.
+--
 vangle :: (Floating u, Real u, InnerSpace (Vec2 u)) 
        => Vec2 u -> Vec2 u -> Radian
 vangle u v = realToFrac $ acos $ (u <.> v) / (magnitude u * magnitude v)
@@ -473,13 +495,15 @@
 zeroPt = P2 0 0
 
 
--- | /Component-wise/ min on points.  
--- Standard 'min' and 'max' via Ord are defined lexographically
--- on pairs, e.g.:
+-- | 'minPt' : @ point1 * point2 -> Point2 @
+--
+-- Synthetic, /component-wise/ min on points. Standard 'min' and 
+-- 'max' via Ord are defined lexographically on pairs, e.g.:
 -- 
 -- > min (1,2) (2,1) = (1,2)
 -- 
--- For Points we want the component-wise min and max, e.g:
+-- For Points we want the component-wise min and max, that 
+-- potentially synthesizes a new point, e.g:
 --
 -- > minPt (P2 1 2) (Pt 2 1) = Pt 1 1 
 -- > maxPt (P2 1 2) (Pt 2 1) = Pt 2 2
@@ -487,14 +511,20 @@
 minPt :: Ord u => Point2 u -> Point2 u -> Point2 u
 minPt (P2 x y) (P2 x' y') = P2 (min x x') (min y y')
 
--- | /Component-wise/ max on points.  
+
+-- | 'maxPt' : @ point1 * point2 -> Point @
 --
+-- Synthetic, /component-wise/ max on points.  
+--
 -- > maxPt (P2 1 2) (Pt 2 1) = Pt 2 2
 -- 
 maxPt :: Ord u => Point2 u -> Point2 u -> Point2 u
 maxPt (P2 x y) (P2 x' y') = P2 (max x x') (max y y')
 
--- | Calculate the counter-clockwise angle between two points 
+
+-- | 'lineDirection' : @ start_point * end_point -> Radian @
+--
+-- Calculate the counter-clockwise angle between two points 
 -- and the x-axis.
 --
 lineDirection :: (Floating u, Real u) => Point2 u -> Point2 u -> Radian
@@ -533,8 +563,10 @@
 
 -- Common transformation matrices (for 2d homogeneous coordinates)
 
--- | Construct a scaling matrix:
+-- | 'scalingMatrix' : @ x_scale_factor * y_scale_factor -> Matrix @
 --
+-- Construct a scaling matrix:
+--
 -- > (M3'3 sx 0  0
 -- >       0  sy 0
 -- >       0  0  1 )
@@ -546,8 +578,10 @@
 
 
 
--- | Construct a translation matrix:
+-- | 'translationMatrix' : @ x_displacement * y_displacement -> Matrix @
 --
+-- Construct a translation matrix:
+--
 -- > (M3'3 1  0  x
 -- >       0  1  y
 -- >       0  0  1 )
@@ -559,8 +593,10 @@
 
 
 
--- | Construct a rotation matrix:
+-- | 'rotationMatrix' : @ ang -> Matrix @
 --
+-- Construct a rotation matrix:
+--
 -- > (M3'3 cos(a)  -sin(a)  0
 -- >       sin(a)   cos(a)  0
 -- >       0        0       1 )
@@ -578,7 +614,9 @@
 -- A reflection about the y-axis is a scale of (-1) 1
 
 
--- | Construct a matrix for rotation about some /point/.
+-- | 'originatedRotationMatrix' : @ ang * point -> Matrix @
+-- 
+-- Construct a matrix for rotation about some /point/.
 --
 -- This is the product of three matrices: T R T^-1
 -- 
@@ -733,10 +771,12 @@
     p3    = pt .+^ avec ang2 r
 
 
--- | 'bezierCircle' : @ n * radius * center -> [Point] @ 
+-- | 'bezierCircle' : @ subdivisions * radius * center -> [Point] @ 
 -- 
--- Make a circle from Bezier curves - @n@ is the number of 
--- subdivsions per quadrant.
+-- Make a circle from Bezier curves - the number of subdivsions 
+-- controls the accuracy or the curve, more subdivisions produce
+-- better curves, but less subdivisions are better for rendering
+-- (producing more efficient PostScript).
 --
 bezierCircle :: (Fractional u, Floating u) 
              => Int -> u -> Point2 u -> [Point2 u]
diff --git a/src/Wumpus/Core/GraphicProps.hs b/src/Wumpus/Core/GraphicProps.hs
--- a/src/Wumpus/Core/GraphicProps.hs
+++ b/src/Wumpus/Core/GraphicProps.hs
@@ -3,7 +3,7 @@
 --------------------------------------------------------------------------------
 -- |
 -- Module      :  Wumpus.Core.GraphicProps
--- Copyright   :  (c) Stephen Tetley 2009-2010
+-- Copyright   :  (c) Stephen Tetley 2009-2011
 -- License     :  BSD3
 --
 -- Maintainer  :  stephen.tetley@gmail.com
@@ -205,7 +205,9 @@
 
 
 
--- | Constructor for the default font, which is @Courier@ (aliased 
+-- | 'defaultFont' :@ font_size -> FontAttr @
+-- 
+-- Constructor for the default font, which is @Courier@ (aliased 
 -- to @Courier New@ for SVG) at the supplied size.
 --
 -- Note - the font uses the Standard encoding - this is common to 
diff --git a/src/Wumpus/Core/Picture.hs b/src/Wumpus/Core/Picture.hs
--- a/src/Wumpus/Core/Picture.hs
+++ b/src/Wumpus/Core/Picture.hs
@@ -5,7 +5,7 @@
 --------------------------------------------------------------------------------
 -- |
 -- Module      :  Wumpus.Core.Picture
--- Copyright   :  (c) Stephen Tetley 2009-2010
+-- Copyright   :  (c) Stephen Tetley 2009-2011
 -- License     :  BSD3
 --
 -- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>
@@ -136,7 +136,8 @@
 -- that the front of the list is drawn /at the back/ in the 
 -- Z-Order.
 --
--- This function throws an error when supplied the empty list.
+-- \*\* WARNING \*\* - this function throws a runtime error when 
+-- supplied the empty list.
 --
 frame :: (Real u, Floating u, FromPtSize u) => [Primitive u] -> Picture u
 frame []     = error "Wumpus.Core.Picture.frame - empty list"
@@ -150,7 +151,8 @@
 
 -- | Place multiple pictures within the standard affine frame.
 --
--- This function throws an error when supplied the empty list.
+-- \*\* WARNING \*\* - this function throws a runtime error when 
+-- supplied the empty list.
 --
 multi :: (Fractional u, Ord u) => [Picture u] -> Picture u
 multi []      = error "Wumpus.Core.Picture.multi - empty list"
@@ -193,8 +195,10 @@
 fontDeltaContext fa p = PContext (FontCtx fa) p
 
 
--- | Create a Path from a start point and a list of PathSegments.
+-- | 'primPath' : @ start_point * [path_segment] -> PrimPath @
 --
+-- Create a Path from a start point and a list of PathSegments.
+--
 primPath :: Num u => Point2 u -> [AbsPathSegment u] -> PrimPath u
 primPath pt xs = PrimPath pt $ step pt xs
   where
@@ -230,7 +234,8 @@
 -- Convert the list of vertices to a path of straight line 
 -- segments.
 --
--- This function throws an error when supplied the empty list.
+-- \*\* WARNING \*\* - this function throws a runtime error when 
+-- supplied the empty list.
 --
 vertexPath :: Num u => [Point2 u] -> PrimPath u
 vertexPath []     = error "Picture.vertexPath - empty point list"
@@ -263,11 +268,16 @@
 
 
 
--- | Convert a list of vertices to a path of curve segments.
+-- | 'curvedPath' : @ points -> PrimPath @
+-- 
+-- Convert a list of vertices to a path of curve segments.
 -- The first point in the list makes the start point, each curve 
 -- segment thereafter takes 3 points. /Spare/ points at the end 
 -- are discarded. 
 --
+-- \*\* WARNING - this function throws an error when supplied the 
+-- empty list.
+-- 
 curvedPath :: Num u => [Point2 u] -> PrimPath u
 curvedPath []     = error "Picture.curvedPath - empty point list"
 curvedPath (x:xs) = PrimPath x $ step x xs
@@ -292,6 +302,19 @@
 
 -- | Create an attribute for SVG output.
 --
+-- Attributes are expected to be /non-graphical/ e.g. @onclick@ 
+-- events or similar. Wumpus does not check the syntax and simply
+-- emits the Strings as-is in the output. 
+--
+-- Graphical properties should not be encoded, they may conflict 
+-- with output that Wumpus produces.
+--
+-- \*\* WARNING \*\* - currently this functionality is 
+-- undercooked. Because SVG has more /extra-graphical/ facilities
+-- than PostScript (hyperlinks, mouseovers, etc.) it seems 
+-- important to have an escape hatch to them, yet so far the 
+-- escape hatch has not been needed.
+--
 svgattr :: String -> String -> SvgAttr
 svgattr = SvgAttr
 
@@ -317,8 +340,8 @@
 
 -- | Group a list of Primitives.
 --
--- This function throws a runtime error when supplied with an
--- empty list.
+-- \*\* WARNING \*\* - this function throws a runtime error when 
+-- supplied the empty list.
 --
 primGroup :: [Primitive u] -> Primitive u
 primGroup []     = error "Picture.primGroup - empty prims list"
diff --git a/src/Wumpus/Core/PtSize.hs b/src/Wumpus/Core/PtSize.hs
--- a/src/Wumpus/Core/PtSize.hs
+++ b/src/Wumpus/Core/PtSize.hs
@@ -37,7 +37,9 @@
 -- | Wrapped Double representing /Point size/ for font metrics 
 -- etc.
 -- 
-newtype PtSize = PtSize { ptSize :: Double } 
+newtype PtSize = PtSize 
+          { ptSize :: Double  -- ^ Extract Point Size as a Double 
+          } 
   deriving (Eq,Ord,Num,Floating,Fractional,Real,RealFrac,RealFloat)
 
 instance Show PtSize where
diff --git a/src/Wumpus/Core/Utils/JoinList.hs b/src/Wumpus/Core/Utils/JoinList.hs
--- a/src/Wumpus/Core/Utils/JoinList.hs
+++ b/src/Wumpus/Core/Utils/JoinList.hs
@@ -91,10 +91,12 @@
   foldr                = joinfoldr
   foldl                = joinfoldl
 
+
 instance Traversable JoinList where
   traverse f (One a)    = One <$> f a
   traverse f (Join t u) = Join <$> traverse f t <*> traverse f u
 
+
 -- Views
 
 instance Functor ViewL where
@@ -207,7 +209,7 @@
 joinfoldr f = go
   where
     go e (One a)    = f a e
-    go e (Join t u) = go (go e t) u
+    go e (Join t u) = go (go e u) t
 
 
 -- | Left-associative fold of a JoinList.
@@ -216,7 +218,7 @@
 joinfoldl f = go 
   where
     go e (One a)    = f e a
-    go e (Join t u) = go (go e u) t
+    go e (Join t u) = go (go e t) u
 
 --------------------------------------------------------------------------------
 -- Views
diff --git a/src/Wumpus/Core/VersionNumber.hs b/src/Wumpus/Core/VersionNumber.hs
--- a/src/Wumpus/Core/VersionNumber.hs
+++ b/src/Wumpus/Core/VersionNumber.hs
@@ -3,7 +3,7 @@
 --------------------------------------------------------------------------------
 -- |
 -- Module      :  Wumpus.Core.VersionNumber
--- Copyright   :  (c) Stephen Tetley 2010
+-- Copyright   :  (c) Stephen Tetley 2010-2011
 -- License     :  BSD3
 --
 -- Maintainer  :  stephen.tetley@gmail.com
@@ -22,7 +22,7 @@
 
 -- | Version number.
 --
--- > (0,41,0)
+-- > (0,42,0)
 --
 wumpus_core_version :: (Int,Int,Int)
-wumpus_core_version = (0,41,0)
+wumpus_core_version = (0,42,0)
diff --git a/wumpus-core.cabal b/wumpus-core.cabal
--- a/wumpus-core.cabal
+++ b/wumpus-core.cabal
@@ -1,5 +1,5 @@
 name:             wumpus-core
-version:          0.41.0
+version:          0.42.0
 license:          BSD3
 license-file:     LICENSE
 copyright:        Stephen Tetley <stephen.tetley@gmail.com>
@@ -30,153 +30,37 @@
   GENERAL DRAWBACKS...
   .
   For actually building pictures, diagrams, etc. Wumpus-Core is 
-  very low-level. There is a supplementary package @Wumpus-Basic@ 
-  available that helps create certain types of diagram, but it is
-  experimental - functionality is added and dropped between 
-  releases, it has no stable API.
+  very low-level. There are two supplementary packages 
+  @Wumpus-Basic@ and @Wumpus-Drawing@ also on Hackage that aim to 
+  be a higher-level basis for creating certain types of diagram, 
+  but they are experimental - functionality is added and dropped 
+  between releases and curently the API is too unstable to write 
+  code upon (they should be considered a technology preview rather
+  than re-usable libraries).
   .
-  Some of the design decisions made for Wumpus-Core are not 
-  sophisticated (e.g. how path and text attributes like colour are 
+  Also, some of the design decisions made for Wumpus-Core are not 
+  sophisticated - e.g. how path and text attributes like colour are 
   handled, and how the bounding boxes of text labels are 
-  calculated), so Wumpus might be limited compared to other 
-  systems. However, the design permits a fairly simple 
-  implementation, which is a priority. 
+  calculated. Compared to other systems, Wumpus might be rather 
+  limited, however, the design permits a fairly simple 
+  implementation.
   .  
   .
-  UPDATING from 0.37.0 or earlier to 0.41.0.
-  .
-  There were substantial changes in verion 0.40.0 - hence the 
-  version number jump from 0.37.0. Version 0.41.0 introduces 
-  mostly cosmetic changes, but for upgrading from 0.37.0 or
-  earlier the change-notes that follow are still relevant.
-  .
-  @Core.Picture@ API change - the path construction function has 
-  changed from @path@ to @primPath@. The type of the path segments
-  has changed, the functions @lineTo@ and @curveTo@ now build
-  @AbsPathSegments@ and @primPath@ consumes @AbsPathSegments@.
-  .
-  The Text API has changed substantially, however most user code
-  should only need minor changes. The functions @writePS_latin1@, 
-  @writeEPS_latin1@ and @writeSVG_latin1@ have been removed, code 
-  should be changed to use @writePS@, @writeEPS@ and and 
-  @writeSVG@ respectively. These three functions no longer take a 
-  @TextEncoder@ argument as TextEncoders no longer exist.
-  .
-  The Font Size API has also changed substantially. It now 
-  exports a more consistent set of metrics (consistent with what 
-  is present in font files - the previous version was derived 
-  from hand measurements). It also adds a margin to bounding box
-  calculations, again this is more consistent with how font files 
-  actually work.
-  .
-  The handling of escaped special characters is now more 
-  consistent and the escaping mecahnism has been clarified 
-  (previously the documentation and the implementation were at 
-  odds): PostScript glyph names are delimited between @&@ 
-  (ampersand) and @;@ (semi), Unicode code points are delimited 
-  by @&\#@ (ampersand-hash) and @;@ (semi). Note Wumpus silently 
-  drops mal-formed escape charcters, for robustness this is 
-  preferable to throwing a runtime error, but it does mean the
-  output needs visually checking.
-  .
   Changelog:
   . 
-  v0.40.0 to v0.41.0:
-  .
-  * Changed PostScript output to use pre-defined procedures for 
-    circles and ellipses. This should be a significant 
-    optimization for drawings that have many circles or ellipses.
-    For drawings that do not use circles or ellipses, it adds 
-    circa. 75 lines to the generated PostScript which is 
-    tolerable.
-  .
-  * API change - @Core.Text.Base@ no longer exports the 
-    constructor and field label for @EscapedText@, it is now an 
-    opaque type. For a building @EscapedText@ either the existing 
-    /safe/constructor @escapeString@ or the new function 
-    @wrapEscChar@ should be used. For destructing @EscapedText@ 
-    there is a new function @destrEscapedText@.
-  .
-  * API change - the argument order of the functions @rtextlabel@ 
-    and @rescapedlabel@ in @Core.Picture@ has changed. The order 
-    of angle of rotation and the baseline-left has been swapped so 
-    that angle of rotation is first. This matches the other 
-    rotated graphics in @Core.Picture@.
-  .
-  * Upper bounds of Cabal build depends relaxed a bit.
-  . 
-  * Added the @UNil@ type to @Core.Geometry@ and added affine 
-    instances for the UNil type, plus Maybe and Pair. @UNil@ is
-    useful for higher-level drawing (it is used extensively in
-    Wumpus-Basic).
-  .
-  * Added the function @emptyPath@ to @Core.Picture@. This creates 
-    a /null path/ with an empty list of path segments. Null paths 
-    still need a start point - this is minimum needed for bounding 
-    box calculation. Improved the PostScript and SVG output so 
-    there is no code generated for empty paths and textlabels.
-  .
-  * Added @vectorPath@ to @Core.Picture@.
-  .
-  * Added @boundaryCenter@ to @Core.BoundingBox@.
-  .
-  * Improved generated SVG code generation for ellipses / circles.
-  .
-  v0.37.0 to v0.40.0: 
-  .
-  * Text handling substantially revised. SVG text output is now 
-    better aligned to Unicode. The encoding tables for PostScript
-    have been re-thought, the previous implementation had some 
-    serious design flaws that should now be rectified.
-  .
-  * The rules for escaping special characters has been clarified.
-    Previously the documentation suggested 
-    @ampersand-name-semicolon@ could be used to escape glyph names
-    however only @ampersand-hash-name-semicolon@ worked.
-    @ampersand-name-semicolon@ is now the correct way. The 
-    ampersand-hash prefix is for numeric literals - 
-    @ampersand-hash-num_literal-semicolon@.
-  .
-  * Versions of the textlabel functions have been added to 
-    @Core.Picture@ for escape-parsed text. It is useful for 
-    higher-level software to escape the text, do some calculations 
-    then render it - going back to un-escaped text for the 
-    rendering would be inefficient.
-  .
-  * The internal representation of paths has changed. They are now 
-    represented as start-point plus list of /relative/ path 
-    segments rather than start-point plus list of absolute path 
-    segments. Using relative path segments makes it cheaper to
-    move paths with @translate@, although calculating the bounding
-    box and rendering to PostScript is more expensive. The 
-    rationale for the change is that to make complex pictures, 
-    paths are potentially moved many times but the other 
-    operations are only performed once.
-  .
-  * Internal change to Primitives and the PrimCTM - ellipses and
-    labels no longer have a point (center or baseline left)
-    as an element in the datatype, the point is now represented 
-    within the PrimCTM.
+  v0.41.0 to v0.42.0:
   .
-  * Name change to @Core.Picture@ API - the path construction 
-    function @path@ has been renamed to @primPath@.
+  * Removed the function @oboundingBox@ from @Core.BoundingBox@.
+    It was unused in Wumpus-Core and had unwise error handling 
+    baked-in.
   .
-  * Name change in @Core.FontSize@, the function @textBoundsEnc@
-    has been renamed to @textBoundsEsc@. Wumpus-Core now calls 
-    strings that have been parsed for escape characters 
-    /Escaped Text/ rather than /Encoded Text/.
+  * Renamed @direction@ in @Wumpus.Core.Geometry@, it is now 
+    @vdirection@.
   .
-  * Fixed bug where ellipse rotation and scaling calculated the 
-    wrong bounding box.
-  . 
-  * Fixed bug in @illustrateControlPoints@ where the control points
-    were drawn but the original primitive was lost. 
+  * Fixed internal Foldable instances for JoinList. The left and
+    right folds worked in the wrong direction.
   .
-  * Added initial support for arbitrary SVG attributes (e.g. 
-    onmouseover handlers) via @annotateGroup@ in @Core.Picture@. 
-    Arbitrary SVG \"defs\" can be written into the defs prologue 
-    by using @writeSVG_defs@ instead of @writeSVG@. This 
-    functionality is mostly untested!
+  * Some improvements to the Haddock documentation. 
   .
   .
 build-type:         Simple
