packages feed

wumpus-core 0.35.0 → 0.36.0

raw patch · 56 files changed

+2950/−2589 lines, 56 filesdep −algebradep ~basePVP ok

version bump matches the API change (PVP)

Dependencies removed: algebra

Dependency ranges changed: base

API changes (from Hackage documentation)

- Wumpus.Core.AffineTrans: instance (Num u) => Scale (Point2 u)
- Wumpus.Core.AffineTrans: instance (Num u) => Scale (Vec2 u)
- Wumpus.Core.AffineTrans: instance (Num u) => Transform (Point2 u)
- Wumpus.Core.AffineTrans: instance (Num u) => Transform (Vec2 u)
- Wumpus.Core.AffineTrans: instance (Num u) => Translate (Point2 u)
- Wumpus.Core.AffineTrans: instance (Num u) => Translate (Vec2 u)
- Wumpus.Core.BoundingBox: instance (Eq u) => Eq (BoundingBox u)
- Wumpus.Core.BoundingBox: instance (Ord u) => Semigroup (BoundingBox u)
- Wumpus.Core.BoundingBox: instance (PSUnit u) => Format (BoundingBox u)
- Wumpus.Core.BoundingBox: instance (Show u) => Show (BoundingBox u)
- Wumpus.Core.Geometry: instance (Eq u) => Eq (Matrix3'3 u)
- Wumpus.Core.Geometry: instance (Eq u) => Eq (Point2 u)
- Wumpus.Core.Geometry: instance (Eq u) => Eq (Vec2 u)
- Wumpus.Core.Geometry: instance (Num u) => AdditiveGroup (Matrix3'3 u)
- Wumpus.Core.Geometry: instance (Num u) => AdditiveGroup (Vec2 u)
- Wumpus.Core.Geometry: instance (Num u) => AffineSpace (Point2 u)
- Wumpus.Core.Geometry: instance (Num u) => MatrixMult (Point2 u)
- Wumpus.Core.Geometry: instance (Num u) => MatrixMult (Vec2 u)
- Wumpus.Core.Geometry: instance (Num u) => Num (Matrix3'3 u)
- Wumpus.Core.Geometry: instance (Num u) => VectorSpace (Matrix3'3 u)
- Wumpus.Core.Geometry: instance (Num u) => VectorSpace (Vec2 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 u) => Show (Matrix3'3 u)
- Wumpus.Core.Geometry: instance (Show u) => Show (Point2 u)
- Wumpus.Core.Geometry: instance (Show u) => Show (Vec2 u)
- Wumpus.Core.GraphicsState: CapButt :: LineCap
- Wumpus.Core.GraphicsState: CapRound :: LineCap
- Wumpus.Core.GraphicsState: CapSquare :: LineCap
- Wumpus.Core.GraphicsState: Dash :: Int -> [(Int, Int)] -> DashPattern
- Wumpus.Core.GraphicsState: FontAttr :: Int -> FontFace -> FontAttr
- Wumpus.Core.GraphicsState: FontFace :: String -> String -> SVGFontStyle -> FontEncoderName -> FontFace
- Wumpus.Core.GraphicsState: GraphicsState :: RGBi -> Int -> FontFace -> StrokeAttr -> GraphicsState
- Wumpus.Core.GraphicsState: JoinBevel :: LineJoin
- Wumpus.Core.GraphicsState: JoinMiter :: LineJoin
- Wumpus.Core.GraphicsState: JoinRound :: LineJoin
- Wumpus.Core.GraphicsState: SVG_BOLD :: SVGFontStyle
- Wumpus.Core.GraphicsState: SVG_BOLD_ITALIC :: SVGFontStyle
- Wumpus.Core.GraphicsState: SVG_BOLD_OBLIQUE :: SVGFontStyle
- Wumpus.Core.GraphicsState: SVG_ITALIC :: SVGFontStyle
- Wumpus.Core.GraphicsState: SVG_OBLIQUE :: SVGFontStyle
- Wumpus.Core.GraphicsState: SVG_REGULAR :: SVGFontStyle
- Wumpus.Core.GraphicsState: Solid :: DashPattern
- Wumpus.Core.GraphicsState: StrokeAttr :: Double -> Double -> LineCap -> LineJoin -> DashPattern -> StrokeAttr
- Wumpus.Core.GraphicsState: dash_pattern :: StrokeAttr -> DashPattern
- Wumpus.Core.GraphicsState: data DashPattern
- Wumpus.Core.GraphicsState: data FontAttr
- Wumpus.Core.GraphicsState: data FontFace
- Wumpus.Core.GraphicsState: data GraphicsState
- Wumpus.Core.GraphicsState: data LineCap
- Wumpus.Core.GraphicsState: data LineJoin
- Wumpus.Core.GraphicsState: data SVGFontStyle
- Wumpus.Core.GraphicsState: data StrokeAttr
- Wumpus.Core.GraphicsState: default_stroke_attr :: StrokeAttr
- Wumpus.Core.GraphicsState: font_enc_name :: FontFace -> FontEncoderName
- Wumpus.Core.GraphicsState: font_face :: FontAttr -> FontFace
- Wumpus.Core.GraphicsState: font_name :: FontFace -> String
- Wumpus.Core.GraphicsState: font_size :: FontAttr -> Int
- Wumpus.Core.GraphicsState: gs_draw_colour :: GraphicsState -> RGBi
- Wumpus.Core.GraphicsState: gs_font_face :: GraphicsState -> FontFace
- Wumpus.Core.GraphicsState: gs_font_size :: GraphicsState -> Int
- Wumpus.Core.GraphicsState: gs_stroke_attr :: GraphicsState -> StrokeAttr
- Wumpus.Core.GraphicsState: instance Enum LineCap
- Wumpus.Core.GraphicsState: instance Enum LineJoin
- Wumpus.Core.GraphicsState: instance Eq DashPattern
- Wumpus.Core.GraphicsState: instance Eq FontAttr
- Wumpus.Core.GraphicsState: instance Eq FontFace
- Wumpus.Core.GraphicsState: instance Eq GraphicsState
- Wumpus.Core.GraphicsState: instance Eq LineCap
- Wumpus.Core.GraphicsState: instance Eq LineJoin
- Wumpus.Core.GraphicsState: instance Eq SVGFontStyle
- Wumpus.Core.GraphicsState: instance Eq StrokeAttr
- Wumpus.Core.GraphicsState: instance Ord FontAttr
- Wumpus.Core.GraphicsState: instance Ord FontFace
- Wumpus.Core.GraphicsState: instance Ord SVGFontStyle
- Wumpus.Core.GraphicsState: instance Show DashPattern
- Wumpus.Core.GraphicsState: instance Show FontAttr
- Wumpus.Core.GraphicsState: instance Show FontFace
- Wumpus.Core.GraphicsState: instance Show GraphicsState
- Wumpus.Core.GraphicsState: instance Show LineCap
- Wumpus.Core.GraphicsState: instance Show LineJoin
- Wumpus.Core.GraphicsState: instance Show SVGFontStyle
- Wumpus.Core.GraphicsState: instance Show StrokeAttr
- Wumpus.Core.GraphicsState: line_cap :: StrokeAttr -> LineCap
- Wumpus.Core.GraphicsState: line_join :: StrokeAttr -> LineJoin
- Wumpus.Core.GraphicsState: line_width :: StrokeAttr -> Double
- Wumpus.Core.GraphicsState: miter_limit :: StrokeAttr -> Double
- Wumpus.Core.GraphicsState: svg_font_family :: FontFace -> String
- Wumpus.Core.GraphicsState: svg_font_style :: FontFace -> SVGFontStyle
- Wumpus.Core.GraphicsState: zeroGS :: GraphicsState
- Wumpus.Core.Picture: wumpus_default_font :: FontAttr
- Wumpus.Core.TextDefaultEncoder: defaultEncoder :: TextEncoder
- Wumpus.Core.TextEncoder: FontEncoder :: PostScriptLookup -> SVGLookup -> GlyphName -> CharCode -> FontEncoder
- Wumpus.Core.TextEncoder: FontEncoderName :: Word16 -> FontEncoderName
- Wumpus.Core.TextEncoder: TextEncoder :: String -> Map FontEncoderName FontEncoder -> TextEncoder
- Wumpus.Core.TextEncoder: data FontEncoder
- Wumpus.Core.TextEncoder: data TextEncoder
- Wumpus.Core.TextEncoder: font_encoder_map :: TextEncoder -> Map FontEncoderName FontEncoder
- Wumpus.Core.TextEncoder: getFontEncoderName :: FontEncoderName -> Word16
- Wumpus.Core.TextEncoder: instance Eq FontEncoderName
- Wumpus.Core.TextEncoder: instance Ord FontEncoderName
- Wumpus.Core.TextEncoder: instance Show FontEncoderName
- Wumpus.Core.TextEncoder: newtype FontEncoderName
- Wumpus.Core.TextEncoder: ps_fallback :: FontEncoder -> GlyphName
- Wumpus.Core.TextEncoder: ps_lookup :: FontEncoder -> PostScriptLookup
- Wumpus.Core.TextEncoder: svg_encoding_name :: TextEncoder -> String
- Wumpus.Core.TextEncoder: svg_fallback :: FontEncoder -> CharCode
- Wumpus.Core.TextEncoder: svg_lookup :: FontEncoder -> SVGLookup
- Wumpus.Core.TextEncoder: type CharCode = Int
- Wumpus.Core.TextEncoder: type GlyphName = String
- Wumpus.Core.TextEncoder: type PostScriptLookup = CharCode -> Maybe GlyphName
- Wumpus.Core.TextEncoder: type SVGLookup = GlyphName -> Maybe CharCode
- Wumpus.Core.TextLatin1: latin1FontAll :: [(GlyphName, CharCode)]
- Wumpus.Core.TextLatin1: latin1FontEncoder :: FontEncoder
- Wumpus.Core.TextLatin1: latin1_font_encoder :: FontEncoderName
- Wumpus.Core.TextSymbolFont: symbolFontAll :: [(GlyphName, CharCode)]
- Wumpus.Core.TextSymbolFont: symbolFontEncoder :: FontEncoder
- Wumpus.Core.TextSymbolFont: symbol_font_encoder :: FontEncoderName
- Wumpus.Core.WumpusTypes: data EllipseProps
- Wumpus.Core.WumpusTypes: data LabelProps
- Wumpus.Core.WumpusTypes: data PathProps
- Wumpus.Core.WumpusTypes: data PrimElement u
- Wumpus.Core.WumpusTypes: rotatePrim :: (Real u, Floating u) => Radian -> PrimElement u -> PrimElement u
- Wumpus.Core.WumpusTypes: scalePrim :: (Num u) => u -> u -> PrimElement u -> PrimElement u
- Wumpus.Core.WumpusTypes: translatePrim :: (Num u) => u -> u -> PrimElement u -> PrimElement u
- Wumpus.Core.WumpusTypes: type DPrimElement = PrimElement Double
- Wumpus.Core.WumpusTypes: uniformScalePrim :: (Num u) => u -> PrimElement u -> PrimElement u
+ Wumpus.Core.AffineTrans: instance Num u => Scale (Point2 u)
+ Wumpus.Core.AffineTrans: instance Num u => Scale (Vec2 u)
+ Wumpus.Core.AffineTrans: instance Num u => Transform (Point2 u)
+ Wumpus.Core.AffineTrans: instance Num u => Transform (Vec2 u)
+ Wumpus.Core.AffineTrans: instance Num u => Translate (Point2 u)
+ Wumpus.Core.AffineTrans: instance Num u => Translate (Vec2 u)
+ Wumpus.Core.BoundingBox: instance Eq u => Eq (BoundingBox u)
+ Wumpus.Core.BoundingBox: instance PSUnit u => Format (BoundingBox u)
+ Wumpus.Core.BoundingBox: instance Show u => Show (BoundingBox u)
+ Wumpus.Core.Geometry: instance Eq u => Eq (Matrix3'3 u)
+ Wumpus.Core.Geometry: instance Eq u => Eq (Point2 u)
+ Wumpus.Core.Geometry: instance Eq u => Eq (Vec2 u)
+ Wumpus.Core.Geometry: instance Num u => AdditiveGroup (Matrix3'3 u)
+ Wumpus.Core.Geometry: instance Num u => AdditiveGroup (Vec2 u)
+ Wumpus.Core.Geometry: instance Num u => AffineSpace (Point2 u)
+ Wumpus.Core.Geometry: instance Num u => MatrixMult (Point2 u)
+ Wumpus.Core.Geometry: instance Num u => MatrixMult (Vec2 u)
+ Wumpus.Core.Geometry: instance Num u => Num (Matrix3'3 u)
+ Wumpus.Core.Geometry: instance Num u => VectorSpace (Matrix3'3 u)
+ Wumpus.Core.Geometry: instance Num u => VectorSpace (Vec2 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 u => Show (Matrix3'3 u)
+ Wumpus.Core.Geometry: instance Show u => Show (Point2 u)
+ Wumpus.Core.Geometry: instance Show u => Show (Vec2 u)
+ Wumpus.Core.GraphicProps: CFill :: RGBi -> PathProps
+ Wumpus.Core.GraphicProps: CFillStroke :: RGBi -> StrokeAttr -> RGBi -> PathProps
+ Wumpus.Core.GraphicProps: CStroke :: StrokeAttr -> RGBi -> PathProps
+ Wumpus.Core.GraphicProps: CapButt :: LineCap
+ Wumpus.Core.GraphicProps: CapRound :: LineCap
+ Wumpus.Core.GraphicProps: CapSquare :: LineCap
+ Wumpus.Core.GraphicProps: Dash :: Int -> [(Int, Int)] -> DashPattern
+ Wumpus.Core.GraphicProps: EFill :: RGBi -> EllipseProps
+ Wumpus.Core.GraphicProps: EFillStroke :: RGBi -> StrokeAttr -> RGBi -> EllipseProps
+ Wumpus.Core.GraphicProps: EStroke :: StrokeAttr -> RGBi -> EllipseProps
+ Wumpus.Core.GraphicProps: FontAttr :: Int -> FontFace -> FontAttr
+ Wumpus.Core.GraphicProps: FontFace :: String -> String -> SVGFontStyle -> FontEncoderName -> FontFace
+ Wumpus.Core.GraphicProps: JoinBevel :: LineJoin
+ Wumpus.Core.GraphicProps: JoinMiter :: LineJoin
+ Wumpus.Core.GraphicProps: JoinRound :: LineJoin
+ Wumpus.Core.GraphicProps: LabelProps :: RGBi -> FontAttr -> LabelProps
+ Wumpus.Core.GraphicProps: OStroke :: StrokeAttr -> RGBi -> PathProps
+ Wumpus.Core.GraphicProps: SVG_BOLD :: SVGFontStyle
+ Wumpus.Core.GraphicProps: SVG_BOLD_ITALIC :: SVGFontStyle
+ Wumpus.Core.GraphicProps: SVG_BOLD_OBLIQUE :: SVGFontStyle
+ Wumpus.Core.GraphicProps: SVG_ITALIC :: SVGFontStyle
+ Wumpus.Core.GraphicProps: SVG_OBLIQUE :: SVGFontStyle
+ Wumpus.Core.GraphicProps: SVG_REGULAR :: SVGFontStyle
+ Wumpus.Core.GraphicProps: Solid :: DashPattern
+ Wumpus.Core.GraphicProps: StrokeAttr :: Double -> Double -> LineCap -> LineJoin -> DashPattern -> StrokeAttr
+ Wumpus.Core.GraphicProps: dash_pattern :: StrokeAttr -> DashPattern
+ Wumpus.Core.GraphicProps: data DashPattern
+ Wumpus.Core.GraphicProps: data EllipseProps
+ Wumpus.Core.GraphicProps: data FontAttr
+ Wumpus.Core.GraphicProps: data FontFace
+ Wumpus.Core.GraphicProps: data LabelProps
+ Wumpus.Core.GraphicProps: data LineCap
+ Wumpus.Core.GraphicProps: data LineJoin
+ Wumpus.Core.GraphicProps: data PathProps
+ Wumpus.Core.GraphicProps: data SVGFontStyle
+ Wumpus.Core.GraphicProps: data StrokeAttr
+ Wumpus.Core.GraphicProps: defaultFont :: Int -> FontAttr
+ Wumpus.Core.GraphicProps: default_stroke_attr :: StrokeAttr
+ Wumpus.Core.GraphicProps: font_enc_name :: FontFace -> FontEncoderName
+ Wumpus.Core.GraphicProps: font_face :: FontAttr -> FontFace
+ Wumpus.Core.GraphicProps: font_name :: FontFace -> String
+ Wumpus.Core.GraphicProps: font_size :: FontAttr -> Int
+ Wumpus.Core.GraphicProps: instance Enum LineCap
+ Wumpus.Core.GraphicProps: instance Enum LineJoin
+ Wumpus.Core.GraphicProps: instance Eq DashPattern
+ Wumpus.Core.GraphicProps: instance Eq EllipseProps
+ Wumpus.Core.GraphicProps: instance Eq FontAttr
+ Wumpus.Core.GraphicProps: instance Eq FontFace
+ Wumpus.Core.GraphicProps: instance Eq LabelProps
+ Wumpus.Core.GraphicProps: instance Eq LineCap
+ Wumpus.Core.GraphicProps: instance Eq LineJoin
+ Wumpus.Core.GraphicProps: instance Eq PathProps
+ Wumpus.Core.GraphicProps: instance Eq SVGFontStyle
+ Wumpus.Core.GraphicProps: instance Eq StrokeAttr
+ Wumpus.Core.GraphicProps: instance Format EllipseProps
+ Wumpus.Core.GraphicProps: instance Format LabelProps
+ Wumpus.Core.GraphicProps: instance Format PathProps
+ Wumpus.Core.GraphicProps: instance Ord FontAttr
+ Wumpus.Core.GraphicProps: instance Ord FontFace
+ Wumpus.Core.GraphicProps: instance Ord LabelProps
+ Wumpus.Core.GraphicProps: instance Ord SVGFontStyle
+ Wumpus.Core.GraphicProps: instance Show DashPattern
+ Wumpus.Core.GraphicProps: instance Show EllipseProps
+ Wumpus.Core.GraphicProps: instance Show FontAttr
+ Wumpus.Core.GraphicProps: instance Show FontFace
+ Wumpus.Core.GraphicProps: instance Show LabelProps
+ Wumpus.Core.GraphicProps: instance Show LineCap
+ Wumpus.Core.GraphicProps: instance Show LineJoin
+ Wumpus.Core.GraphicProps: instance Show PathProps
+ Wumpus.Core.GraphicProps: instance Show SVGFontStyle
+ Wumpus.Core.GraphicProps: instance Show StrokeAttr
+ Wumpus.Core.GraphicProps: label_colour :: LabelProps -> RGBi
+ Wumpus.Core.GraphicProps: label_font :: LabelProps -> FontAttr
+ Wumpus.Core.GraphicProps: line_cap :: StrokeAttr -> LineCap
+ Wumpus.Core.GraphicProps: line_join :: StrokeAttr -> LineJoin
+ Wumpus.Core.GraphicProps: line_width :: StrokeAttr -> Double
+ Wumpus.Core.GraphicProps: miter_limit :: StrokeAttr -> Double
+ Wumpus.Core.GraphicProps: svg_font_family :: FontFace -> String
+ Wumpus.Core.GraphicProps: svg_font_style :: FontFace -> SVGFontStyle
+ Wumpus.Core.GraphicProps: wumpus_default_font :: FontAttr
+ Wumpus.Core.Picture: primGroup :: [Primitive u] -> Primitive u
+ Wumpus.Core.Picture: rfillEllipse :: Num u => RGBi -> u -> u -> Radian -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: rfillStrokeEllipse :: Num u => RGBi -> StrokeAttr -> RGBi -> u -> u -> Radian -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: rstrokeEllipse :: Num u => RGBi -> StrokeAttr -> u -> u -> Radian -> Point2 u -> Primitive u
+ Wumpus.Core.Picture: rtextlabel :: Num u => RGBi -> FontAttr -> String -> Radian -> Point2 u -> Primitive u
+ Wumpus.Core.Text.DefaultEncoder: defaultEncoder :: TextEncoder
+ Wumpus.Core.Text.Encoder: FontEncoder :: PostScriptLookup -> SVGLookup -> GlyphName -> CharCode -> FontEncoder
+ Wumpus.Core.Text.Encoder: FontEncoderName :: Word16 -> FontEncoderName
+ Wumpus.Core.Text.Encoder: TextEncoder :: String -> Map FontEncoderName FontEncoder -> TextEncoder
+ Wumpus.Core.Text.Encoder: data FontEncoder
+ Wumpus.Core.Text.Encoder: data TextEncoder
+ Wumpus.Core.Text.Encoder: font_encoder_map :: TextEncoder -> Map FontEncoderName FontEncoder
+ Wumpus.Core.Text.Encoder: getFontEncoderName :: FontEncoderName -> Word16
+ Wumpus.Core.Text.Encoder: instance Eq FontEncoderName
+ Wumpus.Core.Text.Encoder: instance Ord FontEncoderName
+ Wumpus.Core.Text.Encoder: instance Show FontEncoderName
+ Wumpus.Core.Text.Encoder: newtype FontEncoderName
+ Wumpus.Core.Text.Encoder: ps_fallback :: FontEncoder -> GlyphName
+ Wumpus.Core.Text.Encoder: ps_lookup :: FontEncoder -> PostScriptLookup
+ Wumpus.Core.Text.Encoder: svg_encoding_name :: TextEncoder -> String
+ Wumpus.Core.Text.Encoder: svg_fallback :: FontEncoder -> CharCode
+ Wumpus.Core.Text.Encoder: svg_lookup :: FontEncoder -> SVGLookup
+ Wumpus.Core.Text.Encoder: type CharCode = Int
+ Wumpus.Core.Text.Encoder: type GlyphName = String
+ Wumpus.Core.Text.Encoder: type PostScriptLookup = CharCode -> Maybe GlyphName
+ Wumpus.Core.Text.Encoder: type SVGLookup = GlyphName -> Maybe CharCode
+ Wumpus.Core.Text.Latin1: latin1FontAll :: [(GlyphName, CharCode)]
+ Wumpus.Core.Text.Latin1: latin1FontEncoder :: FontEncoder
+ Wumpus.Core.Text.Latin1: latin1_font_encoder :: FontEncoderName
+ Wumpus.Core.Text.SymbolFont: symbolFontAll :: [(GlyphName, CharCode)]
+ Wumpus.Core.Text.SymbolFont: symbolFontEncoder :: FontEncoder
+ Wumpus.Core.Text.SymbolFont: symbol_font_encoder :: FontEncoderName
- Wumpus.Core.AffineTrans: rotate :: (Rotate t) => Radian -> t -> t
+ Wumpus.Core.AffineTrans: rotate :: Rotate t => Radian -> t -> t
- Wumpus.Core.AffineTrans: rotate120 :: (Rotate t) => t -> t
+ Wumpus.Core.AffineTrans: rotate120 :: Rotate t => t -> t
- Wumpus.Core.AffineTrans: rotate30 :: (Rotate t) => t -> t
+ Wumpus.Core.AffineTrans: rotate30 :: Rotate t => t -> t
- Wumpus.Core.AffineTrans: rotate45 :: (Rotate t) => t -> t
+ Wumpus.Core.AffineTrans: rotate45 :: Rotate t => t -> t
- Wumpus.Core.AffineTrans: rotate60 :: (Rotate t) => t -> t
+ Wumpus.Core.AffineTrans: rotate60 :: Rotate t => t -> t
- Wumpus.Core.AffineTrans: rotate90 :: (Rotate t) => t -> t
+ Wumpus.Core.AffineTrans: rotate90 :: Rotate t => t -> t
- Wumpus.Core.AffineTrans: translate :: (Translate t) => DUnit t -> DUnit t -> t -> t
+ Wumpus.Core.AffineTrans: translate :: Translate t => DUnit t -> DUnit t -> t -> t
- Wumpus.Core.BoundingBox: bbox :: (Ord u) => Point2 u -> Point2 u -> BoundingBox u
+ Wumpus.Core.BoundingBox: bbox :: Ord u => Point2 u -> Point2 u -> BoundingBox u
- Wumpus.Core.BoundingBox: boundaryHeight :: (Num u) => BoundingBox u -> u
+ Wumpus.Core.BoundingBox: boundaryHeight :: Num u => BoundingBox u -> u
- Wumpus.Core.BoundingBox: boundaryUnion :: (Ord u) => BoundingBox u -> BoundingBox u -> BoundingBox u
+ Wumpus.Core.BoundingBox: boundaryUnion :: Ord u => BoundingBox u -> BoundingBox u -> BoundingBox u
- Wumpus.Core.BoundingBox: boundaryWidth :: (Num u) => BoundingBox u -> u
+ Wumpus.Core.BoundingBox: boundaryWidth :: Num u => BoundingBox u -> u
- Wumpus.Core.BoundingBox: obbox :: (Num u) => u -> u -> BoundingBox u
+ Wumpus.Core.BoundingBox: obbox :: Num u => u -> u -> BoundingBox u
- Wumpus.Core.BoundingBox: withinBoundary :: (Ord u) => Point2 u -> BoundingBox u -> Bool
+ Wumpus.Core.BoundingBox: withinBoundary :: Ord u => Point2 u -> BoundingBox u -> Bool
- Wumpus.Core.Geometry: avec :: (Floating u) => Radian -> u -> Vec2 u
+ Wumpus.Core.Geometry: avec :: Floating u => Radian -> u -> Vec2 u
- Wumpus.Core.Geometry: bezierArc :: (Floating u) => u -> Radian -> Radian -> Point2 u -> (Point2 u, Point2 u, Point2 u, Point2 u)
+ Wumpus.Core.Geometry: bezierArc :: Floating u => u -> Radian -> Radian -> Point2 u -> (Point2 u, Point2 u, Point2 u, Point2 u)
- Wumpus.Core.Geometry: determinant :: (Num u) => Matrix3'3 u -> u
+ Wumpus.Core.Geometry: determinant :: Num u => Matrix3'3 u -> u
- Wumpus.Core.Geometry: fromRadian :: (Fractional a) => Radian -> a
+ Wumpus.Core.Geometry: fromRadian :: Fractional a => Radian -> a
- Wumpus.Core.Geometry: hvec :: (Num u) => u -> Vec2 u
+ Wumpus.Core.Geometry: hvec :: Num u => u -> Vec2 u
- Wumpus.Core.Geometry: identityMatrix :: (Num u) => Matrix3'3 u
+ Wumpus.Core.Geometry: identityMatrix :: Num u => Matrix3'3 u
- Wumpus.Core.Geometry: invert :: (Fractional u) => Matrix3'3 u -> Matrix3'3 u
+ Wumpus.Core.Geometry: invert :: Fractional u => Matrix3'3 u -> Matrix3'3 u
- Wumpus.Core.Geometry: maxPt :: (Ord u) => Point2 u -> Point2 u -> Point2 u
+ Wumpus.Core.Geometry: maxPt :: Ord u => Point2 u -> Point2 u -> Point2 u
- Wumpus.Core.Geometry: minPt :: (Ord u) => Point2 u -> Point2 u -> Point2 u
+ Wumpus.Core.Geometry: minPt :: Ord u => Point2 u -> Point2 u -> Point2 u
- Wumpus.Core.Geometry: pvec :: (Num u) => Point2 u -> Point2 u -> Vec2 u
+ Wumpus.Core.Geometry: pvec :: Num u => Point2 u -> Point2 u -> Vec2 u
- Wumpus.Core.Geometry: scalingMatrix :: (Num u) => u -> u -> Matrix3'3 u
+ Wumpus.Core.Geometry: scalingMatrix :: Num u => u -> u -> Matrix3'3 u
- Wumpus.Core.Geometry: toRadian :: (Real a) => a -> Radian
+ Wumpus.Core.Geometry: toRadian :: Real a => a -> Radian
- Wumpus.Core.Geometry: translationMatrix :: (Num u) => u -> u -> Matrix3'3 u
+ Wumpus.Core.Geometry: translationMatrix :: Num u => u -> u -> Matrix3'3 u
- Wumpus.Core.Geometry: vec :: (Num u) => u -> u -> Vec2 u
+ Wumpus.Core.Geometry: vec :: Num u => u -> u -> Vec2 u
- Wumpus.Core.Geometry: vlength :: (Floating u) => Vec2 u -> u
+ Wumpus.Core.Geometry: vlength :: Floating u => Vec2 u -> u
- Wumpus.Core.Geometry: vvec :: (Num u) => u -> Vec2 u
+ Wumpus.Core.Geometry: vvec :: Num u => u -> Vec2 u
- Wumpus.Core.Geometry: zeroPt :: (Num u) => Point2 u
+ Wumpus.Core.Geometry: zeroPt :: Num u => Point2 u
- Wumpus.Core.Picture: cstroke :: (Num u) => RGBi -> StrokeAttr -> PrimPath u -> PrimElement u
+ Wumpus.Core.Picture: cstroke :: Num u => RGBi -> StrokeAttr -> PrimPath u -> Primitive u
- Wumpus.Core.Picture: fill :: (Num u) => RGBi -> PrimPath u -> PrimElement u
+ Wumpus.Core.Picture: fill :: Num u => RGBi -> PrimPath u -> Primitive u
- Wumpus.Core.Picture: fillEllipse :: (Num u) => RGBi -> u -> u -> Point2 u -> PrimElement u
+ Wumpus.Core.Picture: fillEllipse :: Num u => RGBi -> u -> u -> Point2 u -> Primitive u
- Wumpus.Core.Picture: fillStroke :: (Num u) => RGBi -> StrokeAttr -> RGBi -> PrimPath u -> PrimElement u
+ Wumpus.Core.Picture: fillStroke :: Num u => RGBi -> StrokeAttr -> RGBi -> PrimPath u -> Primitive u
- Wumpus.Core.Picture: fillStrokeEllipse :: (Num u) => RGBi -> StrokeAttr -> RGBi -> u -> u -> Point2 u -> PrimElement u
+ Wumpus.Core.Picture: fillStrokeEllipse :: Num u => RGBi -> StrokeAttr -> RGBi -> u -> u -> Point2 u -> Primitive u
- Wumpus.Core.Picture: frame :: (Real u, Floating u, FromPtSize u) => [PrimElement u] -> Picture u
+ Wumpus.Core.Picture: frame :: (Real u, Floating u, FromPtSize u) => [Primitive u] -> Picture u
- Wumpus.Core.Picture: hkernlabel :: (Num u) => RGBi -> FontAttr -> [KerningChar u] -> Point2 u -> PrimElement u
+ Wumpus.Core.Picture: hkernlabel :: Num u => RGBi -> FontAttr -> [KerningChar u] -> Point2 u -> Primitive u
- Wumpus.Core.Picture: illustrateBoundsPrim :: (Real u, Floating u, FromPtSize u) => RGBi -> PrimElement u -> Picture u
+ Wumpus.Core.Picture: illustrateBoundsPrim :: (Real u, Floating u, FromPtSize u) => RGBi -> Primitive u -> Picture u
- Wumpus.Core.Picture: illustrateControlPoints :: (Real u, Floating u, FromPtSize u) => RGBi -> PrimElement u -> Picture u
+ Wumpus.Core.Picture: illustrateControlPoints :: (Real u, Floating u, FromPtSize u) => RGBi -> Primitive u -> Picture u
- Wumpus.Core.Picture: ostroke :: (Num u) => RGBi -> StrokeAttr -> PrimPath u -> PrimElement u
+ Wumpus.Core.Picture: ostroke :: Num u => RGBi -> StrokeAttr -> PrimPath u -> Primitive u
- Wumpus.Core.Picture: strokeEllipse :: (Num u) => RGBi -> StrokeAttr -> u -> u -> Point2 u -> PrimElement u
+ Wumpus.Core.Picture: strokeEllipse :: Num u => RGBi -> StrokeAttr -> u -> u -> Point2 u -> Primitive u
- Wumpus.Core.Picture: textlabel :: (Num u) => RGBi -> FontAttr -> String -> Point2 u -> PrimElement u
+ Wumpus.Core.Picture: textlabel :: Num u => RGBi -> FontAttr -> String -> Point2 u -> Primitive u
- Wumpus.Core.Picture: vkernlabel :: (Num u) => RGBi -> FontAttr -> [KerningChar u] -> Point2 u -> PrimElement u
+ Wumpus.Core.Picture: vkernlabel :: Num u => RGBi -> FontAttr -> [KerningChar u] -> Point2 u -> Primitive u
- Wumpus.Core.Picture: xlinkGroup :: XLink -> [PrimElement u] -> PrimElement u
+ Wumpus.Core.Picture: xlinkGroup :: XLink -> [Primitive u] -> Primitive u
- Wumpus.Core.Picture: zcstroke :: (Num u) => PrimPath u -> PrimElement u
+ Wumpus.Core.Picture: zcstroke :: Num u => PrimPath u -> Primitive u
- Wumpus.Core.Picture: zellipse :: (Num u) => u -> u -> Point2 u -> PrimElement u
+ Wumpus.Core.Picture: zellipse :: Num u => u -> u -> Point2 u -> Primitive u
- Wumpus.Core.Picture: zfill :: (Num u) => PrimPath u -> PrimElement u
+ Wumpus.Core.Picture: zfill :: Num u => PrimPath u -> Primitive u
- Wumpus.Core.Picture: zostroke :: (Num u) => PrimPath u -> PrimElement u
+ Wumpus.Core.Picture: zostroke :: Num u => PrimPath u -> Primitive u
- Wumpus.Core.Picture: ztextlabel :: (Num u) => String -> Point2 u -> PrimElement u
+ Wumpus.Core.Picture: ztextlabel :: Num u => String -> Point2 u -> Primitive u
- Wumpus.Core.PtSize: class FromPtSize u
+ Wumpus.Core.PtSize: class Num u => FromPtSize u
- Wumpus.Core.PtSize: fromPtSize :: (FromPtSize u) => PtSize -> u
+ Wumpus.Core.PtSize: fromPtSize :: FromPtSize u => PtSize -> u
- Wumpus.Core.WumpusTypes: class (Num a) => PSUnit a
+ Wumpus.Core.WumpusTypes: class Num a => PSUnit a
- Wumpus.Core.WumpusTypes: dtrunc :: (PSUnit a) => a -> String
+ Wumpus.Core.WumpusTypes: dtrunc :: PSUnit a => a -> String
- Wumpus.Core.WumpusTypes: toDouble :: (PSUnit a) => a -> Double
+ Wumpus.Core.WumpusTypes: toDouble :: PSUnit a => a -> Double

Files

demo/AffineTest01.hs view
@@ -20,8 +20,8 @@ rot30 :: (Rotate t, Fractional u, u ~ DUnit t) => t -> t
 rot30 = rotate30
 
-rot30P :: (Real u, Floating u) => PrimElement u -> PrimElement u
-rot30P = rotatePrim (d2r (30.0::Double))
+rot30P :: (Real u, Floating u) => Primitive u -> Primitive u
+rot30P = rotate30
 
 -- Primitive - Text
 
demo/AffineTest02.hs view
@@ -20,8 +20,8 @@ scale_onehalf_x_two = scale 1.5 2.0
 
 
-scale_onehalf_x_twoP :: Fractional u => PrimElement u -> PrimElement u
-scale_onehalf_x_twoP = scalePrim 1.5 2.0
+scale_onehalf_x_twoP :: Fractional u => Primitive u -> Primitive u
+scale_onehalf_x_twoP = scale 1.5 2.0
 
 -- Primitive - Text
 
demo/AffineTest03.hs view
@@ -19,8 +19,8 @@ translate_20x40 :: (Translate t, Fractional u, u ~ DUnit t) => t -> t
 translate_20x40 = translate 20.0 40.0
 
-translate_20x40P :: Fractional u => PrimElement u -> PrimElement u
-translate_20x40P = translatePrim 20.0 40.0
+translate_20x40P :: Fractional u => Primitive u -> Primitive u
+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 -> DPrimElement
+      , ata_prim_constructor    :: RGBi -> DPrimitive
       , ata_pic_transformer     :: DPicture -> DPicture
-      , ata_prim_transformer    :: DPrimElement -> DPrimElement
+      , ata_prim_transformer    :: DPrimitive -> DPrimitive
       }
 
 runATA :: AffineTrafoAlg -> IO ()
@@ -56,9 +56,9 @@                           (ata_prim_transformer ata)
 
 
-buildPictureATA :: (RGBi -> DPrimElement) 
+buildPictureATA :: (RGBi -> DPrimitive) 
          -> (DPicture -> DPicture) 
-         -> (DPrimElement -> DPrimElement) 
+         -> (DPrimitive -> DPrimitive) 
          -> DPicture
 buildPictureATA mk picF primF = 
     picture1 `picBeside` picture2 `picBeside` picture3
@@ -72,7 +72,7 @@     picture3 :: DPicture
     picture3 = illustrateBoundsPrim light_blue $ prim
       where
-        prim :: DPrimElement
+        prim :: DPrimitive
         prim = primF $ mk red
 
 
@@ -85,8 +85,8 @@       { cpa_console_msg         :: String
       , cpa_eps_file            :: FilePath
       , cpa_svg_file            :: FilePath
-      , cpa_prim_constructor    :: RGBi -> DPrimElement
-      , cpa_prim_transformer    :: DPrimElement -> DPrimElement
+      , cpa_prim_constructor    :: RGBi -> DPrimitive
+      , cpa_prim_transformer    :: DPrimitive -> DPrimitive
       }
 
 runCPA :: ControlPointAlg -> IO ()
@@ -98,27 +98,27 @@   where
     pic = cpPicture (cpa_prim_constructor cpa) (cpa_prim_transformer cpa)
 
-cpPicture :: (RGBi -> DPrimElement) -> (DPrimElement -> DPrimElement) -> DPicture
+cpPicture :: (RGBi -> DPrimitive) -> (DPrimitive -> DPrimitive) -> DPicture
 cpPicture constr trafo = 
     illustrateBounds light_blue $ illustrateControlPoints black 
                                 $ transformed_prim
   where
-   transformed_prim :: DPrimElement
+   transformed_prim :: DPrimitive
    transformed_prim = trafo $ constr red
 
 
 --------------------------------------------------------------------------------
 
-rgbLabel :: RGBi -> DPrimElement
+rgbLabel :: RGBi -> DPrimitive
 rgbLabel rgb = textlabel rgb wumpus_default_font "Wumpus!" zeroPt
 
-rgbCircle :: RGBi -> DPrimElement
+rgbCircle :: RGBi -> DPrimitive
 rgbCircle rgb = fillEllipse rgb 60 60 zeroPt
 
-rgbEllipse :: RGBi -> DPrimElement
+rgbEllipse :: RGBi -> DPrimitive
 rgbEllipse rgb = fillEllipse rgb 60 30 zeroPt
 
-rgbPath :: RGBi -> DPrimElement
+rgbPath :: RGBi -> DPrimitive
 rgbPath rgb = ostroke rgb default_stroke_attr $ dog_kennel
 --------------------------------------------------------------------------------
 -- Demo - draw a dog kennel...
demo/DeltaPic.hs view
@@ -41,10 +41,10 @@ -- Note - each label is fully attributed with the font style. -- There really is not attribute inheritance. ---helveticaLabel :: Int -> String -> DPoint2 -> DPrimElement+helveticaLabel :: Int -> String -> DPoint2 -> DPrimitive helveticaLabel sz ss pt = textlabel peru attrs ss pt   where     attrs = FontAttr sz common_ff -courierLabel :: String -> DPoint2 -> DPrimElement+courierLabel :: String -> DPoint2 -> DPrimitive courierLabel ss pt = textlabel black wumpus_default_font ss pt
demo/FontMetrics.hs view
@@ -52,7 +52,7 @@   where     chars = (map letter "ABXabdgjxy12") ++ [agraveU] -type PrimF = DPoint2 -> DPrimElement+type PrimF = DPoint2 -> DPrimitive  bodyHeight  :: PrimF bodyHeight  = vertLine peru $ fromPtSize courier48_numeral_height@@ -60,15 +60,15 @@ agraveU     :: PrimF agraveU     = textlabel black courier_attr "&#Agrave" -letter :: Char -> DPoint2 -> DPrimElement+letter :: Char -> DPoint2 -> DPrimitive letter ch pt = textlabel black courier_attr [ch] pt  -vertLine :: RGBi -> Double -> DPoint2 -> DPrimElement+vertLine :: RGBi -> Double -> DPoint2 -> DPrimitive vertLine rgb height pt =      ostroke rgb default_stroke_attr $ vertexPath [pt, pt .+^ vvec height] -haxis :: RGBi -> PtSize -> DPrimElement+haxis :: RGBi -> PtSize -> DPrimitive haxis rgb ypos =      ostroke rgb dash_attr $ vertexPath [ pt, pt .+^ hvec 440 ]   where
demo/KernPic.hs view
@@ -47,13 +47,13 @@ uUpsilon :: [ DKerningChar ] uUpsilon = [ kernEscInt 6 0o241, kernchar 12 'a', kernchar 12 'b' ]  -helveticaLabelH :: [KerningChar Double] -> DPoint2 -> DPrimElement+helveticaLabelH :: [KerningChar Double] -> DPoint2 -> DPrimitive helveticaLabelH xs pt = hkernlabel black helvetica18 xs pt -helveticaLabelV :: [KerningChar Double] -> DPoint2 -> DPrimElement+helveticaLabelV :: [KerningChar Double] -> DPoint2 -> DPrimitive helveticaLabelV xs pt = vkernlabel black helvetica18 xs pt -symbolLabelH :: [KerningChar Double] -> DPoint2 -> DPrimElement+symbolLabelH :: [KerningChar Double] -> DPoint2 -> DPrimitive symbolLabelH xs pt = hkernlabel black symbol18 xs pt  
demo/LabelPic.hs view
@@ -7,46 +7,15 @@  import System.Directory --------------------------------------------------------------------------------- ---drawBounds :: (Floating u, Real u, FromPtSize u) => Picture u -> Picture u-drawBounds p        = p `picOver` (frame [zcstroke ph])-  where-    ph            = vertexPath $ [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 a = P2 hcenter vcenter -  where  -    BBox (P2 x0 y0) (P2 x1 y1) = boundary a-    hcenter                    = x0 + 0.5 * (x1 - x0)-    vcenter                    = y0 + 0.5 * (y1 - y0)------------------------------------------------------------------------------------peru :: RGBi-peru = RGBi 205  133  63--plum :: RGBi-plum = RGBi 221  160  221--black :: RGBi-black = RGBi 0 0 0 +main :: IO ()+main = do +  createDirectoryIfMissing True "./out/"+  sequence_ [ demo01, demo02, demo03, demo04, demo05+            , demo06, demo07 ]   -lbl1 :: Picture Double-lbl1 = line1 `picBeside` line2 where-  line1 = frame [textlabel peru attrs "Hello" zeroPt]-  line2 = frame [textlabel peru attrs "World" zeroPt]-  attrs = FontAttr 12 (FontFace "Helvetica" "Helvetica" -                                SVG_REGULAR latin1_font_encoder)-- demo01 :: IO () demo01 = do      writeEPS_latin1 "./out/label01.eps" lbl1@@ -131,8 +100,44 @@     pC = drawBounds $ picMoveBy `flip` (vec 0 10) $ bigLetter peru 'C'  -main :: IO ()-main = do -  createDirectoryIfMissing True "./out/"-  sequence_ [ demo01, demo02, demo03, demo04, demo05-            , demo06, demo07 ]+++--------------------------------------------------------------------------------++++drawBounds :: (Floating u, Real u, FromPtSize u) => Picture u -> Picture u+drawBounds p        = p `picOver` (frame [zcstroke ph])+  where+    ph            = vertexPath $ [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 a = P2 hcenter vcenter +  where  +    BBox (P2 x0 y0) (P2 x1 y1) = boundary a+    hcenter                    = x0 + 0.5 * (x1 - x0)+    vcenter                    = y0 + 0.5 * (y1 - y0)++--------------------------------------------------------------------------------++peru :: RGBi+peru = RGBi 205  133  63++plum :: RGBi+plum = RGBi 221  160  221++black :: RGBi+black = RGBi 0 0 0 ++++lbl1 :: Picture Double+lbl1 = line1 `picBeside` line2 where+  line1 = frame [textlabel peru attrs "Hello" zeroPt]+  line2 = frame [textlabel peru attrs "World" zeroPt]+  attrs = FontAttr 12 (FontFace "Helvetica" "Helvetica" +                                SVG_REGULAR latin1_font_encoder)+
demo/Latin1Pic.hs view
@@ -29,7 +29,7 @@   -helveticaLabel :: String -> DPoint2 -> DPrimElement+helveticaLabel :: String -> DPoint2 -> DPrimitive helveticaLabel ss pt = textlabel black helvetica18 ss pt  helvetica18 :: FontAttr
demo/MultiPic.hs view
@@ -26,7 +26,7 @@     ]  -square :: (Num u, Ord u) => RGBi -> u -> Point2 u -> PrimElement u+square :: (Num u, Ord u) => RGBi -> u -> Point2 u -> Primitive u square rgb sidelen bl = fill rgb $ vertexPath $     [bl, bl .+^ hvec sidelen, bl .+^ V2 sidelen sidelen, bl .+^ vvec sidelen] 
− demo/Rotated.hs
@@ -1,70 +0,0 @@-{-# OPTIONS -Wall #-}--module Rotated where--import Wumpus.Core-import Wumpus.Core.Colour--import Data.AffineSpace--import System.Directory---main :: IO ()-main = do -    createDirectoryIfMissing True "./out/"-    writeEPS_latin1 "./out/rot_square.eps"  pic1-    writeSVG_latin1 "./out/rot_square.svg"  pic1-    writeEPS_latin1 "./out/rot_circle.eps"  pic2-    writeSVG_latin1 "./out/rot_circle.svg"  pic2-    writeEPS_latin1 "./out/rot_label.eps"   pic3-    writeSVG_latin1 "./out/rot_label.svg"   pic3----- both squares should share the bottom left coord...--deg45 :: Radian-deg45 = d2r (45.0::Double)---pic1 :: DPicture-pic1 = illustrateBounds grey $ frame $ -    [ rotatePrim deg45 $ square blue 50 (P2 100 100)-    , square red 50 (P2 100 100)-    ]------ both ellipses should share the same center-pic2 :: DPicture-pic2 = illustrateBounds grey $ frame $ -    [ rotatePrim deg45 $ ellipseHH blue 25 (P2 100 100)-    , ellipseHH red 25 (P2 100 100)-    ]----- both labels should share the same bottom left corner-pic3 :: DPicture-pic3 = illustrateBounds grey $ frame $ -    [ rotatePrim deg45 $  label blue (P2 100 100)-    , label red (P2 100 100)-    ]---square :: (Num u, Ord u) => RGBi -> u -> Point2 u -> PrimElement u-square rgb sidelen bl = fill rgb $ vertexPath $-    [bl, bl .+^ hvec sidelen, bl .+^ V2 sidelen sidelen, bl .+^ vvec sidelen]----ellipseHH :: Fractional u => RGBi -> u -> Point2 u -> PrimElement u-ellipseHH rgb radius ctr = fillEllipse rgb radius (0.5*radius) ctr- -label :: Num u => RGBi -> Point2 u -> PrimElement u-label rgb bl = textlabel rgb wumpus_default_font "Wumpus" bl---grey :: RGBi-grey = RGBi 176 197 223--
− demo/Scaled.hs
@@ -1,63 +0,0 @@-{-# OPTIONS -Wall #-}--module Scaled where--import Wumpus.Core-import Wumpus.Core.Colour--import Data.AffineSpace--import System.Directory--main :: IO ()-main = do -    createDirectoryIfMissing True "./out/"-    writeEPS_latin1 "./out/scaled_square.eps"  pic1-    writeSVG_latin1 "./out/scaled_square.svg"  pic1-    writeEPS_latin1 "./out/scaled_circle.eps"  pic2-    writeSVG_latin1 "./out/scaled_circle.svg"  pic2-    writeEPS_latin1 "./out/scaled_label.eps"   pic3-    writeSVG_latin1 "./out/scaled_label.svg"   pic3----- both squares should share the bottom left corner--pic1 :: DPicture-pic1 = illustrateBounds grey $ frame $ -    [ uniformScalePrim 0.5 $ square blue 50 (P2 100 100)-    , square red 50 (P2 100 100)-    ]----- both ellipses should share the same center-pic2 :: DPicture-pic2 = illustrateBounds grey $ frame $ -    [ uniformScalePrim 0.5 $ ellipseHH blue 25 (P2 100 100)-    , ellipseHH red 25 (P2 100 100)-    ]----- both labels should share the same bottom left corner-pic3 :: DPicture-pic3 = illustrateBounds grey $ frame $-    [ uniformScalePrim 0.5 $ label blue (P2 100 100)-    , label red (P2 100 100)-    ]----square :: (Num u, Ord u) => RGBi -> u -> Point2 u -> PrimElement u-square rgb sidelen bl = fill rgb $ vertexPath $-    [bl, bl .+^ hvec sidelen, bl .+^ V2 sidelen sidelen, bl .+^ vvec sidelen]--ellipseHH :: Fractional u => RGBi -> u -> Point2 u -> PrimElement u-ellipseHH rgb radius ctr = fillEllipse rgb radius (0.5*radius) ctr- -label :: Num u => RGBi -> Point2 u -> PrimElement u-label rgb bl = textlabel rgb wumpus_default_font "Wumpus" bl---grey :: RGBi-grey = RGBi 176 197 223--
+ demo/TransformEllipse.hs view
@@ -0,0 +1,95 @@+{-# LANGUAGE TypeFamilies               #-}+{-# OPTIONS -Wall #-}++module TransformEllipse where++import Wumpus.Core+import Wumpus.Core.Colour++import Data.AffineSpace                         -- package: vector-space++import System.Directory+++main :: IO ()+main = do +    createDirectoryIfMissing True "./out/"+    writeEPS_latin1 "./out/transform_ellipse01.eps" pic1+    writeSVG_latin1 "./out/transform_ellipse01.svg" pic1+    writeEPS_latin1 "./out/transform_ellipse02.eps" pic2+    writeSVG_latin1 "./out/transform_ellipse02.svg" pic2+    writeEPS_latin1 "./out/transform_ellipse03.eps" pic3+    writeSVG_latin1 "./out/transform_ellipse03.svg" pic3+    writeEPS_latin1 "./out/transform_ellipse04.eps" pic4+    writeSVG_latin1 "./out/transform_ellipse04.svg" pic4+    writeEPS_latin1 "./out/transform_ellipse05.eps" pic5+    writeSVG_latin1 "./out/transform_ellipse05.svg" pic5++++pic1 :: Picture Double+pic1 = cb `picOver` ell `picOver` xy_frame "no transform"+  where+     ell  = mkRedEllipse id 20 10 pt+     cb   = crossbar 20 10 pt+     pt   = P2 70 10+++pic2 :: Picture Double+pic2 = cb `picOver` ell `picOver` xy_frame "rotate 30deg"+  where+     ell  = mkRedEllipse (rotate ang) 20 10 pt+     cb   = rotate ang $ crossbar 20 10 pt+     pt   = P2 70 10+     ang  = 0.25*pi++pic3 :: Picture Double+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+     ang  = 0.25*pi+++pic4 :: Picture Double+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 = cb `picOver` ell `picOver` xy_frame "translate -70 -10"+  where+     ell  = mkRedEllipse (translate (-70) (-10)) 20 10 pt+     cb   = translate (-70) (-10) $ crossbar 20 10 pt+     pt   = P2 70 10+++mkRedEllipse :: (Real u, Floating u, FromPtSize u) +             => (Primitive u -> Primitive u) +             -> u -> u -> Point2 u -> Picture u+mkRedEllipse trafo rx ry pt = frame [ trafo $ fillEllipse red rx ry pt] ++crossbar :: (Real u, Floating u, FromPtSize u) +         => u -> u -> Point2 u -> Picture u+crossbar rx ry ctr = frame [ostroke black default_stroke_attr $ path west ps]+  where+    ps    = [ lineTo east, lineTo ctr, lineTo north, lineTo 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 ss = +    frame [ mkline (P2 (-4) 0) (P2 150 0)+          , mkline (P2 0 (-4)) (P2 0 150) +          , textlabel black wumpus_default_font ss (P2 0 (-20))+          ]++  where+    mkline p1 p2 = ostroke black default_stroke_attr $ path p1 [lineTo p2]
+ demo/TransformPath.hs view
@@ -0,0 +1,109 @@+{-# OPTIONS -Wall #-}++module TransformPath where++import Wumpus.Core+import Wumpus.Core.Colour++import Data.AffineSpace                         -- package: vector-space++import System.Directory+++main :: IO ()+main = do +    createDirectoryIfMissing True "./out/"+    writeEPS_latin1 "./out/transform_path01.eps" pic1+    writeSVG_latin1 "./out/transform_path01.svg" pic1+    writeEPS_latin1 "./out/transform_path02.eps" pic2+    writeSVG_latin1 "./out/transform_path02.svg" pic2+    writeEPS_latin1 "./out/transform_path03.eps" pic3+    writeSVG_latin1 "./out/transform_path03.svg" pic3+    writeEPS_latin1 "./out/transform_path04.eps" pic4+    writeSVG_latin1 "./out/transform_path04.svg" pic4+    writeEPS_latin1 "./out/transform_path05.eps" pic5+    writeSVG_latin1 "./out/transform_path05.svg" pic5++++pic1 :: Picture Double+pic1 = pth `picOver` ch `picOver` xy_frame "no transform"+  where+     pth  = mkBlackPath id pt+     ch   = zcrosshair pt+     pt   = P2 70 10+++pic2 :: Picture Double+pic2 = pth `picOver` ch `picOver` xy_frame "rotate 30deg"+  where+     pth  = mkBlackPath (rotate ang) pt+     ch   = rotate ang $ zcrosshair pt+     pt   = P2 70 10+     ang  = 0.25*pi++pic3 :: Picture Double+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+     ang  = 0.25*pi+++pic4 :: Picture Double+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 = pth `picOver` ch `picOver` xy_frame "translate -70 -10"+  where+     pth  = mkBlackPath (translate (-70) (-10)) pt+     ch   = translate (-70) (-10) $ zcrosshair pt+     pt   = P2 70 10+++mkBlackPath :: (Real u, Floating u, FromPtSize u) +             => (Primitive u -> Primitive u) +             -> Point2 u -> Picture u+mkBlackPath trafo bl = +    frame [ trafo $ ostroke black custom_stroke_attr $ path bl ps]+  where+    ps = [lineTo p1, lineTo p2, lineTo p3]+    p1 = bl .+^ vec 25 12+    p2 = p1 .+^ vec 6 (-12)+    p3 = p2 .+^ vec 25 12++++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 = crosshair 56 12 ++crosshair :: (Real u, Floating u, FromPtSize u) +          => u -> u -> Point2 u -> Picture u+crosshair w h bl = frame [ostroke burlywood default_stroke_attr $ path bl ps]+  where+    ps    = [ lineTo tr, lineTo br, lineTo tl, lineTo bl ]+    tl    = bl .+^ vvec h+    tr    = bl .+^ vec  w h+    br    = bl .+^ hvec w+    +burlywood :: RGBi+burlywood = RGBi 222 184 135++xy_frame :: (Real u, Floating u, FromPtSize u) => String -> Picture u+xy_frame ss = +    frame [ mkline (P2 (-4) 0) (P2 150 0)+          , mkline (P2 0 (-4)) (P2 0 150) +          , textlabel black wumpus_default_font ss (P2 0 (-20))+          ]++  where+    mkline p1 p2 = ostroke black default_stroke_attr $ path p1 [lineTo p2]
+ demo/TransformTextlabel.hs view
@@ -0,0 +1,99 @@+{-# OPTIONS -Wall #-}++module TransformTextlabel where++import Wumpus.Core+import Wumpus.Core.Colour++import Data.AffineSpace                         -- package: vector-space++import System.Directory+++main :: IO ()+main = do +    createDirectoryIfMissing True "./out/"+    writeEPS_latin1 "./out/transform_textlabel01.eps" pic1+    writeSVG_latin1 "./out/transform_textlabel01.svg" pic1+    writeEPS_latin1 "./out/transform_textlabel02.eps" pic2+    writeSVG_latin1 "./out/transform_textlabel02.svg" pic2+    writeEPS_latin1 "./out/transform_textlabel03.eps" pic3+    writeSVG_latin1 "./out/transform_textlabel03.svg" pic3+    writeEPS_latin1 "./out/transform_textlabel04.eps" pic4+    writeSVG_latin1 "./out/transform_textlabel04.svg" pic4+    writeEPS_latin1 "./out/transform_textlabel05.eps" pic5+    writeSVG_latin1 "./out/transform_textlabel05.svg" pic5++++pic1 :: Picture Double+pic1 = txt `picOver` ch `picOver` xy_frame "no transform"+  where+     txt  = mkBlackTextlabel id pt+     ch   = zcrosshair pt+     pt   = P2 70 10+++pic2 :: Picture Double+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  = 0.25*pi++pic3 :: Picture Double+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  = 0.25*pi+++pic4 :: Picture Double+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++pic5 :: Picture Double+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+++mkBlackTextlabel :: (Real u, Floating u, FromPtSize u) +                 => (Primitive u -> Primitive u) +                 -> Point2 u -> Picture u+mkBlackTextlabel trafo bl = +    frame [ trafo $ textlabel black wumpus_default_font "rhubarb" bl ] ++zcrosshair :: (Real u, Floating u, FromPtSize u) => Point2 u -> Picture u+zcrosshair = crosshair 56 12 ++crosshair :: (Real u, Floating u, FromPtSize u) +          => u -> u -> Point2 u -> Picture u+crosshair w h bl = frame [ostroke burlywood default_stroke_attr $ path bl ps]+  where+    ps    = [ lineTo tr, lineTo br, lineTo tl, lineTo bl ]+    tl    = bl .+^ vvec h+    tr    = bl .+^ vec  w h+    br    = bl .+^ hvec w+    +burlywood :: RGBi+burlywood = RGBi 222 184 135++xy_frame :: (Real u, Floating u, FromPtSize u) => String -> Picture u+xy_frame ss = +    frame [ mkline (P2 (-4) 0) (P2 150 0)+          , mkline (P2 0 (-4)) (P2 0 150) +          , textlabel black wumpus_default_font ss (P2 0 (-20))+          ]++  where+    mkline p1 p2 = ostroke black default_stroke_attr $ path p1 [lineTo p2]
− demo/Translated.hs
@@ -1,59 +0,0 @@-{-# OPTIONS -Wall #-}--module Translated where--import Wumpus.Core-import Wumpus.Core.Colour--import Data.AffineSpace--import System.Directory--main :: IO ()-main = do -    createDirectoryIfMissing True "./out/"-    writeEPS_latin1 "./out/trans_square.eps"  pic1-    writeSVG_latin1 "./out/trans_square.svg"  pic1-    writeEPS_latin1 "./out/trans_circle.eps"  pic2-    writeSVG_latin1 "./out/trans_circle.svg"  pic2-    writeEPS_latin1 "./out/trans_label.eps"   pic3-    writeSVG_latin1 "./out/trans_label.svg"   pic3----- both squares should share the bottom left coord...-pic1 :: DPicture-pic1 = illustrateBounds grey $ frame $ -    [ translatePrim 100 10 $ square blue 50 (P2 100 100)-    , square red 50 (P2 100 100)-    ]--pic2 :: DPicture-pic2 = illustrateBounds grey $ frame $ -    [ translatePrim 100 10 $ ellipseHH blue 25 (P2 100 100)-    , ellipseHH red 25 (P2 100 100)-    ]--pic3 :: DPicture-pic3 = illustrateBounds grey $ frame $ -    [ translatePrim 100 10 $ label blue (P2 100 100)-    , label red (P2 100 100)-    ]----square :: (Num u, Ord u) => RGBi -> u -> Point2 u -> PrimElement u-square rgb sidelen bl = fill rgb $ vertexPath $-    [bl, bl .+^ hvec sidelen, bl .+^ V2 sidelen sidelen, bl .+^ vvec sidelen]--ellipseHH :: Fractional u => RGBi -> u -> Point2 u -> PrimElement u-ellipseHH rgb radius ctr = fillEllipse rgb radius (0.5*radius) ctr- -label :: Num u => RGBi -> Point2 u -> PrimElement u-label rgb bl = textlabel rgb wumpus_default_font "Wumpus" bl---grey :: RGBi-grey = RGBi 176 197 223---
demo/ZOrderPic.hs view
@@ -19,7 +19,7 @@ zorder_msg :: String zorder_msg = unlines $      [ ""-    , "Wumpus-core draws lists of 'PrimElement' left-to-right."+    , "Wumpus-core draws lists of Primitives left-to-right."     , "The head of the list will be drawn first - it will appear"     , "at the top of the output file. It will also be drawn at"     , "the back of the Z-Order."@@ -38,7 +38,7 @@ pic2 :: DPicture  pic2 = multi $ map (\a -> frame [a]) $ prim_list (P2 200 0) -prim_list :: DPoint2 -> [DPrimElement]+prim_list :: DPoint2 -> [DPrimitive] 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,7 +23,7 @@ \section{About \wumpuscore}
 %-----------------------------------------------------------------
 
-This guide was last updated for \wumpuscore version 0.35.0.
+This guide was last updated for \wumpuscore version 0.36.0.
 
 \wumpuscore is a Haskell library for generating 2D vector 
 pictures. It was written with portability as a priority, so it has 
@@ -54,7 +54,7 @@ Some internal data types are also exported as opaque - 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.}]
@@ -87,10 +87,10 @@ 
 \item[\texttt{Wumpus.Core.Geometry.}]
 The usual types an 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 
+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 
-constraints on the unit, class constraints like 
+constraints on the unit - class constraints like 
 \texttt{Fractional u} can then be shifted to the instance 
 declaration rather than the class declaration.
 
@@ -169,17 +169,13 @@ multiple labels.
 
 Primitives are attributed with drawing styles - font name and 
-size for labels; line width, colour, etc. for paths. Drawing 
-\emph{primitives} is unfortunately complicated due to the need to 
-support hyperlinks in SVG output. Primitives have to be lifted 
-to a \texttt{PrimElement} before they can be placed within a 
-\texttt{Picture} - in practive this lifting is done automatically 
-by using the shorthand constructors in 
-\texttt{Wumpus.Core.Picture}. 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). 
+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). 
 
 \begin{figure}
 \centering
@@ -206,9 +202,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. If one wanted 
-to draw blue or red arrows with \wumpuscore, one would make the 
-drawing colour a parameter of the arrow creation function.
+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.
 
 %-----------------------------------------------------------------
 \section{Affine transformations}
@@ -244,14 +240,11 @@ \end{array}
 \end{displaymath}
 
-Affine transformations are communicated to PostScript as 
-\texttt{concat} commands. Effectively \wumpuscore performs no
+Affine transformations on Pictures are communicated to PostScript
+as \texttt{concat} commands. For Pictures, \wumpuscore performs no
 transformations itself, delegating all the work to PostScript or
-SVG. This means transformations can generally be located in the 
-output if a picture needs to be debugged, though as this might 
-not be very helpful in practice. Internally \wumpuscore only 
-performs the transformation on the bounding box of a picture - it 
-needs to do this to maintain the size metrics of a picture 
+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.
 
@@ -270,15 +263,29 @@ <g transform="matrix(1.0, 0.0, 0.0, 1.0, 10.0, 20.0)"> ... </g>
 \end{verbatim}
 
-For efficiency reasons \wumpuscore supports some transformations
-on Primitives. These are not affine transformations as Primitives
-are not in an affine frame until they are lifted to Pictures 
-(Primitives have no notion of origin). For Paths, all the 
-transformations are precomputed before the output is generated. 
-Unfortunately scaling and rotation cannot be precomputed for 
-labels and ellipses, so matrix operations are generated in the 
-PostScript and SVG output.
+\wumpuscore also supports the regular affine transformations 
+on Primitives (the arbitrary matrix transformation 
+\texttt{transform} is not supported). Transformations are 
+implicitly interpreted in the standard affine frame - origin at 
+(0,0) and unit scaling vectors for the bases. 
 
+For paths, all the transformations are precomputed on the control 
+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).
+
+One consequence of transformations operating on the control points
+of primitives is that scalings do not scale the tip of the 
+\emph{drawing pen}. If a path is stroked, lifted to a Picture and
+then scaled the whole graphics state is effectively scaled 
+including the pen tip so the path is drawn with a thicker outline. 
+However, if a path is stoked and then scaled as a Primitive, the 
+drawing pen is not scaled so the path will be drawn with the 
+regular line width.
 
 %-----------------------------------------------------------------
 \section{Font handling}
doc-src/WorldFrame.hs view
@@ -26,13 +26,13 @@   -makeLabelPrim :: String -> DPoint2 -> DPrimElement+makeLabelPrim :: String -> DPoint2 -> DPrimitive makeLabelPrim = textlabel black attrs    where     attrs     = FontAttr 10 (FontFace "Helvetica" "Helvetica"                                        SVG_REGULAR latin1_font_encoder) -makeLinePrim :: Double -> DPoint2 -> DPoint2 -> DPrimElement+makeLinePrim :: Double -> DPoint2 -> DPoint2 -> DPrimitive makeLinePrim lw a b = ostroke black attrs $ path a [lineTo b]   where     attrs = default_stroke_attr {line_width=lw}
doc/Guide.pdf view

binary file changed (59489 → 59778 bytes)

src/Wumpus/Core.hs view
@@ -32,14 +32,14 @@   , module Wumpus.Core.Colour   , module Wumpus.Core.FontSize   , module Wumpus.Core.Geometry-  , module Wumpus.Core.GraphicsState+  , module Wumpus.Core.GraphicProps   , module Wumpus.Core.OutputPostScript   , module Wumpus.Core.OutputSVG   , module Wumpus.Core.Picture   , module Wumpus.Core.PtSize-  , module Wumpus.Core.TextEncoder-  , module Wumpus.Core.TextLatin1-  , module Wumpus.Core.TextSymbolFont+  , module Wumpus.Core.Text.Encoder+  , module Wumpus.Core.Text.Latin1+  , module Wumpus.Core.Text.SymbolFont   , module Wumpus.Core.VersionNumber   , module Wumpus.Core.WumpusTypes @@ -52,14 +52,14 @@                                    cyan, magenta ) import Wumpus.Core.FontSize hiding ( textBoundsEnc ) import Wumpus.Core.Geometry-import Wumpus.Core.GraphicsState hiding ( GraphicsState )+import Wumpus.Core.GraphicProps import Wumpus.Core.OutputPostScript import Wumpus.Core.OutputSVG import Wumpus.Core.Picture import Wumpus.Core.PtSize-import Wumpus.Core.TextEncoder-import Wumpus.Core.TextLatin1-import Wumpus.Core.TextSymbolFont+import Wumpus.Core.Text.Encoder+import Wumpus.Core.Text.Latin1+import Wumpus.Core.Text.SymbolFont import Wumpus.Core.VersionNumber import Wumpus.Core.WumpusTypes 
src/Wumpus/Core/AffineTrans.hs view
@@ -18,23 +18,30 @@ -- The common affine transformations represented as type classes - -- scaling, rotation, translation. ----- Internally, when a picture is composed and transformed, Wumpus+--+-- 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  -- PostScript or SVG for final rendering. This is because Wumpus  -- has no access to the paths that make fonts so cannot transform  -- them directly. ----- As well as Pictures, some elements - e.g. Vectors, Points and --- BoundingBoxes - are also instances of the affine classes. The--- implementation of the instances considers that under --- transformation these objects are implicitly within the standard --- affine frame (origin at point zero and unit basis vectors for --- the horizontal and vertical). +-- Other elements - Vectors, Points, BoundingBoxes and Primtives - +-- are also instances of the affine classes. However, generally +-- Wumpus transforms these elements directly rather than +-- delegating the transformation to PostScript or SVG (the +-- situation for the Label primitive is more complicated - the +-- /start/ point is transformed by Wumpus but a matrix +-- transformation is sent to PostScript to manipulate the opaque +-- character objects). ----- This assumption cannot hold for primitives because text is --- special in PostScript and SVG, so there are no instances of --- the affine classes for Primitive or PrimElement.+-- Note - transformations on Primitives are applied to the control +-- points of the primitive not the /drawing/. A scaled, stroked +-- path will be drawn with at the standard line width rather than +-- with a thicker line. Also, text may not render pleasantly after +-- it has been transformed, PostScript references seem to caution +-- against transforming text and recommend changing @/scalefont@ +-- instead of scaling via a transfomation.  --  -- To generate efficient PostScript, Wumpus relies on the matrix -- representations of the affine transformations being invertible.
src/Wumpus/Core/BoundingBox.hs view
@@ -15,7 +15,11 @@ -- -- Empty pictures cannot be created with Wumpus. This greatly  -- simplifies the implementation of pictures and bounding boxes.+--+-- Note - some of the functions exposed by this module are +-- expected to be pertinent only to Wumpus-Core itself. -- +--  --------------------------------------------------------------------------------  module Wumpus.Core.BoundingBox @@ -45,21 +49,21 @@   ) where  import Wumpus.Core.AffineTrans-import Wumpus.Core.FormatCombinators import Wumpus.Core.Geometry-import Wumpus.Core.Utils ( PSUnit(..) )--import Data.Semigroup                               -- package: algebra-+import Wumpus.Core.Utils.Common ( PSUnit(..) )+import Wumpus.Core.Utils.FormatCombinators   -- | Bounding box of a picture, represented by the lower left and -- upper right corners. --  -- We cannot construct empty pictures - so bounding boxes are --- spared the obligation to be /empty/. BoundingBox is an instance--- of the Semigroup class where @append@ is the union operation.+-- spared the obligation to be /empty/.  -- +-- BoundingBox operates as a semigroup where @boundaryUnion@ is the+-- addition.+-- +--  data BoundingBox u = BBox        { ll_corner :: Point2 u       , ur_corner :: Point2 u @@ -73,12 +77,8 @@ -------------------------------------------------------------------------------- -- instances --- BBox is NOT monoidal - it\'s much simpler that way. -instance Ord u => Semigroup (BoundingBox u) where-  append = boundaryUnion - instance PSUnit u => Format (BoundingBox u) where   format (BBox p0 p1) = parens (text "BBox" <+> text "ll=" <> format p0                                              <+> text "ur=" <> format p1) @@ -124,7 +124,9 @@  -------------------------------------------------------------------------------- --- | Contruct a bounding box, vis the BBox constructor with range +-- | 'bbox' : @lower_left_corner * upper_right_corner -> BoundingBox@+--+-- Contruct a bounding box, vis the BBox constructor with range  -- checking on the corner points. -- -- @bbox@ throws an error if the width or height of the @@ -136,25 +138,28 @@    | otherwise            = error "Wumpus.Core.BoundingBox.bbox - malformed."  --- | Create a BoundingBox with bottom left corner at the origin,+-- | 'obbox' : @width * height -> BoundingBox@+--+-- Create a BoundingBox with bottom left corner at the origin, -- and dimensions @w@ and @h@. -- obbox :: Num u => u -> u -> BoundingBox u obbox w h = BBox zeroPt (P2 w h) --- | Destructor for BoundingBox.+-- | 'destBoundingBox' : @ bbox -> (lower_left_x, lower_lefy_y, +--      upper_right_x, upper_right_y)@ ----- Assembles a four-tuple @ (ll_x, ll_y, ur_x, ur_y) @.+-- Destructor for BoundingBox, assembles a four-tuple of the x +-- and y values of the corner points. -- --- Arguably this is easier to pattern match upon as it removes a +-- Arguably this is easier to pattern match upon, as it removes a  -- layer of nesting. -- destBoundingBox :: BoundingBox u -> (u,u,u,u) destBoundingBox (BBox (P2 llx lly) (P2 urx ury)) = (llx, lly, urx, ury)   --- | The union of two bounding boxes. This is also the @append@ --- of BoundingBox\'s @Semigroup@ instance.+-- | The union of two bounding boxes.  -- boundaryUnion :: Ord u => BoundingBox u -> BoundingBox u -> BoundingBox u BBox ll ur `boundaryUnion` BBox ll' ur' = BBox (minPt ll ll') (maxPt ur ur')@@ -184,8 +189,12 @@     fromCorners (bl,br,tr,tl) = [bl,br,tr,tl]  --- | Generate all the corners of a bounding box, counter-clock +-- | 'boundaryCorners' : @bbox -> (bottom_left, bottm_right,+--      top_right, top_left)@+-- +-- Generate all the corners of a bounding box, counter-clock  -- wise from the bottom left, i.e. @(bl, br, tr, tl)@.+-- boundaryCorners :: BoundingBox u -> (Point2 u, Point2 u, Point2 u, Point2 u) boundaryCorners (BBox bl@(P2 x0 y0) tr@(P2 x1 y1)) = (bl, br, tr, tl) where     br = P2 x1 y0
src/Wumpus/Core/Colour.hs view
@@ -18,7 +18,8 @@ -- @Wumpus.Core.Colour@ directly to use them. -- -- PostScript has no support for RGB-alpha and hence does not--- transparency. Thus Wumpus in turn cannot support transparency.+-- support transparency. Thus Wumpus in turn cannot support +-- transparency. -- -------------------------------------------------------------------------------- @@ -41,7 +42,7 @@        ) where -import Wumpus.Core.FormatCombinators+import Wumpus.Core.Utils.FormatCombinators  import Data.Word 
src/Wumpus/Core/FontSize.hs view
@@ -19,10 +19,10 @@ -- of the text). --  -- This is a deficiency of Wumpus, and limits its text handling--- capabilities - for example, text cannot be reliably centered--- as its true length is not known. However, more powerful --- alternatives would need access to the metrics embedded within--- font files. This would require a font loader and add +-- capabilities - for example, text cannot be reliably centered +-- or right aligned as its true length is not known. However, more +-- powerful alternatives would need access to the metrics embedded +-- within font files. This would require a font loader and add  -- significant implementation complexity. --  --------------------------------------------------------------------------------@@ -62,7 +62,7 @@ import Wumpus.Core.BoundingBox import Wumpus.Core.Geometry import Wumpus.Core.PtSize-import Wumpus.Core.TextInternal+import Wumpus.Core.Text.TextInternal  import Data.AffineSpace                 -- package: vector-space @@ -153,9 +153,10 @@ courier48_spacer_width = 3.0  --- | Width of the supplied string when printed at 48pt.+-- | Width of the supplied string when printed at 48pt (i.e. n +-- chars + (n-1) spacers). ----- (i.e. n chars + (n-1) spacers)+-- Use 'charCount' to calculate the @CharCount@. -- widthAt48pt :: CharCount -> PtSize widthAt48pt n = (courier48_width * len) + (courier48_spacer_width * len_sub)@@ -183,7 +184,8 @@ -- problems (this a current deficiency of Wumpus). -- textWidth :: FontSize -> CharCount -> PtSize-textWidth sz n = (fromIntegral sz)/48 * widthAt48pt n+textWidth _  n | n <= 0 = 0+textWidth sz n          = (fromIntegral sz)/48 * widthAt48pt n   -- | Text height is just identity/double-coercion of the Point size.@@ -211,10 +213,12 @@ descenderDepth :: FontSize -> PtSize descenderDepth sz = (fromIntegral sz) / 48 * courier48_descender_depth --- | Find the bounding box for the character count at the +-- | 'textBounds' : @ font_size * baseline_left * text -> BBox@+--+-- Find the bounding box for the character count at the  -- supplied font-size. -- --- The supplied point represents the bottom left corner of the +-- The supplied point represents the baseline left corner of the  -- a regular upper-case letter (that is without descenders). -- The bounding box will always be /dropped/ to accommodate  -- ascenders - no interpretation of the string takes place to @@ -229,8 +233,10 @@ textBounds sz pt ss = textBoundsBody sz pt (charCount ss)   --- | Version of textBounds for EncodedText.+-- | 'textBoundsEnc' : @ font_size * baseline_left * encoded_text -> BBox@ -- +--  Version of textBounds for EncodedText.+--  -- Note this function is hidded by the top-level module  -- @Wumpus.Core@. --@@ -241,12 +247,12 @@  textBoundsBody :: (Num u, Ord u, FromPtSize u)                 => FontSize -> Point2 u -> Int -> BoundingBox u-textBoundsBody sz body_bl len = bbox bl tr +textBoundsBody sz baseline_left len = bbox bl tr    where     h           = fromPtSize $ textHeight sz     w           = fromPtSize $ textWidth  sz len     dd          = fromPtSize $ descenderDepth sz-    bl          = body_bl .-^ V2 0 dd +    bl          = baseline_left .-^ V2 0 dd      tr          = bl .+^ V2 w h  
− src/Wumpus/Core/FormatCombinators.hs
@@ -1,384 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module      :  Wumpus.Core.FormatCombinators--- Copyright   :  (c) Stephen Tetley 2010--- License     :  BSD3------ Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>--- Stability   :  highly unstable--- Portability :  GHC------ Formatting combinators - pretty printers without the fitting.--------------------------------------------------------------------------------------module Wumpus.Core.FormatCombinators-  (-    Doc-  , DocS-  , Format(..)-  , empty-  , showsDoc-  , (<>)-  , (<+>)  -  , vconcat-  , separate-  , hcat-  , hsep-  , vcat--  , text-  , char-  , int-  , integer-  , integral-  , float-  , double--  , space-  , comma-  , semicolon-  , line--  , fill--  , punctuate-  , enclose-  , squotes-  , dquotes-  , parens-  , brackets-  , braces-  , angles--  , lparen-  , rparen-  , lbracket-  , rbracket-  , lbrace-  , rbrace-  , langle-  , rangle--  , list-  , tupled-  , semiBraces--  , indent-    -  ) where--import Data.Monoid-import Numeric---- | Doc is a Join List ...----data Doc = Doc1   ShowS -         | Join   Doc   Doc-         | Line-         | Indent !Int  Doc ---type DocS = Doc -> Doc----- Join could be improved...----unDoc :: Doc -> ShowS-unDoc = step 0 id-  where-   step _ acc (Doc1 sf)    = acc . sf-   step n acc (Join a b)   = let acc' = step n acc a in step n acc' b-   step n acc Line         = acc . showChar '\n' . indentS n-   step n acc (Indent i d) = step (n+i) (acc . (indentS i)) d---indentS :: Int -> ShowS-indentS i | i < 1     = id-          | otherwise = showString $ replicate i ' '--runDoc :: Doc -> String-runDoc = ($ "") . unDoc---instance Show Doc where-  show = runDoc--instance Monoid Doc where-  mempty = empty-  mappend = (<>)---class Format a where format :: a -> Doc-----------------------------------------------------------------------------------        -infixr 6 <>, <+>------ | Create an empty, zero length document.----empty :: Doc-empty = Doc1 id---- | Create a document from a ShowS function.----showsDoc :: ShowS -> Doc-showsDoc = Doc1----- | Horizontally concatenate two documents with no space --- between them.--- -(<>) :: Doc -> Doc -> Doc-a <> b = Join a b ----- | Horizontally concatenate two documents with a single space --- between them.--- -(<+>) :: Doc -> Doc -> Doc-a <+> b = Join a (Join space b)---- | Vertical concatenate two documents with a line break.--- -vconcat :: Doc -> Doc -> Doc-vconcat a b = a <> Line <> b----separate :: Doc -> [Doc] -> Doc-separate _   []     = empty-separate sep (a:as) = step a as-  where-    step acc []     = acc-    step acc (x:xs) = step (acc <> sep <> x) xs---- | Horizontally concatenate a list of documents with @(\<\>)@.----hcat :: [Doc] -> Doc-hcat = foldr (<>) empty---- | Horizontally concatenate a list of documents with @(\<+\>)@.----hsep :: [Doc] -> Doc-hsep = separate space---- | Vertically concatenate a list of documents, with a line --- break between each doc.----vcat :: [Doc] -> Doc-vcat []     = empty-vcat (x:xs) = step x xs -  where-    step acc (z:zs) = step (acc `vconcat` z) zs-    step acc []     = acc---- | Create a document from a literal string.--- --- The string should not contain newlines (though this is not --- enforced). ----text :: String -> Doc-text = Doc1 . showString----- | Create a document from a literal character.------ The char should not be a tab or newline. ----char :: Char -> Doc-char = Doc1 . showChar---- | Show the Int as a Doc.------ > int  = text . show----int :: Int -> Doc-int  = Doc1 . showInt---- | Show the Integer as a Doc.----integer :: Integer -> Doc-integer = Doc1 . showInt---- | Show an \"integral value\" as a Doc via 'fromIntegral'.----integral :: Integral a => a -> Doc-integral = Doc1 . showInt---- | Show the Float as a Doc.----float :: Double -> Doc-float = Doc1 . showFloat---- | Show the Double as a Doc.----double :: Double -> Doc-double = Doc1 . showFloat- --- | Create a Doc containing a single space character.----space :: Doc-space = char ' '---- | Create a Doc containing a comma, \",\".----comma :: Doc-comma = char ','---- | Create a Doc containing a semi colon, \";\".----semicolon :: Doc-semicolon = char ';'---- | Create a Doc containing newline, \"\\n\".----line :: Doc -line = char '\n'--------------------------------------------------------------------------------------- | Fill a doc to the supplied length, padding the right-hand--- side with spaces.------ Note - this function is expensive - it unrolls the functional--- representation of the String. --- --- Also it should only be used for single line Doc\'s.--- -fill :: Int -> Doc -> Doc-fill i d = Doc1 (padr i ' ' $ unDoc d) --padr :: Int -> Char -> ShowS -> ShowS-padr i c df = step (length $ df []) -  where-    step len | len >= i  = df-             | otherwise = df . showString (replicate (i-len) c)-------------------------------------------------------------------------------------- | Punctuate the Doc list with the separator, producing a Doc. ----punctuate :: Doc -> [Doc] -> Doc-punctuate _ []     = empty-punctuate _ [x]    = x-punctuate s (x:xs) = x <> s <> punctuate s xs----- | Enclose the final Doc within the first two.------ There are no spaces between the documents:------ > enclose l r d = l <> d <> r----enclose :: Doc -> Doc -> Doc -> Doc-enclose l r d = l <> d <> r------ | Enclose the Doc within single quotes.----squotes :: Doc -> Doc-squotes = enclose (char '\'') (char '\'')---- | Enclose the Doc within double quotes.----dquotes :: Doc -> Doc-dquotes = enclose (char '"') (char '"')---- | Enclose the Doc within parens @()@.----parens :: Doc -> Doc-parens = enclose lparen rparen---- | Enclose the Doc within square brackets @[]@.----brackets :: Doc -> Doc-brackets = enclose lbracket rbracket---- | Enclose the Doc within curly braces @{}@.----braces :: Doc -> Doc-braces = enclose lbrace rbrace---- | Enclose the Doc within angle brackets @\<\>@.----angles :: Doc -> Doc-angles = enclose langle rangle------ | Create a Doc containing a left paren, \'(\'.----lparen :: Doc-lparen = char '('---- | Create a Doc containing a right paren, \')\'.----rparen :: Doc-rparen = char ')'---- | Create a Doc containing a left square bracket, \'[\'.----lbracket :: Doc-lbracket = char '['---- | Create a Doc containing a right square bracket, \']\'.----rbracket :: Doc-rbracket = char ']'---- | Create a Doc containing a left curly brace, \'{\'.----lbrace :: Doc-lbrace = char '{'---- | Create a Doc containing a right curly brace, \'}\'.----rbrace :: Doc-rbrace = char '}'---- | Create a Doc containing a left angle bracket, \'\<\'.----langle :: Doc-langle = char '<'---- | Create a Doc containing a right angle bracket, \'\>\'.----rangle :: Doc-rangle = char '>'---- | Comma separate the list of documents and enclose in square--- brackets.----list :: [Doc] -> Doc-list = brackets . punctuate comma---- | Comma separate the list of documents and enclose in parens.----tupled :: [Doc] -> Doc-tupled = parens . punctuate comma---- | Separate the list with a semicolon and enclose in curly --- braces.----semiBraces :: [Doc] -> Doc-semiBraces = braces . punctuate semicolon----- | Horizontally indent a Doc.------ Note - this space-prefixes the Doc on /the current line/. It--- does not indent subsequent lines if the Doc spans multiple --- lines.----indent :: Int -> Doc -> Doc-indent i d | i < 1     = d-           | otherwise = Indent i d--
src/Wumpus/Core/Geometry.hs view
@@ -76,14 +76,15 @@   , r2d   , circularModulo +  -- * Bezier curves   , bezierArc   , bezierCircle    ) where  -import Wumpus.Core.FormatCombinators-import Wumpus.Core.Utils+import Wumpus.Core.Utils.Common+import Wumpus.Core.Utils.FormatCombinators  import Data.AffineSpace                         -- package: vector-space import Data.VectorSpace@@ -411,7 +412,7 @@ -------------------------------------------------------------------------------- -- Points --- | Construct a point at 0 0.+-- | Construct a point at (0,0). -- zeroPt :: Num u => Point2 u zeroPt = P2 0 0@@ -640,7 +641,7 @@ r2d = (*) (180/pi) . fromRadian  --- | Modulate a (positive) angle to be in the range 0..2*pi+-- | Modulo a (positive) angle into the range @0..2*pi@. -- circularModulo :: Radian -> Radian circularModulo r = d2r $ dec + (fromIntegral $ i `mod` 360)@@ -655,7 +656,10 @@ -------------------------------------------------------------------------------- -- Bezier curves --- | Create an arc - this construction is the analogue of +-- | 'bezierArc' : @ radius * ang1 * ang2 * center -> +--       (start_point, control_point1, control_point2, end_point) @+-- +-- Create an arc - this construction is the analogue of  -- PostScript\'s @arc@ command, but the arc is created as a  -- Bezier curve so it should span less than 90deg. --@@ -674,7 +678,9 @@     p3    = pt .+^ avec ang2 r  --- | Make a circle from Bezier curves - @n@ is the number of +-- | 'bezierCircle' : @ n * radius * center -> [Point] @ +-- +-- Make a circle from Bezier curves - @n@ is the number of  -- subdivsions per quadrant. -- bezierCircle :: (Fractional u, Floating u) 
+ src/Wumpus/Core/GraphicProps.hs view
@@ -0,0 +1,224 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Core.GraphicProps+-- Copyright   :  (c) Stephen Tetley 2009-2010+-- License     :  BSD3+--+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable+-- Portability :  GHC+--+-- Data types for stroke and label styles corresponding to the+-- styles provided by PostScript / SVG (@StrokeAttr@, etc.).+--+-- Data types for annotating Primitives with their drawing style+-- (@PathProps@, etc.). Wumpus represents pictures as trees and+-- decorates all elements (paths, text-labels) with their drawing+-- style. This is boardly similar to how SVG handles attributes. +-- For PostScript output, Wumpus renders attribute changes as +-- graphics state updates. +--   +--------------------------------------------------------------------------------+++module Wumpus.Core.GraphicProps+  (+  +  -- * Stroke attributes+    StrokeAttr(..)+  , LineCap(..)+  , LineJoin(..)+  , DashPattern(..)++  -- * Font attributes+  , FontAttr(..)+  , FontFace(..)+  , SVGFontStyle(..)+++  -- * Drawing styles for Primitives+  , PathProps(..)+  , LabelProps(..)+  , EllipseProps(..)++  -- * Defaults+  , default_stroke_attr+  , defaultFont+  , wumpus_default_font++  ) where++import Wumpus.Core.Colour+import Wumpus.Core.Text.Encoder+import Wumpus.Core.Text.Latin1+import Wumpus.Core.Utils.FormatCombinators++++-- | Stroke attributes for drawing paths.+--+data StrokeAttr = StrokeAttr+      { line_width      :: Double+      , miter_limit     :: Double+      , line_cap        :: LineCap+      , line_join       :: LineJoin+      , dash_pattern    :: DashPattern+      }+  deriving (Eq,Show)++++-- | Line cap - default in output is butt.+--+data LineCap = CapButt | CapRound | CapSquare+  deriving (Enum,Eq,Show)++-- | Line join - default in output is miter.+--+data LineJoin = JoinMiter | JoinRound | JoinBevel+  deriving (Enum,Eq,Show)++-- | Dash pattern - either a solid line or a list of on-off pairs+-- together with an /offset/ into the dashes.+--+data DashPattern = Solid | Dash Int [(Int,Int)]+  deriving (Eq,Show)+++-- | Font face and size. Equivalent fonts have different names+-- in PostScript and SVG. A PostScript font name includes the +-- font style (e.g. @Times-BoldItalic@) whereas an SVG font has +-- a name (the @font-family@ attribute) and a style.+--+-- For PostScript, the following fonts are expected to exist on +-- most platforms:+--+-- > Times-Roman  Times-Italic  Times-Bold  Times-BoldOtalic+-- > Helvetica  Helvetica-Oblique  Helvetica-Bold  Helvetica-Bold-Oblique+-- > Courier  Courier-Oblique  Courier-Bold  Courier-Bold-Oblique+-- > Symbol+--+-- See the PostScript Language Reference Manual.+--+data FontAttr = FontAttr +      { font_size       :: Int +      , font_face       :: FontFace+      }+  deriving (Eq,Ord,Show)++-- | 'FontFace' : @ postscript_name * svg_font_family * svg_font_style @+--+data FontFace = FontFace+      { font_name       :: String        -- for PostScript+      , svg_font_family :: String        -- for SVG+      , svg_font_style  :: SVGFontStyle+      , font_enc_name   :: FontEncoderName+      }+  deriving (Eq,Ord,Show)++++-- | SVG font styles - potentially a style may generate both+-- @font-weight@ and @font-style@ attributes in the SVG output.+--+data SVGFontStyle = SVG_REGULAR | SVG_BOLD | SVG_ITALIC | SVG_BOLD_ITALIC+                  | SVG_OBLIQUE | SVG_BOLD_OBLIQUE+  deriving (Eq,Ord,Show)+++--------------------------------------------------------------------------------++-- | Note when drawn /filled/ and drawn /stroked/ the same+-- polygon will have (slightly) different size:+--+-- * A filled shape fills /within/ the boundary of the shape+--+-- * A stroked shape draws a pen line around the boundary+--   of the shape. The actual size depends on the thickness+--   of the line (stroke width).+--+data PathProps = CFill RGBi +               | CStroke StrokeAttr RGBi+               | OStroke StrokeAttr RGBi+               -- Note - first colour fill, second colur stroke.+               | CFillStroke RGBi StrokeAttr RGBi+  deriving (Eq,Show)+++-- | Font rendering properties for a PrimLabel.+--+data LabelProps = LabelProps +      { label_colour    :: RGBi+      , label_font      :: FontAttr+      }+  deriving (Eq,Ord,Show)++++-- | Ellipses and circles are always closed.+--+data EllipseProps = EFill RGBi+                  | EStroke StrokeAttr RGBi +                  -- Note - first colour fill, second colour stroke.+                  | EFillStroke RGBi StrokeAttr RGBi +  deriving (Eq,Show)+++++--------------------------------------------------------------------------------++instance Format PathProps where+  format (CFill rgb)          = format rgb <+> text "Fill"+  format (CStroke _ rgb)      = format rgb <+> text "Closed-stroke"+  format (OStroke _ rgb)      = format rgb <+> text "Open-stroke"+  format (CFillStroke f _ s)  = format f <+> text "Fill" <> char '/'+                                         <+> format s <+> text "Stroke"   ++++instance Format LabelProps where+  format (LabelProps rgb attr) = format rgb +                             <+> text (font_name $ font_face attr)++instance Format EllipseProps where+  format (EFill rgb)          = format rgb <+> text "Fill"+  format (EStroke _ rgb)      = format rgb <+> text "Stroke"+  format (EFillStroke f _ s)  = format f <+> text "Fill" <> char '/'+                            <+> format s <+> text "Stroke"   ++--------------------------------------------------------------------------------+-- Defaults++-- | Default stroke attributes.+--+default_stroke_attr :: StrokeAttr+default_stroke_attr = StrokeAttr { line_width      = 1+                                 , miter_limit     = 1+                                 , line_cap        = CapButt+                                 , line_join       = JoinMiter+                                 , dash_pattern    = Solid+                                 }+++++-- | Constructor for the default font, which is @Courier@ (aliased +-- to @Courier New@ for SVG) at the supplied size.+--+defaultFont :: Int -> FontAttr+defaultFont sz = FontAttr sz face +  where+    face = FontFace { font_name         = "Courier"+                    , svg_font_family   = "Courier New"+                    , svg_font_style    = SVG_REGULAR+                    , font_enc_name     = latin1_font_encoder+                    }+++-- | Constant for the default font (@Courier@) at 14 point.+--+wumpus_default_font :: FontAttr+wumpus_default_font = defaultFont 14
− src/Wumpus/Core/GraphicsState.hs
@@ -1,166 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module      :  Wumpus.Core.GraphicsState--- Copyright   :  (c) Stephen Tetley 2009-2010--- License     :  BSD3------ Maintainer  :  stephen.tetley@gmail.com--- Stability   :  unstable--- Portability :  GHC------ Data types for stroke and label attributes. --- --- Wumpus represents pictures as trees - a leaf represents a --- path or text label. All attributes of a path or text label --- (colour, stroke width, font, ...) are stored in the leaf. So--- a picture is a leaf labelled tree.--- --- By contrast, PostScript maintains a global /graphics state/. A --- PostScript program is free to modify the graphics state --- anywhere in the program and subsequent elements are all drawn --- according to the modified graphics state. ------ When Wumpus renders Pictures as PostScript it maintains a --- limited graphics state with just current colour and current --- font. This is so Wumpus can avoid repeating @setrgbcolor@ and--- @findfont@ operations in the generated PostScript if --- subsequent elements share the same values.--- ---   ------------------------------------------------------------------------------------module Wumpus.Core.GraphicsState -  (-  -- * Data types  -    GraphicsState(..)-  -  -- ** Stroke attributes-  , StrokeAttr(..)-  , LineCap(..)-  , LineJoin(..)-  , DashPattern(..)--  -- ** Font-  , FontAttr(..)-  , FontFace(..)-  , SVGFontStyle(..)--  -- * Initial graphic state-  , zeroGS-  , default_stroke_attr--  ) where--import Wumpus.Core.Colour-import Wumpus.Core.TextEncoder-import Wumpus.Core.TextLatin1---- Graphics state datatypes---- | Graphics state used by the rendering monads.------ This type is hidden by the top-level module @Wumpus.Core@.----data GraphicsState = GraphicsState-      { gs_draw_colour  :: RGBi-      , gs_font_size    :: Int-      , gs_font_face    :: FontFace-      , gs_stroke_attr  :: StrokeAttr -      }-  deriving (Eq,Show)---- | Stroke attributes for drawing paths.----data StrokeAttr = StrokeAttr-      { line_width      :: Double-      , miter_limit     :: Double-      , line_cap        :: LineCap-      , line_join       :: LineJoin-      , dash_pattern    :: DashPattern-      }-  deriving (Eq,Show)------ | Line cap - default in output is butt.----data LineCap = CapButt | CapRound | CapSquare-  deriving (Enum,Eq,Show)---- | Line join - default in output is miter.----data LineJoin = JoinMiter | JoinRound | JoinBevel-  deriving (Enum,Eq,Show)---- | Dash pattern - either a solid line or a list of on-off pairs--- together with an /offset/ into the dashes.----data DashPattern = Solid | Dash Int [(Int,Int)]-  deriving (Eq,Show)----- | Font face and size. Equivalent fonts have different names--- in PostScript and SVG. A PostScript font name includes the --- font style (e.g. @Times-BoldItalic@) whereas an SVG font has --- a name (the @font-family@ attribute) and a style.------ For PostScript, the following fonts are expected to exist on --- most platforms:------ > Times-Roman  Times-Italic  Times-Bold  Times-BoldOtalic--- > Helvetica  Helvetica-Oblique  Helvetica-Bold  Helvetica-Bold-Oblique--- > Courier  Courier-Oblique  Courier-Bold  Courier-Bold-Oblique--- > Symbol------ See the PostScript Language Reference Manual.----data FontAttr = FontAttr -      { font_size       :: Int -      , font_face       :: FontFace-      }-  deriving (Eq,Ord,Show)---- | 'FontFace' : @ postscript_name * svg_font_family * svg_font_style @----data FontFace = FontFace-      { font_name       :: String        -- for PostScript-      , svg_font_family :: String        -- for SVG-      , svg_font_style  :: SVGFontStyle-      , font_enc_name   :: FontEncoderName-      }-  deriving (Eq,Ord,Show)------ | SVG font styles - potentially a style may generate both--- @font-weight@ and @font-style@ attributes in the SVG output.----data SVGFontStyle = SVG_REGULAR | SVG_BOLD | SVG_ITALIC | SVG_BOLD_ITALIC-                  | SVG_OBLIQUE | SVG_BOLD_OBLIQUE-  deriving (Eq,Ord,Show)----- | The initial graphics state--zeroGS ::  GraphicsState -zeroGS = GraphicsState { gs_draw_colour  = black-                       , gs_font_size    = (-1)-                       , gs_font_face    = unmatchable_face-                       , gs_stroke_attr  = default_stroke_attr-                       }-  where-    unmatchable_face = FontFace "DONT_MATCH" "" SVG_BOLD_OBLIQUE latin1_font_encoder----- | Default stroke attributes.----default_stroke_attr :: StrokeAttr-default_stroke_attr = StrokeAttr { line_width      = 1-                                 , miter_limit     = 1-                                 , line_cap        = CapButt-                                 , line_join       = JoinMiter-                                 , dash_pattern    = Solid-                                 }
− src/Wumpus/Core/OneList.hs
@@ -1,137 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module      :  Wumpus.Core.OneList--- Copyright   :  (c) Stephen Tetley 2009-2010--- License     :  BSD3------ Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>--- Stability   :  highly unstable--- Portability :  GHC------ Data type for non-empty lists.--- -----------------------------------------------------------------------------------module Wumpus.Core.OneList-  (-   -- OneMany-    OneList-  , ViewL(..)--  , one-  , cons-  , head-  , viewl--  , fromList--  , toListF-  , accumMapL-  , isOne-  , isMany-   -  ) where---import Data.Semigroup                           -- package: algebra--import Control.Applicative-import Data.Foldable-import Data.Monoid-import Data.Traversable--import Prelude hiding ( head )---data OneList a = One a | Many a (OneList a)-  deriving (Eq)--data ViewL a = OneL a | a :< (OneList a)-  deriving (Eq)--------------------------------------------------------------------------------------- Instances--instance Show a => Show (OneList a) where-  show = ('{':) . ($ []) . step where-     step (One a)     = shows a . showChar '}'-     step (Many a as) = shows a . showChar ',' . step as---instance Functor OneList where-  fmap f (One a)        = One $ f a-  fmap f (Many a as)    = Many (f a) (fmap f as)--instance Foldable OneList where-  foldMap f (One a)     = f a-  foldMap f (Many a as) = f a `mappend` foldMap f as--  foldr f b0 = step b0 where-    step b (One a)      = f a b-    step b (Many a as)  = f a (step b as)--  foldl f b0 = step b0 where-    step b (One a)      = f b a-    step b (Many a as)  = step (f b a) as---instance Traversable OneList where-  traverse f (One a)      = One  <$> f a-  traverse f (Many a as)  = Many <$> f a <*> traverse f as---instance Semigroup (OneList e) where-  (One a)     `append` bs  = Many a bs-  (Many a as) `append` bs  = Many a (as `append` bs)------------------------------------------------------------------------------------- | Construct One.-one :: a -> OneList a-one = One----- | Prepend an element. Obviously this transforms a One to a Many.-cons :: a -> OneList a -> OneList a-cons a as   = Many a as---- | 'head' is total of course.-head :: OneList a -> a-head (One a)    = a-head (Many a _) = a--viewl :: OneList a -> ViewL a-viewl (One a)     = OneL a-viewl (Many a as) = a :< as---- | Construct Many. Not this function throws a error if the list has--- zero or one elements-fromList :: [a] -> OneList a-fromList []     = error "OneList.fromList: cannot build Many from empty list"-fromList [a]    = One a-fromList (a:as) = Many a (fromList as)---toListF :: (a -> b) -> OneList a -> [b]-toListF f = step where-  step (One x)     = [f x]-  step (Many x xs) = f x : step xs---accumMapL :: (x -> st -> (y,st)) -> OneList x -> st -> (OneList y,st)-accumMapL f (One x)     st = let (y,st') = f x st in (One y,st')-accumMapL f (Many x xs) st = (Many y ys,st'')-                             where (y, st')  = f x st-                                   (ys,st'') = accumMapL f xs st'--isMany :: OneList a -> Bool-isMany (Many _ _) = True-isMany _          = False--isOne :: OneList a -> Bool-isOne (One _)     = True-isOne _           = False-
src/Wumpus/Core/OutputPostScript.hs view
@@ -29,17 +29,19 @@  import Wumpus.Core.BoundingBox import Wumpus.Core.Colour-import Wumpus.Core.FormatCombinators import Wumpus.Core.Geometry-import Wumpus.Core.GraphicsState-import Wumpus.Core.OneList+import Wumpus.Core.GraphicProps import Wumpus.Core.PictureInternal import Wumpus.Core.PostScriptDoc-import Wumpus.Core.TextDefaultEncoder-import Wumpus.Core.TextEncoder-import Wumpus.Core.TextInternal-import Wumpus.Core.Utils+import Wumpus.Core.Text.DefaultEncoder+import Wumpus.Core.Text.Encoder+import Wumpus.Core.Text.TextInternal+import Wumpus.Core.TrafoInternal+import Wumpus.Core.Utils.Common+import Wumpus.Core.Utils.OneList+import Wumpus.Core.Utils.FormatCombinators + import Control.Applicative hiding ( empty, some ) import Control.Monad @@ -161,6 +163,11 @@ -- | Output a series of pictures to a Postscript file. Each  -- picture will be printed on a separate page.  --+-- Generally an encoder should always support the principal+-- encoders for the fonts used (e.g. Latin1) /and/ the encoder +-- for the Symbol font, as characters from the Symbol font may +-- be used as decorations for plot marks, etc.+-- writePS :: (Real u, Floating u, PSUnit u)          => FilePath -> TextEncoder -> [Picture u] -> IO () writePS filepath enc pic = @@ -170,14 +177,24 @@ -- The .eps file can then be imported or embedded in another  -- document. --+-- Generally an encoder should always support the principal+-- encoders for the fonts used (e.g. Latin1) /and/ the encoder for+-- the Symbol font, as characters from the Symbol font may be used +-- as decorations for plot marks, etc.+-- writeEPS :: (Real u, Floating u, PSUnit u)            => FilePath -> TextEncoder -> Picture u -> IO () writeEPS filepath enc pic =     getZonedTime >>= \ztim -> writeFile filepath (show $ epsDraw ztim enc pic)  --- | Version of 'writePS' - using Latin1 encoding.+-- | Version of 'writePS' - using the /default encoder/ which +-- supports Latin1 and the Symbol font. -- +-- Generally an encoder should always support the principal+-- encoder (e.g. Latin1) /and/ the Symbol font, as characters from+-- the Symbol font may be used as decorations for plot marks, etc.+--  writePS_latin1 :: (Real u, Floating u, PSUnit u)                 => FilePath -> [Picture u] -> IO () writePS_latin1 filepath = writePS filepath defaultEncoder@@ -260,7 +277,7 @@ -- state.  -- picture :: (Real u, Floating u, PSUnit u) => Picture u -> PsMonad Doc-picture (Leaf    (_,xs) ones)   = bracketTrafos xs $ oneConcat primElement ones+picture (Leaf    (_,xs) ones)   = bracketTrafos xs $ oneConcat primitive ones picture (Picture (_,xs) ones)   = bracketTrafos xs $ oneConcat picture ones picture (Group   (_,xs) _ pic) = bracketTrafos xs (picture pic) picture (Clip    (_,xs) cp pic) = bracketTrafos xs $@@ -281,14 +298,12 @@  -- No action is taken for hyperlinks in PostScript. ---primElement :: (Real u, Floating u, PSUnit u) => PrimElement u -> PsMonad Doc-primElement (Atom prim)         = primitive prim-primElement (XLinkGroup _ ones) = oneConcat primElement ones  primitive :: (Real u, Floating u, PSUnit u) => Primitive u -> PsMonad Doc primitive (PPath props pp)     = primPath props pp primitive (PLabel props lbl)   = primLabel props lbl primitive (PEllipse props ell) = primEllipse props ell+primitive (PGroup _ ones)      = oneConcat primitive ones   primPath :: PSUnit u
src/Wumpus/Core/OutputSVG.hs view
@@ -38,17 +38,18 @@  import Wumpus.Core.BoundingBox import Wumpus.Core.Colour-import Wumpus.Core.FormatCombinators import Wumpus.Core.Geometry-import Wumpus.Core.GraphicsState-import Wumpus.Core.OneList+import Wumpus.Core.GraphicProps import Wumpus.Core.PageTranslation import Wumpus.Core.PictureInternal import Wumpus.Core.SVGDoc-import Wumpus.Core.TextDefaultEncoder-import Wumpus.Core.TextEncoder-import Wumpus.Core.TextInternal-import Wumpus.Core.Utils+import Wumpus.Core.Text.DefaultEncoder+import Wumpus.Core.Text.Encoder+import Wumpus.Core.Text.TextInternal+import Wumpus.Core.TrafoInternal+import Wumpus.Core.Utils.Common+import Wumpus.Core.Utils.FormatCombinators+import Wumpus.Core.Utils.OneList  import Control.Applicative hiding ( empty, some ) import Data.Maybe@@ -132,13 +133,23 @@  -- | Output a picture to a SVG file.  --+-- Generally an encoder should always support the principal+-- encoders for the fonts used (e.g. Latin1) /and/ the encoder for+-- the Symbol font, as characters from the Symbol font may be used +-- as decorations for plot marks, etc.+-- writeSVG :: (Real u, Floating u, PSUnit u)           => FilePath -> TextEncoder -> Picture u -> IO () writeSVG filepath enc pic =      writeFile filepath $ show $ svgDraw enc pic  --- | Version of 'writeSVG' - using Latin1 and Symbol font encodings. +-- | Version of 'writeSVG' - using Latin1 and Symbol font encoders.  --+-- Generally an encoder should always support the principal+-- encoders for the fonts used (e.g. Latin1) /and/ the encoder for +-- the Symbol font, as characters from the Symbol font may be used +-- as decorations for plot marks, etc.+-- writeSVG_latin1 :: (Real u, Floating u, PSUnit u)                  => FilePath -> Picture u -> IO () writeSVG_latin1 filepath = writeSVG filepath defaultEncoder@@ -170,7 +181,7 @@   picture :: (Real u, Floating u, PSUnit u) => Picture u -> SvgMonad Doc-picture (Leaf    (_,xs) ones)   = bracketTrafos xs $ oneConcat primElement ones+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@@ -193,14 +204,14 @@     instep ac (e :< rest) = fn e >>= \a -> instep (ac `vconcat` a) (viewl rest)  -primElement :: (Real u, Floating u, PSUnit u) => PrimElement u -> SvgMonad Doc-primElement (Atom prim)          = primitive prim-primElement (XLinkGroup xl ones) = drawXLink xl <$> oneConcat primElement ones- primitive :: (Real u, Floating u, PSUnit u) => Primitive u -> SvgMonad Doc primitive (PPath props pp)     = primPath props pp primitive (PLabel props lbl)   = primLabel props lbl primitive (PEllipse props ell) = primEllipse props ell+primitive (PGroup mb ones)     = +    case mb of+      Nothing -> oneConcat primitive ones+      Just xl -> drawXLink xl <$> oneConcat primitive ones    drawXLink :: XLink -> Doc -> Doc
src/Wumpus/Core/PageTranslation.hs view
@@ -12,6 +12,11 @@ -- -- Core page translation for SVG. --+-- Note - initially an optimized translate was planned - smaller +-- SVG code size and less use of /rectifying/ transformations for +-- text. However working out a translation scheme proved to be +-- tricky and Wumpus is stuck with the /trivialTransformation/.+-- --------------------------------------------------------------------------------  @@ -24,7 +29,7 @@  import Wumpus.Core.AffineTrans import Wumpus.Core.PictureInternal-+import Wumpus.Core.TrafoInternal   --------------------------------------------------------------------------------@@ -39,19 +44,16 @@ trivialTranslation pic = scale 1 (-1) (trivPic pic)  trivPic :: Num u => Picture u -> Picture u-trivPic (Leaf lc ones)      = Leaf lc $ fmap trivPrimElt ones+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 trivPic (Group lc upd pic)  = Group lc upd $ trivPic pic -trivPrimElt :: Num u => PrimElement u -> PrimElement u-trivPrimElt (Atom prim)          = Atom (trivPrim prim)-trivPrimElt (XLinkGroup xl ones) = XLinkGroup xl $ fmap trivPrimElt ones- trivPrim :: Num u => Primitive u -> Primitive u trivPrim (PPath a pp)     = PPath a pp trivPrim (PLabel a lbl)   = PLabel a (trivLabel lbl) trivPrim (PEllipse a ell) = PEllipse a (trivEllipse ell)+trivPrim (PGroup xl ones) = PGroup xl $ fmap trivPrim ones   trivLabel :: Num u => PrimLabel u -> PrimLabel u
src/Wumpus/Core/Picture.hs view
@@ -31,7 +31,7 @@   , curvedPath   , xlinkhref   , xlinkGroup-+  , primGroup    -- * Constructing primitives   , ostroke@@ -46,8 +46,8 @@   , clip    , textlabel+  , rtextlabel   , ztextlabel-  , wumpus_default_font    , hkernlabel   , vkernlabel@@ -56,10 +56,12 @@   , kernEscName    , strokeEllipse+  , rstrokeEllipse   , fillEllipse+  , rfillEllipse   , zellipse   , fillStrokeEllipse-  +  , rfillStrokeEllipse      -- * Operations   , extendBoundary  @@ -80,22 +82,20 @@ import Wumpus.Core.AffineTrans import Wumpus.Core.BoundingBox import Wumpus.Core.Colour-import Wumpus.Core.FormatCombinators hiding ( fill ) import Wumpus.Core.Geometry-import Wumpus.Core.GraphicsState-import Wumpus.Core.OneList+import Wumpus.Core.GraphicProps import Wumpus.Core.PictureInternal import Wumpus.Core.PtSize-import Wumpus.Core.TextInternal-import Wumpus.Core.TextLatin1-import Wumpus.Core.Utils+import Wumpus.Core.Text.TextInternal+import Wumpus.Core.TrafoInternal+import Wumpus.Core.Utils.Common+import Wumpus.Core.Utils.FormatCombinators hiding ( fill )+import Wumpus.Core.Utils.OneList  import Data.AffineSpace                         -- package: vector-space-import Data.Semigroup                           -- package: algebra   - -------------------------------------------------------------------------------- -- Construction @@ -109,13 +109,13 @@ -- -- This function throws an error when supplied the empty list. ---frame :: (Real u, Floating u, FromPtSize u) => [PrimElement u] -> Picture u+frame :: (Real u, Floating u, FromPtSize u) => [Primitive u] -> Picture u frame []     = error "Wumpus.Core.Picture.frame - empty list" frame (p:ps) = let (bb,ones) = step p ps in Leaf (bb,[]) ones    where     step a []     = (boundary a, one a)     step a (x:xs) = let (bb', rest) = step x xs-                    in ( boundary a `append` bb', cons a rest )+                    in ( boundary a `boundaryUnion` bb', cons a rest )   @@ -129,7 +129,7 @@   where     step a []     = (boundary a, one a)     step a (x:xs) = let (bb', rest) = step x xs-                    in ( boundary a `append` bb', cons a rest )+                    in ( boundary a `boundaryUnion` bb', cons a rest )   -- | Update the font /delta/ attributes for SVG output.@@ -169,13 +169,21 @@ path :: Point2 u -> [PrimPathSegment u] -> PrimPath u path = PrimPath  --- | Create a straight-line PathSegment.+-- | 'lineTo' : @ end_point -> path_segment @+-- +-- Create a straight-line PathSegment, the start point is +-- implicitly the previous point in a path. -- lineTo :: Point2 u -> PrimPathSegment u lineTo = PLineTo --- | Create a curved PathSegment.+-- | 'curveTo' : @ 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 -> PrimPathSegment u curveTo = PCurveTo @@ -210,55 +218,83 @@  -- | Create a hyperlinked group of Primitives. ---xlinkGroup :: XLink -> [PrimElement u] -> PrimElement u-xlinkGroup _     [] = error "Picture.xlinkGroup - empty prims list"-xlinkGroup xlink (x:xs) = XLinkGroup xlink (step x xs)+-- This function throws a runtime error when supplied with an+-- empty list.+-- +xlinkGroup :: XLink -> [Primitive u] -> Primitive u+xlinkGroup _     []     = error "Picture.xlinkGroup - empty prims list"+xlinkGroup xlink (x:xs) = PGroup (Just xlink) (step x xs)   where     step a []     = one a     step a (y:ys) = cons a (step y ys)  ++-- | Group a list of Primitives.+--+-- This function throws a runtime error when supplied with an+-- empty list.+--+primGroup :: [Primitive u] -> Primitive u+primGroup []     = error "Picture.primGroup - empty prims list"+primGroup (x:xs) = PGroup Nothing (step x xs)+  where+    step a []     = one a+    step a (y:ys) = cons a (step y ys) + -------------------------------------------------------------------------------- -- Take Paths to Primitives  -- *** Stroke --- | Create a open, stroked path.+-- | 'ostroke' : @ rgb * stroke_attr * path -> Primitive @ --+-- Create a open, stroked path.+-- ostroke :: Num u -        => RGBi -> StrokeAttr -> PrimPath u -> PrimElement u-ostroke rgb sa p = Atom $ PPath (OStroke sa rgb) p+        => RGBi -> StrokeAttr -> PrimPath u -> Primitive u+ostroke rgb sa p = PPath (OStroke sa rgb) p  --- | Create a closed, stroked path.+-- | 'cstroke' : @ rgb * stroke_attr * path -> Primitive @+-- +-- Create a closed, stroked path. -- cstroke :: Num u -        => RGBi -> StrokeAttr -> PrimPath u -> PrimElement u-cstroke rgb sa p = Atom $ PPath (CStroke sa rgb) p+        => RGBi -> StrokeAttr -> PrimPath u -> Primitive u+cstroke rgb sa p = PPath (CStroke sa rgb) p  --- | Create an open, stroked path using the default stroke +-- | 'zostroke' : @ path -> Primitive @+--+-- Create an open, stroked path using the default stroke  -- attributes and coloured black. ---zostroke :: Num u => PrimPath u -> PrimElement u+zostroke :: Num u => PrimPath u -> Primitive u zostroke = ostroke black default_stroke_attr  --- | Create a closed stroked path using the default stroke +-- | 'zcstroke' : @ path -> Primitive @+--+-- Create a closed stroked path using the default stroke  -- attributes and coloured black. ---zcstroke :: Num u => PrimPath u -> PrimElement u+zcstroke :: Num u => PrimPath u -> Primitive u zcstroke = cstroke black default_stroke_attr  -------------------------------------------------------------------------------- -- *** Fill  --- | Create a filled path.+-- | 'fill' : @ rgb * path -> Primitive @ ---fill :: Num u => RGBi -> PrimPath u -> PrimElement u-fill rgb p = Atom $ PPath (CFill rgb) p+--  Create a filled path.+--+fill :: Num u => RGBi -> PrimPath u -> Primitive u+fill rgb p = PPath (CFill rgb) p --- | Create a filled path coloured black. -zfill :: Num u => PrimPath u -> PrimElement u+-- | 'zfill' : @ path -> Primitive @+--+-- Create a filled path coloured black. +zfill :: Num u => PrimPath u -> Primitive u zfill = fill black  @@ -266,14 +302,14 @@ -- Filled and stroked (closed) paths  --- | Create a closed path that is both filled and stroked (the fill--- is below in the zorder).+-- | 'fillStroke' : @ fill_rgb * stroke_attr * stroke_rgb * path -> Primitive @ ----- > fill colour * stroke attrs * stroke_colour * ...+-- 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 -> PrimElement u-fillStroke frgb sa srgb p = Atom $ PPath (CFillStroke frgb sa srgb) p+        => RGBi -> StrokeAttr -> RGBi -> PrimPath u -> Primitive u+fillStroke frgb sa srgb p = PPath (CFillStroke frgb sa srgb) p   @@ -281,7 +317,9 @@ -------------------------------------------------------------------------------- -- Clipping  --- | Clip a picture with respect to the supplied path.+-- | 'clip' : @ path * picture -> Picture @+-- +-- Clip a picture 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@@ -289,7 +327,9 @@ -------------------------------------------------------------------------------- -- Labels to primitive --- | Create a text label. The string should not contain newline+-- | 'textlabel' : @ rgb * font_attr * string * baseline_left -> Primitive @+--+-- Create a text label. The string should not contain newline -- or tab characters. Also double-spaces should not be used - a  -- rendering agent for SVG will coalesce double-spaces into a  -- single space. For precise control of spacing and kerning use@@ -298,35 +338,40 @@ -- The supplied point is the left baseline. -- textlabel :: Num u -          => RGBi -> FontAttr -> String -> Point2 u -> PrimElement u-textlabel rgb attr txt pt = Atom $ PLabel (LabelProps rgb attr) lbl +          => RGBi -> FontAttr -> String -> Point2 u -> Primitive u+textlabel rgb attr txt pt = rtextlabel rgb attr txt 0 pt++-- | 'rtextlabel' : @ rgb * font_attr * string * rotation * +--      baseline_left -> Primitive @+--+-- Create a text label rotated by the supplied angle about the +-- baseline-left. +--+-- The supplied point is the left baseline.+--+rtextlabel :: Num u +           => RGBi -> FontAttr -> String -> Radian -> Point2 u -> Primitive u+rtextlabel rgb attr txt theta pt = PLabel (LabelProps rgb attr) lbl    where-    lbl = PrimLabel pt (StdLayout $ lexLabel txt) identityCTM+    lbl = PrimLabel pt (StdLayout $ lexLabel txt) (thetaCTM theta)  --- | Create a label where the font is @Courier@, text size is 14pt+-- | 'ztextlabel' : @ string * baseline_left -> Primitive @+--+-- Create a label where the font is @Courier@, text size is 14pt -- and colour is black. ---ztextlabel :: Num u => String -> Point2 u -> PrimElement u+ztextlabel :: Num u => String -> Point2 u -> Primitive u ztextlabel = textlabel black wumpus_default_font  --- | Constant for the default font, which is @Courier@ (aliased --- to @Courier New@ for SVG) at 14 point.-------wumpus_default_font :: FontAttr-wumpus_default_font = FontAttr 14 face -  where-    face = FontFace { font_name         = "Courier"-                    , svg_font_family   = "Courier New"-                    , svg_font_style    = SVG_REGULAR-                    , font_enc_name     = latin1_font_encoder-                    }  -------------------------------------------------------------------------------- --- | Create a text label with horizontal /kerning/ for each +-- | 'hkernlabel' : @ rgb * font_attr * kerning_chars * +--        baseline_left -> Primitive @+--+-- Create a text label with horizontal /kerning/ for each  -- character.  -- -- Note - kerning is relative to the left baseline of the @@ -351,14 +396,17 @@ -- hkernlabel :: Num u              => RGBi -> FontAttr -> [KerningChar u] -> Point2 u -            -> PrimElement u-hkernlabel rgb attr xs pt = Atom $ PLabel (LabelProps rgb attr) lbl +            -> Primitive u+hkernlabel rgb attr xs pt = PLabel (LabelProps rgb attr) lbl    where     lbl = PrimLabel pt (KernTextH xs) identityCTM   --- | Create a text label with vertical /kerning/ for each +-- | 'vkernlabel' : @ rgb * font_attr * kerning_chars * +--        baseline_left -> Primitive @+--+-- Create a text label with vertical /kerning/ for each  -- character - the text is expected to grow downwards.  -- -- Note - /kerning/ here is the measure between baselines of @@ -386,26 +434,34 @@ -- vkernlabel :: Num u              => RGBi -> FontAttr -> [KerningChar u] -> Point2 u -            -> PrimElement u-vkernlabel rgb attr xs pt = Atom $ PLabel (LabelProps rgb attr) lbl +            -> Primitive u+vkernlabel rgb attr xs pt = PLabel (LabelProps rgb attr) lbl    where     lbl = PrimLabel pt (KernTextV xs) identityCTM   --- | Construct a regular (i.e. non-special) Char along with its +-- | 'kernchar' : @ displacement * char -> KerningChar @+-- +-- 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 u c = (u, CharLiteral c) --- | Construct a Char by its character code along with its ++-- | 'kernEscInt' : @ displacement * char_code -> KerningChar @+-- +-- 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 u i = (u, CharEscInt i) --- | Construct a Char by its character name along with its ++-- | 'kernEscName' : @ displacement * char_name -> KerningChar @+-- +-- Construct a Char by its character name along with its  -- displacement from the left-baseline of the previous Char. -- kernEscName :: u -> String -> KerningChar u@@ -414,7 +470,9 @@ --------------------------------------------------------------------------------  --- | Create a stroked ellipse.+-- | 'strokeEllipse' : @ rgb * stroke_attr * rx * ry * center -> Primtive @+-- +-- Create a stroked ellipse. -- -- Note - within Wumpus, ellipses are considered an unfortunate -- but useful /optimization/. Drawing good cicles with Beziers @@ -431,37 +489,86 @@ -- Avoid non-uniform scaling stroked ellipses! -- strokeEllipse :: Num u -             => RGBi -> StrokeAttr -> u -> u -> Point2 u -> PrimElement u-strokeEllipse rgb sa hw hh pt = -    Atom $ PEllipse (EStroke sa rgb) (PrimEllipse pt hw hh identityCTM)+             => RGBi -> StrokeAttr -> u -> u -> Point2 u -> Primitive u+strokeEllipse rgb sa hw hh pt = rstrokeEllipse rgb sa hw hh 0 pt --- | Create a filled ellipse.++-- | 'rstrokeEllipse' : @ rgb * stroke_attr * rx * ry * rotation * +--      center -> Primtive @+-- +-- Create a stroked ellipse rotated about the center by /theta/. --+rstrokeEllipse :: Num u +               => RGBi -> StrokeAttr -> u -> u -> Radian -> Point2 u+               -> Primitive u+rstrokeEllipse rgb sa rx ry theta pt = +    PEllipse (EStroke sa rgb) (mkPrimEllipse rx ry theta pt)++++-- | 'fillEllipse' : @ rgb * stroke_attr * rx * ry * center -> Primtive @+--+-- Create a filled ellipse.+-- fillEllipse :: Num u -             => RGBi -> u -> u -> Point2 u -> PrimElement u-fillEllipse rgb hw hh pt = -    Atom $ PEllipse (EFill rgb) (PrimEllipse pt hw hh identityCTM)+             => RGBi -> u -> u -> Point2 u -> Primitive u+fillEllipse rgb rx ry pt = rfillEllipse rgb rx ry 0 pt+  +-- | 'rfillEllipse' : @ colour * stroke_attr * rx * ry * +--      rotation * center -> Primtive @+--+-- Create a filled ellipse rotated about the center by /theta/.+--+rfillEllipse :: Num u +             => RGBi -> u -> u -> Radian -> Point2 u -> Primitive u+rfillEllipse rgb rx ry theta pt = +    PEllipse (EFill rgb) (mkPrimEllipse rx ry theta pt) --- | Create a black, filled ellipse. -zellipse :: Num u => u -> u -> Point2 u -> PrimElement u-zellipse hw hh pt = fillEllipse black hw hh pt +-- | 'zellipse' : @ rx * ry * center -> Primtive @+--+-- Create a black, filled ellipse. +--+zellipse :: Num u => u -> u -> Point2 u -> Primitive u+zellipse hw hh pt = rfillEllipse black hw hh 0 pt --- | Create a bordered (i.e. filled and stroked) ellipse.++-- | 'fillStrokeEllipse' : @ fill_rgb * stroke_attr * stroke_rgb * rx * ry *+--      center -> Primtive @ --+-- Create a bordered (i.e. filled and stroked) ellipse.+-- fillStrokeEllipse :: Num u -                 => RGBi -> StrokeAttr -> RGBi -> u -> u -> Point2 u -                 -> PrimElement u-fillStrokeEllipse frgb sa srgb hw hh pt = -    Atom $ PEllipse (EFillStroke frgb sa srgb) (PrimEllipse pt hw hh identityCTM)+                  => RGBi -> StrokeAttr -> RGBi -> u -> u -> Point2 u +                  -> Primitive u+fillStrokeEllipse frgb sa srgb rx ry pt = +    rfillStrokeEllipse frgb sa srgb rx ry 0 pt+      +-- | 'rfillStrokeEllipse' : @ fill_rgb * stroke_attr * stroke_rgb * rx * ry *+--      theta * center -> Primtive @+--+-- 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 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 rx ry theta pt = PrimEllipse pt rx ry (thetaCTM theta)+ -------------------------------------------------------------------------------- -- Operations --- | Extend the bounding box of a picture. +-- | 'extendBoundary' : @ x * y * picture -> Picture @+-- +-- Extend the bounding box of a picture.  -- -- The bounding box is both horizontal directions by @x@ and  -- both vertical directions by @y@. @x@ and @y@ must be positive@@ -482,7 +589,7 @@  infixr 6 `picBeside`, `picOver` --- | 'picOver' : @ picture -> picture -> picture @+-- | 'picOver' : @ picture * picture -> Picture @ -- -- Draw the first picture on top of the second picture -  -- neither picture will be moved.@@ -490,20 +597,20 @@ picOver :: (Num u, Ord u) => Picture u -> Picture u -> Picture u a `picOver` b = Picture (bb,[]) (cons b $ one a)    where-    bb = boundary a `append` boundary b+    bb = boundary a `boundaryUnion` boundary b  -- picOver note - draw b, put b first in the list, so it draws  -- first in the output (this is also @behind@ in the Z-Order).  --- | 'picMoveBy' : @ picture -> vector -> picture @+-- | 'picMoveBy' : @ picture * vector -> Picture @ --  --  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  --- | 'picBeside' : @ picture -> picture -> picture @+-- | 'picBeside' : @ picture * picture -> Picture @ -- -- Move the second picture to sit at the right side of the -- first picture@@ -524,7 +631,7 @@ printPicture pic = putStrLn (show $ format pic) >> putStrLn []  --- | 'illustrateBounds' : @ colour -> picture -> picture @+-- | 'illustrateBounds' : @ bbox_rgb * picture -> Picture @ --  -- Draw the picture on top of an image of its bounding box. -- The bounding box image will be drawn in the supplied colour.@@ -534,7 +641,7 @@ illustrateBounds rgb p = p `picOver` (frame $ boundsPrims rgb p)   --- | 'illustrateBoundsPrim' : @ colour -> primitive -> picture @+-- | 'illustrateBoundsPrim' : @ bbox_rgb * primitive -> Picture @ --  -- Draw the primitive on top of an image of its bounding box. -- The bounding box image will be drawn in the supplied colour.@@ -542,7 +649,7 @@ -- The result will be lifted from Primitive to Picture. --  illustrateBoundsPrim :: (Real u, Floating u, FromPtSize u) -                     => RGBi -> PrimElement u -> Picture u+                     => RGBi -> Primitive u -> Picture u illustrateBoundsPrim rgb p = frame (p : boundsPrims rgb p)  @@ -551,7 +658,7 @@ -- joining the corners. -- boundsPrims :: (Num u, Ord u, Boundary t, u ~ DUnit t) -            => RGBi -> t -> [PrimElement u]+            => RGBi -> t -> [Primitive u] boundsPrims rgb a = [ bbox_rect, bl_to_tr, br_to_tl ]   where     (bl,br,tr,tl) = boundaryCorners $ boundary a@@ -563,26 +670,25 @@                                         , dash_pattern = Dash 0 [(1,2)] }  --- | Generate the control points illustrating the Bezier curves +-- | 'illustrateControlPoints' : @ control_point_rgb * primitive -> Picture @+-- +-- Generate the control points illustrating the Bezier curves  -- within a picture. --  -- This has no effect on TextLabels. Nor does it draw Beziers of --- a hyperlinked obkect.+-- a hyperlinked object. --  -- Pseudo control points are generated for ellipses, although  -- strictly speaking ellipses do not use Bezier curves - they  -- are implemented with PostScript\'s @arc@ command.   -- illustrateControlPoints :: (Real u, Floating u, FromPtSize u)-                        => RGBi -> PrimElement u -> Picture u-illustrateControlPoints rgb elt = outer elt+                        => RGBi -> Primitive u -> Picture u+illustrateControlPoints rgb elt = frame $ step elt   where-    outer a@(Atom prim) = frame (a : step prim)-    outer a             = frame [a]-     step (PEllipse _ e) = ellipseCtrlLines rgb e     step (PPath    _ p) = pathCtrlLines rgb p-    step _              = []+    step a              = [a]  -- Genrate lines illustrating the control points of curves on  -- a Path.@@ -592,7 +698,7 @@ -- -- Nothing is generated for a straight line. ---pathCtrlLines :: (Num u, Ord u) => RGBi -> PrimPath u -> [PrimElement u]+pathCtrlLines :: (Num u, Ord u) => RGBi -> PrimPath u -> [Primitive u] pathCtrlLines rgb (PrimPath start ss) = step start ss   where      -- trail the current end point through the recursion...@@ -611,7 +717,7 @@ -- start-point to control-point1; control-point2 to end-point -- ellipseCtrlLines :: (Real u, Floating u) -                 => RGBi -> PrimEllipse u -> [PrimElement u]+                 => RGBi -> PrimEllipse u -> [Primitive u] ellipseCtrlLines rgb pe = start all_points   where      -- list in order: 
src/Wumpus/Core/PictureInternal.hs view
@@ -22,51 +22,35 @@     Picture(..)   , DPicture   , Locale-  , AffineTrafo(..)   , FontCtx(..) -  , PrimElement(..)-  , DPrimElement   , Primitive(..)   , DPrimitive   , XLink(..)    , PrimPath(..)   , DPrimPath-  , PathProps(..)   , PrimPathSegment(..)   , DPrimPathSegment   , PrimLabel(..)   , DPrimLabel-  , LabelProps(..)   , LabelBody(..)   , DLabelBody   , KerningChar   , DKerningChar     , PrimEllipse(..)-  , EllipseProps(..)-  , PrimCTM(..) +  , GraphicsState(..)+   , pathBoundary   , mapLocale -  -- * PrimCTM-  , identityCTM-  , scaleCTM-  , rotateCTM-  , matrixRepCTM-  , translMatrixRepCTM--  , rotatePrim-  , scalePrim-  , uniformScalePrim-  , translatePrim-   -- * Additional operations   , concatTrafos   , deconsMatrix   , repositionDeltas +  , zeroGS    ) where @@ -74,17 +58,18 @@ import Wumpus.Core.BoundingBox import Wumpus.Core.Colour import Wumpus.Core.FontSize-import Wumpus.Core.FormatCombinators import Wumpus.Core.Geometry-import Wumpus.Core.GraphicsState-import Wumpus.Core.OneList+import Wumpus.Core.GraphicProps import Wumpus.Core.PtSize-import Wumpus.Core.TextInternal-import Wumpus.Core.Utils+import Wumpus.Core.Text.Latin1+import Wumpus.Core.Text.TextInternal+import Wumpus.Core.TrafoInternal+import Wumpus.Core.Utils.Common+import Wumpus.Core.Utils.FormatCombinators+import Wumpus.Core.Utils.OneList   import Data.AffineSpace                         -- package: vector-space-import Data.Semigroup                           -- package: algebra  import qualified Data.Foldable                  as F @@ -125,7 +110,7 @@ -- updates for the SVG renderer - in some instances this can  -- improve the code size of the generated SVG. ---data Picture u = Leaf     (Locale u)              (OneList (PrimElement u))+data Picture u = Leaf     (Locale u)              (OneList (Primitive u))                | Picture  (Locale u)              (OneList (Picture u))                | Clip     (Locale u) (PrimPath u) (Picture u)                | Group    (Locale u) FontCtx      (Picture u)@@ -133,24 +118,7 @@  type DPicture = Picture Double --- | To represent XLink hyperlinks, Primitives in a Leaf are --- actualy encoded in a tree rather a list.------ As a design, this is rather unfortunate as it demands an extra --- wrapper for ever element regardless of whether hyperlinks are --- actually used. But it does mean that one hyperlink can cover a --- complex graphic element - for example an arrow might be drawn --- with one or more paths, plus extra (filled or stroked) paths --- for the tip and tail, but each element should be within the --- link. ----data PrimElement u = Atom             (Primitive u)-                   | XLinkGroup XLink (OneList (PrimElement u))-  deriving (Show) -type DPrimElement = PrimElement Double-- -- | Set the font /delta/ for SVG rendering.  --  -- Note - this does not change the default colour or font style. @@ -181,15 +149,6 @@ type Locale u = (BoundingBox u, [AffineTrafo u])  --- | 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-  deriving (Eq,Show)                   -- | Wumpus\'s drawings are built from two fundamental  -- primitives: paths (straight line segments and Bezier curves) @@ -214,9 +173,14 @@ -- Though typically for affine transformations a Fractional  -- constraint is also obliged. ---data Primitive u = PPath    PathProps    (PrimPath u)-                 | PLabel   LabelProps   (PrimLabel u)-                 | PEllipse EllipseProps (PrimEllipse u)+-- To represent XLink hyperlinks, Primitives can be grouped +-- together at the same type (so 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)+                 | PGroup   (Maybe XLink) (OneList (Primitive u))   deriving (Eq,Show)  type DPrimitive = Primitive Double@@ -226,6 +190,7 @@ newtype XLink = XLink { getXLink :: String }   deriving (Eq,Show) + -- | PrimPath - start point and a list of path segments. -- data PrimPath u = PrimPath (Point2 u) [PrimPathSegment u]@@ -241,20 +206,6 @@  type DPrimPathSegment = PrimPathSegment Double --- | Note when drawn /filled/ and drawn /stroked/ the same--- polygon will have (slightly) different size:------ * A filled shape fills /within/ the boundary of the shape------ * A stroked shape draws a pen line around the boundary---   of the shape. The actual size depends on the thickness---   of the line (stroke width).----data PathProps = CFill RGBi -               | CStroke StrokeAttr RGBi-               | OStroke StrokeAttr RGBi-               | CFillStroke RGBi StrokeAttr RGBi-  deriving (Eq,Show)   -- | Label - represented by /baseline/ left point and text.@@ -268,15 +219,7 @@  type DPrimLabel = PrimLabel Double --- | Font rendering properties for a PrimLabel.----data LabelProps   = LabelProps -      { label_colour :: RGBi-      , label_font   :: FontAttr-      }-  deriving (Eq,Ord,Show) - -- | Label can be draw with 3 layouts. --  -- The standard layout uses @show@ for PostScript and a single @@ -315,23 +258,22 @@   deriving (Eq,Show)  --- | Ellipses and circles are always closed.----data EllipseProps = EFill RGBi-                  | EStroke StrokeAttr RGBi -                  -- Note - first colour fill, second colour stroke.-                  | EFillStroke RGBi StrokeAttr RGBi -  deriving (Eq,Show)   --- Note - primitives are not considered to exist in an affine --- space. ++--------------------------------------------------------------------------------+-- Graphics state datatypes++-- | Graphics state used by the rendering monads. ---data PrimCTM u = PrimCTM -      { ctm_scale_x     :: u-      , ctm_scale_y     :: u-      , ctm_rotation    :: Radian +-- This type is hidden by the top-level module @Wumpus.Core@.+--+data GraphicsState = GraphicsState+      { gs_draw_colour  :: RGBi+      , gs_font_size    :: Int+      , gs_font_face    :: FontFace+      , gs_stroke_attr  :: StrokeAttr        }   deriving (Eq,Show) @@ -340,9 +282,10 @@ -- family instances  type instance DUnit (Picture u)     = u-type instance DUnit (PrimElement 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@@ -351,7 +294,7 @@ instance (Num u, PSUnit u) => Format (Picture u) where   format (Leaf m prims)     = indent 2 $ vcat [ text "** Leaf-pic **"                                               , fmtLocale m -                                              , fmtPrimElems prims ]+                                              , fmtPrimlist prims ]    format (Picture m pics)   = indent 2 $ vcat [ text "** Tree-pic **"                                               , fmtLocale m@@ -372,17 +315,7 @@   where     fn (n,acc) e = (n+1, vcat [ acc, text "-- " <+> int n, format e, line]) -fmtPrimElems :: PSUnit u => OneList (PrimElement u) -> Doc-fmtPrimElems 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 (PrimElement u) where-  format (Atom prim)          = format prim-  format (XLinkGroup xl ones) = vcat [ text "-- xlink " <+> format xl -                                     , fmtPrimElems ones  ]-                                     - fmtLocale :: (Num u, PSUnit u) => Locale u -> Doc fmtLocale (bb,_) = format bb @@ -397,7 +330,16 @@   format (PEllipse props e) =        indent 2 $ vcat [ text "ellipse:" <+> format props, format e ] +  format (PGroup xl ones)   = +      vcat [ text "-- group " <+> (maybe empty format xl), fmtPrimlist ones  ] ++fmtPrimlist :: PSUnit u => OneList (Primitive u) -> 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@@ -429,32 +371,6 @@                                    <+> text "ctm="      <> format ctm    -instance PSUnit u => Format (PrimCTM u) where-  format (PrimCTM x y ang) = -      parens (text "CTM" <+> text "sx="   <> dtruncFmt x -                         <+> text "sy="   <> dtruncFmt y -                         <+> text "ang="  <> format ang  )---instance Format PathProps where-  format (CFill rgb)          = format rgb <+> text "Fill"-  format (CStroke _ rgb)      = format rgb <+> text "Closed-stroke"-  format (OStroke _ rgb)      = format rgb <+> text "Open-stroke"-  format (CFillStroke f _ s)  = format f <+> text "Fill" <> char '/'-                            <+> format s <+> text "Stroke"   ----instance Format LabelProps where-  format (LabelProps rgb attr) = format rgb -                             <+> text (font_name $ font_face attr)--instance Format EllipseProps where-  format (EFill rgb)          = format rgb <+> text "Fill"-  format (EStroke _ rgb)      = format rgb <+> text "Stroke"-  format (EFillStroke f _ s)  = format f <+> text "Fill" <> char '/'-                            <+> format s <+> text "Stroke"   - instance Format XLink where   format (XLink ss) = text "xlink" <+> text ss @@ -468,20 +384,18 @@   boundary (Group   (bb,_) _ _) = bb  -instance (Real u, Floating u, FromPtSize u) => Boundary (PrimElement u) where-  boundary (Atom prim)         = boundary prim-  boundary (XLinkGroup _ ones) = outer $ viewl ones +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 (PGroup _ ones)  = outer $ viewl ones      where       outer (OneL a)     = boundary a       outer (a :< as)    = inner (boundary a) (viewl as) -      inner bb (OneL a)  = bb `append` boundary a-      inner bb (a :< as) = inner (bb `append` boundary a) (viewl as)+      inner bb (OneL a)  = bb `boundaryUnion` boundary a+      inner bb (a :< as) = inner (bb `boundaryUnion` boundary a) (viewl as) -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   @@ -526,6 +440,7 @@             => FontSize -> EncodedText -> BoundingBox u stdLayoutBB sz etxt = textBoundsEnc sz zeroPt etxt + -- Note - this assumes positive deltas (and a nonempty list)... -- -- Kern deltas are relative to the left basepoint, so they are@@ -579,11 +494,11 @@ -------------------------------------------------------------------------------- -- Affine transformations --- Note YRange remains constant (as do the actually points --- within the primitives).--- --- TO DO - this is potentially wrong...-+-- Affine transformation of Pictures only transforms the +-- BoundingBox, the primitives within the picture are untouched.+-- The transformation is transmitted to PostScript as a matrix +-- update (frame change).+--  instance (Num u, Ord u) => Transform (Picture u) where   transform mtrx = @@ -613,168 +528,61 @@ mapLocale f (Clip lc pp pic)   = Clip (f lc) pp pic mapLocale f (Group lc upd pic) = Group (f lc) upd pic ------------------------------------------------------------------------------------ Manipulating the PrimCTM -identityCTM :: Num u => PrimCTM u-identityCTM = PrimCTM { ctm_scale_x = 1, ctm_scale_y = 1, ctm_rotation = 0 }----scaleCTM :: Num u => u -> u -> PrimCTM u -> PrimCTM u-scaleCTM x1 y1 (PrimCTM sx sy ang) = PrimCTM (x1*sx) (y1*sy) ang--rotateCTM :: Radian -> PrimCTM u -> PrimCTM u-rotateCTM ang1 (PrimCTM sx sy ang) = PrimCTM sx sy (circularModulo $ ang1+ang)--matrixRepCTM :: (Floating u, Real u) => PrimCTM u -> Matrix3'3 u-matrixRepCTM (PrimCTM sx sy ang) = -    rotationMatrix (circularModulo ang) * scalingMatrix sx sy----- Note - the order of combining a translation (i.e. the --- location of a point) and the CTM is crucial as matrix--- multiplication is not commutative.------ This function encapsulates the correct order.----translMatrixRepCTM :: (Floating u, Real u) -                   => u -> u -> PrimCTM u -> Matrix3'3 u-translMatrixRepCTM x y ctm = translationMatrix x y * matrixRepCTM ctm--- -------------------------------------------------------------------------------- -- Transform primitives  --- | Rotate a Primitive.--- --- Note - this is not an affine transformation as Primitives are--- not regarded as being within an affine frame.------ * Paths are rotated about their start point.------ * Labels are rotated about the bottom-left corner.------ * Ellipses are rotated about the center.------ For Primitives and Ellipses applying a rotation and or a scale --- will generate an additional matrix transformation in the --- generated PostScript. For Paths all transformations are--- \"cost-free\".+-- Note - Primitives are not instances of transform ---rotatePrim :: (Real u, Floating u) -           => Radian -> PrimElement u -> PrimElement u-rotatePrim ang (Atom prim)             = Atom $ rotatePrimitive ang prim-rotatePrim ang (XLinkGroup xlink ones) = -    XLinkGroup xlink $ fmap (rotatePrim ang) ones---rotatePrimitive :: (Real u, Floating u) -                => Radian -> Primitive u -> Primitive u-rotatePrimitive ang (PPath a path)   = PPath    a $ rotatePath ang path-rotatePrimitive ang (PLabel a lbl)   = PLabel   a $ rotateLabel ang lbl-rotatePrimitive ang (PEllipse a ell) = PEllipse a $ rotateEllipse ang ell----- | Scale a Primitive.+-- (ShapeCTM is not a real matrix). -- --- Note - this is not an affine transformation as Primitives are--- not regarded as being within an affine frame.------ An affine scaling uniformly scales all the elements in a --- Picture. It is just a change of the Picture\'s basis vectors.--- The elements within the Picture are unchanged - though --- obviously rendering changes according to the transformation.------ By contrast, the scaling operation on Primitives changes the --- properties of the object as it is applied - e.g. for a path--- the vector between the start point and all subsequent points--- is changed with respect to the x,y scaling factors; for an--- ellipse the half-width and half-height of the ellipse is--- scaled.------ For Primitives and Ellipses applying a rotation and or a scale --- will generate an additional matrix transformation in the --- generated PostScript. For Paths all transformations are --- \"cost-free\".----scalePrim :: Num u => u -> u -> PrimElement u -> PrimElement u-scalePrim x y (Atom prim)             = Atom $ scalePrimitive x y prim-scalePrim x y (XLinkGroup xlink ones) = -    XLinkGroup xlink $ fmap (scalePrim x y) ones +instance (Real u, Floating u) => Rotate (Primitive u) 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 (PGroup xln xs)  = PGroup xln $ fmap (rotate r) xs+  -scalePrimitive :: Num u => u -> u -> Primitive u -> Primitive u-scalePrimitive x y (PPath a path)   = PPath    a $ scalePath x y path-scalePrimitive x y (PLabel a lbl)   = PLabel   a $ scaleLabel x y lbl-scalePrimitive x y (PEllipse a ell) = PEllipse a $ scaleEllipse x y ell+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 (PGroup xln xs)  = PGroup xln $ fmap (rotateAbout r pt) xs --- | Apply a uniform scale to a Primitive.----uniformScalePrim :: Num u => u -> PrimElement u -> PrimElement u-uniformScalePrim d = scalePrim d d  --- | Translate a primitive.------ Translation is essentially \"cost-free\" for the generated --- PostScript or SVG. Paths are translated before the PostScript --- is generated. For Ellipses and Labels, translation will --- either move the bottom-left origin (Label) or center --- (Ellipse); or if they are also scaled or rotated the --- translation will be concatenated into the matrix operation in --- the generated output. --- -translatePrim :: Num u => u -> u -> PrimElement u -> PrimElement u-translatePrim x y (Atom prim)             = -    Atom $ translatePrimitive x y prim+instance Num u => Scale (Primitive u) 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 (PGroup xln xs)   = PGroup xln $ fmap (scale sx sy) xs -translatePrim x y (XLinkGroup xlink ones) = -    XLinkGroup xlink $ fmap (translatePrim x y) ones -translatePrimitive :: Num u => u -> u -> Primitive u -> Primitive u-translatePrimitive x y (PPath a path)   = PPath a $ translatePath x y path-translatePrimitive x y (PLabel a lbl)   = PLabel a $ translateLabel x y lbl-translatePrimitive x y (PEllipse a ell) = PEllipse a $ translateEllipse x y ell-+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 (PGroup xln xs)  = PGroup xln $ fmap (translate dx dy) xs   -------------------------------------------------------------------------------- -- Paths --- Cannot support general matrix transform or rotateAbout on --- Ellipses or Labels so there are not supported on Paths.--- --- rotatePath - rotate the path about its start point.--- --- This is a visually intuitive interpretation - Primitives are--- not in an affine space (they have an origin, i.e. the location --- (0,0), but do not have tangible basis vectors) so manipulating --- them cannot follow the standard affine interpretation.---  rotatePath :: (Real u, Floating u) => Radian -> PrimPath u -> PrimPath u-rotatePath ang (PrimPath start xs) = PrimPath start $ map (mapSeg fn) xs -  where-    fn = rotateAbout ang start+rotatePath ang = mapPath (rotate ang) --- scalePath - scale the vector between each point and the start --- point.------ This produces visually inituitive results. As primitives --- don\'t exist in an affine space / affine frame until they--- are lifted to Pictures their manipulation cannot correspond--- to the standard affine manipulations.---++rotateAboutPath :: (Real u, Floating u) +                => Radian -> Point2 u -> PrimPath u -> PrimPath u+rotateAboutPath ang pt = mapPath (rotateAbout ang pt) ++ scalePath :: Num u => u -> u -> PrimPath u -> PrimPath u-scalePath x y (PrimPath pt xs) = PrimPath pt $ map (mapSeg fn) xs-  where-    fn p1 = let dif = p1 .-. pt in pt .+^ (scale x y $ dif)+scalePath sx sy = mapPath (scale sx sy) --- translatePath - move all points in the path by the supplied --- x and y values.---+ translatePath :: Num u => u -> u -> PrimPath u -> PrimPath u translatePath x y = mapPath (translate x y) @@ -791,42 +599,61 @@   --- Rotations on a (primitive) Label are interpreted as rotating--- about the bottom-left corner.+-- Rotate the baseline-left start point _AND_ the CTM of the +-- label. ---rotateLabel :: Radian -> PrimLabel u -> PrimLabel u-rotateLabel ang (PrimLabel pt txt ctm) = PrimLabel pt txt (rotateCTM ang ctm)+rotateLabel :: (Real u, Floating u) +            => Radian -> PrimLabel u -> PrimLabel u+rotateLabel ang (PrimLabel pt txt ctm) = +    PrimLabel (rotate ang pt) 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 pt0 (PrimLabel pt txt ctm) = +    PrimLabel (rotateAbout ang pt0 pt) txt (rotateCTM ang ctm)++ scaleLabel :: Num u => u -> u -> PrimLabel u -> PrimLabel u-scaleLabel x y (PrimLabel pt txt ctm) = PrimLabel pt txt (scaleCTM x y ctm)+scaleLabel sx sy (PrimLabel pt txt ctm) = +    PrimLabel (scale sx sy pt) txt (scaleCTM sx sy ctm)   -- Change the bottom-left corner. -- translateLabel :: Num u => u -> u -> PrimLabel u -> PrimLabel u-translateLabel x y (PrimLabel pt txt ctm) = PrimLabel (translate x y pt) txt ctm+translateLabel dx dy (PrimLabel pt txt ctm) = +    PrimLabel (translate dx dy pt) txt ctm  -------------------------------------------------------------------------------- -- Ellipse  -rotateEllipse :: Radian -> PrimEllipse u -> PrimEllipse u+rotateEllipse :: (Real u, Floating u) +              => Radian -> PrimEllipse u -> PrimEllipse u rotateEllipse ang (PrimEllipse pt hw hh ctm) = -    PrimEllipse pt hw hh (rotateCTM ang ctm)+    PrimEllipse (rotate ang pt) hw hh (rotateCTM ang ctm)      +rotateAboutEllipse :: (Real u, Floating u) +              => Radian -> Point2 u -> PrimEllipse u -> PrimEllipse u+rotateAboutEllipse ang pt0 (PrimEllipse pt hw hh ctm) = +    PrimEllipse (rotateAbout ang pt0 pt) hw hh (rotateCTM ang ctm) + scaleEllipse :: Num u => u -> u -> PrimEllipse u -> PrimEllipse u-scaleEllipse x y (PrimEllipse pt hw hh ctm) = -    PrimEllipse (translate x y pt) hw hh (scaleCTM x y ctm)+scaleEllipse sx sy (PrimEllipse pt hw hh ctm) = +    PrimEllipse (scale sx sy pt) hw hh (scaleCTM sx sy ctm)        -- Change the point -- translateEllipse :: Num u => u -> u -> PrimEllipse u -> PrimEllipse u-translateEllipse x y (PrimEllipse pt hw hh ctm) = -    PrimEllipse (translate x y pt) hw hh ctm+translateEllipse dx dy (PrimEllipse pt hw hh ctm) = +    PrimEllipse (translate dx dy pt) hw hh ctm   @@ -834,17 +661,6 @@ -- Additional operations  -concatTrafos :: (Floating u, Real u) => [AffineTrafo u] -> Matrix3'3 u-concatTrafos = foldr (\e ac -> matrixRepr e * ac) identityMatrix--matrixRepr :: (Floating u, Real u) => AffineTrafo u -> Matrix3'3 u-matrixRepr (Matrix mtrx)        = mtrx-matrixRepr (Rotate theta)       = rotationMatrix theta-matrixRepr (RotAbout theta pt)  = originatedRotationMatrix theta pt-matrixRepr (Scale sx sy)        = scalingMatrix sx sy -matrixRepr (Translate dx dy)    = translationMatrix dx dy-- -- | Destructor for Matrix3'3. --  -- Pattern matching on 6-tuple may be more convenient than using @@ -879,4 +695,26 @@         y  = 4 - lly         ll = P2 (llx+x) (lly+y)         ur = P2 (urx+x) (ury+y) +++--------------------------------------------------------------------------------++-- | 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@+-- command to be generated (PostScript @findfont@ commands are +-- only written in the output on /deltas/ to reduce the +-- output size).+--+zeroGS ::  GraphicsState +zeroGS = GraphicsState { gs_draw_colour  = black+                       , gs_font_size    = (-1)+                       , gs_font_face    = unmatchable_face+                       , gs_stroke_attr  = default_stroke_attr+                       }+  where+    unmatchable_face = FontFace "DONT_MATCH"     "" +                                SVG_BOLD_OBLIQUE latin1_font_encoder+ 
src/Wumpus/Core/PostScriptDoc.hs view
@@ -65,12 +65,12 @@  import Wumpus.Core.BoundingBox import Wumpus.Core.Colour-import Wumpus.Core.FormatCombinators import Wumpus.Core.Geometry-import Wumpus.Core.GraphicsState+import Wumpus.Core.GraphicProps import Wumpus.Core.PictureInternal-import Wumpus.Core.TextEncoder-import Wumpus.Core.Utils+import Wumpus.Core.Text.Encoder+import Wumpus.Core.Utils.Common+import Wumpus.Core.Utils.FormatCombinators  import Data.Time 
src/Wumpus/Core/PtSize.hs view
@@ -49,7 +49,7 @@ -- Note - the Double instance perfoms no scaling, this -- is because internally Wumpus-Core works in points. -- -class FromPtSize u where+class Num u => FromPtSize u where   fromPtSize :: PtSize -> u  instance FromPtSize Double where
src/Wumpus/Core/SVGDoc.hs view
@@ -76,12 +76,12 @@   ) where  import Wumpus.Core.Colour-import Wumpus.Core.FormatCombinators import Wumpus.Core.Geometry-import Wumpus.Core.GraphicsState+import Wumpus.Core.GraphicProps import Wumpus.Core.PictureInternal-import Wumpus.Core.TextEncoder-import Wumpus.Core.Utils+import Wumpus.Core.Text.Encoder+import Wumpus.Core.Utils.Common+import Wumpus.Core.Utils.FormatCombinators   escapeSpecial :: CharCode -> String
+ src/Wumpus/Core/Text/DefaultEncoder.hs view
@@ -0,0 +1,44 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Core.Text.DefaultEncoder+-- Copyright   :  (c) Stephen Tetley 2010+-- License     :  BSD3+--+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable+-- Portability :  GHC+--+-- This is the default @TextEncoder@ with lookups for both Latin1+-- character codes / names and Symbol font.+--+--------------------------------------------------------------------------------++module Wumpus.Core.Text.DefaultEncoder+  ( +    defaultEncoder++  ) where++import Wumpus.Core.Text.Encoder+import Wumpus.Core.Text.Latin1+import Wumpus.Core.Text.SymbolFont++import Data.Map+++-- | This is the default encoder supporting names and codes for +-- both Latin1 and the Symbol font.+--+defaultEncoder :: TextEncoder+defaultEncoder = TextEncoder+      { svg_encoding_name       = "ISO-8859-1"+      , font_encoder_map        = fem+      }+  where+    fem = insert symbol_font_encoder symbolFontEncoder +        $ insert latin1_font_encoder latin1FontEncoder+        $ empty ++
+ src/Wumpus/Core/Text/Encoder.hs view
@@ -0,0 +1,143 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Core.Text.Encoder+-- Copyright   :  (c) Stephen Tetley 2009-2010+-- License     :  BSD3+--+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable+-- Portability :  GHC+--+-- Extended character code handling.+-- +-- Wumpus uses SVG style escaping to embed character codes or +-- names in regular strings:+--+-- > "regular ascii text &#egrave; more ascii text"+--  +-- i.e. character names and codes are delimited by @&\#@ on the +-- left and @;@ on the right.+--+-- In Wumpus both character names and character codes can+-- be embedded in strings - (e.g. @ &\#egrave; or &\#232; @).+--+-- Character codes can be also be expressed as octal or +-- hexadecimal:+--+-- > myst&#0o350;re+--+-- > myst&#0xE8;re+--+-- In the generated PostScript, Wumpus uses the character name, +-- e.g.:  +--+-- > (myst) show /egrave glyphshow (re) show+-- +-- The generated SVG uses the numeric code, e.g.: +--+-- > myst&#232;re+--+-- To accommodate both, Wumpus defines a TextEncoder record which+-- provides a two-way mapping between character codes and glyph +-- names for a character set.+--+--------------------------------------------------------------------------------++module Wumpus.Core.Text.Encoder+  ( +    GlyphName+  , CharCode+  , PostScriptLookup+  , SVGLookup++  , FontEncoderName(..)+  , TextEncoder(..)+  , FontEncoder(..)++  ) where++import Data.Map+import Data.Word++type GlyphName        = String+type CharCode         = Int ++type PostScriptLookup = CharCode -> Maybe GlyphName+type SVGLookup        = GlyphName -> Maybe CharCode++++-- | Font encoder name - a newtype wrapped /number/.+-- +-- Ideally this would be an enumerated type, but it has to be +-- open - new encoders need to be added, so an enum is out of the+-- question.+--+-- A String would be good, but would have slow lookup when used +-- as a key. Dealing with multiple encoders was added late to +-- Wumpus-Core - it is necessary, but taking a performace hit +-- because of it is chagrin. So instead /uniquely/ asssigned+-- numbers are used.+--+-- Numbers below 10000 are reserved for Wumpus, though it is +-- unlikely to need more than a handful. Numbers above are free +-- to use (clearly clashes are possible, but probably unlikely).+-- +-- Wumpus-Core assigns the following, other Wumpus libraries may +-- assign more:+--+-- > 0 - Latin1 (for Helvetica, Times Roman, Courier...)+--+-- > 1 - Symbol Font+-- +newtype FontEncoderName = FontEncoderName { getFontEncoderName :: Word16 }+  deriving (Eq,Ord)++instance Show FontEncoderName where+  show = step . getFontEncoderName+    where+      step 0 = "Latin1"+      step 1 = "Symbol-Font"+      step n = show n++-- | 'TextEncoder'+--+-- An /instance/ needs: +--+-- * A map of FontEncoderNames to FontEncoders.+--+-- * The name of the encoding - this is printed in the xml +-- prologue of the SVG file as the @encoding@ attribute. Latin +-- 1\'s official name is seemingly \"ISO-8859-1\". +-- +-- * The name of the default encoder - this should naturally be +-- in the Font Encoder map.+-- +-- +data TextEncoder = TextEncoder+      { svg_encoding_name       :: String+      , font_encoder_map        :: Map FontEncoderName FontEncoder+      }++-- | 'FontEncoder'.+--+-- * The functions for looking up codes by glyph-name and +-- glyph-name by code. +-- +-- * Fallback glyph-names and char codes in case lookup fails.+-- +-- "Wumpus.Core.TextLatin1" defines an implementation for Latin 1.+--+data FontEncoder = FontEncoder  +      { ps_lookup           :: PostScriptLookup+      , svg_lookup          :: SVGLookup+      , ps_fallback         :: GlyphName+      , svg_fallback        :: CharCode+      }+                     ++-- no show instance as a TextEncoder contains functions.++
+ src/Wumpus/Core/Text/Latin1.hs view
@@ -0,0 +1,257 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Core.Text.Latin1+-- Copyright   :  (c) Stephen Tetley 2009-2010+-- License     :  BSD3+--+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable+-- Portability :  GHC+--+-- A @TextEncoder@ record instance for Latin1 characters.+-- +--------------------------------------------------------------------------------++module Wumpus.Core.Text.Latin1+  ( +  +    latin1_font_encoder+  , latin1FontEncoder+  , latin1FontAll++  ) where++import Wumpus.Core.Text.Encoder++import qualified Data.Map as Map+++-- | Latin1 Font Encoder name +--  +-- (Number 0) +--+latin1_font_encoder :: FontEncoderName+latin1_font_encoder = FontEncoderName 0++-- | Latin1 FontEncoder instance.+latin1FontEncoder :: FontEncoder+latin1FontEncoder = FontEncoder +    { ps_lookup         = Map.lookup `flip` codeToName+    , svg_lookup        = Map.lookup `flip` nameToCode+    , ps_fallback       = "space"+    , svg_fallback      = 0o040+    }++nameToCode :: Map.Map GlyphName CharCode+nameToCode = Map.fromList latin1FontAll++codeToName :: Map.Map CharCode GlyphName+codeToName = foldr fn Map.empty latin1FontAll where+  fn (s,i) a = Map.insert i s a ++-- | A lookup list of Latin 1 names to their octal code.+latin1FontAll :: [(GlyphName, CharCode)]+latin1FontAll = +    [ ("A",                     0o101)+    , ("AE",                    0o306)+    , ("Aacute",                0o301)+    , ("Acircumflex",           0o302)+    , ("Adieresis",             0o304)+    , ("Agrave",                0o300)+    , ("Aring",                 0o305)+    , ("Atilde",                0o303)+    , ("B",                     0o102)+    , ("C",                     0o103)+    , ("Ccedilla",              0o307)+    , ("D",                     0o104)+    , ("E",                     0o105)+    , ("Eacute",                0o311)+    , ("Ecircumflex",           0o312)+    , ("Edieresis",             0o313)+    , ("Egrave",                0o310)+    , ("Eth",                   0o320)+    , ("F",                     0o106)+    , ("G",                     0o107)+    , ("H",                     0o110)+    , ("I",                     0o111)+    , ("Iacute",                0o315)+    , ("Icircumflex",           0o316)+    , ("Idieresis",             0o317)+    , ("Igrave",                0o314)+    , ("J",                     0o112)+    , ("K",                     0o113)+    , ("L",                     0o114)+    , ("M",                     0o115)+    , ("N",                     0o116)+    , ("Ntilde",                0o321)+    , ("O",                     0o117)+    , ("Oacute",                0o323)+    , ("Ocircumflex",           0o324)+    , ("Odieresis",             0o326)+    , ("Ograve",                0o322)+    , ("Oslash",                0o351)+    , ("Otilde",                0o325)+    , ("P",                     0o120)+    , ("Q",                     0o121)+    , ("R",                     0o122)+    , ("S",                     0o123)+    , ("T",                     0o124)+    , ("Thorn",                 0o336)+    , ("U",                     0o125)+    , ("Uacute",                0o332)+    , ("Ucircumflex",           0o333)+    , ("Udieresis",             0o334)+    , ("Ugrave",                0o331)+    , ("V",                     0o126)+    , ("W",                     0o127)+    , ("X",                     0o130)+    , ("Y",                     0o131)+    , ("Yacute",                0o335)+    , ("Z",                     0o132)+    , ("a",                     0o141)+    , ("aacute",                0o341)+    , ("acircumflex",           0o342)+    , ("acute2",                0o264)+    , ("adieresis",             0o344)+    , ("ae",                    0o346)+    , ("agrave",                0o340)+    , ("ampersand",             0o046)+    , ("aring",                 0o345)+    , ("asciicircum",           0o136)+    , ("asciitilde",            0o176)+    , ("asterisk",              0o052)+    , ("at",                    0o100)+    , ("atilde",                0o343)+    , ("b",                     0o142)+    , ("backslash",             0o134)+    , ("bar",                   0o174)+    , ("braceleft",             0o173)+    , ("braceright",            0o175)+    , ("bracketleft",           0o133)+    , ("bracketright",          0o135)+    , ("breve",                 0o226)+    , ("brokenbar",             0o246)+    , ("c",                     0o143)+    , ("caron",                 0o237)+    , ("ccedilla",              0o347)+    , ("cedilla",               0o270)+    , ("cent",                  0o242)+    , ("circumflex",            0o223)+    , ("colon",                 0o072)+    , ("comma",                 0o054)+    , ("copyright",             0o251)+    , ("currency",              0o244)+    , ("d",                     0o144)+    , ("degree",                0o260)+    , ("dieresis",              0o250)+    , ("divide",                0o367)+    , ("dollar",                0o044)+    , ("dotaccent",             0o227)+    , ("dotlessi",              0o220)+    , ("e",                     0o145)+    , ("eacute",                0o351)+    , ("ecircumflex",           0o352)+    , ("edieresis",             0o353)+    , ("egrave",                0o350)+    , ("eight",                 0o070)+    , ("equal",                 0o075)+    , ("eth",                   0o360)+    , ("exclam",                0o041)+    , ("exclamdown",            0o241)+    , ("f",                     0o146)+    , ("five",                  0o065)+    , ("four",                  0o064)+    , ("g",                     0o147)+    , ("germandbls",            0o337)+    , ("grave",                 0o221)+    , ("greater",               0o076)+    , ("guillemotleft",         0o253)+    , ("guillemotright",        0o273)+    , ("h",                     0o150)+    , ("hungarumlaut",          0o235)+    , ("hyphen",                0o255)+    , ("i",                     0o151)+    , ("iacute",                0o355)+    , ("icircumflex",           0o356)+    , ("idieresis",             0o357)+    , ("igrave",                0o354)+    , ("j",                     0o152)+    , ("k",                     0o153)+    , ("l",                     0o154)+    , ("less",                  0o074)+    , ("logicalnot",            0o254)+    , ("m",                     0o155)+    , ("macron",                0o257)+    , ("minus",                 0o055)+    , ("mu",                    0o265)+    , ("multiply",              0o327)+    , ("n",                     0o156)+    , ("nine",                  0o071)+    , ("ntilde",                0o361)+    , ("numbersign",            0o043)+    , ("o",                     0o157)+    , ("oacute",                0o363)+    , ("ocircumflex",           0o364)+    , ("odieresis",             0o366)+    , ("ogonek",                0o236)+    , ("ograve",                0o362)+    , ("one",                   0o061)+    , ("onehalf",               0o275)+    , ("onequarter",            0o274)+    , ("onesuperior",           0o271)+    , ("ordfeminine",           0o252)+    , ("ordmasculine",          0o272)+    , ("oslash",                0o370)+    , ("otilde",                0o365)+    , ("p",                     0o160)+    , ("paragraph",             0o266)+    , ("parenleft",             0o050)+    , ("parenright",            0o051)+    , ("percent",               0o045)+    , ("period",                0o056)+    , ("periodcentered",        0o267)+    , ("plus",                  0o053)+    , ("plusminus",             0o261)+    , ("q",                     0o161)+    , ("question",              0o077)+    , ("questiondown",          0o277)+    , ("quotedbl",              0o042)+    , ("quoteleft",             0o140)+    , ("quoteright",            0o047)+    , ("r",                     0o162)+    , ("registered",            0o256)+    , ("ring",                  0o232)+    , ("s",                     0o163)+    , ("section",               0o247)+    , ("semicolon",             0o073)+    , ("seven",                 0o067)+    , ("six",                   0o066)+    , ("slash",                 0o057)+    , ("space",                 0o040)+    , ("sterling",              0o243)+    , ("t",                     0o164)+    , ("thorn",                 0o376)+    , ("three",                 0o063)+    , ("threequarters",         0o276)+    , ("threesuperior",         0o263)+    , ("tilde",                 0o224)+    , ("two",                   0o062)+    , ("twosuperior",           0o262)+    , ("u",                     0o165)+    , ("uacute",                0o372)+    , ("ucircumflex",           0o373)+    , ("udieresis",             0o374)+    , ("ugrave",                0o371)+    , ("underscore",            0o137)+    , ("v",                     0o166)+    , ("w",                     0o167)+    , ("x",                     0o170)+    , ("y",                     0o171)+    , ("yacute",                0o375)+    , ("ydieresis",             0o377)+    , ("yen",                   0o245)+    , ("z",                     0o172)+    , ("zero",                  0o060)+    ]
+ src/Wumpus/Core/Text/SymbolFont.hs view
@@ -0,0 +1,249 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Core.Text.SymbolFont+-- Copyright   :  (c) Stephen Tetley 2010+-- License     :  BSD3+--+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable+-- Portability :  GHC+--+-- A @TextEncoder@ record instance for Symbol font characters.+-- +--------------------------------------------------------------------------------++module Wumpus.Core.Text.SymbolFont+  ( +  +    symbol_font_encoder+  , symbolFontEncoder+  , symbolFontAll++  ) where++import Wumpus.Core.Text.Encoder++import qualified Data.Map as Map++++-- | Symbol Font Encoder name +--+-- (Number 1)+-- +symbol_font_encoder :: FontEncoderName+symbol_font_encoder = FontEncoderName 1++++-- | Latin1 TextEncoder instance.+symbolFontEncoder :: FontEncoder+symbolFontEncoder = FontEncoder +    { ps_lookup         = Map.lookup `flip` codeToName+    , svg_lookup        = Map.lookup `flip` nameToCode+    , ps_fallback       = "space"+    , svg_fallback      = 0o040+    }++nameToCode :: Map.Map GlyphName CharCode+nameToCode = Map.fromList symbolFontAll++codeToName :: Map.Map CharCode GlyphName+codeToName = foldr fn Map.empty symbolFontAll where+  fn (s,i) a = Map.insert i s a ++-- | A lookup list of Latin 1 names to their octal code.+symbolFontAll :: [(GlyphName, CharCode)]+symbolFontAll = +    [ ("Alpha",                 0o101)+    , ("Beta",                  0o102)+    , ("Chi",                   0o103)+    , ("Delta",                 0o104)+    , ("Epsilon",               0o105)+    , ("Eta",                   0o110)+    , ("Euro",                  0o240)+    , ("Gamma",                 0o107)+    , ("Ifraktur",              0o301)+    , ("Iota",                  0o111)+    , ("Kappa",                 0o113)+    , ("Lambda",                0o114)+    , ("Mu",                    0o115)+    , ("Nu",                    0o116)+    , ("Omega",                 0o127)+    , ("Omicron",               0o117)+    , ("Phi",                   0o106)+    , ("Pi",                    0o120)+    , ("Psi",                   0o131)+    , ("Rfraktur",              0o302)+    , ("Rho",                   0o122)+    , ("Sigma",                 0o123)+    , ("Tau",                   0o124)+    , ("Theta",                 0o121)+    , ("Upsilon",               0o125)+    , ("Upsilon1",              0o241)+    , ("Xi",                    0o130)+    , ("Zeta",                  0o132)+    , ("aleph",                 0o300)+    , ("alpha",                 0o141)+    , ("ampersand",             0o046)+    , ("angle",                 0o320)+    , ("angleleft",             0o341)+    , ("angleright",            0o361)+    , ("approxequal",           0o273)+    , ("arrowboth",             0o253)+    , ("arrowdblboth",          0o333)+    , ("arrowdbldown",          0o337)+    , ("arrowdblleft",          0o334)+    , ("arrowdblright",         0o336)+    , ("arrowdblup",            0o335)+    , ("arrowdown",             0o257)+    , ("arrowhorizex",          0o276)+    , ("arrowleft",             0o254)+    , ("arrowright",            0o256)+    , ("arrowup",               0o255)+    , ("arrowvertex",           0o275)+    , ("asteriskmath",          0o052)+    , ("bar",                   0o174)+    , ("beta",                  0o142)+    , ("braceleft",             0o173)+    , ("braceright",            0o175)+    , ("bracelefttp",           0o354)+    , ("braceleftmid",          0o355)+    , ("braceleftbt",           0o356)+    , ("bracerighttp",          0o374)+    , ("bracerightmid",         0o375)+    , ("bracerightbt",          0o376)+    , ("braceex",               0o357)+    , ("bracketleft",           0o133)+    , ("bracketright",          0o135)+    , ("bracketlefttp",         0o351)+    , ("bracketleftex",         0o352)+    , ("bracketleftbt",         0o353)+    , ("bracketrighttp",        0o371)+    , ("bracketrightex",        0o372)+    , ("bracketrightbt",        0o373)+    , ("bullet",                0o267)+    , ("carriagereturn",        0o277)+    , ("chi",                   0o143)+    , ("circlemultiply",        0o304)+    , ("circleplus",            0o305)+    , ("club",                  0o247)+    , ("colon",                 0o072)+    , ("comma",                 0o054)+    , ("congruent",             0o100)+    , ("copyrightsans",         0o343)+    , ("copyrightserif",        0o323)+    , ("degree",                0o260)+    , ("delta",                 0o144)+    , ("diamond",               0o250)+    , ("divide",                0o270)+    , ("dotmath",               0o327)+    , ("eight",                 0o070)+    , ("element",               0o316)+    , ("ellipsis",              0o274)+    , ("emptyset",              0o306)+    , ("epsilon",               0o145)+    , ("equal",                 0o075)+    , ("equivalence",           0o272)+    , ("eta",                   0o150)+    , ("exclam",                0o041)+    , ("existential",           0o044)+    , ("five",                  0o065)+    , ("florin",                0o246)+    , ("four",                  0o064)+    , ("fraction",              0o244)+    , ("gamma",                 0o147)+    , ("gradient",              0o321)+    , ("greater",               0o076)+    , ("greaterequal",          0o263)+    , ("heart",                 0o251)+    , ("infinity",              0o245)+    , ("integral",              0o362)+    , ("integraltp",            0o363)+    , ("integralex",            0o364)+    , ("integralbt",            0o365)+    , ("intersection",          0o307)+    , ("iota",                  0o151)+    , ("kappa",                 0o153)+    , ("lambda",                0o154)+    , ("less",                  0o074)+    , ("lessequal",             0o243)+    , ("logicaland",            0o331)+    , ("logicalnot",            0o330)+    , ("logicalor",             0o332)+    , ("lozenge",               0o340)+    , ("minus",                 0o055)+    , ("minute",                0o242)+    , ("mu",                    0o155)+    , ("multiply",              0o264)+    , ("nine",                  0o071)+    , ("notelement",            0o317)+    , ("notequal",              0o271)+    , ("notsubset",             0o313)+    , ("nu",                    0o156)+    , ("numbersign",            0o043)+    , ("omega",                 0o167)+    , ("omega1",                0o166)+    , ("omicron",               0o157)+    , ("one",                   0o061)+    , ("parenleft",             0o050)+    , ("parenright",            0o051)+    , ("parenlefttp",           0o346)+    , ("parenleftex",           0o347)+    , ("parenleftbt",           0o350)+    , ("parenrighttp",          0o366)+    , ("parenrightex",          0o367)+    , ("parenrightbt",          0o370)+    , ("partialdiff",           0o266)+    , ("percent",               0o045)+    , ("period",                0o056)+    , ("perpendicular",         0o136)+    , ("phi",                   0o146)+    , ("phi1",                  0o152)+    , ("pi",                    0o160)+    , ("plus",                  0o053)+    , ("plusminus",             0o261)+    , ("product",               0o325)+    , ("propersubset",          0o314)+    , ("propersuperset",        0o311)+    , ("proportional",          0o265)+    , ("psi",                   0o171)+    , ("question",              0o077)+    , ("radical",               0o326)+    , ("radicalex",             0o140)+    , ("reflexsubset",          0o315)+    , ("reflexsuperset",        0o312)+    , ("registersans",          0o342)+    , ("registerserif",         0o322)+    , ("rho",                   0o162)+    , ("second",                0o262)+    , ("semicolon",             0o073)+    , ("seven",                 0o067)+    , ("sigma",                 0o163)+    , ("sigma1",                0o126)+    , ("similar",               0o176)+    , ("six",                   0o066)+    , ("slash",                 0o057)+    , ("space",                 0o040)+    , ("spade",                 0o252)+    , ("suchthat",              0o047)+    , ("summation",             0o345)+    , ("tau",                   0o164)+    , ("therefore",             0o134)+    , ("theta",                 0o161)+    , ("theta1",                0o112)+    , ("three",                 0o063)+    , ("trademarksans",         0o344)+    , ("trademarkserif",        0o324)+    , ("two",                   0o062)+    , ("underscore",            0o137)+    , ("union",                 0o310)+    , ("universal",             0o042)+    , ("upsilon",               0o165)+    , ("weierstrass",           0o303)+    , ("xi",                    0o170)+    , ("zero",                  0o060)+    , ("zeta",                  0o172)+    ]
+ src/Wumpus/Core/Text/TextInternal.hs view
@@ -0,0 +1,173 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Core.Text.TextInternal+-- Copyright   :  (c) Stephen Tetley 2009-2010+-- License     :  BSD3+--+-- Maintainer  :  stephen.tetley@gmail.com+-- Stability   :  unstable+-- Portability :  GHC+--+-- Extended character handling.+-- +--------------------------------------------------------------------------------++module Wumpus.Core.Text.TextInternal+  ( ++    EncodedText(..)    +  , TextChunk(..)+  , EncodedChar(..)++  , textLength+  , lookupByCharCode  +  , lookupByGlyphName+  , getSvgFallback+  , getPsFallback+  +  , lexLabel++  ) where++import Wumpus.Core.Text.Encoder+import Wumpus.Core.Utils.FormatCombinators++import Data.Char+import qualified Data.Map as Map++newtype EncodedText = EncodedText { getEncodedText :: [TextChunk] }+  deriving (Eq,Show)++-- | Wumpus supports both escaped names e.g. @egrave@ and escaped+-- (numeric decimal) character codes in the input string for a +-- TextLabel.+-- +data TextChunk = TextSpan    String+               | TextEscInt  Int+               | TextEscName GlyphName+  deriving (Eq,Show)++-- | For KernLabels Wumpus needs a Char version of TextChunk.+--+data EncodedChar = CharLiteral Char+                 | CharEscInt  Int+                 | CharEscName GlyphName+  deriving (Eq,Show)+++--------------------------------------------------------------------------------++instance Format EncodedText where+  format = hcat . map format . getEncodedText++instance Format TextChunk where+  format (TextSpan s)    = text s+  format (TextEscInt i)  = text "&#" <> int i  <> semicolon+  format (TextEscName s) = text "&#" <> text s <> semicolon++instance Format EncodedChar where+  format (CharLiteral c) = char c+  format (CharEscInt i)  = text "&#" <> int i  <> semicolon+  format (CharEscName s) = text "&#" <> text s <> semicolon+++--------------------------------------------------------------------------------+++textLength :: EncodedText -> Int+textLength = foldr add 0 . getEncodedText where +    add (TextSpan s) n = n + length s+    add _            n = n + 1+++lookupByCharCode :: FontEncoderName -> CharCode -> TextEncoder -> Maybe GlyphName+lookupByCharCode name i enc = +    Map.lookup name (font_encoder_map enc) >>= \a -> (ps_lookup a) i++lookupByGlyphName :: FontEncoderName -> GlyphName -> TextEncoder -> Maybe CharCode+lookupByGlyphName name i enc = +    Map.lookup name (font_encoder_map enc) >>= \a -> (svg_lookup a) i+++getSvgFallback :: FontEncoderName -> TextEncoder -> CharCode+getSvgFallback name enc = case Map.lookup name (font_encoder_map enc) of+   Just fe -> svg_fallback fe +   Nothing -> 0o040                     -- wild guess++getPsFallback :: FontEncoderName -> TextEncoder -> GlyphName+getPsFallback name enc = case Map.lookup name (font_encoder_map enc) of+   Just fe -> ps_fallback fe +   Nothing -> "space"                    -- wild guess+++-- | 'lexLabel' input is regular text and escaped glyph names or+-- decimal character codes. Escaping follows the SVG convention,+-- start with @&#@ (ampersand hash) end with @;@ (semicolon).+--+-- Special chars are output to PostScript as:+--+-- > /egrave glyphshow+--+-- Special chars are output to SVG as an escaped decimal, e.g.:+--+-- > &#232;+--+-- Note, HTML entity names do not seem to be supported in SVG,+-- @ &egrave; @ does not work in FireFox or Chrome.+--+lexLabel :: String -> EncodedText+lexLabel = EncodedText . lexer++-- Note - the lexer reads number spans with isDigit, so reads +-- decimals only.+-- +lexer :: String -> [TextChunk]+lexer []            = []+lexer ('&':'#':cs)  = escStart cs+lexer (c:cs)        = let (ss,rest) = span (/= '&') cs +                      in TextSpan (c:ss) : lexer rest++escStart :: String -> [TextChunk]+escStart ('0':'o':cs)           = escOct cs+escStart ('0':'O':cs)           = escOct cs+escStart ('0':'x':cs)           = escHex cs+escStart ('0':'X':cs)           = escHex cs+escStart (c:cs) | isDigit c     = escDec (digitToInt c) cs+escStart (c:cs)                 = let (ss,rest) = span isAlphaNum cs +                                  in TextEscName (c:ss) : chompToSemi rest+escStart []                     = [] ++-- | One digit consumed already...+--+escDec :: Int -> String -> [TextChunk]+escDec n (c:cs) | isDigit c = escDec (n*10 + digitToInt c) cs+escDec n cs     | n > 0     = TextEscInt n : chompToSemi cs+                | otherwise = chompToSemi cs++escHex :: String -> [TextChunk]+escHex = step 0+  where+    step n (c:cs) | isHexDigit c = step (n*16 + digitToInt c) cs+    step n cs     | n > 0        = TextEscInt n : chompToSemi cs+                  | otherwise    = chompToSemi cs +++escOct :: String -> [TextChunk]+escOct = step 0+  where+    step n (c:cs) | isHexDigit c = step (n*8 + digitToInt c) cs+    step n cs     | n > 0        = TextEscInt n : chompToSemi cs+                  | otherwise    = chompToSemi cs ++++-- The last two conditions both indicate ill-formed input, but it+-- is /best/ if the lexer does not throw errors.+-- +chompToSemi :: String -> [TextChunk]+chompToSemi (';':cs) = lexer cs+chompToSemi (_:cs)   = chompToSemi cs           +chompToSemi []       = []+
− src/Wumpus/Core/TextDefaultEncoder.hs
@@ -1,44 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module      :  Wumpus.Core.TextDefaultEncoder--- Copyright   :  (c) Stephen Tetley 2010--- License     :  BSD3------ Maintainer  :  stephen.tetley@gmail.com--- Stability   :  unstable--- Portability :  GHC------ This is the default Text encoder with lookups for both Latin1--- and Symbol font.--------------------------------------------------------------------------------------module Wumpus.Core.TextDefaultEncoder-  ( -    defaultEncoder--  ) where--import Wumpus.Core.TextEncoder-import Wumpus.Core.TextLatin1-import Wumpus.Core.TextSymbolFont--import Data.Map----- | This is the default encoder supporting names and codes for --- both Latin1 and the Symbol font.----defaultEncoder :: TextEncoder-defaultEncoder = TextEncoder-      { svg_encoding_name       = "ISO-8859-1"-      , font_encoder_map        = fem-      }-  where-    fem = insert symbol_font_encoder symbolFontEncoder -        $ insert latin1_font_encoder latin1FontEncoder-        $ empty --
− src/Wumpus/Core/TextEncoder.hs
@@ -1,143 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module      :  Wumpus.Core.TextEncoder--- Copyright   :  (c) Stephen Tetley 2009-2010--- License     :  BSD3------ Maintainer  :  stephen.tetley@gmail.com--- Stability   :  unstable--- Portability :  GHC------ Extended character code handling.--- --- Wumpus uses SVG style escaping to embed character codes or --- names in regular strings:------ > "regular ascii text &#egrave; more ascii text"---  --- i.e. character names and codes are delimited by @&\#@ on the --- left and @;@ on the right.------ In Wumpus both character names and character codes can--- be embedded in strings - (e.g. @ &\#egrave; or &\#232; @).------ Character codes can be also be expressed as octal or --- hexadecimal:------ > myst&#0o350;re------ > myst&#0xE8;re------ In the generated PostScript, Wumpus uses the character name, --- e.g.:  ------ > (myst) show /egrave glyphshow (re) show--- --- The generated SVG uses the numeric code, e.g.: ------ > myst&#232;re------ To accommodate both, Wumpus defines a TextEncoder record which--- provides a two-way mapping between character codes and glyph --- names for a character set.--------------------------------------------------------------------------------------module Wumpus.Core.TextEncoder-  ( -    GlyphName-  , CharCode-  , PostScriptLookup-  , SVGLookup--  , FontEncoderName(..)-  , TextEncoder(..)-  , FontEncoder(..)--  ) where--import Data.Map-import Data.Word--type GlyphName        = String-type CharCode         = Int --type PostScriptLookup = CharCode -> Maybe GlyphName-type SVGLookup        = GlyphName -> Maybe CharCode------ | Font encoder name - a newtype wrapped /number/.--- --- Ideally this would be an enumerated type, but it has to be --- open - new encoders need to be added, so an enum is out of the--- question.------ A String would be good, but would have slow lookup when used --- as a key. Dealing with multiple encoders was added late to --- Wumpus-Core - it is necessary, but taking a performace hit --- because of it is chagrin. So instead /uniquely/ asssigned--- numbers are used.------ Numbers below 10000 are reserved for Wumpus, though it is --- unlikely to need more than a handful. Numbers above are free --- to use (clearly clashes are possible, but probably unlikely).--- --- Wumpus-Core assigns the following, other Wumpus libraries may --- assign more:------ > 0 - Latin1 (for Helvetica, Times Roman, Courier...)------ > 1 - Symbol Font--- -newtype FontEncoderName = FontEncoderName { getFontEncoderName :: Word16 }-  deriving (Eq,Ord)--instance Show FontEncoderName where-  show = step . getFontEncoderName-    where-      step 0 = "Latin1"-      step 1 = "Symbol-Font"-      step n = show n---- | 'TextEncoder'------ An /instance/ needs: ------ * A map of FontEncoderNames to FontEncoders.------ * The name of the encoding - this is printed in the xml --- prologue of the SVG file as the @encoding@ attribute. Latin --- 1\'s official name is seemingly \"ISO-8859-1\". --- --- * The name of the default encoder - this should naturally be --- in the Font Encoder map.--- --- -data TextEncoder = TextEncoder-      { svg_encoding_name       :: String-      , font_encoder_map        :: Map FontEncoderName FontEncoder-      }---- | 'FontEncoder'.------ * The functions for looking up codes by glyph-name and --- glyph-name by code. --- --- * Fallback glyph-names and char codes in case lookup fails.--- --- "Wumpus.Core.TextLatin1" defines an implementation for Latin 1.----data FontEncoder = FontEncoder  -      { ps_lookup           :: PostScriptLookup-      , svg_lookup          :: SVGLookup-      , ps_fallback         :: GlyphName-      , svg_fallback        :: CharCode-      }-                     ---- no show instance as a TextEncoder contains functions.--
− src/Wumpus/Core/TextInternal.hs
@@ -1,173 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module      :  Wumpus.Core.TextInternal--- Copyright   :  (c) Stephen Tetley 2009-2010--- License     :  BSD3------ Maintainer  :  stephen.tetley@gmail.com--- Stability   :  unstable--- Portability :  GHC------ Extended character handling.--- -----------------------------------------------------------------------------------module Wumpus.Core.TextInternal-  ( --    EncodedText(..)    -  , TextChunk(..)-  , EncodedChar(..)--  , textLength-  , lookupByCharCode  -  , lookupByGlyphName-  , getSvgFallback-  , getPsFallback-  -  , lexLabel--  ) where--import Wumpus.Core.FormatCombinators-import Wumpus.Core.TextEncoder--import Data.Char-import qualified Data.Map as Map--newtype EncodedText = EncodedText { getEncodedText :: [TextChunk] }-  deriving (Eq,Show)---- | Wumpus supports both escaped names e.g. @egrave@ and escaped--- (numeric decimal) character codes in the input string for a --- TextLabel.--- -data TextChunk = TextSpan    String-               | TextEscInt  Int-               | TextEscName GlyphName-  deriving (Eq,Show)---- | For KernLabels Wumpus needs a Char version of TextChunk.----data EncodedChar = CharLiteral Char-                 | CharEscInt  Int-                 | CharEscName GlyphName-  deriving (Eq,Show)-------------------------------------------------------------------------------------instance Format EncodedText where-  format = hcat . map format . getEncodedText--instance Format TextChunk where-  format (TextSpan s)    = text s-  format (TextEscInt i)  = text "&#" <> int i  <> semicolon-  format (TextEscName s) = text "&#" <> text s <> semicolon--instance Format EncodedChar where-  format (CharLiteral c) = char c-  format (CharEscInt i)  = text "&#" <> int i  <> semicolon-  format (CharEscName s) = text "&#" <> text s <> semicolon--------------------------------------------------------------------------------------textLength :: EncodedText -> Int-textLength = foldr add 0 . getEncodedText where -    add (TextSpan s) n = n + length s-    add _            n = n + 1---lookupByCharCode :: FontEncoderName -> CharCode -> TextEncoder -> Maybe GlyphName-lookupByCharCode name i enc = -    Map.lookup name (font_encoder_map enc) >>= \a -> (ps_lookup a) i--lookupByGlyphName :: FontEncoderName -> GlyphName -> TextEncoder -> Maybe CharCode-lookupByGlyphName name i enc = -    Map.lookup name (font_encoder_map enc) >>= \a -> (svg_lookup a) i---getSvgFallback :: FontEncoderName -> TextEncoder -> CharCode-getSvgFallback name enc = case Map.lookup name (font_encoder_map enc) of-   Just fe -> svg_fallback fe -   Nothing -> 0o040                     -- wild guess--getPsFallback :: FontEncoderName -> TextEncoder -> GlyphName-getPsFallback name enc = case Map.lookup name (font_encoder_map enc) of-   Just fe -> ps_fallback fe -   Nothing -> "space"                    -- wild guess----- | 'lexLabel' input is regular text and escaped glyph names or--- decimal character codes. Escaping follows the SVG convention,--- start with @&#@ (ampersand hash) end with @;@ (semicolon).------ Special chars are output to PostScript as:------ > /egrave glyphshow------ Special chars are output to SVG as an escaped decimal, e.g.:------ > &#232;------ Note, HTML entity names do not seem to be supported in SVG,--- @ &egrave; @ does not work in FireFox or Chrome.----lexLabel :: String -> EncodedText-lexLabel = EncodedText . lexer---- Note - the lexer reads number spans with isDigit, so reads --- decimals only.--- -lexer :: String -> [TextChunk]-lexer []            = []-lexer ('&':'#':cs)  = escStart cs-lexer (c:cs)        = let (ss,rest) = span (/= '&') cs -                      in TextSpan (c:ss) : lexer rest--escStart :: String -> [TextChunk]-escStart ('0':'o':cs)           = escOct cs-escStart ('0':'O':cs)           = escOct cs-escStart ('0':'x':cs)           = escHex cs-escStart ('0':'X':cs)           = escHex cs-escStart (c:cs) | isDigit c     = escDec (digitToInt c) cs-escStart (c:cs)                 = let (ss,rest) = span isAlphaNum cs -                                  in TextEscName (c:ss) : chompToSemi rest-escStart []                     = [] ---- | One digit consumed already...----escDec :: Int -> String -> [TextChunk]-escDec n (c:cs) | isDigit c = escDec (n*10 + digitToInt c) cs-escDec n cs     | n > 0     = TextEscInt n : chompToSemi cs-                | otherwise = chompToSemi cs--escHex :: String -> [TextChunk]-escHex = step 0-  where-    step n (c:cs) | isHexDigit c = step (n*16 + digitToInt c) cs-    step n cs     | n > 0        = TextEscInt n : chompToSemi cs-                  | otherwise    = chompToSemi cs ---escOct :: String -> [TextChunk]-escOct = step 0-  where-    step n (c:cs) | isHexDigit c = step (n*8 + digitToInt c) cs-    step n cs     | n > 0        = TextEscInt n : chompToSemi cs-                  | otherwise    = chompToSemi cs ------ The last two conditions both indicate ill-formed input, but it--- is /best/ if the lexer does not throw errors.--- -chompToSemi :: String -> [TextChunk]-chompToSemi (';':cs) = lexer cs-chompToSemi (_:cs)   = chompToSemi cs           -chompToSemi []       = []-
− src/Wumpus/Core/TextLatin1.hs
@@ -1,257 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module      :  Wumpus.Core.TextLatin1--- Copyright   :  (c) Stephen Tetley 2009-2010--- License     :  BSD3------ Maintainer  :  stephen.tetley@gmail.com--- Stability   :  unstable--- Portability :  GHC------ A TextEncoder record instance for Latin1 characters.--- -----------------------------------------------------------------------------------module Wumpus.Core.TextLatin1-  ( -  -    latin1_font_encoder-  , latin1FontEncoder-  , latin1FontAll--  ) where--import Wumpus.Core.TextEncoder--import qualified Data.Map as Map----- | Latin1 Font Encoder name ---  --- (Number 0) ----latin1_font_encoder :: FontEncoderName-latin1_font_encoder = FontEncoderName 0---- | Latin1 FontEncoder instance.-latin1FontEncoder :: FontEncoder-latin1FontEncoder = FontEncoder -    { ps_lookup         = Map.lookup `flip` codeToName-    , svg_lookup        = Map.lookup `flip` nameToCode-    , ps_fallback       = "space"-    , svg_fallback      = 0o040-    }--nameToCode :: Map.Map GlyphName CharCode-nameToCode = Map.fromList latin1FontAll--codeToName :: Map.Map CharCode GlyphName-codeToName = foldr fn Map.empty latin1FontAll where-  fn (s,i) a = Map.insert i s a ---- | A lookup list of Latin 1 names to their octal code.-latin1FontAll :: [(GlyphName, CharCode)]-latin1FontAll = -    [ ("A",                     0o101)-    , ("AE",                    0o306)-    , ("Aacute",                0o301)-    , ("Acircumflex",           0o302)-    , ("Adieresis",             0o304)-    , ("Agrave",                0o300)-    , ("Aring",                 0o305)-    , ("Atilde",                0o303)-    , ("B",                     0o102)-    , ("C",                     0o103)-    , ("Ccedilla",              0o307)-    , ("D",                     0o104)-    , ("E",                     0o105)-    , ("Eacute",                0o311)-    , ("Ecircumflex",           0o312)-    , ("Edieresis",             0o313)-    , ("Egrave",                0o310)-    , ("Eth",                   0o320)-    , ("F",                     0o106)-    , ("G",                     0o107)-    , ("H",                     0o110)-    , ("I",                     0o111)-    , ("Iacute",                0o315)-    , ("Icircumflex",           0o316)-    , ("Idieresis",             0o317)-    , ("Igrave",                0o314)-    , ("J",                     0o112)-    , ("K",                     0o113)-    , ("L",                     0o114)-    , ("M",                     0o115)-    , ("N",                     0o116)-    , ("Ntilde",                0o321)-    , ("O",                     0o117)-    , ("Oacute",                0o323)-    , ("Ocircumflex",           0o324)-    , ("Odieresis",             0o326)-    , ("Ograve",                0o322)-    , ("Oslash",                0o351)-    , ("Otilde",                0o325)-    , ("P",                     0o120)-    , ("Q",                     0o121)-    , ("R",                     0o122)-    , ("S",                     0o123)-    , ("T",                     0o124)-    , ("Thorn",                 0o336)-    , ("U",                     0o125)-    , ("Uacute",                0o332)-    , ("Ucircumflex",           0o333)-    , ("Udieresis",             0o334)-    , ("Ugrave",                0o331)-    , ("V",                     0o126)-    , ("W",                     0o127)-    , ("X",                     0o130)-    , ("Y",                     0o131)-    , ("Yacute",                0o335)-    , ("Z",                     0o132)-    , ("a",                     0o141)-    , ("aacute",                0o341)-    , ("acircumflex",           0o342)-    , ("acute2",                0o264)-    , ("adieresis",             0o344)-    , ("ae",                    0o346)-    , ("agrave",                0o340)-    , ("ampersand",             0o046)-    , ("aring",                 0o345)-    , ("asciicircum",           0o136)-    , ("asciitilde",            0o176)-    , ("asterisk",              0o052)-    , ("at",                    0o100)-    , ("atilde",                0o343)-    , ("b",                     0o142)-    , ("backslash",             0o134)-    , ("bar",                   0o174)-    , ("braceleft",             0o173)-    , ("braceright",            0o175)-    , ("bracketleft",           0o133)-    , ("bracketright",          0o135)-    , ("breve",                 0o226)-    , ("brokenbar",             0o246)-    , ("c",                     0o143)-    , ("caron",                 0o237)-    , ("ccedilla",              0o347)-    , ("cedilla",               0o270)-    , ("cent",                  0o242)-    , ("circumflex",            0o223)-    , ("colon",                 0o072)-    , ("comma",                 0o054)-    , ("copyright",             0o251)-    , ("currency",              0o244)-    , ("d",                     0o144)-    , ("degree",                0o260)-    , ("dieresis",              0o250)-    , ("divide",                0o367)-    , ("dollar",                0o044)-    , ("dotaccent",             0o227)-    , ("dotlessi",              0o220)-    , ("e",                     0o145)-    , ("eacute",                0o351)-    , ("ecircumflex",           0o352)-    , ("edieresis",             0o353)-    , ("egrave",                0o350)-    , ("eight",                 0o070)-    , ("equal",                 0o075)-    , ("eth",                   0o360)-    , ("exclam",                0o041)-    , ("exclamdown",            0o241)-    , ("f",                     0o146)-    , ("five",                  0o065)-    , ("four",                  0o064)-    , ("g",                     0o147)-    , ("germandbls",            0o337)-    , ("grave",                 0o221)-    , ("greater",               0o076)-    , ("guillemotleft",         0o253)-    , ("guillemotright",        0o273)-    , ("h",                     0o150)-    , ("hungarumlaut",          0o235)-    , ("hyphen",                0o255)-    , ("i",                     0o151)-    , ("iacute",                0o355)-    , ("icircumflex",           0o356)-    , ("idieresis",             0o357)-    , ("igrave",                0o354)-    , ("j",                     0o152)-    , ("k",                     0o153)-    , ("l",                     0o154)-    , ("less",                  0o074)-    , ("logicalnot",            0o254)-    , ("m",                     0o155)-    , ("macron",                0o257)-    , ("minus",                 0o055)-    , ("mu",                    0o265)-    , ("multiply",              0o327)-    , ("n",                     0o156)-    , ("nine",                  0o071)-    , ("ntilde",                0o361)-    , ("numbersign",            0o043)-    , ("o",                     0o157)-    , ("oacute",                0o363)-    , ("ocircumflex",           0o364)-    , ("odieresis",             0o366)-    , ("ogonek",                0o236)-    , ("ograve",                0o362)-    , ("one",                   0o061)-    , ("onehalf",               0o275)-    , ("onequarter",            0o274)-    , ("onesuperior",           0o271)-    , ("ordfeminine",           0o252)-    , ("ordmasculine",          0o272)-    , ("oslash",                0o370)-    , ("otilde",                0o365)-    , ("p",                     0o160)-    , ("paragraph",             0o266)-    , ("parenleft",             0o050)-    , ("parenright",            0o051)-    , ("percent",               0o045)-    , ("period",                0o056)-    , ("periodcentered",        0o267)-    , ("plus",                  0o053)-    , ("plusminus",             0o261)-    , ("q",                     0o161)-    , ("question",              0o077)-    , ("questiondown",          0o277)-    , ("quotedbl",              0o042)-    , ("quoteleft",             0o140)-    , ("quoteright",            0o047)-    , ("r",                     0o162)-    , ("registered",            0o256)-    , ("ring",                  0o232)-    , ("s",                     0o163)-    , ("section",               0o247)-    , ("semicolon",             0o073)-    , ("seven",                 0o067)-    , ("six",                   0o066)-    , ("slash",                 0o057)-    , ("space",                 0o040)-    , ("sterling",              0o243)-    , ("t",                     0o164)-    , ("thorn",                 0o376)-    , ("three",                 0o063)-    , ("threequarters",         0o276)-    , ("threesuperior",         0o263)-    , ("tilde",                 0o224)-    , ("two",                   0o062)-    , ("twosuperior",           0o262)-    , ("u",                     0o165)-    , ("uacute",                0o372)-    , ("ucircumflex",           0o373)-    , ("udieresis",             0o374)-    , ("ugrave",                0o371)-    , ("underscore",            0o137)-    , ("v",                     0o166)-    , ("w",                     0o167)-    , ("x",                     0o170)-    , ("y",                     0o171)-    , ("yacute",                0o375)-    , ("ydieresis",             0o377)-    , ("yen",                   0o245)-    , ("z",                     0o172)-    , ("zero",                  0o060)-    ]
− src/Wumpus/Core/TextSymbolFont.hs
@@ -1,249 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module      :  Wumpus.Core.TextSymbolFont--- Copyright   :  (c) Stephen Tetley 2010--- License     :  BSD3------ Maintainer  :  stephen.tetley@gmail.com--- Stability   :  unstable--- Portability :  GHC------ A TextEncoder record instance for Symbol font characters.--- -----------------------------------------------------------------------------------module Wumpus.Core.TextSymbolFont-  ( -  -    symbol_font_encoder-  , symbolFontEncoder-  , symbolFontAll--  ) where--import Wumpus.Core.TextEncoder--import qualified Data.Map as Map------ | Symbol Font Encoder name ------ (Number 1)--- -symbol_font_encoder :: FontEncoderName-symbol_font_encoder = FontEncoderName 1------ | Latin1 TextEncoder instance.-symbolFontEncoder :: FontEncoder-symbolFontEncoder = FontEncoder -    { ps_lookup         = Map.lookup `flip` codeToName-    , svg_lookup        = Map.lookup `flip` nameToCode-    , ps_fallback       = "space"-    , svg_fallback      = 0o040-    }--nameToCode :: Map.Map GlyphName CharCode-nameToCode = Map.fromList symbolFontAll--codeToName :: Map.Map CharCode GlyphName-codeToName = foldr fn Map.empty symbolFontAll where-  fn (s,i) a = Map.insert i s a ---- | A lookup list of Latin 1 names to their octal code.-symbolFontAll :: [(GlyphName, CharCode)]-symbolFontAll = -    [ ("Alpha",                 0o101)-    , ("Beta",                  0o102)-    , ("Chi",                   0o103)-    , ("Delta",                 0o104)-    , ("Epsilon",               0o105)-    , ("Eta",                   0o110)-    , ("Euro",                  0o240)-    , ("Gamma",                 0o107)-    , ("Ifraktur",              0o301)-    , ("Iota",                  0o111)-    , ("Kappa",                 0o113)-    , ("Lambda",                0o114)-    , ("Mu",                    0o115)-    , ("Nu",                    0o116)-    , ("Omega",                 0o127)-    , ("Omicron",               0o117)-    , ("Phi",                   0o106)-    , ("Pi",                    0o120)-    , ("Psi",                   0o131)-    , ("Rfraktur",              0o302)-    , ("Rho",                   0o122)-    , ("Sigma",                 0o123)-    , ("Tau",                   0o124)-    , ("Theta",                 0o121)-    , ("Upsilon",               0o125)-    , ("Upsilon1",              0o241)-    , ("Xi",                    0o130)-    , ("Zeta",                  0o132)-    , ("aleph",                 0o300)-    , ("alpha",                 0o141)-    , ("ampersand",             0o046)-    , ("angle",                 0o320)-    , ("angleleft",             0o341)-    , ("angleright",            0o361)-    , ("approxequal",           0o273)-    , ("arrowboth",             0o253)-    , ("arrowdblboth",          0o333)-    , ("arrowdbldown",          0o337)-    , ("arrowdblleft",          0o334)-    , ("arrowdblright",         0o336)-    , ("arrowdblup",            0o335)-    , ("arrowdown",             0o257)-    , ("arrowhorizex",          0o276)-    , ("arrowleft",             0o254)-    , ("arrowright",            0o256)-    , ("arrowup",               0o255)-    , ("arrowvertex",           0o275)-    , ("asteriskmath",          0o052)-    , ("bar",                   0o174)-    , ("beta",                  0o142)-    , ("braceleft",             0o173)-    , ("braceright",            0o175)-    , ("bracelefttp",           0o354)-    , ("braceleftmid",          0o355)-    , ("braceleftbt",           0o356)-    , ("bracerighttp",          0o374)-    , ("bracerightmid",         0o375)-    , ("bracerightbt",          0o376)-    , ("braceex",               0o357)-    , ("bracketleft",           0o133)-    , ("bracketright",          0o135)-    , ("bracketlefttp",         0o351)-    , ("bracketleftex",         0o352)-    , ("bracketleftbt",         0o353)-    , ("bracketrighttp",        0o371)-    , ("bracketrightex",        0o372)-    , ("bracketrightbt",        0o373)-    , ("bullet",                0o267)-    , ("carriagereturn",        0o277)-    , ("chi",                   0o143)-    , ("circlemultiply",        0o304)-    , ("circleplus",            0o305)-    , ("club",                  0o247)-    , ("colon",                 0o072)-    , ("comma",                 0o054)-    , ("congruent",             0o100)-    , ("copyrightsans",         0o343)-    , ("copyrightserif",        0o323)-    , ("degree",                0o260)-    , ("delta",                 0o144)-    , ("diamond",               0o250)-    , ("divide",                0o270)-    , ("dotmath",               0o327)-    , ("eight",                 0o070)-    , ("element",               0o316)-    , ("ellipsis",              0o274)-    , ("emptyset",              0o306)-    , ("epsilon",               0o145)-    , ("equal",                 0o075)-    , ("equivalence",           0o272)-    , ("eta",                   0o150)-    , ("exclam",                0o041)-    , ("existential",           0o044)-    , ("five",                  0o065)-    , ("florin",                0o246)-    , ("four",                  0o064)-    , ("fraction",              0o244)-    , ("gamma",                 0o147)-    , ("gradient",              0o321)-    , ("greater",               0o076)-    , ("greaterequal",          0o263)-    , ("heart",                 0o251)-    , ("infinity",              0o245)-    , ("integral",              0o362)-    , ("integraltp",            0o363)-    , ("integralex",            0o364)-    , ("integralbt",            0o365)-    , ("intersection",          0o307)-    , ("iota",                  0o151)-    , ("kappa",                 0o153)-    , ("lambda",                0o154)-    , ("less",                  0o074)-    , ("lessequal",             0o243)-    , ("logicaland",            0o331)-    , ("logicalnot",            0o330)-    , ("logicalor",             0o332)-    , ("lozenge",               0o340)-    , ("minus",                 0o055)-    , ("minute",                0o242)-    , ("mu",                    0o155)-    , ("multiply",              0o264)-    , ("nine",                  0o071)-    , ("notelement",            0o317)-    , ("notequal",              0o271)-    , ("notsubset",             0o313)-    , ("nu",                    0o156)-    , ("numbersign",            0o043)-    , ("omega",                 0o167)-    , ("omega1",                0o166)-    , ("omicron",               0o157)-    , ("one",                   0o061)-    , ("parenleft",             0o050)-    , ("parenright",            0o051)-    , ("parenlefttp",           0o346)-    , ("parenleftex",           0o347)-    , ("parenleftbt",           0o350)-    , ("parenrighttp",          0o366)-    , ("parenrightex",          0o367)-    , ("parenrightbt",          0o370)-    , ("partialdiff",           0o266)-    , ("percent",               0o045)-    , ("period",                0o056)-    , ("perpendicular",         0o136)-    , ("phi",                   0o146)-    , ("phi1",                  0o152)-    , ("pi",                    0o160)-    , ("plus",                  0o053)-    , ("plusminus",             0o261)-    , ("product",               0o325)-    , ("propersubset",          0o314)-    , ("propersuperset",        0o311)-    , ("proportional",          0o265)-    , ("psi",                   0o171)-    , ("question",              0o077)-    , ("radical",               0o326)-    , ("radicalex",             0o140)-    , ("reflexsubset",          0o315)-    , ("reflexsuperset",        0o312)-    , ("registersans",          0o342)-    , ("registerserif",         0o322)-    , ("rho",                   0o162)-    , ("second",                0o262)-    , ("semicolon",             0o073)-    , ("seven",                 0o067)-    , ("sigma",                 0o163)-    , ("sigma1",                0o126)-    , ("similar",               0o176)-    , ("six",                   0o066)-    , ("slash",                 0o057)-    , ("space",                 0o040)-    , ("spade",                 0o252)-    , ("suchthat",              0o047)-    , ("summation",             0o345)-    , ("tau",                   0o164)-    , ("therefore",             0o134)-    , ("theta",                 0o161)-    , ("theta1",                0o112)-    , ("three",                 0o063)-    , ("trademarksans",         0o344)-    , ("trademarkserif",        0o324)-    , ("two",                   0o062)-    , ("underscore",            0o137)-    , ("union",                 0o310)-    , ("universal",             0o042)-    , ("upsilon",               0o165)-    , ("weierstrass",           0o303)-    , ("xi",                    0o170)-    , ("zero",                  0o060)-    , ("zeta",                  0o172)-    ]
+ src/Wumpus/Core/TrafoInternal.hs view
@@ -0,0 +1,138 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Core.TrafoInternal+-- Copyright   :  (c) Stephen Tetley 2010+-- License     :  BSD3+--+-- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>+-- Stability   :  unstable +-- Portability :  GHC+--+-- Transformations on (Path) Primtives in Wumpus-Core are +-- performed on the control points rather than transmitted to +-- PostScript. +-- +-- However because text labels are opaque to Wumpus, the corner+-- start point is manipulated in Wumpus, but transformations on +-- the actual text are communicated to PostScript as matrix +-- transformations. +-- +--------------------------------------------------------------------------------+++module Wumpus.Core.TrafoInternal+  (++  -- * Types+    PrimCTM(..)+  , AffineTrafo(..) ++  -- * CTM operations+  , identityCTM+  , thetaCTM++  , scaleCTM+  , rotateCTM+  , matrixRepCTM+  , translMatrixRepCTM++  -- * AffineTrafo operations+  , concatTrafos+  , matrixRepr+  +  ) where+++import Wumpus.Core.Geometry+import Wumpus.Core.Utils.Common+import Wumpus.Core.Utils.FormatCombinators+++-- Primitives support affine transformations.+--+-- The control points of a path, baseline-left of text or center+-- of ellipse are transformed as points; scaling and rotation +-- or text and ellipses are transmitted to PostScript and SVG.+-- +-- Note - line thickness of a stroked path will not be scaled.+--+data PrimCTM u = PrimCTM +      { ctm_scale_x     :: u+      , ctm_scale_y     :: u+      , ctm_rotation    :: Radian +      }+  deriving (Eq,Show)+++++-- | 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+  deriving (Eq,Show)                 +++++instance PSUnit u => Format (PrimCTM u) where+  format (PrimCTM x y ang) = +      parens (text "CTM" <+> text "sx="   <> dtruncFmt x +                         <+> text "sy="   <> dtruncFmt y +                         <+> text "ang="  <> format ang  )+++++--------------------------------------------------------------------------------+-- Manipulating the PrimCTM++identityCTM :: Num u => PrimCTM u+identityCTM = PrimCTM { ctm_scale_x = 1, ctm_scale_y = 1, ctm_rotation = 0 }++thetaCTM :: Num u => Radian -> PrimCTM u+thetaCTM ang = PrimCTM { ctm_scale_x = 1, ctm_scale_y = 1, ctm_rotation = ang }++scaleCTM :: Num u => u -> u -> PrimCTM u -> PrimCTM u+scaleCTM x1 y1 (PrimCTM sx sy ang) = PrimCTM (x1*sx) (y1*sy) ang++rotateCTM :: Radian -> PrimCTM u -> PrimCTM u+rotateCTM ang1 (PrimCTM sx sy ang) = PrimCTM sx sy (circularModulo $ ang1+ang)++matrixRepCTM :: (Floating u, Real u) => PrimCTM u -> Matrix3'3 u+matrixRepCTM (PrimCTM sx sy ang) = +    rotationMatrix (circularModulo ang) * scalingMatrix sx sy+++-- Note - the order of combining a translation (i.e. the location +-- of a point) and the CTM is crucial as matrix multiplication is +-- not commutative.+--+-- This function encapsulates the correct order.+--+translMatrixRepCTM :: (Floating u, Real u) +                   => u -> u -> PrimCTM u -> Matrix3'3 u+translMatrixRepCTM x y ctm = translationMatrix x y * matrixRepCTM ctm+++--------------------------------------------------------------------------------+-- AffineTrafo operations++++concatTrafos :: (Floating u, Real u) => [AffineTrafo u] -> Matrix3'3 u+concatTrafos = foldr (\e ac -> matrixRepr e * ac) identityMatrix++matrixRepr :: (Floating u, Real u) => AffineTrafo u -> Matrix3'3 u+matrixRepr (Matrix mtrx)        = mtrx+matrixRepr (Rotate theta)       = rotationMatrix theta+matrixRepr (RotAbout theta pt)  = originatedRotationMatrix theta pt+matrixRepr (Scale sx sy)        = scalingMatrix sx sy +matrixRepr (Translate dx dy)    = translationMatrix dx dy+
− src/Wumpus/Core/Utils.hs
@@ -1,192 +0,0 @@-{-# LANGUAGE FlexibleInstances          #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module      :  Wumpus.Core.Utils--- Copyright   :  (c) Stephen Tetley 2009-2010--- License     :  BSD3------ Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>--- Stability   :  highly unstable--- Portability :  GHC------ Utility functions and a Hughes list.---------------------------------------------------------------------------------------module Wumpus.Core.Utils-  ( --  -- | Opt - maybe strict in Some-    Opt(..)-  , some--  -- | Conditional application-  , applyIf--  , rescale--  -- * Truncate / print a double-  , PSUnit(..)-  , dtruncFmt--  , truncateDouble-  , roundup-  ---  -- * PostScript time stamp-  , psTimeStamp--  -- * Hughes list-  , H-  , emptyH-  , wrapH-  , consH-  , snocH  -  , appendH-  , toListH--  ) where---import qualified Wumpus.Core.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----- | Truncate the printed decimal representation of a Double.--- The is prefered to 'showFFloat' from Numeric as it produces--- shorter representations where appropriate.--- --- 0.000000000 becomes 0.0 rather than however many digs are --- specified.---  -truncateDouble :: Double -> String-truncateDouble d | abs d < 0.0001  = "0.0"-                 | d < 0.0         = '-' :  show (abs tx)-                 | otherwise       = show tx-  where-    tx :: Double-    tx = (realToFrac (roundi (d*1000000.0))) / 1000000.0--roundi :: RealFrac a => a -> Integer-roundi = round---- | Take 'ceilingi' and show.-roundup :: Double -> String-roundup = show . ceilingi---- Avoid those annoying 'Defaulting ...' warnings...-ceilingi :: RealFrac a => a -> Integer-ceilingi = ceiling------------------------------------------------------------------------------------------ | To be used with getZonedTime--psTimeStamp :: ZonedTime -> ShowS-psTimeStamp zt = localTimeS . showChar ' ' . localDayS-  where-    local_tim   = zonedTimeToLocalTime zt-    localTimeS  = timeOfDay  $ localTimeOfDay $ local_tim-    localDayS   = showString $ showGregorian  $ localDay local_tim--timeOfDay :: TimeOfDay -> ShowS-timeOfDay t = -    fn todHour . showChar ':' . fn todMin . showChar ':' . fn (floori . todSec)-  where-    fn f = pad2 (f t) ---pad2 :: Int -> ShowS-pad2 i | i < 10    = ('0':) . shows i-       | otherwise = shows i  ---floori :: RealFrac a => a -> Int-floori = floor--------------------------------------------------------------------------------------- Hughes list--type H a = [a] -> [a]--emptyH :: H a-emptyH = id---wrapH :: a -> H a-wrapH a = consH a id --consH :: a -> H a -> H a-consH a f = (a:) . f--snocH :: H a -> a -> H a-snocH hl a = hl . (a:)--appendH :: H a -> H a -> H a-appendH f g = f . g--toListH :: H a -> [a]-toListH = ($ [])--
+ src/Wumpus/Core/Utils/Common.hs view
@@ -0,0 +1,192 @@+{-# LANGUAGE FlexibleInstances          #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Core.Utils.Common+-- Copyright   :  (c) Stephen Tetley 2009-2010+-- License     :  BSD3+--+-- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>+-- Stability   :  highly unstable+-- Portability :  GHC+--+-- Utility functions and a Hughes list.+--+--------------------------------------------------------------------------------+++module Wumpus.Core.Utils.Common+  ( ++  -- | Opt - maybe strict in Some+    Opt(..)+  , some++  -- | Conditional application+  , applyIf++  , rescale++  -- * Truncate / print a double+  , PSUnit(..)+  , dtruncFmt++  , truncateDouble+  , roundup+  +++  -- * PostScript time stamp+  , psTimeStamp++  -- * Hughes list+  , H+  , emptyH+  , wrapH+  , consH+  , snocH  +  , appendH+  , toListH++  ) where+++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+++-- | Truncate the printed decimal representation of a Double.+-- The is prefered to 'showFFloat' from Numeric as it produces+-- shorter representations where appropriate.+-- +-- 0.000000000 becomes 0.0 rather than however many digs are +-- specified.+--  +truncateDouble :: Double -> String+truncateDouble d | abs d < 0.0001  = "0.0"+                 | d < 0.0         = '-' :  show (abs tx)+                 | otherwise       = show tx+  where+    tx :: Double+    tx = (realToFrac (roundi (d*1000000.0))) / 1000000.0++roundi :: RealFrac a => a -> Integer+roundi = round++-- | Take 'ceilingi' and show.+roundup :: Double -> String+roundup = show . ceilingi++-- Avoid those annoying 'Defaulting ...' warnings...+ceilingi :: RealFrac a => a -> Integer+ceilingi = ceiling+++++--------------------------------------------------------------------------------+++-- | To be used with getZonedTime++psTimeStamp :: ZonedTime -> ShowS+psTimeStamp zt = localTimeS . showChar ' ' . localDayS+  where+    local_tim   = zonedTimeToLocalTime zt+    localTimeS  = timeOfDay  $ localTimeOfDay $ local_tim+    localDayS   = showString $ showGregorian  $ localDay local_tim++timeOfDay :: TimeOfDay -> ShowS+timeOfDay t = +    fn todHour . showChar ':' . fn todMin . showChar ':' . fn (floori . todSec)+  where+    fn f = pad2 (f t) +++pad2 :: Int -> ShowS+pad2 i | i < 10    = ('0':) . shows i+       | otherwise = shows i  +++floori :: RealFrac a => a -> Int+floori = floor++++--------------------------------------------------------------------------------+-- Hughes list++type H a = [a] -> [a]++emptyH :: H a+emptyH = id+++wrapH :: a -> H a+wrapH a = consH a id ++consH :: a -> H a -> H a+consH a f = (a:) . f++snocH :: H a -> a -> H a+snocH hl a = hl . (a:)++appendH :: H a -> H a -> H a+appendH f g = f . g++toListH :: H a -> [a]+toListH = ($ [])++
+ src/Wumpus/Core/Utils/FormatCombinators.hs view
@@ -0,0 +1,384 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Core.Utils.FormatCombinators+-- Copyright   :  (c) Stephen Tetley 2010+-- License     :  BSD3+--+-- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>+-- Stability   :  highly unstable+-- Portability :  GHC+--+-- Formatting combinators - pretty printers without the fitting.+--+--------------------------------------------------------------------------------++module Wumpus.Core.Utils.FormatCombinators+  (+    Doc+  , DocS+  , Format(..)+  , empty+  , showsDoc+  , (<>)+  , (<+>)  +  , vconcat+  , separate+  , hcat+  , hsep+  , vcat++  , text+  , char+  , int+  , integer+  , integral+  , float+  , double++  , space+  , comma+  , semicolon+  , line++  , fill++  , punctuate+  , enclose+  , squotes+  , dquotes+  , parens+  , brackets+  , braces+  , angles++  , lparen+  , rparen+  , lbracket+  , rbracket+  , lbrace+  , rbrace+  , langle+  , rangle++  , list+  , tupled+  , semiBraces++  , indent+    +  ) where++import Data.Monoid+import Numeric++-- | Doc is a Join List ...+--+data Doc = Doc1   ShowS +         | Join   Doc   Doc+         | Line+         | Indent !Int  Doc +++type DocS = Doc -> Doc+++-- Join could be improved...+--+unDoc :: Doc -> ShowS+unDoc = step 0 id+  where+   step _ acc (Doc1 sf)    = acc . sf+   step n acc (Join a b)   = let acc' = step n acc a in step n acc' b+   step n acc Line         = acc . showChar '\n' . indentS n+   step n acc (Indent i d) = step (n+i) (acc . (indentS i)) d+++indentS :: Int -> ShowS+indentS i | i < 1     = id+          | otherwise = showString $ replicate i ' '++runDoc :: Doc -> String+runDoc = ($ "") . unDoc+++instance Show Doc where+  show = runDoc++instance Monoid Doc where+  mempty = empty+  mappend = (<>)+++class Format a where format :: a -> Doc++--------------------------------------------------------------------------------+        +infixr 6 <>, <+>++++-- | Create an empty, zero length document.+--+empty :: Doc+empty = Doc1 id++-- | Create a document from a ShowS function.+--+showsDoc :: ShowS -> Doc+showsDoc = Doc1+++-- | Horizontally concatenate two documents with no space +-- between them.+-- +(<>) :: Doc -> Doc -> Doc+a <> b = Join a b +++-- | Horizontally concatenate two documents with a single space +-- between them.+-- +(<+>) :: Doc -> Doc -> Doc+a <+> b = Join a (Join space b)++-- | Vertical concatenate two documents with a line break.+-- +vconcat :: Doc -> Doc -> Doc+vconcat a b = a <> Line <> b++++separate :: Doc -> [Doc] -> Doc+separate _   []     = empty+separate sep (a:as) = step a as+  where+    step acc []     = acc+    step acc (x:xs) = step (acc <> sep <> x) xs++-- | Horizontally concatenate a list of documents with @(\<\>)@.+--+hcat :: [Doc] -> Doc+hcat = foldr (<>) empty++-- | Horizontally concatenate a list of documents with @(\<+\>)@.+--+hsep :: [Doc] -> Doc+hsep = separate space++-- | Vertically concatenate a list of documents, with a line +-- break between each doc.+--+vcat :: [Doc] -> Doc+vcat []     = empty+vcat (x:xs) = step x xs +  where+    step acc (z:zs) = step (acc `vconcat` z) zs+    step acc []     = acc++-- | Create a document from a literal string.+-- +-- The string should not contain newlines (though this is not +-- enforced). +--+text :: String -> Doc+text = Doc1 . showString+++-- | Create a document from a literal character.+--+-- The char should not be a tab or newline. +--+char :: Char -> Doc+char = Doc1 . showChar++-- | Show the Int as a Doc.+--+-- > int  = text . show+--+int :: Int -> Doc+int  = Doc1 . showInt++-- | Show the Integer as a Doc.+--+integer :: Integer -> Doc+integer = Doc1 . showInt++-- | Show an \"integral value\" as a Doc via 'fromIntegral'.+--+integral :: Integral a => a -> Doc+integral = Doc1 . showInt++-- | Show the Float as a Doc.+--+float :: Double -> Doc+float = Doc1 . showFloat++-- | Show the Double as a Doc.+--+double :: Double -> Doc+double = Doc1 . showFloat+ +-- | Create a Doc containing a single space character.+--+space :: Doc+space = char ' '++-- | Create a Doc containing a comma, \",\".+--+comma :: Doc+comma = char ','++-- | Create a Doc containing a semi colon, \";\".+--+semicolon :: Doc+semicolon = char ';'++-- | Create a Doc containing newline, \"\\n\".+--+line :: Doc +line = char '\n'+++--------------------------------------------------------------------------------++-- | Fill a doc to the supplied length, padding the right-hand+-- side with spaces.+--+-- Note - this function is expensive - it unrolls the functional+-- representation of the String. +-- +-- Also it should only be used for single line Doc\'s.+-- +fill :: Int -> Doc -> Doc+fill i d = Doc1 (padr i ' ' $ unDoc d) ++padr :: Int -> Char -> ShowS -> ShowS+padr i c df = step (length $ df []) +  where+    step len | len >= i  = df+             | otherwise = df . showString (replicate (i-len) c)++--------------------------------------------------------------------------------++-- | Punctuate the Doc list with the separator, producing a Doc. +--+punctuate :: Doc -> [Doc] -> Doc+punctuate _ []     = empty+punctuate _ [x]    = x+punctuate s (x:xs) = x <> s <> punctuate s xs+++-- | Enclose the final Doc within the first two.+--+-- There are no spaces between the documents:+--+-- > enclose l r d = l <> d <> r+--+enclose :: Doc -> Doc -> Doc -> Doc+enclose l r d = l <> d <> r++++-- | Enclose the Doc within single quotes.+--+squotes :: Doc -> Doc+squotes = enclose (char '\'') (char '\'')++-- | Enclose the Doc within double quotes.+--+dquotes :: Doc -> Doc+dquotes = enclose (char '"') (char '"')++-- | Enclose the Doc within parens @()@.+--+parens :: Doc -> Doc+parens = enclose lparen rparen++-- | Enclose the Doc within square brackets @[]@.+--+brackets :: Doc -> Doc+brackets = enclose lbracket rbracket++-- | Enclose the Doc within curly braces @{}@.+--+braces :: Doc -> Doc+braces = enclose lbrace rbrace++-- | Enclose the Doc within angle brackets @\<\>@.+--+angles :: Doc -> Doc+angles = enclose langle rangle++++-- | Create a Doc containing a left paren, \'(\'.+--+lparen :: Doc+lparen = char '('++-- | Create a Doc containing a right paren, \')\'.+--+rparen :: Doc+rparen = char ')'++-- | Create a Doc containing a left square bracket, \'[\'.+--+lbracket :: Doc+lbracket = char '['++-- | Create a Doc containing a right square bracket, \']\'.+--+rbracket :: Doc+rbracket = char ']'++-- | Create a Doc containing a left curly brace, \'{\'.+--+lbrace :: Doc+lbrace = char '{'++-- | Create a Doc containing a right curly brace, \'}\'.+--+rbrace :: Doc+rbrace = char '}'++-- | Create a Doc containing a left angle bracket, \'\<\'.+--+langle :: Doc+langle = char '<'++-- | Create a Doc containing a right angle bracket, \'\>\'.+--+rangle :: Doc+rangle = char '>'++-- | Comma separate the list of documents and enclose in square+-- brackets.+--+list :: [Doc] -> Doc+list = brackets . punctuate comma++-- | Comma separate the list of documents and enclose in parens.+--+tupled :: [Doc] -> Doc+tupled = parens . punctuate comma++-- | Separate the list with a semicolon and enclose in curly +-- braces.+--+semiBraces :: [Doc] -> Doc+semiBraces = braces . punctuate semicolon+++-- | Horizontally indent a Doc.+--+-- Note - this space-prefixes the Doc on /the current line/. It+-- does not indent subsequent lines if the Doc spans multiple +-- lines.+--+indent :: Int -> Doc -> Doc+indent i d | i < 1     = d+           | otherwise = Indent i d++
+ src/Wumpus/Core/Utils/OneList.hs view
@@ -0,0 +1,133 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module      :  Wumpus.Core.Utils.OneList+-- Copyright   :  (c) Stephen Tetley 2009-2010+-- License     :  BSD3+--+-- Maintainer  :  Stephen Tetley <stephen.tetley@gmail.com>+-- Stability   :  highly unstable+-- Portability :  GHC+--+-- Data type for non-empty lists.+-- +--------------------------------------------------------------------------------++module Wumpus.Core.Utils.OneList+  (+   -- OneMany+    OneList+  , ViewL(..)++  , one+  , cons+  , head+  , viewl++  , fromList++  , toListF+  , accumMapL+  , isOne+  , isMany+   +  ) where++++import Control.Applicative+import Data.Foldable+import Data.Monoid+import Data.Traversable++import Prelude hiding ( head )+++data OneList a = One a | Many a (OneList a)+  deriving (Eq)++data ViewL a = OneL a | a :< (OneList a)+  deriving (Eq)++++--------------------------------------------------------------------------------+-- Instances++instance Show a => Show (OneList a) where+  show = ('{':) . ($ []) . step where+     step (One a)     = shows a . showChar '}'+     step (Many a as) = shows a . showChar ',' . step as+++instance Functor OneList where+  fmap f (One a)        = One $ f a+  fmap f (Many a as)    = Many (f a) (fmap f as)++instance Foldable OneList where+  foldMap f (One a)     = f a+  foldMap f (Many a as) = f a `mappend` foldMap f as++  foldr f b0 = step b0 where+    step b (One a)      = f a b+    step b (Many a as)  = f a (step b as)++  foldl f b0 = step b0 where+    step b (One a)      = f b a+    step b (Many a as)  = step (f b a) as+++instance Traversable OneList where+  traverse f (One a)      = One  <$> f a+  traverse f (Many a as)  = Many <$> f a <*> traverse f as++++--------------------------------------------------------------------------------+-- | Construct One.+one :: a -> OneList a+one = One+++-- | Prepend an element. Obviously this transforms a One to a Many.+cons :: a -> OneList a -> OneList a+cons a as   = Many a as++-- | 'head' is total of course.+head :: OneList a -> a+head (One a)    = a+head (Many a _) = a++viewl :: OneList a -> ViewL a+viewl (One a)     = OneL a+viewl (Many a as) = a :< as++-- | Construct Many. Not this function throws a error if the list has+-- zero or one elements+fromList :: [a] -> OneList a+fromList []     = error "OneList.fromList: cannot build Many from empty list"+fromList [a]    = One a+fromList (a:as) = Many a (fromList as)+++toListF :: (a -> b) -> OneList a -> [b]+toListF f = step where+  step (One x)     = [f x]+  step (Many x xs) = f x : step xs+++accumMapL :: (x -> st -> (y,st)) -> OneList x -> st -> (OneList y,st)+accumMapL f (One x)     st = let (y,st') = f x st in (One y,st')+accumMapL f (Many x xs) st = (Many y ys,st'')+                             where (y, st')  = f x st+                                   (ys,st'') = accumMapL f xs st'++isMany :: OneList a -> Bool+isMany (Many _ _) = True+isMany _          = False++isOne :: OneList a -> Bool+isOne (One _)     = True+isOne _           = False+
src/Wumpus/Core/VersionNumber.hs view
@@ -22,7 +22,7 @@  -- | Version number. ----- > (0,35,0)+-- > (0,36,0) -- wumpus_core_version :: (Int,Int,Int)-wumpus_core_version = (0,35,0)+wumpus_core_version = (0,36,0)
src/Wumpus/Core/WumpusTypes.hs view
@@ -29,8 +29,6 @@   -- * Picture types     Picture   , DPicture-  , PrimElement-  , DPrimElement   , FontCtx   , Primitive   , DPrimitive@@ -44,20 +42,6 @@   , KerningChar   , DKerningChar -  -- * Drawing styles-  , PathProps       -  , LabelProps-  , EllipseProps----  -- * Transformations on PrimElements-  , rotatePrim-  , scalePrim-  , uniformScalePrim-  , translatePrim--   -- * Printable unit for PostScript   , PSUnit(..) @@ -65,5 +49,5 @@   import Wumpus.Core.PictureInternal-import Wumpus.Core.Utils ( PSUnit(..) )+import Wumpus.Core.Utils.Common ( PSUnit(..) ) 
wumpus-core.cabal view
@@ -1,5 +1,5 @@ name:             wumpus-core-version:          0.35.0+version:          0.36.0 license:          BSD3 license-file:     LICENSE copyright:        Stephen Tetley <stephen.tetley@gmail.com>@@ -44,17 +44,78 @@   to convert EPS files generated by Wumpus to many other formats    (bitmaps).    .+  VERSION 0.36.0 UPGRADE NOTES+  .+  There are two major changes between 0.35.0 and 0.36.0. +  .+  @PrimElement@ has been removed and the grouping constructor it +  provided has been moved into the @Primitive@ type. As both +  types are opaque, definitions in client code will work without +  change, /but all/ type signatures referencing @PrimElement@ will +  need to replace @PrimElement@ with @Primitive@.+  .+  Rotations and scalings on Primitives have changed again.+  Primitives are now instances of the affine classes so support - +  @rotate@, @rotateAbout@, @scale@, @translate@. Primitives are +  now considered to be in the implicit affine frame with origin at +  (0,0). Previously rotatation on Primitives (via the function +  @rotatePrim@) was really a special case to allow slanted text, +  the rotation was about the text\'s baseline origin and not the +  affine frame. As rotation now works differently there is a +  special constructor for slanted text @rtextlabel@.+  .   Changelog:   .-  0.34.0 to 0.35.0:+  0.35.0 to 0.36.0:   .-  * Bug fix - PostScript output - when more than one stroke -    property changed the changes were concatenated without -    a separator. This generated invalid PostScript. Now fixed.+  * API / behaviour change - rotation on primitives changed. New +    functions have been added to create rotated text labels and +    ellipses (@rtextlabel@, @rstrokeEllipse@, etc.), and +    Primitives have been made instances of the Affine classes+    except for the general matrix Transform class. The old+    functions for transforming Primitives (@rotatePrim@, +    @scalePrim@, etc.) have been removed. The demos (Rotated.hs,+    Scaled.hs, Translated.hs) have been removed as they pertain +    to the old behaviour, there are new demos highlighting the+    new behaviour (TransformEllipse.hs, etc.).   .-  * Documentation updates to the guide and the Haddock docs.+  * Major change - removed the PrimElement type. The (opaque) +    Primitive type has been changed to incorporate a grouping +    constructor equivalent to PrimElement\'s @XLinkGroup@ +    contructor. The change has made the implementation of SVG +    hyperlinks more efficient, but has forced various type +    signatures to change in @Core.Picture@. Client code will +    also have to change type signatures - @PrimElement@ becomes+    @Primitive@.   .+  * @Core.PtSize@ - the class @FromPtSize@ has been given a @Num@+    superclass constraint. This can shorten type signatures of +    functions that use @fromPtSize@.   .+  * Corrected a bug where textlabels would generate an invalid+    bounding box and cause a runtime error when supplied with an+    empty string. Now there is no runtime error - and /no-ops/ +    are generated in the output.+  .+  * Internal changes - moved @PrimCTM@ from @Core.PictureInternal@+    into separate module. Moved /utility/ modules into their own +    directory @Utils@. Move /text/ modules into their own +    directory @Text@. +  .+  * Removed dependency on @algebra@ for @Semigroup@. The +    equivalent @append@ operation on @BoundingBox@ is +    @boundaryUnion@.+  .+  * Renamed the @Core.GraphicsState@ to @Core.GraphicProps@. +    Moved the property datatypes from @Core.PictureInternal@ into +    @Core.GraphicProps@ (StrokeProps, LabelProps, etc.).+  .+  * Moved @wumpus_default_font@ from @Core.Picture@ into +    @Core.Graphic.Props@.+  .+  * Haddock docs improved.+  .+  . build-type:         Simple stability:          unstable cabal-version:      >= 1.2@@ -72,9 +133,9 @@   demo/LabelPic.hs,   demo/Latin1Pic.hs,   demo/MultiPic.hs,-  demo/Rotated.hs,-  demo/Scaled.hs,-  demo/Translated.hs,+  demo/TransformEllipse.hs,+  demo/TransformPath.hs,+  demo/TransformTextlabel.hs,   demo/ZOrderPic.hs,   doc/Guide.pdf,   doc-src/Guide.lhs,@@ -88,8 +149,7 @@   build-depends:      base            <  5,                        containers      >= 0.3      && <= 0.4,                        time            >= 1.1.3    && < 1.2,-                      vector-space    >= 0.6      && < 1.0,-                      algebra         >= 0.0.0.1+                      vector-space    >= 0.6      && < 1.0                            exposed-modules:     Wumpus.Core,@@ -98,27 +158,28 @@     Wumpus.Core.Colour,     Wumpus.Core.FontSize,     Wumpus.Core.Geometry,-    Wumpus.Core.GraphicsState,+    Wumpus.Core.GraphicProps,     Wumpus.Core.OutputPostScript,     Wumpus.Core.OutputSVG,     Wumpus.Core.Picture,     Wumpus.Core.PtSize,-    Wumpus.Core.TextDefaultEncoder,-    Wumpus.Core.TextEncoder,-    Wumpus.Core.TextLatin1,-    Wumpus.Core.TextSymbolFont,+    Wumpus.Core.Text.DefaultEncoder,+    Wumpus.Core.Text.Encoder,+    Wumpus.Core.Text.Latin1,+    Wumpus.Core.Text.SymbolFont,     Wumpus.Core.VersionNumber,     Wumpus.Core.WumpusTypes    other-modules:-    Wumpus.Core.FormatCombinators,     Wumpus.Core.PageTranslation,     Wumpus.Core.PictureInternal,     Wumpus.Core.PostScriptDoc,     Wumpus.Core.SVGDoc,-    Wumpus.Core.OneList,-    Wumpus.Core.TextInternal,-    Wumpus.Core.Utils+    Wumpus.Core.Text.TextInternal,+    Wumpus.Core.TrafoInternal,+    Wumpus.Core.Utils.Common,+    Wumpus.Core.Utils.OneList,+    Wumpus.Core.Utils.FormatCombinators        extensions: