packages feed

wumpus-core 0.43.0 → 0.50.0

raw patch · 44 files changed

+1412/−1152 lines, 44 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Wumpus.Core.AffineTrans: instance (Floating u, Real u) => Rotate (Point2 u)
- Wumpus.Core.AffineTrans: instance (Floating u, Real u) => Rotate (Vec2 u)
- Wumpus.Core.AffineTrans: instance (Floating u, Real u) => RotateAbout (Point2 u)
- Wumpus.Core.AffineTrans: instance (Floating u, Real u) => RotateAbout (Vec2 u)
- Wumpus.Core.AffineTrans: instance (u ~ DUnit a, u ~ DUnit b, Rotate a, Rotate b) => Rotate (a, b)
- Wumpus.Core.AffineTrans: instance (u ~ DUnit a, u ~ DUnit b, Scale a, Scale b) => Scale (a, b)
- Wumpus.Core.AffineTrans: instance Num u => Scale (Point2 u)
- Wumpus.Core.AffineTrans: instance Num u => Scale (Vec2 u)
- Wumpus.Core.AffineTrans: instance Num u => Translate (Vec2 u)
- Wumpus.Core.AffineTrans: instance Rotate (UNil u)
- Wumpus.Core.AffineTrans: instance RotateAbout (UNil u)
- Wumpus.Core.AffineTrans: instance Scale (UNil u)
- Wumpus.Core.AffineTrans: instance Transform (UNil u)
- Wumpus.Core.AffineTrans: instance Translate (UNil u)
- Wumpus.Core.BoundingBox: instance (Num u, Ord u) => Scale (BoundingBox u)
- Wumpus.Core.BoundingBox: instance (Real u, Floating u) => Rotate (BoundingBox u)
- Wumpus.Core.BoundingBox: instance (Real u, Floating u) => RotateAbout (BoundingBox u)
- Wumpus.Core.BoundingBox: instance Eq u => Eq (BoundingBox u)
- Wumpus.Core.BoundingBox: instance PSUnit u => Format (BoundingBox u)
- Wumpus.Core.FontSize: data PtScale
- Wumpus.Core.FontSize: instance Eq PtScale
- Wumpus.Core.FontSize: instance Floating PtScale
- Wumpus.Core.FontSize: instance Fractional PtScale
- Wumpus.Core.FontSize: instance Num PtScale
- Wumpus.Core.FontSize: instance Ord PtScale
- Wumpus.Core.FontSize: instance Real PtScale
- Wumpus.Core.FontSize: instance RealFloat PtScale
- Wumpus.Core.FontSize: instance RealFrac PtScale
- Wumpus.Core.FontSize: instance Show PtScale
- Wumpus.Core.FontSize: ptSizeScale :: PtScale -> PtSize -> PtSize
- Wumpus.Core.Geometry: data UNil u
- Wumpus.Core.Geometry: instance Bounded (UNil u)
- Wumpus.Core.Geometry: instance Enum (UNil u)
- Wumpus.Core.Geometry: instance Eq (UNil u)
- Wumpus.Core.Geometry: instance Eq u => Eq (Point2 u)
- Wumpus.Core.Geometry: instance Eq u => Eq (Vec2 u)
- Wumpus.Core.Geometry: instance Monoid (UNil u)
- Wumpus.Core.Geometry: instance Num u => MatrixMult (Point2 u)
- Wumpus.Core.Geometry: instance Num u => MatrixMult (Vec2 u)
- Wumpus.Core.Geometry: instance Ord (UNil u)
- Wumpus.Core.Geometry: instance Ord u => Ord (Point2 u)
- Wumpus.Core.Geometry: instance PSUnit u => Format (Matrix3'3 u)
- Wumpus.Core.Geometry: instance PSUnit u => Format (Point2 u)
- Wumpus.Core.Geometry: instance PSUnit u => Format (Vec2 u)
- Wumpus.Core.Geometry: instance Show (UNil u)
- Wumpus.Core.Geometry: uNil :: UNil u
- Wumpus.Core.Picture: curveTo :: Point2 u -> Point2 u -> Point2 u -> AbsPathSegment u
- Wumpus.Core.Picture: curvedPath :: Num u => [Point2 u] -> PrimPath u
- Wumpus.Core.Picture: emptyPath :: Num u => Point2 u -> PrimPath u
- Wumpus.Core.Picture: lineTo :: Point2 u -> AbsPathSegment u
- Wumpus.Core.Picture: primPath :: Num u => Point2 u -> [AbsPathSegment u] -> PrimPath u
- Wumpus.Core.Picture: vectorPath :: Num u => Point2 u -> [Vec2 u] -> PrimPath u
- Wumpus.Core.Picture: vertexPath :: Num u => [Point2 u] -> PrimPath u
- Wumpus.Core.Picture: xlink :: XLink -> Primitive u -> Primitive u
- Wumpus.Core.PtSize: class Num u => FromPtSize u
- Wumpus.Core.PtSize: data PtSize
- Wumpus.Core.PtSize: fromPtSize :: FromPtSize u => PtSize -> u
- Wumpus.Core.PtSize: instance Eq PtSize
- Wumpus.Core.PtSize: instance Floating PtSize
- Wumpus.Core.PtSize: instance Fractional PtSize
- Wumpus.Core.PtSize: instance FromPtSize Double
- Wumpus.Core.PtSize: instance Num PtSize
- Wumpus.Core.PtSize: instance Ord PtSize
- Wumpus.Core.PtSize: instance Real PtSize
- Wumpus.Core.PtSize: instance RealFloat PtSize
- Wumpus.Core.PtSize: instance RealFrac PtSize
- Wumpus.Core.PtSize: instance Show PtSize
- Wumpus.Core.PtSize: ptSize :: PtSize -> Double
- Wumpus.Core.WumpusTypes: class Num a => PSUnit a
- Wumpus.Core.WumpusTypes: dtrunc :: PSUnit a => a -> String
- Wumpus.Core.WumpusTypes: toDouble :: PSUnit a => a -> Double
- Wumpus.Core.WumpusTypes: type DKerningChar = KerningChar Double
- Wumpus.Core.WumpusTypes: type DPicture = Picture Double
- Wumpus.Core.WumpusTypes: type DPrimLabel = PrimLabel Double
- Wumpus.Core.WumpusTypes: type DPrimPath = PrimPath Double
- Wumpus.Core.WumpusTypes: type DPrimPathSegment = PrimPathSegment Double
- Wumpus.Core.WumpusTypes: type DPrimitive = Primitive Double
+ Wumpus.Core.AffineTrans: instance (Real u, Floating u) => Rotate (Point2 u)
+ Wumpus.Core.AffineTrans: instance (Real u, Floating u) => Rotate (Vec2 u)
+ Wumpus.Core.AffineTrans: instance (Real u, Floating u) => RotateAbout (Point2 u)
+ Wumpus.Core.AffineTrans: instance (Real u, Floating u) => RotateAbout (Vec2 u)
+ Wumpus.Core.AffineTrans: instance (Rotate a, Rotate b) => Rotate (a, b)
+ Wumpus.Core.AffineTrans: instance (Scale a, Scale b) => Scale (a, b)
+ Wumpus.Core.AffineTrans: instance (u ~ DUnit a, u ~ DUnit b, Transform a, Transform b) => Transform (a, b)
+ Wumpus.Core.AffineTrans: instance Fractional u => Scale (Point2 u)
+ Wumpus.Core.AffineTrans: instance Fractional u => Scale (Vec2 u)
+ Wumpus.Core.AffineTrans: instance Transform a => Transform (Maybe a)
+ Wumpus.Core.AffineTrans: instance Translate (Vec2 u)
+ Wumpus.Core.BoundingBox: instance (Fractional u, Ord u) => Scale (BoundingBox u)
+ Wumpus.Core.BoundingBox: instance (Real u, Floating u, Ord u) => Rotate (BoundingBox u)
+ Wumpus.Core.BoundingBox: instance (Real u, Floating u, Ord u) => RotateAbout (BoundingBox u)
+ Wumpus.Core.BoundingBox: instance (Tolerance u, Ord u) => Eq (BoundingBox u)
+ Wumpus.Core.BoundingBox: instance Boundary (BoundingBox u)
+ Wumpus.Core.BoundingBox: instance Format u => Format (BoundingBox u)
+ Wumpus.Core.BoundingBox: instance Functor BoundingBox
+ Wumpus.Core.FontSize: afmUnit :: FontSize -> Double -> AfmUnit
+ Wumpus.Core.FontSize: afmValue :: FontSize -> AfmUnit -> Double
+ Wumpus.Core.FontSize: data AfmUnit
+ Wumpus.Core.FontSize: instance Eq AfmUnit
+ Wumpus.Core.FontSize: instance Floating AfmUnit
+ Wumpus.Core.FontSize: instance Fractional AfmUnit
+ Wumpus.Core.FontSize: instance Num AfmUnit
+ Wumpus.Core.FontSize: instance Ord AfmUnit
+ Wumpus.Core.FontSize: instance Real AfmUnit
+ Wumpus.Core.FontSize: instance RealFloat AfmUnit
+ Wumpus.Core.FontSize: instance RealFrac AfmUnit
+ Wumpus.Core.FontSize: instance Show AfmUnit
+ Wumpus.Core.FontSize: instance Tolerance AfmUnit
+ Wumpus.Core.Geometry: class Num u => Tolerance u
+ Wumpus.Core.Geometry: eq_tolerance :: Tolerance u => u
+ Wumpus.Core.Geometry: instance (Tolerance u, Ord u) => Eq (Point2 u)
+ Wumpus.Core.Geometry: instance (Tolerance u, Ord u) => Eq (Vec2 u)
+ Wumpus.Core.Geometry: instance (Tolerance u, Ord u) => Ord (Point2 u)
+ Wumpus.Core.Geometry: instance (Tolerance u, Ord u) => Ord (Vec2 u)
+ Wumpus.Core.Geometry: instance Format u => Format (Matrix3'3 u)
+ Wumpus.Core.Geometry: instance Format u => Format (Point2 u)
+ Wumpus.Core.Geometry: instance Format u => Format (Vec2 u)
+ Wumpus.Core.Geometry: instance MatrixMult Point2
+ Wumpus.Core.Geometry: instance MatrixMult Vec2
+ Wumpus.Core.Geometry: instance Tolerance Double
+ Wumpus.Core.Geometry: length_tolerance :: Tolerance u => u
+ Wumpus.Core.Geometry: tCompare :: (Tolerance u, Ord u) => u -> u -> Ordering
+ Wumpus.Core.Geometry: tEQ :: (Tolerance u, Ord u) => u -> u -> Bool
+ Wumpus.Core.Geometry: tGT :: (Tolerance u, Ord u) => u -> u -> Bool
+ Wumpus.Core.Geometry: tGTE :: (Tolerance u, Ord u) => u -> u -> Bool
+ Wumpus.Core.Geometry: tLT :: (Tolerance u, Ord u) => u -> u -> Bool
+ Wumpus.Core.Geometry: tLTE :: (Tolerance u, Ord u) => u -> u -> Bool
+ Wumpus.Core.Picture: absCurveTo :: DPoint2 -> DPoint2 -> DPoint2 -> AbsPathSegment
+ Wumpus.Core.Picture: absLineTo :: DPoint2 -> AbsPathSegment
+ Wumpus.Core.Picture: absPrimPath :: DPoint2 -> [AbsPathSegment] -> PrimPath
+ Wumpus.Core.Picture: curvedPrimPath :: [DPoint2] -> PrimPath
+ Wumpus.Core.Picture: emptyPrimPath :: DPoint2 -> PrimPath
+ Wumpus.Core.Picture: relCurveTo :: DVec2 -> DVec2 -> DVec2 -> PrimPathSegment
+ Wumpus.Core.Picture: relLineTo :: DVec2 -> PrimPathSegment
+ Wumpus.Core.Picture: relPrimPath :: DPoint2 -> [PrimPathSegment] -> PrimPath
+ Wumpus.Core.Picture: vectorPrimPath :: DPoint2 -> [DVec2] -> PrimPath
+ Wumpus.Core.Picture: vertexPrimPath :: [DPoint2] -> PrimPath
+ Wumpus.Core.Picture: xlinkPrim :: XLink -> Primitive -> Primitive
+ Wumpus.Core.WumpusTypes: class Format a
+ Wumpus.Core.WumpusTypes: data AbsPathSegment
+ Wumpus.Core.WumpusTypes: format :: Format a => a -> Doc
+ Wumpus.Core.WumpusTypes: stringformat :: String -> Doc
- Wumpus.Core.AffineTrans: reflectX :: (Num u, Scale t, (DUnit t) ~ u) => t -> t
+ Wumpus.Core.AffineTrans: reflectX :: Scale t => t -> t
- Wumpus.Core.AffineTrans: reflectY :: (Num u, Scale t, (DUnit t) ~ u) => t -> t
+ Wumpus.Core.AffineTrans: reflectY :: Scale t => t -> t
- Wumpus.Core.AffineTrans: scale :: (Scale t, u ~ (DUnit t)) => u -> u -> t -> t
+ Wumpus.Core.AffineTrans: scale :: Scale t => Double -> Double -> t -> t
- Wumpus.Core.AffineTrans: uniformScale :: (Scale t, (DUnit t) ~ u) => u -> t -> t
+ Wumpus.Core.AffineTrans: uniformScale :: Scale t => Double -> t -> t
- Wumpus.Core.BoundingBox: withinBoundary :: Ord u => Point2 u -> BoundingBox u -> Bool
+ Wumpus.Core.BoundingBox: withinBoundary :: (Tolerance u, Ord u) => Point2 u -> BoundingBox u -> Bool
- Wumpus.Core.FontSize: ascenderHeight :: FontSize -> PtSize
+ Wumpus.Core.FontSize: ascenderHeight :: FontSize -> Double
- Wumpus.Core.FontSize: capHeight :: FontSize -> PtSize
+ Wumpus.Core.FontSize: capHeight :: FontSize -> Double
- Wumpus.Core.FontSize: charWidth :: FontSize -> PtSize
+ Wumpus.Core.FontSize: charWidth :: FontSize -> Double
- Wumpus.Core.FontSize: descenderDepth :: FontSize -> PtSize
+ Wumpus.Core.FontSize: descenderDepth :: FontSize -> Double
- Wumpus.Core.FontSize: mono_ascender :: PtScale
+ Wumpus.Core.FontSize: mono_ascender :: AfmUnit
- Wumpus.Core.FontSize: mono_cap_height :: PtScale
+ Wumpus.Core.FontSize: mono_cap_height :: AfmUnit
- Wumpus.Core.FontSize: mono_descender :: PtScale
+ Wumpus.Core.FontSize: mono_descender :: AfmUnit
- Wumpus.Core.FontSize: mono_left_margin :: PtScale
+ Wumpus.Core.FontSize: mono_left_margin :: AfmUnit
- Wumpus.Core.FontSize: mono_right_margin :: PtScale
+ Wumpus.Core.FontSize: mono_right_margin :: AfmUnit
- Wumpus.Core.FontSize: mono_width :: PtScale
+ Wumpus.Core.FontSize: mono_width :: AfmUnit
- Wumpus.Core.FontSize: mono_x_height :: PtScale
+ Wumpus.Core.FontSize: mono_x_height :: AfmUnit
- Wumpus.Core.FontSize: textBounds :: (Num u, Ord u, FromPtSize u) => FontSize -> Point2 u -> String -> BoundingBox u
+ Wumpus.Core.FontSize: textBounds :: FontSize -> DPoint2 -> String -> BoundingBox Double
- Wumpus.Core.FontSize: textBoundsEsc :: (Num u, Ord u, FromPtSize u) => FontSize -> Point2 u -> EscapedText -> BoundingBox u
+ Wumpus.Core.FontSize: textBoundsEsc :: FontSize -> DPoint2 -> EscapedText -> BoundingBox Double
- Wumpus.Core.FontSize: textWidth :: FontSize -> CharCount -> PtSize
+ Wumpus.Core.FontSize: textWidth :: FontSize -> CharCount -> Double
- Wumpus.Core.FontSize: totalCharHeight :: FontSize -> PtSize
+ Wumpus.Core.FontSize: totalCharHeight :: FontSize -> Double
- Wumpus.Core.FontSize: xcharHeight :: FontSize -> PtSize
+ Wumpus.Core.FontSize: xcharHeight :: FontSize -> Double
- Wumpus.Core.Geometry: (*#) :: (MatrixMult t, (DUnit t) ~ u) => Matrix3'3 u -> t -> t
+ Wumpus.Core.Geometry: (*#) :: (MatrixMult t, Num u) => Matrix3'3 u -> t u -> t u
- Wumpus.Core.OutputPostScript: writeEPS :: (Real u, Floating u, PSUnit u) => FilePath -> Picture u -> IO ()
+ Wumpus.Core.OutputPostScript: writeEPS :: FilePath -> Picture -> IO ()
- Wumpus.Core.OutputPostScript: writePS :: (Real u, Floating u, PSUnit u) => FilePath -> [Picture u] -> IO ()
+ Wumpus.Core.OutputPostScript: writePS :: FilePath -> [Picture] -> IO ()
- Wumpus.Core.OutputSVG: writeSVG :: (Real u, Floating u, PSUnit u) => FilePath -> Picture u -> IO ()
+ Wumpus.Core.OutputSVG: writeSVG :: FilePath -> Picture -> IO ()
- Wumpus.Core.OutputSVG: writeSVG_defs :: (Real u, Floating u, PSUnit u) => FilePath -> String -> Picture u -> IO ()
+ Wumpus.Core.OutputSVG: writeSVG_defs :: FilePath -> String -> Picture -> IO ()
- Wumpus.Core.Picture: annotateGroup :: [SvgAttr] -> Primitive u -> Primitive u
+ Wumpus.Core.Picture: annotateGroup :: [SvgAttr] -> Primitive -> Primitive
- Wumpus.Core.Picture: annotateXLink :: XLink -> [SvgAttr] -> Primitive u -> Primitive u
+ Wumpus.Core.Picture: annotateXLink :: XLink -> [SvgAttr] -> Primitive -> Primitive
- Wumpus.Core.Picture: clip :: (Num u, Ord u) => PrimPath u -> Picture u -> Picture u
+ Wumpus.Core.Picture: clip :: PrimPath -> Primitive -> Primitive
- Wumpus.Core.Picture: cstroke :: Num u => RGBi -> StrokeAttr -> PrimPath u -> Primitive u
+ Wumpus.Core.Picture: cstroke :: RGBi -> StrokeAttr -> PrimPath -> Primitive
- Wumpus.Core.Picture: escapedlabel :: Num u => RGBi -> FontAttr -> EscapedText -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: escapedlabel :: RGBi -> FontAttr -> EscapedText -> DPoint2 -> Primitive
- Wumpus.Core.Picture: extendBoundary :: (Num u, Ord u) => u -> u -> Picture u -> Picture u
+ Wumpus.Core.Picture: extendBoundary :: Double -> Double -> Picture -> Picture
- Wumpus.Core.Picture: fill :: Num u => RGBi -> PrimPath u -> Primitive u
+ Wumpus.Core.Picture: fill :: RGBi -> PrimPath -> Primitive
- Wumpus.Core.Picture: fillEllipse :: Num u => RGBi -> u -> u -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: fillEllipse :: RGBi -> Double -> Double -> DPoint2 -> Primitive
- Wumpus.Core.Picture: fillStroke :: Num u => RGBi -> StrokeAttr -> RGBi -> PrimPath u -> Primitive u
+ Wumpus.Core.Picture: fillStroke :: RGBi -> StrokeAttr -> RGBi -> PrimPath -> Primitive
- Wumpus.Core.Picture: fillStrokeEllipse :: Num u => RGBi -> StrokeAttr -> RGBi -> u -> u -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: fillStrokeEllipse :: RGBi -> StrokeAttr -> RGBi -> Double -> Double -> DPoint2 -> Primitive
- Wumpus.Core.Picture: fontDeltaContext :: FontAttr -> Primitive u -> Primitive u
+ Wumpus.Core.Picture: fontDeltaContext :: FontAttr -> Primitive -> Primitive
- Wumpus.Core.Picture: frame :: (Real u, Floating u, FromPtSize u) => [Primitive u] -> Picture u
+ Wumpus.Core.Picture: frame :: [Primitive] -> Picture
- Wumpus.Core.Picture: hkernlabel :: Num u => RGBi -> FontAttr -> [KerningChar u] -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: hkernlabel :: RGBi -> FontAttr -> [KerningChar] -> DPoint2 -> Primitive
- Wumpus.Core.Picture: illustrateBounds :: (Real u, Floating u, FromPtSize u) => RGBi -> Picture u -> Picture u
+ Wumpus.Core.Picture: illustrateBounds :: RGBi -> Picture -> Picture
- Wumpus.Core.Picture: illustrateBoundsPrim :: (Real u, Floating u, FromPtSize u) => RGBi -> Primitive u -> Picture u
+ Wumpus.Core.Picture: illustrateBoundsPrim :: RGBi -> Primitive -> Picture
- Wumpus.Core.Picture: illustrateControlPoints :: (Real u, Floating u, FromPtSize u) => RGBi -> Primitive u -> Picture u
+ Wumpus.Core.Picture: illustrateControlPoints :: RGBi -> Primitive -> Picture
- Wumpus.Core.Picture: kernEscInt :: u -> Int -> KerningChar u
+ Wumpus.Core.Picture: kernEscInt :: Double -> Int -> KerningChar
- Wumpus.Core.Picture: kernEscName :: u -> String -> KerningChar u
+ Wumpus.Core.Picture: kernEscName :: Double -> String -> KerningChar
- Wumpus.Core.Picture: kernchar :: u -> Char -> KerningChar u
+ Wumpus.Core.Picture: kernchar :: Double -> Char -> KerningChar
- Wumpus.Core.Picture: multi :: (Fractional u, Ord u) => [Picture u] -> Picture u
+ Wumpus.Core.Picture: multi :: [Picture] -> Picture
- Wumpus.Core.Picture: ostroke :: Num u => RGBi -> StrokeAttr -> PrimPath u -> Primitive u
+ Wumpus.Core.Picture: ostroke :: RGBi -> StrokeAttr -> PrimPath -> Primitive
- Wumpus.Core.Picture: picBeside :: (Num u, Ord u) => Picture u -> Picture u -> Picture u
+ Wumpus.Core.Picture: picBeside :: Picture -> Picture -> Picture
- Wumpus.Core.Picture: picMoveBy :: (Num u, Ord u) => Picture u -> Vec2 u -> Picture u
+ Wumpus.Core.Picture: picMoveBy :: Picture -> DVec2 -> Picture
- Wumpus.Core.Picture: picOver :: (Num u, Ord u) => Picture u -> Picture u -> Picture u
+ Wumpus.Core.Picture: picOver :: Picture -> Picture -> Picture
- Wumpus.Core.Picture: primCat :: Primitive u -> Primitive u -> Primitive u
+ Wumpus.Core.Picture: primCat :: Primitive -> Primitive -> Primitive
- Wumpus.Core.Picture: primGroup :: [Primitive u] -> Primitive u
+ Wumpus.Core.Picture: primGroup :: [Primitive] -> Primitive
- Wumpus.Core.Picture: printPicture :: (Num u, PSUnit u) => Picture u -> IO ()
+ Wumpus.Core.Picture: printPicture :: Picture -> IO ()
- Wumpus.Core.Picture: rescapedlabel :: Num u => RGBi -> FontAttr -> EscapedText -> Radian -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: rescapedlabel :: RGBi -> FontAttr -> EscapedText -> Radian -> DPoint2 -> Primitive
- Wumpus.Core.Picture: rfillEllipse :: Num u => RGBi -> u -> u -> Radian -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: rfillEllipse :: RGBi -> Double -> Double -> Radian -> DPoint2 -> Primitive
- Wumpus.Core.Picture: rfillStrokeEllipse :: Num u => RGBi -> StrokeAttr -> RGBi -> u -> u -> Radian -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: rfillStrokeEllipse :: RGBi -> StrokeAttr -> RGBi -> Double -> Double -> Radian -> DPoint2 -> Primitive
- Wumpus.Core.Picture: rstrokeEllipse :: Num u => RGBi -> StrokeAttr -> u -> u -> Radian -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: rstrokeEllipse :: RGBi -> StrokeAttr -> Double -> Double -> Radian -> DPoint2 -> Primitive
- Wumpus.Core.Picture: rtextlabel :: Num u => RGBi -> FontAttr -> String -> Radian -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: rtextlabel :: RGBi -> FontAttr -> String -> Radian -> DPoint2 -> Primitive
- Wumpus.Core.Picture: strokeEllipse :: Num u => RGBi -> StrokeAttr -> u -> u -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: strokeEllipse :: RGBi -> StrokeAttr -> Double -> Double -> DPoint2 -> Primitive
- Wumpus.Core.Picture: textlabel :: Num u => RGBi -> FontAttr -> String -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: textlabel :: RGBi -> FontAttr -> String -> DPoint2 -> Primitive
- Wumpus.Core.Picture: vkernlabel :: Num u => RGBi -> FontAttr -> [KerningChar u] -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: vkernlabel :: RGBi -> FontAttr -> [KerningChar] -> DPoint2 -> Primitive
- Wumpus.Core.Picture: zcstroke :: Num u => PrimPath u -> Primitive u
+ Wumpus.Core.Picture: zcstroke :: PrimPath -> Primitive
- Wumpus.Core.Picture: zellipse :: Num u => u -> u -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: zellipse :: Double -> Double -> DPoint2 -> Primitive
- Wumpus.Core.Picture: zescapedlabel :: Num u => EscapedText -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: zescapedlabel :: EscapedText -> DPoint2 -> Primitive
- Wumpus.Core.Picture: zfill :: Num u => PrimPath u -> Primitive u
+ Wumpus.Core.Picture: zfill :: PrimPath -> Primitive
- Wumpus.Core.Picture: zostroke :: Num u => PrimPath u -> Primitive u
+ Wumpus.Core.Picture: zostroke :: PrimPath -> Primitive
- Wumpus.Core.Picture: ztextlabel :: Num u => String -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: ztextlabel :: String -> DPoint2 -> Primitive
- Wumpus.Core.WumpusTypes: data Picture u
+ Wumpus.Core.WumpusTypes: data Picture
- Wumpus.Core.WumpusTypes: data PrimLabel u
+ Wumpus.Core.WumpusTypes: data PrimLabel
- Wumpus.Core.WumpusTypes: data PrimPath u
+ Wumpus.Core.WumpusTypes: data PrimPath
- Wumpus.Core.WumpusTypes: data PrimPathSegment u
+ Wumpus.Core.WumpusTypes: data PrimPathSegment
- Wumpus.Core.WumpusTypes: data Primitive u
+ Wumpus.Core.WumpusTypes: data Primitive
- Wumpus.Core.WumpusTypes: type KerningChar u = (u, EscapedChar)
+ Wumpus.Core.WumpusTypes: type KerningChar = (Double, EscapedChar)

Files

demo/AffineTest01.hs view
@@ -17,10 +17,10 @@                [ circle_cpa, ellipse_cpa, path_cpa ]
 
 
-rot30 :: (Rotate t, Fractional u, u ~ DUnit t) => t -> t
+rot30 :: Rotate t => t -> t
 rot30 = rotate30
 
-rot30P :: (Real u, Floating u) => Primitive u -> Primitive u
+rot30P :: Primitive -> Primitive
 rot30P = rotate30
 
 -- Primitive - Text
demo/AffineTest02.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE TypeFamilies               #-}
 {-# OPTIONS -Wall #-}
 
 --------------------------------------------------------------------------------
@@ -16,11 +15,11 @@                [ circle_cpa, ellipse_cpa, path_cpa ]
 
 
-scale_onehalf_x_two :: (Scale t, Fractional u, u ~ DUnit t) => t -> t
+scale_onehalf_x_two :: Scale t => t -> t
 scale_onehalf_x_two = scale 1.5 2.0
 
 
-scale_onehalf_x_twoP :: Fractional u => Primitive u -> Primitive u
+scale_onehalf_x_twoP :: Primitive -> Primitive
 scale_onehalf_x_twoP = scale 1.5 2.0
 
 -- Primitive - Text
demo/AffineTest03.hs view
@@ -16,10 +16,10 @@                [ circle_cpa, ellipse_cpa, path_cpa ]
 
 
-translate_20x40 :: (Translate t, Fractional u, u ~ DUnit t) => t -> t
+translate_20x40 :: (Fractional u, Translate t, u ~ DUnit t) => t -> t
 translate_20x40 = translate 20.0 40.0
 
-translate_20x40P :: Fractional u => Primitive u -> Primitive u
+translate_20x40P :: Primitive -> Primitive
 translate_20x40P = translate 20.0 40.0
 
 -- Primitive - Text
demo/AffineTestBase.hs view
@@ -39,9 +39,9 @@       { ata_console_msg         :: String
       , ata_eps_file            :: FilePath
       , ata_svg_file            :: FilePath
-      , ata_prim_constructor    :: RGBi -> DPrimitive
-      , ata_pic_transformer     :: DPicture -> DPicture
-      , ata_prim_transformer    :: DPrimitive -> DPrimitive
+      , ata_prim_constructor    :: RGBi -> Primitive
+      , ata_pic_transformer     :: Picture -> Picture
+      , ata_prim_transformer    :: Primitive -> Primitive
       }
 
 runATA :: AffineTrafoAlg -> IO ()
@@ -56,23 +56,23 @@                           (ata_prim_transformer ata)
 
 
-buildPictureATA :: (RGBi -> DPrimitive) 
-         -> (DPicture -> DPicture) 
-         -> (DPrimitive -> DPrimitive) 
-         -> DPicture
+buildPictureATA :: (RGBi -> Primitive) 
+         -> (Picture -> Picture) 
+         -> (Primitive -> Primitive) 
+         -> Picture
 buildPictureATA mk picF primF = 
     picture1 `picBeside` picture2 `picBeside` picture3
   where
-    picture1 :: DPicture
+    picture1 :: Picture
     picture1 = illustrateBounds light_blue $ frame [mk black]
   
-    picture2 :: DPicture
+    picture2 :: Picture
     picture2 = illustrateBounds light_blue $ picF $ frame [mk blue]
 
-    picture3 :: DPicture
+    picture3 :: Picture
     picture3 = illustrateBoundsPrim light_blue prim
       where
-        prim :: DPrimitive
+        prim :: Primitive
         prim = primF $ mk red
 
 
@@ -85,8 +85,8 @@       { cpa_console_msg         :: String
       , cpa_eps_file            :: FilePath
       , cpa_svg_file            :: FilePath
-      , cpa_prim_constructor    :: RGBi -> DPrimitive
-      , cpa_prim_transformer    :: DPrimitive -> DPrimitive
+      , cpa_prim_constructor    :: RGBi -> Primitive
+      , cpa_prim_transformer    :: Primitive -> Primitive
       }
 
 runCPA :: ControlPointAlg -> IO ()
@@ -98,41 +98,42 @@   where
     pic = cpPicture (cpa_prim_constructor cpa) (cpa_prim_transformer cpa)
 
-cpPicture :: (RGBi -> DPrimitive) -> (DPrimitive -> DPrimitive) -> DPicture
+cpPicture :: (RGBi -> Primitive) -> (Primitive -> Primitive) -> Picture
 cpPicture constr trafo = 
     illustrateBounds light_blue $ illustrateControlPoints black 
                                 $ transformed_prim
   where
-   transformed_prim :: DPrimitive
+   transformed_prim :: Primitive
    transformed_prim = trafo $ constr red
 
 
 --------------------------------------------------------------------------------
 
-rgbLabel :: RGBi -> DPrimitive
+rgbLabel :: RGBi -> Primitive
 rgbLabel rgb = textlabel rgb wumpus_default_font "Wumpus!" zeroPt
 
-rgbCircle :: RGBi -> DPrimitive
+rgbCircle :: RGBi -> Primitive
 rgbCircle rgb = fillEllipse rgb 60 60 zeroPt
 
-rgbEllipse :: RGBi -> DPrimitive
+rgbEllipse :: RGBi -> Primitive
 rgbEllipse rgb = fillEllipse rgb 60 30 zeroPt
 
-rgbPath :: RGBi -> DPrimitive
+rgbPath :: RGBi -> Primitive
 rgbPath rgb = ostroke rgb default_stroke_attr $ dog_kennel
 
 --------------------------------------------------------------------------------
 -- Demo - draw a dog kennel...
 
 
-dog_kennel :: DPrimPath
-dog_kennel = primPath zeroPt [ lineTo  (P2 0 60) 
-                             , lineTo  (P2 40 100)
-                             , lineTo  (P2 80 60)
-                             , lineTo  (P2 80 0)
-                             , lineTo  (P2 60 0)  
-                             , lineTo  (P2 60 30)
-                             , curveTo (P2 60 50) (P2 50 60) (P2 40 60)
-                             , curveTo (P2 30 60) (P2 20 50) (P2 20 30)
-                             , lineTo  (P2 20 0)
-                             ]+dog_kennel :: PrimPath
+dog_kennel = absPrimPath zeroPt $ 
+    [ absLineTo  (P2 0 60) 
+    , absLineTo  (P2 40 100)
+    , absLineTo  (P2 80 60)
+    , absLineTo  (P2 80 0)
+    , absLineTo  (P2 60 0)  
+    , absLineTo  (P2 60 30)
+    , absCurveTo (P2 60 50) (P2 50 60) (P2 40 60)
+    , absCurveTo (P2 30 60) (P2 20 50) (P2 20 30)
+    , absLineTo  (P2 20 0)
+    ]
+ demo/ClipPic.hs view
@@ -0,0 +1,48 @@+{-# OPTIONS -Wall #-}++module ClipPic where++import Wumpus.Core+import Wumpus.Core.Colour++import System.Directory++main :: IO ()+main = do +    createDirectoryIfMissing True "./out"+    writeEPS "./out/clip_path01.eps" pic1+    writeSVG "./out/clip_path01.svg" pic1++++++pic1 :: Picture+pic1 = frame [ body ]+  where+    body = clip dog_house $ primGroup [ red_circle, green_circle, blue_circle ]++red_circle :: Primitive +red_circle = fillEllipse red 60 60      $ P2 (-20) 0++green_circle :: Primitive +green_circle = fillEllipse green 60 60  $ P2 30 80++blue_circle :: Primitive +blue_circle = fillEllipse blue 60 60    $ P2 80 0+++dog_house :: PrimPath+dog_house = absPrimPath zeroPt $ +    [ absLineTo  (P2 0 60) +    , absLineTo  (P2 40 100)+    , absLineTo  (P2 80 60)+    , absLineTo  (P2 80 0)+    , absLineTo  (P2 60 0)  +    , absLineTo  (P2 60 30)+    , absCurveTo (P2 60 50) (P2 50 60) (P2 40 60)+    , absCurveTo (P2 30 60) (P2 20 50) (P2 20 30)+    , absLineTo  (P2 20 0)+    ]++
demo/DeltaPic.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE TypeFamilies               #-} {-# OPTIONS -Wall #-}  -- SVG ouptut has some ability to minimization font change code.@@ -19,7 +18,6 @@   - main :: IO () main = do      createDirectoryIfMissing True "./out/"@@ -27,7 +25,7 @@     writeSVG "./out/delta_pic01.svg" pic1  -pic1 :: DPicture+pic1 :: Picture pic1 = frame1 $ fontDeltaContext delta_ctx $ primGroup             [ helveticaLabel 18 "Optimized - size and face"  (P2 0 60)           , helveticaLabel 14 "Optimized - face only"      (P2 0 40)@@ -44,10 +42,10 @@ -- Note - each label is fully attributed with the font style. -- There really is not attribute inheritance. ---helveticaLabel :: Int -> String -> DPoint2 -> DPrimitive+helveticaLabel :: Int -> String -> DPoint2 -> Primitive helveticaLabel sz ss pt = textlabel peru attrs ss pt   where     attrs = FontAttr sz common_ff -courierLabel :: String -> DPoint2 -> DPrimitive+courierLabel :: String -> DPoint2 -> Primitive courierLabel ss pt = textlabel black wumpus_default_font ss pt
demo/EllipsePic.hs view
@@ -14,25 +14,25 @@     writeSVG "./out/ellipse01.svg" pic1  -pic1 :: DPicture+pic1 :: Picture pic1 = frame [ ellipse01 $ P2 50 50              , ellipse02 $ P2 100 50              , ellipse03 $ P2 150 50              ]  -ellipse01 :: DPoint2 -> DPrimitive+ellipse01 :: DPoint2 -> Primitive ellipse01 pt = cstroke black default_stroke_attr $ -    curvedPath $ bezierEllipse 20 30 pt+    curvedPrimPath $ bezierEllipse 20 30 pt  -ellipse02 :: DPoint2 -> DPrimitive+ellipse02 :: DPoint2 -> Primitive ellipse02 pt = cstroke red default_stroke_attr $ -    curvedPath $ rbezierEllipse 20 30 0 pt+    curvedPrimPath $ rbezierEllipse 20 30 0 pt   -ellipse03 :: DPoint2 -> DPrimitive+ellipse03 :: DPoint2 -> Primitive ellipse03 pt = cstroke red default_stroke_attr $ -    curvedPath $ rbezierEllipse 20 30 (negate $ d2r (10::Double)) pt+    curvedPrimPath $ rbezierEllipse 20 30 (negate $ d2r (10::Double)) pt 
demo/FontMetrics.hs view
@@ -32,10 +32,10 @@ courier_attr = FontAttr 48 (FontFace "Courier" "Courier New"                                       SVG_REGULAR standard_encoding) -metrics_pic :: DPicture+metrics_pic :: Picture metrics_pic = char_pic `picOver` lines_pic -lines_pic   :: DPicture+lines_pic   :: Picture lines_pic   = frame $      [ ascender_line, cap_line, xheight_line, baseline, descender_line ]   where@@ -47,20 +47,20 @@   -char_pic :: Picture Double+char_pic :: Picture char_pic = frame $ zipWith ($) chars (iterate (.+^ hvec 32) zeroPt)   where     chars = map letter "ABXabdgjxy12"   -letter :: Char -> DPoint2 -> DPrimitive+letter :: Char -> DPoint2 -> Primitive letter ch pt = textlabel black courier_attr [ch] pt  -haxis :: RGBi -> PtSize -> DPrimitive+haxis :: RGBi -> Double -> Primitive haxis rgb ypos = -    ostroke rgb dash_attr $ vertexPath [ pt, pt .+^ hvec 440 ]+    ostroke rgb dash_attr $ vertexPrimPath [ pt, pt .+^ hvec 440 ]   where     dash_attr = default_stroke_attr { dash_pattern = Dash 0 [(2,2)] }-    pt        = P2 0 (fromPtSize ypos)+    pt        = P2 0 ypos
demo/Hyperlink.hs view
@@ -15,7 +15,9 @@     writeSVG "./out/svg_link01.svg"  link_pic  -link_pic :: DPicture-link_pic = frame [ xlink xref $ ztextlabel "www.haskell.org" zeroPt ]+link_pic :: Picture+link_pic = frame [ xlinkPrim xref $ ztextlabel "www.haskell.org" zeroPt ]   where          xref = xlinkhref "http://www.haskell.org"++
demo/KernPic.hs view
@@ -21,25 +21,26 @@                , "recommended for SVG."                ] -kern_pic :: DPicture+kern_pic :: Picture kern_pic = pic1 `picOver` pic2 `picOver` pic3  -pic1 :: DPicture+pic1 :: Picture pic1 = frame [ helveticaLabelH universal   (P2 0 50)              , helveticaLabelH universal   (P2 0 25)              ] -pic2 :: DPicture+pic2 :: Picture pic2 = illustrateBoundsPrim blue_violet $            helveticaLabelV universal (P2 200 180) -pic3 :: DPicture+pic3 :: Picture pic3 = frame [ symbolLabelH uUpsilon (P2 0 0) ] + -- Some attention is paid to kerning - note that the kern between  -- @i@ and @v@ is smaller than the norm. ---universal ::[DKerningChar]+universal ::[KerningChar] universal = [ kernchar     0  'u'             , kernchar    15  'n'             , kernchar    15  'i'@@ -57,16 +58,16 @@ -- -- 0o241 is upper-case upsilon in the Symbol encoding vector. -- -uUpsilon :: [ DKerningChar ]+uUpsilon :: [KerningChar] uUpsilon = [ kernEscInt 6 0o241, kernchar 12 'a', kernchar 12 'b' ]  -helveticaLabelH :: [KerningChar Double] -> DPoint2 -> DPrimitive+helveticaLabelH :: [KerningChar] -> DPoint2 -> Primitive helveticaLabelH xs pt = hkernlabel black helvetica18 xs pt -helveticaLabelV :: [KerningChar Double] -> DPoint2 -> DPrimitive+helveticaLabelV :: [KerningChar] -> DPoint2 -> Primitive helveticaLabelV xs pt = vkernlabel black helvetica18 xs pt -symbolLabelH :: [KerningChar Double] -> DPoint2 -> DPrimitive+symbolLabelH :: [KerningChar] -> DPoint2 -> Primitive symbolLabelH xs pt = hkernlabel black symbol18 xs pt  
demo/LabelPic.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE TypeFamilies               #-} {-# OPTIONS -Wall #-}  module LabelPic where@@ -55,13 +54,13 @@   -bigA, bigB, bigT :: Picture Double+bigA, bigB, bigT :: Picture bigA = bigLetter black 'A' bigB = bigLetter peru  'B' bigT = bigLetter plum  'T' -bigLetter :: RGBi -> Char -> Picture Double-bigLetter rgb ch = uniformScale 5 $ frame [textlabel rgb attrs [ch] zeroPt]+bigLetter :: RGBi -> Char -> Picture+bigLetter rgb ch = scale 5 5 $ frame [textlabel rgb attrs [ch] zeroPt]   where     attrs = FontAttr 12 (FontFace "Helvetica" "Helvetica"                                    SVG_REGULAR standard_encoding)@@ -73,7 +72,7 @@     writeEPS "./out/label05.eps" p1     writeSVG "./out/label05.svg" p1   where-    p1 = uniformScale 10 $ bigA `picOver` bigB `picOver` bigT+    p1 = scale 10 10 $ bigA `picOver` bigB `picOver` bigT   @@ -85,7 +84,7 @@     p1 = pA `picBeside` pB `picBeside` pC `picBeside` pA          pA = drawBounds bigA-    pB = drawBounds $ uniformScale 2 bigB+    pB = drawBounds $ scale 2 2 bigB     pC = drawBounds $ picMoveBy `flip` (vec 0 10) $ bigLetter peru 'C'  @@ -97,7 +96,7 @@     p1 = pA `picBeside` pB `picBeside` pC          pA = drawBounds bigA-    pB = drawBounds $ uniformScale 2 bigB+    pB = drawBounds $ scale 2 2 bigB     pC = drawBounds $ picMoveBy `flip` (vec 0 10) $ bigLetter peru 'C'  @@ -107,15 +106,15 @@   -drawBounds :: (Floating u, Real u, FromPtSize u) => Picture u -> Picture u+drawBounds :: Picture -> Picture drawBounds p        = p `picOver` (frame [zcstroke ph])   where-    ph            = vertexPath $ [bl,br,tr,tl]+    ph            = vertexPrimPath $ [bl,br,tr,tl]     (bl,br,tr,tl) = boundaryCorners $ boundary p   -- | The center of a picture.-center :: (Boundary a, Fractional u, DUnit a ~ u) => a -> Point2 u+center :: Picture -> DPoint2 center a = P2 hcenter vcenter    where       BBox (P2 x0 y0) (P2 x1 y1) = boundary a@@ -135,7 +134,7 @@   -lbl1 :: Picture Double+lbl1 :: Picture lbl1 = line1 `picBeside` line2 where   line1 = frame [textlabel peru attrs "Hello" zeroPt]   line2 = frame [textlabel peru attrs "World" zeroPt]
demo/Latin1Pic.hs view
@@ -43,7 +43,7 @@ -- -- Note - 0xE8 corresponds to Lslash in the standard encoding.  -- -pic1 :: DPicture+pic1 :: Picture pic1 = frame [ helveticaLabel "mystère"      (P2 0 60)              , helveticaLabel "mystère"    (P2 0 40) -- no HASH!              , helveticaLabel "myst&#0o350;re"    (P2 0 20)@@ -53,7 +53,7 @@   -helveticaLabel :: String -> DPoint2 -> DPrimitive+helveticaLabel :: String -> DPoint2 -> Primitive helveticaLabel ss pt = textlabel black helvetica18 ss pt  helvetica18 :: FontAttr
demo/MultiPic.hs view
@@ -17,17 +17,17 @@   -pic1 :: DPicture-pic1 = uniformScale 2 $ frame $ -    [ fillEllipse blue 10 10 zeroPt-    , fillEllipse red 10 10 (P2 40 40)-    , ztextlabel "Wumpus!" (P2 40 20)-    , square red 5 (P2 50 10)  +pic1 :: Picture+pic1 = scale 2 2 $ frame $ +    [ fillEllipse blue 10 10  zeroPt+    , fillEllipse red 10 10   (P2 40 40)+    , ztextlabel "Wumpus!"    (P2 40 20)+    , square red 5            (P2 50 10)       ]  -square :: (Num u, Ord u) => RGBi -> u -> Point2 u -> Primitive u-square rgb sidelen bl = fill rgb $ vertexPath $+square :: RGBi -> Double -> DPoint2 -> Primitive+square rgb sidelen bl = fill rgb $ vertexPrimPath $     [bl, bl .+^ hvec sidelen, bl .+^ V2 sidelen sidelen, bl .+^ vvec sidelen]  -- The PostScript generated from this is pretty good.
demo/TextBBox.hs view
@@ -31,7 +31,7 @@                                      SVG_REGULAR standard_encoding)  -words_pic   :: DPicture+words_pic   :: Picture words_pic   = frame $      [ line1, line2, line3, char1, char2 ]   where@@ -42,16 +42,15 @@     char2   = boundedCourier "2"                   (P2 29   0)  -boundedCourier :: String -> DPoint2 -> DPrimitive+boundedCourier :: String -> DPoint2 -> Primitive boundedCourier = boundedText courier -boundedText :: (Num u, Ord u, FromPtSize u) -            => FontAttr -> String -> Point2 u -> Primitive u+boundedText :: FontAttr -> String -> DPoint2 -> Primitive boundedText fa@(FontAttr sz _) ss pt = primCat bbox text   where-    esc_text  = escapeString ss  -    bbox_path = vertexPath $ boundaryCornerList $ textBoundsEsc sz pt esc_text-    bbox      = cstroke peru default_stroke_attr bbox_path-    text      = escapedlabel black fa esc_text pt+    esc_txt = escapeString ss  +    bb_path = vertexPrimPath $ boundaryCornerList $ textBoundsEsc sz pt esc_txt+    bbox    = cstroke peru default_stroke_attr bb_path+    text    = escapedlabel black fa esc_txt pt  
demo/TransformEllipse.hs view
@@ -28,7 +28,7 @@ gray :: RGBi gray = RGBi 127 127 127 -pic1 :: Picture Double+pic1 :: Picture pic1 = cb `picOver` ell `picOver` xy_frame "no transform"   where      ell  = mkRedEllipse id 20 10 pt@@ -36,7 +36,7 @@      pt   = P2 70 10  -pic2 :: Picture Double+pic2 :: Picture pic2 = cb `picOver` ell `picOver` xy_frame "rotate 30deg"   where      ell  = mkRedEllipse (rotate ang) 20 10 pt@@ -44,24 +44,24 @@      pt   = P2 70 10      ang  = d2r (30::Double) -pic3 :: Picture Double+pic3 :: Picture pic3 = cb `picOver` ell `picOver` xy_frame "rotateAbout (60,0) 30deg"   where      ell  = mkRedEllipse (rotateAbout ang pto) 20 10 pt      cb   = rotateAbout ang pto $ crossbar 20 10 pt      pt   = P2 70 10-     pto  = P2 60 0+     pto  = P2 60 0 `asTypeOf` dpt      ang  = d2r (30::Double)  -pic4 :: Picture Double+pic4 :: Picture pic4 = cb `picOver` ell `picOver` xy_frame "scale 1 2"   where      ell  = mkRedEllipse (scale 1 2) 20 10 pt      cb   = scale 1 2 $ crossbar 20 10 pt      pt   = P2 70 10 -pic5 :: Picture Double+pic5 :: Picture pic5 = cb `picOver` ell `picOver` xy_frame "translate -70 -10"   where      ell  = mkRedEllipse (translate (-70) (-10)) 20 10 pt@@ -69,25 +69,23 @@      pt   = P2 70 10  -mkRedEllipse :: (Real u, Floating u, FromPtSize u) -             => (Primitive u -> Primitive u) -             -> u -> u -> Point2 u -> Picture u+mkRedEllipse ::(Primitive -> Primitive) +             -> Double -> Double -> DPoint2 -> Picture mkRedEllipse trafo rx ry pt =      illustrateControlPoints gray $ trafo $ fillEllipse red rx ry pt -crossbar :: (Real u, Floating u, FromPtSize u) -         => u -> u -> Point2 u -> Picture u+crossbar :: Double -> Double -> DPoint2 -> Picture crossbar rx ry ctr = -    frame [ostroke black default_stroke_attr $ primPath west ps]+    frame [ostroke black default_stroke_attr $ absPrimPath west ps]   where-    ps    = [ lineTo east, lineTo ctr, lineTo north, lineTo south ]+    ps    = [ absLineTo east, absLineTo ctr, absLineTo north, absLineTo south ]     north = ctr .+^ vvec ry     south = ctr .-^ vvec ry      east  = ctr .+^ hvec rx     west  = ctr .-^ hvec rx  -xy_frame :: (Real u, Floating u, FromPtSize u) => String -> Picture u+xy_frame :: String -> Picture xy_frame ss =      frame [ mkline (P2 (-4) 0) (P2 150 0)           , mkline (P2 0 (-4)) (P2 0 150) @@ -95,4 +93,8 @@           ]    where-    mkline p1 p2 = ostroke black default_stroke_attr $ primPath p1 [lineTo p2]+    mkline p1 p2 = ostroke black default_stroke_attr $ +                     absPrimPath p1 [absLineTo p2]++dpt :: DPoint2+dpt = zeroPt
demo/TransformPath.hs view
@@ -26,7 +26,7 @@   -pic1 :: Picture Double+pic1 :: Picture pic1 = pth `picOver` ch `picOver` xy_frame "no transform"   where      pth  = mkBlackPath id pt@@ -34,7 +34,7 @@      pt   = P2 70 10  -pic2 :: Picture Double+pic2 :: Picture pic2 = pth `picOver` ch `picOver` xy_frame "rotate 30deg"   where      pth  = mkBlackPath (rotate ang) pt@@ -43,24 +43,24 @@      ang  = d2r (30::Double)  -pic3 :: Picture Double+pic3 :: Picture pic3 = pth `picOver` ch `picOver` xy_frame "rotateAbout (60,0) 30deg"   where      pth  = mkBlackPath (rotateAbout ang pto) pt      ch   = rotateAbout ang pto $ zcrosshair pt      pt   = P2 70 10-     pto  = P2 60 0+     pto  = P2 60 0 `asTypeOf` dpt      ang  = d2r (30::Double)      -pic4 :: Picture Double+pic4 :: Picture pic4 = pth `picOver` ch `picOver` xy_frame "scale 1 2"   where      pth  = mkBlackPath (scale 1 2) pt      ch   = scale 1 2 $ zcrosshair pt      pt   = P2 70 10 -pic5 :: Picture Double+pic5 :: Picture pic5 = pth `picOver` ch `picOver` xy_frame "translate -70 -10"   where      pth  = mkBlackPath (translate (-70) (-10)) pt@@ -68,13 +68,11 @@      pt   = P2 70 10  -mkBlackPath :: (Real u, Floating u, FromPtSize u) -             => (Primitive u -> Primitive u) -             -> Point2 u -> Picture u+mkBlackPath :: (Primitive -> Primitive) -> DPoint2 -> Picture mkBlackPath trafo bl = -    frame [ trafo $ ostroke black custom_stroke_attr $ primPath bl ps]+    frame [ trafo $ ostroke black custom_stroke_attr $ absPrimPath bl ps]   where-    ps = [lineTo p1, lineTo p2, lineTo p3]+    ps = [absLineTo p1, absLineTo p2, absLineTo p3]     p1 = bl .+^ vec 25 12     p2 = p1 .+^ vec 6 (-12)     p3 = p2 .+^ vec 25 12@@ -84,15 +82,14 @@ custom_stroke_attr :: StrokeAttr custom_stroke_attr = default_stroke_attr { line_width = 2 } -zcrosshair :: (Real u, Floating u, FromPtSize u) => Point2 u -> Picture u+zcrosshair :: DPoint2 -> Picture zcrosshair = crosshair 56 12  -crosshair :: (Real u, Floating u, FromPtSize u) -          => u -> u -> Point2 u -> Picture u+crosshair :: Double -> Double -> DPoint2 -> Picture crosshair w h bl = -    frame [ostroke burlywood default_stroke_attr $ primPath bl ps]+    frame [ostroke burlywood default_stroke_attr $ absPrimPath bl ps]   where-    ps    = [ lineTo tr, lineTo br, lineTo tl, lineTo bl ]+    ps    = [ absLineTo tr, absLineTo br, absLineTo tl, absLineTo bl ]     tl    = bl .+^ vvec h     tr    = bl .+^ vec  w h     br    = bl .+^ hvec w@@ -100,7 +97,7 @@ burlywood :: RGBi burlywood = RGBi 222 184 135 -xy_frame :: (Real u, Floating u, FromPtSize u) => String -> Picture u+xy_frame :: String -> Picture xy_frame ss =      frame [ mkline (P2 (-4) 0) (P2 150 0)           , mkline (P2 0 (-4)) (P2 0 150) @@ -108,4 +105,9 @@           ]    where-    mkline p1 p2 = ostroke black default_stroke_attr $ primPath p1 [lineTo p2]+    mkline p1 p2 = ostroke black default_stroke_attr $ +                     absPrimPath p1 [absLineTo p2]+++dpt :: DPoint2 +dpt = zeroPt
demo/TransformTextlabel.hs view
@@ -26,63 +26,60 @@   -pic1 :: Picture Double+pic1 :: Picture pic1 = txt `picOver` ch `picOver` xy_frame "no transform"   where-     txt  = mkBlackTextlabel id pt-     ch   = zcrosshair pt-     pt   = P2 70 10+    txt  = mkBlackTextlabel id pt+    ch   = zcrosshair pt+    pt   = P2 70 10  -pic2 :: Picture Double+pic2 :: Picture pic2 = txt `picOver` ch `picOver` xy_frame "rotate 30deg"   where-     txt  = mkBlackTextlabel (rotate ang) pt-     ch   = rotate ang $ zcrosshair pt-     pt   = P2 70 10-     ang  = d2r (30::Double)+    txt  = mkBlackTextlabel (rotate ang) pt+    ch   = rotate ang $ zcrosshair pt+    pt   = P2 70 10+    ang  = d2r (30::Double)  -pic3 :: Picture Double+pic3 :: Picture pic3 = txt `picOver` ch `picOver` xy_frame "rotateAbout (60,0) 30deg"   where-     txt  = mkBlackTextlabel (rotateAbout ang pto) pt-     ch   = rotateAbout ang pto $ zcrosshair pt-     pt   = P2 70 10-     pto  = P2 60 0-     ang  = d2r (30::Double)+    txt  = mkBlackTextlabel (rotateAbout ang pto) pt+    ch   = rotateAbout ang pto $ zcrosshair pt+    pt   = P2 70 10+    pto  = P2 60 0 `asTypeOf` dpt+    ang  = d2r (30::Double)  -pic4 :: Picture Double+pic4 :: Picture pic4 = txt `picOver` ch `picOver` xy_frame "scale 1 2"   where-     txt  = mkBlackTextlabel (scale 1 2) pt-     ch   = scale 1 2 $ zcrosshair pt-     pt   = P2 70 10+    txt  = mkBlackTextlabel (scale 1 2) pt+    ch   = scale 1 2 $ zcrosshair pt+    pt   = P2 70 10 -pic5 :: Picture Double+pic5 :: Picture pic5 = txt `picOver` ch `picOver` xy_frame "translate -70 -10"   where-     txt  = mkBlackTextlabel (translate (-70) (-10)) pt-     ch   = translate (-70) (-10) $ zcrosshair pt-     pt   = P2 70 10+    txt  = mkBlackTextlabel (translate (-70) (-10)) pt+    ch   = translate (-70) (-10) $ zcrosshair pt+    pt   = P2 70 10  -mkBlackTextlabel :: (Real u, Floating u, FromPtSize u) -                 => (Primitive u -> Primitive u) -                 -> Point2 u -> Picture u+mkBlackTextlabel :: (Primitive -> Primitive) -> DPoint2 -> Picture mkBlackTextlabel trafo bl =      frame [ trafo $ textlabel black wumpus_default_font "rhubarb" bl ]  -zcrosshair :: (Real u, Floating u, FromPtSize u) => Point2 u -> Picture u+zcrosshair :: DPoint2 -> Picture zcrosshair = crosshair 56 12  -crosshair :: (Real u, Floating u, FromPtSize u) -          => u -> u -> Point2 u -> Picture u+crosshair :: Double -> Double -> DPoint2 -> Picture crosshair w h bl = -    frame [ostroke burlywood default_stroke_attr $ primPath bl ps]+    frame [ostroke burlywood default_stroke_attr $ absPrimPath bl ps]   where-    ps    = [ lineTo tr, lineTo br, lineTo tl, lineTo bl ]+    ps    = [ absLineTo tr, absLineTo br, absLineTo tl, absLineTo bl ]     tl    = bl .+^ vvec h     tr    = bl .+^ vec  w h     br    = bl .+^ hvec w@@ -90,7 +87,7 @@ burlywood :: RGBi burlywood = RGBi 222 184 135 -xy_frame :: (Real u, Floating u, FromPtSize u) => String -> Picture u+xy_frame :: String -> Picture xy_frame ss =      frame [ mkline (P2 (-4) 0) (P2 150 0)           , mkline (P2 0 (-4)) (P2 0 150) @@ -98,4 +95,8 @@           ]    where-    mkline p1 p2 = ostroke black default_stroke_attr $ primPath p1 [lineTo p2]+    mkline p1 p2 = ostroke black default_stroke_attr $ +                     absPrimPath p1 [absLineTo p2]++dpt :: DPoint2+dpt = zeroPt
demo/ZOrderPic.hs view
@@ -29,16 +29,16 @@     , ""     ] -combined_pic :: DPicture+combined_pic :: Picture combined_pic = multi [pic1,pic2] -pic1 :: DPicture+pic1 :: Picture pic1 = frame $ prim_list zeroPt -pic2 :: DPicture +pic2 :: Picture  pic2 = multi $ map (\a -> frame [a]) $ prim_list (P2 200 0) -prim_list :: DPoint2 -> [DPrimitive]+prim_list :: DPoint2 -> [Primitive] prim_list = sequence [ fillEllipse red   20 20                      , \p -> fillEllipse green 20 20 (p .+^ hvec 20)                      , \p -> fillEllipse blue  20 20 (p .+^ hvec 40)
doc-src/Guide.lhs view
@@ -23,19 +23,20 @@ \section{About \wumpuscore}
 %-----------------------------------------------------------------
 
-This guide was last updated for \wumpuscore version 0.41.0.
+This guide was last updated for \wumpuscore version 0.50.0.
 
-\wumpuscore is a Haskell library for generating 2D vector 
-pictures. It was written with portability as a priority, so it has 
+\wumpuscore is a Haskell library for generating static 2D vector 
+pictures. It is written with portability as a priority, so it has 
 no dependencies on foreign C libraries. Output to PostScript and 
 SVG (Scalable Vector Graphics) is supported. 
 
 \wumpuscore is rather primitive, the basic drawing objects are 
 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}).
+\texttt{wumpus-basic} and \texttt{wumpus-drawing} build on 
+\wumpuscore adding significant capabilities but they are 
+experimental and the APIs they present are unfortunately a long 
+way from stable - currently they should be considered a 
+\emph{technology preview} not ready for general use.
 
 Although \wumpuscore is heavily inspired by PostScript it avoids 
 PostScript's notion of an (implicit) current point and the 
@@ -55,7 +56,7 @@ Some internal data types are also exported as opaque signatures - 
 the implementation is hidden, but the type name is exposed so it 
 can be used in the type signatures of \emph{userland} functions. 
-Typically, where these data types need to be \emph{instantiated}
+Typically, where these data types need to be \emph{instantiated},
 smart constructors are provided.
 
 \item[\texttt{Wumpus.Core.AffineTrans.}]
@@ -76,22 +77,22 @@ is (255, 255, 255). Some named colours are defined, although they 
 are hidden by the top level shim module to avoid name clashes with
 libraries providing more extensive lists of colours. 
-\texttt{Wumpus.Core.Colour} can be imported directly if a simple 
-list of named colours is required.
+\texttt{Wumpus.Core.Colour} can be imported directly if its
+elementary set of named colours is required.
 
 \item[\texttt{Wumpus.Core.FontSize.}]
-Various calculations for font size metrics. \wumpuscore has only
-approximate handling of font / character size as it does not 
-interpret the metrics within font files (doing so is a 
-substantially task attempted by \texttt{Wumpus.Basic} but 
-currently only for the simple and out-dated \texttt{AFM} font 
-format). Instead, \wumpuscore makes do with operations based on 
-measurements derived from the Courier mono-spaced font. Generally 
-using metrics from a mono-spaced font over-estimates for 
-proportional fonts, though in practice this is tolerable.
+Various calculations for font size measurements. \wumpuscore has 
+only approximate handling of font / character size as it does not 
+interpret the metrics within font files (doing so is a substantial 
+task handled by \texttt{Wumpus.Basic} for the simple \texttt{AFM} 
+font format). Instead, \wumpuscore makes do with operations based 
+on measurements derived from the Courier fixed width font. 
+Generally using metrics from a fixed width font over-estimates 
+sizes for proportional fonts, in practice this is fine as 
+\wumpuscore has limited needs.
 
 \item[\texttt{Wumpus.Core.Geometry.}]
-The usual types an operations from affine geometry - points, 
+The usual types and operations from affine geometry - points, 
 vectors and 3x3 matrices, also the \texttt{DUnit} type family.
 Essentially this type family is a trick used heavily within 
 \wumpuscore to avoid annotating class declarations with 
@@ -105,11 +106,12 @@ Data types modelling the attributes of PostScript's graphics 
 state (stroke style, dash pattern, etc.). Note that 
 \wumpuscore labels all primitives - paths, text labels - with 
-their rendering style, unlike PostScript there is no 
+their drawing attributes, unlike PostScript there is no 
 \emph{inheritance} of a Graphics State in \wumpuscore.
 
 \item[\texttt{Wumpus.Core.OutputPostScript.}]
-Functions to write PostScript or encapsulated PostScript files.
+Functions to write PostScript and Encapsulated PostScript (EPS) 
+files.
 
 \item[\texttt{Wumpus.Core.OutputSVG.}]
 Functions to write SVG files.
@@ -122,29 +124,24 @@ \texttt{PictureInternal} are exported with opaque signatures by 
 \texttt{Wumpus.Core.WumpusTypes}.
 
-\item[\texttt{Wumpus.Core.PtSize.}]
-Text size calculations in \texttt{Core.FontSize} use 
-\emph{printer's points} (i.e. 1/72 of an inch). The 
-\texttt{PtSize} module is a numeric type to represent them.
-
 \item[\texttt{Wumpus.Core.Text.Base.}]
-Types for handling escaped \emph{special} charcters within input 
+Types for handling escaped \emph{special} characters within input 
 text. Wumpus mostly follows SVG conventions for escaping strings, 
 although glyph names should \emph{always} correspond to PostScript 
 names and never XML / SVG ones, e.g. for \texttt{\&} use 
 \texttt{\#ampersand;} not \texttt{\#amp;}. 
 
 Also note, unless only SVG output is being generated, glyph 
-names should be used rather than char codes. For PostScript the 
-resolution of char codes is dependent on the encoding of the font 
-used to render it. As the core PostScript fonts use their own 
-encoding rather than the common Latin1 encoding, using using 
-numeric char codes (intending to be Latin1) can produce unexpected 
-results.
+names should be used rather than character codes. With PostScript, 
+the resolution of character codes is dependent on the encoding of 
+the font used to render it. As the core PostScript fonts use their 
+own encoding rather than the common Latin1 encoding, using using 
+numeric character codes (expected to be Latin1) can produce 
+unanticipated results.
 
 Unfortunately, even core fonts are often missing glyphs that 
 familiarity with Unicode and Web publishing might expect them 
-support. Generally, a PostScript renderer cannot do anything about 
+support. Generally, a PostScript renderer can do nothing about 
 missing glyphs - it might print a space or an open, tall rectangle. 
 As \wumpuscore is oblivious to the contents of fonts, it cannot 
 issue a warning if a glyph is not present when it generates a 
@@ -152,15 +149,16 @@ glyphs are used.
 
 \item[\texttt{Wumpus.Core.Text.GlyphIndices.}]
-An map of PostScript glyph names to Unicode code points. 
+An map of PostScript glyph names to Unicode code points.  
 
 \item[\texttt{Wumpus.Core.Text.GlyphNames.}]
 An map of Unicode code points to PostScript glyph names. 
 Unfortunately this table is \emph{lossy} - some code points have 
 more than one name, and as this file is auto-generated the 
-resolution of which glyph name matches a code point is arbtirary. 
-\wumpuscore uses this table only as a fallback if PostScript glyph 
-name resolution cannot be solved through an encoding vector.
+resolution of which overlapping glyph name matches a code point is 
+arbitrary. \wumpuscore uses this table only as a fallback if 
+PostScript glyph name resolution cannot be solved through a font's 
+encoding vector.
 
 \item[\texttt{Wumpus.Core.Text.Latin1Encoding.}]
 An encoding vector for the Latin 1 character set. 
@@ -191,24 +189,26 @@ \section{Drawing model}
 %-----------------------------------------------------------------
 
-\wumpuscore has two main drawable primitives \emph{paths}
-and text \emph{labels}, ellipses are also a primitive although 
-this is a concession to efficiency when drawing dots (which would 
-otherwise require 4 to 8 Bezier arcs to describe). Paths are made 
+\wumpuscore has two main drawing primitives \emph{paths}
+and text \emph{labels}. Ellipses are also a primitive although 
+this is a concession to efficiency for drawing dots, which would 
+otherwise require four Bezier arcs to describe. Paths are made 
 from straight sections or Bezier curves, they can be open and 
 \emph{stroked} to produce a line; or closed and \emph{stroked}, 
 \emph{filled} or \emph{clipped}. Labels represent a single 
 horizontal line of text - multiple lines must be composed from 
-multiple labels.
+multiple labels and white-space other than the \texttt{space}
+character should not be used.
 
 Primitives are attributed with drawing styles - font name and 
-size for labels; line width, colour, etc. for paths. Primitives
-can be grouped to support support hyperlinks in SVG output (so 
-Primitives are not strictly \emph{primitive}). The function 
-\texttt{frame} assembles a list of primitives into a 
-\texttt{Picture} with the standard affine frame where the origin
- is at (0,0) and the X and Y axes have the unit bases (i.e. they 
-have a \emph{scaling} value of 1). 
+point size for labels; line width, colour, etc. for paths. 
+Primitives can be grouped to support support hyperlinks in SVG 
+output (thus Primitives are not strictly \emph{primitive} as they 
+are implemented with some nesting). The function \texttt{frame} 
+assembles a list of primitives into a \texttt{Picture} with the 
+standard affine frame where the origin is at (0,0) and the X 
+and Y axes have the unit bases (i.e. they have a 
+\emph{scaling value} of 1). 
 
 \begin{figure}
 \centering
@@ -217,13 +217,13 @@ \end{figure}
 
 \wumpuscore uses the same picture frame as PostScript where 
-the origin at the bottom left, see Figure 1. This contrasts to SVG 
-where the origin is at the top-left. When \wumpuscore generates 
-SVG, the whole picture is generated within a matrix transformation 
-[ 1.0, 0.0, 0.0, -1.0, 0.0, 0.0 ] that changes the picture to use 
-PostScript coordinates. This has the side-effect that text is 
-otherwise drawn upside down, so \wumpuscore adds a rectifying 
-transform to each text element.
+the origin at is the bottom left, see Figure 1. This contrasts to 
+SVG where the origin is at the top-left. When \wumpuscore 
+generates SVG, the whole picture is generated within a matrix 
+transformation [ 1.0, 0.0, 0.0, -1.0, 0.0, 0.0 ] that changes the 
+picture to use PostScript coordinates. This has the side-effect 
+that text is otherwise drawn upside down, so \wumpuscore adds a 
+rectifying transformation to each text element.
 
 Once labels and paths are assembled as a \emph{Picture} they are
 transformable with the usual affine transformations (scaling, 
@@ -235,9 +235,9 @@ In some ways this is a limitation - for instance, the 
 \texttt{Diagrams} library appears to support some notion of 
 attribute overriding; however avoiding mutable attributes does 
-keep this part of \wumpuscore conceptually simple. To make 
-a blue or red arrow with \wumpuscore, one would make drawing 
-colour a parameter of the arrow constructor function.
+keep this part of \wumpuscore conceptually simple. To make a 
+blue or red triangle with \wumpuscore, one would make the drawing 
+colour a parameter of the triangle constructor function.
 
 %-----------------------------------------------------------------
 \section{Affine transformations}
@@ -245,7 +245,7 @@ 
 For affine transformations Wumpus uses the \texttt{Matrix3'3} data 
 type to represent 3x3 matrices in row-major form. The constructor
- \texttt{(M3'3 a b c  d e f  g h i)} builds this matrix:
+\texttt{(M3'3 a b c  d e f  g h i)} builds this matrix:
 
 \begin{displaymath}
 \begin{array}{ccc}
@@ -256,10 +256,9 @@ \end{displaymath}
 
 Note, in practice the elements \emph{g} and \emph{h} are 
-superflous. They are included in the data type to make it match 
-the typical representation from geometry texts. Also, typically 
-matrices will implicitly created with functions from the 
-\texttt{Core.Geometry} and \texttt{Core.AffineTrans} modules.
+largely superflous, but they are included in the data type so 
+the matrix operations available (e.g. \texttt{invert} and 
+\texttt{transpose}) have simple, regular definitions.
 
 For example a translation matrix moving 10 units in the X-axis and
 20 in the Y-axis will be encoded as 
@@ -277,9 +276,9 @@ as \texttt{concat} commands. For Pictures, \wumpuscore performs no
 transformations itself, delegating all the work to PostScript or
 SVG. Internally \wumpuscore transforms the bounding boxes of  
-Pictures - it needs to do this to maintain their size metrics 
-allowing transformed pictures to be composed with picture 
-composition operators like the \texttt{picBeside} combinator.
+Pictures - the bounding box of a pictured is cached so that 
+pictures can be composed with \emph{picture composition} operators 
+like the \texttt{picBeside} combinator.
 
 PostScript uses column-major form and uses a six element matrix
 rather than a nine element one. The translation matrix above 
@@ -306,10 +305,10 @@ points before the output is generated. For labels and ellipses the 
 \emph{start point} of the primitive (baseline-left for label, 
 center for ellipse) is transformed by \wumpuscore and matrix 
-operations are transmitted to PostScript and SVG to transform the 
-actual drawing (\wumpuscore has no access to the paths that 
-describe character glyphs so it cannot precompute transformations 
-on them).
+operations are transmitted in the generated PostScript and SVG to 
+transform the actual drawing (\wumpuscore has no access to the 
+paths that describe character glyphs so it cannot precompute 
+transformations on them).
 
 One consequence of transformations operating on the control points
 of primitives is that scalings do not scale the tip of the 
doc-src/WorldFrame.hs view
@@ -7,10 +7,11 @@ import Wumpus.Core.Text.StandardEncoding  main :: IO ()-main = writeEPS "WorldFrame.eps" world_frame+main = writeEPS "./out/WorldFrame.eps" world_frame >>+       writeSVG "./out/WorldFrame.svg" world_frame -world_frame :: DPicture-world_frame = uniformScale 0.75 $ +world_frame :: Picture+world_frame = scale 0.75 0.75 $      frame [ ogin, btm_right, top_left, top_right           , x_axis, y_axis, line1           ]@@ -26,13 +27,14 @@   -makeLabelPrim :: String -> DPoint2 -> DPrimitive+makeLabelPrim :: String -> DPoint2 -> Primitive makeLabelPrim = textlabel black attrs    where     attrs     = FontAttr 10 (FontFace "Helvetica" "Helvetica"                                        SVG_REGULAR standard_encoding) -makeLinePrim :: Double -> DPoint2 -> DPoint2 -> DPrimitive-makeLinePrim lw a b = ostroke black attrs $ primPath a [lineTo b]+makeLinePrim :: Double -> DPoint2 -> DPoint2 -> Primitive+makeLinePrim lw a b = ostroke black attrs $ absPrimPath a [absLineTo b]   where-    attrs = default_stroke_attr {line_width=lw}+    attrs = default_stroke_attr { line_width =  lw }+
doc/Guide.pdf view

binary file changed (68361 → 67925 bytes)

src/Wumpus/Core.hs view
@@ -3,10 +3,10 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Core--- Copyright   :  (c) Stephen Tetley 2009-2010+-- Copyright   :  (c) Stephen Tetley 2009-2011 -- License     :  BSD3 ----- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>+-- Maintainer  :  stephen.tetley@gmail.com -- Stability   :  unstable  -- Portability :  GHC --@@ -44,12 +44,10 @@   , module Wumpus.Core.OutputPostScript   , module Wumpus.Core.OutputSVG   , module Wumpus.Core.Picture-  , module Wumpus.Core.PtSize   , module Wumpus.Core.Text.Base   , module Wumpus.Core.VersionNumber   , module Wumpus.Core.WumpusTypes -   ) where  import Wumpus.Core.AffineTrans@@ -66,7 +64,6 @@ import Wumpus.Core.OutputPostScript import Wumpus.Core.OutputSVG import Wumpus.Core.Picture-import Wumpus.Core.PtSize import Wumpus.Core.Text.Base import Wumpus.Core.VersionNumber import Wumpus.Core.WumpusTypes
src/Wumpus/Core/AffineTrans.hs view
@@ -1,14 +1,12 @@ {-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE FlexibleInstances          #-} {-# OPTIONS -Wall #-} {-# LANGUAGE UndecidableInstances       #-} - ------------------------------------------------------------------------------ -- | -- Module      :  Wumpus.Core.AffineTrans--- Copyright   :  (c) Stephen Tetley 2009-2010+-- Copyright   :  (c) Stephen Tetley 2009-2011 -- License     :  BSD3 -- -- Maintainer  :  stephen.tetley@gmail.com@@ -20,7 +18,6 @@ -- The common affine transformations represented as type classes - -- scaling, rotation, translation. ----- -- Internally, when a Picture is composed and transformed, Wumpus -- only transforms the bounding box - transformations of the  -- picture content (paths or text labels) are communicated to @@ -49,6 +46,24 @@ -- representations of the affine transformations being invertible. -- Do not scale elements by zero! --+--+-- Design note - the formulation of the affine classes is not +-- ideal as dealing with units is avoided and the instances for+-- Point2 and Vec2 are only applicable to @DPoint2@ and @DVec2@.+-- Dealing with units is avoided as some useful units +-- (particulary Em and En) have contextual interterpretations - +-- i.e. their size is dependent on the current font size - and so +-- they cannot be accommodated without some monadic context.+-- +-- For this reason, the naming scheme for the affine classes was+-- changed at revision 0.50.0 to the current \"d\"-prefixed names.+-- This allows higher-level frameworks to define their own +-- functions or class-methods using the obvious good names +-- (@rotate@, @scale@ etc.). The derived operations (@rotate30@, +-- @uniformScale, etc.) have been removed as a higher-level +-- implementation is expected to re-implement them accounting for +-- polymorphic units as necessary.+--   --------------------------------------------------------------------------------  module Wumpus.Core.AffineTrans@@ -93,20 +108,35 @@ -------------------------------------------------------------------------------- -- Affine transformations  +--+-- Design Note +--+-- Perhaps the Transform class is not generally useful in the+-- presence of units.+-- ++ -- | Apply a matrix transformation directly. -- class Transform t where   transform :: u ~ DUnit t => Matrix3'3 u -> t -> t -instance Transform (UNil u) where-  transform _ = id +instance Transform a => Transform (Maybe a) where+  transform = fmap . transform++instance (u ~ DUnit a, u ~ DUnit b, Transform a, Transform b) => +    Transform (a,b)  where+  transform mtrx (a,b) = (transform mtrx a, transform mtrx b)++ instance Num u => Transform (Point2 u) where   transform ctm = (ctm *#)  instance Num u => Transform (Vec2 u) where   transform ctm = (ctm *#) + --------------------------------------------------------------------------------  -- | Type class for rotation.@@ -114,47 +144,68 @@ class Rotate t where   rotate :: Radian -> t -> t -instance Rotate (UNil u) where-  rotate _ = id  instance Rotate a => Rotate (Maybe a) where   rotate = fmap . rotate -instance (Rotate a, Rotate b, u ~ DUnit a, u ~ DUnit b) => Rotate (a,b) where++instance (Rotate a, Rotate b) => Rotate (a,b)  where   rotate ang (a,b) = (rotate ang a, rotate ang b)  -instance (Floating u, Real u) => Rotate (Point2 u) where-  rotate ang = ((rotationMatrix ang) *#)+instance (Real u, Floating u) => Rotate (Point2 u) where+  rotate ang pt = P2 x y +    where+      v        = pvec zeroPt pt+      (V2 x y) = avec (ang + vdirection v) $ vlength v -instance (Floating u, Real u) => Rotate (Vec2 u) where-  rotate ang = ((rotationMatrix ang) *#) +instance (Real u, Floating u) => Rotate (Vec2 u) where+  rotate ang v = avec (ang + vdirection v) $ vlength v +--+--+ -- | Type class for rotation about a point. --+-- Note - the point is a @DPoint2@ - i.e. it has PostScript points+-- for x and y-units.+-- class RotateAbout t where-  rotateAbout :: u ~ DUnit t =>  Radian -> Point2 u -> t -> t +  rotateAbout :: u ~ DUnit t => Radian -> Point2 u -> t -> t  -instance RotateAbout (UNil u) where-  rotateAbout _ _ = id+--+-- Note - it seems GHC 7.0.2 at least, would let us define a +-- RotateAbout instance for @()@, even though it has no valid+-- DUnit instance.+--+-- Still it seems safer to define a nil type with a phantom unit:+--+-- > data UNil u = UNil+-- +-- This data type is provided by Wumpus-Basic.+--  + instance RotateAbout a => RotateAbout (Maybe a) where   rotateAbout ang pt = fmap (rotateAbout ang pt) -instance (RotateAbout a, RotateAbout b, u ~ DUnit a, u ~ DUnit b) => ++instance (u ~ DUnit a, u ~ DUnit b, RotateAbout a, RotateAbout b) =>      RotateAbout (a,b) where   rotateAbout ang pt (a,b) = (rotateAbout ang pt a, rotateAbout ang pt b) +instance (Real u, Floating u) => RotateAbout (Point2 u) where+  rotateAbout ang (P2 ox oy) = +    translate ox oy . rotate ang . translate (-ox) (-oy)   -instance (Floating u, Real u) => RotateAbout (Point2 u) where-  rotateAbout ang pt = ((originatedRotationMatrix ang pt) *#)  +instance (Real u, Floating u) => RotateAbout (Vec2 u) where+  rotateAbout ang (P2 ox oy) = +    translate ox oy . rotate ang . translate (-ox) (-oy)  -instance (Floating u, Real u) => RotateAbout (Vec2 u) where-  rotateAbout ang pt = ((originatedRotationMatrix ang pt) *#)     -------------------------------------------------------------------------------- -- Scale@@ -162,22 +213,20 @@ -- | Type class for scaling. -- class Scale t where-  scale :: u ~ DUnit t => u -> u -> t -> t+  scale :: Double -> Double -> t -> t -instance Scale (UNil u) where-  scale _ _ = id  instance Scale a => Scale (Maybe a) where   scale sx sy = fmap (scale sx sy) -instance (Scale a, Scale b, u ~ DUnit a, u ~ DUnit b) => Scale (a,b) where+instance (Scale a, Scale b) => Scale (a,b) where   scale sx sy (a,b) = (scale sx sy a, scale sx sy b) -instance Num u => Scale (Point2 u) where-  scale sx sy = ((scalingMatrix sx sy) *#) +instance Fractional u => Scale (Point2 u) where+  scale sx sy (P2 x y) = P2 (x * realToFrac sx) (y * realToFrac sy) -instance Num u => Scale (Vec2 u) where-  scale sx sy = ((scalingMatrix sx sy) *#) +instance Fractional u => Scale (Vec2 u) where+  scale sx sy (V2 x y) = V2 (x * realToFrac sx) (y * realToFrac sy)  -------------------------------------------------------------------------------- -- Translate@@ -187,30 +236,27 @@ class Translate t where   translate :: u ~ DUnit t => u -> u -> t -> t --instance Translate (UNil u) where-  translate _ _ = id+instance Translate a => Translate (Maybe a) where+  translate dx dy = fmap (translate dx dy) -instance (Translate a, Translate b, u ~ DUnit a, u ~ DUnit b) => +instance (u ~ DUnit a, u ~ DUnit b, Translate a, Translate b) =>      Translate (a,b) where   translate dx dy (a,b) = (translate dx dy a, translate dx dy b) --instance Translate a => Translate (Maybe a) where-  translate dx dy = fmap (translate dx dy)- instance Num u => Translate (Point2 u) where-  translate dx dy (P2 x y) = P2 (x+dx) (y+dy)+  translate dx dy (P2 x y) = P2 (x + dx) (y + dy) -instance Num u => Translate (Vec2 u) where-  translate dx dy (V2 x y) = V2 (x+dx) (y+dy)+-- | Vectors do not respond to translation.+--+instance Translate (Vec2 u) where+  translate _ _ v0 = v0  + --------------------------------------------------------------------------------  -- Common rotations  - -- | Rotate by 30 degrees about the origin.  -- rotate30 :: Rotate t => t -> t @@ -268,17 +314,17 @@  -- | Scale both x and y dimensions by the same amount. ---uniformScale :: (Scale t, DUnit t ~ u) => u -> t -> t +uniformScale :: Scale t => Double -> t -> t  uniformScale a = scale a a   -- | Reflect in the X-plane about the origin. ---reflectX :: (Num u, Scale t, DUnit t ~ u) => t -> t+reflectX :: Scale t => t -> t reflectX = scale (-1) 1  -- | Reflect in the Y-plane about the origin. ---reflectY :: (Num u, Scale t, DUnit t ~ u) => t -> t+reflectY :: Scale t => t -> t reflectY = scale 1 (-1)  --------------------------------------------------------------------------------
src/Wumpus/Core/BoundingBox.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE FlexibleInstances          #-} {-# OPTIONS -Wall #-}  --------------------------------------------------------------------------------@@ -54,7 +55,6 @@  import Wumpus.Core.AffineTrans import Wumpus.Core.Geometry-import Wumpus.Core.Utils.Common ( PSUnit(..) ) import Wumpus.Core.Utils.FormatCombinators  @@ -73,50 +73,55 @@       { ll_corner :: Point2 u       , ur_corner :: Point2 u        }-  deriving (Eq,Show)+  deriving (Show)  type DBoundingBox = BoundingBox Double -+type instance DUnit (BoundingBox u) = u  -------------------------------------------------------------------------------- -- instances +instance (Tolerance u, Ord u) => Eq (BoundingBox u) where+  BBox ll0 ur0 == BBox ll1 ur1  = ll0 == ll1 && ur0 == ur1 +instance Functor BoundingBox where+  fmap f (BBox p0 p1) = BBox (fmap f p0) (fmap f p1) -instance PSUnit u => Format (BoundingBox u) where+instance Format u => Format (BoundingBox u) where   format (BBox p0 p1) = parens (text "BBox" <+> text "ll=" <> format p0                                              <+> text "ur=" <> format p1)    ----------------------------------------------------------------------------------- --type instance DUnit (BoundingBox u) = u+-- Transform... -pointTransform :: (Num u , Ord u)+-- | Helper for transformation.+--+pointTransform :: (Num u, Ord u)                 => (Point2 u -> Point2 u) -> BoundingBox u -> BoundingBox u-pointTransform fn bb = traceBoundary $ map fn $ [bl,br,tr,tl]-    where -      (bl,br,tr,tl) = boundaryCorners bb+pointTransform fn bb = +    traceBoundary $ map fn $ [bl,br,tr,tl]+  where +    (bl,br,tr,tl) = boundaryCorners bb  + instance (Num u, Ord u) => Transform (BoundingBox u) where   transform mtrx = pointTransform  (mtrx *#) -instance (Real u, Floating u) => Rotate (BoundingBox u) where+instance (Real u, Floating u, Ord u) => Rotate (BoundingBox u) where   rotate theta = pointTransform (rotate theta) -instance (Real u, Floating u) => RotateAbout (BoundingBox u) where+instance (Real u, Floating u, Ord u) => RotateAbout (BoundingBox u) where   rotateAbout theta pt = pointTransform (rotateAbout theta pt) -instance (Num u, Ord u) => Scale (BoundingBox u) where+instance (Fractional u, Ord u) => Scale (BoundingBox u) where   scale sx sy = pointTransform (scale sx sy)  instance (Num u, Ord u) => Translate (BoundingBox u) where   translate dx dy = pointTransform (translate dx dy) - -------------------------------------------------------------------------------- -- Boundary class @@ -127,6 +132,9 @@   boundary :: u ~ DUnit t => t -> BoundingBox u   +instance Boundary (BoundingBox u) where+  boundary = id+ --------------------------------------------------------------------------------  -- | 'boundingBox' : @lower_left_corner * upper_right_corner -> BoundingBox@@@ -237,7 +245,7 @@ --  -- Within test - is the supplied point within the bounding box? ---withinBoundary :: Ord u => Point2 u -> BoundingBox u -> Bool+withinBoundary :: (Tolerance u, Ord u) => Point2 u -> BoundingBox u -> Bool withinBoundary p (BBox ll ur) = (minPt p ll) == ll && (maxPt p ur) == ur  
src/Wumpus/Core/Colour.hs view
@@ -3,11 +3,11 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Core.Colour--- Copyright   :  (c) Stephen Tetley 2009-2010+-- Copyright   :  (c) Stephen Tetley 2009-2011 -- License     :  BSD3 ----- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>--- Stability   :  highly unstable+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable -- Portability :  GHC -- -- Colour represented as RGB with each component in the range 
src/Wumpus/Core/FontSize.hs view
@@ -36,8 +36,9 @@   -- * Type synonyms     FontSize   , CharCount-  , PtScale-  , ptSizeScale+  , AfmUnit+  , afmUnit+  , afmValue    -- * Scaling values derived from Courier   , mono_width@@ -66,11 +67,9 @@  import Wumpus.Core.BoundingBox import Wumpus.Core.Geometry-import Wumpus.Core.PtSize import Wumpus.Core.Text.Base  - type CharCount = Int type FontSize = Int @@ -79,22 +78,39 @@ -- (Point size) of a font. AFM files encode all measurements  -- as these units.  -- -newtype PtScale = PtScale { getPtScale :: Double } +newtype AfmUnit = AfmUnit { getAfmUnit :: Double }    deriving (Eq,Ord,Num,Floating,Fractional,Real,RealFrac,RealFloat)  -instance Show PtScale where-  showsPrec p d = showsPrec p (getPtScale d)+instance Show AfmUnit where+  showsPrec p d = showsPrec p (getAfmUnit d) +instance Tolerance AfmUnit where+  eq_tolerance     = 0.001+  length_tolerance = 0.1 --- | 'ptSizeScale' : @ scale_factor -> pt_size -> PTSize @++-- | Flipped version of 'afmValue'. ----- Scale the point size by the scale factor.+afmValueSZ :: AfmUnit -> FontSize -> Double+afmValueSZ = flip afmValue+++-- | Compute the size of a measurement in PostScript points +-- scaling the Afm unit size by the point size of the font. ---ptSizeScale :: PtScale -> PtSize -> PtSize -ptSizeScale sc sz = sz * realToFrac sc+afmValue :: FontSize -> AfmUnit -> Double+afmValue sz u = realToFrac u * (fromIntegral sz) / 1000  +-- | Compute the size of a measurement in Afm units scaled by the+-- point size of the font.+--+afmUnit :: FontSize -> Double -> AfmUnit+afmUnit sz u = 1000.0 * (realToFrac u) / (fromIntegral sz) +++ -- NOTE - I\'ve largely tried to follow the terminoloy from  -- Edward Tufte\'s /Visual Explantions/, page 99. --@@ -102,17 +118,17 @@  -- | The ratio of width to point size of a letter in Courier. ----- > mono_width = 0.6 +-- > mono_width = 600 ---mono_width :: PtScale-mono_width = 0.600+mono_width :: AfmUnit+mono_width = 600  -- | The ratio of cap height to point size of a letter in Courier. ----- > mono_cap_height = 0.562+-- > mono_cap_height = 562 -- -mono_cap_height :: PtScale -mono_cap_height = 0.562+mono_cap_height :: AfmUnit +mono_cap_height = 562   @@ -121,70 +137,70 @@ -- -- This is also known as the \"body height\". ----- > mono_x_height = 0.426+-- > mono_x_height = 426 -- -mono_x_height :: PtScale-mono_x_height = 0.426+mono_x_height :: AfmUnit+mono_x_height = 426   -- | The ratio of descender depth to point size of a letter in  -- Courier. -- --- > mono_descender = -0.157+-- > mono_descender = -157 -- -mono_descender :: PtScale-mono_descender = (-0.157)+mono_descender :: AfmUnit+mono_descender = (-157)   -- | The ratio of ascender to point size of a letter in Courier. -- --- > mono_ascender = 0.629+-- > mono_ascender = 629 -- -mono_ascender :: PtScale-mono_ascender = 0.629+mono_ascender :: AfmUnit+mono_ascender = 629   -- | The distance from baseline to max height as a ratio to point  -- size for Courier. -- --- > mono_max_height = 0.805+-- > mono_max_height = 805 -- -mono_max_height :: PtScale -mono_max_height = 0.805+mono_max_height :: AfmUnit +mono_max_height = 805   -- | The distance from baseline to max depth as a ratio to point  -- size for Courier. -- --- > max_depth = -0.250+-- > max_depth = -250 -- -mono_max_depth :: PtScale -mono_max_depth = (-0.250)+mono_max_depth :: AfmUnit +mono_max_depth = (-250)   -- | The left margin for the bounding box of printed text as a  -- ratio to point size for Courier. -- --- > mono_left_margin = -0.046+-- > mono_left_margin = -46 -- -mono_left_margin :: PtScale -mono_left_margin = (-0.046)+mono_left_margin :: AfmUnit +mono_left_margin = (-46)   -- | The right margin for the bounding box of printed text as a  -- ratio to point size for Courier. -- --- > mono_right_margin = 0.050+-- > mono_right_margin = 50 -- -mono_right_margin :: PtScale -mono_right_margin = 0.050+mono_right_margin :: AfmUnit +mono_right_margin = 50   -- | Approximate the width of a monospace character using  -- metrics derived from the Courier font. ---charWidth :: FontSize -> PtSize-charWidth = ptSizeScale mono_width . fromIntegral+charWidth :: FontSize -> Double+charWidth = afmValueSZ mono_width   @@ -196,7 +212,7 @@ -- NOTE - this does not account for any left and right margins  -- around the printed text. ---textWidth :: FontSize -> CharCount -> PtSize+textWidth :: FontSize -> CharCount -> Double textWidth _  n | n <= 0 = 0 textWidth sz n          = fromIntegral n * charWidth sz @@ -204,37 +220,37 @@ -- | Height of capitals e.g. \'A\' using metrics derived  -- the Courier monospaced font. ---capHeight :: FontSize -> PtSize+capHeight :: FontSize -> Double capHeight = fromIntegral   -- | Height of the lower-case char \'x\' using metrics derived  -- the Courier monospaced font. ---xcharHeight :: FontSize -> PtSize-xcharHeight = ptSizeScale mono_x_height . fromIntegral+xcharHeight :: FontSize -> Double+xcharHeight = afmValueSZ mono_x_height  -- | The total height span of the glyph bounding box for the  -- Courier monospaced font. ---totalCharHeight :: FontSize -> PtSize-totalCharHeight sz = let sz' = fromIntegral sz in -    ptSizeScale mono_max_height sz' + negate (ptSizeScale mono_max_depth sz')+totalCharHeight :: FontSize -> Double+totalCharHeight sz =  +    afmValueSZ mono_max_height sz + negate (afmValueSZ mono_max_depth sz)     -- | Ascender height for font size @sz@ using metrics from the  -- Courier monospaced font. -- -ascenderHeight :: FontSize -> PtSize-ascenderHeight = ptSizeScale mono_ascender . fromIntegral +ascenderHeight :: FontSize -> Double+ascenderHeight = afmValueSZ mono_ascender    -- | Descender depth for font size @sz@ using metrics from the  -- Courier monospaced font. -- -descenderDepth :: FontSize -> PtSize-descenderDepth = ptSizeScale mono_descender . fromIntegral +descenderDepth :: FontSize -> Double+descenderDepth = afmValueSZ mono_descender   -- | 'textBounds' : @ font_size * baseline_left * text -> BBox @@@ -250,8 +266,7 @@ -- For proportional fonts the calculated bounding box will  -- usually be too long. ---textBounds :: (Num u, Ord u, FromPtSize u) -           => FontSize -> Point2 u -> String -> BoundingBox u+textBounds :: FontSize -> DPoint2 -> String -> BoundingBox Double textBounds sz pt ss = textBoundsBody sz pt (charCount ss)   @@ -259,21 +274,18 @@ --  --  Version of textBounds for already escaped text. ---textBoundsEsc :: (Num u, Ord u, FromPtSize u) -           => FontSize -> Point2 u -> EscapedText -> BoundingBox u+textBoundsEsc :: FontSize -> DPoint2 -> EscapedText -> BoundingBox Double textBoundsEsc sz pt esc = textBoundsBody sz pt (textLength esc)   -textBoundsBody :: (Num u, Ord u, FromPtSize u) -               => FontSize -> Point2 u -> Int -> BoundingBox u+textBoundsBody :: FontSize -> DPoint2 -> Int -> BoundingBox Double textBoundsBody sz (P2 x y) len = boundingBox ll ur   where-    pt_sz       = fromIntegral sz-    w           = fromPtSize $ textWidth  sz len-    left_m      = fromPtSize $ ptSizeScale mono_left_margin  pt_sz-    right_m     = fromPtSize $ ptSizeScale mono_right_margin pt_sz-    max_depth   = fromPtSize $ ptSizeScale mono_max_depth  pt_sz-    max_height  = fromPtSize $ ptSizeScale mono_max_height pt_sz+    w           = textWidth  sz len+    left_m      = afmValueSZ mono_left_margin  sz+    right_m     = afmValueSZ mono_right_margin sz+    max_depth   = afmValueSZ mono_max_depth    sz+    max_height  = afmValueSZ mono_max_height   sz     ll          = P2 (x + left_m)      (y + max_depth)     ur          = P2 (x + w + right_m) (y + max_height) 
src/Wumpus/Core/Geometry.hs view
@@ -10,8 +10,8 @@ -- Copyright   :  (c) Stephen Tetley 2009-2011 -- License     :  BSD3 ----- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>--- Stability   :  highly unstable+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable -- Portability :  GHC -- -- Objects and operations for 2D geometry.@@ -26,12 +26,13 @@ module Wumpus.Core.Geometry   (  -  -- * Type family +    -- * Type family      DUnit-  , GuardEq-  ++  , Tolerance(..)++   -- * Data types-  , UNil   , Vec2(..)   , DVec2   , Point2(..)@@ -43,9 +44,15 @@    , MatrixMult(..) -  -- * UNil operations-  , uNil +  -- * Tolerance helpers+  , tEQ+  , tGT+  , tLT+  , tGTE+  , tLTE+  , tCompare+   -- * Vector operations   , vec   , hvec@@ -70,7 +77,7 @@   , rotationMatrix   , originatedRotationMatrix -  -- * matrix operations+  -- * Matrix operations   , invert   , determinant   , transpose@@ -93,23 +100,20 @@   ) where  -import Wumpus.Core.Utils.Common import Wumpus.Core.Utils.FormatCombinators  import Data.AffineSpace                         -- package: vector-space import Data.VectorSpace -import Data.Monoid  - -------------------------------------------------------------------------------- --- | Some unit of dimension usually double.+-- | Some unit of dimension usually Double. -- -- This very useful for reducing the kind of type classes to *. -- --- Doing this then allows constraints on the Unit type on the +-- Then constraints on the Unit type can be declared on the  -- instances rather than in the class declaration. --  type family DUnit a :: *@@ -122,33 +126,53 @@   --------------------------------------------------------------------------------- --- Datatypes ---- | Phantom @()@.+-- | Class for tolerance on floating point numbers. -- --- This newtype is Haskell\'s @()@ with unit of dimension @u@ as--- a phantom type.+-- Two tolerances are required tolerance for equality - commonly +-- used for testing if two points are equal - and tolerance for +-- path length measurement. -- --- 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.) +-- Path length measurement in Wumpus does not have a strong +-- need to be exact (precision is computational costly) - by +-- default it is 100x the equality tolerance. -- -newtype UNil u = UNil ()-  deriving (Bounded,Enum,Eq,Ord)+-- Bezier path lengths are calculated by iteration, so greater +-- accuracy requires more compution. As it is hard to visually+-- differentiate measures of less than a point the tolerance +-- for Points is quite high quite high (0.1).+-- +-- The situation is more complicated for contextual units +-- (Em and En) as they are really scaling factors. The bigger+-- the point size the less accurate the measure is.+-- +class Num u => Tolerance u where +  eq_tolerance     :: u+  length_tolerance :: u +  length_tolerance = 100 * eq_tolerance    +instance Tolerance Double where +  eq_tolerance     = 0.001+  length_tolerance = 0.1++++-- Datatypes ++ -- | 2D Vector - both components are strict. --+-- Note - equality is defined with 'Tolerance' and tolerance is +-- quite high for the usual units. See the note for 'Point2'.+--  data Vec2 u = V2        { vector_x :: !u        , vector_y :: !u       }-  deriving (Eq,Show)+  deriving (Show)  type DVec2 = Vec2 Double @@ -156,14 +180,19 @@  -- | 2D Point - both components are strict. -- --- Note - Point2 derives Ord so it can be used as a key in --- Data.Map etc.+-- Note - equality is defined with 'Tolerance' and tolerance is +-- quite high for the usual units. +-- +-- This is useful for drawing, *but* unacceptable data centric +-- work. If more accurate equality is needed define a newtype+-- wrapper over the unit type and make a @Tolerance@ instance with +-- much greater accuracy. -- data Point2 u = P2        { point_x    :: !u       , point_y    :: !u       }-  deriving (Eq,Ord,Show)+  deriving (Show)  type DPoint2 = Point2 Double @@ -215,10 +244,10 @@ newtype Radian = Radian { getRadian :: Double }   deriving (Num,Real,Fractional,Floating,RealFrac,RealFloat) + -------------------------------------------------------------------------------- -- Family instances -type instance DUnit (UNil u)        = u type instance DUnit (Point2 u)      = u type instance DUnit (Vec2 u)        = u type instance DUnit (Matrix3'3 u)   = u@@ -243,12 +272,32 @@ -------------------------------------------------------------------------------- -- instances +-- Eq (with tolerance) -instance Monoid (UNil u) where-  mempty        = UNil ()-  _ `mappend` _ = UNil ()+instance (Tolerance u, Ord u) => Eq (Vec2 u) where+  V2 x0 y0 == V2 x1 y1 = x0 `tEQ` x1 && y0 `tEQ` y1  +instance (Tolerance u, Ord u) => Eq (Point2 u) where+  P2 x0 y0 == P2 x1 y1 = x0 `tEQ` x1 && y0 `tEQ` y1+++-- Ord (with Tolerance)++instance (Tolerance u, Ord u) => Ord (Vec2 u) where+  V2 x0 y0 `compare` V2 x1 y1 = case tCompare x0 x1 of+                                  EQ  -> tCompare y0 y1+                                  ans -> ans+++instance (Tolerance u, Ord u) => Ord (Point2 u) where+  P2 x0 y0 `compare` P2 x1 y1 = case tCompare x0 x1 of+                                  EQ  -> tCompare y0 y1+                                  ans -> ans++++ -- Functor  instance Functor Vec2 where@@ -266,9 +315,6 @@  -- Show -instance Show (UNil u) where-  show _ = "UNil"- instance Show u => Show (Matrix3'3 u) where   show (M3'3 a b c d e f g h i) = "(M3'3 " ++ body ++ ")" where     body = show [[a,b,c],[d,e,f],[g,h,i]]@@ -308,18 +354,18 @@ -------------------------------------------------------------------------------- -- Pretty printing -instance PSUnit u => Format (Vec2 u) where-  format (V2 a b) = parens (text "Vec" <+> dtruncFmt a <+> dtruncFmt b)+instance Format u => Format (Vec2 u) where+  format (V2 a b) = parens (text "Vec" <+> format a <+> format b) -instance PSUnit u => Format (Point2 u) where-  format (P2 a b) = parens (dtruncFmt a <> comma <+> dtruncFmt b)+instance Format u => Format (Point2 u) where+  format (P2 a b) = parens (format a <> comma <+> format b) -instance PSUnit u => Format (Matrix3'3 u) where+instance Format u => Format (Matrix3'3 u) where   format (M3'3 a b c  d e f  g h i) =        vcat [matline a b c, matline d e f, matline g h i]     where       matline x y z = char '|' -         <+> (hcat $ map (fill 12 . dtruncFmt) [x,y,z]) +         <+> (hcat $ map (fill 12 . format) [x,y,z])           <+> char '|'     @@ -378,25 +424,76 @@ -- represented as homogeneous coordinates.  -- class MatrixMult t where -  (*#) :: DUnit t ~ u => Matrix3'3 u -> t -> t+  (*#) :: Num u => Matrix3'3 u -> t u -> t u  -instance Num u => MatrixMult (Vec2 u) where       -  (M3'3 a b c d e f _ _ _) *# (V2 m n) = V2 (a*m+b*n+c*0) (d*m+e*n+f*0)+instance MatrixMult Vec2 where       +  (M3'3 a b c d e f _ _ _) *# (V2 m n) = V2 (a*m + b*n + c*0) +                                            (d*m + e*n + f*0)  -instance Num u => MatrixMult (Point2 u) where-  (M3'3 a b c d e f _ _ _) *# (P2 m n) = P2 (a*m+b*n+c*1) (d*m+e*n+f*1)+instance MatrixMult Point2 where+  (M3'3 a b c d e f _ _ _) *# (P2 m n) = P2 (a*m + b*n + c*1) +                                            (d*m + e*n + f*1)   ----------------------------------------------------------------------------------- UNil --- | Construct a UNil.+infix 4 `tEQ`, `tLT`, `tGT`++-- | Tolerant equality - helper function for defining Eq instances+-- that use tolerance. ---uNil :: UNil u-uNil = UNil ()+-- Note - the definition actually needs Ord which is +-- unfortunate (as Ord is /inaccurate/).+--+tEQ :: (Tolerance u, Ord u) => u -> u -> Bool+tEQ a b = (abs (a-b)) < eq_tolerance +-- | Tolerant less than.+--+-- Note - the definition actually needs Ord which is +-- unfortunate (as Ord is /inaccurate/).+--+tLT :: (Tolerance u, Ord u) => u -> u -> Bool+tLT a b = a < b && (b - a) > eq_tolerance+++-- | Tolerant greater than.+--+-- Note - the definition actually needs Ord which is +-- unfortunate (as Ord is /inaccurate/).+--+tGT :: (Tolerance u, Ord u) => u -> u -> Bool+tGT a b = a > b && (a - b) > eq_tolerance++++-- | Tolerant less than or equal.+--+-- Note - the definition actually needs Ord which is +-- unfortunate (as Ord is /inaccurate/).+--+tLTE :: (Tolerance u, Ord u) => u -> u -> Bool+tLTE a b = tEQ a b || tLT a b+++-- | Tolerant greater than or equal.+--+-- Note - the definition actually needs Ord which is +-- unfortunate (as Ord is /inaccurate/).+--+tGTE :: (Tolerance u, Ord u) => u -> u -> Bool+tGTE a b = tEQ a b || tGT a b+++-- | Tolerant @compare@.+--+tCompare :: (Tolerance u, Ord u) => u -> u -> Ordering+tCompare a b | a `tEQ` b = EQ+             | otherwise = compare a b++ -------------------------------------------------------------------------------- -- Vectors @@ -441,7 +538,7 @@ avec :: Floating u => Radian -> u -> Vec2 u avec theta d = V2 x y    where-    ang = fromRadian theta+    ang = fromRadian $ circularModulo theta     x   = d * cos ang     y   = d * sin ang @@ -605,7 +702,8 @@ -- >       sin(a)   cos(a)  0 -- >       0        0       1 ) ---rotationMatrix :: (Floating u, Real u) => Radian -> Matrix3'3 u+rotationMatrix :: (Floating u, Real u) +               => Radian -> Matrix3'3 u rotationMatrix a = M3'3 (cos ang) (negate $ sin ang) 0                          (sin ang) (cos ang)          0                           0         0                  1@@ -637,7 +735,8 @@      mTinv = M3'3 1 0 (-x)                    0 1 (-y)  -                 0 0   1+                 0 0 1+     @@ -825,7 +924,7 @@ -- the approximation seems fine in practice. -- rbezierEllipse :: (Real u, Floating u) -              => u -> u -> Radian -> Point2 u -> [Point2 u]+               => u -> u -> Radian -> Point2 u -> [Point2 u] rbezierEllipse rx ry theta pt@(P2 x y) =      [ p00,c01,c02, p03,c04,c05, p06,c07,c08, p09,c10,c11, p00 ]   where
src/Wumpus/Core/GraphicProps.hs view
@@ -108,8 +108,26 @@       }   deriving (Eq,Ord,Show) --- | 'FontFace' : @ postscript_name * svg_font_family * svg_font_style @+-- | 'FontFace' : @ postscript_name * svg_font_family * svg_font_style +--                * encoding_vector  @ --+-- For the writing fonts in the Core 14 set the definitions are:+--+-- > "Times-Roman"       "Times New Roman" SVG_REGULAR     standard_encoding+-- > "Times-Italic"      "Times New Roman" SVG_ITALIC      standard_encoding+-- > "Times-Bold"        "Times New Roman" SVG_BOLD        standard_encoding+-- > "Times-BoldItalic"  "Times New Roman" SVG_BOLD_ITALIC standard_encoding+-- > +-- > "Helvetica"              "Helvetica" SVG_REGULAR      standard_encoding+-- > "Helvetica-Oblique"      "Helvetica" SVG_OBLIQUE      standard_encoding+-- > "Helvetica-Bold"         "Helvetica" SVG_BOLD         standard_encoding+-- > "Helvetica-Bold-Oblique" "Helvetica" SVG_BOLD_OBLIQUE standard_encoding+-- >+-- > "Courier"              "Courier New"    SVG_REGULAR      standard_encoding+-- > "Courier-Oblique"      "Courier New"    SVG_OBLIQUE      standard_encoding+-- > "Courier-Bold"         "Courier New"    SVG_BOLD         standard_encoding+-- > "Courier-Bold-Oblique" "Courier New"    SVG_BOLD_OBLIQUE standard_encoding+-- data FontFace = FontFace       { ps_font_name            :: String       , svg_font_family         :: String@@ -193,6 +211,12 @@ -- Defaults  -- | Default stroke attributes.+-- +-- > line_width      = 1+-- > miter_limit     = 1+-- > line_cap        = CapButt+-- > line_join       = JoinMiter+-- > dash_pattern    = Solid -- default_stroke_attr :: StrokeAttr default_stroke_attr = StrokeAttr { line_width      = 1
src/Wumpus/Core/OutputPostScript.hs view
@@ -4,11 +4,11 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Core.PostScript--- Copyright   :  (c) Stephen Tetley 2009-2010+-- Copyright   :  (c) Stephen Tetley 2009-2011 -- License     :  BSD3 ----- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>--- Stability   :  highly unstable+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable -- Portability :  GHC -- -- Output PostScript - either PostScript (PS) files or @@ -36,7 +36,6 @@ import Wumpus.Core.Text.Base import Wumpus.Core.Text.GlyphNames import Wumpus.Core.TrafoInternal-import Wumpus.Core.Utils.Common import Wumpus.Core.Utils.JoinList hiding ( cons ) import Wumpus.Core.Utils.FormatCombinators @@ -164,8 +163,7 @@ -- | Output a series of pictures to a Postscript file. Each  -- picture will be printed on a separate page.  ---writePS :: (Real u, Floating u, PSUnit u) -        => FilePath -> [Picture u] -> IO ()+writePS :: FilePath -> [Picture] -> IO () writePS filepath pics =      getZonedTime >>= \ztim -> writeFile filepath (show $ psDraw ztim pics) @@ -173,8 +171,7 @@ -- The .eps file can then be imported or embedded in another  -- document. ---writeEPS :: (Real u, Floating u, PSUnit u)  -         => FilePath -> Picture u -> IO ()+writeEPS :: FilePath -> Picture -> IO () writeEPS filepath pic =     getZonedTime >>= \ztim -> writeFile filepath (show $ epsDraw ztim pic) @@ -193,8 +190,7 @@ -- will need translating. -- -psDraw :: (Real u, Floating u, PSUnit u) -       => ZonedTime -> [Picture u] -> Doc+psDraw :: ZonedTime -> [Picture] -> Doc psDraw timestamp pics =      let body = vcat $ runPsMonad $ zipWithM psDrawPage pages pics     in vcat [ psHeader (length pics) timestamp@@ -208,10 +204,8 @@ -- | Note the bounding box may /below the origin/ - if it is, it -- will need translating. ---psDrawPage :: (Real u, Floating u, PSUnit u)-           => (String,Int) -> Picture u -> PsMonad Doc+psDrawPage :: (String,Int) -> Picture -> PsMonad Doc psDrawPage (lbl,ordinal) pic = -    let (_,cmdtrans) = imageTranslation pic in      (\doc -> vcat [ dsc_Page lbl ordinal                   , ps_gsave                   , cmdtrans@@ -220,27 +214,28 @@                   , ps_showpage                   ])        <$> picture pic-+  where+    (_,cmdtrans) = imageTranslation pic   -- | Note the bounding box may /below the origin/ - if it is, it -- will need translating. ---epsDraw :: (Real u, Floating u, PSUnit u)-        => ZonedTime -> Picture u -> Doc+epsDraw :: ZonedTime -> Picture -> Doc epsDraw timestamp pic =-    let (bb,cmdtrans) = imageTranslation pic -        body          = runPsMonad (picture pic) -    in vcat [ epsHeader bb timestamp-            , ps_wumpus_prolog-            , ps_gsave-            , cmdtrans-            , body-            , ps_grestore-            , epsFooter-            ]+    vcat [ epsHeader bb timestamp+         , ps_wumpus_prolog+         , ps_gsave+         , cmdtrans+         , body+         , ps_grestore+         , epsFooter+         ]+  where+    (bb,cmdtrans) = imageTranslation pic +    body          = runPsMonad (picture pic)   -imageTranslation :: (Ord u, PSUnit u) => Picture u -> (BoundingBox u, Doc)+imageTranslation :: Picture -> (DBoundingBox, Doc) imageTranslation pic = case repositionDeltas pic of   (bb, Nothing) -> (bb, empty)   (bb, Just v)  -> (bb, ps_translate v)@@ -288,20 +283,9 @@  -------------------------------------------------------------------------------- --- Note - PostScript ignotes any FontCtx changes via the @Group@--- constructor.------ Also - because Clip uses gsave grestore it has to resetGS on--- ending, otherwise the next picture will be diffing against--- a modified state (in Wumpus land) that contradicts the PostScript --- state. ----picture :: (Real u, Floating u, PSUnit u) => Picture u -> PsMonad Doc+picture :: Picture -> PsMonad Doc picture (Leaf    (_,xs) ones)   = bracketTrafos xs $ oneConcat primitive ones picture (Picture (_,xs) ones)   = bracketTrafos xs $ oneConcat picture ones-picture (Clip    (_,xs) cp pic) = bracketTrafos xs $-    (\d1 d2 -> vcat [ps_gsave,d1,d2,ps_grestore])-      <$> clipPath cp <*> picture pic <* resetGS   @@ -318,8 +302,16 @@ -- No action is taken for hyperlinks or font context changes in  -- PostScript. --+-- PostScript ignores any FontCtx changes via the @Group@ +-- constructor.+--+-- Also - because Clip uses gsave grestore it has to resetGS on+-- ending, otherwise the next picture will be diffing against a +-- modified state (in Wumpus land) that contradicts the PostScript +-- state. +-- -primitive :: (Real u, Floating u, PSUnit u) => Primitive u -> PsMonad Doc+primitive :: Primitive -> PsMonad Doc primitive (PPath props pp)          | isEmptyPath pp           = pure empty      | otherwise                = primPath props pp@@ -336,9 +328,12 @@  primitive (PGroup ones)        = oneConcat primitive ones +primitive (PClip cp chi) = +    (\d1 d2 -> vcat [ps_gsave,d1,d2,ps_grestore])+      <$> clipPath cp <*> primitive chi <* resetGS -primPath :: PSUnit u-         => PathProps -> PrimPath u -> PsMonad Doc++primPath :: PathProps -> PrimPath -> PsMonad Doc primPath (CFill rgb)     p =      (\rgbd -> vcat [rgbd, pathBody p, ps_closepath, ps_fill])        <$> deltaDrawColour rgb  @@ -357,13 +352,14 @@       <$> primPath (CFill fc) p <*> primPath (CStroke attrs sc) p  -clipPath :: PSUnit u => PrimPath u -> PsMonad Doc+clipPath :: PrimPath -> PsMonad Doc clipPath p = pure $ vcat [pathBody p , ps_closepath, ps_clip]  -pathBody :: PSUnit u => PrimPath u -> Doc-pathBody (PrimPath start xs) = -    vcat $ ps_newpath : ps_moveto start : (snd $ mapAccumL step start xs)+pathBody :: PrimPath -> Doc+pathBody ppath =+    let (start,xs) = extractRelPath ppath +    in vcat $ ps_newpath : ps_moveto start : (snd $ mapAccumL step start xs)   where     step pt (RelLineTo v)         = let p1 = pt .+^ v in (p1, ps_lineto p1)     step pt (RelCurveTo v1 v2 v3) = let p1 = pt .+^ v1 @@ -384,8 +380,7 @@ -- For good stroked ellipses, Bezier curves constructed from  -- PrimPaths should be used. ---primEllipse :: (Real u, Floating u, PSUnit u) -            => EllipseProps -> PrimEllipse u -> PsMonad Doc+primEllipse :: EllipseProps -> PrimEllipse -> PsMonad Doc primEllipse props (PrimEllipse hw hh ctm)      | hw == hh  = bracketPrimCTM ctm (drawC props)     | otherwise = bracketPrimCTM ctm (drawE props)@@ -404,13 +399,12 @@  -- This will need to become monadic to handle /colour delta/. ---fillEllipse :: PSUnit u => RGBi -> u -> u -> Point2 u -> PsMonad Doc+fillEllipse :: RGBi -> Double -> Double -> DPoint2 -> PsMonad Doc fillEllipse rgb rx ry pt =      (\rgbd -> rgbd `vconcat` ps_wumpus_FELL pt rx ry)       <$> deltaDrawColour rgb -strokeEllipse :: PSUnit u -              => RGBi -> StrokeAttr -> u -> u -> Point2 u -> PsMonad Doc+strokeEllipse :: RGBi -> StrokeAttr -> Double -> Double -> DPoint2 -> PsMonad Doc strokeEllipse rgb sa rx ry pt =     (\rgbd attrd -> vcat [ rgbd                          , attrd@@ -420,13 +414,12 @@  -- This will need to become monadic to handle /colour delta/. ---fillCircle :: PSUnit u => RGBi -> u -> Point2 u -> PsMonad Doc+fillCircle :: RGBi -> Double -> DPoint2 -> PsMonad Doc fillCircle rgb r pt =      (\rgbd -> rgbd `vconcat` ps_wumpus_FCIRC pt r)       <$> deltaDrawColour rgb -strokeCircle :: PSUnit u -              => RGBi -> StrokeAttr -> u -> Point2 u -> PsMonad Doc+strokeCircle :: RGBi -> StrokeAttr -> Double -> DPoint2 -> PsMonad Doc strokeCircle rgb sa r pt =     (\rgbd attrd -> vcat [ rgbd                          , attrd@@ -437,8 +430,7 @@ -- Note - for the otherwise case, the x-and-y coordinates are  -- encoded in the matrix, hence the @ 0 0 moveto @. ---primLabel :: (Real u, Floating u, PSUnit u) -          => LabelProps -> PrimLabel u -> PsMonad Doc+primLabel :: LabelProps -> PrimLabel -> PsMonad Doc primLabel (LabelProps rgb attrs) (PrimLabel body ctm) = bracketPrimCTM ctm mf   where     ev    = font_enc_vector $ font_face attrs    @@ -466,15 +458,13 @@ --      -labelBody :: PSUnit u -          => EncodingVector -> Point2 u -> LabelBody u -> Doc+labelBody :: EncodingVector -> DPoint2 -> LabelBody -> Doc labelBody ev pt (StdLayout txt) = ps_moveto pt `vconcat` psText ev txt labelBody ev pt (KernTextH xs)  = kernTextH ev pt xs labelBody ev pt (KernTextV xs)  = kernTextV ev pt xs  -- -kernTextH :: PSUnit u -                => EncodingVector -> Point2 u -> [KerningChar u] -> Doc+kernTextH :: EncodingVector -> DPoint2 -> [KerningChar] -> Doc kernTextH ev pt0 xs = snd $ F.foldl' fn (pt0,empty) xs   where     fn (P2 x y,acc) (dx,ch) = let doc1 = psChar ev ch@@ -484,8 +474,7 @@  -- Note - vertical labels grow downwards... ---kernTextV :: PSUnit u -                => EncodingVector -> Point2 u -> [KerningChar u] -> Doc+kernTextV :: EncodingVector -> DPoint2 -> [KerningChar] -> Doc kernTextV ev pt0 xs = snd $ F.foldl' fn (pt0,empty) xs   where     fn (P2 x y,acc) (dy,ch) = let doc1 = psChar ev ch@@ -568,12 +557,10 @@ -------------------------------------------------------------------------------- -- Bracket matrix and PrimCTM trafos -bracketTrafos :: (Real u, Floating u, PSUnit u) -              => [AffineTrafo u] -> PsMonad Doc -> PsMonad Doc+bracketTrafos :: [AffineTrafo] -> PsMonad Doc -> PsMonad Doc bracketTrafos xs ma = bracketMatrix (concatTrafos xs) ma  -bracketMatrix :: (Fractional u, PSUnit u) -              => Matrix3'3 u -> PsMonad Doc -> PsMonad Doc+bracketMatrix :: Matrix3'3 Double -> PsMonad Doc -> PsMonad Doc bracketMatrix mtrx ma      | mtrx == identityMatrix = ma     | otherwise              = (\doc -> vcat [inn, doc, out]) <$> ma@@ -582,16 +569,15 @@     out   = ps_concat $ invert mtrx  -bracketPrimCTM :: forall u. (Real u, Floating u, PSUnit u)-               => PrimCTM u -               -> (Point2 u -> PsMonad Doc) -> PsMonad Doc+bracketPrimCTM :: PrimCTM -> (DPoint2 -> PsMonad Doc) -> PsMonad Doc bracketPrimCTM ctm0 mf = step $ unCTM ctm0    where -    step (pt,ctm) -      | ctm == identityCTM  = mf pt+    step (p0,ctm) +      | ctm == identityCTM  = mf p0       | otherwise           = let mtrx  = matrixRepCTM ctm0  -- originalCTM                                   inn   = ps_concat $ mtrx                                   out   = ps_concat $ invert mtrx                               in (\doc -> vcat [inn, doc, out]) <$> mf zeroPt+  
src/Wumpus/Core/OutputSVG.hs view
@@ -4,11 +4,11 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Core.OutputSVG--- Copyright   :  (c) Stephen Tetley 2009-2010+-- Copyright   :  (c) Stephen Tetley 2009-2011 -- License     :  BSD3 ----- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>--- Stability   :  highly unstable+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable -- Portability :  GHC -- -- Output SVG. @@ -47,7 +47,6 @@ import Wumpus.Core.TrafoInternal import Wumpus.Core.Text.Base import Wumpus.Core.Text.GlyphIndices-import Wumpus.Core.Utils.Common import Wumpus.Core.Utils.FormatCombinators import Wumpus.Core.Utils.JoinList @@ -109,9 +108,9 @@ asksGraphicsState :: (GraphicsState -> a) -> SvgMonad a asksGraphicsState fn = fmap fn askGraphicsState -askFontAttr :: SvgMonad FontAttr-askFontAttr = asksGraphicsState $ \r -> -                FontAttr (gs_font_size r) (gs_font_face r)+askFontAttr     :: SvgMonad FontAttr+askFontAttr     = asksGraphicsState $ \r -> +                    FontAttr (gs_font_size r) (gs_font_face r)  askLineWidth    :: SvgMonad Double askLineWidth    = asksGraphicsState (line_width . gs_stroke_attr)@@ -143,8 +142,7 @@  -- | Output a picture to a SVG file.  ---writeSVG :: (Real u, Floating u, PSUnit u) -         => FilePath -> Picture u -> IO ()+writeSVG :: FilePath -> Picture -> IO () writeSVG filepath pic =      writeFile filepath $ show $ svgDraw Nothing pic  @@ -153,16 +151,14 @@ -- Output a picture to a SVG file the supplied /defs/ are -- written into the defs section of SVG file verbatim.  ---writeSVG_defs :: (Real u, Floating u, PSUnit u) -              => FilePath -> String -> Picture u -> IO ()+writeSVG_defs :: FilePath -> String -> Picture -> IO () writeSVG_defs filepath ss pic =      writeFile filepath $ show $ svgDraw (Just ss) pic   -svgDraw :: (Real u, Floating u, PSUnit u) -        => Maybe String -> Picture u -> Doc+svgDraw :: Maybe String -> Picture -> Doc svgDraw mb_defs original_pic = -    let pic          = trivialTranslation original_pic+    let pic          = svgPageTranslation original_pic         (_,imgTrafo) = imageTranslation pic         body         = runSvgMonad $ picture pic         mkSvg        = maybe elem_svg elem_svg_defs mb_defs@@ -170,8 +166,7 @@   -imageTranslation :: (Ord u, PSUnit u) -                 => Picture u -> (BoundingBox u, Doc -> Doc)+imageTranslation :: Picture -> (DBoundingBox, Doc -> Doc) imageTranslation pic = case repositionDeltas pic of   (bb, Nothing) -> (bb, id)   (bb, Just v)  -> let attr = attr_transform (val_translate v) @@ -179,20 +174,13 @@  -------------------------------------------------------------------------------- +-- Note - might be simpler to only print a @Picture Double@ -picture :: (Real u, Floating u, PSUnit u) => Picture u -> SvgMonad Doc+picture :: Picture -> SvgMonad Doc picture (Leaf    (_,xs) ones)   = bracketTrafos xs $ oneConcat primitive ones picture (Picture (_,xs) ones)   = bracketTrafos xs $ oneConcat picture ones-picture (Clip    (_,xs) cp pic) = -    bracketTrafos xs $ do { lbl <- newClipLabel-                          ; let d1 = clipPath lbl cp-                          ; d2  <- picture pic-                          ; return (vconcat d1 (elem_g (attr_clip_path lbl) d2))-                          }   -- oneConcat :: (a -> SvgMonad Doc) -> JoinList a -> SvgMonad Doc oneConcat fn ones = outstep (viewl ones)   where@@ -203,7 +191,7 @@     instep ac (e :< rest) = fn e >>= \a -> instep (ac `vconcat` a) (viewl rest)  -primitive :: (Real u, Floating u, PSUnit u) => Primitive u -> SvgMonad Doc+primitive :: Primitive -> SvgMonad Doc primitive (PPath props pp)           | isEmptyPath pp            = pure empty     | otherwise                 = primPath props pp@@ -219,6 +207,15 @@ primitive (PSVG anno chi)       = svgAnnoPrim anno <$> primitive chi  primitive (PGroup ones)         = oneConcat primitive ones++primitive (PClip cp chi)        =  do +    { lbl <- newClipLabel+    ; let d1 = clipPath lbl cp+    ; d2  <- primitive chi+    ; return (vconcat d1 (elem_g (attr_clip_path lbl) d2))+    } ++    svgAnnoPrim :: SvgAnno -> Doc -> Doc@@ -239,12 +236,12 @@ svgAttribute :: SvgAttr -> Doc svgAttribute (SvgAttr n v) = svgAttr n $ text v  -clipPath :: PSUnit u => String -> PrimPath u -> Doc+clipPath :: String -> PrimPath -> Doc clipPath clip_id pp =      elem_clipPath (attr_id clip_id) (elem_path_no_attrs $ path pp)   -primPath :: PSUnit u => PathProps -> PrimPath u -> SvgMonad Doc+primPath :: PathProps -> PrimPath -> SvgMonad Doc primPath props pp = (\(a,f) -> elem_path a (f $ path pp)) <$> pathProps props  --@@ -259,9 +256,10 @@ -- an encouragement to change when it moved to relative ones.  --  -path :: PSUnit u => PrimPath u -> Doc-path (PrimPath start xs) = -    path_m start <+> hsep (snd $ mapAccumL step start xs)+path :: PrimPath -> Doc+path ppath = +    let (start,xs) = extractRelPath ppath+    in path_m start <+> hsep (snd $ mapAccumL step start xs)   where     step pt (RelLineTo v)         = let p1 = pt .+^ v in (p1, path_l p1)     step pt (RelCurveTo v1 v2 v3) = let p1 = pt .+^ v1 @@ -296,18 +294,17 @@  -- Note - if hw==hh then draw the ellipse as a circle. ---primEllipse :: (Real u, Floating u, PSUnit u)-            => EllipseProps -> PrimEllipse u -> SvgMonad Doc+primEllipse :: EllipseProps -> PrimEllipse -> SvgMonad Doc primEllipse props (PrimEllipse hw hh ctm)      | hw == hh  = (\a b -> elem_circle (a <+> circle_radius <+> b))                     <$> bracketEllipseCTM ctm mkCXCY <*> ellipseProps props     | otherwise = (\a b -> elem_ellipse (a <+> ellipse_radius <+> b))                     <$> bracketEllipseCTM ctm mkCXCY <*> ellipseProps props   where-   mkCXCY (P2 x y) = pure $ attr_cx x <+> attr_cy y+    mkCXCY (P2 x y) = pure $ attr_cx x <+> attr_cy y    -   circle_radius   = attr_r hw-   ellipse_radius  = attr_rx hw <+> attr_ry hh+    circle_radius   = attr_r hw+    ellipse_radius  = attr_rx hw <+> attr_ry hh    @@ -323,15 +320,14 @@   --- Note - Rendering coloured text seemed convoluted --- (mandating the tspan element). +-- Note - SVG rendering coloured text seemed convoluted +-- mandating the tspan element in the output.  -- -- TO CHECK - is this really the case? --  -- -primLabel :: (Real u, Floating u, PSUnit u) -      => LabelProps -> PrimLabel u -> SvgMonad Doc+primLabel :: LabelProps -> PrimLabel -> SvgMonad Doc primLabel (LabelProps rgb attrs) (PrimLabel body ctm) =      (\fa ca -> elem_text (fa <+> ca) (makeTspan rgb dtext))       <$> deltaFontAttrs attrs <*> bracketTextCTM ctm coordf@@ -340,12 +336,12 @@     coordf = \p0 -> pure $ labelBodyCoords body p0     dtext  = labelBodyText body -labelBodyCoords :: PSUnit u => LabelBody u -> Point2 u -> Doc+labelBodyCoords :: LabelBody -> DPoint2 -> Doc labelBodyCoords (StdLayout _)  pt = makeXY pt labelBodyCoords (KernTextH xs) pt = makeXsY pt xs         labelBodyCoords (KernTextV xs) pt = makeXYs pt xs -labelBodyText :: LabelBody u -> Doc+labelBodyText :: LabelBody -> Doc labelBodyText (StdLayout enctext) = encodedText enctext labelBodyText (KernTextH xs)      = kerningText xs labelBodyText (KernTextV xs)      = kerningText xs@@ -354,7 +350,7 @@ encodedText :: EscapedText -> Doc encodedText enctext = hcat $ destrEscapedText (map svgChar) enctext -kerningText :: [KerningChar u] -> Doc+kerningText :: [KerningChar] -> Doc kerningText xs = hcat $ map (\(_,c) -> svgChar c) xs  @@ -362,7 +358,7 @@ makeTspan :: RGBi -> Doc -> Doc makeTspan rgb body = elem_tspan (attr_fill rgb) body -makeXY :: PSUnit u => Point2 u -> Doc+makeXY :: DPoint2 -> Doc makeXY (P2 x y) = attr_x x <+> attr_y y  -- This is for horizontal kerning text, the output is of the @@ -370,7 +366,7 @@ --  -- > x="0 10 25 35" y="0" ---makeXsY :: PSUnit u => Point2 u -> [KerningChar u] -> Doc+makeXsY :: DPoint2 -> [KerningChar] -> Doc makeXsY (P2 x y) ks = attr_xs (step x ks) <+> attr_y y   where      step ax ((d,_):ds) = let a = ax+d in a : step a ds @@ -385,7 +381,7 @@ -- Note - this is different to the horizontal version as the  -- x-coord needs to be /realigned/ at each step. ---makeXYs :: PSUnit u => Point2 u -> [KerningChar u] -> Doc+makeXYs :: DPoint2 -> [KerningChar] -> Doc makeXYs (P2 x y) ks = attr_xs xcoords <+> attr_ys (step y ks)   where      xcoords            = replicate (length ks) x@@ -496,15 +492,13 @@ -------------------------------------------------------------------------------- -- Bracket matrix and PrimCTM trafos -bracketTrafos :: (Real u, Floating u, PSUnit u) -              => [AffineTrafo u] -> SvgMonad Doc -> SvgMonad Doc+bracketTrafos :: [AffineTrafo] -> SvgMonad Doc -> SvgMonad Doc bracketTrafos xs ma = bracketMatrix (concatTrafos xs) ma  -bracketMatrix :: (Fractional u, PSUnit u) -              => Matrix3'3 u -> SvgMonad Doc -> SvgMonad Doc+bracketMatrix :: Matrix3'3 Double -> SvgMonad Doc -> SvgMonad Doc bracketMatrix mtrx ma -    | mtrx == identityMatrix = (\doc -> elem_g_no_attrs doc) <$>  ma-    | otherwise              = (\doc -> elem_g trafo doc) <$> ma+    | mtrx == identityMatrix = (\doc -> elem_g_no_attrs doc) <$> ma+    | otherwise              = (\doc -> elem_g trafo doc)    <$> ma   where     trafo = attr_transform $ val_matrix mtrx @@ -520,33 +514,33 @@ -- rectifying flip transformation /if/ the ellipse or circle has  -- not been scaled or rotated. ---bracketTextCTM :: forall u. (Real u, Floating u, PSUnit u)-               => PrimCTM u -               -> (Point2 u -> SvgMonad Doc) -> SvgMonad Doc+bracketTextCTM :: PrimCTM -> (DPoint2 -> SvgMonad Doc) -> SvgMonad Doc bracketTextCTM ctm0 pf = (\xy -> xy <+> mtrx) <$> pf zeroPt   where     mtrx = attr_transform $ val_matrix $ matrixRepCTM ctm0  + -- Note - the otherwise step uses the original ctm (ctm0). --  -- Note v0.41.0 otherwise step always fires because the matrix  -- has been transformed for SVG coordspace to [1,0,0,-1]. ---bracketEllipseCTM :: forall u. (Real u, Floating u, PSUnit u)-                  => PrimCTM u -                  -> (Point2 u -> SvgMonad Doc) -> SvgMonad Doc+bracketEllipseCTM :: PrimCTM -> (DPoint2 -> SvgMonad Doc) -> SvgMonad Doc bracketEllipseCTM ctm0 pf = step $ unCTM ctm0   where-    step (pt, ctm) -        | ctm == flippedCTM   = pf pt+    step (p0, ctm) +        | ctm == flippedCTM   = pf p0         | otherwise           = let mtrx = attr_transform $                                               val_matrix $ matrixRepCTM ctm0                                 in (\xy -> xy <+> mtrx) <$> pf zeroPt  -flippedCTM :: Num u => PrimCTM u-flippedCTM = PrimCTM { ctm_transl_x = 0,  ctm_transl_y = 0-                     , ctm_scale_x  = 1,  ctm_scale_y  = (-1)-                     , ctm_rotation = 0 }+flippedCTM :: PrimCTM+flippedCTM = PrimCTM { ctm_trans_x = 0+                     , ctm_trans_y = 0+                     , ctm_scale_x = 1+                     , ctm_scale_y = (-1)+                     , ctm_rotation = 0 +                     } 
src/Wumpus/Core/PageTranslation.hs view
@@ -3,11 +3,11 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Core.PageTranslation--- Copyright   :  (c) Stephen Tetley 2010+-- Copyright   :  (c) Stephen Tetley 2010-2011 -- License     :  BSD3 ----- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>--- Stability   :  highly unstable+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable -- Portability :  GHC -- -- Core page translation for SVG.@@ -22,8 +22,7 @@  module Wumpus.Core.PageTranslation   ( --    trivialTranslation+    svgPageTranslation    ) where @@ -31,7 +30,6 @@ import Wumpus.Core.PictureInternal import Wumpus.Core.TrafoInternal - -------------------------------------------------------------------------------- -- trivial translation @@ -40,32 +38,42 @@ -- worry about scaling the BoundingBox -- -trivialTranslation :: (Num u, Ord u) => Picture u -> Picture u-trivialTranslation pic = scale 1 (-1) (trivPic pic) -trivPic :: Num u => Picture u -> Picture u-trivPic (Leaf lc ones)      = Leaf lc $ fmap trivPrim ones-trivPic (Picture lc ones)   = Picture lc $ fmap trivPic ones-trivPic (Clip lc pp pic)    = Clip lc pp $ trivPic pic -trivPrim :: Num u => Primitive u -> Primitive u++svgPageTranslation :: Picture -> Picture+svgPageTranslation pic = scale 1 (-1) (trivPic pic)++++trivPic :: Picture -> Picture+trivPic (Leaf lc ones)      = Leaf lc (fmap trivPrim ones)+trivPic (Picture lc ones)   = Picture lc (fmap trivPic ones)+++-- | Path is unchanged because it is drawn directly in the output+-- and thus doesn\'t need a rectifying transformation.+--+trivPrim :: Primitive -> Primitive trivPrim (PPath a pp)     = PPath a pp trivPrim (PLabel a lbl)   = PLabel a (trivLabel lbl) trivPrim (PEllipse a ell) = PEllipse a (trivEllipse ell) trivPrim (PContext a chi) = PContext a (trivPrim chi) trivPrim (PSVG a chi)     = PSVG a (trivPrim chi) trivPrim (PGroup ones)    = PGroup $ fmap trivPrim ones+trivPrim (PClip pp chi)   = PClip pp (trivPrim chi)  -trivLabel :: Num u => PrimLabel u -> PrimLabel u-trivLabel (PrimLabel txt ctm) = PrimLabel txt (trivPrimCTM ctm) -trivEllipse :: Num u => PrimEllipse u -> PrimEllipse u+trivLabel :: PrimLabel -> PrimLabel+trivLabel (PrimLabel txt ctm) = +    PrimLabel txt (trivPrimCTM ctm)++trivEllipse :: PrimEllipse -> PrimEllipse trivEllipse (PrimEllipse hw hh ctm) = PrimEllipse hw hh (trivPrimCTM ctm) --- Is the translation here just negating the angle with scaling--- left untouched?+-- Negate the y scaling to flip the image. ---trivPrimCTM :: Num u => PrimCTM u -> PrimCTM u-trivPrimCTM (PrimCTM dx dy sx sy theta) = PrimCTM dx dy sx (-sy) theta+trivPrimCTM :: PrimCTM -> PrimCTM+trivPrimCTM (PrimCTM dx dy sx sy theta) = PrimCTM dx dy sx (negate sy) theta 
src/Wumpus/Core/Picture.hs view
@@ -1,5 +1,4 @@-{-# LANGUAGE TypeFamilies               #-}-{-# LANGUAGE FlexibleInstances          #-}+{-# LANGUAGE FlexibleContexts           #-} {-# OPTIONS -Wall #-}  --------------------------------------------------------------------------------@@ -8,8 +7,8 @@ -- Copyright   :  (c) Stephen Tetley 2009-2011 -- License     :  BSD3 ----- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>--- Stability   :  highly unstable+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable -- Portability :  GHC -- -- Construction of pictures, paths and text labels.@@ -39,15 +38,18 @@     frame   , multi   , fontDeltaContext-  , primPath-  , lineTo-  , curveTo-  , vertexPath-  , vectorPath-  , emptyPath-  , curvedPath+  , absPrimPath+  , absLineTo+  , absCurveTo+  , relPrimPath+  , relLineTo+  , relCurveTo+  , vertexPrimPath+  , vectorPrimPath+  , emptyPrimPath+  , curvedPrimPath   , xlinkhref-  , xlink+  , xlinkPrim   , svgattr   , annotateGroup   , annotateXLink@@ -112,10 +114,9 @@ import Wumpus.Core.Geometry import Wumpus.Core.GraphicProps import Wumpus.Core.PictureInternal-import Wumpus.Core.PtSize import Wumpus.Core.Text.Base import Wumpus.Core.TrafoInternal-import Wumpus.Core.Utils.Common+-- import Wumpus.Core.Units import Wumpus.Core.Utils.FormatCombinators hiding ( fill ) import Wumpus.Core.Utils.HList import Wumpus.Core.Utils.JoinList@@ -139,7 +140,7 @@ -- \*\* WARNING \*\* - this function throws a runtime error when  -- supplied the empty list. ---frame :: (Real u, Floating u, FromPtSize u) => [Primitive u] -> Picture u+frame :: [Primitive] -> Picture frame []     = error "Wumpus.Core.Picture.frame - empty list" frame (p:ps) = let (bb,ones) = step p ps in Leaf (bb,[]) ones    where@@ -154,7 +155,7 @@ -- \*\* WARNING \*\* - this function throws a runtime error when  -- supplied the empty list. ---multi :: (Fractional u, Ord u) => [Picture u] -> Picture u+multi :: [Picture] -> Picture multi []      = error "Wumpus.Core.Picture.multi - empty list" multi (p:ps)  = let (bb,ones) = step p ps in Picture (bb,[]) ones    where@@ -191,16 +192,16 @@ -- introducing nesting with @gsave@ and @grestore@ is not likely -- to improve the PostScript Wumpus generates. ---fontDeltaContext :: FontAttr -> Primitive u -> Primitive u+fontDeltaContext :: FontAttr -> Primitive -> Primitive fontDeltaContext fa p = PContext (FontCtx fa) p  --- | 'primPath' : @ start_point * [path_segment] -> PrimPath @+-- | 'absPrimPath' : @ start_point * [abs_path_segment] -> PrimPath @ ----- Create a Path from a start point and a list of PathSegments.+-- Create a Path from a start point and a list of AbsPathSegments. ---primPath :: Num u => Point2 u -> [AbsPathSegment u] -> PrimPath u-primPath pt xs = PrimPath pt $ step pt xs+absPrimPath :: DPoint2 -> [AbsPathSegment] -> PrimPath+absPrimPath pt xs = PrimPath (step pt xs) (startPointCTM pt)   where     step p (AbsLineTo p1:rest)        = RelLineTo (p1 .-. p) : step p1 rest     step p (AbsCurveTo p1 p2 p3:rest) = @@ -209,42 +210,71 @@     step _ []                         = []  +          --- | 'lineTo' : @ end_point -> path_segment @+-- | 'absLineTo' : @ end_point -> path_segment @ --  -- Create a straight-line PathSegment, the start point is  -- implicitly the previous point in a path. ---lineTo :: Point2 u -> AbsPathSegment u-lineTo = AbsLineTo+absLineTo :: DPoint2 -> AbsPathSegment +absLineTo = AbsLineTo --- | 'curveTo' : @ control_point1 * control_point2 * end_point -> +-- | 'absCurveTo' : @ control_point1 * control_point2 * end_point ->  --        path_segment @ --  -- Create a curved PathSegment, the start point is implicitly the  -- previous point in a path. -- ---curveTo :: Point2 u -> Point2 u -> Point2 u -> AbsPathSegment u-curveTo = AbsCurveTo+absCurveTo :: DPoint2 -> DPoint2 -> DPoint2 -> AbsPathSegment+absCurveTo = AbsCurveTo  --- | 'vertexPath' : @ [point] -> PrimPath @+-- | 'relPrimPath' : @ start_point * [rel_path_segment] -> PrimPath @+--+-- Create a Path from a start point and a list of RelPathSegments.+--+relPrimPath :: DPoint2 -> [PrimPathSegment] -> PrimPath+relPrimPath pt xs = PrimPath xs (startPointCTM pt)++++-- | 'relLineTo' : @ vec_to_end -> path_segment @ -- +-- Create a straight-line relative PathSegment, the vector is the +-- relative displacement.+--+relLineTo :: DVec2 -> PrimPathSegment +relLineTo = RelLineTo+    +-- | 'relCurveTo' : @ vec_to_cp1 * vec_to_cp2 * vec_to_end -> +--        path_segment @+-- +-- Create a curved relative PathSegment.+--+--+relCurveTo :: DVec2 -> DVec2 -> DVec2 -> PrimPathSegment+relCurveTo = RelCurveTo+++-- | 'vertexPrimPath' : @ [point] -> PrimPath @+--  -- Convert the list of vertices to a path of straight line  -- segments. -- -- \*\* 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"-vertexPath (x:xs) = PrimPath x $ snd $ mapAccumL step x xs+vertexPrimPath :: [DPoint2] -> PrimPath+vertexPrimPath []     = error "Picture.vertexPath - empty point list"+vertexPrimPath (x:xs) = +    PrimPath (snd $ mapAccumL step x xs) (startPointCTM x)   where     step a b = let v = b .-. a in (b, RelLineTo v)  --- | 'vectorPath' : @ start_point -> [next_vector] -> PrimPath @+-- | 'vectorPrimPath' : @ start_point -> [next_vector] -> PrimPath @ --  -- Build a \"relative\" path from the start point, appending  -- successive straight line segments formed from the list of @@ -253,22 +283,22 @@ -- This function can be supplied with an empty list - this  -- simulates a null graphic. ---vectorPath :: Num u => Point2 u -> [Vec2 u] -> PrimPath u-vectorPath pt xs = PrimPath pt $ map RelLineTo xs+vectorPrimPath :: DPoint2 -> [DVec2] -> PrimPath+vectorPrimPath pt xs = PrimPath (map RelLineTo xs) (startPointCTM pt)  --- | 'emptyPath' : @ start_point -> PrimPath @+-- | 'emptyPrimPath' : @ start_point -> PrimPath @ --  -- Build an empty path. The start point must be specified even -- though the path is not drawn - a start point is the minimum  -- information needed to calculate a bounding box.  ---emptyPath :: Num u => Point2 u -> PrimPath u-emptyPath pt  = PrimPath pt []+emptyPrimPath :: DPoint2 -> PrimPath+emptyPrimPath pt = PrimPath [] (startPointCTM pt)   --- | 'curvedPath' : @ points -> PrimPath @+-- | 'curvedPrimPath' : @ 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 @@ -278,9 +308,9 @@ -- \*\* 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+curvedPrimPath :: [DPoint2] -> PrimPath+curvedPrimPath []     = error "Picture.curvedPath - empty point list"+curvedPrimPath (x:xs) = PrimPath (step x xs) (startPointCTM x)   where     step p (a:b:c:ys) = let v1 = a .-. p                              v2 = b .-. a@@ -296,8 +326,8 @@  -- | Create a hyperlinked Primitive. ---xlink :: XLink -> Primitive u -> Primitive u-xlink hypl p = PSVG (ALink hypl) p  +xlinkPrim :: XLink -> Primitive -> Primitive+xlinkPrim hypl p = PSVG (ALink hypl) p     -- | Create an attribute for SVG output.@@ -324,7 +354,7 @@ -- The primitive will be printed in a @g@ (group) element  -- labelled with the annotations. ---annotateGroup :: [SvgAttr] -> Primitive u -> Primitive u+annotateGroup :: [SvgAttr] -> Primitive -> Primitive annotateGroup xs p = PSVG (GAnno xs) p    @@ -333,7 +363,7 @@ -- The primitive will be printed in a @g@ (group) element, itself -- inside an @a@ link. ---annotateXLink :: XLink -> [SvgAttr] -> Primitive u -> Primitive u+annotateXLink :: XLink -> [SvgAttr] -> Primitive -> Primitive annotateXLink hypl xs p = PSVG (SvgAG hypl xs) p    @@ -343,7 +373,7 @@ -- \*\* WARNING \*\* - this function throws a runtime error when  -- supplied the empty list. ---primGroup :: [Primitive u] -> Primitive u+primGroup :: [Primitive] -> Primitive primGroup []     = error "Picture.primGroup - empty prims list" primGroup (x:xs) = PGroup (step x xs)   where@@ -365,7 +395,7 @@ -- practice this may have no noticeable benefit as Wumpus has very  -- simple access patterns into the Primitive tree.  ---primCat :: Primitive u -> Primitive u -> Primitive u+primCat :: Primitive -> Primitive -> Primitive primCat (PGroup a) (PGroup b) = PGroup $ join a b primCat (PGroup a) prim       = PGroup $ join a (one prim)  primCat prim       (PGroup b) = PGroup $ join (one prim) b@@ -382,8 +412,7 @@ -- -- Create a open, stroked path. ---ostroke :: Num u -        => RGBi -> StrokeAttr -> PrimPath u -> Primitive u+ostroke :: RGBi -> StrokeAttr -> PrimPath -> Primitive ostroke rgb sa p = PPath (OStroke sa rgb) p  @@ -391,8 +420,7 @@ --  -- Create a closed, stroked path. ---cstroke :: Num u -        => RGBi -> StrokeAttr -> PrimPath u -> Primitive u+cstroke :: RGBi -> StrokeAttr -> PrimPath -> Primitive cstroke rgb sa p = PPath (CStroke sa rgb) p  @@ -401,7 +429,7 @@ -- Create an open, stroked path using the default stroke  -- attributes and coloured black. ---zostroke :: Num u => PrimPath u -> Primitive u+zostroke :: PrimPath -> Primitive zostroke = ostroke black default_stroke_attr   -- | 'zcstroke' : @ path -> Primitive @@@ -409,7 +437,7 @@ -- Create a closed stroked path using the default stroke  -- attributes and coloured black. ---zcstroke :: Num u => PrimPath u -> Primitive u+zcstroke :: PrimPath -> Primitive zcstroke = cstroke black default_stroke_attr  --------------------------------------------------------------------------------@@ -420,13 +448,13 @@ -- --  Create a filled path. ---fill :: Num u => RGBi -> PrimPath u -> Primitive u+fill :: RGBi -> PrimPath -> Primitive fill rgb p = PPath (CFill rgb) p  -- | 'zfill' : @ path -> Primitive @ -- -- Create a filled path coloured black. -zfill :: Num u => PrimPath u -> Primitive u+zfill :: PrimPath -> Primitive zfill = fill black  @@ -439,8 +467,7 @@ -- Create a closed path that is both filled and stroked (the fill -- is below in the zorder). ---fillStroke :: Num u -        => RGBi -> StrokeAttr -> RGBi -> PrimPath u -> Primitive u+fillStroke :: RGBi -> StrokeAttr -> RGBi -> PrimPath -> Primitive fillStroke frgb sa srgb p = PPath (CFillStroke frgb sa srgb) p  @@ -449,12 +476,12 @@ -------------------------------------------------------------------------------- -- Clipping  --- | 'clip' : @ path * picture -> Picture @+-- | 'clip' : @ path * primitive -> Primitive @ -- --- Clip a picture with respect to the supplied path.+-- Clip a primitive with respect to the supplied path. ---clip :: (Num u, Ord u) => PrimPath u -> Picture u -> Picture u-clip cp p = Clip (pathBoundary cp, []) cp p+clip :: PrimPath -> Primitive -> Primitive+clip cp p = PClip cp p  -------------------------------------------------------------------------------- -- Labels to primitive@@ -469,8 +496,7 @@ -- -- The supplied point is the left baseline. ---textlabel :: Num u -          => RGBi -> FontAttr -> String -> Point2 u -> Primitive u+textlabel :: RGBi -> FontAttr -> String -> DPoint2 -> Primitive textlabel rgb attr txt pt = rtextlabel rgb attr txt 0 pt  -- | 'rtextlabel' : @ rgb * font_attr * string * theta * @@ -481,8 +507,7 @@ -- -- The supplied point is the left baseline. ---rtextlabel :: Num u -           => RGBi -> FontAttr -> String -> Radian -> Point2 u -> Primitive u+rtextlabel :: RGBi -> FontAttr -> String -> Radian -> DPoint2 -> Primitive rtextlabel rgb attr txt pt theta =      rescapedlabel rgb attr (escapeString txt) pt theta @@ -492,7 +517,7 @@ -- Create a label where the font is @Courier@, text size is 14pt -- and colour is black. ---ztextlabel :: Num u => String -> Point2 u -> Primitive u+ztextlabel :: String -> DPoint2 -> Primitive ztextlabel = textlabel black wumpus_default_font  @@ -505,8 +530,7 @@ -- -- The supplied point is the left baseline. ---escapedlabel :: Num u -             => RGBi -> FontAttr -> EscapedText -> Point2 u -> Primitive u+escapedlabel :: RGBi -> FontAttr -> EscapedText -> DPoint2 -> Primitive escapedlabel rgb attr txt pt = rescapedlabel rgb attr txt 0 pt  -- | 'rescapedlabel' : @ rgb * font_attr * escaped_text * theta * @@ -517,9 +541,8 @@ -- -- The supplied point is the left baseline. ---rescapedlabel :: Num u -              => RGBi -> FontAttr -> EscapedText -> Radian -> Point2 u -              -> Primitive u+rescapedlabel :: RGBi -> FontAttr -> EscapedText -> Radian -> DPoint2+              -> Primitive rescapedlabel rgb attr txt theta (P2 dx dy) = PLabel (LabelProps rgb attr) lbl    where     lbl = PrimLabel (StdLayout txt) (makeThetaCTM dx dy theta)@@ -530,7 +553,7 @@ -- Version of 'ztextlabel' where the label text has already been  -- encoded. ---zescapedlabel :: Num u => EscapedText -> Point2 u -> Primitive u+zescapedlabel :: EscapedText -> DPoint2 -> Primitive zescapedlabel = escapedlabel black wumpus_default_font  @@ -567,9 +590,7 @@ -- PostScript analogue. While the same picture is generated in  -- both cases, the PostScript code is not particularly inefficient. ---hkernlabel :: Num u -            => RGBi -> FontAttr -> [KerningChar u] -> Point2 u -            -> Primitive u+hkernlabel :: RGBi -> FontAttr -> [KerningChar] -> DPoint2 -> Primitive hkernlabel rgb attr xs (P2 x y) = PLabel (LabelProps rgb attr) lbl    where     lbl = PrimLabel (KernTextH xs) (makeTranslCTM x y)@@ -609,9 +630,7 @@ -- PostScript analogue. While the same picture is generated in  -- both cases, the PostScript code is not particularly inefficient. ---vkernlabel :: Num u -            => RGBi -> FontAttr -> [KerningChar u] -> Point2 u -            -> Primitive u+vkernlabel :: RGBi -> FontAttr -> [KerningChar] -> DPoint2 -> Primitive vkernlabel rgb attr xs (P2 x y) = PLabel (LabelProps rgb attr) lbl    where     lbl = PrimLabel (KernTextV xs) (makeTranslCTM x y)@@ -623,7 +642,7 @@ -- Construct a regular (i.e. non-special) Char along with its  -- displacement from the left-baseline of the previous Char. ---kernchar :: u -> Char -> KerningChar u+kernchar :: Double -> Char -> KerningChar kernchar u c = (u, CharLiteral c)  @@ -632,7 +651,7 @@ -- Construct a Char by its character code along with its  -- displacement from the left-baseline of the previous Char. ---kernEscInt :: u -> Int -> KerningChar u+kernEscInt :: Double -> Int -> KerningChar kernEscInt u i = (u, CharEscInt i)  @@ -641,7 +660,7 @@ -- Construct a Char by its character name along with its  -- displacement from the left-baseline of the previous Char. ---kernEscName :: u -> String -> KerningChar u+kernEscName :: Double -> String -> KerningChar kernEscName u s = (u, CharEscName s)  --------------------------------------------------------------------------------@@ -666,8 +685,7 @@ -- -- Avoid non-uniform scaling stroked ellipses! ---strokeEllipse :: Num u -             => RGBi -> StrokeAttr -> u -> u -> Point2 u -> Primitive u+strokeEllipse :: RGBi -> StrokeAttr -> Double -> Double -> DPoint2 -> Primitive strokeEllipse rgb sa hw hh pt = rstrokeEllipse rgb sa hw hh 0 pt  @@ -677,31 +695,27 @@ -- Create a stroked primitive ellipse rotated about the center by  -- /theta/. ---rstrokeEllipse :: Num u -               => RGBi -> StrokeAttr -> u -> u -> Radian -> Point2 u-               -> Primitive u+rstrokeEllipse :: RGBi -> StrokeAttr -> Double -> Double -> Radian -> DPoint2+               -> Primitive rstrokeEllipse rgb sa rx ry theta pt =      PEllipse (EStroke sa rgb) (mkPrimEllipse rx ry theta pt)   --- | 'fillEllipse' : @ rgb * stroke_attr * rx * ry * center -> Primtive @+-- | 'fillEllipse' : @ rgb * rx * ry * center -> Primtive @ -- -- Create a filled primitive ellipse. ---fillEllipse :: Num u -             => RGBi -> u -> u -> Point2 u -> Primitive u+fillEllipse :: RGBi -> Double -> Double -> DPoint2 -> Primitive fillEllipse rgb rx ry pt = rfillEllipse rgb rx ry 0 pt   --- | 'rfillEllipse' : @ colour * stroke_attr * rx * ry * theta * center ---        -> Primitive @+-- | 'rfillEllipse' : @ rgb * rx * ry * theta * center -> Primitive @ -- -- Create a filled primitive ellipse rotated about the center by  -- /theta/. ---rfillEllipse :: Num u -             => RGBi -> u -> u -> Radian -> Point2 u -> Primitive u+rfillEllipse :: RGBi -> Double -> Double -> Radian -> DPoint2 -> Primitive rfillEllipse rgb rx ry theta pt =      PEllipse (EFill rgb) (mkPrimEllipse rx ry theta pt) @@ -710,7 +724,7 @@ -- -- Create a black, filled ellipse.  ---zellipse :: Num u => u -> u -> Point2 u -> Primitive u+zellipse :: Double -> Double -> DPoint2 -> Primitive zellipse hw hh pt = rfillEllipse black hw hh 0 pt  @@ -719,9 +733,9 @@ -- -- Create a bordered (i.e. filled and stroked) primitive ellipse. ---fillStrokeEllipse :: Num u -                  => RGBi -> StrokeAttr -> RGBi -> u -> u -> Point2 u -                  -> Primitive u+fillStrokeEllipse :: RGBi -> StrokeAttr -> RGBi +                  -> Double -> Double -> DPoint2+                  -> Primitive fillStrokeEllipse frgb sa srgb rx ry pt =      rfillStrokeEllipse frgb sa srgb rx ry 0 pt     @@ -733,14 +747,14 @@ -- Create a bordered (i.e. filled and stroked) ellipse rotated  -- about the center by /theta/. ---rfillStrokeEllipse :: Num u -                   => RGBi -> StrokeAttr -> RGBi -> u -> u -> Radian -> Point2 u-                   -> Primitive u+rfillStrokeEllipse :: RGBi -> StrokeAttr -> RGBi +                   -> Double -> Double -> Radian -> DPoint2+                   -> Primitive rfillStrokeEllipse frgb sa srgb rx ry theta pt =      PEllipse (EFillStroke frgb sa srgb) (mkPrimEllipse rx ry theta pt)  -mkPrimEllipse :: Num u => u -> u -> Radian -> Point2 u -> PrimEllipse u+mkPrimEllipse :: Double -> Double -> Radian -> DPoint2 -> PrimEllipse mkPrimEllipse rx ry theta (P2 dx dy) =      PrimEllipse rx ry (makeThetaCTM dx dy theta) @@ -755,8 +769,9 @@ -- both vertical directions by @y@. @x@ and @y@ must be positive -- This function cannot be used to shrink a boundary. ---extendBoundary :: (Num u, Ord u) => u -> u -> Picture u -> Picture u-extendBoundary x y = mapLocale (\(bb,xs) -> (extBB (posve x) (posve y) bb, xs)) +extendBoundary :: Double -> Double -> Picture -> Picture+extendBoundary x y = +    mapLocale (\(bb,xs) -> (extBB (posve x) (posve y) bb, xs))    where     extBB x' y' (BBox (P2 x0 y0) (P2 x1 y1)) = BBox pt1 pt2 where          pt1 = P2 (x0-x') (y0-y')@@ -775,7 +790,7 @@ -- Draw the first picture on top of the second picture -  -- neither picture will be moved. ---picOver :: (Num u, Ord u) => Picture u -> Picture u -> Picture u+picOver :: Picture -> Picture -> Picture a `picOver` b = Picture (bb,[]) (join (one b) (one a))      where     bb = boundary a `boundaryUnion` boundary b@@ -788,15 +803,15 @@ --  --  Move a picture by the supplied vector.  ---picMoveBy :: (Num u, Ord u) => Picture u -> Vec2 u -> Picture u-p `picMoveBy` (V2 dx dy) = translate dx dy p +picMoveBy :: Picture -> DVec2 -> Picture+p `picMoveBy` (V2 x y) = translate x y p   -- | 'picBeside' : @ picture * picture -> Picture @ -- -- Move the second picture to sit at the right side of the -- first picture ---picBeside :: (Num u, Ord u) => Picture u -> Picture u -> Picture u+picBeside :: Picture -> Picture -> Picture a `picBeside` b = a `picOver` (b `picMoveBy` v)    where      (P2 x1 _) = ur_corner $ boundary a@@ -808,7 +823,7 @@  -- | Print the syntax tree of a Picture to the console. ---printPicture :: (Num u, PSUnit u) => Picture u -> IO ()+printPicture :: Picture -> IO () printPicture pic = putStrLn (show $ format pic) >> putStrLn []  @@ -817,9 +832,9 @@ -- Draw the picture on top of an image of its bounding box. -- The bounding box image will be drawn in the supplied colour. ---illustrateBounds :: (Real u, Floating u, FromPtSize u) -                 => RGBi -> Picture u -> Picture u-illustrateBounds rgb p = p `picOver` (frame $ boundsPrims rgb p $ []) +illustrateBounds :: RGBi -> Picture -> Picture+illustrateBounds rgb p =+    p `picOver` (frame $ boundsPrims rgb (boundary p) $ [])    -- | 'illustrateBoundsPrim' : @ bbox_rgb * primitive -> Picture @@@ -829,23 +844,22 @@ -- -- The result will be lifted from Primitive to Picture. -- -illustrateBoundsPrim :: (Real u, Floating u, FromPtSize u) -                     => RGBi -> Primitive u -> Picture u-illustrateBoundsPrim rgb p = frame $ boundsPrims rgb p $ [p]+illustrateBoundsPrim :: RGBi -> Primitive -> Picture+illustrateBoundsPrim rgb p = +    frame $ boundsPrims rgb (boundary p) $ [p]    -- | Draw a the rectangle of a bounding box, plus cross lines -- joining the corners. ---boundsPrims :: (Num u, Ord u, Boundary t, u ~ DUnit t) -            => RGBi -> t -> H (Primitive u)-boundsPrims rgb a = fromListH $ [ bbox_rect, bl_to_tr, br_to_tl ]+boundsPrims :: RGBi -> BoundingBox Double -> H Primitive+boundsPrims rgb bb = fromListH $ [ bbox_rect, bl_to_tr, br_to_tl ]   where-    (bl,br,tr,tl) = boundaryCorners $ boundary a-    bbox_rect     = cstroke rgb line_attr $ vertexPath [bl,br,tr,tl]-    bl_to_tr      = ostroke rgb line_attr $ vertexPath [bl,tr]-    br_to_tl      = ostroke rgb line_attr $ vertexPath [br,tl]+    (bl,br,tr,tl) = boundaryCorners bb+    bbox_rect     = cstroke rgb line_attr $ vertexPrimPath [bl,br,tr,tl]+    bl_to_tr      = ostroke rgb line_attr $ vertexPrimPath [bl,tr]+    br_to_tl      = ostroke rgb line_attr $ vertexPrimPath [br,tl]      line_attr     = default_stroke_attr { line_cap     = CapRound                                         , dash_pattern = Dash 0 [(1,2)] }@@ -859,15 +873,14 @@ -- This has no effect on TextLabels. Nor does it draw Beziers of  -- a hyperlinked object. -- -illustrateControlPoints :: (Real u, Floating u, FromPtSize u)-                        => RGBi -> Primitive u -> Picture u+illustrateControlPoints :: RGBi -> Primitive -> Picture illustrateControlPoints rgb elt = frame $ fn elt   where     fn (PPath    _ p) = pathCtrlLines rgb p $ [elt]     fn a              = [a]  --- Genrate lines illustrating the control points of curves on +-- | Generate lines illustrating the control points of curves on  -- a Path. -- -- Two lines are generated for a Bezier curve:@@ -875,8 +888,9 @@ -- -- Nothing is generated for a straight line. ---pathCtrlLines :: (Num u, Ord u) => RGBi -> PrimPath u -> H (Primitive u)-pathCtrlLines rgb (PrimPath start ss) = step start ss+pathCtrlLines :: RGBi -> PrimPath -> H Primitive+pathCtrlLines rgb ppath = +    let (start,ss) = extractRelPath ppath in step start ss   where      step s (RelLineTo v:xs)         = step (s .+^ v) xs @@ -887,6 +901,8 @@      step _ []                       = emptyH -    mkLine s v                      = let pp = (PrimPath s [RelLineTo v]) +    mkLine s v                      = let seg1 = absLineTo $ s .+^ v+                                          pp   = absPrimPath s [seg1]                                        in ostroke rgb default_stroke_attr pp + 
src/Wumpus/Core/PictureInternal.hs view
@@ -1,14 +1,15 @@ {-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE MultiParamTypeClasses      #-} {-# OPTIONS -Wall #-}  -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Core.PictureInternal--- Copyright   :  (c) Stephen Tetley 2009-2010+-- Copyright   :  (c) Stephen Tetley 2009-2011 -- License     :  BSD3 ----- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>--- Stability   :  highly unstable+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable -- Portability :  GHC -- -- Internal representation of Pictures.@@ -20,39 +21,31 @@   (       Picture(..)-  , DPicture   , Locale   , FontCtx(..)    , Primitive(..)-  , DPrimitive   , SvgAnno(..)   , XLink(..)   , SvgAttr(..)    , PrimPath(..)-  , DPrimPath   , PrimPathSegment(..)-  , DPrimPathSegment   , AbsPathSegment(..)-  , DAbsPathSegment   , PrimLabel(..)-  , DPrimLabel   , LabelBody(..)-  , DLabelBody   , KerningChar-  , DKerningChar     , PrimEllipse(..)    , GraphicsState(..) -  , pathBoundary   , mapLocale    -- * Additional operations   , concatTrafos   , deconsMatrix   , repositionDeltas+  , extractRelPath    , zeroGS   , isEmptyPath@@ -66,10 +59,8 @@ import Wumpus.Core.FontSize import Wumpus.Core.Geometry import Wumpus.Core.GraphicProps-import Wumpus.Core.PtSize import Wumpus.Core.Text.Base import Wumpus.Core.TrafoInternal-import Wumpus.Core.Utils.Common import Wumpus.Core.Utils.FormatCombinators import Wumpus.Core.Utils.JoinList @@ -80,49 +71,29 @@ import qualified Data.IntMap                    as IntMap  --- | Picture is a leaf attributed tree - where attributes are --- colour, line-width etc. It is parametric on the unit type --- of points (typically Double).--- --- Wumpus\'s leaf attributed tree, is not directly matched to --- PostScript\'s picture representation, which might be --- considered a node attributed tree (if you consider graphics--- state changes less imperatively - setting attributes rather --- than global state change).------ Considered as a node-attributed tree PostScript precolates --- graphics state updates downwards in the tree (vis-a-vis --- inherited attributes in an attibute grammar), where a --- graphics state change deeper in the tree overrides a higher --- one.+-- | Picture is a rose tree. Leaves themselves are attributed+-- with colour, line-width etc. The /unit/ of a Picture is +-- fixed to Double representing PostScript\'s /Point/ unit. +-- Output is always gewnerated with PostScript points - other+-- units are converted to PostScript points before building the +-- Picture. -- --- Wumpus on the other hand, simply labels each leaf with its--- drawing attributes - there is no attribute inheritance.--- When it draws the PostScript picture it does some --- optimization to avoid generating excessive graphics state --- changes in the PostScript code.+-- By attributing leaves with their drawing properties, Wumpus\'s +-- picture representaion is not directly matched to PostScript.+-- PostScript has a global graphics state (that allows local +-- modifaction) from where drawing properties are inherited.+-- Wumpus has no attribute inheritance. ----- Omitting some details, Picture is a simple non-empty --- leaf-labelled rose tree via:+-- Omitting some details of the list representation, Picture is a +-- simple non-empty rose tree via: --  -- > tree = Leaf [primitive] | Picture [tree] ----- The additional constructors are convenience:------ @Clip@ nests a picture (tree) inside a clipping path.------ The @Group@ constructor allows local shared graphics state --- updates for the SVG renderer - in some instances this can --- improve the code size of the generated SVG.----data Picture u = Leaf     (Locale u)              (JoinList (Primitive u))-               | Picture  (Locale u)              (JoinList (Picture u))-               | Clip     (Locale u) (PrimPath u) (Picture u)+data Picture = Leaf     Locale  (JoinList Primitive)+             | Picture  Locale  (JoinList Picture)   deriving (Show) -type DPicture = Picture Double--+type instance DUnit Picture = Double  -- | Locale = (bounding box * current translation matrix) -- @@ -141,7 +112,7 @@ -- transformation, the corners of bounding boxes are transformed -- pointwise when the picture is scaled, rotated etc. ---type Locale u = (BoundingBox u, [AffineTrafo u])+type Locale = (BoundingBox Double, [AffineTrafo])   @@ -168,6 +139,9 @@ -- Though typically for affine transformations a Fractional  -- constraint is also obliged. --+-- Clipping is represented by a pair of the clipping path and+-- the primitive embedded within the path.+-- -- To represent XLink hyperlinks, Primitives can be annotated  -- with some a hyperlink (likewise a /passive/ font change for  -- better SVG code generation) and grouped - a hyperlinked arrow @@ -177,16 +151,16 @@ -- This means that Primitives aren\'t strictly /primitive/ as  -- the actual implementation is a tree. -- -data Primitive u = PPath    PathProps         (PrimPath u)-                 | PLabel   LabelProps        (PrimLabel u)-                 | PEllipse EllipseProps      (PrimEllipse u)-                 | PContext FontCtx           (Primitive u)-                 | PSVG     SvgAnno           (Primitive u)-                 | PGroup   (JoinList (Primitive u))+data Primitive = PPath    PathProps         PrimPath+               | PLabel   LabelProps        PrimLabel+               | PEllipse EllipseProps      PrimEllipse+               | PContext FontCtx           Primitive+               | PSVG     SvgAnno           Primitive+               | PGroup   (JoinList Primitive)+               | PClip    PrimPath          Primitive   deriving (Eq,Show) --type DPrimitive = Primitive Double+type instance DUnit Primitive = Double   -- | Set the font /delta/ for SVG rendering. @@ -235,52 +209,52 @@       }   deriving (Eq,Show) --- | PrimPath - start point and a list of path segments.+-- | PrimPath - a list of path segments and a CTM.+-- +-- Start point is the dx - dy of the CTM. ---data PrimPath u = PrimPath (Point2 u) [PrimPathSegment u]+data PrimPath = PrimPath [PrimPathSegment] PrimCTM   deriving (Eq,Show) -type DPrimPath = PrimPath Double+type instance DUnit PrimPath = Double + -- | PrimPathSegment - either a relative cubic Bezier /curve-to/  -- or a relative /line-to/. ---data PrimPathSegment u = RelCurveTo  (Vec2 u) (Vec2 u) (Vec2 u)-                       | RelLineTo   (Vec2 u)+data PrimPathSegment = RelCurveTo  DVec2 DVec2 DVec2+                     | RelLineTo   DVec2   deriving (Eq,Show) -type DPrimPathSegment = PrimPathSegment Double---- Design note - if paths were represented as:---   start-point plus [relative-path-segment]--- They would be cheaper to move...---+type instance DUnit PrimPathSegment = Double   -- | AbsPathSegment - either a cubic Bezier curve or a line. --  -- Note this data type is transitory - it is only used as a --- convenience to build relative paths. +-- convenience to build relative paths. Hence the unit type is +-- parametric. ---data AbsPathSegment u = AbsCurveTo  (Point2 u) (Point2 u) (Point2 u)-                      | AbsLineTo   (Point2 u)+data AbsPathSegment = AbsCurveTo  DPoint2 DPoint2 DPoint2+                    | AbsLineTo   DPoint2    deriving (Eq,Show) -type DAbsPathSegment = AbsPathSegment Double +type instance DUnit AbsPathSegment = Double   -- | Label - represented by baseline-left point and text. -- -- Baseline-left is the dx * dy of the PrimCTM. ---data PrimLabel u = PrimLabel -      { label_body          :: LabelBody u-      , label_ctm           :: PrimCTM u+--+data PrimLabel = PrimLabel +      { label_body      :: LabelBody+      , label_ctm       :: PrimCTM       }   deriving (Eq,Show) -type DPrimLabel = PrimLabel Double+type instance DUnit PrimLabel = Double   -- | Label can be draw with 3 layouts.@@ -295,33 +269,40 @@ -- Kerned vertical layout - each character is encoded with the -- upwards distance from the last charcaters left base-line. -- -data LabelBody u = StdLayout EscapedText-                 | KernTextH [KerningChar u]-                 | KernTextV [KerningChar u]+data LabelBody = StdLayout EscapedText+               | KernTextH [KerningChar]+               | KernTextV [KerningChar]   deriving (Eq,Show) -type DLabelBody = LabelBody Double+type instance DUnit LabelBody = Double  --- | A Char (possibly escaped) paired with is displacement from +-- | A Char (possibly escaped) paired with its displacement from  -- the previous KerningChar. ---type KerningChar u = (u,EscapedChar) +type KerningChar = (Double,EscapedChar)  -type DKerningChar = KerningChar Double  -- | Ellipse represented by center and half_width * half_height. -- -- Center is the dx * dy of the PrimCTM. ---data PrimEllipse u = PrimEllipse -      { ellipse_half_width    :: u-      , ellipse_half_height   :: u -      , ellipse_ctm           :: PrimCTM u+data PrimEllipse = PrimEllipse +      { ellipse_half_width    :: !Double+      , ellipse_half_height   :: !Double+      , ellipse_ctm           :: PrimCTM       }    deriving (Eq,Show) +type instance DUnit PrimEllipse = Double +--+-- Design note - the CTM unit type is fixed to Double (PS point) +-- rather than parametric on unit.+--+-- For the rationale see the PrimLabel design note.+-- +   -------------------------------------------------------------------------------- -- Graphics state datatypes@@ -340,19 +321,11 @@   ----------------------------------------------------------------------------------- family instances--type instance DUnit (Picture u)     = u-type instance DUnit (Primitive u)   = u-type instance DUnit (PrimEllipse u) = u-type instance DUnit (PrimLabel u)   = u-type instance DUnit (PrimPath u)    = u---------------------------------------------------------------------------------- -- instances +-- format -instance (Num u, PSUnit u) => Format (Picture u) where+instance Format Picture where   format (Leaf m prims)     = indent 2 $ vcat [ text "** Leaf-pic **"                                               , fmtLocale m                                                , fmtPrimlist prims ]@@ -361,23 +334,18 @@                                               , fmtLocale m                                               , fmtPics pics ]  -  format (Clip m path pic)  = indent 2 $ vcat [ text "** Clip-path **"-                                              , fmtLocale m-                                              , format path-                                              , format pic  ] --fmtPics :: PSUnit u => JoinList (Picture u) -> Doc+fmtPics :: JoinList Picture -> Doc fmtPics ones = snd $ F.foldl' fn (0,empty) ones   where     fn (n,acc) e = (n+1, vcat [ acc, text "-- " <+> int n, format e, line])  -fmtLocale :: (Num u, PSUnit u) => Locale u -> Doc+fmtLocale :: Locale -> Doc fmtLocale (bb,_) = format bb  -instance PSUnit u => Format (Primitive u) where+instance Format Primitive where   format (PPath props p)    =        indent 2 $ vcat [ text "path:" <+> format props, format p ] @@ -396,39 +364,42 @@   format (PGroup ones)      =        vcat [ text "-- group ", fmtPrimlist ones  ] +  format (PClip path pic)  = +      vcat [ text "-- clip-path ", format path, format pic  ] -fmtPrimlist :: PSUnit u => JoinList (Primitive u) -> Doc+++fmtPrimlist :: JoinList Primitive -> Doc fmtPrimlist ones = snd $ F.foldl' fn (0,empty) ones   where     fn (n,acc) e = (n+1, vcat [ acc, text "-- leaf" <+> int n, format e, line])  -instance PSUnit u => Format (PrimPath u) where-   format (PrimPath pt ps) = vcat (start : map format ps)-      where-        start = text "start_point " <> format pt+instance Format PrimPath where+   format (PrimPath vs ctm) = vcat [ hcat $ map format vs+                                   , text "ctm=" <> format ctm ] -instance PSUnit u => Format (PrimPathSegment u) where+instance Format PrimPathSegment where   format (RelCurveTo p1 p2 p3)  =     text "rel_curve_to " <> format p1 <+> format p2 <+> format p3    format (RelLineTo pt)         = text "rel_line_to  " <> format pt -instance PSUnit u => Format (PrimLabel u) where+instance Format PrimLabel where   format (PrimLabel s ctm) =       vcat [ dquotes (format s)           , text "ctm="           <> format ctm           ] -instance PSUnit u => Format (LabelBody u) where+instance Format LabelBody where   format (StdLayout enctext) = format enctext   format (KernTextH xs)      = text "(KernH)" <+> hcat (map (format .snd) xs)   format (KernTextV xs)      = text "(KernV)" <+> hcat (map (format .snd) xs)  -instance PSUnit u => Format (PrimEllipse u) where-  format (PrimEllipse hw hh ctm) =  text "hw="       <> dtruncFmt hw-                                <+> text "hh="       <> dtruncFmt hh+instance Format PrimEllipse where+  format (PrimEllipse hw hh ctm) =  text "hw="       <> format hw+                                <+> text "hh="       <> format hh                                 <+> text "ctm="      <> format ctm    @@ -438,32 +409,44 @@  -------------------------------------------------------------------------------- -instance Boundary (Picture u) where-  boundary (Leaf    (bb,_) _)   = bb-  boundary (Picture (bb,_) _)   = bb-  boundary (Clip    (bb,_) _ _) = bb+instance Boundary Picture where+  boundary = boundaryPicture +boundaryPicture :: Picture -> BoundingBox Double+boundaryPicture (Leaf    (bb,_) _)   = bb+boundaryPicture (Picture (bb,_) _)   = bb -instance (Real u, Floating u, FromPtSize u) => Boundary (Primitive u) where-  boundary (PPath _ p)      = pathBoundary p-  boundary (PLabel a l)     = labelBoundary (label_font a) l-  boundary (PEllipse _ e)   = ellipseBoundary e-  boundary (PContext _ a)   = boundary a-  boundary (PSVG _ a)       = boundary a-  boundary (PGroup ones)    = outer $ viewl ones -    where-      outer (OneL a)     = boundary a-      outer (a :< as)    = inner (boundary a) (viewl as) -      inner bb (OneL a)  = bb `boundaryUnion` boundary a-      inner bb (a :< as) = inner (bb `boundaryUnion` boundary a) (viewl as)+instance Boundary Primitive where+  boundary = boundaryPrimitive +boundaryPrimitive :: Primitive -> BoundingBox Double+boundaryPrimitive (PPath _ p)      = boundaryPrimPath p+boundaryPrimitive (PLabel a l)     = labelBoundary (label_font a) l+boundaryPrimitive (PEllipse _ e)   = ellipseBoundary e+boundaryPrimitive (PContext _ a)   = boundaryPrimitive a+boundaryPrimitive (PSVG _ a)       = boundaryPrimitive a+boundaryPrimitive (PClip p _)      = boundaryPrimPath p+boundaryPrimitive (PGroup ones)    = outer $ viewl ones +  where+    outer (OneL a)     = boundaryPrimitive a+    outer (a :< as)    = inner (boundaryPrimitive a) (viewl as) +    inner bb (OneL a)  = bb `boundaryUnion` boundaryPrimitive a+    inner bb (a :< as) = inner (bb `boundaryUnion` boundaryPrimitive a) +                               (viewl as)  -pathBoundary :: (Num u, Ord u) => PrimPath u -> BoundingBox u-pathBoundary (PrimPath st xs) = step st (st,st) xs+instance Boundary PrimPath where+  boundary = boundaryPrimPath+++boundaryPrimPath :: PrimPath -> BoundingBox Double+boundaryPrimPath (PrimPath vs ctm) = +    retraceBoundary (m33 *#) $ step zeroPt (zeroPt,zeroPt) vs   where+    m33         = matrixRepCTM ctm+     step _  (lo,hi) []                         = BBox lo hi       step pt (lo,hi) (RelLineTo v1:rest)        = @@ -490,23 +473,20 @@    -labelBoundary :: (Floating u, Real u, FromPtSize u) -              => FontAttr -> PrimLabel u -> BoundingBox u+labelBoundary :: FontAttr -> PrimLabel -> BoundingBox Double labelBoundary attr (PrimLabel body ctm) =      retraceBoundary (m33 *#) untraf_bbox   where     m33         = matrixRepCTM ctm     untraf_bbox = labelBodyBoundary (font_size attr) body -labelBodyBoundary :: (Num u, Ord u, FromPtSize u) -                  => FontSize -> LabelBody u -> BoundingBox u+labelBodyBoundary :: FontSize -> LabelBody -> BoundingBox Double labelBodyBoundary sz (StdLayout etxt) = stdLayoutBB sz etxt labelBodyBoundary sz (KernTextH xs)   = hKerningBB sz xs labelBodyBoundary sz (KernTextV xs)   = vKerningBB sz xs  -stdLayoutBB :: (Num u, Ord u, FromPtSize u) -            => FontSize -> EscapedText -> BoundingBox u+stdLayoutBB :: FontSize -> EscapedText -> BoundingBox Double stdLayoutBB sz etxt = textBoundsEsc sz zeroPt etxt  @@ -518,8 +498,7 @@ -- then expands the right edge with the sum of the (rightwards) -- displacements. -- -hKerningBB :: (Num u, Ord u, FromPtSize u) -           => FontSize -> [(u,EscapedChar)] -> BoundingBox u+hKerningBB :: FontSize -> [(Double,EscapedChar)] -> BoundingBox Double hKerningBB sz xs = rightGrow (sumDiffs xs) $ textBounds sz zeroPt "A"   where     sumDiffs                          = foldr (\(u,_) i -> i+u)  0@@ -535,8 +514,7 @@ --  -- Also note, that the Label /grows/ downwards... ---vKerningBB :: (Num u, Ord u, FromPtSize u) -           => FontSize -> [(u,EscapedChar)] -> BoundingBox u+vKerningBB :: FontSize -> [(Double,EscapedChar)] -> BoundingBox Double vKerningBB sz xs = downGrow (sumDiffs xs) $ textBounds sz zeroPt "A"   where     sumDiffs                                = foldr (\(u,_) i -> i+u)  0@@ -546,7 +524,7 @@ -- | Ellipse bbox is the bounding rectangle, rotated as necessary  -- then retraced. ---ellipseBoundary :: (Real u, Floating u) => PrimEllipse u -> BoundingBox u+ellipseBoundary :: PrimEllipse -> BoundingBox Double ellipseBoundary (PrimEllipse hw hh ctm) =      traceBoundary $ map (m33 *#) [sw,se,ne,nw]   where@@ -566,32 +544,36 @@ -- update (frame change). -- -instance (Num u, Ord u) => Transform (Picture u) where+instance Transform Picture where   transform mtrx = -    mapLocale $ \(bb,xs) -> (transform mtrx bb, Matrix mtrx:xs)+    mapLocale $ \(bb,xs) -> let cmd = Matrix mtrx+                            in (transform mtrx bb, cmd : xs) -instance (Real u, Floating u) => Rotate (Picture u) where+instance Rotate Picture where   rotate theta =      mapLocale $ \(bb,xs) -> (rotate theta bb, Rotate theta:xs)  -instance (Real u, Floating u) => RotateAbout (Picture u) where+instance RotateAbout Picture where   rotateAbout theta pt = -    mapLocale $ \(bb,xs) -> (rotateAbout theta pt bb, RotAbout theta pt:xs)+    mapLocale $ \(bb,xs) -> let cmd = RotAbout theta pt+                            in (rotateAbout theta pt bb, cmd : xs) -instance (Num u, Ord u) => Scale (Picture u) where+instance Scale Picture where   scale sx sy = -    mapLocale $ \(bb,xs) -> (scale sx sy bb, Scale sx sy : xs)+    mapLocale $ \(bb,xs) -> let cmd = Scale sx sy+                            in (scale sx sy bb, cmd : xs) -instance (Num u, Ord u) => Translate (Picture u) where+instance Translate Picture where   translate dx dy = -    mapLocale $ \(bb,xs) -> (translate dx dy bb, Translate dx dy:xs)+    mapLocale $ \(bb,xs) -> let cmd = Translate dx dy+                            in (translate dx dy bb, cmd : xs)+                       -mapLocale :: (Locale u -> Locale u) -> Picture u -> Picture u+mapLocale :: (Locale -> Locale) -> Picture -> Picture mapLocale f (Leaf lc ones)     = Leaf (f lc) ones mapLocale f (Picture lc ones)  = Picture (f lc) ones-mapLocale f (Clip lc pp pic)   = Clip (f lc) pp pic   --------------------------------------------------------------------------------@@ -603,73 +585,98 @@ -- (ShapeCTM is not a real matrix). --  -instance (Real u, Floating u) => Rotate (Primitive u) where+instance Rotate Primitive where   rotate r (PPath a path)   = PPath a    $ rotatePath r path   rotate r (PLabel a lbl)   = PLabel a   $ rotateLabel r lbl   rotate r (PEllipse a ell) = PEllipse a $ rotateEllipse r ell   rotate r (PContext a chi) = PContext a $ rotate r chi    rotate r (PSVG a chi)     = PSVG a     $ rotate r chi    rotate r (PGroup xs)      = PGroup     $ fmap (rotate r) xs- +  rotate r (PClip p chi)    = PClip (rotatePath r p) (rotate r chi) -instance (Real u, Floating u) => RotateAbout (Primitive u) where-  rotateAbout r pt (PPath a path)   = PPath a    $ rotateAboutPath r pt path-  rotateAbout r pt (PLabel a lbl)   = PLabel a   $ rotateAboutLabel r pt lbl-  rotateAbout r pt (PEllipse a ell) = PEllipse a $ rotateAboutEllipse r pt ell-  rotateAbout r pt (PContext a chi) = PContext a $ rotateAbout r pt chi-  rotateAbout r pt (PSVG a chi)     = PSVG a     $ rotateAbout r pt chi-  rotateAbout r pt (PGroup xs)      = PGroup     $ fmap (rotateAbout r pt) xs+instance RotateAbout Primitive where+  rotateAbout ang p0 (PPath a path)   = +      PPath a    $ rotateAboutPath ang p0 path +  rotateAbout ang  p0 (PLabel a lbl)   = +      PLabel a   $ rotateAboutLabel ang p0 lbl -instance Num u => Scale (Primitive u) where+  rotateAbout ang p0 (PEllipse a ell) = +      PEllipse a $ rotateAboutEllipse ang p0 ell++  rotateAbout ang p0 (PContext a chi) = +      PContext a $ rotateAbout ang p0 chi++  rotateAbout ang p0 (PSVG a chi)     = +      PSVG a     $ rotateAbout ang p0 chi++  rotateAbout ang p0 (PGroup xs)      = +      PGroup     $ fmap (rotateAbout ang p0) xs++  rotateAbout ang p0 (PClip p chi)    = +      PClip (rotateAboutPath ang p0 p) (rotateAbout ang p0 chi)+++instance Scale Primitive where   scale sx sy (PPath a path)    = PPath a    $ scalePath sx sy path   scale sx sy (PLabel a lbl)    = PLabel a   $ scaleLabel sx sy lbl   scale sx sy (PEllipse a ell)  = PEllipse a $ scaleEllipse sx sy ell   scale sx sy (PContext a chi)  = PContext a $ scale sx sy chi   scale sx sy (PSVG a chi)      = PSVG a     $ scale sx sy chi   scale sx sy (PGroup xs)       = PGroup     $ fmap (scale sx sy) xs+  scale sx sy (PClip p chi)     = PClip (scalePath sx sy p) (scale sx sy chi)  -instance Num u => Translate (Primitive u) where-  translate dx dy (PPath a path)   = PPath a    $ translatePath dx dy path-  translate dx dy (PLabel a lbl)   = PLabel a   $ translateLabel dx dy lbl-  translate dx dy (PEllipse a ell) = PEllipse a $ translateEllipse dx dy ell-  translate dx dy (PContext a chi) = PContext a $ translate dx dy chi-  translate dx dy (PSVG a chi)     = PSVG a     $ translate dx dy chi-  translate dx dy (PGroup xs)      = PGroup     $ fmap (translate dx dy) xs+instance Translate Primitive where+  translate dx dy (PPath a path)   = +      PPath a    $ translatePath dx dy path +  translate dx dy (PLabel a lbl)   = +      PLabel a   $ translateLabel dx dy lbl +  translate dx dy (PEllipse a ell) = +      PEllipse a $ translateEllipse dx dy ell++  translate dx dy (PContext a chi) = +      PContext a $ translate dx dy chi++  translate dx dy (PSVG a chi)     = +      PSVG a     $ translate dx dy chi++  translate dx dy (PGroup xs)      = +      PGroup     $ fmap (translate dx dy) xs++  translate dx dy (PClip p chi)    = +      PClip (translatePath dx dy p) (translate dx dy chi)++ -------------------------------------------------------------------------------- -- Paths +-- Affine transformations on paths are applied to their control+-- points.  -rotatePath :: (Real u, Floating u) => Radian -> PrimPath u -> PrimPath u-rotatePath ang = mapPath (rotate ang) (rotate ang)+rotatePath :: Radian -> PrimPath -> PrimPath+rotatePath ang (PrimPath vs ctm) = PrimPath vs (rotateCTM ang ctm)  -rotateAboutPath :: (Real u, Floating u) -                => Radian -> Point2 u -> PrimPath u -> PrimPath u-rotateAboutPath ang pt = mapPath (rotateAbout ang pt) (rotateAbout ang pt) +rotateAboutPath :: Radian -> DPoint2 -> PrimPath -> PrimPath+rotateAboutPath ang (P2 x y) (PrimPath vs ctm) = +    PrimPath vs (rotateAboutCTM ang (P2 x y) ctm)  -scalePath :: Num u => u -> u -> PrimPath u -> PrimPath u-scalePath sx sy = mapPath (scale sx sy) (scale sx sy)+scalePath :: Double -> Double -> PrimPath -> PrimPath+scalePath sx sy (PrimPath vs ctm) = PrimPath vs (scaleCTM sx sy ctm) + -- Note - translate only needs change the start point /because/  -- the path represented as a relative path. -- -translatePath :: Num u => u -> u -> PrimPath u -> PrimPath u-translatePath x y (PrimPath st xs) = PrimPath (translate x y st) xs+translatePath :: Double -> Double -> PrimPath -> PrimPath+translatePath dx dy (PrimPath vs ctm) = +    PrimPath vs (translateCTM dx dy ctm)  -mapPath :: (Point2 u -> Point2 u) -> (Vec2 u -> Vec2 u) -        -> PrimPath u -> PrimPath u-mapPath f g (PrimPath st xs) = PrimPath (f st) (map (mapSeg g) xs)--mapSeg :: (Vec2 u -> Vec2 u) -> PrimPathSegment u -> PrimPathSegment u-mapSeg fn (RelLineTo p)         = RelLineTo (fn p)-mapSeg fn (RelCurveTo p1 p2 p3) = RelCurveTo (fn p1) (fn p2) (fn p3)- -------------------------------------------------------------------------------- -- Labels @@ -678,26 +685,25 @@ -- Rotate the baseline-left start point _AND_ the CTM of the  -- label. ---rotateLabel :: (Real u, Floating u) -            => Radian -> PrimLabel u -> PrimLabel u+rotateLabel :: Radian -> PrimLabel -> PrimLabel rotateLabel ang (PrimLabel txt ctm) = PrimLabel txt (rotateCTM ang ctm)   -- /rotateAbout/ the start-point, /rotate/ the the CTM. ---rotateAboutLabel :: (Real u, Floating u) -                 => Radian -> Point2 u -> PrimLabel u -> PrimLabel u-rotateAboutLabel ang pt (PrimLabel txt ctm) = -    PrimLabel txt (rotateAboutCTM ang pt ctm)+rotateAboutLabel :: Radian -> DPoint2 -> PrimLabel -> PrimLabel+rotateAboutLabel ang (P2 x y) (PrimLabel txt ctm) = +    PrimLabel txt (rotateAboutCTM ang (P2 x y) ctm)  -scaleLabel :: Num u => u -> u -> PrimLabel u -> PrimLabel u-scaleLabel sx sy (PrimLabel txt ctm) = PrimLabel txt (scaleCTM sx sy ctm)+scaleLabel :: Double -> Double -> PrimLabel -> PrimLabel+scaleLabel sx sy (PrimLabel txt ctm) = +    PrimLabel txt (scaleCTM sx sy ctm)   -- Change the bottom-left corner. ---translateLabel :: Num u => u -> u -> PrimLabel u -> PrimLabel u+translateLabel :: Double -> Double -> PrimLabel -> PrimLabel translateLabel dx dy (PrimLabel txt ctm) =      PrimLabel txt (translateCTM dx dy ctm) @@ -705,19 +711,17 @@ -- Ellipse  -rotateEllipse :: (Real u, Floating u) -              => Radian -> PrimEllipse u -> PrimEllipse u+rotateEllipse :: Radian -> PrimEllipse -> PrimEllipse rotateEllipse ang (PrimEllipse hw hh ctm) =      PrimEllipse hw hh (rotateCTM ang ctm)      -rotateAboutEllipse :: (Real u, Floating u) -              => Radian -> Point2 u -> PrimEllipse u -> PrimEllipse u-rotateAboutEllipse ang pt (PrimEllipse hw hh ctm) = -    PrimEllipse hw hh (rotateAboutCTM ang pt ctm)+rotateAboutEllipse :: Radian -> DPoint2 -> PrimEllipse -> PrimEllipse+rotateAboutEllipse ang (P2 x y) (PrimEllipse hw hh ctm) = +    PrimEllipse hw hh (rotateAboutCTM ang (P2 x y) ctm)  -scaleEllipse :: Num u => u -> u -> PrimEllipse u -> PrimEllipse u+scaleEllipse :: Double -> Double -> PrimEllipse -> PrimEllipse scaleEllipse sx sy (PrimEllipse hw hh ctm) =      PrimEllipse hw hh (scaleCTM sx sy ctm)     @@ -725,7 +729,7 @@  -- Change the point ---translateEllipse :: Num u => u -> u -> PrimEllipse u -> PrimEllipse u+translateEllipse :: Double -> Double -> PrimEllipse -> PrimEllipse translateEllipse dx dy (PrimEllipse hw hh ctm) =      PrimEllipse hw hh (translateCTM dx dy ctm) @@ -751,15 +755,15 @@   --- If a picture has coordinates smaller than (P2 4 4) then it --- needs repositioning before it is drawn to PostScript or SVG.+-- If a picture has coordinates smaller than (P2 4 4) especially+-- negative ones then it needs repositioning before it is drawn +-- to PostScript or SVG. --  -- (P2 4 4) gives a 4 pt margin - maybe it sould be (0,0) or  -- user defined. ---repositionDeltas :: (Num u, Ord u) -                 => Picture u -> (BoundingBox u, Maybe (Vec2 u))-repositionDeltas = step . boundary +repositionDeltas :: Picture -> (BoundingBox Double, Maybe DVec2)+repositionDeltas = step . boundaryPicture   where     step bb@(BBox (P2 llx lly) (P2 urx ury))         | llx < 4 || lly < 4  = (BBox ll ur, Just $ V2 x y)@@ -771,12 +775,24 @@         ur = P2 (urx+x) (ury+y)   +extractRelPath :: PrimPath -> (DPoint2, [PrimPathSegment])+extractRelPath (PrimPath ss ctm) = (start, usegs)+  where +    (start,dctm)  = unCTM ctm+    mtrafo        = transform (matrixRepCTM dctm)+    usegs         = map fn ss+    +    fn (RelCurveTo v1 v2 v3) = RelCurveTo (mtrafo v1) (mtrafo v2) (mtrafo v3)+    fn (RelLineTo v1)        = RelLineTo  (mtrafo v1)+++ --------------------------------------------------------------------------------  -- | The initial graphics state. -- -- PostScript has no default font so we always want the first --- /delta/ operation not to find a match and cause a @findfint@+-- /delta/ operation not to find a match and cause a @findfont@ -- command to be generated (PostScript @findfont@ commands are  -- only written in the output on /deltas/ to reduce the  -- output size).@@ -796,12 +812,12 @@  -- | Is the path empty - if so we might want to avoid printing it. ---isEmptyPath :: PrimPath u -> Bool-isEmptyPath (PrimPath _ xs) = null xs+isEmptyPath :: PrimPath -> Bool+isEmptyPath (PrimPath xs _) = null xs  -- | Is the label empty - if so we might want to avoid printing it. ---isEmptyLabel :: PrimLabel u -> Bool+isEmptyLabel :: PrimLabel -> Bool isEmptyLabel (PrimLabel txt _) = body txt    where      body (StdLayout esc) = destrEscapedText null esc
src/Wumpus/Core/PostScriptDoc.hs view
@@ -3,11 +3,11 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Core.PostScriptDoc--- Copyright   :  (c) Stephen Tetley 2009-2010+-- Copyright   :  (c) Stephen Tetley 2009-2011 -- License     :  BSD3 ----- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>--- Stability   :  highly unstable+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable -- Portability :  GHC -- -- PostScript Doc combinators.@@ -117,7 +117,7 @@     ]  -epsHeader :: PSUnit u => BoundingBox u -> ZonedTime -> Doc+epsHeader :: DBoundingBox -> ZonedTime -> Doc epsHeader bb tod = vcat $      [ text "%!PS-Adobe-3.0 EPSF-3.0"     , text "%%BoundingBox:"   <+> upint llx <+> upint lly@@ -126,7 +126,7 @@     , text "%%EndComments"     ]   where-    upint             = text . roundup . toDouble+    upint             = text . roundup     (llx,lly,urx,ury) = destBoundingBox bb   @@ -184,7 +184,7 @@  -- | @ ... setlinewidth @ ---ps_setlinewidth :: PSUnit u => u -> Doc+ps_setlinewidth :: Double -> Doc ps_setlinewidth u = command "setlinewidth" [dtruncFmt u]  -- | @ ... setlinecap @@@ -199,7 +199,7 @@  -- | @ ... setmiterlimit @ ---ps_setmiterlimit :: PSUnit u => u -> Doc+ps_setmiterlimit :: Double -> Doc ps_setmiterlimit u = command "setmiterlimit" [dtruncFmt u]  -- | @ [... ...] ... setdash @@@ -225,7 +225,8 @@ -- coordinate system and matrix operators   -- | @ ... ... translate @-ps_translate :: PSUnit u => (Vec2 u) -> Doc+--+ps_translate :: DVec2 -> Doc ps_translate (V2 dx dy) = command "translate" [dtruncFmt dx, dtruncFmt dy]  @@ -237,7 +238,7 @@  -- | @ [... ... ... ... ... ...] concat @ ---ps_concat :: PSUnit u => Matrix3'3 u -> Doc+ps_concat :: Matrix3'3 Double -> Doc ps_concat mtrx = doc <+> text  "concat"   where      (a,b,c,d,e,f) = deconsMatrix mtrx@@ -260,25 +261,25 @@  -- | @ ... ... moveto @ ---ps_moveto :: PSUnit u => Point2 u -> Doc+ps_moveto :: DPoint2 -> Doc ps_moveto (P2 x y) = command "moveto" [dtruncFmt x, dtruncFmt y]   -- | @ ... ... rmoveto @ ---ps_rmoveto :: PSUnit u => Point2 u -> Doc+ps_rmoveto :: DPoint2 -> Doc ps_rmoveto (P2 x y) = command "rmoveto" [dtruncFmt x, dtruncFmt y]   -- | @ ... ... lineto @ ---ps_lineto :: PSUnit u => Point2 u -> Doc+ps_lineto :: DPoint2 -> Doc ps_lineto (P2 x y) = command "lineto" [dtruncFmt x, dtruncFmt y]   -- | @ ... ... ... ... ... arc @ ---ps_arc :: PSUnit u => Point2 u -> u -> Radian -> Radian -> Doc+ps_arc :: DPoint2 -> Double -> Radian -> Radian -> Doc ps_arc (P2 x y) radius ang1 ang2 =      command "arc" $ [ dtruncFmt x                     , dtruncFmt y@@ -292,7 +293,7 @@  -- | @ ... ... ... ... ... ... curveto @ ---ps_curveto :: PSUnit u => Point2 u -> Point2 u -> Point2 u -> Doc+ps_curveto :: DPoint2 -> DPoint2 -> DPoint2 -> Doc ps_curveto (P2 x1 y1) (P2 x2 y2) (P2 x3 y3) =     command "curveto" $ map dtruncFmt [x1,y1, x2,y2, x3,y3] @@ -377,7 +378,7 @@ -- -- Custom Wumpus proc for filled ellipse. ---ps_wumpus_FELL :: PSUnit u => Point2 u -> u -> u -> Doc+ps_wumpus_FELL :: DPoint2 -> Double -> Double -> Doc ps_wumpus_FELL (P2 x y) rx ry =      command "FELL" $ map dtruncFmt [x, y, rx, ry] @@ -387,7 +388,7 @@ -- -- Custom Wumpus proc for stroked ellipse. ---ps_wumpus_SELL :: PSUnit u => Point2 u -> u -> u -> Doc+ps_wumpus_SELL :: DPoint2 -> Double -> Double -> Doc ps_wumpus_SELL (P2 x y) rx ry =      command "SELL" $ map dtruncFmt [x, y, rx, ry] @@ -397,14 +398,14 @@ -- -- Custom Wumpus proc for filled circle. ---ps_wumpus_FCIRC :: PSUnit u => Point2 u -> u -> Doc+ps_wumpus_FCIRC :: DPoint2 -> Double -> Doc ps_wumpus_FCIRC (P2 x y) r = command "FCIRC" $ map dtruncFmt [x, y, r]  -- | @ X Y R SCIRC  @ -- -- Custom Wumpus proc for stroked circle. ---ps_wumpus_SCIRC :: PSUnit u => Point2 u -> u -> Doc+ps_wumpus_SCIRC :: DPoint2 -> Double -> Doc ps_wumpus_SCIRC (P2 x y) r = command "SCIRC" $ map dtruncFmt [x, y, r]  -- | @ SZ NAME FL  @
− src/Wumpus/Core/PtSize.hs
@@ -1,61 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module      :  Wumpus.Core.PtSize--- Copyright   :  (c) Stephen Tetley 2010--- License     :  BSD3------ Maintainer  :  stephen.tetley@gmail.com--- Stability   :  unstable--- Portability :  GHC------ Numeric type representing Point size (1/72 inch) which is --- PostScript and Wumpus-Core\'s internal unit size.------ Other unit types (e.g. centimeter) should define an --- appropriate instance of FromPtSize.--- -----------------------------------------------------------------------------------module Wumpus.Core.PtSize-  ( -  -  -- * Point size type-    PtSize-  -  -- * Extract (unscaled) PtSize as a Double -  , ptSize--  -- * Conversion class-  , FromPtSize(..)--  ) where----- | Wrapped Double representing /Point size/ for font metrics --- etc.--- -newtype PtSize = PtSize -          { ptSize :: Double  -- ^ Extract Point Size as a Double -          } -  deriving (Eq,Ord,Num,Floating,Fractional,Real,RealFrac,RealFloat)--instance Show PtSize where-  showsPrec p d = showsPrec p (ptSize d)----- | Convert the value of PtSize scaling accordingly.------ Note - the Double instance perfoms no scaling, this--- is because internally Wumpus-Core works in points.--- -class Num u => FromPtSize u where-  fromPtSize :: PtSize -> u--instance FromPtSize Double where-  fromPtSize = ptSize---
src/Wumpus/Core/SVGDoc.hs view
@@ -3,11 +3,11 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Core.SVGDoc--- Copyright   :  (c) Stephen Tetley 2009-2010+-- Copyright   :  (c) Stephen Tetley 2009-2011 -- License     :  BSD3 ----- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>--- Stability   :  highly unstable+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable -- Portability :  GHC -- -- SVG Doc combinators.@@ -80,7 +80,7 @@ import Wumpus.Core.Geometry import Wumpus.Core.GraphicProps import Wumpus.Core.PictureInternal-import Wumpus.Core.Utils.Common+import Wumpus.Core.Utils.Common ( dtruncFmt ) import Wumpus.Core.Utils.FormatCombinators  @@ -217,7 +217,7 @@  -- | @ x=\"...\" @ ---attr_x :: PSUnit u => u -> Doc+attr_x :: Double -> Doc attr_x = svgAttr "x" . dtruncFmt  @@ -225,13 +225,13 @@ -- -- /List/ version of attr_x -- -attr_xs :: PSUnit u => [u] -> Doc+attr_xs :: [Double] -> Doc attr_xs = svgAttr "x" . hsep . map dtruncFmt   -- | @ y=\"...\" @ ---attr_y :: PSUnit u => u -> Doc+attr_y :: Double -> Doc attr_y = svgAttr "y" . dtruncFmt  @@ -239,34 +239,34 @@ -- -- /List/ version of attr_y -- -attr_ys :: PSUnit u => [u] -> Doc+attr_ys :: [Double] -> Doc attr_ys = svgAttr "y" . hsep . map dtruncFmt   -- | @ r=\"...\" @ ---attr_r :: PSUnit u => u -> Doc+attr_r :: Double -> Doc attr_r = svgAttr "r" . dtruncFmt   -- | @ rx=\"...\" @ ---attr_rx :: PSUnit u => u -> Doc+attr_rx :: Double -> Doc attr_rx = svgAttr "rx" . dtruncFmt  -- | @ ry=\"...\" @ ---attr_ry :: PSUnit u => u -> Doc+attr_ry :: Double -> Doc attr_ry = svgAttr "ry" . dtruncFmt  -- | @ cx=\"...\" @ ---attr_cx :: PSUnit u => u -> Doc+attr_cx :: Double -> Doc attr_cx = svgAttr "cx" . dtruncFmt  -- | @ cy=\"...\" @ ---attr_cy :: PSUnit u => u -> Doc+attr_cy :: Double -> Doc attr_cy = svgAttr "cy" . dtruncFmt  @@ -280,21 +280,21 @@ -- -- c.f. PostScript's @moveto@. ---path_m :: PSUnit u => Point2 u -> Doc+path_m :: DPoint2 -> Doc path_m (P2 x y) = char 'M' <+> dtruncFmt x <+> dtruncFmt y  -- | @ L ... ... @ -- -- c.f. PostScript's @lineto@. ---path_l :: PSUnit u => Point2 u -> Doc+path_l :: DPoint2 -> Doc path_l (P2 x y) = char 'L' <+> dtruncFmt x <+> dtruncFmt y  -- | @ C ... ... ... ... ... ... @ --  -- c.f. PostScript's @curveto@. ---path_c :: PSUnit u => Point2 u -> Point2 u -> Point2 u -> Doc+path_c :: DPoint2 -> DPoint2 -> DPoint2 -> Doc path_c (P2 x1 y1) (P2 x2 y2) (P2 x3 y3) =     char 'C' <+> dtruncFmt x1 <+> dtruncFmt y1              <+> dtruncFmt x2 <+> dtruncFmt y2@@ -349,13 +349,13 @@  -- | @ stroke-width=\"...\" @ ---attr_stroke_width :: PSUnit u => u -> Doc+attr_stroke_width :: Double -> Doc attr_stroke_width = svgAttr "stroke-width" . dtruncFmt   -- | @ stroke-miterlimit=\"...\" @ ---attr_stroke_miterlimit :: PSUnit u => u -> Doc+attr_stroke_miterlimit :: Double -> Doc attr_stroke_miterlimit = svgAttr "stroke-miterlimit" . dtruncFmt  -- | @ stroke-linejoin=\"...\" @@@ -410,12 +410,21 @@  -- | @ matrix(..., ..., ..., ..., ..., ...) @ ---val_matrix :: PSUnit u => Matrix3'3 u -> Doc+val_matrix :: Matrix3'3 Double -> Doc val_matrix mtrx = text "matrix" <> tupled (map dtruncFmt [a,b,c,d,e,f])   where     (a,b,c,d,e,f) = deconsMatrix mtrx +    -- Note - Matrix is problematic for units. +    -- e.g. for pica (12 ps points) we don\'t want to scale the +    -- identity matrix by 12:+    --+    -- > fmap (12*) [1,0,0,0,0,1]+    -- > [12,0,0,0,0,12] +    --++ -- | @ translate(..., ..., ..., ..., ..., ...) @ ---val_translate :: PSUnit u => Vec2 u -> Doc+val_translate :: DVec2 -> Doc val_translate (V2 x y) = text "translate" <> tupled [dtruncFmt x, dtruncFmt y]
src/Wumpus/Core/Text/Base.hs view
@@ -3,7 +3,7 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Core.Text.Base--- Copyright   :  (c) Stephen Tetley 2010+-- Copyright   :  (c) Stephen Tetley 2010-2011 -- License     :  BSD3 -- -- Maintainer  :  stephen.tetley@gmail.com@@ -101,6 +101,9 @@ -- An 'EscapedChar' may be either a regular character, an integer -- representing a Unicode code-point or a PostScript glyph -- name.+-- +-- PostScript glyph names are generally made up only of chars+-- @[a-zA-Z]@. --  data EscapedChar = CharLiteral Char                  | CharEscInt  Int
src/Wumpus/Core/TrafoInternal.hs view
@@ -1,12 +1,13 @@+{-# LANGUAGE TypeFamilies               #-} {-# OPTIONS -Wall #-}  -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Core.TrafoInternal--- Copyright   :  (c) Stephen Tetley 2010+-- Copyright   :  (c) Stephen Tetley 2010-2011 -- License     :  BSD3 ----- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>+-- Maintainer  :  stephen.tetley@gmail.com -- Stability   :  unstable  -- Portability :  GHC --@@ -27,12 +28,14 @@    -- * Types     PrimCTM(..)+   , AffineTrafo(..)     -- * CTM operations   , identityCTM   , makeThetaCTM   , makeTranslCTM+  , startPointCTM    , translateCTM   , scaleCTM@@ -50,9 +53,10 @@  import Wumpus.Core.AffineTrans import Wumpus.Core.Geometry-import Wumpus.Core.Utils.Common+import Wumpus.Core.Utils.Common ( dtruncFmt ) import Wumpus.Core.Utils.FormatCombinators +-- Note - PrimCTM can be specialized to Double.  -- Primitives support affine transformations. --@@ -62,32 +66,35 @@ --  -- Note - line thickness of a stroked path will not be scaled. ---data PrimCTM u = PrimCTM -      { ctm_transl_x    :: !u-      , ctm_transl_y    :: !u-      , ctm_scale_x     :: !u-      , ctm_scale_y     :: !u+data PrimCTM = PrimCTM +      { ctm_trans_x     :: !Double+      , ctm_trans_y     :: !Double+      , ctm_scale_x     :: !Double+      , ctm_scale_y     :: !Double       , ctm_rotation    :: !Radian        }   deriving (Eq,Show)  +type instance DUnit PrimCTM = Double   -- | For Pictures - Affine transformations are represented as  -- /syntax/ so they can be manipulated easily. ---data AffineTrafo u = Matrix (Matrix3'3 u)-                   | Rotate Radian-                   | RotAbout Radian (Point2 u)-                   | Scale u u-                   | Translate u u+data AffineTrafo = Matrix (Matrix3'3 Double)+                 | Rotate Radian+                 | RotAbout Radian (Point2 Double)+                 | Scale Double Double+                 | Translate Double Double   deriving (Eq,Show)                  -+type instance DUnit AffineTrafo = Double +--------------------------------------------------------------------------------+-- instances -instance PSUnit u => Format (PrimCTM u) where+instance Format PrimCTM where   format (PrimCTM dx dy sx sy ang) =        parens (text "CTM" <+> text "dx =" <> dtruncFmt dx                          <+> text "dy =" <> dtruncFmt dy@@ -97,30 +104,44 @@   - -------------------------------------------------------------------------------- -- Manipulating the PrimCTM -identityCTM :: Num u => PrimCTM u-identityCTM = PrimCTM { ctm_transl_x = 0, ctm_transl_y = 0-                      , ctm_scale_x = 1,  ctm_scale_y = 1-                      , ctm_rotation = 0 }+identityCTM :: PrimCTM+identityCTM = PrimCTM { ctm_trans_x  = 0+                      , ctm_trans_y  = 0+                      , ctm_scale_x  = 1+                      , ctm_scale_y  = 1+                      , ctm_rotation = 0   } -makeThetaCTM :: Num u => u -> u -> Radian -> PrimCTM u-makeThetaCTM dx dy ang = PrimCTM { ctm_transl_x = dx, ctm_transl_y = dy-                                 , ctm_scale_x = 1, ctm_scale_y = 1++makeThetaCTM :: Double -> Double -> Radian -> PrimCTM+makeThetaCTM dx dy ang = PrimCTM { ctm_trans_x  = dx+                                 , ctm_trans_y  = dy+                                 , ctm_scale_x  = 1+                                 , ctm_scale_y  = 1                                  , ctm_rotation = ang }  -makeTranslCTM :: Num u => u -> u -> PrimCTM u-makeTranslCTM dx dy = PrimCTM { ctm_transl_x = dx, ctm_transl_y = dy-                              , ctm_scale_x = 1, ctm_scale_y = 1+makeTranslCTM :: Double -> Double -> PrimCTM+makeTranslCTM dx dy = PrimCTM { ctm_trans_x  = dx+                              , ctm_trans_y  = dy+                              , ctm_scale_x  = 1+                              , ctm_scale_y  = 1                               , ctm_rotation = 0 }  +startPointCTM :: DPoint2 -> PrimCTM+startPointCTM (P2 x y) = PrimCTM { ctm_trans_x  = x+                                 , ctm_trans_y  = y+                                 , ctm_scale_x  = 1+                                 , ctm_scale_y  = 1+                                 , ctm_rotation = 0 }  -translateCTM :: Num u => u -> u -> PrimCTM u -> PrimCTM u+++translateCTM :: Double -> Double -> PrimCTM -> PrimCTM translateCTM x1 y1 (PrimCTM dx dy sx sy ang) =      PrimCTM (x1+dx) (y1+dy) sx sy ang @@ -132,19 +153,25 @@ -- It is expected that the point is extracted from the matrix, so -- scales and rotations operate on the point coordinates as well -- as the scale and rotation components. +-- -scaleCTM :: Num u => u -> u -> PrimCTM u -> PrimCTM u+-- | Scale the CTM.+--+scaleCTM :: Double -> Double -> PrimCTM -> PrimCTM scaleCTM x1 y1 (PrimCTM dx dy sx sy ang) =      let P2 x y = scale x1 y1 (P2 dx dy)      in PrimCTM x y (x1*sx) (y1*sy) ang -rotateCTM :: (Real u, Floating u) => Radian -> PrimCTM u -> PrimCTM u+-- | Rotate the CTM.+--+rotateCTM :: Radian -> PrimCTM -> PrimCTM rotateCTM theta (PrimCTM dx dy sx sy ang) =      let P2 x y = rotate theta (P2 dx dy)      in PrimCTM x y sx sy (circularModulo $ theta+ang) -rotateAboutCTM :: (Real u, Floating u) -               => Radian -> Point2 u -> PrimCTM u -> PrimCTM u+-- | RotateAbout the CTM.+--+rotateAboutCTM :: Radian -> DPoint2 -> PrimCTM -> PrimCTM rotateAboutCTM theta pt (PrimCTM dx dy sx sy ang) =      let P2 x y = rotateAbout theta pt (P2 dx dy)     in PrimCTM x y sx sy (circularModulo $ theta+ang)@@ -157,7 +184,7 @@ -- This function encapsulates the correct order (or does it? -  -- some of the demos are not working properly...). ---matrixRepCTM :: (Real u, Floating u) => PrimCTM u -> Matrix3'3 u+matrixRepCTM :: PrimCTM -> Matrix3'3 Double matrixRepCTM (PrimCTM dx dy sx sy ang) =      translationMatrix dx dy * rotationMatrix (circularModulo ang)                              * scalingMatrix sx sy@@ -169,7 +196,7 @@ -- If the residual CTM is the identity CTM, the SVG or PostScript -- output can be optimized. -- -unCTM :: Num u => PrimCTM  u -> (Point2 u, PrimCTM u)+unCTM :: PrimCTM -> (DPoint2, PrimCTM) unCTM (PrimCTM dx dy sx sy ang) = (P2 dx dy, PrimCTM 0 0 sx sy ang)  @@ -178,10 +205,10 @@   -concatTrafos :: (Floating u, Real u) => [AffineTrafo u] -> Matrix3'3 u+concatTrafos :: [AffineTrafo] -> Matrix3'3 Double concatTrafos = foldr (\e ac -> matrixRepr e * ac) identityMatrix -matrixRepr :: (Floating u, Real u) => AffineTrafo u -> Matrix3'3 u+matrixRepr :: AffineTrafo -> Matrix3'3 Double matrixRepr (Matrix mtrx)        = mtrx matrixRepr (Rotate theta)       = rotationMatrix theta matrixRepr (RotAbout theta pt)  = originatedRotationMatrix theta pt
src/Wumpus/Core/Utils/Common.hs view
@@ -4,11 +4,11 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Core.Utils.Common--- Copyright   :  (c) Stephen Tetley 2009-2010+-- Copyright   :  (c) Stephen Tetley 2009-2011 -- License     :  BSD3 ----- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>--- Stability   :  highly unstable+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable -- Portability :  GHC -- -- Utility functions and a Hughes list.@@ -19,18 +19,8 @@ module Wumpus.Core.Utils.Common   (  -  -- | Opt - maybe strict in Some-    Opt(..)-  , some--  -- | Conditional application-  , applyIf--  , rescale-   -- * Truncate / print a double-  , PSUnit(..)-  , dtruncFmt+    dtruncFmt    , truncateDouble   , roundup@@ -47,56 +37,17 @@ import qualified Wumpus.Core.Utils.FormatCombinators as Fmt  -import Data.Ratio import Data.Time -data Opt a = None | Some !a -  deriving (Eq,Show) -some :: a -> Opt a -> a-some dflt None     = dflt-some _    (Some a) = a  -applyIf :: Bool -> (a -> a) -> a -> a-applyIf cond fn a = if cond then fn a else a ---- rescale a (originally in the range amin to amax) within the --- the range bmin to bmax.----rescale :: Fractional a => (a,a) -> (a,a) -> a -> a-rescale (amin,amax) (bmin,bmax) a = -    bmin + apos * (brange / arange)  -  where-    arange = amax - amin-    brange = bmax - bmin-    apos   = a - amin-- -------------------------------------------------------------------------------- -- PS Unit -class Num a => PSUnit a where-  toDouble :: a -> Double-  dtrunc   :: a -> String-  -  dtrunc = truncateDouble . toDouble--instance PSUnit Double where-  toDouble = id-  dtrunc   = truncateDouble--instance PSUnit Float where-  toDouble = realToFrac--instance PSUnit (Ratio Integer) where-  toDouble = realToFrac--instance PSUnit (Ratio Int) where-  toDouble = realToFrac--dtruncFmt :: PSUnit a => a -> Fmt.Doc-dtruncFmt = Fmt.text . dtrunc+-- +dtruncFmt :: Double -> Fmt.Doc+dtruncFmt = Fmt.text . truncateDouble   -- | Truncate the printed decimal representation of a Double.
src/Wumpus/Core/Utils/FormatCombinators.hs view
@@ -3,11 +3,11 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Core.Utils.FormatCombinators--- Copyright   :  (c) Stephen Tetley 2010+-- Copyright   :  (c) Stephen Tetley 2010-2011 -- License     :  BSD3 ----- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>--- Stability   :  highly unstable+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable -- Portability :  GHC -- -- Formatting combinators - pretty printers without the fitting.@@ -120,7 +120,19 @@   mappend = (<>)  +--------------------------------------------------------------------------------+ class Format a where format :: a -> Doc++instance Format Int where+  format = int++instance Format Integer where+  format = integer++instance Format Double where+  format = double+  --------------------------------------------------------------------------------         
src/Wumpus/Core/Utils/JoinList.hs view
@@ -3,7 +3,7 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Core.Utils.JoinList--- Copyright   :  (c) Stephen Tetley 2010+-- Copyright   :  (c) Stephen Tetley 2010-2011 -- License     :  BSD3 -- -- A \"join list\" datatype and operations. @@ -32,7 +32,7 @@   -- * Conversion between join lists and regular lists   , fromList   , toList-  , toListF+  , toListF_rl    -- * Construction   , one@@ -110,7 +110,7 @@ -- | Convert a join list to a regular list. -- toList :: JoinList a -> [a]-toList = joinfoldl (flip (:)) []+toList = joinfoldr (:) []  -- | Build a join list from a regular list. --@@ -125,10 +125,10 @@ fromList (x:xs) = Join (One x) (fromList xs)  --- Note -- this works from Right to left...+-- Note -- this works from Right to Left... ---toListF :: (a -> b) -> JoinList a -> [b]-toListF f = step []+toListF_rl :: (a -> b) -> JoinList a -> [b]+toListF_rl f = step []   where     step acc (One x)     = f x : acc     step acc (Join t u)  = let acc' = step acc u in step acc' t@@ -153,6 +153,8 @@ one :: a -> JoinList a one = One ++infixr 5 `cons`  -- | Cons an element to the front of the join list. --
src/Wumpus/Core/VersionNumber.hs view
@@ -22,7 +22,7 @@  -- | Version number. ----- > (0,43,0)+-- > (0,50,0) -- wumpus_core_version :: (Int,Int,Int)-wumpus_core_version = (0,43,0)+wumpus_core_version = (0,50,0)
src/Wumpus/Core/WumpusTypes.hs view
@@ -3,10 +3,10 @@ -------------------------------------------------------------------------------- -- | -- Module      :  Wumpus.Core.WumpusTypes--- Copyright   :  (c) Stephen Tetley 2009-2010+-- Copyright   :  (c) Stephen Tetley 2009-2011 -- License     :  BSD3 ----- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>+-- Maintainer  :  stephen.tetley@gmail.com -- Stability   :  unstable  -- Portability :  GHC --@@ -34,26 +34,41 @@    -- * Picture types     Picture-  , DPicture   , FontCtx   , Primitive-  , DPrimitive   , XLink   , PrimPath-  , DPrimPath   , PrimPathSegment-  , DPrimPathSegment+  , AbsPathSegment   , PrimLabel-  , DPrimLabel   , KerningChar-  , DKerningChar -  -- * Printable unit for PostScript-  , PSUnit(..)+  , Format(..)+  , stringformat +   ) where   import Wumpus.Core.PictureInternal-import Wumpus.Core.Utils.Common ( PSUnit(..) )+import Wumpus.Core.Utils.FormatCombinators ( Format(..), text, Doc ) ++++-- | 'stringformat' : String -> Doc+--+-- The format combinators are not exported by Wumpus-Core, +-- however for debugging unit types might need to be made +-- instances of the 'Format' class.+-- +-- To define Format instances render the unit type to a String+-- then use 'stringformat', e.g:+--+-- >+-- > instance Format Pica where+-- >   format a = stringformat (show a)+-- >+--+stringformat :: String -> Doc+stringformat = text
wumpus-core.cabal view
@@ -1,5 +1,5 @@ name:             wumpus-core-version:          0.43.0+version:          0.50.0 license:          BSD3 license-file:     LICENSE copyright:        Stephen Tetley <stephen.tetley@gmail.com>@@ -39,8 +39,8 @@   than re-usable libraries).   .   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 +  sophisticated - e.g. how path and text attributes like colour +  are handled, and how the bounding boxes of text labels are    calculated. Compared to other systems, Wumpus might be rather    limited, however, the design permits a fairly simple    implementation.@@ -48,6 +48,48 @@   .   Changelog:   .+  v0.43.0 to v0.50.0:+  .+  * Major change hence the version number jump - the notion of +    parametric unit has been removed from the @Picture@ objects +    (it for remains the @Geometric@ objects @Point2@, @Vec2@ etc.). +    Certain useful units, e.g. @em@ and @en@, are contextual on +    the \"current point size\", and having a parametric unit here +    was actually a hinderance to supporting units properly in +    higher-level layers. Now all Picture objects (those defined +    or exported from @Core.Picture@) are fixed to use Double +    - representing PostScript points. Higher level layers that +    intend to support alternative units must translate drawing +    objects to PostScript point measurements /before/ calling the +    Picture API. Geometric objects - objects defined in +    @Core.Geometry@, e.g. @Point2@, @Vec2@ - are still polymorphic +    on unit. +  .  +  * Picture API change - Various function names changed.+    @lineTo@ becomes @absLineTo@ and @curveTo@ becomes +    @absCurveTo@. The path builders are qualified with /Prim/, +    @vertexPath@ becomes @vertexPrimPath@, @vectorPath@ becomes +    @vectorPrimPath@, @emptyPath@ becomes @emptyPrimPath@ and +    @curvedPath@ becomes @curvedPrimPath@. @xlink@ becomes +    @xlinkPrim@.+  . +  * API change - @PtSize@ data type replaced by @AfmUnit@ for font +    measurements.+  .+  * API and representation change - clipping paths are represented+    as @Primitive@ constructor rather than a @Picture@ constructor.+    This should make them more useful. The type of the function +    @clip@ in @Core.Picture@ has likewise changed.+  .+  * Picture API change - changed @primPath@ to @absPrimPath@, added+    the functions @relPrimPath@, @relLineTo@, @relCurveTo@.+  . +  * Added the class @Tolerance@ to @Core.Geometry@ and made the Eq +    instances of @Point2@, @Vec2@ and @BoundingBox@ tolerant. +    Tolerance accounts for a fairly lax equality on floating point +    numbers - it is suitable for Wumpus (printing) where high +    accuracy is needed.+  .   v0.42.1 to v0.43.0:   .   * API change - the function @bezierCircle@ in @Core.Geometry@@@ -71,6 +113,7 @@   demo/AffineTest02.hs,   demo/AffineTest03.hs,   demo/AffineTestBase.hs,+  demo/ClipPic.hs,   demo/DeltaPic.hs,   demo/EllipsePic.hs,   demo/FontMetrics.hs,@@ -109,7 +152,6 @@     Wumpus.Core.OutputPostScript,     Wumpus.Core.OutputSVG,     Wumpus.Core.Picture,-    Wumpus.Core.PtSize,     Wumpus.Core.Text.Base,     Wumpus.Core.Text.GlyphIndices,     Wumpus.Core.Text.GlyphNames,