wumpus-basic 0.16.0 → 0.17.0
raw patch · 61 files changed
+7435/−4089 lines, 61 filesdep ~wumpus-corePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: wumpus-core
API changes (from Hackage documentation)
- Wumpus.Basic.Geometry.Base: instance Eq u => Eq (BezierCurve u)
- Wumpus.Basic.Geometry.Base: instance Eq u => Eq (LineSegment u)
- Wumpus.Basic.Geometry.Base: instance Ord u => Ord (BezierCurve u)
- Wumpus.Basic.Geometry.Base: instance Ord u => Ord (LineSegment u)
- Wumpus.Basic.Geometry.Intersection: data LineSegment u
- Wumpus.Basic.Geometry.Intersection: polygonLineSegments :: [Point2 u] -> [LineSegment u]
- Wumpus.Basic.Geometry.Intersection: rectangleLineSegments :: Num u => u -> u -> Point2 u -> [LineSegment u]
- Wumpus.Basic.Kernel.Base.Anchors: apex :: (ApexAnchor t, (DUnit t) ~ u) => t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: bottomLeftCorner :: (BottomCornerAnchor t, (DUnit t) ~ u) => t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: bottomRightCorner :: (BottomCornerAnchor t, (DUnit t) ~ u) => t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: center :: (CenterAnchor t, (DUnit t) ~ u) => t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: class ApexAnchor t
- Wumpus.Basic.Kernel.Base.Anchors: class BottomCornerAnchor t
- Wumpus.Basic.Kernel.Base.Anchors: class CardinalAnchor t
- Wumpus.Basic.Kernel.Base.Anchors: class CardinalAnchor2 t
- Wumpus.Basic.Kernel.Base.Anchors: class CenterAnchor t
- Wumpus.Basic.Kernel.Base.Anchors: class RadialAnchor t
- Wumpus.Basic.Kernel.Base.Anchors: class SideMidpointAnchor t
- Wumpus.Basic.Kernel.Base.Anchors: class TopCornerAnchor t
- Wumpus.Basic.Kernel.Base.Anchors: east :: (CardinalAnchor t, (DUnit t) ~ u) => t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: instance Fractional u => CardinalAnchor (BoundingBox u)
- Wumpus.Basic.Kernel.Base.Anchors: instance Fractional u => CardinalAnchor2 (BoundingBox u)
- Wumpus.Basic.Kernel.Base.Anchors: instance Fractional u => CenterAnchor (BoundingBox u)
- Wumpus.Basic.Kernel.Base.Anchors: north :: (CardinalAnchor t, (DUnit t) ~ u) => t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: northeast :: (CardinalAnchor2 t, (DUnit t) ~ u) => t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: northwest :: (CardinalAnchor2 t, (DUnit t) ~ u) => t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: projectAnchor :: (Real u, Floating u, u ~ (DUnit t), CenterAnchor t) => (t -> Point2 u) -> u -> t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: radialAnchor :: (RadialAnchor t, (DUnit t) ~ u) => Radian -> t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: radialConnectorPoints :: (Real u, Floating u, CenterAnchor t1, RadialAnchor t1, CenterAnchor t2, RadialAnchor t2, u ~ (DUnit t1), (DUnit t1) ~ (DUnit t2)) => t1 -> t2 -> (Point2 u, Point2 u)
- Wumpus.Basic.Kernel.Base.Anchors: sideMidpoint :: (SideMidpointAnchor t, (DUnit t) ~ u) => Int -> t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: south :: (CardinalAnchor t, (DUnit t) ~ u) => t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: southeast :: (CardinalAnchor2 t, (DUnit t) ~ u) => t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: southwest :: (CardinalAnchor2 t, (DUnit t) ~ u) => t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: topLeftCorner :: (TopCornerAnchor t, (DUnit t) ~ u) => t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: topRightCorner :: (TopCornerAnchor t, (DUnit t) ~ u) => t -> Point2 u
- Wumpus.Basic.Kernel.Base.Anchors: west :: (CardinalAnchor t, (DUnit t) ~ u) => t -> Point2 u
- Wumpus.Basic.Kernel.Base.BaseDefs: class Monad m => PointSupplyM m :: (* -> *)
- Wumpus.Basic.Kernel.Base.BaseDefs: instance OPlus (Primitive u)
- Wumpus.Basic.Kernel.Base.BaseDefs: position :: (PointSupplyM m, (MonUnit m) ~ u) => m (Point2 u)
- Wumpus.Basic.Kernel.Base.ContextFun: at :: LocCF u a -> Point2 u -> CF a
- Wumpus.Basic.Kernel.Base.ContextFun: atRot :: LocThetaCF u a -> Point2 u -> Radian -> CF a
- Wumpus.Basic.Kernel.Base.ContextFun: chain1 :: OPlus w => CF1 s1 (s1, w) -> CF1 s1 (s1, w) -> CF1 s1 (s1, w)
- Wumpus.Basic.Kernel.Base.ContextFun: connCtx :: ConnectorCF u DrawingContext
- Wumpus.Basic.Kernel.Base.ContextFun: connEnd :: ConnectorCF u (Point2 u)
- Wumpus.Basic.Kernel.Base.ContextFun: connStart :: ConnectorCF u (Point2 u)
- Wumpus.Basic.Kernel.Base.ContextFun: connect :: ConnectorCF u a -> Point2 u -> Point2 u -> CF a
- Wumpus.Basic.Kernel.Base.ContextFun: data CF1 r1 a
- Wumpus.Basic.Kernel.Base.ContextFun: data CF2 r1 r2 a
- Wumpus.Basic.Kernel.Base.ContextFun: instance Applicative (CF1 r1)
- Wumpus.Basic.Kernel.Base.ContextFun: instance Applicative (CF2 r1 r2)
- Wumpus.Basic.Kernel.Base.ContextFun: instance DrawingCtxM (CF1 r1)
- Wumpus.Basic.Kernel.Base.ContextFun: instance DrawingCtxM (CF2 r1 r2)
- Wumpus.Basic.Kernel.Base.ContextFun: instance Functor (CF1 r1)
- Wumpus.Basic.Kernel.Base.ContextFun: instance Functor (CF2 r1 r2)
- Wumpus.Basic.Kernel.Base.ContextFun: instance Monad (CF1 r1)
- Wumpus.Basic.Kernel.Base.ContextFun: instance Monad (CF2 r1 r2)
- Wumpus.Basic.Kernel.Base.ContextFun: instance Monoid a => Monoid (CF1 r1 a)
- Wumpus.Basic.Kernel.Base.ContextFun: instance Monoid a => Monoid (CF2 r1 r2 a)
- Wumpus.Basic.Kernel.Base.ContextFun: instance OPlus a => OPlus (CF1 r1 a)
- Wumpus.Basic.Kernel.Base.ContextFun: instance OPlus a => OPlus (CF2 r1 r2 a)
- Wumpus.Basic.Kernel.Base.ContextFun: locCtx :: LocCF u DrawingContext
- Wumpus.Basic.Kernel.Base.ContextFun: locPoint :: LocCF u (Point2 u)
- Wumpus.Basic.Kernel.Base.ContextFun: locThetaAng :: LocThetaCF u Radian
- Wumpus.Basic.Kernel.Base.ContextFun: locThetaCtx :: LocThetaCF u DrawingContext
- Wumpus.Basic.Kernel.Base.ContextFun: locThetaPoint :: LocThetaCF u (Point2 u)
- Wumpus.Basic.Kernel.Base.ContextFun: queryCtx :: (DrawingContext -> a) -> CF a
- Wumpus.Basic.Kernel.Base.ContextFun: rot :: LocThetaCF u a -> Radian -> LocCF u a
- Wumpus.Basic.Kernel.Base.ContextFun: runCF1 :: DrawingContext -> r1 -> CF1 r1 a -> a
- Wumpus.Basic.Kernel.Base.ContextFun: runCF2 :: DrawingContext -> r1 -> r2 -> CF2 r1 r2 a -> a
- Wumpus.Basic.Kernel.Base.ContextFun: type ConnectorCF u a = CF2 (Point2 u) (Point2 u) a
- Wumpus.Basic.Kernel.Base.ContextFun: type DConnectorCF a = ConnectorCF Double a
- Wumpus.Basic.Kernel.Base.ContextFun: type DLocCF a = LocCF Double a
- Wumpus.Basic.Kernel.Base.ContextFun: type DLocThetaCF a = LocThetaCF Double a
- Wumpus.Basic.Kernel.Base.ContextFun: type LocCF u a = CF1 (Point2 u) a
- Wumpus.Basic.Kernel.Base.ContextFun: type LocThetaCF u a = CF2 (Point2 u) Radian a
- Wumpus.Basic.Kernel.Base.DrawingContext: default_drawing_context :: DrawingContext
- Wumpus.Basic.Kernel.Base.DrawingContext: fallback_metrics :: DrawingContext -> MetricsOps
- Wumpus.Basic.Kernel.Base.DrawingContext: fill_colour :: DrawingContext -> RGBi
- Wumpus.Basic.Kernel.Base.DrawingContext: font_props :: DrawingContext -> FontAttr
- Wumpus.Basic.Kernel.Base.DrawingContext: glyph_tables :: DrawingContext -> GlyphMetrics
- Wumpus.Basic.Kernel.Base.DrawingContext: line_spacing_factor :: DrawingContext -> Double
- Wumpus.Basic.Kernel.Base.DrawingContext: round_corner_factor :: DrawingContext -> Double
- Wumpus.Basic.Kernel.Base.DrawingContext: stroke_colour :: DrawingContext -> RGBi
- Wumpus.Basic.Kernel.Base.DrawingContext: stroke_props :: DrawingContext -> StrokeAttr
- Wumpus.Basic.Kernel.Base.DrawingContext: text_margin :: DrawingContext -> TextMargin
- Wumpus.Basic.Kernel.Base.GlyphMetrics: FontMetricsOps :: FontName -> MetricsOps -> FontMetricsOps
- Wumpus.Basic.Kernel.Base.GlyphMetrics: MetricsOps :: (forall u. FromPtSize u => PtSize -> BoundingBox u) -> (forall u. FromPtSize u => PtSize -> CharWidthTable u) -> (forall u. FromPtSize u => PtSize -> u) -> (forall u. FromPtSize u => PtSize -> u) -> MetricsOps
- Wumpus.Basic.Kernel.Base.GlyphMetrics: data FontMetricsOps
- Wumpus.Basic.Kernel.Base.GlyphMetrics: data GlyphMetrics
- Wumpus.Basic.Kernel.Base.GlyphMetrics: data MetricsOps
- Wumpus.Basic.Kernel.Base.GlyphMetrics: emptyGlyphMetrics :: GlyphMetrics
- Wumpus.Basic.Kernel.Base.GlyphMetrics: get_bounding_box :: MetricsOps -> forall u. FromPtSize u => PtSize -> BoundingBox u
- Wumpus.Basic.Kernel.Base.GlyphMetrics: get_cap_height :: MetricsOps -> forall u. FromPtSize u => PtSize -> u
- Wumpus.Basic.Kernel.Base.GlyphMetrics: get_cw_table :: MetricsOps -> forall u. FromPtSize u => PtSize -> CharWidthTable u
- Wumpus.Basic.Kernel.Base.GlyphMetrics: get_descender :: MetricsOps -> forall u. FromPtSize u => PtSize -> u
- Wumpus.Basic.Kernel.Base.GlyphMetrics: insertFont :: FontMetricsOps -> GlyphMetrics -> GlyphMetrics
- Wumpus.Basic.Kernel.Base.GlyphMetrics: instance Monoid GlyphMetrics
- Wumpus.Basic.Kernel.Base.GlyphMetrics: lookupFont :: FontName -> GlyphMetrics -> Maybe MetricsOps
- Wumpus.Basic.Kernel.Base.GlyphMetrics: monospace_metrics :: MetricsOps
- Wumpus.Basic.Kernel.Base.GlyphMetrics: type CharWidthTable u = CodePoint -> Vec2 u
- Wumpus.Basic.Kernel.Base.GlyphMetrics: type CodePoint = Int
- Wumpus.Basic.Kernel.Base.GlyphMetrics: type FontName = String
- Wumpus.Basic.Kernel.Base.QueryDC: baselineSpacing :: (DrawingCtxM m, Fractional u) => m u
- Wumpus.Basic.Kernel.Base.QueryDC: getRoundCornerSize :: (DrawingCtxM m, Fractional u, FromPtSize u) => m u
- Wumpus.Basic.Kernel.Base.QueryDC: getTextMargin :: (DrawingCtxM m, Fractional u, FromPtSize u) => m (u, u)
- Wumpus.Basic.Kernel.Base.QueryDC: glyphCapHeight :: (FromPtSize u, DrawingCtxM m) => m u
- Wumpus.Basic.Kernel.Base.QueryDC: glyphDescender :: (FromPtSize u, DrawingCtxM m) => m u
- Wumpus.Basic.Kernel.Base.QueryDC: glyphVerticalSpan :: (FromPtSize u, DrawingCtxM m) => m u
- Wumpus.Basic.Kernel.Base.QueryDC: monoAscenderHeight :: (DrawingCtxM m, FromPtSize u) => m u
- Wumpus.Basic.Kernel.Base.QueryDC: monoCapHeight :: (DrawingCtxM m, FromPtSize u) => m u
- Wumpus.Basic.Kernel.Base.QueryDC: monoCharWidth :: (DrawingCtxM m, FromPtSize u) => m u
- Wumpus.Basic.Kernel.Base.QueryDC: monoDefaultPadding :: (DrawingCtxM m, Fractional u, FromPtSize u) => m u
- Wumpus.Basic.Kernel.Base.QueryDC: monoDescenderDepth :: (DrawingCtxM m, FromPtSize u) => m u
- Wumpus.Basic.Kernel.Base.QueryDC: monoFontPointSize :: (DrawingCtxM m, FromPtSize u) => m u
- Wumpus.Basic.Kernel.Base.QueryDC: monoLowerxHeight :: (DrawingCtxM m, FromPtSize u) => m u
- Wumpus.Basic.Kernel.Base.QueryDC: monoMultiLineHeight :: (DrawingCtxM m, Fractional u, FromPtSize u) => Int -> m u
- Wumpus.Basic.Kernel.Base.QueryDC: monoTextDimensions :: (DrawingCtxM m, Num u, Ord u, FromPtSize u) => String -> m (u, u)
- Wumpus.Basic.Kernel.Base.QueryDC: monoTextLength :: (DrawingCtxM m, FromPtSize u) => String -> m u
- Wumpus.Basic.Kernel.Base.QueryDC: monoTextWidth :: (DrawingCtxM m, FromPtSize u) => Int -> m u
- Wumpus.Basic.Kernel.Base.QueryDC: monoVecToCenter :: (DrawingCtxM m, Fractional u, Ord u, FromPtSize u) => String -> m (Vec2 u)
- Wumpus.Basic.Kernel.Base.QueryDC: withBorderedAttr :: DrawingCtxM m => (RGBi -> StrokeAttr -> RGBi -> a) -> m a
- Wumpus.Basic.Kernel.Base.QueryDC: withFillAttr :: DrawingCtxM m => (RGBi -> a) -> m a
- Wumpus.Basic.Kernel.Base.QueryDC: withStrokeAttr :: DrawingCtxM m => (RGBi -> StrokeAttr -> a) -> m a
- Wumpus.Basic.Kernel.Base.QueryDC: withTextAttr :: DrawingCtxM m => (RGBi -> FontAttr -> a) -> m a
- Wumpus.Basic.Kernel.Base.ScalingContext: ScalingContext :: (ux -> u) -> (uy -> u) -> ScalingContext ux uy u
- Wumpus.Basic.Kernel.Base.ScalingContext: coordinateScaling :: Num u => u -> u -> ScalingContext Int Int u
- Wumpus.Basic.Kernel.Base.ScalingContext: data ScalingContext ux uy u
- Wumpus.Basic.Kernel.Base.ScalingContext: scalePt :: ScalingContext ux uy u -> ux -> uy -> Point2 u
- Wumpus.Basic.Kernel.Base.ScalingContext: scaleVec :: ScalingContext ux uy u -> ux -> uy -> Vec2 u
- Wumpus.Basic.Kernel.Base.ScalingContext: scaleX :: ScalingContext ux uy u -> ux -> u
- Wumpus.Basic.Kernel.Base.ScalingContext: scaleY :: ScalingContext ux uy u -> uy -> u
- Wumpus.Basic.Kernel.Base.ScalingContext: scale_in_x :: ScalingContext ux uy u -> ux -> u
- Wumpus.Basic.Kernel.Base.ScalingContext: scale_in_y :: ScalingContext ux uy u -> uy -> u
- Wumpus.Basic.Kernel.Base.ScalingContext: uniformScaling :: Num u => u -> ScalingContext u u u
- Wumpus.Basic.Kernel.Base.ScalingContext: unitX :: Num ux => ScalingContext ux uy u -> u
- Wumpus.Basic.Kernel.Base.ScalingContext: unitY :: Num uy => ScalingContext ux uy u -> u
- Wumpus.Basic.Kernel.Base.UpdateDC: bothFillColour :: DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: bothStrokeColour :: DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: capButt :: DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: capRound :: DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: capSquare :: DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: dashPattern :: DashPattern -> DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: doubledashes :: DashPattern -> DashPattern
- Wumpus.Basic.Kernel.Base.UpdateDC: doublegaps :: DashPattern -> DashPattern
- Wumpus.Basic.Kernel.Base.UpdateDC: doublesize :: DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: dphase :: Int -> DashPattern -> DashPattern
- Wumpus.Basic.Kernel.Base.UpdateDC: fillColour :: RGBi -> DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: fontAttr :: FontFace -> Int -> DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: fontFace :: FontFace -> DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: fontSize :: Int -> DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: halfsize :: DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: joinBevel :: DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: joinMiter :: DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: joinRound :: DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: lineWidth :: Double -> DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: phase :: Int -> DashPattern -> DashPattern
- Wumpus.Basic.Kernel.Base.UpdateDC: roundCornerFactor :: Double -> DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: scalesize :: Ratio Int -> DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: strokeColour :: RGBi -> DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: swapColours :: DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: textMargin :: Double -> Double -> DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: thick :: DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: thin :: DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: ultrathick :: DrawingContextF
- Wumpus.Basic.Kernel.Base.UpdateDC: unit_dash_pattern :: DashPattern
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: class TraceM m :: (* -> *)
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: collectH :: PrimGraphic u -> HPrim u
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: data PrimGraphic u
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: getPrimGraphic :: PrimGraphic u -> Primitive u
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: instance (Real u, Floating u) => Rotate (PrimGraphic u)
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: instance (Real u, Floating u) => RotateAbout (PrimGraphic u)
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: instance Eq u => Eq (PrimGraphic u)
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: instance Num u => Scale (PrimGraphic u)
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: instance Num u => Translate (PrimGraphic u)
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: instance OPlus (PrimGraphic u)
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: instance Show u => Show (PrimGraphic u)
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: metamorphPrim :: (Primitive u -> Primitive u) -> PrimGraphic u -> PrimGraphic u
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: primGraphic :: Primitive u -> PrimGraphic u
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: trace :: (TraceM m, (MonUnit m) ~ u) => HPrim u -> m ()
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: advcat :: Num u => AdvGraphic u -> AdvGraphic u -> AdvGraphic u
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: advconcat :: Num u => [AdvGraphic u] -> AdvGraphic u
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: advfill :: Num u => Vec2 u -> AdvGraphic u -> AdvGraphic u
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: advpunctuate :: Num u => AdvGraphic u -> [AdvGraphic u] -> AdvGraphic u
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: advsep :: Num u => Vec2 u -> AdvGraphic u -> AdvGraphic u -> AdvGraphic u
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: advspace :: Num u => Vec2 u -> [AdvGraphic u] -> AdvGraphic u
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: emptyAdvGraphic :: Num u => AdvGraphic u
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: intoAdvGraphic :: LocCF u (Vec2 u) -> LocGraphic u -> AdvGraphic u
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: type AdvGraphic u = LocImage u (Vec2 u)
- Wumpus.Basic.Kernel.Objects.AdvanceGraphic: type DAdvGraphic = AdvGraphic Double
- Wumpus.Basic.Kernel.Objects.BaseObjects: instance (DUnit a ~ u, Num u, Scale a) => Scale (Image u a)
- Wumpus.Basic.Kernel.Objects.BaseObjects: instance (DUnit a ~ u, Num u, Scale a) => Scale (LocImage u a)
- Wumpus.Basic.Kernel.Objects.BaseObjects: instance (DUnit a ~ u, Num u, Translate a) => Translate (Image u a)
- Wumpus.Basic.Kernel.Objects.BaseObjects: instance (DUnit a ~ u, Num u, Translate a) => Translate (LocImage u a)
- Wumpus.Basic.Kernel.Objects.BaseObjects: instance (DUnit a ~ u, Real u, Floating u, Rotate a) => Rotate (Image u a)
- Wumpus.Basic.Kernel.Objects.BaseObjects: instance (DUnit a ~ u, Real u, Floating u, Rotate a) => Rotate (LocImage u a)
- Wumpus.Basic.Kernel.Objects.BaseObjects: instance (DUnit a ~ u, Real u, Floating u, RotateAbout a) => RotateAbout (Image u a)
- Wumpus.Basic.Kernel.Objects.BaseObjects: instance (DUnit a ~ u, Real u, Floating u, RotateAbout a) => RotateAbout (LocImage u a)
- Wumpus.Basic.Kernel.Objects.BaseObjects: type DImage a = Image Double a
- Wumpus.Basic.Kernel.Objects.BaseObjects: type DLocImage a = LocImage Double a
- Wumpus.Basic.Kernel.Objects.BaseObjects: type DLocThetaImage a = LocThetaImage Double a
- Wumpus.Basic.Kernel.Objects.BaseObjects: type DrawingInfo a = CF a
- Wumpus.Basic.Kernel.Objects.BaseObjects: type GraphicAns u = ImageAns u (UNil u)
- Wumpus.Basic.Kernel.Objects.BaseObjects: type Image u a = CF (ImageAns u a)
- Wumpus.Basic.Kernel.Objects.BaseObjects: type ImageAns u a = (a, PrimGraphic u)
- Wumpus.Basic.Kernel.Objects.BaseObjects: type LocDrawingInfo u a = LocCF u a
- Wumpus.Basic.Kernel.Objects.BaseObjects: type LocImage u a = LocCF u (ImageAns u a)
- Wumpus.Basic.Kernel.Objects.BaseObjects: type LocThetaDrawingInfo u a = LocThetaCF u a
- Wumpus.Basic.Kernel.Objects.BaseObjects: type LocThetaImage u a = LocThetaCF u (ImageAns u a)
- Wumpus.Basic.Kernel.Objects.CtxPicture: clipCtxPicture :: (Num u, Ord u) => PrimPath u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignColumn :: (Real u, Floating u, FromPtSize u) => VAlign -> CtxPicture u -> [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignColumnSep :: (Real u, Floating u, FromPtSize u) => VAlign -> u -> CtxPicture u -> [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignH :: (Fractional u, Ord u) => HAlign -> CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignRow :: (Real u, Floating u, FromPtSize u) => HAlign -> CtxPicture u -> [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignRowSep :: (Real u, Floating u, FromPtSize u) => HAlign -> u -> CtxPicture u -> [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignSepH :: (Fractional u, Ord u) => HAlign -> u -> CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignSepV :: (Fractional u, Ord u) => VAlign -> u -> CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpAlignV :: (Fractional u, Ord u) => VAlign -> CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpBeneath :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpCenteredAt :: (Fractional u, Ord u) => CtxPicture u -> Point2 u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpColumn :: (Real u, Floating u, FromPtSize u) => CtxPicture u -> [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpColumnSep :: (Real u, Floating u, FromPtSize u) => u -> CtxPicture u -> [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpDown :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpDownSep :: (Num u, Ord u) => u -> CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpRight :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpRightSep :: (Num u, Ord u) => u -> CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpRow :: (Real u, Floating u, FromPtSize u) => CtxPicture u -> [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpRowSep :: (Real u, Floating u, FromPtSize u) => u -> CtxPicture u -> [CtxPicture u] -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: cxpUniteCenter :: (Fractional u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u
- Wumpus.Basic.Kernel.Objects.CtxPicture: instance (Num u, Ord u) => OPlus (CtxPicture u)
- Wumpus.Basic.Kernel.Objects.CtxPicture: instance (Num u, Ord u) => Scale (CtxPicture u)
- Wumpus.Basic.Kernel.Objects.CtxPicture: instance (Num u, Ord u) => Translate (CtxPicture u)
- Wumpus.Basic.Kernel.Objects.CtxPicture: instance (Real u, Floating u) => Rotate (CtxPicture u)
- Wumpus.Basic.Kernel.Objects.CtxPicture: instance (Real u, Floating u) => RotateAbout (CtxPicture u)
- Wumpus.Basic.Kernel.Objects.CtxPicture: type DCtxPicture = CtxPicture Double
- Wumpus.Basic.Kernel.Objects.Displacement: eastwards :: Num u => u -> PointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: moveStartThetaAngle :: ThetaDisplace -> LocThetaCF u a -> LocThetaCF u a
- Wumpus.Basic.Kernel.Objects.Displacement: northeastwards :: Floating u => u -> PointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: northwards :: Num u => u -> PointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: northwestwards :: Floating u => u -> PointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: southeastwards :: Floating u => u -> PointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: southwards :: Num u => u -> PointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: southwestwards :: Floating u => u -> PointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: thetaEastwards :: Floating u => u -> ThetaPointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: thetaNortheastwards :: Floating u => u -> ThetaPointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: thetaNorthwards :: Floating u => u -> ThetaPointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: thetaNorthwestwards :: Floating u => u -> ThetaPointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: thetaSoutheastwards :: Floating u => u -> ThetaPointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: thetaSouthwards :: Floating u => u -> ThetaPointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: thetaSouthwestwards :: Floating u => u -> ThetaPointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: thetaWestwards :: Floating u => u -> ThetaPointDisplace u
- Wumpus.Basic.Kernel.Objects.Displacement: westwards :: Num u => u -> PointDisplace u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: curveGraphic :: Fractional u => Point2 u -> Point2 u -> Point2 u -> Point2 u -> Graphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: emptyLocPath :: Num u => LocCF u (PrimPath u)
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: escapedline :: Num u => EscapedText -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: hkernline :: Num u => [KerningChar u] -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: locPath :: Num u => [Vec2 u] -> LocCF u (PrimPath u)
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rescapedline :: Num u => EscapedText -> LocThetaGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rtextline :: Num u => String -> LocThetaGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: straightLineGraphic :: Fractional u => Point2 u -> Point2 u -> Graphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: textline :: Num u => String -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: vkernline :: Num u => [KerningChar u] -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: adecorate :: Monad m => m (ImageAns u a) -> (a -> m (ImageAns u zz)) -> m (ImageAns u a)
- Wumpus.Basic.Kernel.Objects.Graphic: decorate :: Monad m => m (ImageAns u a) -> m (ImageAns u zz) -> m (ImageAns u a)
- Wumpus.Basic.Kernel.Objects.Graphic: emptyLocGraphic :: Num u => LocGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: emptyLocThetaGraphic :: Num u => LocThetaGraphic u
- Wumpus.Basic.Kernel.Objects.Graphic: hyperlink :: Functor m => XLink -> m (ImageAns u a) -> m (ImageAns u a)
- Wumpus.Basic.Kernel.Objects.Graphic: ignoreAns :: Functor f => f (a, b) -> f (UNil u, b)
- Wumpus.Basic.Kernel.Objects.Graphic: intoImage :: CF a -> Graphic u -> Image u a
- Wumpus.Basic.Kernel.Objects.Graphic: intoLocImage :: LocCF u a -> LocGraphic u -> LocImage u a
- Wumpus.Basic.Kernel.Objects.Graphic: intoLocThetaImage :: LocThetaCF u a -> LocThetaGraphic u -> LocThetaImage u a
- Wumpus.Basic.Kernel.Objects.Graphic: mapAns :: Functor f => (a -> z) -> f (a, b) -> f (z, b)
- Wumpus.Basic.Kernel.Objects.Graphic: replaceAns :: Functor f => z -> f (a, b) -> f (z, b)
- Wumpus.Basic.Kernel.Objects.Graphic: safeconcat :: OPlus a => Image u a -> [Image u a] -> Image u a
- Wumpus.Basic.Kernel.Objects.Graphic: sdecorate :: Monad m => m (ImageAns u a) -> (a -> m (ImageAns u zz)) -> m (ImageAns u a)
- Wumpus.Basic.Kernel.Objects.Graphic: type DGraphic = Graphic Double
- Wumpus.Basic.Kernel.Objects.Graphic: type DLocGraphic = LocGraphic Double
- Wumpus.Basic.Kernel.Objects.Graphic: type DLocThetaGraphic = LocThetaGraphic Double
- Wumpus.Basic.Kernel.Objects.Graphic: type Graphic u = Image u (UNil u)
- Wumpus.Basic.Kernel.Objects.Graphic: type LocGraphic u = LocImage u (UNil u)
- Wumpus.Basic.Kernel.Objects.Graphic: type LocThetaGraphic u = LocThetaImage u (UNil u)
- Wumpus.Basic.Kernel.Objects.PosImage: CENTER :: RectPosition
- Wumpus.Basic.Kernel.Objects.PosImage: EE :: RectPosition
- Wumpus.Basic.Kernel.Objects.PosImage: NE :: RectPosition
- Wumpus.Basic.Kernel.Objects.PosImage: NN :: RectPosition
- Wumpus.Basic.Kernel.Objects.PosImage: NW :: RectPosition
- Wumpus.Basic.Kernel.Objects.PosImage: ObjectPos :: !u -> !u -> !u -> !u -> ObjectPos u
- Wumpus.Basic.Kernel.Objects.PosImage: SE :: RectPosition
- Wumpus.Basic.Kernel.Objects.PosImage: SS :: RectPosition
- Wumpus.Basic.Kernel.Objects.PosImage: SW :: RectPosition
- Wumpus.Basic.Kernel.Objects.PosImage: WW :: RectPosition
- Wumpus.Basic.Kernel.Objects.PosImage: atStartPos :: Floating u => PosImage u a -> Point2 u -> RectPosition -> Image u a
- Wumpus.Basic.Kernel.Objects.PosImage: data ObjectPos u
- Wumpus.Basic.Kernel.Objects.PosImage: data RectPosition
- Wumpus.Basic.Kernel.Objects.PosImage: instance (Fractional u, Ord u) => OPlus (ObjectPos u)
- Wumpus.Basic.Kernel.Objects.PosImage: instance Enum RectPosition
- Wumpus.Basic.Kernel.Objects.PosImage: instance Eq RectPosition
- Wumpus.Basic.Kernel.Objects.PosImage: instance Eq u => Eq (ObjectPos u)
- Wumpus.Basic.Kernel.Objects.PosImage: instance Ord RectPosition
- Wumpus.Basic.Kernel.Objects.PosImage: instance Ord u => Ord (ObjectPos u)
- Wumpus.Basic.Kernel.Objects.PosImage: instance Show RectPosition
- Wumpus.Basic.Kernel.Objects.PosImage: instance Show u => Show (ObjectPos u)
- Wumpus.Basic.Kernel.Objects.PosImage: makePosImage :: Fractional u => ObjectPos u -> LocImage u a -> PosImage u a
- Wumpus.Basic.Kernel.Objects.PosImage: objectPosBounds :: Fractional u => Point2 u -> RectPosition -> ObjectPos u -> BoundingBox u
- Wumpus.Basic.Kernel.Objects.PosImage: op_x_major :: ObjectPos u -> !u
- Wumpus.Basic.Kernel.Objects.PosImage: op_x_minor :: ObjectPos u -> !u
- Wumpus.Basic.Kernel.Objects.PosImage: op_y_major :: ObjectPos u -> !u
- Wumpus.Basic.Kernel.Objects.PosImage: op_y_minor :: ObjectPos u -> !u
- Wumpus.Basic.Kernel.Objects.PosImage: startPos :: Floating u => PosImage u a -> RectPosition -> LocImage u a
- Wumpus.Basic.Kernel.Objects.PosImage: type DPosGraphic = PosGraphic Double
- Wumpus.Basic.Kernel.Objects.PosImage: type DPosImage a = PosImage Double a
- Wumpus.Basic.Kernel.Objects.PosImage: type PosGraphic u = PosImage u (UNil u)
- Wumpus.Basic.Kernel.Objects.PosImage: type PosImage u a = CF2 (Point2 u) RectPosition (ImageAns u a)
- Wumpus.Basic.Kernel.Objects.TraceDrawing: drawi_ :: (TraceM m, DrawingCtxM m, (MonUnit m) ~ u) => Image u a -> m ()
- Wumpus.Basic.Kernel.Objects.TraceDrawing: query :: DrawingCtxM m => CF a -> m a
- Wumpus.Basic.Kernel.Objects.TraceDrawing: xdraw :: (TraceM m, DrawingCtxM m, u ~ (MonUnit m)) => XLink -> Graphic u -> m ()
- Wumpus.Basic.Kernel.Objects.TraceDrawing: xdrawi :: (TraceM m, DrawingCtxM m, (MonUnit m) ~ u) => XLink -> Image u a -> m a
- Wumpus.Basic.Kernel.Objects.TraceDrawing: xdrawi_ :: (TraceM m, DrawingCtxM m, (MonUnit m) ~ u) => XLink -> Image u a -> m ()
- Wumpus.Basic.System.FontLoader.Afm: loadAfmMetrics :: FilePath -> [FontName] -> IO (GlyphMetrics, [String])
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: afmFileParser :: CharParser AfmGlyphMetrics -> CharParser AfmFile
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: charBBox :: CharParser AfmBoundingBox
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: cint :: CharParser Int
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: double :: CharParser Double
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: getCapHeight :: GlobalInfo -> Maybe AfmUnit
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: getEncodingScheme :: GlobalInfo -> Maybe String
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: getFontBBox :: GlobalInfo -> Maybe AfmBoundingBox
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: hexInt :: CharParser Int
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: int :: CharParser Int
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: integer :: CharParser Integer
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: keyName :: CharParser AfmKey
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: keyStringPair :: CharParser (AfmKey, String)
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: lexeme :: CharParser a -> CharParser a
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: metric :: String -> a -> CharParser a -> CharParser a
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: name :: CharParser String
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: name1 :: CharParser String
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: newlineOrEOF :: CharParser ()
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: number :: CharParser AfmUnit
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: octInt :: CharParser Int
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: runQuery :: String -> CharParser a -> GlobalInfo -> Maybe a
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: semi :: CharParser Char
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: startCharMetrics :: CharParser Int
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: symbol :: String -> CharParser String
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: textQuery :: String -> GlobalInfo -> Maybe String
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: uptoNewline :: CharParser String
- Wumpus.Basic.System.FontLoader.Base.AfmParserBase: versionNumber :: CharParser String
- Wumpus.Basic.System.FontLoader.Base.AfmV2Parser: afmV2Parser :: CharParser AfmFile
- Wumpus.Basic.System.FontLoader.Base.AfmV4Dot1Parser: afmV4Dot1Parser :: CharParser AfmFile
- Wumpus.Basic.System.FontLoader.Base.Datatypes: AfmFile :: Maybe String -> Maybe AfmBoundingBox -> Maybe AfmUnit -> Maybe AfmUnit -> [AfmGlyphMetrics] -> AfmFile
- Wumpus.Basic.System.FontLoader.Base.Datatypes: AfmGlyphMetrics :: !PSCharCode -> !Vec2 AfmUnit -> !String -> AfmGlyphMetrics
- Wumpus.Basic.System.FontLoader.Base.Datatypes: FontProps :: BoundingBox cu -> Vec2 cu -> IntMap (Vec2 cu) -> cu -> cu -> FontProps cu
- Wumpus.Basic.System.FontLoader.Base.Datatypes: MonospaceDefaults :: BoundingBox cu -> cu -> cu -> Vec2 cu -> MonospaceDefaults cu
- Wumpus.Basic.System.FontLoader.Base.Datatypes: afmUnitScale :: AfmUnit -> PtSize
- Wumpus.Basic.System.FontLoader.Base.Datatypes: afmValue :: FromPtSize u => AfmUnit -> PtSize -> u
- Wumpus.Basic.System.FontLoader.Base.Datatypes: afm_cap_height :: AfmFile -> Maybe AfmUnit
- Wumpus.Basic.System.FontLoader.Base.Datatypes: afm_char_code :: AfmGlyphMetrics -> !PSCharCode
- Wumpus.Basic.System.FontLoader.Base.Datatypes: afm_char_name :: AfmGlyphMetrics -> !String
- Wumpus.Basic.System.FontLoader.Base.Datatypes: afm_descender :: AfmFile -> Maybe AfmUnit
- Wumpus.Basic.System.FontLoader.Base.Datatypes: afm_encoding :: AfmFile -> Maybe String
- Wumpus.Basic.System.FontLoader.Base.Datatypes: afm_glyph_metrics :: AfmFile -> [AfmGlyphMetrics]
- Wumpus.Basic.System.FontLoader.Base.Datatypes: afm_letter_bbox :: AfmFile -> Maybe AfmBoundingBox
- Wumpus.Basic.System.FontLoader.Base.Datatypes: afm_width_vector :: AfmGlyphMetrics -> !Vec2 AfmUnit
- Wumpus.Basic.System.FontLoader.Base.Datatypes: buildMetricsOps :: (cu -> PtSize) -> FontProps cu -> MetricsOps
- Wumpus.Basic.System.FontLoader.Base.Datatypes: data AfmFile
- Wumpus.Basic.System.FontLoader.Base.Datatypes: data AfmGlyphMetrics
- Wumpus.Basic.System.FontLoader.Base.Datatypes: data AfmUnit
- Wumpus.Basic.System.FontLoader.Base.Datatypes: data FontProps cu
- Wumpus.Basic.System.FontLoader.Base.Datatypes: data MonospaceDefaults cu
- Wumpus.Basic.System.FontLoader.Base.Datatypes: default_cap_height :: MonospaceDefaults cu -> cu
- Wumpus.Basic.System.FontLoader.Base.Datatypes: default_char_width :: MonospaceDefaults cu -> Vec2 cu
- Wumpus.Basic.System.FontLoader.Base.Datatypes: default_descender :: MonospaceDefaults cu -> cu
- Wumpus.Basic.System.FontLoader.Base.Datatypes: default_letter_bbox :: MonospaceDefaults cu -> BoundingBox cu
- Wumpus.Basic.System.FontLoader.Base.Datatypes: fp_adv_vecs :: FontProps cu -> IntMap (Vec2 cu)
- Wumpus.Basic.System.FontLoader.Base.Datatypes: fp_bounding_box :: FontProps cu -> BoundingBox cu
- Wumpus.Basic.System.FontLoader.Base.Datatypes: fp_cap_height :: FontProps cu -> cu
- Wumpus.Basic.System.FontLoader.Base.Datatypes: fp_default_adv_vec :: FontProps cu -> Vec2 cu
- Wumpus.Basic.System.FontLoader.Base.Datatypes: fp_descender :: FontProps cu -> cu
- Wumpus.Basic.System.FontLoader.Base.Datatypes: instance Eq AfmGlyphMetrics
- Wumpus.Basic.System.FontLoader.Base.Datatypes: instance Eq AfmUnit
- Wumpus.Basic.System.FontLoader.Base.Datatypes: instance Eq cu => Eq (MonospaceDefaults cu)
- Wumpus.Basic.System.FontLoader.Base.Datatypes: instance Floating AfmUnit
- Wumpus.Basic.System.FontLoader.Base.Datatypes: instance Fractional AfmUnit
- Wumpus.Basic.System.FontLoader.Base.Datatypes: instance Num AfmUnit
- Wumpus.Basic.System.FontLoader.Base.Datatypes: instance Ord AfmUnit
- Wumpus.Basic.System.FontLoader.Base.Datatypes: instance Real AfmUnit
- Wumpus.Basic.System.FontLoader.Base.Datatypes: instance RealFloat AfmUnit
- Wumpus.Basic.System.FontLoader.Base.Datatypes: instance RealFrac AfmUnit
- Wumpus.Basic.System.FontLoader.Base.Datatypes: instance Show AfmFile
- Wumpus.Basic.System.FontLoader.Base.Datatypes: instance Show AfmGlyphMetrics
- Wumpus.Basic.System.FontLoader.Base.Datatypes: instance Show AfmUnit
- Wumpus.Basic.System.FontLoader.Base.Datatypes: instance Show cu => Show (MonospaceDefaults cu)
- Wumpus.Basic.System.FontLoader.Base.Datatypes: type AfmBoundingBox = BoundingBox AfmUnit
- Wumpus.Basic.System.FontLoader.Base.Datatypes: type AfmKey = String
- Wumpus.Basic.System.FontLoader.Base.Datatypes: type GlobalInfo = Map AfmKey String
- Wumpus.Basic.System.FontLoader.Base.Datatypes: type PSCharCode = Int
- Wumpus.Basic.System.FontLoader.Base.Datatypes: type PSEncodingScheme = String
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: buildAfmFontProps :: MonospaceDefaults AfmUnit -> AfmFile -> FontLoadIO (FontProps AfmUnit)
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: checkFontPath :: FilePath -> FilePath -> FontLoadIO FilePath
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: data FontLoadIO a
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: evalFontLoadIO :: FontLoadIO a -> IO (Either FontLoadErr a)
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: instance Functor FontLoadIO
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: instance Monad FontLoadIO
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: instance Monoid FontLoadLog
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: loadError :: FontLoadErr -> FontLoadIO a
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: logLoadMsg :: String -> FontLoadIO ()
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: promoteEither :: Either FontLoadErr a -> FontLoadIO a
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: promoteIO :: IO a -> FontLoadIO a
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: runFontLoadIO :: FontLoadIO a -> IO (Either FontLoadErr a, [String])
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: runParserFLIO :: FilePath -> Parser Char a -> FontLoadIO a
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: sequenceAll :: [FontLoadIO a] -> FontLoadIO [a]
- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad: type FontLoadErr = String
- Wumpus.Basic.System.FontLoader.Base.GSFontMap: GSFontMap :: String -> Map String (String, FilePath) -> GSFontMap
- Wumpus.Basic.System.FontLoader.Base.GSFontMap: data GSFontMap
- Wumpus.Basic.System.FontLoader.Base.GSFontMap: ghostscript_fontmap :: GSFontMap -> Map String (String, FilePath)
- Wumpus.Basic.System.FontLoader.Base.GSFontMap: ghostscript_fontmap_8_54 :: GSFontMap
- Wumpus.Basic.System.FontLoader.Base.GSFontMap: ghostscript_version :: GSFontMap -> String
- Wumpus.Basic.System.FontLoader.Base.GSFontMap: gsFontAlias :: GSFontMap -> String -> Maybe String
- Wumpus.Basic.System.FontLoader.Base.GSFontMap: gsMetricsFile :: GSFontMap -> String -> Maybe FilePath
- Wumpus.Basic.System.FontLoader.Base.GSFontMap: gsVersionNumber :: GSFontMap -> String
- Wumpus.Basic.System.FontLoader.GhostScript: loadGSMetrics :: FilePath -> [FontName] -> IO (GlyphMetrics, [String])
+ Wumpus.Basic.Geometry.Base: instance (Ord u, Tolerance u) => Eq (BezierCurve u)
+ Wumpus.Basic.Geometry.Base: instance (Ord u, Tolerance u) => Eq (LineSegment u)
+ Wumpus.Basic.Geometry.Base: instance (Ord u, Tolerance u) => Ord (BezierCurve u)
+ Wumpus.Basic.Geometry.Base: instance (Ord u, Tolerance u) => Ord (LineSegment u)
+ Wumpus.Basic.Geometry.Base: quarter_pi :: Floating u => u
+ Wumpus.Basic.Geometry.Paths: arcPathAlg :: Floating u => u -> Radian -> Radian -> PathAlg u
+ Wumpus.Basic.Geometry.Paths: blRectanglePathAlg :: Num u => u -> u -> PathAlg u
+ Wumpus.Basic.Geometry.Paths: circlePathAlg :: (Fractional u, Floating u) => u -> PathAlg u
+ Wumpus.Basic.Geometry.Paths: data PathAlg u
+ Wumpus.Basic.Geometry.Paths: diamondPathAlg :: Num u => u -> u -> PathAlg u
+ Wumpus.Basic.Geometry.Paths: instance Enum PathAlgScheme
+ Wumpus.Basic.Geometry.Paths: instance Eq PathAlgScheme
+ Wumpus.Basic.Geometry.Paths: instance Ord PathAlgScheme
+ Wumpus.Basic.Geometry.Paths: instance Show PathAlgScheme
+ Wumpus.Basic.Geometry.Paths: pathIterateLocus :: Num u => [Vec2 u] -> PathAlg u
+ Wumpus.Basic.Geometry.Paths: pathStartIsLocus :: [Vec2 u] -> PathAlg u
+ Wumpus.Basic.Geometry.Paths: pathStartIsStart :: [Vec2 u] -> PathAlg u
+ Wumpus.Basic.Geometry.Paths: polygonPathAlg :: Floating u => Int -> u -> PathAlg u
+ Wumpus.Basic.Geometry.Paths: rectanglePathAlg :: Fractional u => u -> u -> PathAlg u
+ Wumpus.Basic.Geometry.Paths: runPathAlgPoint :: Num u => Point2 u -> PathAlg u -> [Point2 u]
+ Wumpus.Basic.Geometry.Paths: runPathAlgVec :: PathAlg u -> (Maybe (Vec2 u), [Vec2 u])
+ Wumpus.Basic.Kernel.Base.BaseDefs: UNil :: UNil u
+ Wumpus.Basic.Kernel.Base.BaseDefs: altconcat :: OPlus a => a -> [a] -> a
+ Wumpus.Basic.Kernel.Base.BaseDefs: class Num u => InterpretUnit u
+ Wumpus.Basic.Kernel.Base.BaseDefs: class ScalarUnit a
+ Wumpus.Basic.Kernel.Base.BaseDefs: data UNil u
+ Wumpus.Basic.Kernel.Base.BaseDefs: dinterp :: InterpretUnit u => FontSize -> Double -> u
+ Wumpus.Basic.Kernel.Base.BaseDefs: dinterpF :: (Functor t, InterpretUnit u) => FontSize -> t Double -> t u
+ Wumpus.Basic.Kernel.Base.BaseDefs: fromPsPoint :: ScalarUnit a => Double -> a
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance Eq (UNil u)
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance Functor UNil
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance InterpretUnit AfmUnit
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance InterpretUnit Double
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance Monoid (UNil u)
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance OPlus Primitive
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance OPlus a => OPlus (Const a b)
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance Ord (UNil u)
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance Read (UNil u)
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance Rotate (UNil u)
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance RotateAbout (UNil u)
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance ScalarUnit Double
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance Scale (UNil u)
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance Show (UNil u)
+ Wumpus.Basic.Kernel.Base.BaseDefs: instance Translate (UNil u)
+ Wumpus.Basic.Kernel.Base.BaseDefs: intraMapFunctor :: (Functor f, InterpretUnit u) => FontSize -> (f Double -> f Double) -> f u -> f u
+ Wumpus.Basic.Kernel.Base.BaseDefs: intraMapPoint :: InterpretUnit u => FontSize -> (DPoint2 -> DPoint2) -> Point2 u -> Point2 u
+ Wumpus.Basic.Kernel.Base.BaseDefs: normalize :: InterpretUnit u => FontSize -> u -> Double
+ Wumpus.Basic.Kernel.Base.BaseDefs: normalizeF :: (Functor t, InterpretUnit u) => FontSize -> t u -> t Double
+ Wumpus.Basic.Kernel.Base.BaseDefs: toPsPoint :: ScalarUnit a => a -> Double
+ Wumpus.Basic.Kernel.Base.BaseDefs: uconvert1 :: (InterpretUnit u, InterpretUnit u1) => FontSize -> u -> u1
+ Wumpus.Basic.Kernel.Base.BaseDefs: uconvertF :: (Functor t, InterpretUnit u, InterpretUnit u1) => FontSize -> t u -> t u1
+ Wumpus.Basic.Kernel.Base.ContextFun: consCF :: (DrawingContext -> a) -> CF a
+ Wumpus.Basic.Kernel.Base.ContextFun: domMap1 :: (r1 -> r1) -> CF (r1 -> a) -> CF (r1 -> a)
+ Wumpus.Basic.Kernel.Base.ContextFun: domMap2 :: (r1 -> r1) -> (r2 -> r2) -> CF (r1 -> r2 -> a) -> CF (r1 -> r2 -> a)
+ Wumpus.Basic.Kernel.Base.ContextFun: instance Rotate a => Rotate (CF a)
+ Wumpus.Basic.Kernel.Base.ContextFun: instance RotateAbout a => RotateAbout (CF a)
+ Wumpus.Basic.Kernel.Base.ContextFun: instance Scale a => Scale (CF a)
+ Wumpus.Basic.Kernel.Base.ContextFun: instance Translate a => Translate (CF a)
+ Wumpus.Basic.Kernel.Base.ContextFun: pushR0 :: (a -> a1) -> CF a -> CF a1
+ Wumpus.Basic.Kernel.Base.ContextFun: pushR1 :: (a -> a1) -> CF (r1 -> a) -> CF (r1 -> a1)
+ Wumpus.Basic.Kernel.Base.ContextFun: pushR2 :: (a -> a1) -> CF (r1 -> r2 -> a) -> CF (r1 -> r2 -> a1)
+ Wumpus.Basic.Kernel.Base.ContextFun: type Query a = CF a
+ Wumpus.Basic.Kernel.Base.ContextFun: uconvR0 :: (FontSize -> ans -> ans1) -> CF ans -> CF ans1
+ Wumpus.Basic.Kernel.Base.ContextFun: uconvR1 :: (Functor t, InterpretUnit u, InterpretUnit u1) => (FontSize -> ans -> ans1) -> CF (t u -> ans) -> CF (t u1 -> ans1)
+ Wumpus.Basic.Kernel.Base.ContextFun: uconvR2a :: (Functor t, InterpretUnit u, InterpretUnit u1) => (FontSize -> ans -> ans1) -> CF (t u -> r2 -> ans) -> CF (t u1 -> r2 -> ans1)
+ Wumpus.Basic.Kernel.Base.ContextFun: uconvR2ab :: (Functor t1, Functor t2, InterpretUnit u, InterpretUnit u1) => (FontSize -> ans -> ans1) -> CF (t1 u -> t2 u -> ans) -> CF (t1 u1 -> t2 u1 -> ans1)
+ Wumpus.Basic.Kernel.Base.DrawingContext: ConnectorProps :: !Em -> !Em -> !Em -> !Em -> !Radian -> !Em -> !Em -> !Em -> !Em -> ConnectorProps
+ Wumpus.Basic.Kernel.Base.DrawingContext: addFontTables :: FontLoadResult -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.DrawingContext: data ConnectorProps
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_conn_arc_ang :: ConnectorProps -> !Radian
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_conn_box_halfsize :: ConnectorProps -> !Em
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_conn_dst_arm :: ConnectorProps -> !Em
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_conn_dst_offset :: ConnectorProps -> !Em
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_conn_dst_space :: ConnectorProps -> !Em
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_conn_loop_size :: ConnectorProps -> !Em
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_conn_src_arm :: ConnectorProps -> !Em
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_conn_src_offset :: ConnectorProps -> !Em
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_conn_src_space :: ConnectorProps -> !Em
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_connector_props :: DrawingContext -> ConnectorProps
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_fallback_metrics :: DrawingContext -> FontMetrics
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_fill_colour :: DrawingContext -> RGBi
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_font_face :: DrawingContext -> FontFace
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_font_load_log :: DrawingContext -> FontLoadLog
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_font_metrics_table :: DrawingContext -> FontTable
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_font_size :: DrawingContext -> !FontSize
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_line_spacing_factor :: DrawingContext -> Double
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_snap_grid_factors :: DrawingContext -> (Double, Double)
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_stroke_colour :: DrawingContext -> RGBi
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_stroke_props :: DrawingContext -> StrokeAttr
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_text_colour :: DrawingContext -> RGBi
+ Wumpus.Basic.Kernel.Base.DrawingContext: dc_text_margin :: DrawingContext -> TextMargin
+ Wumpus.Basic.Kernel.Base.DrawingContext: reset_drawing_metrics :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.DrawingContext: reset_drawing_properties :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.FontSupport: FontDef :: FontFace -> String -> String -> FontDef
+ Wumpus.Basic.Kernel.Base.FontSupport: FontFamily :: FontDef -> Maybe FontDef -> Maybe FontDef -> Maybe FontDef -> FontFamily
+ Wumpus.Basic.Kernel.Base.FontSupport: FontLoadResult :: FontTable -> FontLoadLog -> FontLoadResult
+ Wumpus.Basic.Kernel.Base.FontSupport: FontMetrics :: (FontSize -> BoundingBox Double) -> (FontSize -> CharWidthLookup) -> (FontSize -> Double) -> (FontSize -> Double) -> FontMetrics
+ Wumpus.Basic.Kernel.Base.FontSupport: afm_file_name :: FontDef -> String
+ Wumpus.Basic.Kernel.Base.FontSupport: boldItalicWeight :: FontFamily -> FontDef
+ Wumpus.Basic.Kernel.Base.FontSupport: boldWeight :: FontFamily -> FontDef
+ Wumpus.Basic.Kernel.Base.FontSupport: data FontDef
+ Wumpus.Basic.Kernel.Base.FontSupport: data FontFamily
+ Wumpus.Basic.Kernel.Base.FontSupport: data FontLoadLog
+ Wumpus.Basic.Kernel.Base.FontSupport: data FontLoadResult
+ Wumpus.Basic.Kernel.Base.FontSupport: data FontMetrics
+ Wumpus.Basic.Kernel.Base.FontSupport: data FontTable
+ Wumpus.Basic.Kernel.Base.FontSupport: emptyFontTable :: FontTable
+ Wumpus.Basic.Kernel.Base.FontSupport: ff_bold :: FontFamily -> Maybe FontDef
+ Wumpus.Basic.Kernel.Base.FontSupport: ff_bold_italic :: FontFamily -> Maybe FontDef
+ Wumpus.Basic.Kernel.Base.FontSupport: ff_italic :: FontFamily -> Maybe FontDef
+ Wumpus.Basic.Kernel.Base.FontSupport: ff_regular :: FontFamily -> FontDef
+ Wumpus.Basic.Kernel.Base.FontSupport: fontLoadMsg :: String -> FontLoadLog
+ Wumpus.Basic.Kernel.Base.FontSupport: font_def_face :: FontDef -> FontFace
+ Wumpus.Basic.Kernel.Base.FontSupport: get_bounding_box :: FontMetrics -> FontSize -> BoundingBox Double
+ Wumpus.Basic.Kernel.Base.FontSupport: get_cap_height :: FontMetrics -> FontSize -> Double
+ Wumpus.Basic.Kernel.Base.FontSupport: get_cw_table :: FontMetrics -> FontSize -> CharWidthLookup
+ Wumpus.Basic.Kernel.Base.FontSupport: get_descender :: FontMetrics -> FontSize -> Double
+ Wumpus.Basic.Kernel.Base.FontSupport: gs_file_name :: FontDef -> String
+ Wumpus.Basic.Kernel.Base.FontSupport: insertFont :: FontName -> FontMetrics -> FontTable -> FontTable
+ Wumpus.Basic.Kernel.Base.FontSupport: instance Eq FontDef
+ Wumpus.Basic.Kernel.Base.FontSupport: instance Monoid FontLoadLog
+ Wumpus.Basic.Kernel.Base.FontSupport: instance Monoid FontTable
+ Wumpus.Basic.Kernel.Base.FontSupport: instance Ord FontDef
+ Wumpus.Basic.Kernel.Base.FontSupport: instance Show FontDef
+ Wumpus.Basic.Kernel.Base.FontSupport: italicWeight :: FontFamily -> FontDef
+ Wumpus.Basic.Kernel.Base.FontSupport: loaded_font_table :: FontLoadResult -> FontTable
+ Wumpus.Basic.Kernel.Base.FontSupport: loader_errors :: FontLoadResult -> FontLoadLog
+ Wumpus.Basic.Kernel.Base.FontSupport: lookupFont :: FontName -> FontTable -> Maybe FontMetrics
+ Wumpus.Basic.Kernel.Base.FontSupport: monospace_metrics :: FontMetrics
+ Wumpus.Basic.Kernel.Base.FontSupport: printLoadErrors :: FontLoadResult -> IO ()
+ Wumpus.Basic.Kernel.Base.FontSupport: regularWeight :: FontFamily -> FontDef
+ Wumpus.Basic.Kernel.Base.FontSupport: type CharWidthLookup = CodePoint -> Vec2 Double
+ Wumpus.Basic.Kernel.Base.FontSupport: type CodePoint = Int
+ Wumpus.Basic.Kernel.Base.FontSupport: type FontLoadMsg = String
+ Wumpus.Basic.Kernel.Base.FontSupport: type FontName = String
+ Wumpus.Basic.Kernel.Base.QueryDC: capHeight :: (DrawingCtxM m, InterpretUnit u) => m u
+ Wumpus.Basic.Kernel.Base.QueryDC: connectorArcAngle :: DrawingCtxM m => m Radian
+ Wumpus.Basic.Kernel.Base.QueryDC: connectorBoxHalfSize :: (DrawingCtxM m, InterpretUnit u) => m u
+ Wumpus.Basic.Kernel.Base.QueryDC: connectorDstArm :: (DrawingCtxM m, InterpretUnit u) => m u
+ Wumpus.Basic.Kernel.Base.QueryDC: connectorDstOffset :: (DrawingCtxM m, InterpretUnit u) => m u
+ Wumpus.Basic.Kernel.Base.QueryDC: connectorDstSpace :: (DrawingCtxM m, InterpretUnit u) => m u
+ Wumpus.Basic.Kernel.Base.QueryDC: connectorLoopSize :: (DrawingCtxM m, InterpretUnit u) => m u
+ Wumpus.Basic.Kernel.Base.QueryDC: connectorSrcArm :: (DrawingCtxM m, InterpretUnit u) => m u
+ Wumpus.Basic.Kernel.Base.QueryDC: connectorSrcOffset :: (DrawingCtxM m, InterpretUnit u) => m u
+ Wumpus.Basic.Kernel.Base.QueryDC: connectorSrcSpace :: (DrawingCtxM m, InterpretUnit u) => m u
+ Wumpus.Basic.Kernel.Base.QueryDC: descender :: (DrawingCtxM m, InterpretUnit u) => m u
+ Wumpus.Basic.Kernel.Base.QueryDC: dinterpCtx :: (DrawingCtxM m, InterpretUnit u) => Double -> m u
+ Wumpus.Basic.Kernel.Base.QueryDC: dinterpCtxF :: (DrawingCtxM m, Functor t, InterpretUnit u) => t Double -> m (t u)
+ Wumpus.Basic.Kernel.Base.QueryDC: getTextColour :: DrawingCtxM m => m RGBi
+ Wumpus.Basic.Kernel.Base.QueryDC: normalizeCtx :: (DrawingCtxM m, InterpretUnit u) => u -> m Double
+ Wumpus.Basic.Kernel.Base.QueryDC: normalizeCtxF :: (DrawingCtxM m, Functor t, InterpretUnit u) => t u -> m (t Double)
+ Wumpus.Basic.Kernel.Base.QueryDC: pointSize :: DrawingCtxM m => m FontSize
+ Wumpus.Basic.Kernel.Base.QueryDC: position :: (DrawingCtxM m, Fractional u) => (Int, Int) -> m (Point2 u)
+ Wumpus.Basic.Kernel.Base.QueryDC: snapmove :: (DrawingCtxM m, Fractional u) => (Int, Int) -> m (Vec2 u)
+ Wumpus.Basic.Kernel.Base.QueryDC: textMargin :: (DrawingCtxM m, InterpretUnit u) => m (u, u)
+ Wumpus.Basic.Kernel.Base.QueryDC: textlineSpace :: (DrawingCtxM m, Fractional u, InterpretUnit u) => m u
+ Wumpus.Basic.Kernel.Base.QueryDC: uconvertCtx1 :: (DrawingCtxM m, InterpretUnit u, InterpretUnit u1) => u -> m u1
+ Wumpus.Basic.Kernel.Base.QueryDC: uconvertCtxF :: (DrawingCtxM m, Functor t, InterpretUnit u, InterpretUnit u1) => t u -> m (t u1)
+ Wumpus.Basic.Kernel.Base.QueryDC: verticalSpan :: (DrawingCtxM m, InterpretUnit u) => m u
+ Wumpus.Basic.Kernel.Base.Units: cm :: Fractional u => Centimeter -> u
+ Wumpus.Basic.Kernel.Base.Units: data Centimeter
+ Wumpus.Basic.Kernel.Base.Units: data Em
+ Wumpus.Basic.Kernel.Base.Units: data En
+ Wumpus.Basic.Kernel.Base.Units: data Pica
+ Wumpus.Basic.Kernel.Base.Units: dcm :: Double -> Centimeter
+ Wumpus.Basic.Kernel.Base.Units: dpica :: Double -> Pica
+ Wumpus.Basic.Kernel.Base.Units: instance Eq Centimeter
+ Wumpus.Basic.Kernel.Base.Units: instance Eq Em
+ Wumpus.Basic.Kernel.Base.Units: instance Eq En
+ Wumpus.Basic.Kernel.Base.Units: instance Eq Pica
+ Wumpus.Basic.Kernel.Base.Units: instance Floating Centimeter
+ Wumpus.Basic.Kernel.Base.Units: instance Floating Em
+ Wumpus.Basic.Kernel.Base.Units: instance Floating En
+ Wumpus.Basic.Kernel.Base.Units: instance Floating Pica
+ Wumpus.Basic.Kernel.Base.Units: instance Fractional Centimeter
+ Wumpus.Basic.Kernel.Base.Units: instance Fractional Em
+ Wumpus.Basic.Kernel.Base.Units: instance Fractional En
+ Wumpus.Basic.Kernel.Base.Units: instance Fractional Pica
+ Wumpus.Basic.Kernel.Base.Units: instance InterpretUnit Centimeter
+ Wumpus.Basic.Kernel.Base.Units: instance InterpretUnit Em
+ Wumpus.Basic.Kernel.Base.Units: instance InterpretUnit En
+ Wumpus.Basic.Kernel.Base.Units: instance InterpretUnit Pica
+ Wumpus.Basic.Kernel.Base.Units: instance Num Centimeter
+ Wumpus.Basic.Kernel.Base.Units: instance Num Em
+ Wumpus.Basic.Kernel.Base.Units: instance Num En
+ Wumpus.Basic.Kernel.Base.Units: instance Num Pica
+ Wumpus.Basic.Kernel.Base.Units: instance Ord Centimeter
+ Wumpus.Basic.Kernel.Base.Units: instance Ord Em
+ Wumpus.Basic.Kernel.Base.Units: instance Ord En
+ Wumpus.Basic.Kernel.Base.Units: instance Ord Pica
+ Wumpus.Basic.Kernel.Base.Units: instance Real Centimeter
+ Wumpus.Basic.Kernel.Base.Units: instance Real Em
+ Wumpus.Basic.Kernel.Base.Units: instance Real En
+ Wumpus.Basic.Kernel.Base.Units: instance Real Pica
+ Wumpus.Basic.Kernel.Base.Units: instance RealFloat Centimeter
+ Wumpus.Basic.Kernel.Base.Units: instance RealFloat Em
+ Wumpus.Basic.Kernel.Base.Units: instance RealFloat En
+ Wumpus.Basic.Kernel.Base.Units: instance RealFloat Pica
+ Wumpus.Basic.Kernel.Base.Units: instance RealFrac Centimeter
+ Wumpus.Basic.Kernel.Base.Units: instance RealFrac Em
+ Wumpus.Basic.Kernel.Base.Units: instance RealFrac En
+ Wumpus.Basic.Kernel.Base.Units: instance RealFrac Pica
+ Wumpus.Basic.Kernel.Base.Units: instance ScalarUnit Centimeter
+ Wumpus.Basic.Kernel.Base.Units: instance ScalarUnit Pica
+ Wumpus.Basic.Kernel.Base.Units: instance Show Centimeter
+ Wumpus.Basic.Kernel.Base.Units: instance Show Em
+ Wumpus.Basic.Kernel.Base.Units: instance Show En
+ Wumpus.Basic.Kernel.Base.Units: instance Show Pica
+ Wumpus.Basic.Kernel.Base.Units: instance Tolerance Centimeter
+ Wumpus.Basic.Kernel.Base.Units: instance Tolerance Em
+ Wumpus.Basic.Kernel.Base.Units: instance Tolerance En
+ Wumpus.Basic.Kernel.Base.Units: instance Tolerance Pica
+ Wumpus.Basic.Kernel.Base.Units: pica :: Fractional u => Pica -> u
+ Wumpus.Basic.Kernel.Base.UpdateDC: cap_butt :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: cap_default :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: cap_round :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: cap_square :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: conn_arc_angle :: Radian -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: conn_box_halfsize :: InterpretUnit u => u -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: conn_loop_size :: InterpretUnit u => u -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: dashed_line :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: dest_arm_len :: InterpretUnit u => u -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: dest_offset :: (Ord u, InterpretUnit u) => u -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: dest_space :: (Ord u, InterpretUnit u) => u -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: dotted_line :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: double_point_size :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: fill_colour :: RGBi -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: fill_use_stroke_colour :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: fill_use_text_colour :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: font_attr :: FontDef -> Int -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: half_point_size :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: join_bevel :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: join_default :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: join_miter :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: join_round :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: line_default :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: line_thick :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: line_thin :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: line_ultra_thick :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: loose_dashed :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: loose_dotted :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: packed_dashed :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: packed_dotted :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: scale_point_size :: Double -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: set_dash_pattern :: DashPattern -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: set_font :: FontDef -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: set_font_size :: Int -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: set_line_width :: Double -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: single_colour :: RGBi -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: snap_grid_factors :: Double -> Double -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: solid_line :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: source_arm_len :: InterpretUnit u => u -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: source_offset :: (Ord u, InterpretUnit u) => u -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: source_space :: (Ord u, InterpretUnit u) => u -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: stroke_colour :: RGBi -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: stroke_use_fill_colour :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: stroke_use_text_colour :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: swap_colours :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: text_colour :: RGBi -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: text_margin :: Em -> Em -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: text_margin_default :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: text_margin_loose :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: text_margin_none :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: text_margin_tight :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: text_use_fill_colour :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: text_use_stroke_colour :: DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: uniform_arm_len :: InterpretUnit u => u -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.UpdateDC: uniform_conn_space :: (Ord u, InterpretUnit u) => u -> DrawingContextF
+ Wumpus.Basic.Kernel.Base.WrappedPrimitive: cpmap :: (Primitive -> Primitive) -> CatPrim -> CatPrim
+ Wumpus.Basic.Kernel.Base.WrappedPrimitive: data CatPrim
+ Wumpus.Basic.Kernel.Base.WrappedPrimitive: instance Monoid CatPrim
+ Wumpus.Basic.Kernel.Base.WrappedPrimitive: instance OPlus CatPrim
+ Wumpus.Basic.Kernel.Base.WrappedPrimitive: instance Rotate CatPrim
+ Wumpus.Basic.Kernel.Base.WrappedPrimitive: instance RotateAbout CatPrim
+ Wumpus.Basic.Kernel.Base.WrappedPrimitive: instance Scale CatPrim
+ Wumpus.Basic.Kernel.Base.WrappedPrimitive: instance Translate CatPrim
+ Wumpus.Basic.Kernel.Base.WrappedPrimitive: prim1 :: Primitive -> CatPrim
+ Wumpus.Basic.Kernel.Objects.AdvObject: advance :: Num u => AdvObject u -> AdvObject u -> AdvObject u
+ Wumpus.Basic.Kernel.Objects.AdvObject: advances :: InterpretUnit u => [AdvObject u] -> AdvObject u
+ Wumpus.Basic.Kernel.Objects.AdvObject: advfill :: Num u => Vec2 u -> AdvObject u -> AdvObject u
+ Wumpus.Basic.Kernel.Objects.AdvObject: advrepeat :: InterpretUnit u => Int -> AdvObject u -> AdvObject u
+ Wumpus.Basic.Kernel.Objects.AdvObject: advspace :: Num u => Vec2 u -> AdvObject u -> AdvObject u -> AdvObject u
+ Wumpus.Basic.Kernel.Objects.AdvObject: data AdvObject u
+ Wumpus.Basic.Kernel.Objects.AdvObject: emptyAdvObject :: InterpretUnit u => AdvObject u
+ Wumpus.Basic.Kernel.Objects.AdvObject: evenspace :: InterpretUnit u => Vec2 u -> [AdvObject u] -> AdvObject u
+ Wumpus.Basic.Kernel.Objects.AdvObject: instance InterpretUnit u => Monoid (AdvObject u)
+ Wumpus.Basic.Kernel.Objects.AdvObject: makeAdvObject :: Query (Vec2 u) -> LocGraphic u -> AdvObject u
+ Wumpus.Basic.Kernel.Objects.AdvObject: punctuate :: InterpretUnit u => AdvObject u -> [AdvObject u] -> AdvObject u
+ Wumpus.Basic.Kernel.Objects.AdvObject: runAdvObjectR0 :: Point2 u -> AdvObject u -> Image u (Vec2 u)
+ Wumpus.Basic.Kernel.Objects.AdvObject: runAdvObjectR1 :: AdvObject u -> AdvGraphic u
+ Wumpus.Basic.Kernel.Objects.AdvObject: type AdvGraphic u = LocImage u (Vec2 u)
+ Wumpus.Basic.Kernel.Objects.AdvObject: type DAdvGraphic = AdvGraphic Double
+ Wumpus.Basic.Kernel.Objects.AdvObject: type DAdvObject = AdvObject Double
+ Wumpus.Basic.Kernel.Objects.Anchors: apex :: (ApexAnchor a, u ~ (DUnit a)) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: bottomLeftCorner :: (BottomCornerAnchor a, u ~ (DUnit a)) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: bottomRightCorner :: (BottomCornerAnchor a, u ~ (DUnit a)) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: center :: (CenterAnchor a, u ~ (DUnit a)) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: class ApexAnchor a
+ Wumpus.Basic.Kernel.Objects.Anchors: class BottomCornerAnchor a
+ Wumpus.Basic.Kernel.Objects.Anchors: class CardinalAnchor a
+ Wumpus.Basic.Kernel.Objects.Anchors: class CardinalAnchor2 a
+ Wumpus.Basic.Kernel.Objects.Anchors: class CenterAnchor a
+ Wumpus.Basic.Kernel.Objects.Anchors: class RadialAnchor a
+ Wumpus.Basic.Kernel.Objects.Anchors: class SideMidpointAnchor a
+ Wumpus.Basic.Kernel.Objects.Anchors: class TopCornerAnchor a
+ Wumpus.Basic.Kernel.Objects.Anchors: east :: (CardinalAnchor a, u ~ (DUnit a)) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: instance Fractional u => CardinalAnchor (BoundingBox u)
+ Wumpus.Basic.Kernel.Objects.Anchors: instance Fractional u => CardinalAnchor2 (BoundingBox u)
+ Wumpus.Basic.Kernel.Objects.Anchors: instance Fractional u => CenterAnchor (BoundingBox u)
+ Wumpus.Basic.Kernel.Objects.Anchors: north :: (CardinalAnchor a, u ~ (DUnit a)) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: northeast :: (CardinalAnchor2 a, u ~ (DUnit a)) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: northwest :: (CardinalAnchor2 a, u ~ (DUnit a)) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: projectAnchor :: (Real u, Floating u, CenterAnchor a, u ~ (DUnit a)) => (a -> Anchor u) -> u -> a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: radialAnchor :: RadialAnchor a => Radian -> u ~ (DUnit a) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: radialConnectorPoints :: (Real u, Floating u, CenterAnchor a, RadialAnchor a, CenterAnchor b, RadialAnchor b, u ~ (DUnit a), u ~ (DUnit b)) => a -> b -> (Point2 u, Point2 u)
+ Wumpus.Basic.Kernel.Objects.Anchors: sideMidpoint :: SideMidpointAnchor a => Int -> u ~ (DUnit a) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: south :: (CardinalAnchor a, u ~ (DUnit a)) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: southeast :: (CardinalAnchor2 a, u ~ (DUnit a)) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: southwest :: (CardinalAnchor2 a, u ~ (DUnit a)) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: topLeftCorner :: (TopCornerAnchor a, u ~ (DUnit a)) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: topRightCorner :: (TopCornerAnchor a, u ~ (DUnit a)) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Anchors: type Anchor u = Point2 u
+ Wumpus.Basic.Kernel.Objects.Anchors: west :: (CardinalAnchor a, u ~ (DUnit a)) => a -> Anchor u
+ Wumpus.Basic.Kernel.Objects.Basis: Ans :: CatPrim -> a -> ImageAns u a
+ Wumpus.Basic.Kernel.Objects.Basis: answer :: ImageAns u a -> a
+ Wumpus.Basic.Kernel.Objects.Basis: at :: LocQuery u a -> Point2 u -> CF a
+ Wumpus.Basic.Kernel.Objects.Basis: atIncline :: LocThetaQuery u a -> Point2 u -> Radian -> CF a
+ Wumpus.Basic.Kernel.Objects.Basis: clipObject :: PrimPath -> ImageAns t u -> ImageAns t u
+ Wumpus.Basic.Kernel.Objects.Basis: connect :: ConnectorQuery u a -> Point2 u -> Point2 u -> CF a
+ Wumpus.Basic.Kernel.Objects.Basis: data ImageAns u a
+ Wumpus.Basic.Kernel.Objects.Basis: decorateR0 :: CF (ImageAns u a) -> CF (GraphicAns u) -> CF (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Basis: decorateR1 :: CF (r1 -> ImageAns u a) -> CF (r1 -> GraphicAns u) -> CF (r1 -> ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Basis: decorateR2 :: CF (r1 -> r2 -> ImageAns u a) -> CF (r1 -> r2 -> GraphicAns u) -> CF (r1 -> r2 -> ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Basis: elaborateR0 :: CF (ImageAns u a) -> (a -> CF (GraphicAns u)) -> CF (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Basis: elaborateR1 :: CF (r1 -> ImageAns u a) -> (a -> CF (r1 -> GraphicAns u)) -> CF (r1 -> ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Basis: elaborateR2 :: CF (r1 -> r2 -> ImageAns u a) -> (a -> CF (r1 -> r2 -> GraphicAns u)) -> CF (r1 -> r2 -> ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Basis: graphicAns :: CatPrim -> GraphicAns u
+ Wumpus.Basic.Kernel.Objects.Basis: hyperlink :: XLink -> ImageAns u a -> ImageAns u a
+ Wumpus.Basic.Kernel.Objects.Basis: ignoreAns :: ImageAns u a -> GraphicAns u
+ Wumpus.Basic.Kernel.Objects.Basis: incline :: LocThetaQuery u a -> Radian -> LocQuery u a
+ Wumpus.Basic.Kernel.Objects.Basis: instance (u ~ DUnit a, RotateAbout a, ScalarUnit u) => RotateAbout (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Basis: instance (u ~ DUnit a, Translate a, ScalarUnit u) => Translate (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Basis: instance Monoid a => Monoid (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Basis: instance OPlus a => OPlus (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Basis: instance Rotate a => Rotate (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Basis: instance Scale a => Scale (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Basis: mapAns :: (a -> a1) -> ImageAns u a -> ImageAns u a1
+ Wumpus.Basic.Kernel.Objects.Basis: replaceAns :: ans -> ImageAns u a -> ImageAns u ans
+ Wumpus.Basic.Kernel.Objects.Basis: replaceAnsR0 :: ans -> CF (ImageAns u a) -> CF (ImageAns u ans)
+ Wumpus.Basic.Kernel.Objects.Basis: replaceAnsR1 :: ans -> CF (r1 -> ImageAns u a) -> CF (r1 -> ImageAns u ans)
+ Wumpus.Basic.Kernel.Objects.Basis: replaceAnsR2 :: ans -> CF (r1 -> r2 -> ImageAns u a) -> CF (r1 -> r2 -> ImageAns u ans)
+ Wumpus.Basic.Kernel.Objects.Basis: szconvAnsF :: (Functor t, InterpretUnit u, InterpretUnit u1) => FontSize -> ImageAns u (t u) -> ImageAns u1 (t u1)
+ Wumpus.Basic.Kernel.Objects.Basis: szconvAnsZ :: FontSize -> ImageAns u a -> ImageAns u1 a
+ Wumpus.Basic.Kernel.Objects.Basis: type ConnectorQuery u a = CF (Point2 u -> Point2 u -> a)
+ Wumpus.Basic.Kernel.Objects.Basis: type GraphicAns u = ImageAns u (UNil u)
+ Wumpus.Basic.Kernel.Objects.Basis: type LocQuery u a = CF (Point2 u -> a)
+ Wumpus.Basic.Kernel.Objects.Basis: type LocThetaQuery u a = CF (Point2 u -> Radian -> a)
+ Wumpus.Basic.Kernel.Objects.Chain: chain :: InterpretUnit u => ChainAlg u -> [LocImage u a] -> LocImage u (Point2 u)
+ Wumpus.Basic.Kernel.Objects.Chain: chainH :: Num u => u -> ChainAlg u
+ Wumpus.Basic.Kernel.Objects.Chain: chainIterate :: (Point2 u -> Point2 u) -> ChainAlg u
+ Wumpus.Basic.Kernel.Objects.Chain: chainV :: Num u => u -> ChainAlg u
+ Wumpus.Basic.Kernel.Objects.Chain: chain_ :: InterpretUnit u => ChainAlg u -> [LocImage u a] -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.Chain: data ChainAlg u
+ Wumpus.Basic.Kernel.Objects.Chain: data IterationScheme u
+ Wumpus.Basic.Kernel.Objects.Chain: iterationScheme :: (Point2 u -> st) -> (st -> (st, Point2 u)) -> IterationScheme u
+ Wumpus.Basic.Kernel.Objects.Chain: linear :: IterationScheme u -> ChainAlg u
+ Wumpus.Basic.Kernel.Objects.Chain: prefix :: Int -> ChainAlg u -> ChainAlg u -> ChainAlg u
+ Wumpus.Basic.Kernel.Objects.Chain: radialChain :: Floating u => u -> Radian -> Radian -> ChainAlg u
+ Wumpus.Basic.Kernel.Objects.Chain: tableDown :: Num u => Int -> (u, u) -> ChainAlg u
+ Wumpus.Basic.Kernel.Objects.Chain: tableRight :: Num u => Int -> (u, u) -> ChainAlg u
+ Wumpus.Basic.Kernel.Objects.Concat: alignColumn :: (Monoid o, Align o) => VAlign -> [o] -> o
+ Wumpus.Basic.Kernel.Objects.Concat: alignColumnSep :: (Monoid o, AlignSpace o, u ~ (DUnit o)) => VAlign -> u -> [o] -> o
+ Wumpus.Basic.Kernel.Objects.Concat: alignRow :: (Monoid o, Align o) => HAlign -> [o] -> o
+ Wumpus.Basic.Kernel.Objects.Concat: alignRowSep :: (Monoid o, AlignSpace o, u ~ (DUnit o)) => HAlign -> u -> [o] -> o
+ Wumpus.Basic.Kernel.Objects.Concat: anterior :: ZConcat o => o -> o -> o
+ Wumpus.Basic.Kernel.Objects.Concat: cat :: (Monoid o, ZConcat o) => [o] -> o
+ Wumpus.Basic.Kernel.Objects.Concat: class Align o
+ Wumpus.Basic.Kernel.Objects.Concat: class AlignSpace o
+ Wumpus.Basic.Kernel.Objects.Concat: class CatSpace o
+ Wumpus.Basic.Kernel.Objects.Concat: class Concat o
+ Wumpus.Basic.Kernel.Objects.Concat: class ZConcat o
+ Wumpus.Basic.Kernel.Objects.Concat: halign :: Align o => HAlign -> o -> o -> o
+ Wumpus.Basic.Kernel.Objects.Concat: halignSpace :: (AlignSpace o, u ~ (DUnit o)) => HAlign -> u -> o -> o -> o
+ Wumpus.Basic.Kernel.Objects.Concat: hcat :: (Monoid o, Concat o) => [o] -> o
+ Wumpus.Basic.Kernel.Objects.Concat: hconcat :: Concat o => o -> o -> o
+ Wumpus.Basic.Kernel.Objects.Concat: hsep :: (Monoid o, CatSpace o, u ~ (DUnit o)) => u -> [o] -> o
+ Wumpus.Basic.Kernel.Objects.Concat: hspace :: (CatSpace o, u ~ (DUnit o)) => u -> o -> o -> o
+ Wumpus.Basic.Kernel.Objects.Concat: superior :: ZConcat o => o -> o -> o
+ Wumpus.Basic.Kernel.Objects.Concat: valign :: Align o => VAlign -> o -> o -> o
+ Wumpus.Basic.Kernel.Objects.Concat: valignSpace :: (AlignSpace o, u ~ (DUnit o)) => VAlign -> u -> o -> o -> o
+ Wumpus.Basic.Kernel.Objects.Concat: vcat :: (Monoid o, Concat o) => [o] -> o
+ Wumpus.Basic.Kernel.Objects.Concat: vconcat :: Concat o => o -> o -> o
+ Wumpus.Basic.Kernel.Objects.Concat: vsep :: (Monoid o, CatSpace o, u ~ (DUnit o)) => u -> [o] -> o
+ Wumpus.Basic.Kernel.Objects.Concat: vspace :: (CatSpace o, u ~ (DUnit o)) => u -> o -> o -> o
+ Wumpus.Basic.Kernel.Objects.Connector: connectorGraphic_ :: ConnectorImage u a -> ConnectorGraphic u
+ Wumpus.Basic.Kernel.Objects.Connector: uconvConnectorImageF :: (InterpretUnit u, InterpretUnit u1, Functor t) => ConnectorImage u (t u) -> ConnectorImage u1 (t u1)
+ Wumpus.Basic.Kernel.Objects.Connector: uconvConnectorImageZ :: (InterpretUnit u, InterpretUnit u1) => ConnectorImage u a -> ConnectorImage u1 a
+ Wumpus.Basic.Kernel.Objects.CtxPicture: centeredAt :: CtxPicture -> DPoint2 -> CtxPicture
+ Wumpus.Basic.Kernel.Objects.CtxPicture: instance Align CtxPicture
+ Wumpus.Basic.Kernel.Objects.CtxPicture: instance AlignSpace CtxPicture
+ Wumpus.Basic.Kernel.Objects.CtxPicture: instance CatSpace CtxPicture
+ Wumpus.Basic.Kernel.Objects.CtxPicture: instance Concat CtxPicture
+ Wumpus.Basic.Kernel.Objects.CtxPicture: instance Monoid CtxPicture
+ Wumpus.Basic.Kernel.Objects.CtxPicture: instance OPlus CtxPicture
+ Wumpus.Basic.Kernel.Objects.CtxPicture: instance Rotate CtxPicture
+ Wumpus.Basic.Kernel.Objects.CtxPicture: instance RotateAbout CtxPicture
+ Wumpus.Basic.Kernel.Objects.CtxPicture: instance Scale CtxPicture
+ Wumpus.Basic.Kernel.Objects.CtxPicture: instance Translate CtxPicture
+ Wumpus.Basic.Kernel.Objects.CtxPicture: instance ZConcat CtxPicture
+ Wumpus.Basic.Kernel.Objects.CtxPicture: udrawTracing :: u -> TraceDrawing u a -> CtxPicture
+ Wumpus.Basic.Kernel.Objects.CtxPicture: uniteCenter :: CtxPicture -> CtxPicture -> CtxPicture
+ Wumpus.Basic.Kernel.Objects.Displacement: above_left_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ (DUnit a)) => a -> Query (Anchor u)
+ Wumpus.Basic.Kernel.Objects.Displacement: above_right_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ (DUnit a)) => a -> Query (Anchor u)
+ Wumpus.Basic.Kernel.Objects.Displacement: adisp_east :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: adisp_north :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: adisp_northeast :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: adisp_northwest :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: adisp_south :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: adisp_southeast :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: adisp_southwest :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: adisp_west :: Floating u => u -> ThetaPointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: below_left_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ (DUnit a)) => a -> Query (Anchor u)
+ Wumpus.Basic.Kernel.Objects.Displacement: below_right_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ (DUnit a)) => a -> Query (Anchor u)
+ Wumpus.Basic.Kernel.Objects.Displacement: centerRelative :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ (DUnit a)) => (Int, Int) -> a -> Query (Anchor u)
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_down :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_down_left :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_down_right :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_east :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_left :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_north :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_northeast :: Floating u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_northwest :: Floating u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_right :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_south :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_southeast :: Floating u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_southwest :: Floating u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_up :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_up_left :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_up_right :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: disp_west :: Num u => u -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: left_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ (DUnit a)) => a -> Query (Anchor u)
+ Wumpus.Basic.Kernel.Objects.Displacement: moveStartThetaIncl :: ThetaDisplace -> LocThetaQuery u a -> LocThetaQuery u a
+ Wumpus.Basic.Kernel.Objects.Displacement: right_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ (DUnit a)) => a -> Query (Anchor u)
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: curvePP :: InterpretUnit u => [Point2 u] -> Query PrimPath
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: curvedLine :: InterpretUnit u => Point2 u -> Point2 u -> Point2 u -> Point2 u -> Graphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: emptyLocPP :: InterpretUnit u => LocQuery u PrimPath
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: escTextLine :: InterpretUnit u => EscapedText -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: hkernLine :: InterpretUnit u => [KernChar u] -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: locPP :: InterpretUnit u => [Vec2 u] -> LocQuery u PrimPath
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: locStraightLine :: InterpretUnit u => Vec2 u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: plainTextLine :: InterpretUnit u => String -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rescTextLine :: InterpretUnit u => EscapedText -> LocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rplainTextLine :: InterpretUnit u => String -> LocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: straightConnector :: InterpretUnit u => ConnectorGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: type KernChar u = (u, EscapedChar)
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: vertexPP :: InterpretUnit u => [Point2 u] -> Query PrimPath
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: vkernLine :: InterpretUnit u => [KernChar u] -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.Image: graphic_ :: Image u a -> Graphic u
+ Wumpus.Basic.Kernel.Objects.Image: intoImage :: Query a -> Graphic u -> Image u a
+ Wumpus.Basic.Kernel.Objects.Image: type DGraphic = Graphic Double
+ Wumpus.Basic.Kernel.Objects.Image: type DImage a = Image Double a
+ Wumpus.Basic.Kernel.Objects.Image: type Graphic u = CF (GraphicAns u)
+ Wumpus.Basic.Kernel.Objects.Image: type Image u a = CF (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Image: uconvImageF :: (Functor t, InterpretUnit u, InterpretUnit u1) => Image u (t u) -> Image u1 (t u1)
+ Wumpus.Basic.Kernel.Objects.Image: uconvImageZ :: (InterpretUnit u, InterpretUnit u1) => Image u a -> Image u1 a
+ Wumpus.Basic.Kernel.Objects.LocImage: distrib :: (Monoid a, InterpretUnit u) => Vec2 u -> [LocImage u a] -> LocImage u a
+ Wumpus.Basic.Kernel.Objects.LocImage: distribH :: (Monoid a, InterpretUnit u) => u -> [LocImage u a] -> LocImage u a
+ Wumpus.Basic.Kernel.Objects.LocImage: distribV :: (Monoid a, InterpretUnit u) => u -> [LocImage u a] -> LocImage u a
+ Wumpus.Basic.Kernel.Objects.LocImage: duplicate :: (Monoid a, InterpretUnit u) => Int -> Vec2 u -> LocImage u a -> LocImage u a
+ Wumpus.Basic.Kernel.Objects.LocImage: duplicateH :: (Monoid a, InterpretUnit u) => Int -> u -> LocImage u a -> LocImage u a
+ Wumpus.Basic.Kernel.Objects.LocImage: duplicateV :: (Monoid a, InterpretUnit u) => Int -> u -> LocImage u a -> LocImage u a
+ Wumpus.Basic.Kernel.Objects.LocImage: emptyLocGraphic :: InterpretUnit u => LocGraphic u
+ Wumpus.Basic.Kernel.Objects.LocImage: intoLocImage :: LocQuery u a -> LocGraphic u -> LocImage u a
+ Wumpus.Basic.Kernel.Objects.LocImage: locGraphic_ :: LocImage u a -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.LocImage: type DLocGraphic = LocGraphic Double
+ Wumpus.Basic.Kernel.Objects.LocImage: type DLocImage a = LocImage Double a
+ Wumpus.Basic.Kernel.Objects.LocImage: type LocGraphic u = LocQuery u (GraphicAns u)
+ Wumpus.Basic.Kernel.Objects.LocImage: type LocImage u a = LocQuery u (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.LocImage: uconvLocImageF :: (InterpretUnit u, InterpretUnit u1, Functor t) => LocImage u (t u) -> LocImage u1 (t u1)
+ Wumpus.Basic.Kernel.Objects.LocImage: uconvLocImageZ :: (InterpretUnit u, InterpretUnit u1) => LocImage u a -> LocImage u1 a
+ Wumpus.Basic.Kernel.Objects.LocThetaImage: emptyLocThetaGraphic :: InterpretUnit u => LocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.LocThetaImage: intoLocThetaImage :: LocThetaQuery u a -> LocThetaGraphic u -> LocThetaImage u a
+ Wumpus.Basic.Kernel.Objects.LocThetaImage: locThetaGraphic_ :: LocThetaImage u a -> LocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.LocThetaImage: type DLocThetaGraphic = LocThetaGraphic Double
+ Wumpus.Basic.Kernel.Objects.LocThetaImage: type DLocThetaImage a = LocThetaImage Double a
+ Wumpus.Basic.Kernel.Objects.LocThetaImage: type LocThetaGraphic u = LocThetaQuery u (GraphicAns u)
+ Wumpus.Basic.Kernel.Objects.LocThetaImage: type LocThetaImage u a = LocThetaQuery u (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.LocThetaImage: uconvLocThetaImageF :: (InterpretUnit u, InterpretUnit u1, Functor t) => LocThetaImage u (t u) -> LocThetaImage u1 (t u1)
+ Wumpus.Basic.Kernel.Objects.LocThetaImage: uconvLocThetaImageZ :: (InterpretUnit u, InterpretUnit u1) => LocThetaImage u a -> LocThetaImage u1 a
+ Wumpus.Basic.Kernel.Objects.Orientation: BLC :: RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: BLL :: RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: BLR :: RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: CENTER :: RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: EE :: RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: NE :: RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: NN :: RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: NW :: RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: Orientation :: !u -> !u -> !u -> !u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: SE :: RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: SS :: RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: SW :: RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: WW :: RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: binmoveHBottom :: Num u => Orientation u -> Orientation u -> Vec2 u
+ Wumpus.Basic.Kernel.Objects.Orientation: binmoveHCenter :: (Fractional u, Ord u) => Orientation u -> Orientation u -> Vec2 u
+ Wumpus.Basic.Kernel.Objects.Orientation: binmoveHTop :: Num u => Orientation u -> Orientation u -> Vec2 u
+ Wumpus.Basic.Kernel.Objects.Orientation: binmoveVCenter :: (Fractional u, Ord u) => Orientation u -> Orientation u -> Vec2 u
+ Wumpus.Basic.Kernel.Objects.Orientation: binmoveVLeft :: Num u => Orientation u -> Orientation u -> Vec2 u
+ Wumpus.Basic.Kernel.Objects.Orientation: binmoveVRight :: Num u => Orientation u -> Orientation u -> Vec2 u
+ Wumpus.Basic.Kernel.Objects.Orientation: data Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: data RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: extendODown :: Num u => u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: extendOLeft :: Num u => u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: extendORight :: Num u => u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: extendOUp :: Num u => u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: extendOrientation :: Num u => u -> u -> u -> u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: halignBottomO :: (Num u, Ord u) => Orientation u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: halignCenterO :: (Fractional u, Ord u) => Orientation u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: halignTopO :: (Num u, Ord u) => Orientation u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: instance (Fractional u, Ord u) => Monoid (Orientation u)
+ Wumpus.Basic.Kernel.Objects.Orientation: instance (Fractional u, Ord u) => OPlus (Orientation u)
+ Wumpus.Basic.Kernel.Objects.Orientation: instance Enum RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: instance Eq RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: instance Eq u => Eq (Orientation u)
+ Wumpus.Basic.Kernel.Objects.Orientation: instance Functor Orientation
+ Wumpus.Basic.Kernel.Objects.Orientation: instance Ord RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: instance Ord u => Ord (Orientation u)
+ Wumpus.Basic.Kernel.Objects.Orientation: instance Show RectAddress
+ Wumpus.Basic.Kernel.Objects.Orientation: instance Show u => Show (Orientation u)
+ Wumpus.Basic.Kernel.Objects.Orientation: or_x_major :: Orientation u -> !u
+ Wumpus.Basic.Kernel.Objects.Orientation: or_x_minor :: Orientation u -> !u
+ Wumpus.Basic.Kernel.Objects.Orientation: or_y_major :: Orientation u -> !u
+ Wumpus.Basic.Kernel.Objects.Orientation: or_y_minor :: Orientation u -> !u
+ Wumpus.Basic.Kernel.Objects.Orientation: orientationBounds :: Num u => Orientation u -> Point2 u -> BoundingBox u
+ Wumpus.Basic.Kernel.Objects.Orientation: orientationStart :: Fractional u => RectAddress -> Orientation u -> Vec2 u
+ Wumpus.Basic.Kernel.Objects.Orientation: padHEven :: (Fractional u, Ord u) => u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: padVEven :: (Fractional u, Ord u) => u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: padXMajor :: (Num u, Ord u) => u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: padXMinor :: (Num u, Ord u) => u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: padYMajor :: (Num u, Ord u) => u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: padYMinor :: (Num u, Ord u) => u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: spineBelow :: (Num u, Ord u) => Orientation u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: spineRight :: (Num u, Ord u) => Orientation u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: spinemoveH :: Num u => Orientation u -> Orientation u -> Vec2 u
+ Wumpus.Basic.Kernel.Objects.Orientation: spinemoveV :: Num u => Orientation u -> Orientation u -> Vec2 u
+ Wumpus.Basic.Kernel.Objects.Orientation: valignCenterO :: (Fractional u, Ord u) => Orientation u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: valignLeftO :: (Fractional u, Ord u) => Orientation u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.Orientation: valignRightO :: (Fractional u, Ord u) => Orientation u -> Orientation u -> Orientation u
+ Wumpus.Basic.Kernel.Objects.PosObject: aelaboratePO :: (Orientation u -> LocGraphic u) -> PosObject u -> PosObject u
+ Wumpus.Basic.Kernel.Objects.PosObject: atStartAddr :: Floating u => BoundedLocRectGraphic u -> Point2 u -> RectAddress -> BoundedGraphic u
+ Wumpus.Basic.Kernel.Objects.PosObject: data PosObject u
+ Wumpus.Basic.Kernel.Objects.PosObject: elaboratePO :: (Orientation u -> LocGraphic u) -> PosObject u -> PosObject u
+ Wumpus.Basic.Kernel.Objects.PosObject: emptyPosObject :: InterpretUnit u => PosObject u
+ Wumpus.Basic.Kernel.Objects.PosObject: extendPosObject :: Num u => u -> u -> u -> u -> PosObject u -> PosObject u
+ Wumpus.Basic.Kernel.Objects.PosObject: illustratePosObject :: InterpretUnit u => PosObject u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.PosObject: instance (Fractional u, Ord u) => Align (PosObject u)
+ Wumpus.Basic.Kernel.Objects.PosObject: instance (Fractional u, Ord u) => AlignSpace (PosObject u)
+ Wumpus.Basic.Kernel.Objects.PosObject: instance (Fractional u, Ord u) => OPlus (PosObject u)
+ Wumpus.Basic.Kernel.Objects.PosObject: instance (Fractional u, Ord u) => ZConcat (PosObject u)
+ Wumpus.Basic.Kernel.Objects.PosObject: instance (Fractional u, Ord u, InterpretUnit u) => Monoid (PosObject u)
+ Wumpus.Basic.Kernel.Objects.PosObject: instance (Num u, Ord u) => CatSpace (PosObject u)
+ Wumpus.Basic.Kernel.Objects.PosObject: instance (Num u, Ord u) => Concat (PosObject u)
+ Wumpus.Basic.Kernel.Objects.PosObject: localizePO :: DrawingContextF -> PosObject u -> PosObject u
+ Wumpus.Basic.Kernel.Objects.PosObject: makeBindPosObject :: Query a -> (a -> Query (Orientation u)) -> (a -> LocGraphic u) -> PosObject u
+ Wumpus.Basic.Kernel.Objects.PosObject: makePosObject :: Query (Orientation u) -> LocGraphic u -> PosObject u
+ Wumpus.Basic.Kernel.Objects.PosObject: padDownPO :: (Num u, Ord u) => u -> PosObject u -> PosObject u
+ Wumpus.Basic.Kernel.Objects.PosObject: padHorizontalPO :: (Fractional u, Ord u) => u -> PosObject u -> PosObject u
+ Wumpus.Basic.Kernel.Objects.PosObject: padLeftPO :: (Num u, Ord u) => u -> PosObject u -> PosObject u
+ Wumpus.Basic.Kernel.Objects.PosObject: padRightPO :: (Num u, Ord u) => u -> PosObject u -> PosObject u
+ Wumpus.Basic.Kernel.Objects.PosObject: padUpPO :: (Num u, Ord u) => u -> PosObject u -> PosObject u
+ Wumpus.Basic.Kernel.Objects.PosObject: padVerticalPO :: (Fractional u, Ord u) => u -> PosObject u -> PosObject u
+ Wumpus.Basic.Kernel.Objects.PosObject: runPosObjectR0 :: Fractional u => Point2 u -> RectAddress -> PosObject u -> BoundedGraphic u
+ Wumpus.Basic.Kernel.Objects.PosObject: runPosObjectR1 :: Fractional u => RectAddress -> PosObject u -> BoundedLocGraphic u
+ Wumpus.Basic.Kernel.Objects.PosObject: runPosObjectR2 :: Fractional u => PosObject u -> BoundedLocRectGraphic u
+ Wumpus.Basic.Kernel.Objects.PosObject: startAddr :: Floating u => BoundedLocRectGraphic u -> RectAddress -> BoundedLocGraphic u
+ Wumpus.Basic.Kernel.Objects.PosObject: type BoundedLocRectGraphic u = LocRectQuery u (ImageAns u (BoundingBox u))
+ Wumpus.Basic.Kernel.Objects.PosObject: type DPosObject = PosObject Double
+ Wumpus.Basic.Kernel.Objects.PosObject: type LocRectQuery u a = CF (Point2 u -> RectAddress -> a)
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: class TraceM m :: (* -> *)
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: drawc :: (TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => Anchor u -> Anchor u -> ConnectorImage u a -> m ()
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: drawci :: (TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => Anchor u -> Anchor u -> ConnectorImage u a -> m a
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: drawl :: (TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => Anchor u -> LocImage u a -> m ()
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: drawli :: (TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => Anchor u -> LocImage u a -> m a
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: drawrc :: (Real u, Floating u, DrawingCtxM m, TraceM m, CenterAnchor a, RadialAnchor a, CenterAnchor b, RadialAnchor b, u ~ (MonUnit (m ())), u ~ (DUnit a), u ~ (DUnit b)) => a -> b -> ConnectorImage u ans -> m ()
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: drawrci :: (Real u, Floating u, DrawingCtxM m, TraceM m, CenterAnchor a, RadialAnchor a, CenterAnchor b, RadialAnchor b, u ~ (MonUnit (m ())), u ~ (DUnit a), u ~ (DUnit b)) => a -> b -> ConnectorImage u ans -> m ans
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: evalQuery :: DrawingCtxM m => Query a -> m a
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: fontDelta :: TraceM m => m a -> m a
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: trace :: (TraceM m, (MonUnit (m ())) ~ u) => HPrim u -> m ()
+ Wumpus.Basic.System.FontLoader: afmLoaderByEnv :: IO (Maybe FontLoader)
+ Wumpus.Basic.System.FontLoader: default_font_loader_help :: String
+ Wumpus.Basic.System.FontLoader: gsLoaderByEnv :: IO (Maybe FontLoader)
+ Wumpus.Basic.System.FontLoader: simpleFontLoader :: (FontLoader -> IO a) -> IO (Maybe a)
+ Wumpus.Basic.System.FontLoader: type FontLoader = [Either FontDef FontFamily] -> IO FontLoadResult
+ Wumpus.Basic.System.FontLoader.AfmParserBase: afmFileParser :: CharParser AfmGlyphMetrics -> CharParser AfmFile
+ Wumpus.Basic.System.FontLoader.AfmParserBase: charBBox :: CharParser AfmBoundingBox
+ Wumpus.Basic.System.FontLoader.AfmParserBase: cint :: CharParser Int
+ Wumpus.Basic.System.FontLoader.AfmParserBase: double :: CharParser Double
+ Wumpus.Basic.System.FontLoader.AfmParserBase: getCapHeight :: GlobalInfo -> Maybe AfmUnit
+ Wumpus.Basic.System.FontLoader.AfmParserBase: getEncodingScheme :: GlobalInfo -> Maybe String
+ Wumpus.Basic.System.FontLoader.AfmParserBase: getFontBBox :: GlobalInfo -> Maybe AfmBoundingBox
+ Wumpus.Basic.System.FontLoader.AfmParserBase: hexInt :: CharParser Int
+ Wumpus.Basic.System.FontLoader.AfmParserBase: int :: CharParser Int
+ Wumpus.Basic.System.FontLoader.AfmParserBase: integer :: CharParser Integer
+ Wumpus.Basic.System.FontLoader.AfmParserBase: keyName :: CharParser AfmKey
+ Wumpus.Basic.System.FontLoader.AfmParserBase: keyStringPair :: CharParser (AfmKey, String)
+ Wumpus.Basic.System.FontLoader.AfmParserBase: lexeme :: CharParser a -> CharParser a
+ Wumpus.Basic.System.FontLoader.AfmParserBase: metric :: String -> a -> CharParser a -> CharParser a
+ Wumpus.Basic.System.FontLoader.AfmParserBase: name :: CharParser String
+ Wumpus.Basic.System.FontLoader.AfmParserBase: name1 :: CharParser String
+ Wumpus.Basic.System.FontLoader.AfmParserBase: newlineOrEOF :: CharParser ()
+ Wumpus.Basic.System.FontLoader.AfmParserBase: number :: CharParser AfmUnit
+ Wumpus.Basic.System.FontLoader.AfmParserBase: octInt :: CharParser Int
+ Wumpus.Basic.System.FontLoader.AfmParserBase: runQuery :: String -> CharParser a -> GlobalInfo -> Maybe a
+ Wumpus.Basic.System.FontLoader.AfmParserBase: semi :: CharParser Char
+ Wumpus.Basic.System.FontLoader.AfmParserBase: startCharMetrics :: CharParser Int
+ Wumpus.Basic.System.FontLoader.AfmParserBase: symbol :: String -> CharParser String
+ Wumpus.Basic.System.FontLoader.AfmParserBase: textQuery :: String -> GlobalInfo -> Maybe String
+ Wumpus.Basic.System.FontLoader.AfmParserBase: uptoNewline :: CharParser String
+ Wumpus.Basic.System.FontLoader.AfmParserBase: versionNumber :: CharParser String
+ Wumpus.Basic.System.FontLoader.AfmTopLevel: loadAfmFont1 :: FilePath -> FontDef -> IO FontLoadResult
+ Wumpus.Basic.System.FontLoader.AfmTopLevel: loadAfmFontMetrics :: FilePath -> [FontDef] -> IO FontLoadResult
+ Wumpus.Basic.System.FontLoader.AfmV2Parser: afmV2Parser :: CharParser AfmFile
+ Wumpus.Basic.System.FontLoader.AfmV4Dot1Parser: afmV4Dot1Parser :: CharParser AfmFile
+ Wumpus.Basic.System.FontLoader.Datatypes: AfmFile :: Maybe String -> Maybe AfmBoundingBox -> Maybe AfmUnit -> Maybe AfmUnit -> [AfmGlyphMetrics] -> AfmFile
+ Wumpus.Basic.System.FontLoader.Datatypes: AfmGlyphMetrics :: !PSCharCode -> !Vec2 AfmUnit -> !String -> AfmGlyphMetrics
+ Wumpus.Basic.System.FontLoader.Datatypes: FontProps :: BoundingBox cu -> Vec2 cu -> IntMap (Vec2 cu) -> cu -> cu -> FontProps cu
+ Wumpus.Basic.System.FontLoader.Datatypes: MonospaceDefaults :: BoundingBox cu -> cu -> cu -> Vec2 cu -> MonospaceDefaults cu
+ Wumpus.Basic.System.FontLoader.Datatypes: afm_cap_height :: AfmFile -> Maybe AfmUnit
+ Wumpus.Basic.System.FontLoader.Datatypes: afm_char_code :: AfmGlyphMetrics -> !PSCharCode
+ Wumpus.Basic.System.FontLoader.Datatypes: afm_char_name :: AfmGlyphMetrics -> !String
+ Wumpus.Basic.System.FontLoader.Datatypes: afm_descender :: AfmFile -> Maybe AfmUnit
+ Wumpus.Basic.System.FontLoader.Datatypes: afm_encoding :: AfmFile -> Maybe String
+ Wumpus.Basic.System.FontLoader.Datatypes: afm_glyph_metrics :: AfmFile -> [AfmGlyphMetrics]
+ Wumpus.Basic.System.FontLoader.Datatypes: afm_letter_bbox :: AfmFile -> Maybe AfmBoundingBox
+ Wumpus.Basic.System.FontLoader.Datatypes: afm_width_vector :: AfmGlyphMetrics -> !Vec2 AfmUnit
+ Wumpus.Basic.System.FontLoader.Datatypes: buildMetricsOps :: (FontSize -> cu -> Double) -> FontProps cu -> FontMetrics
+ Wumpus.Basic.System.FontLoader.Datatypes: data AfmFile
+ Wumpus.Basic.System.FontLoader.Datatypes: data AfmGlyphMetrics
+ Wumpus.Basic.System.FontLoader.Datatypes: data FontProps cu
+ Wumpus.Basic.System.FontLoader.Datatypes: data MonospaceDefaults cu
+ Wumpus.Basic.System.FontLoader.Datatypes: default_cap_height :: MonospaceDefaults cu -> cu
+ Wumpus.Basic.System.FontLoader.Datatypes: default_char_width :: MonospaceDefaults cu -> Vec2 cu
+ Wumpus.Basic.System.FontLoader.Datatypes: default_descender :: MonospaceDefaults cu -> cu
+ Wumpus.Basic.System.FontLoader.Datatypes: default_letter_bbox :: MonospaceDefaults cu -> BoundingBox cu
+ Wumpus.Basic.System.FontLoader.Datatypes: fp_adv_vecs :: FontProps cu -> IntMap (Vec2 cu)
+ Wumpus.Basic.System.FontLoader.Datatypes: fp_bounding_box :: FontProps cu -> BoundingBox cu
+ Wumpus.Basic.System.FontLoader.Datatypes: fp_cap_height :: FontProps cu -> cu
+ Wumpus.Basic.System.FontLoader.Datatypes: fp_default_adv_vec :: FontProps cu -> Vec2 cu
+ Wumpus.Basic.System.FontLoader.Datatypes: fp_descender :: FontProps cu -> cu
+ Wumpus.Basic.System.FontLoader.Datatypes: instance (Ord cu, Tolerance cu) => Eq (MonospaceDefaults cu)
+ Wumpus.Basic.System.FontLoader.Datatypes: instance Eq AfmGlyphMetrics
+ Wumpus.Basic.System.FontLoader.Datatypes: instance Show AfmFile
+ Wumpus.Basic.System.FontLoader.Datatypes: instance Show AfmGlyphMetrics
+ Wumpus.Basic.System.FontLoader.Datatypes: instance Show cu => Show (MonospaceDefaults cu)
+ Wumpus.Basic.System.FontLoader.Datatypes: type AfmBoundingBox = BoundingBox AfmUnit
+ Wumpus.Basic.System.FontLoader.Datatypes: type AfmKey = String
+ Wumpus.Basic.System.FontLoader.Datatypes: type GlobalInfo = Map AfmKey String
+ Wumpus.Basic.System.FontLoader.Datatypes: type PSCharCode = Int
+ Wumpus.Basic.System.FontLoader.Datatypes: type PSEncodingScheme = String
+ Wumpus.Basic.System.FontLoader.FontLoadMonad: buildAfmFontProps :: MonospaceDefaults AfmUnit -> AfmFile -> FontLoadIO (FontProps AfmUnit)
+ Wumpus.Basic.System.FontLoader.FontLoadMonad: checkFontPath :: FilePath -> FilePath -> FontLoadIO FilePath
+ Wumpus.Basic.System.FontLoader.FontLoadMonad: data FontLoadIO a
+ Wumpus.Basic.System.FontLoader.FontLoadMonad: evalFontLoadIO :: FontLoadIO a -> IO (Either FontLoadMsg a)
+ Wumpus.Basic.System.FontLoader.FontLoadMonad: instance Functor FontLoadIO
+ Wumpus.Basic.System.FontLoader.FontLoadMonad: instance Monad FontLoadIO
+ Wumpus.Basic.System.FontLoader.FontLoadMonad: loadError :: FontLoadMsg -> FontLoadIO a
+ Wumpus.Basic.System.FontLoader.FontLoadMonad: promoteEither :: Either FontLoadMsg a -> FontLoadIO a
+ Wumpus.Basic.System.FontLoader.FontLoadMonad: promoteIO :: IO a -> FontLoadIO a
+ Wumpus.Basic.System.FontLoader.FontLoadMonad: runFontLoadIO :: FontLoadIO a -> IO (Either FontLoadMsg a, FontLoadLog)
+ Wumpus.Basic.System.FontLoader.FontLoadMonad: runParserFLIO :: FilePath -> Parser Char a -> FontLoadIO a
+ Wumpus.Basic.System.FontLoader.FontLoadMonad: sequenceAll :: [FontLoadIO a] -> FontLoadIO [a]
+ Wumpus.Basic.System.FontLoader.FontLoadMonad: tellLoadMsg :: String -> FontLoadIO ()
+ Wumpus.Basic.System.FontLoader.GSTopLevel: loadGSFont1 :: FilePath -> FontDef -> IO FontLoadResult
+ Wumpus.Basic.System.FontLoader.GSTopLevel: loadGSFontMetrics :: FilePath -> [FontDef] -> IO FontLoadResult
+ Wumpus.Basic.Utils.HList: prefixListH :: H a -> [a] -> [a]
- Wumpus.Basic.Geometry.Base: bezierLength :: (Floating u, Ord u, FromPtSize u) => BezierCurve u -> u
+ Wumpus.Basic.Geometry.Base: bezierLength :: (Floating u, Ord u, Tolerance u) => BezierCurve u -> u
- Wumpus.Basic.Geometry.Intersection: findIntersect :: (Floating u, Real u, Ord u, FromPtSize u) => Point2 u -> Radian -> [LineSegment u] -> Maybe (Point2 u)
+ Wumpus.Basic.Geometry.Intersection: findIntersect :: (Floating u, Real u, Ord u, Tolerance u) => Point2 u -> Radian -> [LineSegment u] -> Maybe (Point2 u)
- Wumpus.Basic.Geometry.Intersection: interCurveLine :: (Floating u, Ord u, FromPtSize u) => BezierCurve u -> (Point2 u, Point2 u) -> Maybe (Point2 u)
+ Wumpus.Basic.Geometry.Intersection: interCurveLine :: (Floating u, Ord u, Tolerance u) => BezierCurve u -> (Point2 u, Point2 u) -> Maybe (Point2 u)
- Wumpus.Basic.Geometry.Intersection: interLinesegLine :: (Fractional u, Ord u, FromPtSize u) => LineSegment u -> (Point2 u, Point2 u) -> Maybe (Point2 u)
+ Wumpus.Basic.Geometry.Intersection: interLinesegLine :: (Fractional u, Ord u, Tolerance u) => LineSegment u -> (Point2 u, Point2 u) -> Maybe (Point2 u)
- Wumpus.Basic.Geometry.Intersection: interLinesegLineseg :: (Fractional u, Ord u, FromPtSize u) => LineSegment u -> LineSegment u -> Maybe (Point2 u)
+ Wumpus.Basic.Geometry.Intersection: interLinesegLineseg :: (Fractional u, Ord u, Tolerance u) => LineSegment u -> LineSegment u -> Maybe (Point2 u)
- Wumpus.Basic.Geometry.Paths: coordinatePrimPath :: Num u => Point2 u -> LocCoordPath u -> PrimPath u
+ Wumpus.Basic.Geometry.Paths: coordinatePrimPath :: InterpretUnit u => LocCoordPath u -> Point2 u -> Query PrimPath
- Wumpus.Basic.Kernel.Base.ContextFun: apply1R1 :: CF1 r1 a -> r1 -> CF a
+ Wumpus.Basic.Kernel.Base.ContextFun: apply1R1 :: CF (r1 -> a) -> r1 -> CF a
- Wumpus.Basic.Kernel.Base.ContextFun: apply1R2 :: CF2 r1 r2 a -> r2 -> CF1 r1 a
+ Wumpus.Basic.Kernel.Base.ContextFun: apply1R2 :: CF (r1 -> r2 -> a) -> r2 -> CF (r1 -> a)
- Wumpus.Basic.Kernel.Base.ContextFun: apply2R2 :: CF2 r1 r2 a -> r1 -> r2 -> CF a
+ Wumpus.Basic.Kernel.Base.ContextFun: apply2R2 :: CF (r1 -> r2 -> a) -> r1 -> r2 -> CF a
- Wumpus.Basic.Kernel.Base.ContextFun: drawingCtx :: CF DrawingContext
+ Wumpus.Basic.Kernel.Base.ContextFun: drawingCtx :: Query DrawingContext
- Wumpus.Basic.Kernel.Base.ContextFun: lift0R1 :: CF a -> CF1 r1 a
+ Wumpus.Basic.Kernel.Base.ContextFun: lift0R1 :: CF a -> CF (r1 -> a)
- Wumpus.Basic.Kernel.Base.ContextFun: lift0R2 :: CF a -> CF2 r1 r2 a
+ Wumpus.Basic.Kernel.Base.ContextFun: lift0R2 :: CF a -> CF (r1 -> r2 -> a)
- Wumpus.Basic.Kernel.Base.ContextFun: lift1R2 :: CF1 r1 a -> CF2 r1 r2 a
+ Wumpus.Basic.Kernel.Base.ContextFun: lift1R2 :: CF (r1 -> a) -> CF (r1 -> r2 -> a)
- Wumpus.Basic.Kernel.Base.ContextFun: promoteR1 :: (r1 -> CF a) -> CF1 r1 a
+ Wumpus.Basic.Kernel.Base.ContextFun: promoteR1 :: (r1 -> CF a) -> CF (r1 -> a)
- Wumpus.Basic.Kernel.Base.ContextFun: promoteR2 :: (r1 -> r2 -> CF a) -> CF2 r1 r2 a
+ Wumpus.Basic.Kernel.Base.ContextFun: promoteR2 :: (r1 -> r2 -> CF a) -> CF (r1 -> r2 -> a)
- Wumpus.Basic.Kernel.Base.DrawingContext: DrawingContext :: GlyphMetrics -> MetricsOps -> StrokeAttr -> FontAttr -> RGBi -> RGBi -> Double -> Double -> TextMargin -> DrawingContext
+ Wumpus.Basic.Kernel.Base.DrawingContext: DrawingContext :: FontTable -> FontLoadLog -> FontMetrics -> FontFace -> !FontSize -> (Double, Double) -> StrokeAttr -> RGBi -> RGBi -> RGBi -> Double -> TextMargin -> ConnectorProps -> DrawingContext
- Wumpus.Basic.Kernel.Base.DrawingContext: TextMargin :: !Double -> !Double -> TextMargin
+ Wumpus.Basic.Kernel.Base.DrawingContext: TextMargin :: !Em -> !Em -> TextMargin
- Wumpus.Basic.Kernel.Base.DrawingContext: metricsContext :: FontSize -> GlyphMetrics -> DrawingContext
+ Wumpus.Basic.Kernel.Base.DrawingContext: metricsContext :: FontSize -> FontLoadResult -> DrawingContext
- Wumpus.Basic.Kernel.Base.DrawingContext: text_margin_x :: TextMargin -> !Double
+ Wumpus.Basic.Kernel.Base.DrawingContext: text_margin_x :: TextMargin -> !Em
- Wumpus.Basic.Kernel.Base.DrawingContext: text_margin_y :: TextMargin -> !Double
+ Wumpus.Basic.Kernel.Base.DrawingContext: text_margin_y :: TextMargin -> !Em
- Wumpus.Basic.Kernel.Base.DrawingContext: withFontMetrics :: (MetricsOps -> PtSize -> u) -> DrawingContext -> u
+ Wumpus.Basic.Kernel.Base.DrawingContext: withFontMetrics :: (FontMetrics -> FontSize -> u) -> DrawingContext -> u
- Wumpus.Basic.Kernel.Base.QueryDC: cwLookupTable :: (FromPtSize u, DrawingCtxM m) => m (CharWidthTable u)
+ Wumpus.Basic.Kernel.Base.QueryDC: cwLookupTable :: DrawingCtxM m => m CharWidthLookup
- Wumpus.Basic.Kernel.Base.QueryDC: glyphBoundingBox :: (FromPtSize u, DrawingCtxM m) => m (BoundingBox u)
+ Wumpus.Basic.Kernel.Base.QueryDC: glyphBoundingBox :: (DrawingCtxM m, InterpretUnit u) => m (BoundingBox u)
- Wumpus.Basic.Kernel.Base.QueryDC: markHalfHeight :: (DrawingCtxM m, Fractional u, FromPtSize u) => m u
+ Wumpus.Basic.Kernel.Base.QueryDC: markHalfHeight :: (Fractional u, DrawingCtxM m, InterpretUnit u) => m u
- Wumpus.Basic.Kernel.Base.QueryDC: markHeight :: (DrawingCtxM m, FromPtSize u) => m u
+ Wumpus.Basic.Kernel.Base.QueryDC: markHeight :: (DrawingCtxM m, InterpretUnit u) => m u
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: hprimToList :: HPrim u -> [Primitive u]
+ Wumpus.Basic.Kernel.Base.WrappedPrimitive: hprimToList :: HPrim u -> [Primitive]
- Wumpus.Basic.Kernel.Base.WrappedPrimitive: singleH :: Primitive u -> HPrim u
+ Wumpus.Basic.Kernel.Base.WrappedPrimitive: singleH :: CatPrim -> HPrim u
- Wumpus.Basic.Kernel.Objects.Bounded: bbrectangle :: Fractional u => BoundingBox u -> Graphic u
+ Wumpus.Basic.Kernel.Objects.Bounded: bbrectangle :: InterpretUnit u => BoundingBox u -> Graphic u
- Wumpus.Basic.Kernel.Objects.Bounded: centerOrthoBBox :: (Real u, Floating u) => Radian -> BoundingBox u -> BoundingBox u
+ Wumpus.Basic.Kernel.Objects.Bounded: centerOrthoBBox :: (Real u, Floating u, Ord u) => Radian -> BoundingBox u -> BoundingBox u
- Wumpus.Basic.Kernel.Objects.Bounded: emptyBoundedLocGraphic :: Num u => BoundedLocGraphic u
+ Wumpus.Basic.Kernel.Objects.Bounded: emptyBoundedLocGraphic :: InterpretUnit u => BoundedLocGraphic u
- Wumpus.Basic.Kernel.Objects.Bounded: emptyBoundedLocThetaGraphic :: Num u => BoundedLocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.Bounded: emptyBoundedLocThetaGraphic :: InterpretUnit u => BoundedLocThetaGraphic u
- Wumpus.Basic.Kernel.Objects.Bounded: illustrateBoundedGraphic :: Fractional u => BoundedGraphic u -> BoundedGraphic u
+ Wumpus.Basic.Kernel.Objects.Bounded: illustrateBoundedGraphic :: InterpretUnit u => BoundedGraphic u -> BoundedGraphic u
- Wumpus.Basic.Kernel.Objects.Bounded: illustrateBoundedLocGraphic :: Fractional u => BoundedLocGraphic u -> BoundedLocGraphic u
+ Wumpus.Basic.Kernel.Objects.Bounded: illustrateBoundedLocGraphic :: InterpretUnit u => BoundedLocGraphic u -> BoundedLocGraphic u
- Wumpus.Basic.Kernel.Objects.Bounded: illustrateBoundedLocThetaGraphic :: Fractional u => BoundedLocThetaGraphic u -> BoundedLocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.Bounded: illustrateBoundedLocThetaGraphic :: InterpretUnit u => BoundedLocThetaGraphic u -> BoundedLocThetaGraphic u
- Wumpus.Basic.Kernel.Objects.Connector: emptyConnectorGraphic :: Num u => ConnectorGraphic u
+ Wumpus.Basic.Kernel.Objects.Connector: emptyConnectorGraphic :: InterpretUnit u => ConnectorGraphic u
- Wumpus.Basic.Kernel.Objects.Connector: intoConnectorImage :: ConnectorCF u a -> ConnectorGraphic u -> ConnectorImage u a
+ Wumpus.Basic.Kernel.Objects.Connector: intoConnectorImage :: ConnectorQuery u a -> ConnectorGraphic u -> ConnectorImage u a
- Wumpus.Basic.Kernel.Objects.Connector: type ConnectorGraphic u = ConnectorCF u (GraphicAns u)
+ Wumpus.Basic.Kernel.Objects.Connector: type ConnectorGraphic u = ConnectorQuery u (GraphicAns u)
- Wumpus.Basic.Kernel.Objects.Connector: type ConnectorImage u a = ConnectorCF u (ImageAns u a)
+ Wumpus.Basic.Kernel.Objects.Connector: type ConnectorImage u a = ConnectorQuery u (ImageAns u a)
- Wumpus.Basic.Kernel.Objects.CtxPicture: data CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: data CtxPicture
- Wumpus.Basic.Kernel.Objects.CtxPicture: drawTracing :: (Real u, Floating u, FromPtSize u) => TraceDrawing u a -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: drawTracing :: TraceDrawing u a -> CtxPicture
- Wumpus.Basic.Kernel.Objects.CtxPicture: mapCtxPicture :: (Picture u -> Picture u) -> CtxPicture u -> CtxPicture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: mapCtxPicture :: (Picture -> Picture) -> CtxPicture -> CtxPicture
- Wumpus.Basic.Kernel.Objects.CtxPicture: runCtxPicture :: DrawingContext -> CtxPicture u -> Maybe (Picture u)
+ Wumpus.Basic.Kernel.Objects.CtxPicture: runCtxPicture :: DrawingContext -> CtxPicture -> Maybe Picture
- Wumpus.Basic.Kernel.Objects.CtxPicture: runCtxPictureU :: DrawingContext -> CtxPicture u -> Picture u
+ Wumpus.Basic.Kernel.Objects.CtxPicture: runCtxPictureU :: DrawingContext -> CtxPicture -> Picture
- Wumpus.Basic.Kernel.Objects.Displacement: moveStart :: PointDisplace u -> LocCF u a -> LocCF u a
+ Wumpus.Basic.Kernel.Objects.Displacement: moveStart :: PointDisplace u -> LocQuery u a -> LocQuery u a
- Wumpus.Basic.Kernel.Objects.Displacement: moveStartTheta :: ThetaPointDisplace u -> LocThetaCF u a -> LocThetaCF u a
+ Wumpus.Basic.Kernel.Objects.Displacement: moveStartTheta :: ThetaPointDisplace u -> LocThetaQuery u a -> LocThetaQuery u a
- Wumpus.Basic.Kernel.Objects.Displacement: moveStartThetaPoint :: PointDisplace u -> LocThetaCF u a -> LocThetaCF u a
+ Wumpus.Basic.Kernel.Objects.Displacement: moveStartThetaPoint :: PointDisplace u -> LocThetaQuery u a -> LocThetaQuery u a
- Wumpus.Basic.Kernel.Objects.Displacement: type ThetaPointDisplace u = Radian -> PointDisplace u
+ Wumpus.Basic.Kernel.Objects.Displacement: type ThetaPointDisplace u = Radian -> Point2 u -> Point2 u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedCircle :: Floating u => u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedCircle :: InterpretUnit u => u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedDisk :: Num u => u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedDisk :: InterpretUnit u => u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedEllipse :: Floating u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedEllipse :: InterpretUnit u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedEllipseDisk :: Num u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedEllipseDisk :: InterpretUnit u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedPath :: Num u => PrimPath u -> Graphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedPath :: PrimPath -> Graphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedRectangle :: Fractional u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: borderedRectangle :: InterpretUnit u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: closedStroke :: Num u => PrimPath u -> Graphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: closedStroke :: PrimPath -> Graphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledCircle :: Floating u => u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledCircle :: InterpretUnit u => u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledDisk :: Num u => u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledDisk :: InterpretUnit u => u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledEllipse :: Floating u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledEllipse :: InterpretUnit u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledEllipseDisk :: Num u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledEllipseDisk :: InterpretUnit u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledPath :: Num u => PrimPath u -> Graphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledPath :: PrimPath -> Graphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledRectangle :: Fractional u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: filledRectangle :: InterpretUnit u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: openStroke :: Num u => PrimPath u -> Graphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: openStroke :: PrimPath -> Graphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rborderedEllipse :: (Real u, Floating u) => u -> u -> LocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rborderedEllipse :: InterpretUnit u => u -> u -> LocThetaGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rfilledEllipse :: (Real u, Floating u) => u -> u -> LocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rfilledEllipse :: InterpretUnit u => u -> u -> LocThetaGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rstrokedEllipse :: (Real u, Floating u) => u -> u -> LocThetaGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: rstrokedEllipse :: InterpretUnit u => u -> u -> LocThetaGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: straightLine :: Fractional u => Vec2 u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: straightLine :: InterpretUnit u => Point2 u -> Point2 u -> Graphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedCircle :: Floating u => u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedCircle :: InterpretUnit u => u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedDisk :: Num u => u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedDisk :: InterpretUnit u => u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedEllipse :: Floating u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedEllipse :: InterpretUnit u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedEllipseDisk :: Num u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedEllipseDisk :: InterpretUnit u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedRectangle :: Fractional u => u -> u -> LocGraphic u
+ Wumpus.Basic.Kernel.Objects.DrawingPrimitives: strokedRectangle :: InterpretUnit u => u -> u -> LocGraphic u
- Wumpus.Basic.Kernel.Objects.TraceDrawing: draw :: (TraceM m, DrawingCtxM m, u ~ (MonUnit m)) => Graphic u -> m ()
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: draw :: (TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => Image u a -> m ()
- Wumpus.Basic.Kernel.Objects.TraceDrawing: drawi :: (TraceM m, DrawingCtxM m, u ~ (MonUnit m)) => Image u a -> m a
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: drawi :: (TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => Image u a -> m a
- Wumpus.Basic.Kernel.Objects.TraceDrawing: liftToPictureMb :: (Real u, Floating u, FromPtSize u) => HPrim u -> Maybe (Picture u)
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: liftToPictureMb :: HPrim u -> Maybe Picture
- Wumpus.Basic.Kernel.Objects.TraceDrawing: liftToPictureU :: (Real u, Floating u, FromPtSize u) => HPrim u -> Picture u
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: liftToPictureU :: HPrim u -> Picture
- Wumpus.Basic.Kernel.Objects.TraceDrawing: mbPictureU :: (Real u, Floating u, FromPtSize u) => Maybe (Picture u) -> Picture u
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: mbPictureU :: Maybe Picture -> Picture
- Wumpus.Basic.Kernel.Objects.TraceDrawing: node :: (TraceM m, DrawingCtxM m, PointSupplyM m, (MonUnit m) ~ u) => LocGraphic u -> m ()
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: node :: (Fractional u, TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => (Int, Int) -> LocImage u a -> m ()
- Wumpus.Basic.Kernel.Objects.TraceDrawing: nodei :: (TraceM m, DrawingCtxM m, PointSupplyM m, (MonUnit m) ~ u) => LocImage u a -> m a
+ Wumpus.Basic.Kernel.Objects.TraceDrawing: nodei :: (Fractional u, TraceM m, DrawingCtxM m, u ~ (MonUnit (m ()))) => (Int, Int) -> LocImage u a -> m a
Files
- demo/AltUnits.hs +77/−0
- demo/FontDeltaPic.hs +9/−10
- demo/SimpleAdvGraphic.hs +29/−13
- demo/SimplePosImage.hs +0/−98
- demo/SimplePosObject.hs +108/−0
- src/Wumpus/Basic/Geometry.hs +31/−0
- src/Wumpus/Basic/Geometry/Base.hs +14/−14
- src/Wumpus/Basic/Geometry/Intersection.hs +14/−22
- src/Wumpus/Basic/Geometry/Paths.hs +214/−9
- src/Wumpus/Basic/Kernel.hs +26/−15
- src/Wumpus/Basic/Kernel/Base/Anchors.hs +0/−222
- src/Wumpus/Basic/Kernel/Base/BaseDefs.hs +193/−33
- src/Wumpus/Basic/Kernel/Base/ContextFun.hs +126/−371
- src/Wumpus/Basic/Kernel/Base/DrawingContext.hs +280/−74
- src/Wumpus/Basic/Kernel/Base/FontSupport.hs +256/−0
- src/Wumpus/Basic/Kernel/Base/GlyphMetrics.hs +0/−120
- src/Wumpus/Basic/Kernel/Base/QueryDC.hs +172/−160
- src/Wumpus/Basic/Kernel/Base/ScalingContext.hs +0/−104
- src/Wumpus/Basic/Kernel/Base/Units.hs +163/−0
- src/Wumpus/Basic/Kernel/Base/UpdateDC.hs +516/−139
- src/Wumpus/Basic/Kernel/Base/WrappedPrimitive.hs +62/−70
- src/Wumpus/Basic/Kernel/Objects/AdvObject.hs +230/−0
- src/Wumpus/Basic/Kernel/Objects/AdvanceGraphic.hs +0/−166
- src/Wumpus/Basic/Kernel/Objects/Anchors.hs +233/−0
- src/Wumpus/Basic/Kernel/Objects/BaseObjects.hs +0/−186
- src/Wumpus/Basic/Kernel/Objects/Basis.hs +564/−0
- src/Wumpus/Basic/Kernel/Objects/Bounded.hs +66/−30
- src/Wumpus/Basic/Kernel/Objects/Chain.hs +228/−0
- src/Wumpus/Basic/Kernel/Objects/Concat.hs +188/−0
- src/Wumpus/Basic/Kernel/Objects/Connector.hs +76/−49
- src/Wumpus/Basic/Kernel/Objects/CtxPicture.hs +140/−342
- src/Wumpus/Basic/Kernel/Objects/Displacement.hs +202/−72
- src/Wumpus/Basic/Kernel/Objects/DrawingPrimitives.hs +287/−157
- src/Wumpus/Basic/Kernel/Objects/Graphic.hs +0/−282
- src/Wumpus/Basic/Kernel/Objects/Image.hs +105/−0
- src/Wumpus/Basic/Kernel/Objects/LocImage.hs +199/−0
- src/Wumpus/Basic/Kernel/Objects/LocThetaImage.hs +367/−0
- src/Wumpus/Basic/Kernel/Objects/Orientation.hs +500/−0
- src/Wumpus/Basic/Kernel/Objects/PosImage.hs +0/−237
- src/Wumpus/Basic/Kernel/Objects/PosObject.hs +446/−0
- src/Wumpus/Basic/Kernel/Objects/TraceDrawing.hs +193/−56
- src/Wumpus/Basic/System/FontLoader.hs +141/−0
- src/Wumpus/Basic/System/FontLoader/Afm.hs +0/−83
- src/Wumpus/Basic/System/FontLoader/AfmParserBase.hs +214/−0
- src/Wumpus/Basic/System/FontLoader/AfmTopLevel.hs +111/−0
- src/Wumpus/Basic/System/FontLoader/AfmV2Parser.hs +65/−0
- src/Wumpus/Basic/System/FontLoader/AfmV4Dot1Parser.hs +63/−0
- src/Wumpus/Basic/System/FontLoader/Base/AfmParserBase.hs +0/−214
- src/Wumpus/Basic/System/FontLoader/Base/AfmV2Parser.hs +0/−65
- src/Wumpus/Basic/System/FontLoader/Base/AfmV4Dot1Parser.hs +0/−63
- src/Wumpus/Basic/System/FontLoader/Base/Datatypes.hs +0/−182
- src/Wumpus/Basic/System/FontLoader/Base/FontLoadMonad.hs +0/−215
- src/Wumpus/Basic/System/FontLoader/Base/GSFontMap.hs +0/−108
- src/Wumpus/Basic/System/FontLoader/Datatypes.hs +158/−0
- src/Wumpus/Basic/System/FontLoader/FontLoadMonad.hs +200/−0
- src/Wumpus/Basic/System/FontLoader/GSTopLevel.hs +108/−0
- src/Wumpus/Basic/System/FontLoader/GhostScript.hs +0/−87
- src/Wumpus/Basic/Utils/HList.hs +4/−0
- src/Wumpus/Basic/Utils/JoinList.hs +1/−1
- src/Wumpus/Basic/VersionNumber.hs +2/−2
- wumpus-basic.cabal +54/−18
+ demo/AltUnits.hs view
@@ -0,0 +1,77 @@+{-# OPTIONS -Wall #-}+++module AltUnits where++import Wumpus.Basic.Kernel++import Wumpus.Core -- package: wumpus-core++import System.Directory++main :: IO ()+main = do + createDirectoryIfMissing True "./out/"+ let pic1 = runCtxPictureU std_attr drawing01+ writeEPS "./out/alt_units01.eps" pic1+ writeSVG "./out/alt_units01.svg" pic1+++std_attr :: DrawingContext+std_attr = (stroke_colour firebrick . fill_colour linen) $ standardContext 12+++drawing01 :: CtxPicture+drawing01 = drawTracing $ combined+++mf1 :: TraceDrawing Double ()+mf1 = do+ draw $ dblLocGraphic `at` P2 12 0++mf2 :: TraceDrawing Em ()+mf2 = do+ draw $ emLocGraphic `at` P2 1 0++combined :: TraceDrawing Double ()+combined = do + draw $ dblLocGraphic `at` P2 12 108+ drawl (P2 12 72) $ uconvLocImageF emLocGraphic+ draw $ uconvImageF $ emLocGraphic `at` P2 1 3+ drawl (P2 12 0) $ uconvLocImageF $ pushR1 (hyperlink haskell_org) enLocGraphic++dblLocGraphic :: LocGraphic Double+dblLocGraphic = rect1 `oplus` rect2 + where+ rect1 = borderedRectangle 36 24 + rect2 = moveStart (displaceH 36) $ borderedRectangle 60 24 ++++emLocGraphic :: LocGraphic Em+emLocGraphic = localize swap_colours $ rect1 `oplus` rect2 + where+ rect1 = borderedRectangle 3 2 + rect2 = moveStart (displaceH 3) $ borderedRectangle 5 2 +++enLocGraphic :: LocGraphic En+enLocGraphic = localize (fill_colour lemon_chiffon) $ rect1 `oplus` rect2 + where+ rect1 = borderedRectangle 6 4+ rect2 = moveStart (displaceH 6) $ borderedRectangle 10 4+++haskell_org :: XLink+haskell_org = xlinkhref "http://www.haskell.org"++firebrick :: RGBi+firebrick = RGBi 0xb2 0x22 0x22++lemon_chiffon :: RGBi+lemon_chiffon = RGBi 0xff 0xfa 0xcd++linen :: RGBi+linen = RGBi 0xfa 0xf0 0xe6++
demo/FontDeltaPic.hs view
@@ -16,8 +16,7 @@ main :: IO () main = do createDirectoryIfMissing True "./out/"- putStrLn $ "Note - the SVG optimization that should be used here"- putStrLn $ "has bit-rotted and is not currently in use.."+ putStrLn $ "Check the generated SVG to verify the font attrs are grouped..." -- let pic1 = runCtxPictureU std_attr drawing01 writeEPS "./out/font_delta01.eps" pic1@@ -28,23 +27,23 @@ std_attr = standardContext 24 -drawing01 :: DCtxPicture+drawing01 :: CtxPicture drawing01 = drawTracing $ mf -mf :: (Floating u, FromPtSize u) => TraceDrawing u ()-mf = do +mf :: TraceDrawing Double ()+mf = fontDelta $ do draw $ line1 `at` (P2 0 100) draw $ line2 `at` (P2 0 75) draw $ line3 `at` (P2 0 50) draw $ line4 `at` (P2 0 25) draw $ line5 `at` (P2 0 0) where- line1 = textline "All the lines of this drawing" - line2 = textline "should be grouped within a SVG"- line3 = textline "g-element, from where they"- line4 = textline "inherit the font-family and"- line5 = textline "font-size attributes."+ line1 = plainTextLine "All the lines of this drawing" + line2 = plainTextLine "should be grouped within a SVG"+ line3 = plainTextLine "g-element, from where they"+ line4 = plainTextLine "inherit the font-family and"+ line5 = plainTextLine "font-size attributes."
demo/SimpleAdvGraphic.hs view
@@ -7,6 +7,7 @@ import Wumpus.Core -- package: wumpus-core +import Control.Applicative import System.Directory main :: IO ()@@ -21,31 +22,46 @@ std_attr = standardContext 24 -drawing01 :: DCtxPicture-drawing01 = drawTracing $ mf +drawing01 :: CtxPicture+drawing01 = drawTracing mf -mf :: (Floating u, FromPtSize u) => TraceDrawing u ()++-- Although TraceDrawing can be fully unit polymorphic, it seems +-- always best to specialize as we are stating concrete values+-- (and they will be in some unit).+--++mf :: TraceDrawing Double () mf = do- drawi_ $ advspace (hvec 10) [text01, text02, text01] `at` P2 0 120- drawi_ $ advconcat [text01, text02, text01] `at` P2 0 80- drawi_ $ (miniDisk `advcat` text01 `advcat` miniDisk) `at` P2 0 40 - drawi_ $ (miniDisk `advcat` text02 `advcat` miniDisk) `at` P2 0 0 + drawl (P2 0 120) $ + runAdvObjectR1 $ evenspace (hvec 10) [text01, text02, text01] + drawl (P2 0 80) $ + runAdvObjectR1 $ advances [text01, text02, text01] + drawl (P2 0 40) $ + runAdvObjectR1 (miniDisk `advance` text01 `advance` miniDisk)++ drawl (P2 0 0) $+ runAdvObjectR1 (miniDisk `advance` text02 `advance` miniDisk)++ -- Normally, text calculate the advance vector from the font -- metrics... ---text01 :: Num u => AdvGraphic u -text01 = replaceAns (hvec 84) $ textline "text01"+text01 :: AdvObject Double+text01 = makeAdvObject (pure $ hvec 84) $ plainTextLine "text01" -text02 :: Num u => AdvGraphic u -text02 = replaceAns (hvec 210) $ textline "text number two"+text02 :: AdvObject Double+text02 = makeAdvObject (pure $ hvec 210) $ plainTextLine "text number two" -miniDisk :: Num u => AdvGraphic u-miniDisk = replaceAns (V2 0 0) $ localize (fillColour sienna) $ filledDisk 3+miniDisk :: AdvObject Double+miniDisk = makeAdvObject (pure $ V2 0 0) disk1 + where+ disk1 = localize (fill_colour sienna) $ filledDisk 3 sienna :: RGBi
− demo/SimplePosImage.hs
@@ -1,98 +0,0 @@-{-# OPTIONS -Wall #-}---module SimplePosImage where--import Wumpus.Basic.Kernel--import Wumpus.Core -- package: wumpus-core-import Wumpus.Core.Colour ( red )--import System.Directory--main :: IO ()-main = do - createDirectoryIfMissing True "./out/"- let pic1 = runCtxPictureU std_attr drawing01- writeEPS "./out/simple_pos_image01.eps" pic1- writeSVG "./out/simple_pos_image01.svg" pic1---std_attr :: DrawingContext-std_attr = standardContext 24---drawing01 :: DCtxPicture-drawing01 = drawTracing $ localize (fillColour red) $ mf ---mf :: (Floating u, FromPtSize u) => TraceDrawing u ()-mf = do- draw $ testDrawMinor NN `at` (P2 0 300)- draw $ testDrawMinor SS `at` (P2 75 300)- draw $ testDrawMinor EE `at` (P2 150 300)- draw $ testDrawMinor WW `at` (P2 225 300)- draw $ testDrawMinor NE `at` (P2 0 225)- draw $ testDrawMinor SE `at` (P2 75 225)- draw $ testDrawMinor SW `at` (P2 150 225)- draw $ testDrawMinor NW `at` (P2 225 225)- draw $ testDrawMinor CENTER `at` (P2 0 150)- draw $ testDrawBl CENTER `at` (P2 225 150)- draw $ testDrawBl NN `at` (P2 0 75)- draw $ testDrawBl SS `at` (P2 75 75)- draw $ testDrawBl EE `at` (P2 150 75)- draw $ testDrawBl WW `at` (P2 225 75)- draw $ testDrawBl NE `at` (P2 0 0)- draw $ testDrawBl SE `at` (P2 75 0)- draw $ testDrawBl SW `at` (P2 150 0)- draw $ testDrawBl NW `at` (P2 225 0)- --testDrawBl :: Floating u => RectPosition -> LocGraphic u-testDrawBl rpos = filledDisk 2 `oplus` (rectBl `startPos` rpos)--rectBl :: Floating u => PosGraphic u -rectBl = makePosImage opos (mkRectBl w h)- where- w = 40 - h = 20- opos = ObjectPos { op_x_minor = 0- , op_x_major = w- , op_y_minor = 0- , op_y_major = h }- ---- start-point - bottom left-mkRectBl :: Floating u => u -> u -> LocGraphic u-mkRectBl w h = promoteR1 $ \bl -> - let br = displaceH w bl- tr = displaceV h br- tl = displaceV h bl- in closedStroke $ vertexPath [bl, br, tr, tl]----testDrawMinor :: Floating u => RectPosition -> LocGraphic u-testDrawMinor rpos = filledDisk 2 `oplus` (rectMinor `startPos` rpos)--rectMinor :: Floating u => PosGraphic u -rectMinor = makePosImage opos (mkRectMinor m w h)- where- m = 10- w = 40 - h = 20- opos = ObjectPos { op_x_minor = m- , op_x_major = (w-m)- , op_y_minor = m- , op_y_major = (h-m) }- ---- start-point - +10 +10-mkRectMinor :: Floating u => u -> u -> u -> LocGraphic u-mkRectMinor m w h = promoteR1 $ \pt -> - let bl = displaceVec (vec (-m) (-m)) pt- br = displaceH w bl- tr = displaceV h br- tl = displaceV h bl- in closedStroke $ vertexPath [bl, br, tr, tl]-
+ demo/SimplePosObject.hs view
@@ -0,0 +1,108 @@+{-# OPTIONS -Wall #-}+++module SimplePosObject where++import Wumpus.Basic.Kernel++import Wumpus.Core -- package: wumpus-core+import Wumpus.Core.Colour ( red )++import System.Directory++++main :: IO ()+main = do + createDirectoryIfMissing True "./out/"+ let pic1 = runCtxPictureU std_ctx drawing01+ writeEPS "./out/simple_pos_object01.eps" pic1+ writeSVG "./out/simple_pos_object01.svg" pic1+++std_ctx :: DrawingContext+std_ctx = standardContext 24+++drawing01 :: CtxPicture+drawing01 = drawTracing $ localize (fill_colour red) $ mf +++mf :: TraceDrawing Double ()+mf = do+ draw $ testDrawMinor NN `at` (P2 0 400)+ draw $ testDrawMinor SS `at` (P2 75 400)+ draw $ testDrawMinor EE `at` (P2 150 400)+ draw $ testDrawMinor WW `at` (P2 225 400)+ draw $ testDrawMinor NE `at` (P2 0 325)+ draw $ testDrawMinor SE `at` (P2 75 325)+ draw $ testDrawMinor SW `at` (P2 150 325)+ draw $ testDrawMinor NW `at` (P2 225 325)+ draw $ testDrawMinor CENTER `at` (P2 0 250)+ draw $ testDrawMinor BLL `at` (P2 75 250)+ draw $ testDrawMinor BLC `at` (P2 150 250)+ draw $ testDrawMinor BLR `at` (P2 225 250)+++ draw $ testDrawBl NN `at` (P2 0 150)+ draw $ testDrawBl SS `at` (P2 75 150)+ draw $ testDrawBl EE `at` (P2 150 150)+ draw $ testDrawBl WW `at` (P2 225 150)+ draw $ testDrawBl NE `at` (P2 0 75)+ draw $ testDrawBl SE `at` (P2 75 75)+ draw $ testDrawBl SW `at` (P2 150 75)+ draw $ testDrawBl NW `at` (P2 225 75)+ draw $ testDrawBl CENTER `at` (P2 0 0)+ draw $ testDrawBl BLL `at` (P2 75 0)+ draw $ testDrawBl BLC `at` (P2 150 0)+ draw $ testDrawBl BLR `at` (P2 225 0)+ ++testDrawBl :: (Floating u, InterpretUnit u) => RectAddress -> LocGraphic u+testDrawBl rpos = + filledDisk 2 `oplus` (pushR1 ignoreAns $ rectBl `startAddr` rpos)++rectBl :: (Fractional u, InterpretUnit u) => BoundedLocRectGraphic u+rectBl = runPosObjectR2 $ makePosObject (return ortt) (mkRectBl w h)+ where+ w = 40 + h = 30+ ortt = Orientation { or_x_minor = 0+ , or_x_major = w+ , or_y_minor = 0+ , or_y_major = h }+ ++-- start-point - bottom left+mkRectBl :: InterpretUnit u => u -> u -> LocGraphic u+mkRectBl w h = strokedRectangle w h++++testDrawMinor :: (Floating u, InterpretUnit u) => RectAddress -> LocGraphic u+testDrawMinor rpos = + filledDisk 2 `oplus` (pushR1 ignoreAns $ rectMinor `startAddr` rpos)+++rectMinor :: (Fractional u, InterpretUnit u) => BoundedLocRectGraphic u +rectMinor = + runPosObjectR2 $ makePosObject (return ortt) (mkRectMinor m w h)+ where+ m = 10+ w = 40 + h = 30+ ortt = Orientation { or_x_minor = m+ , or_x_major = (w-m)+ , or_y_minor = m+ , or_y_major = (h-m) }+ ++-- start-point - +10 +10+mkRectMinor :: InterpretUnit u => u -> u -> u -> LocGraphic u+mkRectMinor m w h = promoteR1 $ \pt -> + let bl = displaceVec (vec (-m) (-m)) pt+ br = displaceH w bl+ tr = displaceV h br+ tl = displaceV h bl+ in vertexPP [bl, br, tr, tl] >>= closedStroke+
+ src/Wumpus/Basic/Geometry.hs view
@@ -0,0 +1,31 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.Kernel+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- Import shim for @Wumpus.Basic.Geometry@ modules.+--+--+--------------------------------------------------------------------------------++module Wumpus.Basic.Geometry+ (+ module Wumpus.Basic.Geometry.Base+ , module Wumpus.Basic.Geometry.Intersection+ , module Wumpus.Basic.Geometry.Paths+ , module Wumpus.Basic.Geometry.Quadrant++ ) where+++import Wumpus.Basic.Geometry.Base+import Wumpus.Basic.Geometry.Intersection+import Wumpus.Basic.Geometry.Paths+import Wumpus.Basic.Geometry.Quadrant
src/Wumpus/Basic/Geometry/Base.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE TypeFamilies #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -19,7 +18,8 @@ ( -- * constants- half_pi+ quarter_pi+ , half_pi , two_pi -- * 2x2 Matrix@@ -75,13 +75,18 @@ -half_pi :: Floating u => u-half_pi = 0.5*pi -two_pi :: Floating u => u-two_pi = 2*pi +quarter_pi :: Floating u => u+quarter_pi = 0.25 * pi +half_pi :: Floating u => u+half_pi = 0.5 * pi++two_pi :: Floating u => u+two_pi = 2.0 * pi++ -------------------------------------------------------------------------------- -- 2x2 matrix @@ -99,9 +104,7 @@ type DMatrix2'2 = Matrix2'2 Double -type instance DUnit (Matrix2'2 u) = u - instance Functor Matrix2'2 where fmap f (M2'2 a b c d) = M2'2 (f a) (f b) (f c) (f d) @@ -166,7 +169,6 @@ type DLineEquation = LineEquation Double -type instance DUnit (LineEquation u) = u -- | 'lineEquation' : @ point1 * point2 -> LineEquation @ -- @@ -230,7 +232,6 @@ type DLineSegment = LineSegment Double -type instance DUnit (LineSegment u) = u @@ -276,7 +277,6 @@ type DBezierCurve = BezierCurve Double -type instance DUnit (BezierCurve u) = u @@ -291,9 +291,9 @@ -- The result is found through repeated subdivision so the -- calculation is potentially costly. ---bezierLength :: (Floating u, Ord u, FromPtSize u) +bezierLength :: (Floating u, Ord u, Tolerance u) => BezierCurve u -> u-bezierLength = gravesenLength (fromPtSize 0.1)+bezierLength = gravesenLength length_tolerance @@ -408,7 +408,7 @@ -- > ang should be in the range 0 < ang <= 90deg. -- bezierMinorArc :: Floating u - => Radian -> u -> Radian -> Point2 u -> BezierCurve u+ => Radian -> u -> Radian -> Point2 u -> BezierCurve u bezierMinorArc ang radius theta pt = BezierCurve p0 c1 c2 p3 where kfactor = fromRadian $ ang / (0.5*pi)
src/Wumpus/Basic/Geometry/Intersection.hs view
@@ -20,16 +20,13 @@ module Wumpus.Basic.Geometry.Intersection ( - LineSegment- , interLineLine+ interLineLine , interLinesegLineseg , interLinesegLine , interCurveLine , findIntersect , makePlane- , rectangleLineSegments- , polygonLineSegments ) @@ -85,7 +82,7 @@ -- An answer of @Nothing@ indicates that the line segments -- coincide, or that there is no intersection. ---interLinesegLineseg :: (Fractional u, Ord u, FromPtSize u)+interLinesegLineseg :: (Fractional u, Ord u, Tolerance u) => LineSegment u -> LineSegment u -> Maybe (Point2 u) interLinesegLineseg a@(LineSegment p q) b@(LineSegment s t) = interLineLine (p,q) (s,t) >>= segcheck@@ -101,7 +98,7 @@ -- An answer of @Nothing@ indicates that the the line and line -- segment coincide, or that there is no intersection. ---interLinesegLine :: (Fractional u, Ord u, FromPtSize u)+interLinesegLine :: (Fractional u, Ord u, Tolerance u) => LineSegment u -> (Point2 u, Point2 u) -> Maybe (Point2 u) interLinesegLine a@(LineSegment p q) line = interLineLine (p,q) line >>= segcheck@@ -117,30 +114,28 @@ -- Note - this function is to be used \*after\* an intersection -- has been found. Hence it is not export. ---withinPoints :: (Ord u, FromPtSize u) => Point2 u -> LineSegment u -> Bool+withinPoints :: (Ord u, Fractional u, Tolerance u) + => Point2 u -> LineSegment u -> Bool withinPoints (P2 x y) (LineSegment (P2 x0 y0) (P2 x1 y1)) = between x (ordpair x0 x1) && between y (ordpair y0 y1) where ordpair a b = (min a b, max a b) between a (s,t) = (s `tGT` a) && (a `tGT` t) - tGT a b = a < b || abs (a-b) < tolerance --- | Note - its important to use tolerance for the @withPoints@ --- function.----tolerance :: FromPtSize u => u-tolerance = fromPtSize 0.01 -+pve :: (Fractional u, Ord u, Tolerance u) => u -> Bool+pve a = a > eq_tolerance +nve :: (Fractional u, Ord u, Tolerance u) => u -> Bool+nve a = a < (negate eq_tolerance) -------------------------------------------------------------------------------- -- intersection of line and Bezier curve -interCurveLine :: (Floating u , Ord u, FromPtSize u)+interCurveLine :: (Floating u , Ord u, Tolerance u) => BezierCurve u -> (Point2 u, Point2 u) -> Maybe (Point2 u) interCurveLine c0 (p,q) = step c0 where@@ -159,16 +154,13 @@ -- as it saves performing a subdivision. But make the return type -- a bit involved. ---cut :: (Floating u , Ord u, FromPtSize u)+cut :: (Floating u , Ord u, Tolerance u) => BezierCurve u -> LineEquation u -> Either (Point2 u) Bool cut (BezierCurve p0 p1 p2 p3) line = if d0 `tEQ` 0 then Left p0 else if d3 `tEQ` 0 then Left p3 else let ds = [d0,d1,d2,d3] in Right $ not $ all pve ds || all nve ds where- tEQ = \a b -> abs (a-b) < tolerance- pve = \a -> a > tolerance- nve = \a -> a < (negate tolerance) d0 = pointLineDistance p0 line d1 = pointLineDistance p1 line d2 = pointLineDistance p2 line @@ -190,9 +182,9 @@ -- at angle @theta@ and the supplied line segments, if there -- is one. ---findIntersect :: (Floating u, Real u, Ord u, FromPtSize u)- => Point2 u -> Radian -> [LineSegment u] - -> Maybe (Point2 u)+findIntersect :: (Floating u, Real u, Ord u, Tolerance u)+ => Point2 u -> Radian -> [LineSegment u] + -> Maybe (Point2 u) findIntersect radial_ogin ang = step where plane = makePlane radial_ogin ang
src/Wumpus/Basic/Geometry/Paths.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE TypeFamilies #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -18,7 +19,24 @@ module Wumpus.Basic.Geometry.Paths ( - LocCoordPath++ PathAlg+ , runPathAlgPoint+ , runPathAlgVec+ , pathStartIsStart+ , pathStartIsLocus+ , pathIterateLocus++ , rectanglePathAlg+ , blRectanglePathAlg++ , diamondPathAlg+ , polygonPathAlg++ , arcPathAlg+ , circlePathAlg++ , LocCoordPath , coordinatePrimPath , rectangleCoordPath@@ -31,14 +49,202 @@ ) where +import Wumpus.Basic.Geometry.Base+import Wumpus.Basic.Kernel+ import Wumpus.Core -- package: wumpus-core import Data.AffineSpace -- package: vector-space-+import Data.VectorSpace import Data.List ( unfoldr ) +data PathAlgScheme = START_IS_START | START_IS_LOCUS + deriving (Enum,Eq,Ord,Show)+++-- | A vector chain building a path.+--+-- The vectors are relative to the predecessor, so the+-- rendering of a 'PathAlg' iterates the start point.+--+-- A polygon PathAlg should have steps for all sides of the +-- polygon with the end point generated by the last vector +-- coinciding with thet start point.+-- +data PathAlg u = PathAlg { path_alg_scheme :: PathAlgScheme+ , path_alg_steps :: [Vec2 u]+ }+++type instance DUnit (PathAlg u) = u++runPathAlgPoint :: Num u => Point2 u -> PathAlg u -> [Point2 u]+runPathAlgPoint _ (PathAlg _ []) = []+runPathAlgPoint p0 (PathAlg scm (v0:xs)) + | scm == START_IS_START = p0 : step (p0 .+^ v0) xs+ | otherwise = step (p0 .+^ v0) xs+ where+ step pt [] = [pt]+ step pt (v:vs) = pt : step (pt .+^ v) vs+++runPathAlgVec :: PathAlg u -> (Maybe (Vec2 u), [Vec2 u]) +runPathAlgVec (PathAlg START_IS_LOCUS (v:vs)) = (Just v, vs)+runPathAlgVec (PathAlg _ vs) = (Nothing, vs)++++-- TO CLARIFY - should all four side paths of a rectangle be +-- generated, or three sides with the implication that close forms+-- the fourth?+--++pathStartIsStart :: [Vec2 u] -> PathAlg u+pathStartIsStart vs = PathAlg { path_alg_scheme = START_IS_START+ , path_alg_steps = vs }++++pathStartIsLocus :: [Vec2 u] -> PathAlg u+pathStartIsLocus vs = PathAlg { path_alg_scheme = START_IS_LOCUS+ , path_alg_steps = vs }++-- | Note this creates a path very the first vector represents a+-- @moveto@, then the subsequence vectors represent @linetos@.+-- +pathIterateLocus :: Num u => [Vec2 u] -> PathAlg u+pathIterateLocus [] = pathStartIsLocus []+pathIterateLocus (v0:xs) = pathStartIsLocus $ v0 : step v0 xs+ where+ step v1 [] = [v0 ^-^ v1]+ step v1 (v2:vs) = (v2 ^-^ v1) : step v2 vs+++++-- | Supplied point is /center/, the genearated points are +-- counter-clockwise so [ bl, br, tr, tl ] .+--+rectanglePathAlg :: Fractional u => u -> u -> PathAlg u+rectanglePathAlg w h = pathStartIsLocus [ vbl, vbr, vtr, vtl ]+ where+ vbl = vec (negate $ 0.5*w) (negate $ 0.5*h)+ vbr = hvec w+ vtr = vvec h+ vtl = hvec (-w) ++-- | Supplied point is /bottom-left/, subsequent points are +-- counter-clockwise so [ bl, br, tr, tl ] .+--+blRectanglePathAlg :: Num u => u -> u -> PathAlg u+blRectanglePathAlg w h = pathStartIsStart [ vbr, vtr, vtl, vbl ]+ where+ vbr = hvec w+ vtr = vvec h+ vtl = hvec (-w) + vbl = vvec (-h)+++++-- | 'diamondPathAlg' : @ half_width * half_height -> PathAlg @+--+diamondPathAlg :: Num u => u -> u -> PathAlg u+diamondPathAlg hw hh = pathIterateLocus [ vs,ve,vn,vw ]+ where+ vs = vvec (-hh)+ ve = hvec hw+ vn = vvec hh+ vw = hvec (-hw)+ ++-- | 'polygonPathAlg' : @ num_points * radius -> PathAlg @ +--+polygonPathAlg :: Floating u => Int -> u -> PathAlg u+polygonPathAlg n radius = pathIterateLocus $ unfoldr phi (0,top)+ where+ top = 0.5*pi+ theta = (2*pi) / fromIntegral n+ + phi (i,ang) | i < n = Just (avec ang radius, (i+1,ang+theta))+ | otherwise = Nothing+++arcPathAlg :: Floating u => u -> Radian -> Radian -> PathAlg u+arcPathAlg r ang1 ang2 = pathStartIsLocus $ step1 $ arcdiv ang1 ang2+ where+ step1 [] = []+ step1 ((a,b):xs) = let (v0,v1,v2,v3) = minorArcQuadVec r a b+ in v0 : v1: v2: v3 : step xs++ step [] = []+ step ((a,b):xs) = let (_,v1,v2,v3) = minorArcQuadVec r a b+ in v1: v2: v3 : step xs+++ +-- | Helper - generate four vectors building a minor (<90 deg) +-- arc.+--+-- The first vec is from center - for cumulative arcs this should +-- only taken once.+--+minorArcQuadVec :: Floating u + => u -> Radian -> Radian -> (Vec2 u, Vec2 u, Vec2 u, Vec2 u)+minorArcQuadVec r ang1 ang2 = (v0, v1, v2, v3)+ where+ (p1,p2,p3,p4) = bezierArc r ang1 ang2 zeroPt+ v0 = pvec zeroPt p1 + v1 = pvec p1 p2+ v2 = pvec p2 p3+ v3 = pvec p3 p4+++circlePathAlg :: (Fractional u, Floating u) + => u -> PathAlg u+circlePathAlg r = pathStartIsLocus vs+ where+ vs = hvec r : diff (flip pvec) (bezierCircle r zeroPt)+++++-- | Helper - diff +-- +-- Note diff relies on the pointlist cycling the endpoint+-- +-- > [p0, ..., p0]+--+-- This is how Wumpus-Core generates Bezier circles.+-- +diff :: (a -> a -> b) -> [a] -> [b]+diff _ [] = []+diff op (x:xs) = step x xs+ where+ step _ [] = []+ step a (b:bs) = b `op` a : step b bs++-- | Helper - divide an arc into quadrants plus remainder.+--+arcdiv :: Radian -> Radian -> [(Radian,Radian)]+arcdiv ang1 ang2 | ang1 > ang2 = step ang1 (ang2 + 2 * pi) + | otherwise = step ang1 ang2+ where+ step a1 a2 | a1 == a2 = []+ step a1 a2 | a2 - a1 > half_pi = norm (a1,a1+half_pi) : step (a1+half_pi) a2+ | otherwise = [(a1,a2)]++ norm (a,b) = (circularModulo a, circularModulo b)++++-- arcs - wedges - circles...++---------------------------------------------------------------------------+-- OLD ...+ -- | A functional type from /initial point/ to point list. -- type LocCoordPath u = Point2 u -> [Point2 u]@@ -51,17 +257,16 @@ -- The Path data type will also need a similar function... -- -coordinatePrimPath :: Num u => Point2 u -> LocCoordPath u -> PrimPath u-coordinatePrimPath pt fn = go (fn pt)- where- go ps@(_:_) = vertexPath ps- go [] = emptyPath pt -- fallback+-- | Relative unit version of 'coordinatePrimPathAU'.+--+coordinatePrimPath :: InterpretUnit u + => LocCoordPath u -> Point2 u -> Query PrimPath+coordinatePrimPath fn pt = vertexPP $ fn pt --- NOTE - These functions need changing to generate LocCoordPaths... -- | Supplied point is /bottom-left/, subsequenct points are --- counter-clockise so [ bl, br, tr, tl ] .+-- counter-clockwise so [ bl, br, tr, tl ] . -- rectangleCoordPath :: Num u => u -> u -> LocCoordPath u rectangleCoordPath w h bl = [ bl, br, tr, tl ]
src/Wumpus/Basic/Kernel.hs view
@@ -17,43 +17,54 @@ module Wumpus.Basic.Kernel (- module Wumpus.Basic.Kernel.Base.Anchors- , module Wumpus.Basic.Kernel.Base.BaseDefs+ module Wumpus.Basic.Kernel.Base.BaseDefs , module Wumpus.Basic.Kernel.Base.ContextFun , module Wumpus.Basic.Kernel.Base.DrawingContext- , module Wumpus.Basic.Kernel.Base.GlyphMetrics+ , module Wumpus.Basic.Kernel.Base.FontSupport , module Wumpus.Basic.Kernel.Base.QueryDC- , module Wumpus.Basic.Kernel.Base.ScalingContext+ , module Wumpus.Basic.Kernel.Base.Units , module Wumpus.Basic.Kernel.Base.UpdateDC , module Wumpus.Basic.Kernel.Base.WrappedPrimitive- , module Wumpus.Basic.Kernel.Objects.AdvanceGraphic- , module Wumpus.Basic.Kernel.Objects.BaseObjects+ , module Wumpus.Basic.Kernel.Objects.AdvObject+ , module Wumpus.Basic.Kernel.Objects.Anchors+ , module Wumpus.Basic.Kernel.Objects.Basis , module Wumpus.Basic.Kernel.Objects.Bounded+ , module Wumpus.Basic.Kernel.Objects.Chain+ , module Wumpus.Basic.Kernel.Objects.Concat , module Wumpus.Basic.Kernel.Objects.Connector , module Wumpus.Basic.Kernel.Objects.CtxPicture , module Wumpus.Basic.Kernel.Objects.Displacement , module Wumpus.Basic.Kernel.Objects.DrawingPrimitives- , module Wumpus.Basic.Kernel.Objects.Graphic- , module Wumpus.Basic.Kernel.Objects.PosImage+ , module Wumpus.Basic.Kernel.Objects.Image+ , module Wumpus.Basic.Kernel.Objects.LocImage+ , module Wumpus.Basic.Kernel.Objects.LocThetaImage+ , module Wumpus.Basic.Kernel.Objects.Orientation+ , module Wumpus.Basic.Kernel.Objects.PosObject , module Wumpus.Basic.Kernel.Objects.TraceDrawing+ ) where -import Wumpus.Basic.Kernel.Base.Anchors import Wumpus.Basic.Kernel.Base.BaseDefs import Wumpus.Basic.Kernel.Base.ContextFun import Wumpus.Basic.Kernel.Base.DrawingContext-import Wumpus.Basic.Kernel.Base.GlyphMetrics+import Wumpus.Basic.Kernel.Base.FontSupport import Wumpus.Basic.Kernel.Base.QueryDC-import Wumpus.Basic.Kernel.Base.ScalingContext+import Wumpus.Basic.Kernel.Base.Units import Wumpus.Basic.Kernel.Base.UpdateDC import Wumpus.Basic.Kernel.Base.WrappedPrimitive-import Wumpus.Basic.Kernel.Objects.AdvanceGraphic-import Wumpus.Basic.Kernel.Objects.BaseObjects+import Wumpus.Basic.Kernel.Objects.AdvObject+import Wumpus.Basic.Kernel.Objects.Anchors+import Wumpus.Basic.Kernel.Objects.Basis import Wumpus.Basic.Kernel.Objects.Bounded+import Wumpus.Basic.Kernel.Objects.Chain+import Wumpus.Basic.Kernel.Objects.Concat import Wumpus.Basic.Kernel.Objects.Connector import Wumpus.Basic.Kernel.Objects.CtxPicture import Wumpus.Basic.Kernel.Objects.Displacement import Wumpus.Basic.Kernel.Objects.DrawingPrimitives-import Wumpus.Basic.Kernel.Objects.Graphic-import Wumpus.Basic.Kernel.Objects.PosImage+import Wumpus.Basic.Kernel.Objects.Image+import Wumpus.Basic.Kernel.Objects.LocImage+import Wumpus.Basic.Kernel.Objects.LocThetaImage+import Wumpus.Basic.Kernel.Objects.Orientation+import Wumpus.Basic.Kernel.Objects.PosObject import Wumpus.Basic.Kernel.Objects.TraceDrawing
− src/Wumpus/Basic/Kernel/Base/Anchors.hs
@@ -1,222 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.Kernel.Base.Anchors--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Anchor points on shapes, bounding boxes, etc.------ Anchors are addressable positions, an examplary use is taking--- anchors on node shapes to get the start and end points for --- connectors in a network (graph) diagram.--- --- \*\* WARNING \*\* - The API here needs some thought as to a--- good balance of the type classes - in a nutshell \"are corners --- better than cardinals\". Originally I tried to follow how I --- understand the TikZ anchors to work, but this is perhaps not --- ideal for dividing into type-classes.--------------------------------------------------------------------------------------module Wumpus.Basic.Kernel.Base.Anchors- ( -- -- * Anchors- CenterAnchor(..)- , ApexAnchor(..)- , CardinalAnchor(..)- , CardinalAnchor2(..)- , RadialAnchor(..)- , TopCornerAnchor(..)- , BottomCornerAnchor(..)- , SideMidpointAnchor(..)--- -- * Extended anchor points- , projectAnchor-- , radialConnectorPoints-- ) where--import Wumpus.Core -- package: wumpus-core--import Data.AffineSpace -- package: vector-space----- | Center of an object.----class CenterAnchor t where- center :: DUnit t ~ u => t -> Point2 u----- | Apex of an object.----class ApexAnchor t where- apex :: DUnit t ~ u => t -> Point2 u----- | Cardinal (compass) positions on an object. --- --- Note - in TikZ cardinal anchors are not necessarily at the--- equivalent radial position, for instance reactangle north-east--- is the top-right corner whether or not this is incident at --- 45deg.------ Wumpus generally follows the TikZ convention.----class CardinalAnchor t where- north :: DUnit t ~ u => t -> Point2 u- south :: DUnit t ~ u => t -> Point2 u- east :: DUnit t ~ u => t -> Point2 u- west :: DUnit t ~ u => t -> Point2 u------- Note - a design change is probably in order where the cardinals --- should /always/ represent their true cardinal position.------ If this change is made, it is worthwhile having cardinals as--- classes (rather than making them derived operations on --- RadialAnchor) as classes allow for more efficient --- implementations usually by trigonometry.--- ----- | Secondary group of cardinal (compass) positions on an object. --- --- It seems possible that for some objects defining the primary--- compass points (north, south,...) will be straight-forward --- whereas defining the secondary compass points may be --- problematic, hence the compass points are split into two --- classes.----class CardinalAnchor2 t where- northeast :: DUnit t ~ u => t -> Point2 u- southeast :: DUnit t ~ u => t -> Point2 u- southwest :: DUnit t ~ u => t -> Point2 u- northwest :: DUnit t ~ u => t -> Point2 u----- | Anchor on a border that can be addressed by an angle.------ The angle is counter-clockwise from the right-horizontal, i.e.--- 0 is /east/.----class RadialAnchor t where- radialAnchor :: DUnit t ~ u => Radian -> t -> Point2 u----- | Anchors at the top left and right corners of a shape.------ For some shapes (Rectangle) the TikZ convention appears to be--- have cardinals as the corner anchors, but this doesn\'t seem--- to be uniform. Wumpus will need to reconsider anchors at some --- point...----class TopCornerAnchor t where- topLeftCorner :: DUnit t ~ u => t -> Point2 u- topRightCorner :: DUnit t ~ u => t -> Point2 u----- | Anchors at the bottom left and right corners of a shape.----class BottomCornerAnchor t where- bottomLeftCorner :: DUnit t ~ u => t -> Point2 u- bottomRightCorner :: DUnit t ~ u => t -> Point2 u----- | Anchors in the center of a side.--- --- Sides are addressable by index. Following TikZ, side 1 is --- expected to be the top of the shape. If the shape has an apex --- instead of a side then side 1 is expected to be the first side --- left of the apex.--- --- Implementations are also expected to modulo the side number, --- rather than throw an out-of-bounds error.----class SideMidpointAnchor t where- sideMidpoint :: DUnit t ~ u => Int -> t -> Point2 u---------------------------------------------------------------------------------------- | 'projectAnchor' : @ extract_func * dist * object -> Point @--- --- Derive a anchor by projecting a line from the center of an --- object through the intermediate anchor (produced by the --- extraction function). The final answer point is located along--- the projected line at the supplied distance @dist@.--- --- E.g. take the north of a rectangle and project it 10 units --- further on:--- --- > projectAnchor north 10 my_rect------ If the distance is zero the answer with be whatever point the --- the extraction function produces.------ If the distance is negative the answer will be along the --- projection line, between the center and the intermediate anchor.------ If the distance is positive the anchor will be extend outwards --- from the intermediate anchor.----projectAnchor :: (Real u, Floating u, u ~ DUnit t, CenterAnchor t) - => (t -> Point2 u) -> u -> t -> Point2 u-projectAnchor f d a = p1 .+^ (avec ang d)- where- p1 = f a- v = pvec (center a) p1- ang = vdirection v- --------------------------------------------------------------------------------------- | 'radialConnectorPoints' : @ object_a * object_b -> (Point_a, Point_b) @------ Find the radial connectors points for objects @a@ and @b@ along--- the line joining their centers.----radialConnectorPoints :: ( Real u, Floating u- , CenterAnchor t1, RadialAnchor t1- , CenterAnchor t2, RadialAnchor t2- , u ~ DUnit t1, DUnit t1 ~ DUnit t2 ) - => t1 -> t2 -> (Point2 u, Point2 u) -radialConnectorPoints a b = (radialAnchor theta a, radialAnchor (theta+pi) b)- where- theta = vdirection $ pvec (center a) (center b)- ------------------------------------------------------------------------------------- Instances --instance Fractional u => CenterAnchor (BoundingBox u) where- center (BBox (P2 xl ylo) (P2 xr yhi)) = P2 x y - where- x = xl+0.5*(xr-xl)- y = ylo+0.5*(yhi-ylo)- --instance Fractional u => CardinalAnchor (BoundingBox u) where- north (BBox (P2 xl _ ) (P2 xr yhi)) = P2 (xl+0.5*(xr-xl)) yhi- south (BBox (P2 xl ylo) (P2 xr _ )) = P2 (xl+0.5*(xr-xl)) ylo- east (BBox (P2 _ ylo) (P2 xr yhi)) = P2 xr (ylo+0.5*(yhi-ylo))- west (BBox (P2 xl ylo) (P2 _ yhi)) = P2 xl (ylo+0.5*(yhi-ylo))---instance Fractional u => CardinalAnchor2 (BoundingBox u) where- northeast (BBox _ ur) = ur- southeast (BBox (P2 _ ylo) (P2 xr _)) = P2 xr ylo- southwest (BBox ll _) = ll- northwest (BBox (P2 xl _) (P2 _ yhi)) = P2 xl yhi -
src/Wumpus/Basic/Kernel/Base/BaseDefs.hs view
@@ -1,13 +1,10 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS -Wall #-} -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Basic.Kernal.Base.BaseDefs--- Copyright : (c) Stephen Tetley 2010+-- Copyright : (c) Stephen Tetley 2010-2011 -- License : BSD3 -- -- Maintainer : stephen.tetley@gmail.com@@ -21,16 +18,35 @@ module Wumpus.Basic.Kernel.Base.BaseDefs (+ + MonUnit -- * A semigroup class- OPlus(..)+ , OPlus(..) , oconcat+ , altconcat + -- * A bifunctor class , Bimap(..) , replaceL , replaceR + -- * Unit phantom type+ , UNil(..)++ -- * Non-contextual unit conversion.+ , ScalarUnit(..)++ -- * Unit interpretation with respect to the current Point size+ , InterpretUnit(..)+ , dinterpF+ , normalizeF+ , uconvert1+ , uconvertF+ , intraMapPoint+ , intraMapFunctor+ -- * Alignment , HAlign(..) , VAlign(..) @@ -43,18 +59,29 @@ , advanceH , advanceV -- -- * Monadic drawing- , MonUnit-- , PointSupplyM(..)- ) where import Wumpus.Core -- package: wumpus-core import Data.VectorSpace -- package: vector-space +import Control.Applicative+import Data.Monoid++++++-- | Type family to access the unit parameter of a TraceDrawing+-- or a promoted TraceDrawingT transformer.+--+type family MonUnit m :: *++++++ infixr 6 `oplus` -- | A Semigroup class.@@ -66,6 +93,17 @@ class OPlus t where oplus :: t -> t -> t +-- | 'oconcat' : @ list_head * [rest] -> Ans @+-- +-- Semigroup version of @mconcat@ from the module @Data.Monoid@.+--+-- As a semigroup cannot build a zero value, /concat/ cannot +-- handle the empty list. So to make 'oconcat' a safe function+-- the input list is already destructured by one cons cell.+-- +-- Effectively this means that client code must handle the +-- empty list case, before calling 'oconcat'.+-- oconcat :: OPlus t => t -> [t] -> t oconcat t = step t where@@ -74,16 +112,35 @@ +-- | 'altconcat' : @ alternative * [list] -> Ans@+-- +-- 'altconcat' uses 'oplus' to create a summary value from a list+-- of values. +--+-- When supplied the empty list 'altconcat' returns the supplied +-- /alternative/ value. If the list is inhabited, the alternative+-- value is discarded.+--+-- This contrasts to 'oconcat' where the single value represents +-- the head of an already destructured list.+-- +altconcat :: OPlus a => a -> [a] -> a+altconcat _ (x:xs) = oconcat x xs+altconcat alt [] = alt++ instance OPlus () where _ `oplus` _ = () -instance OPlus (UNil u) where- _ `oplus` _ = uNil +instance OPlus a => OPlus (Const a b) where+ Const a0 `oplus` Const a1 = Const $ a0 `oplus` a1 ++ instance Ord u => OPlus (BoundingBox u) where oplus = boundaryUnion -instance OPlus (Primitive u) where+instance OPlus Primitive where a `oplus` b = primGroup [a,b] instance (OPlus a, OPlus b) => OPlus (a,b) where@@ -144,7 +201,129 @@ --------------------------------------------------------------------------------+-- Simple objects wrapped with unit phatom type ++-- | The empty data type - i.e. @()@ - wrapped with a phantom unit +-- parameter.+--+data UNil u = UNil deriving (Eq,Ord,Read,Show)++type instance DUnit (UNil u) = u++instance Functor UNil where+ fmap _ UNil= UNil+++instance Monoid (UNil u) where+ mempty = UNil+ _ `mappend` _ = UNil++instance OPlus (UNil u) where+ _ `oplus` _ = UNil+++++instance Rotate (UNil u) where+ rotate _ = id++instance RotateAbout (UNil u) where+ rotateAbout _ _ = id++instance Scale (UNil u) where+ scale _ _ = id++instance Translate (UNil u) where+ translate _ _ = id++--------------------------------------------------------------------------------+-- Non-contextual units++class ScalarUnit a where+ fromPsPoint :: Double -> a + toPsPoint :: a -> Double++instance ScalarUnit Double where+ fromPsPoint = id+ toPsPoint = id ++++--------------------------------------------------------------------------------+-- Interpreting units ++-- Units may or may not depend on current font size+--++class Num u => InterpretUnit u where+ normalize :: FontSize -> u -> Double+ dinterp :: FontSize -> Double -> u++instance InterpretUnit Double where+ normalize _ = id+ dinterp _ = id ++instance InterpretUnit AfmUnit where+ normalize sz = afmValue sz + dinterp sz = afmUnit sz+++-- | 'dinterp' an object that gives access to its unit at the +-- functor position.+--+dinterpF :: (Functor t, InterpretUnit u) => FontSize -> t Double -> t u+dinterpF sz = fmap (dinterp sz)+++-- | 'normalize' an object that gives access to its unit at the +-- functor position.+--+normalizeF :: (Functor t, InterpretUnit u) => FontSize -> t u -> t Double+normalizeF sz = fmap (normalize sz)+++-- | Convert a scalar value from one unit to another.+--+uconvert1 :: (InterpretUnit u, InterpretUnit u1) => FontSize -> u -> u1+uconvert1 sz = dinterp sz . normalize sz++-- | Unit convert an object that gives access to its unit at the+-- Functor position.+--+-- In practive this will be \*all\* Image answers.+--+uconvertF :: (Functor t, InterpretUnit u, InterpretUnit u1) + => FontSize -> t u -> t u1+uconvertF sz = fmap (uconvert1 sz)++++-- Helper for defining Affine instances. This function allows +-- scaling etc to be applied on a Point coerced to a Double then+-- converted back to the original unit. Thus transformations can +-- work in contextual units.+--+intraMapPoint :: InterpretUnit u + => FontSize -> (DPoint2 -> DPoint2) -> Point2 u -> Point2 u+intraMapPoint sz fn (P2 x y) = + let P2 x' y' = fn $ P2 (normalize sz x) (normalize sz y)+ in P2 (dinterp sz x') (dinterp sz y')++++-- Helper for defining Affine instances. This function allows +-- scaling etc to be applied on a Point coerced to a Double then+-- converted back to the original unit. Thus transformations can +-- work in contextual units.+--+intraMapFunctor :: (Functor f, InterpretUnit u)+ => FontSize -> (f Double -> f Double) -> f u -> f u+intraMapFunctor sz fn ma = dinterpF sz $ fn $ normalizeF sz ma+++--------------------------------------------------------------------------------+ -- Alignment -- | Horizontal alignment - align to the top, center or bottom.@@ -195,22 +374,3 @@ advanceV (V2 _ h) = h -------------------------------------------------------------------------------------- Monadic drawing---- | DUnit is always for fully saturated type constructors, so --- (seemingly) an equivalent type family is needed for monads.--type family MonUnit m :: * ----- | A monad that supplies points, e.g. a turtle monad. ------ \*\* WARNING \*\* - the idea behind this class is somewhat--- half-baked. It may be revised or even dropped in subsequent--- versions of Wumpus-Basic.----class Monad m => PointSupplyM (m :: * -> *) where- position :: MonUnit m ~ u => m (Point2 u)
src/Wumpus/Basic/Kernel/Base/ContextFun.hs view
@@ -1,9 +1,11 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleInstances #-} {-# OPTIONS -Wall #-} -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Basic.Kernel.Base.ContextFun--- Copyright : (c) Stephen Tetley 2010+-- Copyright : (c) Stephen Tetley 2010-2011 -- License : BSD3 -- -- Maintainer : stephen.tetley@gmail.com@@ -18,57 +20,42 @@ module Wumpus.Basic.Kernel.Base.ContextFun ( - -- * /Context functional/ types+ -- * /Context functional/ type CF - , CF1- , CF2 - , LocCF- , LocThetaCF- , ConnectorCF- , DLocCF- , DLocThetaCF- , DConnectorCF+ -- * Alias+ , Query + -- * Run function+ , runCF + -- * Construction+ , consCF - -- * Run functions- , runCF- , runCF1 - , runCF2+ , domMap1+ , domMap2 - -- * Lift functions- , lift0R1- , lift0R2- , lift1R2- , promoteR1 , promoteR2 + , pushR0+ , pushR1+ , pushR2 , apply1R1- , apply2R2 , apply1R2+ , apply2R2 - -- * Extractors- , drawingCtx- , queryCtx- , locCtx- , locPoint- , locThetaCtx- , locThetaPoint- , locThetaAng- , connCtx- , connStart- , connEnd+ , lift0R1+ , lift0R2+ , lift1R2 - -- * Combinators- , at- , rot- , atRot- , connect- , chain1+ , uconvR0+ , uconvR1+ , uconvR2a+ , uconvR2ab + , drawingCtx ) where @@ -85,6 +72,9 @@ -------------------------------------------------------------------------------- -- +-- NOTE - 31.03.11 - is there an advantage to adding a phantom+-- unit param to the CF functions?+ -- | Most drawing operations in Wumpus-Basic have an implicit -- /graphics state/ the 'DrawingContext', so the most primitive -- building block is a function from the DrawingContext to some @@ -95,121 +85,46 @@ -- -- > CF :: DrawingContext -> a ---newtype CF a = CF { unCF :: DrawingContext -> a }+newtype CF a = CF { getCF :: DrawingContext -> a } +type instance DUnit (CF a) = DUnit a --- | Variation of 'CF' with one parametric /static argument/.------ The static argument is commonly a point representing the start --- point / origin of a drawing.--- --- > CF1 :: DrawingContext -> r1 -> a ----newtype CF1 r1 a = CF1 { unCF1 :: DrawingContext -> r1 -> a } --- | Variation of 'CF' with two parametric /static arguments/.------ The first argument is commonly a point representing the start --- point / origin of a drawing. The second argument might --- typically be the angle of displacement (for drawing arrowheads) --- or an end point (for drawing connectors between two points).+-- | Alias for 'CF'. Wumpus considers Context functions that+-- don\'t produce graphics to be /queries/. -- --- > CF2 :: DrawingContext -> r1 -> r2 -> a +-- > Query :: DrawingContext -> a ---newtype CF2 r1 r2 a = CF2 { unCF2 :: DrawingContext -> r1 -> r2 -> a }-+-- 'Query' has no unit type parameter.+-- +type Query a = CF a --- | Type specialized verison of 'CF1' where the /static argument/--- is the /start point/.--- --- > LocCF :: DrawingContext -> Point2 u -> a ----type LocCF u a = CF1 (Point2 u) a --- | Type specialized verison of 'CF2' where the /static arguments/--- are the /start point/ and the /angle of displacement/.--- --- > LocThetaCF :: DrawingContext -> Point2 u -> Radian -> a ----type LocThetaCF u a = CF2 (Point2 u) Radian a --- | Type specialized verison of 'CF2' where the /static arguments/--- are the /start point/ and the /end point/.--- --- > ConnectorCF :: DrawingContext -> Point2 u -> Point2 u -> a ----type ConnectorCF u a = CF2 (Point2 u) (Point2 u) a----- | Alias of 'LocCF' where the unit type is specialized to --- @Double@.----type DLocCF a = LocCF Double a----- | Alias of 'LocThetaCF' where the unit type is specialized to --- @Double@.----type DLocThetaCF a = LocThetaCF Double a---- | Alias of 'ConnectorCF' where the unit type is specialized to --- @Double@.----type DConnectorCF a = ConnectorCF Double a--- -------------------------------------------------------------------------------- -- CF instances -- OPlus instance OPlus a => OPlus (CF a) where- fa `oplus` fb = CF $ \ctx -> unCF fa ctx `oplus` unCF fb ctx--instance OPlus a => OPlus (CF1 r1 a) where- fa `oplus` fb = CF1 $ \ctx r1 -> unCF1 fa ctx r1 `oplus` unCF1 fb ctx r1--instance OPlus a => OPlus (CF2 r1 r2 a) where- fa `oplus` fb = CF2 $ \ctx r1 r2 -> - unCF2 fa ctx r1 r2 `oplus` unCF2 fb ctx r1 r2+ fa `oplus` fb = CF $ \ctx -> getCF fa ctx `oplus` getCF fb ctx -- Monoid --- Nothing is stopping monoid instances, though in practice there--- might be few useful types (more in Semgigroup / OPlus)...- instance Monoid a => Monoid (CF a) where mempty = CF $ \_ -> mempty- fa `mappend` fb = CF $ \ctx -> unCF fa ctx `mappend` unCF fb ctx--instance Monoid a => Monoid (CF1 r1 a) where - mempty = CF1 $ \_ _ -> mempty- fa `mappend` fb = CF1 $ \ctx r1 -> unCF1 fa ctx r1 `mappend` unCF1 fb ctx r1--instance Monoid a => Monoid (CF2 r1 r2 a) where - mempty = CF2 $ \_ _ _ -> mempty- fa `mappend` fb = CF2 $ \ctx r1 r2 -> - unCF2 fa ctx r1 r2 `mappend` unCF2 fb ctx r1 r2-+ fa `mappend` fb = CF $ \ctx -> getCF fa ctx `mappend` getCF fb ctx -- Functor instance Functor CF where- fmap f ma = CF $ \ctx -> f $ unCF ma ctx ---instance Functor (CF1 r1) where- fmap f ma = CF1 $ \ctx r1 -> f $ unCF1 ma ctx r1 --instance Functor (CF2 r1 r2) where- fmap f ma = CF2 $ \ctx r1 r2 -> f $ unCF2 ma ctx r1 r2+ fmap f ma = CF $ \ctx -> f $ getCF ma ctx @@ -217,69 +132,46 @@ instance Applicative CF where pure a = CF $ \_ -> a- mf <*> ma = CF $ \ctx -> let f = unCF mf ctx- a = unCF ma ctx+ mf <*> ma = CF $ \ctx -> let f = getCF mf ctx+ a = getCF ma ctx in f a -instance Applicative (CF1 r1) where- pure a = CF1 $ \_ _ -> a- mf <*> ma = CF1 $ \ctx r1 -> let f = unCF1 mf ctx r1 - a = unCF1 ma ctx r1- in f a --instance Applicative (CF2 r1 r2) where- pure a = CF2 $ \_ _ _ -> a- mf <*> ma = CF2 $ \ctx r1 r2 -> let f = unCF2 mf ctx r1 r2- a = unCF2 ma ctx r1 r2- in f a---- -- Monad instance Monad CF where return a = CF $ \_ -> a- ma >>= k = CF $ \ctx -> let a = unCF ma ctx in (unCF . k) a ctx --instance Monad (CF1 r1) where- return a = CF1 $ \_ _ -> a- ma >>= k = CF1 $ \ctx r1 -> let a = unCF1 ma ctx r1 in (unCF1 . k) a ctx r1 --instance Monad (CF2 r1 r2) where- return a = CF2 $ \_ _ _ -> a- ma >>= k = CF2 $ \ctx r1 r2 -> - let a = unCF2 ma ctx r1 r2 in (unCF2 . k) a ctx r1 r2-+ ma >>= k = CF $ \ctx -> let a = getCF ma ctx in (getCF . k) a ctx -- DrawingCtxM instance DrawingCtxM CF where askDC = CF $ \ctx -> ctx- localize upd df = CF $ \ctx -> unCF df (upd ctx)+ localize upd df = CF $ \ctx -> getCF df (upd ctx) -instance DrawingCtxM (CF1 r1) where- askDC = CF1 $ \ctx _ -> ctx- localize upd df = CF1 $ \ctx r1 -> unCF1 df (upd ctx) r1 +--------------------------------------------------------------------------------+-- Affine instances -instance DrawingCtxM (CF2 r1 r2) where- askDC = CF2 $ \ctx _ _ -> ctx- localize upd df = CF2 $ \ctx r1 r2 -> unCF2 df (upd ctx) r1 r2 --- Note - there is nothing determining a DUnit for the CF types, --- so it seems appropriate not to define affine instances.------ However affine instances can be made for the Image type in --- Objects.BaseObjects.---+instance Rotate a => Rotate (CF a) where+ rotate ang = fmap (rotate ang) +instance RotateAbout a => RotateAbout (CF a) where+ rotateAbout ang pt = fmap (rotateAbout ang pt) +instance Scale a => Scale (CF a) where+ scale sx sy = fmap (scale sx sy)++instance Translate a => Translate (CF a) where+ translate dx dy = fmap (translate dx dy)+++ -------------------------------------------------------------------------------- -- Run functions @@ -287,264 +179,127 @@ -- /DrawingContext/. -- runCF :: DrawingContext -> CF a -> a-runCF ctx df = unCF df ctx+runCF ctx cf = getCF cf ctx --- | Run a /CF1/ (context function) with the supplied --- /DrawingContext/ and static argument.----runCF1 :: DrawingContext -> r1 -> CF1 r1 a -> a-runCF1 ctx r1 df = unCF1 df ctx r1 ---- | Run a /CF1/ (context function) with the supplied --- /DrawingContext/ and two static arguments.+-- | Construction function. ---runCF2 :: DrawingContext -> r1 -> r2 -> CF2 r1 r2 a -> a-runCF2 ctx r1 r2 df = unCF2 df ctx r1 r2+consCF :: (DrawingContext -> a) -> CF a+consCF fn = CF $ \ctx -> fn ctx ------------------------------------------------------------------------------------ lift functions --- | Lift a zero-arity context function 'CF' to an arity one --- context function 'CF1'.--- -lift0R1 :: CF a -> CF1 r1 a-lift0R1 mf = CF1 $ \ctx _ -> unCF mf ctx+domMap1 :: (r1 -> r1) -> CF (r1 -> a) -> CF (r1 -> a)+domMap1 f ma = CF $ \ctx -> + (\r1 -> let f1 = getCF ma ctx in f1 (f r1)) --- | Lift a zero-arity context function 'CF' to an arity two --- context function 'CF2'.--- -lift0R2 :: CF a -> CF2 r1 r2 a-lift0R2 mf = CF2 $ \ctx _ _ -> unCF mf ctx+domMap2 :: (r1 -> r1) -> (r2 -> r2) -> CF (r1 -> r2 -> a) -> CF (r1 -> r2 -> a)+domMap2 f g ma = CF $ \ctx -> + (\r1 r2 -> let f1 = getCF ma ctx in f1 (f r1) (g r2)) --- | Lift an arity one context function 'CF1' to an arity two--- context function 'CF2'.--- -lift1R2 :: CF1 r1 a -> CF2 r1 r2 a-lift1R2 mf = CF2 $ \ctx r1 _ -> unCF1 mf ctx r1 +promoteR1 :: (r1 -> CF a) -> CF (r1 -> a)+promoteR1 mf = CF $ \ctx r1 -> getCF (mf r1) ctx --- | Promote a function @from one argument to a Context Function@ --- to an arity one @Context Function@.------ The type signature is as explanatory as a description:------ > promoteR1 :: (r1 -> CF a) -> CF1 r1 a--- -promoteR1 :: (r1 -> CF a) -> CF1 r1 a-promoteR1 mf = CF1 $ \ctx r1 -> unCF (mf r1) ctx+promoteR2 :: (r1 -> r2 -> CF a) -> CF (r1 -> r2 -> a)+promoteR2 mf = CF $ \ctx r1 r2 -> getCF (mf r1 r2) ctx --- | Promote a function @from two arguments to a Context Function@ --- to an arity two @Context Function@.+-- | Apply the value transformer to the answer of the context +-- function. Figuratively /push it right/ so it works on the +-- answer. ----- The type signature is as explanatory as a description:+-- > pushR0 = fmap ----- > promoteR2 :: (r1 -> r2 -> CF a) -> CF2 r1 r2 a--- -promoteR2 :: (r1 -> r2 -> CF a) -> CF2 r1 r2 a-promoteR2 mf = CF2 $ \ctx r1 r2 -> unCF (mf r1 r2) ctx-+pushR0 :: (a -> a1) -> CF a -> CF a1+pushR0 = fmap --- | Apply an arity-one Context Function to a single argument, --- downcasting it by one level, making an arity-zero Context --- function. --- --- The type signature is as explanatory as a description:------ > apply1R1 :: CF1 r1 a -> r1 -> CF a+-- | Apply the value transformer to the answer of the context +-- function. Figuratively /push it right/ so it works on the +-- answer. ---apply1R1 :: CF1 r1 a -> r1 -> CF a-apply1R1 mf r1 = CF $ \ctx -> unCF1 mf ctx r1----- | Apply an arity-two Context Function to two arguments, --- downcasting it by two levels, making an arity-zero Context --- function. --- --- The type signature is as explanatory as a description:+-- > pushR1 = fmap . fmap ----- > apply2R2 :: CF2 r1 r2 a -> r1 -> r2 -> CF a--- -apply2R2 :: CF2 r1 r2 a -> r1 -> r2 -> CF a-apply2R2 mf r1 r2 = CF $ \ctx -> unCF2 mf ctx r1 r2+pushR1 :: (a -> a1) -> CF (r1 -> a) -> CF (r1 -> a1)+pushR1 = fmap . fmap --- | Apply an arity-two Context Function to one argument, --- downcasting it by one level, making an arity-one Context --- function. --- --- The type signature is as explanatory as a description:+-- | Apply the value transformer to the answer of the context +-- function. Figuratively /push it right/ so it works on the +-- answer. ----- > apply1R2 :: CF2 r1 r2 a -> r2 -> CF1 r1 a+-- > pushR2 = fmap . fmap . fmap ---apply1R2 :: CF2 r1 r2 a -> r2 -> CF1 r1 a-apply1R2 mf r2 = CF1 $ \ctx r1 -> unCF2 mf ctx r1 r2+pushR2 :: (a -> a1) -> CF (r1 -> r2 -> a) -> CF (r1 -> r2 -> a1)+pushR2 = fmap . fmap . fmap ------------------------------------------------------------------------------------ extractors --- | Extract the drawing context from a CtxFun.------ > (ctx -> ctx)--- -drawingCtx :: CF DrawingContext-drawingCtx = CF $ \ctx -> ctx --- | Apply the projection function to the drawing context.------ > (ctx -> a) -> (ctx -> a)----queryCtx :: (DrawingContext -> a) -> CF a-queryCtx f = CF $ \ctx -> f ctx+apply1R1 :: CF (r1 -> a) -> r1 -> CF a+apply1R1 mf r1 = CF $ \ctx -> getCF mf ctx r1 --- | Extract the drawing context from a LocCF.------ > (ctx -> pt -> ctx)----locCtx :: LocCF u DrawingContext-locCtx = CF1 $ \ctx _ -> ctx+apply1R2 :: CF (r1 -> r2 -> a) -> r2 -> CF (r1 -> a)+apply1R2 mf r2 = CF $ \ctx r1 -> getCF mf ctx r1 r2 --- | Extract the /start/ point from a LocCF.------ > (ctx -> pt -> pt)----locPoint :: LocCF u (Point2 u)-locPoint = CF1 $ \_ pt -> pt +apply2R2 :: CF (r1 -> r2 -> a) -> r1 -> r2 -> CF a+apply2R2 mf r1 r2 = CF $ \ctx -> getCF mf ctx r1 r2 --- | Extract the drawing context from a LocThetaCF.------ > (ctx -> pt -> ang -> ctx)----locThetaCtx :: LocThetaCF u DrawingContext-locThetaCtx = CF2 $ \ctx _ _ -> ctx +lift0R1 :: CF a -> CF (r1 -> a)+lift0R1 mf = CF $ \ctx _ -> getCF mf ctx --- | Extract the /start/ point from a LocThetaCF.------ > (ctx -> pt -> ang -> pt)----locThetaPoint :: LocThetaCF u (Point2 u)-locThetaPoint = CF2 $ \_ pt _ -> pt+lift0R2 :: CF a -> CF (r1 -> r2 -> a)+lift0R2 mf = CF $ \ctx _ _ -> getCF mf ctx --- | Extract the angle from a LocThetaCF.------ > (ctx -> pt -> ang -> ang)----locThetaAng :: LocThetaCF u Radian-locThetaAng = CF2 $ \_ _ ang -> ang+lift1R2 :: CF (r1 -> a) -> CF (r1 -> r2 -> a)+lift1R2 mf = CF $ \ctx r1 _ -> getCF mf ctx r1 --- | Extract the drawing context from a ConnectorCF.------ > (ctx -> pt1 -> pt2 -> ctx)----connCtx :: ConnectorCF u DrawingContext-connCtx = CF2 $ \ctx _ _ -> ctx --- | Extract the start point from a ConnectorCF.------ > (ctx -> pt1 -> pt2 -> pt1)----connStart :: ConnectorCF u (Point2 u) -connStart = CF2 $ \_ pt _ -> pt --- | Extract the end point from a ConnectorCF.------ > (ctx -> pt1 -> pt2 -> pt2)----connEnd :: ConnectorCF u (Point2 u) -connEnd = CF2 $ \_ _ pt -> pt +uconvR0 :: (FontSize -> ans -> ans1) -> CF ans -> CF ans1+uconvR0 post df = CF $ \ctx ->+ let sz = dc_font_size ctx + in post sz $ getCF df ctx +uconvR1 :: (Functor t, InterpretUnit u, InterpretUnit u1) + => (FontSize -> ans -> ans1) + -> CF (t u -> ans) -> CF (t u1 -> ans1)+uconvR1 post df = CF $ \ctx r1 -> + let sz = dc_font_size ctx + in post sz $ getCF df ctx (uconvertF sz r1) ------------------------------------------------------------------------------------ Combinators+uconvR2a :: (Functor t, InterpretUnit u, InterpretUnit u1) + => (FontSize -> ans -> ans1)+ -> CF (t u -> r2 -> ans) -> CF (t u1 -> r2 -> ans1)+uconvR2a post df = CF $ \ctx r1 r2 -> + let sz = dc_font_size ctx + in post sz $ getCF df ctx (uconvertF sz r1) r2 -infixr 1 `at`----- | Downcast a 'LocCF' function by applying it to the supplied --- point, making an arity-zero Context Function. --- --- Remember a 'LocCF' function is a 'CF1' context function where--- the /static argument/ is specialized to a start point.----at :: LocCF u a -> Point2 u -> CF a-at = apply1R1---infixr 1 `rot`----- | Downcast a 'LocThetaCF' function by applying it to the --- supplied angle, making an arity-one Context Function (a --- 'LocCF'). --- --rot :: LocThetaCF u a -> Radian -> LocCF u a-rot = apply1R2----- | Downcast a 'LocThetaCF' function by applying it to the --- supplied point and angle, making an arity-zero Context --- Function (a 'CF'). ----atRot :: LocThetaCF u a -> Point2 u -> Radian -> CF a-atRot = apply2R2----- | Downcast a 'ConnectorCF' function by applying it to the --- start and end point, making an arity-zero Context Function --- (a 'CF'). --- -connect :: ConnectorCF u a -> Point2 u -> Point2 u -> CF a-connect = apply2R2+uconvR2ab :: (Functor t1, Functor t2, InterpretUnit u, InterpretUnit u1) + => (FontSize -> ans -> ans1)+ -> CF (t1 u -> t2 u -> ans) -> CF (t1 u1 -> t2 u1 -> ans1)+uconvR2ab post df = CF $ \ctx r1 r2 -> + let sz = dc_font_size ctx + in post sz $ getCF df ctx (uconvertF sz r1) (uconvertF sz r2) -infixr 6 `chain1`---- | /Chaining/ combinator - the /answer/ of the --- first Context Function is feed to the second Context Function. ------ This contrasts with the usual idiom in @Wumpus-Basic@ where --- composite graphics are built by applying both functions to the --- same initial /static argument/.------ Desciption:------ Evaluate the first Context Function with the drawing context --- and the /initial state/ @st0@. The result of the evaluation is --- a new /state/ @st1@ and and answer @a1@. ------ Evaluate the second Context Function with the drawing context --- and the new state @st1@, producing a new state @s2@ and an --- answer @a2@.------ Return the result of combining the answers with --- @op :: (ans -> ans -> ans)@ and the second state @s2@.------ @ (ctx -> s1 -> (w,s1)) -> (ctx -> s1 -> (w,s1)) -> (ctx -> s1 -> (w,s1)) @+-- | Extract the drawing context from a CtxFun. ----- This models chaining start points together, which is the model--- PostScript uses for text output when successively calling the --- @show@ operator.+-- > (ctx -> ctx) -- -chain1 :: OPlus w - => CF1 s1 (s1,w) -> CF1 s1 (s1,w) -> CF1 s1 (s1,w)-chain1 f g = CF1 $ \ctx s -> let (s1,a1) = unCF1 f ctx s- (s2,a2) = unCF1 g ctx s1- in (s2, a1 `oplus` a2)+drawingCtx :: Query DrawingContext+drawingCtx = CF $ \ctx -> ctx
src/Wumpus/Basic/Kernel/Base/DrawingContext.hs view
@@ -4,7 +4,7 @@ -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Basic.Kernel.Base.DrawingContext--- Copyright : (c) Stephen Tetley 2010+-- Copyright : (c) Stephen Tetley 2010-2011 -- License : BSD3 -- -- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>@@ -24,22 +24,24 @@ module Wumpus.Basic.Kernel.Base.DrawingContext ( - -- * Drawing context+ -- * Drawing context types DrawingContext(..)- , DrawingContextF + , DrawingContextF , TextMargin(..)+ , ConnectorProps(..) + -- * Construction , standardContext , metricsContext+ , addFontTables - , default_drawing_context+ , reset_drawing_properties+ , reset_drawing_metrics -- * DrawingCtxM (reader) monad , DrawingCtxM(..)- , asksDC - -- * Glyph metrics , withFontMetrics @@ -47,13 +49,15 @@ ) where -import Wumpus.Basic.Kernel.Base.GlyphMetrics+import Wumpus.Basic.Kernel.Base.FontSupport+import Wumpus.Basic.Kernel.Base.Units import Wumpus.Core -- package: wumpus-core import Wumpus.Core.Text.StandardEncoding import Control.Applicative import Data.Maybe+import Data.Monoid -- | 'DrawingContext' - the \"graphics state\" of Wumpus-Basic. -- DrawingContext is operated on within a Reader monad rather than @@ -61,29 +65,31 @@ -- operation (called @localize@ in Wumpus), rather than permanent -- until overridden as per @set@ of a State monad. -- --- Note - @round_corner_factor@ is only accounted for by some --- graphic objects (certain Path objects and Shapes in --- Wumpus-Drawing for instance). There many be many objects that --- ignore it and are drawn only with angular corners.--- --- Also note - in contrast to most other drawing objects in --- Wumpus, none of the measurement values are parameteric - --- usually notated with the type variable @u@ in Wumpus. This is --- so Wumpus can (potentially) support different units e.g. --- centimeters rather than just Doubles (represening printers --- points), though adding support for other units has a very low --- priority.--- +-- Note - in contrast to most other drawing objects in Wumpus, +-- none of the types of measurement values are parameteric +-- (usually notated with the type variable @u@ in Wumpus). Types +-- are either 'Double' representing PostScript points or Em - a +-- contextual size that is interpreted according to the current +-- font size.+--+-- It is easier to specialize all the measurement types and +-- within the 'DrawingContext' and add parametricity to the +-- /getters/ and /setters/ instead.+-- data DrawingContext = DrawingContext- { glyph_tables :: GlyphMetrics- , fallback_metrics :: MetricsOps- , stroke_props :: StrokeAttr- , font_props :: FontAttr- , stroke_colour :: RGBi -- also text colour...- , fill_colour :: RGBi - , line_spacing_factor :: Double- , round_corner_factor :: Double - , text_margin :: TextMargin+ { dc_font_metrics_table :: FontTable+ , dc_font_load_log :: FontLoadLog+ , dc_fallback_metrics :: FontMetrics+ , dc_font_face :: FontFace+ , dc_font_size :: !FontSize+ , dc_snap_grid_factors :: (Double,Double)+ , dc_stroke_props :: StrokeAttr+ , dc_stroke_colour :: RGBi+ , dc_fill_colour :: RGBi + , dc_text_colour :: RGBi+ , dc_line_spacing_factor :: Double+ , dc_text_margin :: TextMargin+ , dc_connector_props :: ConnectorProps } -- TODO - what parts of the Drawing Context should be strict? @@ -93,43 +99,240 @@ -- type DrawingContextF = DrawingContext -> DrawingContext --- | The unit of Margin is always Double representing Points, e.g.--- 1.0 is 1 Point. Margins are not scaled relative to the current--- font size.+-- | The text margin is measured in 'Em' so it is relative to the+-- current font size. -- --- The default value is 2 point.+-- The default value is 0.5. -- data TextMargin = TextMargin- { text_margin_x :: !Double- , text_margin_y :: !Double+ { text_margin_x :: !Em+ , text_margin_y :: !Em } +-- | ConnectorProps control the drawing of connectors in +-- Wumpus-Drawing.+--+-- > conn_src_space :: Em+-- > conn_dst_space :: Em+--+-- Source and destination spacers - these add spacing between the +-- respective connector points and the tips of the drawn connector.+-- +-- > conn_src_offset :: Em+-- > conn_dst_offset :: Em+--+-- Source and destination offsets - these offset the drawing of+-- the connector perpendicular to the direction of line formed +-- between the connector points (a positive offset is drawn above, +-- a negative offset below). The main use of offsets is to draw+-- parallel line connectors.+--+-- > conn_arc_ang :: Radian +--+-- Control the /bend/ of an arc connector.+-- +-- > conn_src_arm :: Em+-- > conn_dst_arm :: Em +--+-- Control the /arm/ length of a jointed connector - arms are the +-- initial segments of the connector. +--+-- > conn_loop_size :: Em+--+-- Control the /height/ of a loop connector. +--+-- > conn_box_halfsize :: Em+-- +-- Control the size of a connector box. Connector boxes are +-- drawn with the exterior lines projected out from the connector+-- points a halfsize above and below.+-- +data ConnectorProps = ConnectorProps+ { dc_conn_src_space :: !Em+ , dc_conn_dst_space :: !Em+ , dc_conn_src_offset :: !Em+ , dc_conn_dst_offset :: !Em+ , dc_conn_arc_ang :: !Radian+ , dc_conn_src_arm :: !Em+ , dc_conn_dst_arm :: !Em+ , dc_conn_loop_size :: !Em+ , dc_conn_box_halfsize :: !Em+ } +++-- | 'standardContext' : @ font_size -> DrawingContext @ +--+-- Create a 'DrawingContext'.+-- +-- Note - @font_size@ is used for sizing more than just text +-- labels. Arrowheads, plot marks and other elements have their+-- metrics derived from the font size.+-- +-- No real font metrics are present in the 'DrawingContext' +-- created by 'standardContext'. Static, hard-coded fallback +-- metrics derived from the @Courier@ font are available but+-- these metrics might not accurately correspond to the +-- @Courier@ available to the the final renderer (GhostScript,+-- an SVG viewer, etc.).+-- +-- Use this constructor for drawings that make primitive use of+-- text.+-- +-- > font_metrics_table: empty+-- > font_load_log: empty+-- > fallback_metrics: monospace_metrics+-- > font_face: Courier+-- > font_size: @supplied_font_size@+-- > stroke_props: line_width 1, no dash_pattern, cap-butt, join-miter. +-- > stroke_colour: black+-- > fill_colour: light_gray+-- > text_colour: black+-- > line_spacing_factor: 0.2+-- > round_corner_factor: 0+-- > text_margin: (0.5 em, 0.5 em) +--+-- > conn_src_sep: 0+-- > conn_dst_sep: 0+-- > conn_src_offset: 0+-- > conn_dst_offset: 0+-- > conn_arc_ang: pi / 12+-- > conn_src_arm: 1+-- > conn_dst_arm: 1+-- > conn_loop_size: 2 +-- +-- standardContext :: FontSize -> DrawingContext standardContext sz = - DrawingContext { glyph_tables = emptyGlyphMetrics- , fallback_metrics = monospace_metrics- , stroke_props = default_stroke_attr- , font_props = FontAttr sz wumpus_courier- , stroke_colour = wumpus_black- , fill_colour = wumpus_light_gray- , line_spacing_factor = 1.2 - , round_corner_factor = 0- , text_margin = standardTextMargin+ DrawingContext { dc_font_metrics_table = emptyFontTable+ , dc_font_load_log = mempty+ , dc_fallback_metrics = monospace_metrics+ , dc_font_face = wumpus_courier+ , dc_font_size = sz+ , dc_stroke_props = default_stroke_attr+ , dc_snap_grid_factors = (50.0, 50.0)+ , dc_stroke_colour = wumpus_black+ , dc_fill_colour = wumpus_light_gray+ , dc_text_colour = wumpus_black+ , dc_line_spacing_factor = default_line_spacing + , dc_text_margin = default_text_margin+ , dc_connector_props = default_connector_props } -standardTextMargin :: TextMargin-standardTextMargin = TextMargin { text_margin_x = 2.0, text_margin_y = 2.0 } --- out-of-date - should be adding loaded fonts, not replacing the --- GlyphMetrics Map wholesale.+-- | 'metricsContext' : @ font_size * font_metrics -> DrawingContext @ ---metricsContext :: FontSize -> GlyphMetrics -> DrawingContext-metricsContext sz bgm = - let env = standardContext sz in env { glyph_tables = bgm }+-- Create a 'DrawingContext' with font metrics loaded from the +-- file system.+-- +-- Note - @font_size@ is used for sizing more than just text +-- labels. Arrowheads, plot marks and other elements have their+-- metrics derived from the font size.+-- +-- Use this constructor for drawings that make use of the text +-- objects provided by @Wumpus-Drawing@ (DocText and RotText).+-- +metricsContext :: FontSize -> FontLoadResult -> DrawingContext+metricsContext sz res = + let env = standardContext sz + in env { dc_font_metrics_table = loaded_font_table res+ , dc_font_load_log = loader_errors res+ } ++-- | 'addFontTables' : @ font_load_result -> DrawinContextUpdate @+--+-- Add the font metrics from the FontLoadResult, if a font with +-- the same name alreay exists in the 'DrawingContext' it will be +-- replaced. Error and warning messages in the @font_load_result@ +-- will be appended to the 'font_load_log'.+--+addFontTables :: FontLoadResult -> DrawingContextF+addFontTables (FontLoadResult table msgs) = + (\s i j -> s { dc_font_metrics_table = i `mappend` table+ , dc_font_load_log = j `mappend` msgs }) + <*> dc_font_metrics_table <*> dc_font_load_log++++-- | 'reset_drawing_properties' : @ DrawingContextF @ +--+-- Reset the drawing properties in the 'DrawingContext' to their +-- default values. This changes the following fields:+--+-- > stroke_props: line_width 1, no dash_pattern, cap-butt, join-miter. +-- > stroke_colour: black+-- > fill_colour: light_gray+-- > text_colour: black+-- > line_spacing_factor: 0.2+-- > round_corner_factor: 0+-- > text_margin: (0.5 em, 0.5 em) +--+reset_drawing_properties :: DrawingContextF +reset_drawing_properties dcxt = + dcxt { dc_stroke_props = default_stroke_attr+ , dc_stroke_colour = wumpus_black+ , dc_fill_colour = wumpus_light_gray+ , dc_text_colour = wumpus_black+ , dc_line_spacing_factor = default_line_spacing+ , dc_text_margin = default_text_margin+ , dc_connector_props = default_connector_props+ }++-- Ideally @reset_drawing_properties@ would be in the UpdateDC +-- module, but that would mean exporting @default_line_spacing@ +-- etc.+--++++-- | 'reset_drawing_metrics' : @ DrawingContextF @ +--+-- Reset the drawing metrics in the 'DrawingContext' to their +-- default values. This is a more limited version of+-- 'reset_drawing_properties' and changes the following fields:+--+-- > stroke_props: line_width 1, no dash_pattern, cap-butt, join-miter. +-- > line_spacing_factor: 0.2+-- > round_corner_factor: 0+-- > text_margin: (0.5 em, 0.5 em) +--+reset_drawing_metrics :: DrawingContextF +reset_drawing_metrics dcxt = + dcxt { dc_stroke_props = default_stroke_attr+ , dc_line_spacing_factor = default_line_spacing+ , dc_text_margin = default_text_margin+ }++++-- Helpers - not exported++default_text_margin :: TextMargin+default_text_margin = TextMargin { text_margin_x = 0.5, text_margin_y = 0.5 }+++-- Arc angle is 15deg - quite shallow.+--+default_connector_props :: ConnectorProps+default_connector_props = + ConnectorProps { dc_conn_src_space = 0+ , dc_conn_dst_space = 0+ , dc_conn_src_offset = 0+ , dc_conn_dst_offset = 0+ , dc_conn_arc_ang = pi / 12+ , dc_conn_src_arm = 1+ , dc_conn_dst_arm = 1+ , dc_conn_loop_size = 2 + , dc_conn_box_halfsize = 2 + }+++default_line_spacing :: Double+default_line_spacing = 0.2+ wumpus_black :: RGBi wumpus_black = RGBi 0 0 0 @@ -144,26 +347,27 @@ FontFace "Courier" "Courier New" SVG_REGULAR standard_encoding --default_drawing_context :: DrawingContext-default_drawing_context = - standardContext (font_size wumpus_default_font)--- -------------------------------------------------------------------------------- --class (Applicative m, Monad m) => DrawingCtxM (m :: * -> *) where- askDC :: m DrawingContext- localize :: (DrawingContext -> DrawingContext) -> m a -> m a----- | Project a value out of a context.+-- | 'DrawingCtxM' is equivalent to the to the @MonadReader@ +-- class, but the environment type is fixed to 'DrawingContext'. ---asksDC :: DrawingCtxM m => (DrawingContext -> a) -> m a-asksDC f = askDC >>= (return . f)+-- To avoid name clashes with @mtl@ this scheme is used:+--+-- > askDC = ask+-- > asksDC = asks+-- > localize = local+--+-- Note, because the derived operation 'query' (aka @asks@) is+-- expected to be used more often than queryCtx (aka @ask@) it +-- gets the more convenient name.+--+class (Applicative m, Monad m) => DrawingCtxM (m :: * -> *) where+ askDC :: m DrawingContext+ asksDC :: (DrawingContext -> a) -> m a+ localize :: (DrawingContext -> DrawingContext) -> m a -> m a + asksDC f = f <$> askDC --------------------------------------------------------------------------------@@ -173,13 +377,15 @@ -withFontMetrics :: (MetricsOps -> PtSize -> u) -> DrawingContext -> u-withFontMetrics fn ctx@(DrawingContext { font_props = font_stats }) = - fn metric_set point_sz+withFontMetrics :: (FontMetrics -> FontSize -> u) -> DrawingContext -> u+withFontMetrics fn ctx@(DrawingContext { dc_font_face = fface+ , dc_font_size = ftsize }) = + fn metric_set ftsize where - ps_name = ps_font_name $ font_face font_stats- point_sz = fromIntegral $ font_size font_stats - metric_set = fromMaybe (fallback_metrics ctx) $ - lookupFont ps_name (glyph_tables ctx) + ps_name = ps_font_name fface+ metric_set = fromMaybe (dc_fallback_metrics ctx) $ + lookupFont ps_name (dc_font_metrics_table ctx)++
+ src/Wumpus/Basic/Kernel/Base/FontSupport.hs view
@@ -0,0 +1,256 @@+{-# LANGUAGE RankNTypes #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.Kernel.Base.FontSupport+-- Copyright : (c) Stephen Tetley 2010-2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Data types representing font metrics.+-- +--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Base.FontSupport+ ( ++ FontName+ , CodePoint+ , FontDef(..)+ , FontFamily(..)+ , regularWeight+ , boldWeight+ , italicWeight+ , boldItalicWeight++ , CharWidthLookup++ , FontMetrics(..)++ , FontTable+ , emptyFontTable+ , lookupFont+ , insertFont++ , FontLoadMsg+ , FontLoadLog+ , fontLoadMsg++ , FontLoadResult(..)+ , printLoadErrors++ , monospace_metrics++ + ) where++import Wumpus.Basic.Utils.HList++import Wumpus.Core -- package: wumpus-core++import qualified Data.Map as Map+import Data.Monoid++++type FontName = String++-- | A Unicode code-point.+--+type CodePoint = Int++-- | FontDef wraps @FontFace@ from Wumpus-Core with file name+-- information for the font loaders.+--+data FontDef = FontDef+ { font_def_face :: FontFace+ , gs_file_name :: String+ , afm_file_name :: String+ }+ deriving (Eq,Ord,Show)++++-- | A family group of FontDefs (regular, bold, italic and +-- bold-italic).+--+-- It is convenient for some higher-level text objects in Wumpus +-- (particularly @Doc@ in Wumpus-Drawing) to treat a font and its+-- standard weights as the same entity. This allows @Doc@ API to +-- provide a @bold@ operation to simply change to the the bold+-- weight of the current family, rather than use the primitive +-- @set_font@ operation to change to an explicitly named font.+--+--+data FontFamily = FontFamily+ { ff_regular :: FontDef+ , ff_bold :: Maybe FontDef+ , ff_italic :: Maybe FontDef+ , ff_bold_italic :: Maybe FontDef + }++-- | Extract the regular weight 'FontDef' from a 'FontFamily'.+--+regularWeight :: FontFamily -> FontDef+regularWeight = ff_regular+++-- | Extract the bold weight 'FontDef' from a 'FontFamily'.+--+-- Note - this falls back to the regular weight if the font family +-- has no bold weight. To get the bold weight or @Nothing@ if it+-- is not present use the record selector @ff_bold@.+--+boldWeight :: FontFamily -> FontDef+boldWeight s = maybe (ff_regular s) id $ ff_bold s+++-- | Extract the @italic@ weight 'FontDef' from a 'FontFamily'.+--+-- Note - this falls back to the regular weight if the font family +-- has no italic weight. To get the italic weight or @Nothing@ if +-- it is not present use the record selector @ff_italic@.+--+italicWeight :: FontFamily -> FontDef+italicWeight s = maybe (ff_regular s) id $ ff_italic s+++-- | Extract the @bold-italic@ weight 'FontDef' from a +-- 'FontFamily'.+--+-- Note - this falls back to the regular weight if the font family +-- has no bold-italic weight. To get the bold-italic weight or +-- @Nothing@ if it is not present use the record selector +-- @ff_bold_italic@.+--+boldItalicWeight :: FontFamily -> FontDef+boldItalicWeight s = maybe (ff_regular s) id $ ff_bold_italic s++++-- | A lookup function from code point to /width vector/.+--+-- The unit is always stored as a Double representing PostScript+-- points.+--+-- Note - in PostScript terminology a width vector is not obliged+-- to be left-to-right (writing direction 0). It could be +-- top-to-bottom (writing direction 1).+--+type CharWidthLookup = CodePoint -> Vec2 Double++++-- | 'FontMetrics' store a subset of the properties available in +-- a font file - enough to calculate accurate bounding boxes and+-- positions for text.+--+-- > Bounding box representing the maximum glyph area.+-- > Width vectors for each character.+-- > Cap height+-- > Descender depth.+--+-- Because Wumpus always needs font metrics respective to the +-- current point size, the actual fields are all functions.+--+data FontMetrics = FontMetrics+ { get_bounding_box :: FontSize -> BoundingBox Double+ , get_cw_table :: FontSize -> CharWidthLookup+ , get_cap_height :: FontSize -> Double+ , get_descender :: FontSize -> Double+ }+++-- | A map between a font name and the respective FontMetrics.+--+newtype FontTable = FontTable { + getFontTable :: Map.Map FontName FontMetrics }++++instance Monoid FontTable where+ mempty = emptyFontTable+ a `mappend` b = FontTable $ getFontTable a `mappend` getFontTable b+++emptyFontTable :: FontTable+emptyFontTable = FontTable $ Map.empty+++-- | 'FontLoadMsg' - type synonym for String.+--+type FontLoadMsg = String++-- | 'FontLoadLog' is a Hughes list of Strings, so it supports +-- efficient append.+--+newtype FontLoadLog = FontLoadLog { getFontLoadLog :: H FontLoadMsg }+++instance Monoid FontLoadLog where+ mempty = FontLoadLog $ emptyH+ a `mappend` b = FontLoadLog $ getFontLoadLog a `appendH` getFontLoadLog b+++fontLoadMsg :: String -> FontLoadLog +fontLoadMsg = FontLoadLog . wrapH+++-- Need a synonym for @FontLoading@...+data FontLoadResult = FontLoadResult+ { loaded_font_table :: FontTable+ , loader_errors :: FontLoadLog+ }+++-- | Print the loader errors from the 'FontLoadResult' to std-out.+--+printLoadErrors :: FontLoadResult -> IO ()+printLoadErrors = mapM_ putStrLn . toListH . getFontLoadLog . loader_errors++--------------------------------------------------------------------------------+++-- | 'lookupFont' : @ name * font_table -> Maybe FontMetrics @ +-- +-- Lookup a font in the font_table.+-- +lookupFont :: FontName -> FontTable -> Maybe FontMetrics+lookupFont name = Map.lookup name . getFontTable++-- | 'insertFont' : @ name * font_metrics * font_table -> FontTable @ +-- +-- Insert a named font into the font_table.+-- +insertFont :: FontName -> FontMetrics -> FontTable -> FontTable+insertFont name ops = + FontTable . Map.insert name ops . getFontTable++-- | This ignores the Char code lookup and just returns the +-- default advance vector.+--+monospace_metrics :: FontMetrics+monospace_metrics = FontMetrics+ { get_bounding_box = \sz -> BBox (lowerLeft sz) (upperRight sz)+ , get_cw_table = \sz _ -> hvec (upscale sz width_vec) + , get_cap_height = \sz -> upscale sz cap_height+ , get_descender = \sz -> upscale sz descender+ }+ where+ llx = (-23) / 1000+ lly = (-250) / 1000+ urx = 715 / 1000+ ury = 805 / 1000+ width_vec = 600 / 1000+ cap_height = 562 / 1000+ descender = (-157) / 1000++ upscale sz d = d * fromIntegral sz+ lowerLeft sz = P2 (upscale sz llx) (upscale sz lly) + upperRight sz = P2 (upscale sz urx) (upscale sz ury) ++
− src/Wumpus/Basic/Kernel/Base/GlyphMetrics.hs
@@ -1,120 +0,0 @@-{-# LANGUAGE RankNTypes #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.Kernel.Base.GlyphMetrics--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Data types representing glyph metrics loaded from font files.--- -----------------------------------------------------------------------------------module Wumpus.Basic.Kernel.Base.GlyphMetrics- ( -- FontName- , CodePoint- , CharWidthTable- , MetricsOps(..)- , FontMetricsOps(..)-- , GlyphMetrics- , emptyGlyphMetrics- , lookupFont- , insertFont-- , monospace_metrics-- - ) where--import Wumpus.Core -- package: wumpus-core--import qualified Data.Map as Map-import Data.Monoid----type FontName = String---- | A Unicode code-point.----type CodePoint = Int---- | A lookup from code point to /width vector/.------ Note - in PostScript terminology a width vector is not obliged--- to be left-to-right (writing direction 0). It could be --- top-to-bottom (writing direction 1).----type CharWidthTable u = CodePoint -> Vec2 u------ | Operations on the metrics set of a font.------ The is the internal representation used by Wumpus-Basic after--- parsing the font file.----data MetricsOps = MetricsOps- { get_bounding_box :: forall u. FromPtSize u => PtSize -> BoundingBox u - , get_cw_table :: forall u. FromPtSize u => PtSize -> CharWidthTable u- , get_cap_height :: forall u. FromPtSize u => PtSize -> u- , get_descender :: forall u. FromPtSize u => PtSize -> u- }---- | 'MetricsOps' for a particular named font.--- -data FontMetricsOps = FontMetricsOps FontName MetricsOps----- | A map between a font name and MetricsOps.----newtype GlyphMetrics = GlyphMetrics { - getGlyphMetrics :: Map.Map FontName MetricsOps }--instance Monoid GlyphMetrics where- mempty = emptyGlyphMetrics- a `mappend` b = GlyphMetrics $ getGlyphMetrics a `mappend` getGlyphMetrics b---emptyGlyphMetrics :: GlyphMetrics-emptyGlyphMetrics = GlyphMetrics $ Map.empty--lookupFont :: FontName -> GlyphMetrics -> Maybe MetricsOps-lookupFont name = Map.lookup name . getGlyphMetrics--insertFont :: FontMetricsOps -> GlyphMetrics -> GlyphMetrics-insertFont (FontMetricsOps name ops) = - GlyphMetrics . Map.insert name ops . getGlyphMetrics---- | This ignores the Char code lookup and just returns the --- default advance vector.----monospace_metrics :: MetricsOps-monospace_metrics = MetricsOps- { get_bounding_box = \sz -> BBox (lowerLeft sz) (upperRight sz)- , get_cw_table = \sz _ -> hvec (upscale sz width_vec) - , get_cap_height = \sz -> upscale sz cap_height- , get_descender = \sz -> upscale sz descender- }- where- llx = (-23) / 1000- lly = (-250) / 1000- urx = 715 / 1000- ury = 805 / 1000- width_vec = 600 / 1000- cap_height = 562 / 1000- descender = (-157) / 1000-- upscale sz d = fromPtSize $ sz * d- lowerLeft sz = P2 (upscale sz llx) (upscale sz lly) - upperRight sz = P2 (upscale sz urx) (upscale sz ury) --
src/Wumpus/Basic/Kernel/Base/QueryDC.hs view
@@ -21,55 +21,61 @@ module Wumpus.Basic.Kernel.Base.QueryDC ( - - textAttr- , withTextAttr+ normalizeCtx+ , normalizeCtxF+ , dinterpCtx+ , dinterpCtxF - , strokeAttr- , withStrokeAttr+ , uconvertCtx1+ , uconvertCtxF - , fillAttr- , withFillAttr+ , pointSize + , strokeAttr+ , fillAttr , borderedAttr- , withBorderedAttr+ , textAttr - , getRoundCornerSize- , getTextMargin+ , position+ , snapmove + , textMargin+ , getLineWidth , getFontAttr , getFontSize , getFontFace+ , getTextColour+ , markHeight , markHalfHeight- , baselineSpacing+ , textlineSpace -- * Glyph metrics , glyphBoundingBox- , glyphCapHeight- , glyphDescender- , glyphVerticalSpan+ , capHeight+ , descender+ , verticalSpan+ , cwLookupTable - -- * Default monospace metrics - , monoFontPointSize- , monoCharWidth- , monoTextWidth- , monoTextLength- , monoCapHeight- , monoLowerxHeight- , monoDescenderDepth- , monoAscenderHeight- , monoTextDimensions- , monoMultiLineHeight- , monoDefaultPadding- , monoVecToCenter + -- * Connector props+ , connectorSrcSpace+ , connectorDstSpace+ , connectorSrcOffset+ , connectorDstOffset+ , connectorArcAngle+ , connectorSrcArm+ , connectorDstArm+ , connectorLoopSize+ , connectorBoxHalfSize+ ) where +import Wumpus.Basic.Kernel.Base.BaseDefs import Wumpus.Basic.Kernel.Base.DrawingContext-import Wumpus.Basic.Kernel.Base.GlyphMetrics+import Wumpus.Basic.Kernel.Base.FontSupport import Wumpus.Core -- package: wumpus-core import qualified Wumpus.Core.FontSize as FS@@ -77,225 +83,231 @@ import Control.Applicative -textAttr :: DrawingCtxM m => m (RGBi,FontAttr)-textAttr = (,) <$> asksDC stroke_colour <*> asksDC font_props --- | Because @textAttr@ is so commonly used here is a functional--- version that avoids tupling.----withTextAttr :: DrawingCtxM m => (RGBi -> FontAttr -> a) -> m a-withTextAttr fn = fn <$> asksDC stroke_colour <*> asksDC font_props +normalizeCtx :: (DrawingCtxM m, InterpretUnit u) => u -> m Double+normalizeCtx u = (\sz -> normalize sz u) <$> pointSize -strokeAttr :: DrawingCtxM m => m (RGBi, StrokeAttr)-strokeAttr = (,) <$> asksDC stroke_colour <*> asksDC stroke_props+normalizeCtxF :: (DrawingCtxM m, Functor t, InterpretUnit u) + => t u -> m (t Double)+normalizeCtxF t = (\sz -> fmap (normalize sz) t) <$> pointSize -withStrokeAttr :: DrawingCtxM m => (RGBi -> StrokeAttr -> a) -> m a-withStrokeAttr fn = fn <$> asksDC stroke_colour <*> asksDC stroke_props+dinterpCtx :: (DrawingCtxM m, InterpretUnit u) => Double -> m u+dinterpCtx u = (\sz -> dinterp sz u) <$> pointSize +dinterpCtxF :: (DrawingCtxM m, Functor t, InterpretUnit u) => t Double -> m (t u)+dinterpCtxF u = (\sz -> fmap (dinterp sz) u) <$> pointSize +uconvertCtx1 :: (DrawingCtxM m, InterpretUnit u, InterpretUnit u1) + => u -> m u1+uconvertCtx1 t = (\sz -> uconvert1 sz t) <$> pointSize++uconvertCtxF :: (DrawingCtxM m, Functor t, InterpretUnit u, InterpretUnit u1) + => t u -> m (t u1)+uconvertCtxF t = (\sz -> uconvertF sz t) <$> pointSize+++pointSize :: DrawingCtxM m => m FontSize+pointSize = asksDC dc_font_size++strokeAttr :: DrawingCtxM m => m (RGBi, StrokeAttr)+strokeAttr = (,) <$> asksDC dc_stroke_colour <*> asksDC dc_stroke_props+ fillAttr :: DrawingCtxM m => m RGBi-fillAttr = asksDC fill_colour+fillAttr = asksDC dc_fill_colour -withFillAttr :: DrawingCtxM m => (RGBi -> a) -> m a-withFillAttr fn = fn <$> asksDC fill_colour borderedAttr :: DrawingCtxM m => m (RGBi, StrokeAttr, RGBi)-borderedAttr = (,,) <$> asksDC fill_colour <*> asksDC stroke_props - <*> asksDC stroke_colour+borderedAttr = (,,) <$> asksDC dc_fill_colour + <*> asksDC dc_stroke_props + <*> asksDC dc_stroke_colour -withBorderedAttr :: DrawingCtxM m => (RGBi -> StrokeAttr -> RGBi -> a) -> m a-withBorderedAttr fn = - fn <$> asksDC fill_colour <*> asksDC stroke_props - <*> asksDC stroke_colour +textAttr :: DrawingCtxM m => m (RGBi,FontAttr)+textAttr = + (\a b c -> (a, FontAttr b c)) + <$> asksDC dc_text_colour <*> asksDC dc_font_size <*> asksDC dc_font_face --- | Size of the round corner factor.++++-- | Get the Point corresponding the grid coordinates scaled by+-- the snap-grid scaling factors. ---getRoundCornerSize :: (DrawingCtxM m, Fractional u, FromPtSize u) => m u-getRoundCornerSize = (\factor -> (realToFrac factor) * fromPtSize 1)- <$> asksDC round_corner_factor+position :: (DrawingCtxM m, Fractional u) => (Int, Int) -> m (Point2 u)+position (x,y) = post <$> asksDC dc_snap_grid_factors+ where+ post (sx,sy) = P2 (realToFrac $ sx * fromIntegral x) + (realToFrac $ sy * fromIntegral y) ++-- | Scale a vector coordinate by the snap-grid scaling factors.+--+-- Absolute units.+--+snapmove :: (DrawingCtxM m, Fractional u) => (Int,Int) -> m (Vec2 u)+snapmove (x,y) = post <$> asksDC dc_snap_grid_factors+ where+ post (sx,sy) = V2 (realToFrac $ sx * fromIntegral x) + (realToFrac $ sy * fromIntegral y)+++ -- | Get the (x,y) margin around text. -- -- Note - not all text operations in Wumpus are drawn with text -- margin. -- -getTextMargin :: (DrawingCtxM m, Fractional u, FromPtSize u) => m (u,u)-getTextMargin = (\(TextMargin xsep ysep) -> (fn xsep, fn ysep))- <$> asksDC text_margin+textMargin :: (DrawingCtxM m, InterpretUnit u) => m (u,u)+textMargin = post <$> asksDC dc_font_size <*> asksDC dc_text_margin where- fn d = (realToFrac d) * fromPtSize 1+ post sz (TextMargin xem yem) = (uconvert1 sz xem, uconvert1 sz yem) ++ getLineWidth :: DrawingCtxM m => m Double-getLineWidth = line_width <$> asksDC stroke_props+getLineWidth = line_width <$> asksDC dc_stroke_props getFontAttr :: DrawingCtxM m => m FontAttr-getFontAttr = asksDC font_props+getFontAttr = FontAttr <$> asksDC dc_font_size <*> asksDC dc_font_face -getFontSize :: DrawingCtxM m => m Int-getFontSize = font_size <$> asksDC font_props -getFontFace :: DrawingCtxM m => m FontFace-getFontFace = font_face <$> asksDC font_props+getFontSize :: DrawingCtxM m => m Int+getFontSize = asksDC dc_font_size +getFontFace :: DrawingCtxM m => m FontFace+getFontFace = asksDC dc_font_face +getTextColour :: DrawingCtxM m => m RGBi+getTextColour = asksDC dc_text_colour --- | Vertical distance between baselines of consecutive text --- lines.----baselineSpacing :: (DrawingCtxM m, Fractional u) => m u-baselineSpacing = - (\sz factor -> realToFrac $ factor * fromIntegral sz)- <$> asksDC (font_size . font_props) <*> asksDC line_spacing_factor- -- | The /mark/ height is the height of a lowercase letter in the --- current font.+-- Courier font at the current point size. -- -- Arrowheads, dots etc. should generally be drawn at the mark -- height. -- -markHeight :: (DrawingCtxM m, FromPtSize u) => m u-markHeight = (fromPtSize . FS.xcharHeight . font_size) <$> asksDC font_props+markHeight :: (DrawingCtxM m, InterpretUnit u) => m u+markHeight = post <$> asksDC dc_font_size + where+ post sz = dinterp sz (FS.xcharHeight sz) -markHalfHeight :: (DrawingCtxM m, Fractional u, FromPtSize u) => m u++markHalfHeight :: (Fractional u, DrawingCtxM m, InterpretUnit u) => m u markHalfHeight = (0.5*) <$> markHeight --- Note - there are probably enough functions that use just --- markHeight to merit a withMarkHeight function. +-- | Vertical distance between descender of a line and the +-- cap-height of the line below. +-- +textlineSpace :: (DrawingCtxM m, Fractional u, InterpretUnit u) => m u+textlineSpace = + post <$> asksDC dc_font_size <*> asksDC dc_line_spacing_factor+ where+ post sz factor = dinterp sz ((fromIntegral sz) * (realToFrac factor)) -------------------------------------------------------------------------------- -glyphQuery :: DrawingCtxM m => (MetricsOps -> PtSize -> u) -> m u++glyphQuery :: DrawingCtxM m => (FontMetrics -> FontSize -> a) -> m a glyphQuery fn = (\ctx -> withFontMetrics fn ctx) <$> askDC ++ -- | Get the font bounding box - this is the maximum boundary of -- the glyphs in the font. The span of the height is expected to -- be bigger than the cap_height plus descender depth. ---glyphBoundingBox :: (FromPtSize u, DrawingCtxM m) => m (BoundingBox u)-glyphBoundingBox = glyphQuery get_bounding_box+glyphBoundingBox :: (DrawingCtxM m, InterpretUnit u) => m (BoundingBox u)+glyphBoundingBox = + uconvertF <$> asksDC dc_font_size <*> glyphQuery get_bounding_box +-- | Height of a capital letter.+--+capHeight :: (DrawingCtxM m, InterpretUnit u) => m u+capHeight = dinterp <$> asksDC dc_font_size <*> glyphQuery get_cap_height -glyphCapHeight :: (FromPtSize u, DrawingCtxM m) => m u-glyphCapHeight = glyphQuery get_cap_height- -- | Note - descender is expected to be negative. ---glyphDescender :: (FromPtSize u, DrawingCtxM m) => m u-glyphDescender = glyphQuery get_descender+descender :: (DrawingCtxM m, InterpretUnit u) => m u+descender = dinterp <$> asksDC dc_font_size <*> glyphQuery get_descender + -- | This is the distance from cap_height to descender. ---glyphVerticalSpan :: (FromPtSize u, DrawingCtxM m) => m u-glyphVerticalSpan = - (\ch dd -> ch - dd) <$> glyphCapHeight <*> glyphDescender+verticalSpan :: (DrawingCtxM m, InterpretUnit u) => m u+verticalSpan = + (\ch dd -> ch - dd) <$> capHeight <*> descender -cwLookupTable :: (FromPtSize u, DrawingCtxM m) => m (CharWidthTable u)-cwLookupTable = glyphQuery get_cw_table +-- | Note the CharWidthLookup is not parameteric on units.+--+-- /CharWidth/ is always Double representing PostScript points.+-- Client code must convert this value accordingly.+--+cwLookupTable :: DrawingCtxM m => m CharWidthLookup+cwLookupTable = glyphQuery get_cw_table --------------------------------------------------------------------------------+-- Connector props -withFontSize :: DrawingCtxM m => (FontSize -> u) -> m u-withFontSize fn = (fn . font_size) <$> asksDC font_props+-- helper +connectorAsks :: DrawingCtxM m => (ConnectorProps -> a) -> m a+connectorAsks f = f <$> asksDC dc_connector_props --- NOTE - textHeight in Wumpus-Core should be renamed as it is--- (probably) more indiactive of Cap height than /font point size/--- -monoFontPointSize :: (DrawingCtxM m, FromPtSize u) => m u-monoFontPointSize = withFontSize (fromPtSize . fromIntegral)+connectorSrcSpace :: (DrawingCtxM m, InterpretUnit u) => m u +connectorSrcSpace = (\sz u -> uconvert1 sz u) + <$> pointSize <*> connectorAsks dc_conn_src_space -monoCharWidth :: (DrawingCtxM m, FromPtSize u) => m u-monoCharWidth = withFontSize (fromPtSize . FS.charWidth) +connectorDstSpace :: (DrawingCtxM m, InterpretUnit u) => m u +connectorDstSpace = (\sz u -> uconvert1 sz u) + <$> pointSize <*> connectorAsks dc_conn_dst_space -monoTextWidth :: (DrawingCtxM m, FromPtSize u) => Int -> m u-monoTextWidth n = withFontSize $ \sz -> fromPtSize $ FS.textWidth sz n+connectorSrcOffset :: (DrawingCtxM m, InterpretUnit u) => m u +connectorSrcOffset = (\sz u -> uconvert1 sz u) + <$> pointSize <*> connectorAsks dc_conn_src_offset -monoTextLength :: (DrawingCtxM m, FromPtSize u) => String -> m u-monoTextLength ss = monoTextWidth $ charCount ss+connectorDstOffset :: (DrawingCtxM m, InterpretUnit u) => m u +connectorDstOffset = (\sz u -> uconvert1 sz u) + <$> pointSize <*> connectorAsks dc_conn_dst_offset -monoCapHeight :: (DrawingCtxM m, FromPtSize u) => m u-monoCapHeight = withFontSize (fromPtSize . FS.capHeight)--monoTotalCharHeight :: (DrawingCtxM m, FromPtSize u) => m u-monoTotalCharHeight = withFontSize (fromPtSize . FS.totalCharHeight)-+connectorArcAngle :: DrawingCtxM m => m Radian+connectorArcAngle = connectorAsks dc_conn_arc_ang --- | Height of a lower case \'x\' in Courier.--- --- \'x\' has no ascenders or descenders. --- -monoLowerxHeight :: (DrawingCtxM m, FromPtSize u) => m u-monoLowerxHeight = withFontSize (fromPtSize . FS.xcharHeight)--monoDescenderDepth :: (DrawingCtxM m, FromPtSize u) => m u-monoDescenderDepth = withFontSize (fromPtSize . FS.descenderDepth)--monoAscenderHeight :: (DrawingCtxM m, FromPtSize u) => m u-monoAscenderHeight = withFontSize (fromPtSize . FS.ascenderHeight)+connectorSrcArm :: (DrawingCtxM m, InterpretUnit u) => m u +connectorSrcArm = (\sz u -> uconvert1 sz u) + <$> pointSize <*> connectorAsks dc_conn_src_arm --- | Query the dimensions of the text using the current font size--- but using metrics derived from Courier.------ Note - the width will generally be a over-estimate for --- non-monospaced fonts.--- -monoTextDimensions :: (DrawingCtxM m, Num u, Ord u, FromPtSize u)- => String -> m (u,u)-monoTextDimensions ss = - (\sz -> post $ textBounds sz zeroPt ss) - <$> asksDC (font_size . font_props)- where- post bb = (boundaryWidth bb, boundaryHeight bb)+connectorDstArm :: (DrawingCtxM m, InterpretUnit u) => m u +connectorDstArm = (\sz u -> uconvert1 sz u) + <$> pointSize <*> connectorAsks dc_conn_dst_arm --- | The heigth of @n@ lines of text, which is --- @n lines + n-1 line spacers@----monoMultiLineHeight :: (DrawingCtxM m, Fractional u, FromPtSize u) - => Int -> m u-monoMultiLineHeight n | n < 0 = pure 0-monoMultiLineHeight n = - (\h lsf -> h + (fromIntegral $ n-1) * (h * realToFrac lsf))- <$> monoTotalCharHeight <*> asksDC line_spacing_factor- - -- Note as the height calculation has changed in Wumpus-Core this- -- no longer quite works... -- -{-# DEPRECATED monoDefaultPadding "Needs a rethink" #-}---- | The default padding is half of the /char width/.----monoDefaultPadding :: (DrawingCtxM m, Fractional u, FromPtSize u) => m u-monoDefaultPadding = (0.5*) <$> monoCharWidth-+connectorLoopSize :: (DrawingCtxM m, InterpretUnit u) => m u +connectorLoopSize = (\sz u -> uconvert1 sz u) + <$> pointSize <*> connectorAsks dc_conn_loop_size --- | Vector from baseline left to center----monoVecToCenter :: (DrawingCtxM m, Fractional u, Ord u, FromPtSize u) - => String -> m (Vec2 u)-monoVecToCenter ss = (\(w,h) dy -> vec (0.5*w) (0.5*h - dy)) - <$> monoTextDimensions ss <*> monoDescenderDepth+connectorBoxHalfSize :: (DrawingCtxM m, InterpretUnit u) => m u +connectorBoxHalfSize = + (\sz u -> uconvert1 sz u) + <$> pointSize <*> connectorAsks dc_conn_box_halfsize
− src/Wumpus/Basic/Kernel/Base/ScalingContext.hs
@@ -1,104 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.Kernel.Base.ScalingContext--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : unstable--- Portability : GHC------ Scaling in X and Y------ \*\* WARNING \*\* - half baked.--- -----------------------------------------------------------------------------------module Wumpus.Basic.Kernel.Base.ScalingContext- (-- ScalingContext(..)-- , scaleX- , scaleY- , scalePt- , scaleVec-- , unitX- , unitY-- , uniformScaling- , coordinateScaling-- ) where---import Wumpus.Core -- package: wumpus-core------ | ScalingContext is a dictionary of two functions for scaling --- in X and Y.----data ScalingContext ux uy u = ScalingContext- { scale_in_x :: ux -> u- , scale_in_y :: uy -> u- }---scaleX :: ScalingContext ux uy u -> ux -> u-scaleX ctx ux = (scale_in_x ctx) ux--scaleY :: ScalingContext ux uy u -> uy -> u-scaleY ctx uy = (scale_in_y ctx) uy---scalePt :: ScalingContext ux uy u -> ux -> uy -> Point2 u-scalePt ctx ux uy = P2 (scale_in_x ctx ux) (scale_in_y ctx uy)--scaleVec :: ScalingContext ux uy u -> ux -> uy -> Vec2 u-scaleVec ctx ux uy = V2 (scale_in_x ctx ux) (scale_in_y ctx uy)---unitX :: Num ux => ScalingContext ux uy u -> u-unitX ctx = scaleX ctx 1- -unitY :: Num uy => ScalingContext ux uy u -> u-unitY ctx = scaleY ctx 1---------------------------------------------------------------------------------------- constructors for scaling context----- | Build a ScalingContext where both X and Y are scaled by the --- same uniform step.------ The dimensions (types) of the ScalingContext are unified - the --- output type and the input types are all the same.----uniformScaling :: Num u => u -> ScalingContext u u u-uniformScaling u = ScalingContext- { scale_in_x = (\x -> u*x)- , scale_in_y = (\y -> u*y)- }------ | Build a ScalingContext for scaling Int coordinates.------ The scaling factors in X and Y can be different sizes.-----coordinateScaling :: Num u => u -> u -> ScalingContext Int Int u-coordinateScaling sx sy = ScalingContext- { scale_in_x = (\x -> sx * fromIntegral x)- , scale_in_y = (\y -> sy * fromIntegral y)- }---
+ src/Wumpus/Basic/Kernel/Base/Units.hs view
@@ -0,0 +1,163 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.Kernel.Base.Units+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Units @cm@, @pica@ and \"contextual\" units - @em@, @en@.+-- +--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Base.Units+ (+++ -- * Centimeter+ Centimeter+ , cm+ , dcm++ -- * Pica+ , Pica+ , pica+ , dpica++ -- * Em+ , Em++ -- * En+ , En++ ) where+++import Wumpus.Basic.Kernel.Base.BaseDefs++import Wumpus.Core -- package: wumpus-core+++--------------------------------------------------------------------------------++-- | Wrapped Double representing Centimeter.+-- +newtype Centimeter = Centimeter { getCentimeter :: Double } + deriving (Eq,Ord,Num,Floating,Fractional,Real,RealFrac,RealFloat)+++instance Show Centimeter where+ showsPrec p d = showsPrec p (getCentimeter d)++-- | Cast a value in Centimeters to some Fractional type.+-- +-- Note - this casting should only be used for non-contextual+-- units such as Double.+--+cm :: Fractional u => Centimeter -> u +cm = realToFrac . (28.45275619 *) . getCentimeter++-- | Convert Double to Centimer.+-- +dcm :: Double -> Centimeter+dcm = Centimeter . (0.03514598 *)++instance ScalarUnit Centimeter where+ fromPsPoint = dcm+ toPsPoint = cm ++instance InterpretUnit Centimeter where+ normalize _ = cm + dinterp _ = dcm+++-- | Wrapped Double /Pica/ unit type.+-- +-- Pica is 12 Points.+--+newtype Pica = Pica { getPica :: Double } + deriving (Eq,Ord,Num,Floating,Fractional,Real,RealFrac,RealFloat)+++instance Show Pica where+ showsPrec p d = showsPrec p (getPica d)++ +-- | Cast a value in Pica to some Fractional type.+-- +-- Note - this casting should only be used for non-contextual+-- units such as Double.+--+pica :: Fractional u => Pica -> u +pica = realToFrac . (* 12.0) . getPica++-- | Convert a Double to a Pica.+--+dpica :: Double -> Pica+dpica = Pica . (\x -> x / 12.0)+++instance Tolerance Pica where + eq_tolerance = 0.001+ length_tolerance = 0.01+++instance ScalarUnit Pica where+ fromPsPoint = dpica+ toPsPoint = pica++instance InterpretUnit Pica where+ normalize _ = pica+ dinterp _ = dpica++++--------------------------------------------------------------------------------+-- Contextual units++-- | Wrapped Double representing an Em. +-- +newtype Em = Em { getEm :: Double } + deriving (Eq,Ord,Num,Floating,Fractional,Real,RealFrac,RealFloat)++instance Show Em where+ showsPrec p d = showsPrec p (getEm d)++++instance InterpretUnit Em where+ normalize sz a = fromIntegral sz * realToFrac a+ dinterp sz d = realToFrac d / fromIntegral sz++instance Tolerance Centimeter where + eq_tolerance = 0.001+ length_tolerance = 0.01+++-- | Wrapped Double representing an En.+-- +newtype En = En { getEn :: Double } + deriving (Eq,Ord,Num,Floating,Fractional,Real,RealFrac,RealFloat)++instance Show En where+ showsPrec p d = showsPrec p (getEn d)+++instance InterpretUnit En where+ normalize sz a = (realToFrac a) * 0.5 * fromIntegral sz+ dinterp sz d = 2 * (realToFrac d) / (fromIntegral sz)++++instance Tolerance Em where + eq_tolerance = 0.001+ length_tolerance = 0.01++instance Tolerance En where+ eq_tolerance = 0.001 + length_tolerance = 0.01
src/Wumpus/Basic/Kernel/Base/UpdateDC.hs view
@@ -3,263 +3,640 @@ -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Basic.Kernel.Base.UpdateDC--- Copyright : (c) Stephen Tetley 2010+-- Copyright : (c) Stephen Tetley 2010-2011 -- License : BSD3 -- -- Maintainer : Stephen Tetley <stephen.tetley@gmail.com> -- Stability : highly unstable -- Portability : GHC ----- Customize drawing attributes------ \*\* WARNING \*\* - this module needs systematic naming --- schemes both for update functions (primaryColour, ...) and --- for synthesized selectors (e.g. lowerxHeight). The current --- names will change.+-- Customize drawing attributes. The functions here are +-- @DrawingContext@ modifiers to be run within a the scope of a +-- @localize@ block (cf. @local@ of the Reader monad). --+-- By convention, underscore-separated names are used for +-- DrawingContext modifiers in this module. This is because the +-- modifiers defined here are expected to be used mostly as static +-- \"properties\" resembling constants in drawings. -- -------------------------------------------------------------------------------- module Wumpus.Basic.Kernel.Base.UpdateDC ( - -- * Modifiers - - roundCornerFactor- , textMargin+ -- * Modifiers + snap_grid_factors -- ** Line widths- , lineWidth- , thick- , ultrathick- , thin+ , set_line_width + , line_default+ , line_thin+ , line_thick+ , line_ultra_thick+ -- ** Line caps- , capButt- , capRound- , capSquare+ , cap_default+ , cap_butt+ , cap_round+ , cap_square -- ** Line joins- , joinMiter- , joinRound- , joinBevel+ , join_default+ , join_miter+ , join_round+ , join_bevel -- ** Dash Pattern- , dashPattern- , unit_dash_pattern- , phase- , dphase- , doublegaps- , doubledashes+ , set_dash_pattern + , solid_line+ , dotted_line+ , packed_dotted+ , loose_dotted+ + , dashed_line+ , packed_dashed+ , loose_dashed+ -- * Font properties- , fontAttr- , fontSize- , fontFace+ , font_attr+ , set_font+ , set_font_size + -- * Font / mark drawing size- , scalesize- , doublesize- , halfsize+ , scale_point_size + , double_point_size+ , half_point_size++ , text_margin+ , text_margin_none+ , text_margin_tight+ , text_margin_default+ , text_margin_loose++ -- * Colour- , swapColours- , bothStrokeColour- , bothFillColour- , strokeColour- , fillColour + , stroke_colour+ , fill_colour + , text_colour+ , single_colour + , swap_colours+ , fill_use_stroke_colour+ , stroke_use_fill_colour - + , fill_use_text_colour+ , stroke_use_text_colour++ , text_use_stroke_colour+ , text_use_fill_colour++ -- * Connector Props+ , source_space+ , dest_space+ , source_offset+ , dest_offset+ , uniform_conn_space+ , conn_arc_angle+ , source_arm_len+ , dest_arm_len+ , uniform_arm_len+ , conn_loop_size+ , conn_box_halfsize+ ) where +import Wumpus.Basic.Kernel.Base.BaseDefs import Wumpus.Basic.Kernel.Base.DrawingContext+import Wumpus.Basic.Kernel.Base.FontSupport+import Wumpus.Basic.Kernel.Base.Units import Wumpus.Core -- package: wumpus-core import Control.Applicative -import Data.Ratio --------------------------------------------------------------------------------+-- helpers updateStrokeProps :: (StrokeAttr -> StrokeAttr) -> DrawingContextF-updateStrokeProps fn = (\s i -> s { stroke_props = fn i }) <*> stroke_props--updateFontProps :: (FontAttr -> FontAttr) -> DrawingContextF-updateFontProps fn = (\s i -> s { font_props = fn i }) <*> font_props+updateStrokeProps fn = + (\s i -> s { dc_stroke_props = fn i }) <*> dc_stroke_props +withFontSize :: (FontSize -> DrawingContextF) -> DrawingContextF+withFontSize fn = (\s i -> fn i s) <*> dc_font_size -------------------------------------------------------------------------------- -roundCornerFactor :: Double -> DrawingContextF-roundCornerFactor d = (\s -> s { round_corner_factor = d }) --- | 'textMargin' : @ xsep * ysep -> DrawingContextF @++-- | 'snap_grid_factors' : @ x_unit * y_unit -> DrawingContextF @+-- +-- Set the @snap grid factors@ - a snap grid is an alternative +-- coordinate space, it can be convenient for drawing +-- \"box and arrow\" diagrams. ---textMargin :: Double -> Double -> DrawingContextF-textMargin xsep ysep = (\s -> s { text_margin = TextMargin xsep ysep })+snap_grid_factors :: Double -> Double -> DrawingContextF+snap_grid_factors xu yu = \s -> s { dc_snap_grid_factors = (xu, yu) } -------------------------------------------------------------------------------- -- line widths --- Note - some care might be needed if we ever define other unit --- types... -lineWidth :: Double -> DrawingContextF-lineWidth d = updateStrokeProps (\s -> s { line_width = d })+-- | set_line_width : @ width_in_points -> DrawingContextF @+--+-- Set the line_width to the supplied point size.+--+-- Initially the line width is 1.0.+--+-- /Constant/ variations of the function maybe be more +-- convenient:+--+-- > line_default, line_thin, line_thick, line_ultra_thick+--+set_line_width :: Double -> DrawingContextF+set_line_width d = updateStrokeProps (\s -> s { line_width = d }) --- std_line_width :: Double--- std_line_width = 1.0+-- | Set the line_width to @default@ - 1.0.+--+line_default :: DrawingContextF+line_default = set_line_width 1.0 -thick_line :: Double-thick_line = 2.0 -ultra_thick_line :: Double-ultra_thick_line = 4.0--thin_line :: Double-thin_line = 0.5+-- | Set the line_width to @thin@ - 0.5.+--+line_thin :: DrawingContextF+line_thin = set_line_width 0.5 --- | Set the line width to a /thick/.+-- | Set the line_width to @thick@ - 2.0. ----- Note this context update is /oblivious/ - operationally the --- line width is set to exactly @2.0@.+line_thick :: DrawingContextF+line_thick = set_line_width 2.0++-- | Set the line_width to @ultra_thick@ - 4.0. ---thick :: DrawingContextF-thick = lineWidth thick_line+line_ultra_thick :: DrawingContextF+line_ultra_thick = set_line_width 4.0 -ultrathick :: DrawingContextF-ultrathick = lineWidth ultra_thick_line -thin :: DrawingContextF-thin = lineWidth thin_line+--+-- All options share the prefix so the enumeration is obvious...+-- --------------------------------------------------------------------------------+-- Line props setLineCap :: LineCap -> DrawingContextF setLineCap d = updateStrokeProps (\s -> s { line_cap = d }) +setLineJoin :: LineJoin -> DrawingContextF+setLineJoin d = updateStrokeProps (\s -> s { line_join = d }) -capButt :: DrawingContextF-capButt = setLineCap CapButt -capRound :: DrawingContextF-capRound = setLineCap CapRound+-- | Set the line_cap to the default which is @butt@.+--+-- This is a synonym for 'cap_butt'.+--+cap_default :: DrawingContextF+cap_default = cap_butt -capSquare :: DrawingContextF-capSquare = setLineCap CapSquare+-- | Set the line_cap to @butt@.+--+-- Butt squares of the stroke at the end point.+--+-- This is the default.+--+cap_butt :: DrawingContextF+cap_butt = setLineCap CapButt +-- | Set the line_cap to @round@.+--+-- This rounds the end of the stroke and the visually the +-- rounding slightly extends the length of the line.+--+cap_round :: DrawingContextF+cap_round = setLineCap CapRound -setLineJoin :: LineJoin -> DrawingContextF-setLineJoin d = updateStrokeProps (\s -> s { line_join = d }) +-- | Set the line_cap to @square@.+--+-- This squares off the end of the stroke, visually extending +-- the stroke by half the line width.+--+cap_square :: DrawingContextF+cap_square = setLineCap CapSquare -joinMiter :: DrawingContextF-joinMiter = setLineJoin JoinMiter -joinRound :: DrawingContextF-joinRound = setLineJoin JoinRound -joinBevel :: DrawingContextF-joinBevel = setLineJoin JoinBevel+-- | Set the line_join to the default which is @miter@.+--+-- This is a synonym for 'join_miter'.+--+join_default :: DrawingContextF+join_default = join_miter +-- | Set the line_join to @miter@.+--+-- This extends the joining line segments to form a sharp miter.+--+-- This is the default.+--+join_miter :: DrawingContextF+join_miter = setLineJoin JoinMiter+++-- | Set the line_join to @round@.+--+-- This rounds off the corner of the joined line segments.+--+join_round :: DrawingContextF+join_round = setLineJoin JoinRound+++-- | Set the line_join to @round@.+--+-- This bevels off the corner of the joined line segments with a +-- notch.+--+join_bevel :: DrawingContextF+join_bevel = setLineJoin JoinBevel++ -------------------------------------------------------------------------------- -dashPattern :: DashPattern -> DrawingContextF-dashPattern d = updateStrokeProps (\s -> s { dash_pattern = d }) + +-- | Set the dash pattern.+--+-- Initially the dash pattern is 'Solid'.+--+set_dash_pattern :: DashPattern -> DrawingContextF+set_dash_pattern d = updateStrokeProps (\s -> s { dash_pattern = d }) -unit_dash_pattern :: DashPattern-unit_dash_pattern = Dash 0 [(1,1)] --- oblivious-phase :: Int -> DashPattern -> DashPattern-phase _ Solid = Solid-phase i (Dash _ xs) = Dash i xs+-- | Set the dash_pattern to @solid@ - i.e. no dash pattern.+--+-- This is the default.+--+solid_line :: DrawingContextF +solid_line = set_dash_pattern Solid --- non-oblivious-dphase :: Int -> DashPattern -> DashPattern-dphase _ Solid = Solid-dphase d (Dash i xs) = Dash (i+d) xs+-- | Set the dash pattern to draw a dotted line.+-- +-- A dot is actually a square - side length is equal to the line +-- width.+-- +-- The spacing between dots is 2 times the dot width.+--+dotted_line :: DrawingContextF +dotted_line = set_dash_pattern $ Dash 0 [(1,2)] -doublegaps :: DashPattern -> DashPattern-doublegaps Solid = Solid-doublegaps (Dash i xs) = Dash i (map fn xs)- where- fn (a,b) = (a,2*b)+-- | Set the dash pattern to draw a tightly packed dotted line.+-- +-- A dot is actually a square - side length is equal to the line +-- width.+-- +-- The spacing between dots is equal to the dot width.+--+packed_dotted :: DrawingContextF +packed_dotted = set_dash_pattern $ Dash 0 [(1,1)] -doubledashes :: DashPattern -> DashPattern-doubledashes Solid = Solid-doubledashes (Dash i xs) = Dash i (map fn xs)- where- fn (a,b) = (a*2,b) +-- | Set the dash pattern to draw a loosely dotted line.+-- +-- A dot is actually a square - side length is equal to the line +-- width.+-- +-- The spacing between dots is 4 times the dot width.+--+loose_dotted :: DrawingContextF +loose_dotted = set_dash_pattern $ Dash 0 [(1,4)] --------------------------------------------------------------------------------- -fontAttr :: FontFace -> Int -> DrawingContextF-fontAttr ff sz = (\s -> s { font_props = FontAttr sz ff }) -fontFace :: FontFace -> DrawingContextF-fontFace ff = updateFontProps (\(FontAttr sz _) -> FontAttr sz ff)+-- | Set the dash pattern to draw a dashed line.+-- +-- The dash length is 3 times the line width, the spacing is 2+-- times the line width.+--+dashed_line :: DrawingContextF+dashed_line = set_dash_pattern $ Dash 0 [(3,2)] -fontSize :: Int -> DrawingContextF-fontSize sz = updateFontProps (\(FontAttr _ ff) -> FontAttr sz ff) +-- | Set the dash pattern to draw a tightly packed, dashed line.+-- +-- The dash length is 3 times the line width, the spacing is +-- equal to the line width.+--+packed_dashed :: DrawingContextF+packed_dashed = set_dash_pattern $ Dash 0 [(3,1)] ++-- | Set the dash pattern to draw a loosely dashed line.+-- +-- The dash length is 3 times the line width, the spacing is 4+-- times the line width.+--+loose_dashed :: DrawingContextF+loose_dashed = set_dash_pattern $ Dash 0 [(3,4)]+++ -------------------------------------------------------------------------------- -scalesize :: Ratio Int -> DrawingContextF-scalesize r = let (n,d) = (numerator r, denominator r)- in (\s sz -> fontSize (n * sz `div` d) s) - <*> (font_size . font_props)+-- | Set the font attributes, point size and font face.+--+font_attr :: FontDef -> Int -> DrawingContextF+font_attr ft sz = \s -> s { dc_font_size = sz+ , dc_font_face = font_def_face ft } --- | Set the font size to double the current size, note the font--- size also controls the size of dots, arrowsheads etc.+-- | Set the font face.+--+set_font :: FontDef -> DrawingContextF+set_font ft = \s -> s { dc_font_face = font_def_face ft }+++-- | Set the point size.+--+-- This controls the drawing size of both +-- text labels and marks (e.g. dots and arrowheads).+--+set_font_size :: Int -> DrawingContextF+set_font_size sz = \s -> s { dc_font_size = sz }+++-- | Scale the current point size by the supplied ratio. -- -doublesize :: DrawingContextF-doublesize = scalesize 2 +-- Note - as fonts can only be drawn at integral sizes this +-- operation is not exact - for instance scaling 15pt by (1%2) +-- results in 7pt.+-- +scale_point_size :: Double -> DrawingContextF+scale_point_size a = (\s sz -> set_font_size (floor $ a * fromIntegral sz) s) + <*> dc_font_size +-- | Set the point size (font and mark size) to double the current +-- size.+--+double_point_size :: DrawingContextF+double_point_size = scale_point_size 2 --- | Set the font size to half the current size, note the font++-- | Set the point size to half the current size, note the point -- size also controls the size of dots, arrowsheads etc. -- --- As fontsize is an integer this is not exact - half size of--- 15pt type is 7pt.+-- Note - as fonts can only be drawn at integral sizes this +-- operation is not exact - half size of 15pt type is 7pt. -- -halfsize :: DrawingContextF-halfsize = scalesize (1%2)+half_point_size :: DrawingContextF+half_point_size = scale_point_size 0.5 +-- | 'text_margin' : @ x_sep * y_sep -> DrawingContextF @+--+-- NOTE - ideally this would use Em or En rather thn Double...+--+text_margin :: Em -> Em -> DrawingContextF+text_margin xsep ysep = \s -> + s { dc_text_margin = TextMargin xsep ysep }+++-- | Set the text margin to (0,0).+-- +-- This produces a tight box around the text vertically measured +-- to the cap-height and descender. Therefore some characters may +-- extend outside the margin (e.g. accented capitals like +-- A-grave).+--+text_margin_none :: DrawingContextF+text_margin_none = text_margin 0 0 ++++-- | Set the text margin to (0.25 em, 0.25 em).+-- +text_margin_tight :: DrawingContextF+text_margin_tight = text_margin 0.25 0.25++-- | Set the text margin to (0.5 em, 0.5 em).+-- +text_margin_default :: DrawingContextF+text_margin_default = text_margin 0.5 0.5++-- | Set the text margin to (1.0 em, 1.0 em).+-- +text_margin_loose :: DrawingContextF+text_margin_loose = text_margin 1.0 1.0++ -------------------------------------------------------------------------------- -swapColours :: DrawingContextF-swapColours = - (\s a b -> s { stroke_colour = b, fill_colour = a })- <*> stroke_colour <*> fill_colour+-- | Set the stroke colour.+--+stroke_colour :: RGBi -> DrawingContextF+stroke_colour rgb = \s -> s { dc_stroke_colour = rgb } -bothStrokeColour :: DrawingContextF-bothStrokeColour = (\s a -> s { fill_colour = a }) <*> stroke_colour -bothFillColour :: DrawingContextF-bothFillColour = (\s a -> s { stroke_colour = a }) <*> fill_colour+-- | Set the fill colour.+--+fill_colour :: RGBi -> DrawingContextF+fill_colour rgb = \s -> s { dc_fill_colour = rgb } +-- | Set the text colour.+--+text_colour :: RGBi -> DrawingContextF+text_colour rgb = (\s -> s { dc_text_colour = rgb}) -strokeColour :: RGBi -> DrawingContextF-strokeColour rgb = \s -> s { stroke_colour = rgb } -fillColour :: RGBi -> DrawingContextF-fillColour rgb = \s -> s { fill_colour = rgb } +-- | Set the stroke, fill and text colours to a single colour.+--+single_colour :: RGBi -> DrawingContextF+single_colour rgb = stroke_colour rgb . fill_colour rgb . text_colour rgb +-- | Swap the stroke colour and fill colours.+--+swap_colours :: DrawingContextF+swap_colours = + (\s a b -> s { dc_stroke_colour = b, dc_fill_colour = a })+ <*> dc_stroke_colour <*> dc_fill_colour ++-- | Set the fill colour to use the current stroke colour.+--+fill_use_stroke_colour :: DrawingContextF+fill_use_stroke_colour = + (\s a -> s { dc_fill_colour = a }) <*> dc_stroke_colour+++-- | Set the stroke colour to use the current fill colour.+--+stroke_use_fill_colour :: DrawingContextF+stroke_use_fill_colour = + (\s a -> s { dc_stroke_colour = a }) <*> dc_fill_colour+++-- | Set the fill colour to use the current text colour.+--+fill_use_text_colour :: DrawingContextF+fill_use_text_colour = + (\s a -> s { dc_fill_colour = a }) <*> dc_text_colour+++-- | Set the stroke colour to use the current fill colour.+--+stroke_use_text_colour :: DrawingContextF+stroke_use_text_colour = + (\s a -> s { dc_stroke_colour = a }) <*> dc_text_colour++++-- | Set the text colour to use the current stroke colour.+--+text_use_stroke_colour :: DrawingContextF+text_use_stroke_colour = + (\s a -> s { dc_text_colour = a }) <*> dc_stroke_colour+++-- | Set the text colour to use the current fill colour.+--+text_use_fill_colour :: DrawingContextF+text_use_fill_colour = + (\s a -> s { dc_text_colour = a }) <*> dc_fill_colour++++--------------------------------------------------------------------------------+-- Connector props++-- helper +connectorUpd :: (ConnectorProps -> ConnectorProps) -> DrawingContextF+connectorUpd f = + (\s a -> s { dc_connector_props = f a }) <*> dc_connector_props++-- | Normalize to zero if negative.+--+normZero :: (Num u, Ord u) => u -> u+normZero u = if u < 0 then 0 else u++-- | Set the connector source spacing.+--+-- The spacing is used as a projection along the line formed +-- between connector points making the connection /looser/ if +-- required.+-- +-- The default value is 0. Negative values are not allowed, they+-- are normalized to 0.+--+source_space :: (Ord u, InterpretUnit u) => u -> DrawingContextF+source_space u = withFontSize $ \sz -> + connectorUpd (\s -> s { dc_conn_src_space = uconvert1 sz $ normZero u })+++-- | Set the connector destination spacing.+--+-- The spacing is used as a projection along the line formed +-- between connector points making the connection /looser/ if +-- required.+-- +-- The default value is 0. Negative values are not allowed, they+-- are normalized to 0.+--+dest_space :: (Ord u, InterpretUnit u) => u -> DrawingContextF+dest_space u = withFontSize $ \sz -> + connectorUpd (\s -> s { dc_conn_dst_space = uconvert1 sz $ normZero u })++++-- | Set the connector source and destination spacings to the +-- same length.+--+uniform_conn_space :: (Ord u, InterpretUnit u) => u -> DrawingContextF+uniform_conn_space u = withFontSize $ \sz -> + connectorUpd (\s -> s { dc_conn_src_space = uconvert1 sz $ normZero u+ , dc_conn_dst_space = uconvert1 sz $ normZero u })++++-- | Set the connector source offset.+--+-- The offset is used to shift the start point /upwards/ +-- perpendicular to its true origin (negative values are +-- downwards). This can be used to draw a connector with two +-- parallel lines, for example.+--+-- Upwards and downwards in this description are dependent on the+-- direction of the line, of course. Generally the documentations +-- consider lines are left-to-right unless specifically noted.+--+source_offset :: (Ord u, InterpretUnit u) => u -> DrawingContextF+source_offset u = withFontSize $ \sz -> + connectorUpd (\s -> s { dc_conn_src_offset = uconvert1 sz u })+++-- | Set the connector destination offset.+--+-- See 'source_offset' for an explanation.+--+dest_offset :: (Ord u, InterpretUnit u) => u -> DrawingContextF+dest_offset u = withFontSize $ \sz -> + connectorUpd (\s -> s { dc_conn_dst_offset = uconvert1 sz u })+++-- | Set the connector arc angle.+--+conn_arc_angle :: Radian -> DrawingContextF+conn_arc_angle ang = + connectorUpd (\s -> s { dc_conn_arc_ang = ang })+++-- | Set the connector source arm length.+--+source_arm_len :: InterpretUnit u => u -> DrawingContextF+source_arm_len u = withFontSize $ \sz -> + connectorUpd (\s -> s { dc_conn_src_arm = uconvert1 sz u })+ ++++-- | Set the connector destination arm length.+--+dest_arm_len :: InterpretUnit u => u -> DrawingContextF+dest_arm_len u = withFontSize $ \sz -> + connectorUpd (\s -> s { dc_conn_dst_arm = uconvert1 sz u })+++++-- | Set the connector source and destination arms to the same +-- length.+--+uniform_arm_len :: InterpretUnit u => u -> DrawingContextF+uniform_arm_len u = withFontSize $ \sz -> + connectorUpd (\s -> s { dc_conn_src_arm = uconvert1 sz u+ , dc_conn_dst_arm = uconvert1 sz u })+++-- | Set the connector loop size.+--+conn_loop_size :: InterpretUnit u => u -> DrawingContextF+conn_loop_size u = withFontSize $ \sz -> + connectorUpd (\s -> s { dc_conn_loop_size = uconvert1 sz u })++-- | Set the connector box halfsize.+--+conn_box_halfsize :: InterpretUnit u => u -> DrawingContextF+conn_box_halfsize u = withFontSize $ \sz -> + connectorUpd (\s -> s { dc_conn_box_halfsize = uconvert1 sz u })
src/Wumpus/Basic/Kernel/Base/WrappedPrimitive.hs view
@@ -1,39 +1,36 @@ {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE FlexibleInstances #-} {-# OPTIONS -Wall #-} -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Basic.Kernel.Base.WrappedPrimitive--- Copyright : (c) Stephen Tetley 2010+-- Copyright : (c) Stephen Tetley 2010-2011 -- License : BSD3 -- -- Maintainer : stephen.tetley@gmail.com -- Stability : highly unstable -- Portability : GHC ----- Two /warpped/ versions of the Primitive type from Wumpus-Core.+-- Wrapped versions of the @Primitive@ type from Wumpus-Core. -- -------------------------------------------------------------------------------- module Wumpus.Basic.Kernel.Base.WrappedPrimitive ( ++ -- * Primitives- HPrim+ CatPrim+ , prim1+ , cpmap++ , HPrim , hprimToList , singleH - -- * Collect primitives (writer monad) - , TraceM(..) - , PrimGraphic - , getPrimGraphic- , primGraphic- , metamorphPrim- , collectH ) where @@ -47,24 +44,57 @@ --- As of version 0.36.0, Wumpus-Core supports grouping primitives--- together (a common operation in vector drawing editors). ------ For Wumpus-Basic this means e.g. a line with arrowheads can --- still be a primitive.------ Still, we wrap Primitive as a newtype...+-- | CatPrim could probably manage happily just being a+-- Primitive, but it is wrapped as a newtype... --+data CatPrim = CZero+ | Cat1 Primitive -newtype PrimGraphic u = PrimGraphic { getPrimGraphic :: Primitive u }- deriving (Eq,Show)+type instance DUnit CatPrim = Double +instance OPlus CatPrim where+ CZero `oplus` b = b+ a `oplus` CZero = a+ Cat1 a `oplus` Cat1 b = Cat1 $ a `primCat` b -type instance DUnit (PrimGraphic u) = u +instance Monoid CatPrim where+ mempty = CZero+ CZero `mappend` b = b+ a `mappend` CZero = a+ Cat1 a `mappend` Cat1 b = Cat1 $ a `primCat` b + --------------------------------------------------------------------------------++instance Rotate CatPrim where+ rotate _ CZero = CZero+ rotate ang (Cat1 a) = Cat1 $ rotate ang a++instance RotateAbout CatPrim where+ rotateAbout _ _ CZero = CZero+ rotateAbout ang pt (Cat1 a) = Cat1 $ rotateAbout ang pt a++instance Scale CatPrim where+ scale _ _ CZero = CZero+ scale sx sy (Cat1 a) = Cat1 $ scale sx sy a++instance Translate CatPrim where+ translate _ _ CZero = CZero+ translate dx dy (Cat1 a) = Cat1 $ translate dx dy a+++--------------------------------------------------------------------------------++prim1 :: Primitive -> CatPrim +prim1 = Cat1++cpmap :: (Primitive -> Primitive) -> CatPrim -> CatPrim+cpmap _ CZero = CZero+cpmap f (Cat1 a) = Cat1 $ f a++-------------------------------------------------------------------------------- -- Lists of primitives... -- | Graphics objects, even simple ones (line, arrow, dot) might @@ -81,8 +111,13 @@ -- representation, and a Hughes list which supports -- efficient concatenation is wise. ---newtype HPrim u = HPrim { getHPrim :: H (Primitive u) }+-- NOTE - currently HPrim has a phantom unit @u@, this is so +-- trace drawings can have a unit type, but this may change as +-- perhaps trace drawings don\'t benefit from having units.+-- +newtype HPrim u = HPrim { getHPrim :: H Primitive }+ -- Note - only a Monoid instance for HPrim - they cannot be -- shown, fmapped etc. @@ -91,59 +126,16 @@ ha `mappend` hb = HPrim $ getHPrim ha `appendH` getHPrim hb -hprimToList :: HPrim u -> [Primitive u]+hprimToList :: HPrim u -> [Primitive] hprimToList = toListH . getHPrim -singleH :: Primitive u -> HPrim u-singleH = HPrim . wrapH --------------------------------------------------------------------------------------- | Collect elementary graphics as part of a larger drawing.------ TraceM works much like a writer monad.----class TraceM (m :: * -> *) where- trace :: MonUnit m ~ u => HPrim u -> m ()+singleH :: CatPrim -> HPrim u+singleH CZero = HPrim emptyH+singleH (Cat1 a) = HPrim $ wrapH a ------------------------------------------------------------------------------------ instances--instance OPlus (PrimGraphic u) where- oplus a b = PrimGraphic $ getPrimGraphic a `oplus` getPrimGraphic b----- Affine transformations--instance (Real u, Floating u) => Rotate (PrimGraphic u) where- rotate ang = PrimGraphic . rotate ang . getPrimGraphic---instance (Real u, Floating u) => RotateAbout (PrimGraphic u) where- rotateAbout ang pt = PrimGraphic . rotateAbout ang pt . getPrimGraphic---instance Num u => Scale (PrimGraphic u) where- scale sx sy = PrimGraphic . scale sx sy . getPrimGraphic---instance Num u => Translate (PrimGraphic u) where- translate dx dy = PrimGraphic . translate dx dy . getPrimGraphic------------------------------------------------------------------------------------primGraphic :: Primitive u -> PrimGraphic u -primGraphic = PrimGraphic--metamorphPrim :: (Primitive u -> Primitive u) -> PrimGraphic u -> PrimGraphic u-metamorphPrim f = primGraphic . f . getPrimGraphic--collectH :: PrimGraphic u -> HPrim u-collectH = singleH . getPrimGraphic
+ src/Wumpus/Basic/Kernel/Objects/AdvObject.hs view
@@ -0,0 +1,230 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.Kernel.Objects.AdvObject+-- Copyright : (c) Stephen Tetley 2010-2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- Extended Graphic object - an AdvanceGraphic is a Graphic +-- twinned with and advance vector.+--+--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Objects.AdvObject+ (++ -- * Advance-vector object and graphic+ AdvObject+ , DAdvObject+ + , AdvGraphic+ , DAdvGraphic++ , makeAdvObject+ , emptyAdvObject++ , runAdvObjectR0+ , runAdvObjectR1+++ -- * Composition+ , advance+ , advances+ , advspace+ , evenspace++ , advrepeat+ , punctuate+ , advfill++ ) where++import Wumpus.Basic.Kernel.Base.BaseDefs+import Wumpus.Basic.Kernel.Base.ContextFun+import Wumpus.Basic.Kernel.Objects.Basis+import Wumpus.Basic.Kernel.Objects.Displacement+import Wumpus.Basic.Kernel.Objects.Image+import Wumpus.Basic.Kernel.Objects.LocImage++import Wumpus.Core -- package: wumpus-core++import Data.AffineSpace -- package: vector-space+import Data.VectorSpace++import Control.Applicative+import Data.Monoid++++type AdvDraw u = Point2 u -> GraphicAns u+++-- | /Advance vector/ graphic - this partially models the +-- PostScript @show@ command which moves the /current point/ by the+-- advance (width) vector as each character is drawn.+--+newtype AdvObject u = AdvObject { getAdvObject :: CF (Vec2 u, AdvDraw u) }++type instance DUnit (AdvObject u) = u++type DAdvObject = AdvObject Double+++type AdvGraphic u = LocImage u (Vec2 u)+type DAdvGraphic = AdvGraphic Double+++--------------------------------------------------------------------------------++instance (InterpretUnit u) => Monoid (AdvObject u) where+ mempty = emptyAdvObject+ mappend = advplus+++-- | 'makeAdvObject' : @ loc_context_function * graphic -> AdvObject @+--+-- Build an 'AdvObject' from a context function ('CF') that +-- generates the answer displacement vector and a 'LocGraphic' +-- that draws the 'AdvObject'.+--+makeAdvObject :: Query (Vec2 u) -> LocGraphic u -> AdvObject u+makeAdvObject qvec gf = AdvObject body+ where+ body = drawingCtx >>= \ctx -> + let v1 = runCF ctx qvec+ pf = runCF ctx gf+ in return (v1,pf)++++-- | 'emptyAdvObjectAU' : @ AdvObject @+--+-- Build an empty 'AdvObject'.+-- +-- The 'emptyAdvObject' is treated as a /null primitive/ by +-- @Wumpus-Core@ and is not drawn, the answer vector generated is+-- the zero vector @(V2 0 0)@.+-- +emptyAdvObject :: InterpretUnit u => AdvObject u+emptyAdvObject = makeAdvObject (pure $ V2 0 0) emptyLocGraphic++++runAdvObjectR0 :: Point2 u -> AdvObject u -> Image u (Vec2 u)+runAdvObjectR0 pt (AdvObject mf) = + (\(v1,pf) -> replaceAns v1 $ pf pt) <$> mf+++runAdvObjectR1 :: AdvObject u -> AdvGraphic u+runAdvObjectR1 (AdvObject mf) = promoteR1 $ \pt -> + (\(v1,pf) -> replaceAns v1 $ pf pt) <$> mf+++--------------------------------------------------------------------------------+-- Combining AdvObjects++++-- | Primitive combination.+-- +-- Move second object by the advance vector of the first. Sum +-- both advance vecots.+--+advplus :: Num u => AdvObject u -> AdvObject u -> AdvObject u+advplus a b = AdvObject body+ where + body = drawingCtx >>= \ctx ->+ let (v0,pf0) = runCF ctx (getAdvObject a)+ (v1,pf1) = runCF ctx (getAdvObject b)+ pf = \pt -> pf0 pt `oplus` pf1 (pt .+^ v0)+ in return (v0 ^+^ v1, pf)++-- Helper for list concatenation.+-- +listcat :: InterpretUnit u + => (AdvObject u -> AdvObject u -> AdvObject u)+ -> [AdvObject u] -> AdvObject u+listcat _ [] = emptyAdvObject+listcat op (x:xs) = go x xs+ where+ go acc [] = acc+ go acc (b:bs) = go (acc `op` b) bs++++-- AdvObject does not have the same ability to be concatenated+-- as PosObject - all the advance vector says is \"where to go +-- next\". Nothing in the AdvObject tracks the boundary so we+-- cannot implement the Concat classes.++infixr 6 `advance`+++-- | Draw the first AdvObject and use the advance vector to +-- displace the second AdvObject.+--+-- The final answer is the sum of both advance vectors.+--+advance :: Num u => AdvObject u -> AdvObject u -> AdvObject u+advance = advplus+ ++-- | Concatenate the list of AdvObjects with 'advance'.+--+advances :: InterpretUnit u => [AdvObject u] -> AdvObject u+advances = listcat advance+++-- | Combine the AdvObjects using the answer vector of the +-- first object plus the separator to move the start of the second+-- object. +--+advspace :: Num u => Vec2 u -> AdvObject u -> AdvObject u -> AdvObject u+advspace sep a b = AdvObject body+ where + body = drawingCtx >>= \ctx ->+ let (v0,pf0) = runCF ctx (getAdvObject a)+ (v1,pf1) = runCF ctx (getAdvObject b)+ pf = \pt -> pf0 pt `oplus` pf1 (displaceVec (sep ^+^ v0) pt)+ in return (v0 ^+^ sep ^+^ v1, pf)++-- | List version of 'nextSpace'.+--+evenspace :: InterpretUnit u => Vec2 u -> [AdvObject u] -> AdvObject u+evenspace v = listcat (advspace v)++++-- | Repeat the AdvObject @n@ times, moving each time with +-- 'advance'.+--+advrepeat :: InterpretUnit u => Int -> AdvObject u -> AdvObject u+advrepeat n = advances . replicate n+++-- | Concatenate the list of AdvObjects, going next and adding+-- the separator at each step.+--+punctuate :: InterpretUnit u => AdvObject u -> [AdvObject u] -> AdvObject u+punctuate sep = listcat (\a b -> a `advance` sep `advance` b)++++-- | Render the supplied AdvObject, but swap the result advance+-- for the supplied vector. This function has behaviour analogue +-- to @fill@ in the @wl-pprint@ library.+-- +advfill :: Num u => Vec2 u -> AdvObject u -> AdvObject u+advfill sv a = AdvObject body+ where + body = drawingCtx >>= \ctx ->+ let (_,pf) = runCF ctx (getAdvObject a) in return (sv, pf)+++
− src/Wumpus/Basic/Kernel/Objects/AdvanceGraphic.hs
@@ -1,166 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.Kernel.Objects.AdvanceGraphic--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : highly unstable--- Portability : GHC ------ Extended Graphic object - an AdvanceGraphic is a Graphic --- twinned with and advance vector.--------------------------------------------------------------------------------------module Wumpus.Basic.Kernel.Objects.AdvanceGraphic- (-- -- * Advance-vector graphic- AdvGraphic- , DAdvGraphic--- , intoAdvGraphic- , emptyAdvGraphic--- -- * Composition- , advcat- , advsep- , advconcat- , advspace- , advpunctuate- , advfill-- ) where--import Wumpus.Basic.Kernel.Base.BaseDefs-import Wumpus.Basic.Kernel.Base.ContextFun-import Wumpus.Basic.Kernel.Objects.BaseObjects-import Wumpus.Basic.Kernel.Objects.Graphic--import Wumpus.Core -- package: wumpus-core--import Data.AffineSpace -- package: vector-space-import Data.VectorSpace------ | /Advance vector/ graphic - this partially models the --- PostScript @show@ command which moves the /current point/ by the--- advance (width) vector as each character is drawn.----type AdvGraphic u = LocImage u (Vec2 u)--type DAdvGraphic = AdvGraphic Double------------------------------------------------------------------------------------------- | 'intoAdvGraphic' : @ loc_context_function * graphic -> Image @------ Build an 'AdvGraphic' from a context function ('CF') that --- generates the answer displacement vector and a 'LocGraphic' --- that draws the 'AdvGraphic'.----intoAdvGraphic :: LocCF u (Vec2 u)- -> LocGraphic u - -> AdvGraphic u-intoAdvGraphic = intoLocImage----- | 'emptyAdvGraphic' : @ AdvGraphic @------ Build an empty 'AdvGraphic'.--- --- The 'emptyAdvGraphic' is treated as a /null primitive/ by --- @Wumpus-Core@ and is not drawn, the answer vetor generated is--- the empty vector @(V2 0 0)@.--- -emptyAdvGraphic :: Num u => AdvGraphic u-emptyAdvGraphic = replaceAns (V2 0 0) $ emptyLocGraphic------ runAdvGraphic :: DrawingContext -> Point2 u -> AdvGraphic u --- -> (Point2 u, PrimGraphic u)--- runAdvGraphic ctx pt df = runCF1 ctx pt df--------------------------------------------------------------------------------------- composition---- Note there are opportunities for extra composition operators--- like the /picture language/...----- Naming convention - binary functions are favoured for shorter names.--infixr 6 `advcat`-infixr 5 `advsep`---- | Concatenate the two AdvGraphics.----advcat :: Num u => AdvGraphic u -> AdvGraphic u -> AdvGraphic u-advcat af ag = promoteR1 $ \start -> - (af `at` start) >>= \(v1,prim1) -> - (ag `at` start .+^ v1) >>= \(v2,prim2) -> - return (v1 ^+^ v2, prim1 `oplus` prim2)----- | Concatenate the two AdvGraphics spacing them by the supplied --- vector.----advsep :: Num u => Vec2 u -> AdvGraphic u -> AdvGraphic u -> AdvGraphic u-advsep sv af ag = promoteR1 $ \start -> - (af `at` start) >>= \(v1,prim1) -> - (ag `at` start .+^ sv ^+^ v1) >>= \(v2,prim2) -> - return (v1 ^+^ sv ^+^ v2, prim1 `oplus` prim2)----- | Concatenate the list of AdvGraphic with 'advcat'.----advconcat :: Num u => [AdvGraphic u] -> AdvGraphic u-advconcat [] = emptyAdvGraphic-advconcat (x:xs) = step x xs- where- step a (b:bs) = step (a `advcat` b) bs- step a [] = a----- | Concatenate the list of AdvGraphic with 'advsep'.----advspace :: Num u => Vec2 u -> [AdvGraphic u] -> AdvGraphic u-advspace _ [] = emptyAdvGraphic-advspace sv (x:xs) = step x xs- where- step a (b:bs) = step (advsep sv a b) bs- step a [] = a----- | Concatenate the list of AdvGraphic with 'advsep'.----advpunctuate :: Num u => AdvGraphic u -> [AdvGraphic u] -> AdvGraphic u-advpunctuate _ [] = emptyAdvGraphic-advpunctuate sep (x:xs) = step x xs- where- step a (b:bs) = step (a `advcat` sep `advcat` b) bs- step a [] = a----- | Render the supplied AdvGraphic, but swap the result advance--- for the supplied vector. This function has behaviour analogue --- to @fill@ in the @wl-pprint@ library.--- -advfill :: Num u => Vec2 u -> AdvGraphic u -> AdvGraphic u-advfill sv = replaceAns sv
+ src/Wumpus/Basic/Kernel/Objects/Anchors.hs view
@@ -0,0 +1,233 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE KindSignatures #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.Kernel.Objects.Anchors+-- Copyright : (c) Stephen Tetley 2010-2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Anchor points on shapes, bounding boxes, etc.+--+-- Anchors are addressable positions, an examplary use is taking+-- anchors on node shapes to get the start and end points for +-- connectors in a network (graph) diagram.+-- +-- \*\* WARNING \*\* - The API here needs some thought as to a+-- good balance of the type classes - in a nutshell \"are corners +-- better than cardinals\". Originally I tried to follow how I +-- understand the TikZ anchors to work, but this is perhaps not +-- ideal for dividing into type-classes.+--+--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Objects.Anchors+ ( ++ -- * Anchors+ Anchor++ -- * Anchor classes+ , CenterAnchor(..)+ , ApexAnchor(..)+ , CardinalAnchor(..)+ , CardinalAnchor2(..)+ , RadialAnchor(..)+ , TopCornerAnchor(..)+ , BottomCornerAnchor(..)+ , SideMidpointAnchor(..)+++ -- * Extended anchor points+ , projectAnchor++ , radialConnectorPoints++ ) where+++import Wumpus.Core -- package: wumpus-core++import Data.AffineSpace -- package: vector-space+++-- | Note an Anchor is just a Point2.+--+type Anchor u = Point2 u+++-- | Center of an object.+--+class CenterAnchor a where+ center :: u ~ DUnit a => a -> Anchor u+++-- | Apex of an object.+--+class ApexAnchor a where+ apex :: u ~ DUnit a => a -> Anchor u+++-- | Cardinal (compass) positions on an object. +-- +-- Cardinal anchors should be at their equivalent radial position.+-- However, some shapes may not be able to easily define radial +-- positions or may be able to provide more efficient definitions +-- for the cardinal anchors. Hence the redundancy seems justified. +--+class CardinalAnchor a where+ north :: u ~ DUnit a => a -> Anchor u+ south :: u ~ DUnit a => a -> Anchor u+ east :: u ~ DUnit a => a -> Anchor u+ west :: u ~ DUnit a => a -> Anchor u++--+-- Note - a design change is probably in order where the cardinals +-- should /always/ represent their true cardinal position.+--+-- If this change is made, it is worthwhile having cardinals as+-- classes (rather than making them derived operations on +-- RadialAnchor) as classes allow for more efficient +-- implementations usually by trigonometry.+-- +++-- | Secondary group of cardinal (compass) positions on an object+-- for the diagonal positions. +-- +-- It seems possible that for some objects defining the primary+-- compass points (north, south,...) will be straight-forward +-- whereas defining the secondary compass points may be +-- problematic, hence the compass points are split into two +-- classes.+--+class CardinalAnchor2 a where+ northeast :: u ~ DUnit a => a -> Anchor u+ southeast :: u ~ DUnit a => a -> Anchor u+ southwest :: u ~ DUnit a => a -> Anchor u+ northwest :: u ~ DUnit a => a -> Anchor u+++-- | Anchor on a border that can be addressed by an angle.+--+-- The angle is counter-clockwise from the right-horizontal, i.e.+-- 0 is /east/.+--+class RadialAnchor a where+ radialAnchor :: Radian -> u ~ DUnit a => a -> Anchor u+++-- | Anchors at the top left and right corners of a shape.+--+-- For some shapes (Rectangle) the TikZ convention appears to be+-- have cardinals as the corner anchors, but this doesn\'t seem+-- to be uniform. Wumpus will need to reconsider anchors at some +-- point...+--+class TopCornerAnchor a where+ topLeftCorner :: u ~ DUnit a => a -> Anchor u+ topRightCorner :: u ~ DUnit a => a -> Anchor u+++-- | Anchors at the bottom left and right corners of a shape.+--+class BottomCornerAnchor a where+ bottomLeftCorner :: u ~ DUnit a => a -> Anchor u+ bottomRightCorner :: u ~ DUnit a => a -> Anchor u+++-- | Anchors in the center of a side.+-- +-- Sides are addressable by index. Following TikZ, side 1 is +-- expected to be the top of the shape. If the shape has an apex +-- instead of a side then side 1 is expected to be the first side +-- left of the apex.+-- +-- Implementations are also expected to modulo the side number, +-- rather than throw an out-of-bounds error.+--+class SideMidpointAnchor a where+ sideMidpoint :: Int -> u ~ DUnit a => a -> Anchor u++++--------------------------------------------------------------------------------++-- | 'projectAnchor' : @ extract_func * dist * object -> Point @+-- +-- Derive a anchor by projecting a line from the center of an +-- object through the intermediate anchor (produced by the +-- extraction function). The final answer point is located along+-- the projected line at the supplied distance @dist@.+-- +-- E.g. take the north of a rectangle and project it 10 units +-- further on:+-- +-- > projectAnchor north 10 my_rect+--+-- If the distance is zero the answer with be whatever point the +-- the extraction function produces.+--+-- If the distance is negative the answer will be along the +-- projection line, between the center and the intermediate anchor.+--+-- If the distance is positive the anchor will be extend outwards +-- from the intermediate anchor.+--+projectAnchor :: (Real u, Floating u, CenterAnchor a, u ~ DUnit a) + => (a -> Anchor u) -> u -> a -> Anchor u+projectAnchor fn d a = p1 .+^ (avec (vdirection v) d)+ where+ p1 = fn a + v = pvec (center a) p1 + +++--------------------------------------------------------------------------------++-- | 'radialConnectorPoints' : @ object_a * object_b -> (Point_a, Point_b) @+--+-- Find the radial connectors points for objects @a@ and @b@ along+-- the line joining their centers.+--+radialConnectorPoints :: ( Real u, Floating u+ , CenterAnchor a, RadialAnchor a+ , CenterAnchor b, RadialAnchor b+ , u ~ DUnit a, u ~ DUnit b) + => a -> b -> (Point2 u, Point2 u) +radialConnectorPoints a b = (radialAnchor ang a, radialAnchor (ang+pi) b)+ where+ ang = vdirection $ pvec (center a) (center b)+ + ++--------------------------------------------------------------------------------+-- Instances ++instance Fractional u => CenterAnchor (BoundingBox u) where+ center (BBox (P2 xl ylo) (P2 xr yhi)) = P2 x y + where+ x = xl+0.5*(xr-xl)+ y = ylo+0.5*(yhi-ylo)+ ++instance Fractional u => CardinalAnchor (BoundingBox u) where+ north (BBox (P2 xl _ ) (P2 xr yhi)) = P2 (xl+0.5*(xr-xl)) yhi+ south (BBox (P2 xl ylo) (P2 xr _ )) = P2 (xl+0.5*(xr-xl)) ylo+ east (BBox (P2 _ ylo) (P2 xr yhi)) = P2 xr (ylo+0.5*(yhi-ylo))+ west (BBox (P2 xl ylo) (P2 _ yhi)) = P2 xl (ylo+0.5*(yhi-ylo))+++instance Fractional u => CardinalAnchor2 (BoundingBox u) where+ northeast (BBox _ ur) = ur+ southeast (BBox (P2 _ ylo) (P2 xr _)) = P2 xr ylo+ southwest (BBox ll _) = ll+ northwest (BBox (P2 xl _) (P2 _ yhi)) = P2 xl yhi +
− src/Wumpus/Basic/Kernel/Objects/BaseObjects.hs
@@ -1,186 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.Kernel.Objects.BaseObjects--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : highly unstable--- Portability : GHC ------ Aliases for ContextFun types.--- -----------------------------------------------------------------------------------module Wumpus.Basic.Kernel.Objects.BaseObjects- (-- -- * Drawing info- DrawingInfo- , LocDrawingInfo- , LocThetaDrawingInfo--- - -- * Drawing objects- , ImageAns- , GraphicAns-- , Image- , LocImage- , LocThetaImage-- , DImage- , DLocImage- , DLocThetaImage-- ) where--import Wumpus.Basic.Kernel.Base.ContextFun-import Wumpus.Basic.Kernel.Base.WrappedPrimitive--import Wumpus.Core -- package: wumpus-core------------------------------------------------------------------------------------- DrawingInfo---- | A query on the DrawingContext.------ Alias for 'CF'.--- -type DrawingInfo a = CF a----- | A query on the DrawingContext respective to the supplied--- point.------ Alias for 'LocCF'.--- -type LocDrawingInfo u a = LocCF u a----- | A query on the DrawingContext respective to the supplied--- point and angle.------ Alias for 'LocCF'.--- -type LocThetaDrawingInfo u a = LocThetaCF u a---------------------------------------------------------------------------------------- Image----- | An Image always returns a pair of some polymorphic answer @a@--- and a PrimGraphic.------ Note a PrimGraphic cannot be empty.--- -type ImageAns u a = (a, PrimGraphic u)---type GraphicAns u = ImageAns u (UNil u)----- | Draw a PrimGraphic repsective to the 'DrawingContext' and --- return some answer @a@.--- -type Image u a = CF (ImageAns u a)----- | Draw a PrimGraphic respective to the 'DrawingContext' and --- the supplied point, return some answer @a@.--- -type LocImage u a = LocCF u (ImageAns u a)----- | Draw a PrimGraphic respective to the 'DrawingContext' and--- the supplied point and angle.--- -type LocThetaImage u a = LocThetaCF u (ImageAns u a)----type DImage a = Image Double a-type DLocImage a = LocImage Double a-type DLocThetaImage a = LocThetaImage Double a---type instance DUnit (Image u a) = u -- GuardEq (DUnit a) (DUnit (PrimGraphic u))--type instance DUnit (LocImage u a) = u -- GuardEq (DUnit a) (DUnit (PrimGraphic u))--type instance DUnit (LocThetaImage u a) = u--------------------------------------------------------------------------------------- Affine instances---- Note - it seems better to have these instances for Image (even --- though Image is a type synonym) rather than more general --- instances on a CF.------ There is nothing determining a DUnit for the CF types.------ The downside is these instances are effectively orphan --- instances.-----instance (Real u, Floating u, Rotate a, DUnit a ~ u) => - Rotate (Image u a) where- rotate ang = fmap (rotate ang)---instance (Real u, Floating u, RotateAbout a, DUnit a ~ u) => - RotateAbout (Image u a) where- rotateAbout ang pt = fmap (rotateAbout ang pt)---instance (Num u, Scale a, DUnit a ~ u) => Scale (Image u a) where- scale sx sy = fmap (scale sx sy)---instance (Num u, Translate a, DUnit a ~ u) => Translate (Image u a) where- translate dx dy = fmap (translate dx dy)----- \*\* WARNING \*\* - I am not sure having affine instances for --- LocImage makes sense...------ Particularly, what is a rotateAbout on a function from Point to --- Graphic? Is it just a post-transformation, or should the start --- point be transformed as well.-----instance (Real u, Floating u, Rotate a, DUnit a ~ u) => - Rotate (LocImage u a) where- rotate ang = fmap (rotate ang)--instance (Real u, Floating u, RotateAbout a, DUnit a ~ u) => - RotateAbout (LocImage u a) where- rotateAbout ang pt = fmap (rotateAbout ang pt)---instance (Num u, Scale a, DUnit a ~ u) => Scale (LocImage u a) where- scale sx sy = fmap (scale sx sy)---instance (Num u, Translate a, DUnit a ~ u) => Translate (LocImage u a) where- translate dx dy = fmap (translate dx dy)------------------------------------------------------------------------------------------
+ src/Wumpus/Basic/Kernel/Objects/Basis.hs view
@@ -0,0 +1,564 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE UndecidableInstances #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.Kernel.Objects.Basis+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- Common types and operations.+-- +--+--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Objects.Basis+ (++ LocQuery+ , LocThetaQuery+ , ConnectorQuery ++ , GraphicAns+ , ImageAns(..)++ , graphicAns+ , mapAns+ , replaceAns+ , ignoreAns+ , answer+ , hyperlink + , clipObject + + , szconvAnsF+ , szconvAnsZ+++ , at+ , incline+ , atIncline+ , connect++ , replaceAnsR0+ , replaceAnsR1+ , replaceAnsR2++ , decorateR0+ , decorateR1+ , decorateR2++ , elaborateR0+ , elaborateR1+ , elaborateR2+ ++ ) where++import Wumpus.Basic.Kernel.Base.BaseDefs+import Wumpus.Basic.Kernel.Base.ContextFun+import Wumpus.Basic.Kernel.Base.WrappedPrimitive++import Wumpus.Core -- package: wumpus-core+++import Control.Applicative+import Data.Monoid+++type LocQuery u a = CF (Point2 u -> a)+type LocThetaQuery u a = CF (Point2 u -> Radian -> a)+type ConnectorQuery u a = CF (Point2 u -> Point2 u -> a)+++-- Design note - GraphicAns needs a unit for consistency even +-- though it is never scrutinized.+-- +++data ImageAns u a = Ans CatPrim a++type GraphicAns u = ImageAns u (UNil u)++++type instance DUnit (ImageAns u a) = u+++--------------------------------------------------------------------------------+-- OPlus and monoid+++instance OPlus a => OPlus (ImageAns u a) where+ Ans cp0 a `oplus` Ans cp1 b = Ans (cp0 `oplus` cp1) (a `oplus` b)+++instance Monoid a => Monoid (ImageAns u a) where+ mempty = Ans mempty mempty+ Ans cp0 a `mappend` Ans cp1 b = Ans (cp0 `mappend` cp1) (a `mappend` b)+++--------------------------------------------------------------------------------+-- Affine instances ++-- +-- Design Note+--+-- Translate and RotateAbout require the unit to be /scalar/ +-- e.g. Double, Centimeter, Pica.+--+-- This is annoying and a limitation, but an alternative would+-- need access to current-font-size which cannot be a pure +-- function.+-- ++instance Rotate a => Rotate (ImageAns u a) where+ rotate ang (Ans cp a) = Ans (rotate ang cp) (rotate ang a)+++instance (RotateAbout a, ScalarUnit u, u ~ DUnit a) => + RotateAbout (ImageAns u a) where+ rotateAbout ang pt@(P2 x y) (Ans cp a) = + Ans (rotateAbout ang (P2 (toPsPoint x) (toPsPoint y)) cp)+ (rotateAbout ang pt a) + +++instance Scale a => Scale (ImageAns u a) where+ scale sx sy (Ans cp a) = Ans (scale sx sy cp) (scale sx sy a)+++instance (Translate a, ScalarUnit u, u ~ DUnit a) => + Translate (ImageAns u a) where+ translate dx dy (Ans cp a) = + Ans (translate (toPsPoint dx) (toPsPoint dy) cp) (translate dx dy a) +++--------------------------------------------------------------------------------++++-- | Map the answer produced by a graphic object.+--+-- Note - the new answer must share the same unit type as the+-- initial answer, although it does not need to have the same+-- wrapper type.+--+mapAns :: (a -> a1) -> ImageAns u a -> ImageAns u a1+mapAns f (Ans cp a) = Ans cp (f a) ++++-- | Replace the answer produced by a graphic object.+--+-- Note - the new answer must share the same unit type as the+-- initial answer, although it does not need to have the same+-- wrapper type.+--+replaceAns :: ans -> ImageAns u a -> ImageAns u ans+replaceAns ans (Ans prim _) = Ans prim ans+++-- | Turn an imageAns into a GraphicAns by ignoring the +-- result.+-- +-- Usually this function will be used with one of the @push@ +-- family of combinators.+--+-- > LocImage-to-LocGraphic = pushR1 ignoreAns +--+ignoreAns :: ImageAns u a -> GraphicAns u+ignoreAns(Ans prim _) = Ans prim UNil++++graphicAns :: CatPrim -> GraphicAns u+graphicAns prim = Ans prim UNil++-- | Extractor for the answer part of an image.+--+answer :: ImageAns u a -> a+answer (Ans _ a) = a+++-- | Note - maybe this requires an arity family instead?+--+hyperlink :: XLink -> ImageAns u a -> ImageAns u a+hyperlink hypl (Ans prim a) = Ans (cpmap (xlinkPrim hypl) prim) a+++-- | Clip a graphic object.+-- +-- Note - maybe this requires an arity family instead?+--+clipObject :: PrimPath -> ImageAns t u -> ImageAns t u+clipObject pp (Ans prim a) = Ans (cpmap (clip pp) prim) a+++--------------------------------------------------------------------------------+-- Helpers for unit conversion...++++szconvAnsF :: (Functor t, InterpretUnit u, InterpretUnit u1) + => FontSize -> ImageAns u (t u) -> ImageAns u1 (t u1)+szconvAnsF sz (Ans prim a) = Ans prim (uconvertF sz a)++szconvAnsZ :: FontSize -> ImageAns u a -> ImageAns u1 a+szconvAnsZ _ (Ans prim a) = Ans prim a++++infixr 1 `at`+++-- | Downcast a 'LocCF' function by applying it to the supplied +-- point, making an arity-zero Context Function. +-- +-- Remember a 'LocCF' function is a 'CF1' context function where+-- the /static argument/ is specialized to a start point.+--+at :: LocQuery u a -> Point2 u -> CF a+at = apply1R1++++infixr 1 `incline`+++-- | Downcast a 'LocThetaQuery' function by applying it to the +-- supplied angle, making an arity-one Context Function (a +-- 'LocCF'). +-- +incline :: LocThetaQuery u a -> Radian -> LocQuery u a+incline = apply1R2+++-- | Downcast a LocThetaQuery function by applying it to the +-- supplied point and angle, making an arity-zero Context Function +-- (a CF). +--+atIncline :: LocThetaQuery u a -> Point2 u -> Radian -> CF a+atIncline = apply2R2+++-- | Downcast a 'ConnectorQuery' function by applying it to the +-- start and end point, making an arity-zero Context Function +-- (a 'CF'). +-- +connect :: ConnectorQuery u a -> Point2 u -> Point2 u -> CF a+connect = apply2R2++++-- | Replace the ans - arity 0.+-- +replaceAnsR0 :: ans -> CF (ImageAns u a) -> CF (ImageAns u ans)+replaceAnsR0 ans = fmap (replaceAns ans)+++-- | Replace the ans - arity 1.+--+replaceAnsR1 :: ans -> CF (r1 -> ImageAns u a) -> CF (r1 -> ImageAns u ans)+replaceAnsR1 ans = fmap $ fmap (replaceAns ans)+++-- | Replace the ans - arity 2.+--+replaceAnsR2 :: ans + -> CF (r1 -> r2 -> ImageAns u a) + -> CF (r1 -> r2 -> ImageAns u ans)+replaceAnsR2 ans = fmap $ fmap $ fmap (replaceAns ans) +++-- | Decorate an Image by superimposing a Graphic.+--+-- Note - this function has a very general type signature and+-- supports various graphic types:+--+decorateR0 :: CF (ImageAns u a) -> CF (GraphicAns u) -> CF (ImageAns u a) +decorateR0 img gf = op <$> img <*> gf+ where+ op (Ans cp a) (Ans cp1 _) = Ans (cp `oplus` cp1) a+++decorateR1 :: CF (r1 -> ImageAns u a) + -> CF (r1 -> GraphicAns u) + -> CF (r1 -> ImageAns u a) +decorateR1 img gf = promoteR1 $ \r1 ->+ op <$> apply1R1 img r1 <*> apply1R1 gf r1+ where+ op (Ans cp a) (Ans cp1 _) = Ans (cp `oplus` cp1) a+++decorateR2 :: CF (r1 -> r2 -> ImageAns u a) + -> CF (r1 -> r2 -> GraphicAns u) + -> CF (r1 -> r2 -> ImageAns u a) +decorateR2 img gf = promoteR2 $ \r1 r2 ->+ op <$> apply2R2 img r1 r2 <*> apply2R2 gf r1 r2+ where+ op (Ans cp a) (Ans cp1 _) = Ans (cp `oplus` cp1) a+++-- | Decorate an Image by superimposing a Graphic.+--+-- Note - this function has a very general type signature and+-- supports various graphic types:+--+elaborateR0 :: CF (ImageAns u a) -> (a -> CF (GraphicAns u)) -> CF (ImageAns u a) +elaborateR0 img gf = + img >>= \(Ans p1 a) ->+ gf a >>= \(Ans p2 _) -> + return $ Ans (p1 `oplus` p2) a+++++-- | Decorate an Image by superimposing a Graphic.+--+-- Note - this function has a very general type signature and+-- supports various graphic types:+--+elaborateR1 :: CF (r1 -> ImageAns u a) + -> (a -> CF (r1 -> GraphicAns u)) + -> CF (r1 -> ImageAns u a) +elaborateR1 img gf = promoteR1 $ \r1 -> + apply1R1 img r1 >>= \(Ans p1 a) ->+ apply1R1 (gf a) r1 >>= \(Ans p2 _) -> + return $ Ans (p1 `oplus` p2) a++++elaborateR2 :: CF (r1 -> r2 -> ImageAns u a) + -> (a -> CF (r1 -> r2 -> GraphicAns u)) + -> CF (r1 -> r2 -> ImageAns u a) +elaborateR2 img gf = promoteR2 $ \r1 r2 -> + apply2R2 img r1 r2 >>= \(Ans p1 a) ->+ apply2R2 (gf a) r1 r2 >>= \(Ans p2 _) -> + return $ Ans (p1 `oplus` p2) a+++++{-++-- Not exported - thanks to Max Bollingbroke.+--+type family GuardEqAns a b :: *+type instance GuardEqAns a a = a++-- | An Image always returns a pair of some polymorphic answer @a@+-- and a PrimGraphic.+--+data ImageAns t u = Ans (t u) CatPrim++type instance DUnit (ImageAns t u) = GuardEqAns u (DUnit (t u))++type GraphicAns u = ImageAns UNil u+++instance Functor t => Functor (ImageAns t) where+ fmap f (Ans a prim) = Ans (fmap f a) prim++instance OPlus (t u) => OPlus (ImageAns t u) where+ Ans a p1 `oplus` Ans b p2 = Ans (a `oplus` b) (p1 `oplus` p2)+++--------------------------------------------------------------------------------+-- Affine instances ++-- +-- Design Note+--+-- Translate and RotateAbout require the unit to be /scalar/ +-- e.g. Double, Centimeter, Pica.+--+-- This is annoying and a limitation, but an alternative would+-- need access to current-font-size which cannot be a pure +-- function.+-- ++instance Rotate (t u) => Rotate (ImageAns t u) where+ rotate ang (Ans a p) = Ans (rotate ang a) (rotate ang p)+++instance (RotateAbout (t u), ScalarUnit u, u ~ DUnit (t u)) => + RotateAbout (ImageAns t u) where+ rotateAbout ang pt@(P2 x y) (Ans a p) = + Ans (rotateAbout ang pt a) + (rotateAbout ang (P2 (toPsPoint x) (toPsPoint y)) p)+++instance Scale (t u) => Scale (ImageAns t u) where+ scale sx sy (Ans a p) = Ans (scale sx sy a) (scale sx sy p)+++instance (Translate (t u), ScalarUnit u, u ~ DUnit (t u)) => + Translate (ImageAns t u) where+ translate dx dy (Ans a p) = + Ans (translate dx dy a) (translate (toPsPoint dx) (toPsPoint dy) p)+++--------------------------------------------------------------------------------+++-- | Ignore the answer produced by an Image (or LocImage, etc.)+-- and form a Graphic instead.+--+ignoreAns :: Functor f+ => cf (ImageAns t u) -> cf (GraphicAns u)+ignoreAns = fmap (\(Ans _ prim) -> Ans UNil prim)++++-- | Replace the answer produced by a graphic object.+--+-- Note - the new answer must share the same unit type as the+-- initial answer, although it does not need to have the same+-- wrapper type.+--+replaceAns :: Functor cf+ => t1 u -> cf (ImageAns t u) -> cf (ImageAns t1 u)+replaceAns ans = fmap (\(Ans _ prim) -> Ans ans prim)+++-- | Map the answer produced by a graphic object.+--+-- Note - the new answer must share the same unit type as the+-- initial answer, although it does not need to have the same+-- wrapper type.+--+mapAns :: Functor cf+ => (t u -> t1 u) -> cf (ImageAns t u) -> cf (ImageAns t1 u)+mapAns f = fmap (trafoImageAns f id) ++++-- | Transform both the answer produced by a graphic object and +-- transform the primitive drawing.+--+-- Note - the new answer must share the same unit type as the+-- initial answer, although it does not need to have the same+-- wrapper type. Also this function is specifically exposed to+-- enable affine transofrmations - it is not expected to be +-- generally useful.+--+trafoImageAns :: (t u -> t1 u) -> (CatPrim -> CatPrim) + -> ImageAns t u -> ImageAns t1 u+trafoImageAns f g (Ans a prim) = Ans (f a) (g prim)+++-- | Decorate an Image by superimposing a Graphic.+--+-- Note - this function has a very general type signature and+-- supports various graphic types:+--+-- > decorate :: Image u a -> Graphic u -> Image u a+-- > decorate :: LocImage u a -> LocGraphic u -> LocImage u a+-- > decorate :: LocThetaImage u a -> LocThetaGraphic u -> LocTheteImage u a+--+decorate :: Monad cf+ => cf (ImageAns t u) -> cf (GraphicAns u) -> cf (ImageAns t u) +decorate img gf = combind const img (const gf) +++-- | Ante-decorate - version of 'decorate' where the decoration is +-- drawn behind the Image.+--+adecorate :: Monad cf+ => cf (ImageAns t u) -> cf (GraphicAns u) -> cf (ImageAns t u) +adecorate img gf = acombind const img (const gf)+++-- | Version of 'elaborate' where the decorating Graphic has access +-- to the result produced by the Image.+--+-- Again, this function has a very general type signature and+-- supports various graphic types:+--+-- > elaborate :: Image u a -> Graphic u -> Image u a+-- > elaborate :: LocImage u a -> LocGraphic u -> LocImage u a+-- > elaborate :: LocThetaImage u a -> LocThetaGraphic u -> LocTheteImage u a+--+elaborate :: Monad cf + => cf (ImageAns t u) + -> (t u -> cf (GraphicAns u)) + -> cf (ImageAns t u)+elaborate img gf = combind const img gf++-- | Ante-elaborate - version of 'elaborate' where the decoration +-- is drawn behind the Image.+--+aelaborate :: Monad cf + => cf (ImageAns t u) -> (t u -> cf (GraphicAns u)) -> cf (ImageAns t u)+aelaborate img gf = acombind const img gf+++-- | Hyperlink a graphic object.+-- +-- This function has a very general type signature and supports +-- various graphic types:+--+-- > hyperlink :: XLink -> Graphic u -> Graphic u+-- > hyperlink :: XLink -> Image u a -> Image u a+-- > hyperlink :: XLink -> LocImage u a -> LocImage u a+-- > hyperlink :: XLink -> LocThetaImage u a -> LocThetaImage u a+--+hyperlink :: Functor cf + => XLink -> cf (ImageAns t u) -> cf (ImageAns t u)+hyperlink hypl = + fmap (\(Ans a prim) -> Ans a (cpmap (xlinkPrim hypl) prim))+++-- | Clip a graphic object.+-- +clipObject :: Functor cf + => PrimPath -> cf (ImageAns t u) -> cf (ImageAns t u)+clipObject pp = + fmap (\(Ans a prim) -> Ans a (cpmap (clip pp) prim))+++++-- | This is a very general monadic combiner.+-- +-- The first argument is a pure combiner cf. @liftM2@, @liftA2@+-- +-- The second argument is an Image to be evaluated.+--+-- The third argument, uses the ouput from the first Image to +-- build a second Image.+-- +-- The function concatenates the CatPrims formed by both Images+-- and uses the pure combiner to build an answer from the+-- intermediate answers.+--+-- NOTE - note useful with CF representation change.+--+combind :: Monad cf + => (t1 u -> t2 u -> t3 u)+ -> cf (ImageAns t1 u) + -> (t1 u -> cf (ImageAns t2 u)) + -> cf (ImageAns t3 u) +combind op gf fn = gf >>= \(Ans a p1) -> + fn a >>= \(Ans b p2) -> + return $ Ans (a `op` b) (p1 `oplus` p2)+++-- | Version of combind where the drawing order is flipped.+--+acombind :: Monad cf + => (t1 u -> t2 u -> t3 u)+ -> cf (ImageAns t1 u) + -> (t1 u -> cf (ImageAns t2 u)) + -> cf (ImageAns t3 u) +acombind op gf fn = gf >>= \(Ans a p1) -> + fn a >>= \(Ans b p2) -> + return $ Ans (a `op` b) (p2 `oplus` p1)++-}
src/Wumpus/Basic/Kernel/Objects/Bounded.hs view
@@ -3,7 +3,7 @@ -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Basic.Kernel.Objects.Bounded--- Copyright : (c) Stephen Tetley 2010+-- Copyright : (c) Stephen Tetley 2010-2011 -- License : BSD3 -- -- Maintainer : stephen.tetley@gmail.com@@ -14,6 +14,8 @@ -- -- Bounded meaning they are actually Images that return the -- bounding box of the Graphic.+-- +-- These abojects are type synonyms. -- -------------------------------------------------------------------------------- @@ -29,10 +31,12 @@ , BoundedLocThetaGraphic , DBoundedLocThetaGraphic + , emptyBoundedLocGraphic , emptyBoundedLocThetaGraphic , centerOrthoBBox+ , illustrateBoundedGraphic , illustrateBoundedLocGraphic , illustrateBoundedLocThetaGraphic@@ -45,13 +49,14 @@ import Wumpus.Basic.Kernel.Base.ContextFun import Wumpus.Basic.Kernel.Base.DrawingContext import Wumpus.Basic.Kernel.Base.UpdateDC-import Wumpus.Basic.Kernel.Objects.BaseObjects+import Wumpus.Basic.Kernel.Objects.Basis import Wumpus.Basic.Kernel.Objects.DrawingPrimitives-import Wumpus.Basic.Kernel.Objects.Graphic+import Wumpus.Basic.Kernel.Objects.Image+import Wumpus.Basic.Kernel.Objects.LocImage+import Wumpus.Basic.Kernel.Objects.LocThetaImage import Wumpus.Core -- package: wumpus-core -import Control.Applicative -------------------------------------------------------------------------------- @@ -84,6 +89,9 @@ +++ -- | 'centerOrthoBBox' : @ theta * bbox -> BBox @ -- -- Rotate a bounding box by @theta@ about its center. Take the @@ -93,15 +101,13 @@ -- so the dimensions as well as the positions may change under -- rotation. ---centerOrthoBBox :: (Real u, Floating u) ++centerOrthoBBox :: (Real u, Floating u, Ord u) => Radian -> BoundingBox u -> BoundingBox u-centerOrthoBBox theta bb = - traceBoundary $ map (rotateAbout theta ctr) ps+centerOrthoBBox theta bb = traceBoundary $ map (rotateAbout theta ctr) ps where- ps = boundaryCornerList bb ctr = boundaryCenter bb--+ ps = boundaryCornerList bb -- | 'emptyBoundedLocGraphic' : @ BoundedLocGraphic @@@ -113,12 +119,14 @@ -- the minimum bounding box with both the bottom-left and -- upper-right corners at the implicit start point. ---emptyBoundedLocGraphic :: Num u => BoundedLocGraphic u+emptyBoundedLocGraphic :: InterpretUnit u => BoundedLocGraphic u emptyBoundedLocGraphic = intoLocImage fn emptyLocGraphic where- fn = promoteR1 $ \pt -> pure (BBox pt pt)+ fn = promoteR1 $ \pt -> return $ BBox pt pt ++ -- | 'emptyBoundedLocThetaGraphic' : @ BoundedLocThetaGraphic @ -- -- Build an empty 'BoundedLocThetaGraphic'.@@ -129,40 +137,68 @@ -- upper-right corners at the implicit start point (the implicit -- inclination can be ignored). ---emptyBoundedLocThetaGraphic :: Num u => BoundedLocThetaGraphic u-emptyBoundedLocThetaGraphic = lift1R2 emptyBoundedLocGraphic+emptyBoundedLocThetaGraphic :: InterpretUnit u => BoundedLocThetaGraphic u+emptyBoundedLocThetaGraphic = intoLocThetaImage fn emptyLocThetaGraphic+ where+ fn = promoteR2 $ \pt _ -> return $ BBox pt pt ++--+-- NOTE - CONCATENATION+--+-- Because there is no tangible relation between the start point +-- and answer BoundingBox, LocBoundedGraphic supports exactly the+-- same concatenation as LocImage.+--+-- PosImage and AdvGraphic are the objects that support more +-- sophisticated concatenation.+--+ ++ -------------------------------------------------------------------------------- -- --- This is a common pattern so needs a name... -illustrateBoundedGraphic :: Fractional u => BoundedGraphic u -> BoundedGraphic u-illustrateBoundedGraphic mf = - mf >>= \(bb,g1) -> bbrectangle bb >>= \(_,g0) -> return (bb, g0 `oplus` g1)+-- | Draw a BoundedGraphic, illustrating the bounding box.+--+illustrateBoundedGraphic :: InterpretUnit u+ => BoundedGraphic u -> BoundedGraphic u+illustrateBoundedGraphic gf = elaborateR0 gf bbrectangle -illustrateBoundedLocGraphic :: Fractional u ++-- | Draw a BoundedLocGraphic, illustrating the bounding box.+--+illustrateBoundedLocGraphic :: InterpretUnit u => BoundedLocGraphic u -> BoundedLocGraphic u-illustrateBoundedLocGraphic mf = - promoteR1 $ \pt -> illustrateBoundedGraphic $ apply1R1 mf pt+illustrateBoundedLocGraphic gf = elaborateR1 gf fn+ where+ fn bb = lift0R1 (bbrectangle bb) -illustrateBoundedLocThetaGraphic :: Fractional u - => BoundedLocThetaGraphic u -> BoundedLocThetaGraphic u-illustrateBoundedLocThetaGraphic mf = - promoteR2 $ \pt theta-> illustrateBoundedGraphic $ apply2R2 mf pt theta --- -bbrectangle :: Fractional u => BoundingBox u -> Graphic u+-- | Draw a BoundedLocThetaGraphic, illustrating the bounding box.+--+illustrateBoundedLocThetaGraphic :: InterpretUnit u+ => BoundedLocThetaGraphic u + -> BoundedLocThetaGraphic u+illustrateBoundedLocThetaGraphic gf = elaborateR2 gf fn+ where+ fn bb = lift0R2 (bbrectangle bb)+++++bbrectangle :: InterpretUnit u => BoundingBox u -> Graphic u bbrectangle (BBox p1@(P2 llx lly) p2@(P2 urx ury)) | llx == urx && lly == ury = emptyLocGraphic `at` p1 | otherwise = localize drawing_props $ rect1 `oplus` cross where- drawing_props = capRound . dashPattern (Dash 0 [(1,2)])+ drawing_props = cap_round . dotted_line rect1 = strokedRectangle (urx-llx) (ury-lly) `at` p1- cross = straightLineGraphic p1 p2 - `oplus` straightLineGraphic (P2 llx ury) (P2 urx lly)+ cross = straightLine p1 p2 + `oplus` straightLine (P2 llx ury) (P2 urx lly)
+ src/Wumpus/Basic/Kernel/Objects/Chain.hs view
@@ -0,0 +1,228 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.Kernel.Objects.Chain+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- Chaining moveable LocGraphics.+--+--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Objects.Chain+ (+ ChainAlg+ , IterationScheme+ + , chain+ , chain_+ + , linear+ , prefix+ , iterationScheme++ , chainIterate+ , chainH+ , chainV++ , tableRight + , tableDown++ , radialChain++ ) where+++import Wumpus.Basic.Kernel.Base.BaseDefs+import Wumpus.Basic.Kernel.Base.ContextFun+import Wumpus.Basic.Kernel.Objects.Basis+import Wumpus.Basic.Kernel.Objects.Displacement+import Wumpus.Basic.Kernel.Objects.LocImage+import Wumpus.Basic.Kernel.Objects.Image+import Wumpus.Basic.Utils.HList++import Wumpus.Core -- package: wumpus-core++++-- In TikZ chains are finite node list and iterated (infite) points+++-- | Chain algorithm.+-- +-- @Linear@ simply iterates points.+--+-- @Prefix@ runs the left chain @n@ times then runs the right +-- chain from the end point of the left chain.+-- +data ChainAlg u = L1 (IterationScheme u)+ | PX Int (ChainAlg u) (ChainAlg u)+++++type instance DUnit (ChainAlg u) = u++++data IterationScheme u = forall st. Scheme + { scheme_start :: Point2 u -> st+ , scheme_step :: st -> (st, Point2 u)+ }++type instance DUnit (IterationScheme u) = u+++++-- | Note the tail of of result list is infinite.+-- +-- As any prefixes will be generated fully. This potentially+-- produces a /space bubble/ where a long prefix has to be +-- generated without the streaming of lazy evaluation. However,+-- chains that are long enough to cause this problem will be +-- problematic for a PostScript or SVG renderer.+--+-- In short - don'\t make long chains.+--+interpChainAlg :: ChainAlg u -> Point2 u -> [Point2 u]+interpChainAlg ch start = go start ch+ where+ go pt (L1 (Scheme mk run)) = let st = mk pt in runInf run st+ go pt (PX n chl chr) = let (af,end) = takeAndLast n (go pt chl)+ in prefixListH af $ go end chr+++runInf :: (st -> (st,Point2 u)) -> st -> [Point2 u]+runInf fn = \st -> go (fn st) + where+ go (st,a) = a : go (fn st)+++++-- | Take n elements - also return the last of element in the +-- tuple so it can be accessed without a second traversal.+--+-- Note @(n > 0)@ +-- +takeAndLast :: Int -> [a] -> (H a,a)+takeAndLast _ [] = error "takeAndLast - empty list (unreachable?)"+takeAndLast n (a:as) = go (wrapH a,a) (n-1) as+ where+ go (af,_) i (x:xs) | i > 0 = go (af `snocH` x, x) (i-1) xs+ go acc _ _ = acc++++-- | Returns the end point...+--+chain :: InterpretUnit u + => ChainAlg u -> [LocImage u a] -> LocImage u (Point2 u)+chain _ [] = promoteR1 $ \pt -> + fmap (replaceAns pt) $ emptyLocGraphic `at` pt++chain alg fs = promoteR1 $ \pt -> + let ps = interpChainAlg alg pt in go1 fs pt ps + where+ go1 (gf:gs) _ (p:ps) = go (graphic_ $ gf `at` p) gs p ps+ go1 _ p0 _ = fmap (replaceAns p0) $ emptyLocGraphic `at` p0++ go acc (gf:gs) _ (p:ps) = let g1 = graphic_ $ gf `at` p+ in go (acc `oplus` g1) gs p ps+ go acc _ p0 _ = fmap (replaceAns p0) acc+++-- | Returns no answer, just a 'LocGraphic'.+chain_ :: InterpretUnit u => ChainAlg u -> [LocImage u a] -> LocGraphic u+chain_ alg xs = locGraphic_ $ chain alg xs+++linear :: IterationScheme u -> ChainAlg u+linear = L1++prefix :: Int -> ChainAlg u -> ChainAlg u -> ChainAlg u+prefix n c1 c2 | n < 1 = c2+ | otherwise = PX n c1 c2+++iterationScheme :: (Point2 u -> st) + -> (st -> (st, Point2 u)) + -> IterationScheme u+iterationScheme start stepper = Scheme start stepper+++++chainIterate :: (Point2 u -> Point2 u) -> ChainAlg u+chainIterate fn = L1 $ Scheme { scheme_start = id+ , scheme_step = \pt -> (fn pt, pt)+ }+++chainH :: Num u => u -> ChainAlg u+chainH = L1 . scHorizontal++scHorizontal :: Num u => u -> IterationScheme u+scHorizontal dx = Scheme { scheme_start = id+ , scheme_step = \pt -> (displaceH dx pt, pt)+ }+ +++chainV :: Num u => u -> ChainAlg u+chainV = L1 . scVertical++scVertical :: Num u => u -> IterationScheme u+scVertical dy = Scheme { scheme_start = id+ , scheme_step = \pt -> (displaceV dy pt, pt)+ }+++tableRight :: Num u => Int -> (u,u) -> ChainAlg u+tableRight num_cols (col_width,row_height) = + L1 $ scStepper downF num_cols rightF+ where+ downF = displaceV $ negate row_height+ rightF = displaceH col_width++tableDown :: Num u => Int -> (u,u) -> ChainAlg u+tableDown num_rows (col_width,row_height) = + L1 $ scStepper rightF num_rows downF+ where+ downF = displaceV $ negate row_height+ rightF = displaceH col_width+++-- | Outer and inner steppers.+--+scStepper :: PointDisplace u -> Int -> PointDisplace u -> IterationScheme u+scStepper outF n innF = Scheme start step+ where+ start pt = (pt,pt,0)+ step (ogin,pt,i) | i < n = ((ogin, innF pt, i+1), pt)+ | otherwise = let o1 = outF ogin + in ((o1, innF o1,1), o1) +++++radialChain :: Floating u => u -> Radian -> Radian -> ChainAlg u+radialChain radius start step = L1 $ scCircular radius start step++ +scCircular :: Floating u => u -> Radian -> Radian -> IterationScheme u+scCircular radius angstart angseg = Scheme start step + where+ start pt = (pt,angstart)+ step (ogin,ang) = ((ogin,ang + angseg), displaceVec (avec ang radius) ogin)++
+ src/Wumpus/Basic/Kernel/Objects/Concat.hs view
@@ -0,0 +1,188 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.Kernel.Objects.Concat+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- Classes for concatenation.+--+--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Objects.Concat+ (++ ZConcat(..)+ , cat+ , Concat(..)+ , hcat+ , vcat++ , CatSpace(..)+ , hsep+ , vsep++ , Align(..)+ , alignRow+ , alignColumn++ , AlignSpace(..)+ , alignRowSep+ , alignColumnSep+ + + ) where++import Wumpus.Basic.Kernel.Base.BaseDefs++import Wumpus.Core -- package: wumpus-core++import Data.Monoid++infixr 6 `superior`, `anterior`++-- | Minimal defintion is 'superior', 'anterior' is usually +-- @flip superior@.+--+-- > `superior` (infixr 6)+--+-- > `anterior` (infixr 6)+-- +-- +class ZConcat o where+ anterior :: o -> o -> o + superior :: o -> o -> o++ anterior = flip superior+++cat :: (Monoid o, ZConcat o) => [o] -> o+cat [] = mempty+cat (x:xs) = go x xs+ where+ go acc [] = acc+ go acc (a:as) = go (acc `superior` a) as+ +++infixr 6 `hconcat`+infixr 5 `vconcat`+++-- | Concatenation with /movement/ - the second object is moved+-- next to the first.+--+-- > hconcat is equivalent to @(<>)@ in WL-PPrint.+-- > (infixr 6)+-- +-- > vconcat is equivalent to @(<$>)@ in WL_PPrint.+-- > (infixr 5)+--+class Concat o where+ hconcat :: o -> o -> o+ vconcat :: o -> o -> o++-- | Horizontally concatenate a list of objects.+-- +-- Note - the first argument is an /alternative/ - this is drawn +-- if the list is empty, otherwise it is not drawn.+--+hcat :: (Monoid o, Concat o) => [o] -> o+hcat [] = mempty+hcat (x:xs) = go x xs+ where+ go acc [] = acc+ go acc (a:as) = go (acc `hconcat` a) as+ ++-- | Vertically concatenate a list of objects.+-- +-- Note - the first argument is an /alternative/ - this is drawn +-- if the list is empty, otherwise it is not drawn.+--+vcat :: (Monoid o, Concat o) => [o] -> o+vcat [] = mempty+vcat (x:xs) = go x xs+ where+ go acc [] = acc+ go acc (a:as) = go (acc `vconcat` a) as+ ++class CatSpace o where+ hspace :: u ~ DUnit o => u -> o -> o -> o+ vspace :: u ~ DUnit o => u -> o -> o -> o++hsep :: (Monoid o, CatSpace o, u ~ DUnit o) => u -> [o] -> o+hsep _ [] = mempty+hsep dx (x:xs) = go x xs+ where+ op = hspace dx+ go acc [] = acc+ go acc (a:as) = go (acc `op` a) as+ ++vsep :: (Monoid o, CatSpace o, u ~ DUnit o) => u -> [o] -> o+vsep _ [] = mempty+vsep dx (x:xs) = go x xs+ where+ op = vspace dx+ go acc [] = acc+ go acc (a:as) = go (acc `op` a) as+++class Align o where+ halign :: HAlign -> o -> o -> o + valign :: VAlign -> o -> o -> o+++alignRow :: (Monoid o, Align o) => HAlign -> [o] -> o+alignRow _ [] = mempty+alignRow ha (x:xs) = go x xs+ where+ op = halign ha + go acc [] = acc+ go acc (a:as) = go (acc `op` a) as+++alignColumn :: (Monoid o, Align o) => VAlign -> [o] -> o+alignColumn _ [] = mempty+alignColumn va (x:xs) = go x xs+ where+ op = valign va + go acc [] = acc+ go acc (a:as) = go (acc `op` a) as++++class AlignSpace o where+ halignSpace :: u ~ DUnit o => HAlign -> u -> o -> o -> o + valignSpace :: u ~ DUnit o => VAlign -> u -> o -> o -> o++++alignRowSep :: (Monoid o, AlignSpace o, u ~ DUnit o) + => HAlign -> u -> [o] -> o+alignRowSep _ _ [] = mempty+alignRowSep ha dx (x:xs) = go x xs+ where+ op = halignSpace ha dx+ go acc [] = acc+ go acc (a:as) = go (acc `op` a) as+++alignColumnSep :: (Monoid o, AlignSpace o, u ~ DUnit o) + => VAlign -> u -> [o] -> o+alignColumnSep _ _ [] = mempty+alignColumnSep va dx (x:xs) = go x xs+ where+ op = valignSpace va dx+ go acc [] = acc+ go acc (a:as) = go (acc `op` a) as++
src/Wumpus/Basic/Kernel/Objects/Connector.hs view
@@ -1,99 +1,95 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeSynonymInstances #-} {-# OPTIONS -Wall #-} -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Basic.Kernel.Objects.Connector--- Copyright : (c) Stephen Tetley 2010+-- Copyright : (c) Stephen Tetley 2011 -- License : BSD3 -- -- Maintainer : stephen.tetley@gmail.com -- Stability : highly unstable -- Portability : GHC ----- Graphic and Image types representing connectors - connectors--- have two implicit points - start and end.+-- ConnImage and ConnGraphic types - these are functional types+-- from the DrawingContext plus start point and end point to a +-- graphic /primitive/. -- -------------------------------------------------------------------------------- module Wumpus.Basic.Kernel.Objects.Connector- (+ (+ ConnectorImage+ , ConnectorGraphic - -- * Connector Graphic- ConnectorGraphic- , DConnectorGraphic+ , DConnectorImage+ , DConnectorGraphic + , intoConnectorImage+ , connectorGraphic_ - -- * Connector Image- , ConnectorImage- , DConnectorImage+ , emptyConnectorGraphic - , intoConnectorImage- , emptyConnectorGraphic+ , uconvConnectorImageF+ , uconvConnectorImageZ - ) where+ ) + where+ import Wumpus.Basic.Kernel.Base.BaseDefs import Wumpus.Basic.Kernel.Base.ContextFun-import Wumpus.Basic.Kernel.Objects.BaseObjects-import Wumpus.Basic.Kernel.Objects.Graphic+import Wumpus.Basic.Kernel.Objects.Basis+import Wumpus.Basic.Kernel.Objects.LocImage --- import Wumpus.Core -- package: wumpus-core import Control.Applicative ------------------------------------------------------------------------------------ Connector Graphic ---- | ConnectorGraphic is a connector drawn between two points --- contructing a Graphic.----type ConnectorGraphic u = ConnectorCF u (GraphicAns u)---- | Alias of 'ConnectorGraphic' where the unit type is --- specialized to Double. +-- | ConnectorImage - function from DrawingContext and start and +-- end points to a polymorphic /answer/ and a graphic /primitive/. ---type DConnectorGraphic = ConnectorGraphic Double--+type ConnectorImage u a = ConnectorQuery u (ImageAns u a) ------------------------------------------------------------------------------------ Connector Image+-- | ConnectorGraphic - function from DrawingContext and start and +-- end points to a graphic /primitive/.+--+type ConnectorGraphic u = ConnectorQuery u (GraphicAns u) --- | ConnectorImage is a connector drawn between two points --- constructing an Image.------ Usually the answer type of a ConnectorImage will be a Path --- (defined in Wumpus-Drawing) so the points at @midway@, --- @atstart@ etc. or the end directions and tangents can be taken --- on it.+-- | Type specialized version of 'ConnectorImage'. ---type ConnectorImage u a = ConnectorCF u (ImageAns u a)-+type DConnectorImage a = ConnectorImage Double a --- | Alias of 'ConnectorImage' where the unit type is --- specialized to Double. +-- | Type specialized version of 'ConnectorGraphic'. ---type DConnectorImage a = ConnectorImage Double a+type DConnectorGraphic = ConnectorGraphic Double --- | 'intoConnectorImage' : @ conn_context_function * conn_graphic -> LocImage @+-- | 'intoConnectorImage' : @ conn_query * conn_graphic -> LocImage @ -- -- /Connector/ version of 'intoImage'. -- -- The 'ConnectorImage' is built as a function from an implicit -- start and end points to the answer. ---intoConnectorImage :: ConnectorCF u a -> ConnectorGraphic u +intoConnectorImage :: ConnectorQuery u a+ -> ConnectorGraphic u -> ConnectorImage u a-intoConnectorImage = liftA2 (\a (_,b) -> (a,b))+intoConnectorImage qf ma = + promoteR2 $ \a b -> replaceAns <$> apply2R2 qf a b <*> apply2R2 ma a b +-- | /Downcast/ an 'ConnectorImage' to a 'ConnectorGraphic'.+-- +-- This means forgetting the answer of the Image, replacing it +-- with @()@.+--+connectorGraphic_ :: ConnectorImage u a -> ConnectorGraphic u+connectorGraphic_ = (fmap . fmap . fmap) ignoreAns++ -- | 'emptyConnectorGraphic' : @ ConnectorGraphic @ -- -- Build an empty 'ConnectorGraphic'.@@ -103,10 +99,41 @@ -- bounding box around the rectangular hull of the start and end -- points. -- -emptyConnectorGraphic :: Num u => ConnectorGraphic u +emptyConnectorGraphic :: InterpretUnit u => ConnectorGraphic u emptyConnectorGraphic = promoteR2 $ \start end -> let a = emptyLocGraphic `at` start b = emptyLocGraphic `at` end in a `oplus` b ++++-- | Use this to convert 'ConnectorGraphic' or 'ConnectorImage' +-- with Functor answer.+--+uconvConnectorImageF :: (InterpretUnit u, InterpretUnit u1, Functor t) + => ConnectorImage u (t u) -> ConnectorImage u1 (t u1)+uconvConnectorImageF = uconvR2ab szconvAnsF++++-- | Use this to convert 'ConnectorImage' with unit-less answer.+--+uconvConnectorImageZ :: (InterpretUnit u, InterpretUnit u1) + => ConnectorImage u a -> ConnectorImage u1 a+uconvConnectorImageZ = uconvR2ab szconvAnsZ+++--------------------------------------------------------------------------------+++--+-- Design note - potentially there are no useful combining +-- operators on Connectors (!).+--+-- Division - i.e. splitting a path at points between the start +-- and end - seems a more obvious operation on connector paths +-- than combination. See the ConnectorPath operations in +-- Wumpus-Drawing for some examples.+--
src/Wumpus/Basic/Kernel/Objects/CtxPicture.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE RankNTypes #-} {-# OPTIONS -Wall #-} --------------------------------------------------------------------------------@@ -31,50 +32,25 @@ ( CtxPicture- , DCtxPicture , runCtxPicture , runCtxPictureU , drawTracing+ , udrawTracing - , clipCtxPicture , mapCtxPicture -- * Composition- , cxpBeneath - , cxpUniteCenter- , cxpRight- , cxpDown+ , uniteCenter - , cxpCenteredAt--- , cxpRow - , cxpColumn--- , cxpRightSep- , cxpDownSep- , cxpRowSep- , cxpColumnSep- - -- * Compose with alignment- , cxpAlignH- , cxpAlignV- , cxpAlignSepH- , cxpAlignSepV- , cxpAlignRow- , cxpAlignColumn- , cxpAlignRowSep- , cxpAlignColumnSep-+ , centeredAt ) where -import Wumpus.Basic.Kernel.Base.Anchors import Wumpus.Basic.Kernel.Base.BaseDefs-import Wumpus.Basic.Kernel.Base.ContextFun import Wumpus.Basic.Kernel.Base.DrawingContext+import Wumpus.Basic.Kernel.Objects.Anchors+import Wumpus.Basic.Kernel.Objects.Concat import Wumpus.Basic.Kernel.Objects.TraceDrawing import Wumpus.Core -- package: wumpus-core@@ -82,45 +58,45 @@ import Data.AdditiveGroup -- package: vector-space import Data.AffineSpace -import Control.Applicative-import Data.List ( foldl' )+import Data.Monoid --- Note - PosGraphic should take priority for the good names. --- | A /Contextual Picture/.+-- | A /Contextual/ Picture. -- +-- > CtxPicture = DrawingContext -> Maybe Picture+-- -- This type corresponds to the 'Picture' type in Wumpus-Core, but -- it is embedded with a 'DrawingContext' (for font properties, --- fill colour etc.). So it is a function --- /from DrawingContext to Picture/.------ Internally the result is actually a (Maybe Picture) and not a --- Picture, this is a trick to promote the extraction from --- possibly empty drawings (created by TraceDrawing) to the --- top-level of the type hierarchy where client code can deal --- with empty drawings explicitly (empty Pictures cannot be --- rendered by Wumpus-Core).+-- fill colour etc.). The DrawingContext is embedded so that font+-- metrics - loaded in @IO@ can be passed into the pure world of+-- 'TraceDrawing'. ----- > a `oplus` b+-- Internally a /context picture/ is a function from +-- 'DrawingContext' to @(Maybe Picture)@. The @Maybe@ represents+-- that it is possible to construct empty Pictures, even though+-- @Wumpus-Core@ cannot render them. Just as the DrawingContext+-- pushes font-metrics from the IO to the pure world, the Maybe+-- lifts the problem of unrenderable Pictures into the API where+-- client code must deal with it explicitly. ----- The 'OPlus' (semigroup) instance for 'CtxPicture' draws picture --- a in front of picture b in the z-order, neither picture is --- moved. (Usually the picture composition operators in this --- module move the second picture aligning it somehow with the --- first).+-- (In practice, it is very unlikely a program will create empty +-- pictures and @runCtxPictureU@ can be used without worry).+-- +-- +-- Note - pictures are fixed to the unit @Double@ (representing +-- PostScript points). Pictures are intentionally unsophisticated,+-- any fine grained control of units should be delegated to the +-- elements that build the picture (Graphics, LocGraphics, etc.). ---newtype CtxPicture u = CtxPicture { getCtxPicture :: CF (Maybe (Picture u)) }+newtype CtxPicture = CtxPicture { + getCtxPicture :: DrawingContext -> Maybe Picture } --- | Version of CtxPicture specialized to Double for the unit type.----type DCtxPicture = CtxPicture Double+type instance DUnit CtxPicture = Double -type instance DUnit (CtxPicture u) = u - -- | 'runCtxPicture' : @ drawing_ctx * ctx_picture -> Maybe Picture @ -- -- Run a 'CtxPicture' with the supplied 'DrawingContext' @@ -131,9 +107,10 @@ -- result is wrapped within a Maybe. This delegates reponsibility -- for handling empty pictures to client code. ---runCtxPicture :: DrawingContext -> CtxPicture u -> Maybe (Picture u)-runCtxPicture ctx drw = runCF ctx (getCtxPicture drw) +runCtxPicture :: DrawingContext -> CtxPicture -> Maybe Picture+runCtxPicture ctx drw = getCtxPicture drw ctx + -- | 'runCtxPictureU' : @ drawing_ctx * ctx_picture -> Picture @ -- -- /Unsafe/ version of 'runCtxPicture'.@@ -141,7 +118,7 @@ -- This function throws a runtime error when supplied with an -- empty CtxPicture. ---runCtxPictureU :: DrawingContext -> CtxPicture u -> Picture u+runCtxPictureU :: DrawingContext -> CtxPicture -> Picture runCtxPictureU ctx df = maybe fk id $ runCtxPicture ctx df where fk = error "runCtxPictureU - empty CtxPicture." @@ -151,139 +128,76 @@ -- -- Transform a 'TraceDrawing' into a 'CtxPicture'. ---drawTracing :: (Real u, Floating u, FromPtSize u) - => TraceDrawing u a -> CtxPicture u-drawTracing mf = CtxPicture $ - drawingCtx >>= \ctx -> return (liftToPictureMb $ execTraceDrawing ctx mf)-+drawTracing :: TraceDrawing u a -> CtxPicture+drawTracing mf = + CtxPicture $ \ctx -> liftToPictureMb $ execTraceDrawing ctx mf --- Note - cannot get an answer from a TraceDrawing with this --- CtxPicture type. There is nowhere to put the answer in the type.+-- | 'udrawTracing' : @ scalar_unit_value * trace_drawing -> CtxPicture @ ----- If the type was extended:+-- Variant of 'drawTracing' with a phantom first argument - the +-- phantom identifies the unit type of the 'TraceDrawing'. It is +-- not scurtinized at the value level. ----- > newtype CtxPicture u a = CtxPicture { getCtxPicture :: CF (a, Maybe (Picture u))) } ----- It would make things difficult for the drawing composition --- operators. @a@ could be monoidial but are there any types of --- a where this would be useful (rather than just making things --- more complicated)? ---+udrawTracing :: u -> TraceDrawing u a -> CtxPicture+udrawTracing _ mf = + CtxPicture $ \ctx -> liftToPictureMb $ execTraceDrawing ctx mf --- | 'clipCtxPicture' : @ path * ctx_picture -> CtxPicture @------ Clip a picture with a path.--- -clipCtxPicture :: (Num u, Ord u) => PrimPath u -> CtxPicture u -> CtxPicture u-clipCtxPicture cpath = mapCtxPicture (clip cpath) --- Note - it seems preferable to clip a smaller type in the --- hierarchy than CtxPicture. But which one Graphic, TraceDrawing? --- ...--- + -- | 'mapCtxPicture' : @ trafo * ctx_picture -> CtxPicture @ -- -- Apply a picture transformation function to the 'Picture' -- warpped in a 'CtxPicture'. ---mapCtxPicture :: (Picture u -> Picture u) -> CtxPicture u -> CtxPicture u-mapCtxPicture pf = CtxPicture . fmap (fmap pf) . getCtxPicture+mapCtxPicture :: (Picture -> Picture) -> CtxPicture -> CtxPicture+mapCtxPicture pf pic1 = CtxPicture $ \ctx -> fmap pf $ getCtxPicture pic1 ctx ----------------------------------------------------------------------------------+-- Affine instances -instance (Real u, Floating u) => Rotate (CtxPicture u) where - rotate ang = mapCtxPicture (rotate ang)+instance Rotate CtxPicture where + rotate ang = mapCtxPicture (rotate ang) -instance (Real u, Floating u) => RotateAbout (CtxPicture u) where- rotateAbout r pt = mapCtxPicture (rotateAbout r pt)+instance RotateAbout CtxPicture where+ rotateAbout ang pt = mapCtxPicture (rotateAbout ang pt) -instance (Num u, Ord u) => Scale (CtxPicture u) where- scale sx sy = mapCtxPicture (scale sx sy)+instance Scale CtxPicture where+ scale sx sy = mapCtxPicture (scale sx sy) -instance (Num u, Ord u) => Translate (CtxPicture u) where- translate dx dy = mapCtxPicture (translate dx dy)+instance Translate CtxPicture where+ translate dx dy = mapCtxPicture (translate dx dy) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- Extract anchors--boundaryExtr :: (BoundingBox u -> a) -> Picture u -> a-boundaryExtr f = f . boundary---- Operations on bounds---- | The center of a picture.----boundaryCtr :: Fractional u => Picture u -> Point2 u-boundaryCtr = boundaryExtr center------ | Extract the mid point of the top edge.----boundaryN :: Fractional u => Picture u -> Point2 u-boundaryN = boundaryExtr north---- | Extract the mid point of the bottom edge.----boundaryS :: Fractional u => Picture u -> Point2 u-boundaryS = boundaryExtr south---- | Extract the mid point of the left edge.----boundaryE :: Fractional u => Picture u -> Point2 u-boundaryE = boundaryExtr east+-- Monoid --- | Extract the mid point of the right edge.----boundaryW :: Fractional u => Picture u -> Point2 u-boundaryW = boundaryExtr west+instance Monoid CtxPicture where+ mempty = CtxPicture $ \_ -> Nothing+ mappend = moveSnd $ \_ _ -> V2 0 0 --- | Extract the top-left corner.----boundaryNW :: Fractional u => Picture u -> Point2 u-boundaryNW = boundaryExtr northwest---- | Extract the top-right corner.----boundaryNE :: Picture u -> Point2 u-boundaryNE = boundaryExtr ur_corner---- | Extract the bottom-left corner.----boundarySW :: Picture u -> Point2 u-boundarySW = boundaryExtr ll_corner---- | Extract the bottom-right corner.----boundarySE :: Fractional u => Picture u -> Point2 u-boundarySE = boundaryExtr southeast+--------------------------------------------------------------------------------+-- Extract /planes/. -boundaryLeftEdge :: Picture u -> u-boundaryLeftEdge = boundaryExtr (point_x . ll_corner)+leftEdge :: BoundingBox Double -> Double+leftEdge = point_x . ll_corner -boundaryRightEdge :: Picture u -> u-boundaryRightEdge = boundaryExtr (point_x . ur_corner)+rightEdge :: BoundingBox Double -> Double+rightEdge = point_x . ur_corner -boundaryBottomEdge :: Picture u -> u-boundaryBottomEdge = boundaryExtr (point_y . ll_corner)+bottomEdge :: BoundingBox Double -> Double+bottomEdge = point_y . ll_corner -boundaryTopEdge :: Picture u -> u-boundaryTopEdge = boundaryExtr (point_y . ur_corner)-+topEdge :: BoundingBox Double -> Double+topEdge = point_y . ur_corner @@ -302,14 +216,12 @@ -- ambiguous as when used as binary operators). -- -cxpConcat :: (Picture u -> Picture u -> Picture u) - -> CtxPicture u -> CtxPicture u -> CtxPicture u-cxpConcat op a b = CtxPicture $ mbpostcomb op (getCtxPicture a) (getCtxPicture b) --mbpostcomb :: (a -> a -> a) -> CF (Maybe a) -> CF (Maybe a) -> CF (Maybe a)-mbpostcomb op = liftA2 fn +combineP2 :: (Picture -> Picture -> Picture) + -> CtxPicture -> CtxPicture -> CtxPicture+combineP2 op mf mg = + CtxPicture $ \ctx -> fn (getCtxPicture mf ctx) (getCtxPicture mg ctx) where fn (Just a) (Just b) = Just $ a `op` b fn a Nothing = a@@ -327,95 +239,81 @@ -- --- Picture /mega-combiner/ - moves only the second argument aka the --- right picture.----megaCombR :: (Num u, Ord u)- => (Picture u -> a) -> (Picture u -> a) - -> (a -> a -> Picture u -> Picture u) - -> CtxPicture u -> CtxPicture u- -> CtxPicture u-megaCombR qL qR trafoR = cxpConcat fn+moveSnd :: (DBoundingBox -> DBoundingBox -> DVec2) + -> CtxPicture -> CtxPicture+ -> CtxPicture+moveSnd mkV = combineP2 fn where- fn pic1 pic2 = let a = qL pic1- b = qR pic2- p2 = trafoR a b pic2- in pic1 `picOver` p2+ fn pl pr = let v1 = mkV (boundary pl) (boundary pr)+ in pl `picOver` (picMoveBy pr v1) +++ -- | > a `oplus` b -- -- Place \'drawing\' a over b. The idea of @over@ here is in -- terms z-ordering, nither picture a or b are actually moved. ---instance (Num u, Ord u) => OPlus (CtxPicture u) where- oplus = cxpConcat picOver+instance OPlus CtxPicture where+ oplus = moveSnd $ \_ _ -> V2 0 0 --- | 'cxpBeneath' : @ ctx_picture1 * ctx_picture2 -> CtxPicture @--- --- > a `cxpBeneath` b------ Similarly @beneath@ draws the first picture behind the second --- picture in the z-order, neither picture is moved.----cxpBeneath :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u-cxpBeneath = flip oplus +instance ZConcat CtxPicture where+ superior = oplus+ anterior = flip oplus -------------------------------------------------------------------------------- -- Composition -infixr 5 `cxpDown`-infixr 6 `cxpRight`, `cxpUniteCenter` +infixr 6 `uniteCenter` + -- | Draw @a@, move @b@ so its center is at the same center as -- @a@, @b@ is drawn over underneath in the zorder. -- -- > a `cxpUniteCenter` b -- -cxpUniteCenter :: (Fractional u, Ord u) - => CtxPicture u -> CtxPicture u -> CtxPicture u-cxpUniteCenter = megaCombR boundaryCtr boundaryCtr moveFun- where- moveFun p1 p2 pic = let v = p1 .-. p2 in pic `picMoveBy` v-+uniteCenter :: CtxPicture -> CtxPicture -> CtxPicture+uniteCenter = moveSnd $ \a b -> center a .-. center b -- -- Are combinator names less ambiguous if they name direction -- rather than position? -- +instance Concat CtxPicture where+ hconcat = cxpRight+ vconcat = cxpBelow++ -- | > a `cxpRight` b -- -- Horizontal composition - position picture @b@ to the right of -- picture @a@. -- -cxpRight :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u-cxpRight = megaCombR boundaryRightEdge boundaryLeftEdge moveFun- where - moveFun a b pic = pic `picMoveBy` hvec (a - b)-+cxpRight :: CtxPicture -> CtxPicture -> CtxPicture+cxpRight = moveSnd $ \a b -> hvec $ rightEdge a - leftEdge b --- | > a `cxpDown` b+-- | > a `cxpBelow` b -- -- Vertical composition - position picture @b@ /down/ from picture -- @a@. ---cxpDown :: (Num u, Ord u) => CtxPicture u -> CtxPicture u -> CtxPicture u-cxpDown = megaCombR boundaryBottomEdge boundaryTopEdge moveFun- where - moveFun a b drw = drw `picMoveBy` vvec (a - b)+cxpBelow :: CtxPicture -> CtxPicture -> CtxPicture+cxpBelow = moveSnd $ \a b -> vvec $ bottomEdge a - topEdge b -- | Center the picture at the supplied point. ---cxpCenteredAt :: (Fractional u, Ord u) => CtxPicture u -> Point2 u -> CtxPicture u-cxpCenteredAt d (P2 x y) = mapCtxPicture fn d+centeredAt :: CtxPicture -> DPoint2 -> CtxPicture+centeredAt pic (P2 x y) = mapCtxPicture fn pic where fn p = let bb = boundary p dx = x - (boundaryWidth bb * 0.5)@@ -424,37 +322,12 @@ --- | 'cxpRow' : @ ctx_picture1 * [ctx_picture] -> CtxPicture @--- --- Make a row of pictures concatenating them horizontally.--- --- Note - this function is in /destructor form/. As Wumpus cannot--- make a Picture from an empty list of Pictures, --- /destructor form/ decomposes the list into the @head@ and the --- @rest@ in the function signature, rather than take a possibly--- empty list and have to throw an error.--- -cxpRow :: (Real u, Floating u, FromPtSize u) - => CtxPicture u -> [CtxPicture u] -> CtxPicture u-cxpRow = foldl' cxpRight ---- | 'cxpColumn' : @ ctx_picture1 * [ctx_picture] -> CtxPicture @--- --- Make a column of pictures concatenating them vertically.--- --- Note - this function is in /destructor form/.----cxpColumn :: (Real u, Floating u, FromPtSize u) - => CtxPicture u -> [CtxPicture u] -> CtxPicture u-cxpColumn = foldl' cxpDown---- -------------------------------------------------------------------------------- -+instance CatSpace CtxPicture where+ hspace = cxpRightSep+ vspace = cxpDownSep -- | > cxpRightSep n a b@@ -462,12 +335,8 @@ -- Horizontal composition - move @b@, placing it to the right -- of @a@ with a horizontal gap of @n@ separating the pictures. ---cxpRightSep :: (Num u, Ord u) => u -> CtxPicture u -> CtxPicture u -> CtxPicture u-cxpRightSep n = megaCombR boundaryRightEdge boundaryLeftEdge moveFun- where- moveFun a b pic = pic `picMoveBy` hvec (n + a - b)-- +cxpRightSep :: Double -> CtxPicture -> CtxPicture -> CtxPicture+cxpRightSep n = moveSnd $ \a b -> hvec $ n + (rightEdge a - leftEdge b) @@ -476,58 +345,27 @@ -- Vertical composition - move @b@, placing it below @a@ with a -- vertical gap of @n@ separating the pictures. ---cxpDownSep :: (Num u, Ord u) - => u -> CtxPicture u -> CtxPicture u -> CtxPicture u-cxpDownSep n = megaCombR boundaryBottomEdge boundaryTopEdge moveFun- where - moveFun a b pic = pic `picMoveBy` vvec (a - b - n)------ | > picRowSep n x xs------ Concatenate the list of pictures @xs@ horizontally with --- @hspace@ starting at @x@. The pictures are interspersed with --- spaces of @n@ units.----cxpRowSep :: (Real u, Floating u, FromPtSize u) - => u -> CtxPicture u -> [CtxPicture u] -> CtxPicture u-cxpRowSep n = foldl' (cxpRightSep n)------ | > vsepPic n xs------ Concatenate the list of pictures @xs@ vertically with --- @vspace@ starting at @x@. The pictures are interspersed with --- spaces of @n@ units.----cxpColumnSep :: (Real u, Floating u, FromPtSize u) - => u -> CtxPicture u -> [CtxPicture u] -> CtxPicture u-cxpColumnSep n = foldl' (cxpDownSep n)+cxpDownSep :: Double -> CtxPicture -> CtxPicture -> CtxPicture+cxpDownSep n = moveSnd $ \a b -> vvec $ bottomEdge a - (topEdge b + n) -------------------------------------------------------------------------------- -- Aligning pictures -alignMove :: (Num u, Ord u) => Point2 u -> Point2 u -> Picture u -> Picture u-alignMove p1 p2 pic = pic `picMoveBy` (p1 .-. p2) ---- Note - these don\'t conform to the naming convention, but using --- /Right/ in the names would be confusing with alignment.-+instance Align CtxPicture where+ halign = cxpAlignH+ valign = cxpAlignV -- | > cxpAlignH align a b -- -- Horizontal composition - move @b@, placing it to the right -- of @a@ and align it with the top, center or bottom of @a@. -- -cxpAlignH :: (Fractional u, Ord u) - => HAlign -> CtxPicture u -> CtxPicture u -> CtxPicture u-cxpAlignH HTop = megaCombR boundaryNE boundaryNW alignMove-cxpAlignH HCenter = megaCombR boundaryE boundaryW alignMove-cxpAlignH HBottom = megaCombR boundarySE boundarySW alignMove+cxpAlignH :: HAlign -> CtxPicture -> CtxPicture -> CtxPicture+cxpAlignH HTop = moveSnd $ \a b -> northeast a .-. northwest b+cxpAlignH HCenter = moveSnd $ \a b -> east a .-. west b+cxpAlignH HBottom = moveSnd $ \a b -> southeast a .-. southwest b -- | > cxpAlignV align a b@@ -535,81 +373,41 @@ -- Vertical composition - move @b@, placing it below @a@ -- and align it with the left, center or right of @a@. -- -cxpAlignV :: (Fractional u, Ord u) - => VAlign -> CtxPicture u -> CtxPicture u -> CtxPicture u-cxpAlignV VLeft = megaCombR boundarySW boundaryNW alignMove-cxpAlignV VCenter = megaCombR boundaryS boundaryN alignMove-cxpAlignV VRight = megaCombR boundarySE boundaryNE alignMove+cxpAlignV :: VAlign -> CtxPicture -> CtxPicture -> CtxPicture+cxpAlignV VLeft = moveSnd $ \a b -> southwest a .-. northwest b+cxpAlignV VCenter = moveSnd $ \a b -> south a .-. north b+cxpAlignV VRight = moveSnd $ \a b -> southeast a .-. northeast b -alignMove2 :: (Num u, Ord u) - => Vec2 u -> Point2 u -> Point2 u -> Picture u -> Picture u-alignMove2 v p1 p2 pic = pic `picMoveBy` (v ^+^ (p1 .-. p2))--+instance AlignSpace CtxPicture where+ halignSpace = cxpAlignSpaceH+ valignSpace = cxpAlignSpaceV --- | > cxpAlignSepH align sep a b+-- | > cxpAlignSpaceH align sep a b -- -- Spacing version of 'cxpAlignH' - move @b@ to the right of @a@ -- separated by @sep@ units, align @b@ according to @align@. -- -cxpAlignSepH :: (Fractional u, Ord u) - => HAlign -> u -> CtxPicture u -> CtxPicture u -> CtxPicture u-cxpAlignSepH align dx = go align+cxpAlignSpaceH :: HAlign -> Double -> CtxPicture -> CtxPicture -> CtxPicture+cxpAlignSpaceH align dx = go align where- go HTop = megaCombR boundaryNE boundaryNW (alignMove2 (hvec dx))- go HCenter = megaCombR boundaryE boundaryW (alignMove2 (hvec dx))- go HBottom = megaCombR boundarySE boundarySW (alignMove2 (hvec dx))+ mv f g = moveSnd $ \a b -> hvec dx ^+^ (f a .-. g b)+ go HTop = mv northeast northwest+ go HCenter = mv east west + go HBottom = mv southeast southwest --- | > cxpAlignSepV align sep a b+-- | > cxpAlignSpaceV align sep a b -- -- Spacing version of alignV - move @b@ below @a@ -- separated by @sep@ units, align @b@ according to @align@. -- -cxpAlignSepV :: (Fractional u, Ord u) - => VAlign -> u -> CtxPicture u -> CtxPicture u -> CtxPicture u-cxpAlignSepV align dy = go align+cxpAlignSpaceV :: VAlign -> Double -> CtxPicture -> CtxPicture -> CtxPicture+cxpAlignSpaceV align dy = go align where- go VLeft = megaCombR boundarySW boundaryNW (alignMove2 $ vvec (-dy)) - go VCenter = megaCombR boundaryS boundaryN (alignMove2 $ vvec (-dy)) - go VRight = megaCombR boundarySE boundaryNE (alignMove2 $ vvec (-dy))----- | Variant of 'cxpRow' that aligns the pictures as well as--- concatenating them.----cxpAlignRow :: (Real u, Floating u, FromPtSize u) - => HAlign -> CtxPicture u-> [CtxPicture u] -> CtxPicture u-cxpAlignRow ha = foldl' (cxpAlignH ha)------ | Variant of 'cxpColumn' that aligns the pictures as well as--- concatenating them.----cxpAlignColumn :: (Real u, Floating u, FromPtSize u) - => VAlign -> CtxPicture u -> [CtxPicture u] -> CtxPicture u-cxpAlignColumn va = foldl' (cxpAlignV va)----- | Variant of 'cxpRow' that aligns the pictures as well as--- concatenating and spacing them.----cxpAlignRowSep :: (Real u, Floating u, FromPtSize u) - => HAlign -> u -> CtxPicture u -> [CtxPicture u] - -> CtxPicture u-cxpAlignRowSep ha n = foldl' (cxpAlignSepH ha n)----- | Variant of 'cxpColumn' that aligns the pictures as well as--- concatenating and spacing them.----cxpAlignColumnSep :: (Real u, Floating u, FromPtSize u) - => VAlign -> u -> CtxPicture u -> [CtxPicture u] - -> CtxPicture u-cxpAlignColumnSep va n = foldl' (cxpAlignSepV va n) --+ mv f g = moveSnd $ \a b -> vvec (-dy) ^+^ (f a .-. g b)+ go VLeft = mv southwest northwest + go VCenter = mv south north + go VRight = mv southeast northeast
src/Wumpus/Basic/Kernel/Objects/Displacement.hs view
@@ -1,9 +1,11 @@+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# OPTIONS -Wall #-} -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Basic.Kernel.Objects.Displacement--- Copyright : (c) Stephen Tetley 2010+-- Copyright : (c) Stephen Tetley 2010-2011 -- License : BSD3 -- -- Maintainer : stephen.tetley@gmail.com@@ -17,8 +19,6 @@ module Wumpus.Basic.Kernel.Objects.Displacement ( -- -- * Moving points and angles PointDisplace , ThetaDisplace , ThetaPointDisplace@@ -27,42 +27,65 @@ , moveStart , moveStartTheta , moveStartThetaPoint- , moveStartThetaAngle+ , moveStartThetaIncl , displace , displaceVec , displaceH , displaceV - , northwards- , southwards - , eastwards- , westwards + , disp_up+ , disp_down+ , disp_left+ , disp_right - , northeastwards- , northwestwards- , southeastwards- , southwestwards+ , disp_up_left+ , disp_up_right+ , disp_down_left+ , disp_down_right+ + , disp_north+ , disp_south+ , disp_east+ , disp_west + , disp_northeast+ , disp_northwest+ , disp_southeast+ , disp_southwest++ , displaceParallel , displacePerpendicular , displaceOrtho - , thetaNorthwards- , thetaSouthwards - , thetaEastwards- , thetaWestwards + , adisp_north+ , adisp_south+ , adisp_east+ , adisp_west - , thetaNortheastwards- , thetaNorthwestwards- , thetaSoutheastwards- , thetaSouthwestwards+ , adisp_northeast+ , adisp_northwest+ , adisp_southeast+ , adisp_southwest + , centerRelative+ , left_of+ , right_of+ , above_left_of+ , above_right_of+ , below_left_of+ , below_right_of+ ) where +import Wumpus.Basic.Kernel.Base.BaseDefs import Wumpus.Basic.Kernel.Base.ContextFun+import Wumpus.Basic.Kernel.Base.QueryDC+import Wumpus.Basic.Kernel.Objects.Anchors+import Wumpus.Basic.Kernel.Objects.Basis import Wumpus.Core -- package: wumpus-core @@ -70,8 +93,6 @@ ------------------------------------------------------------------------------------ Displacing points -- | 'PointDisplace' is a type representing functions -- @from Point to Point@.@@ -83,6 +104,8 @@ type PointDisplace u = Point2 u -> Point2 u ++ -- | 'ThetaDisplace' is a type representing functions -- @from Radian to Radian@. --@@ -100,39 +123,44 @@ -- with an implicit angle representing the direction of the line -- at the arrow tip. ---type ThetaPointDisplace u = Radian -> PointDisplace u+type ThetaPointDisplace u = Radian -> Point2 u -> Point2 u +--------------------------------------------------------------------------------+-- Displacing points and inclination --- | Move the start-point of a 'LocCF' with the supplied +++-- | Move the start-point of a 'LocQuery' with the supplied -- displacement function. ---moveStart :: PointDisplace u -> LocCF u a -> LocCF u a-moveStart f ma = promoteR1 $ \pt -> apply1R1 ma (f pt)+moveStart :: PointDisplace u -> LocQuery u a -> LocQuery u a+moveStart f ma = domMap1 f ma --- | Move the start-point of a 'LocThetaCF' with the supplied +-- | Move the start-point of a 'LocThetaQuery' with the supplied -- displacement function. ---moveStartTheta :: ThetaPointDisplace u -> LocThetaCF u a -> LocThetaCF u a-moveStartTheta f ma = promoteR2 $ \pt theta -> let p2 = f theta pt - in apply2R2 ma p2 theta+moveStartTheta :: ThetaPointDisplace u + -> LocThetaQuery u a -> LocThetaQuery u a+moveStartTheta f cf = consCF $ \ctx -> + (\pt ang -> let f1 = runCF ctx cf in f1 (f ang pt) ang) -- | Move the start-point of a 'LocThetaCF' with the supplied -- displacement function. ---moveStartThetaPoint :: PointDisplace u -> LocThetaCF u a -> LocThetaCF u a-moveStartThetaPoint f ma = promoteR2 $ \pt theta -> apply2R2 ma (f pt) theta+moveStartThetaPoint :: PointDisplace u + -> LocThetaQuery u a -> LocThetaQuery u a+moveStartThetaPoint f = domMap2 f id -- | Change the inclination of a 'LocThetaCF' with the supplied -- displacement function. ---moveStartThetaAngle :: ThetaDisplace -> LocThetaCF u a -> LocThetaCF u a-moveStartThetaAngle f ma = promoteR2 $ \pt theta -> apply2R2 ma pt (f theta)-+moveStartThetaIncl :: ThetaDisplace -> LocThetaQuery u a -> LocThetaQuery u a+moveStartThetaIncl f = domMap2 id f --------------------------------------------------------------------------------@@ -173,36 +201,71 @@ displaceV dy (P2 x y) = P2 x (y+dy) --- Cardinal displacement +disp_up :: Num u => u -> PointDisplace u+disp_up = displaceV -northwards :: Num u => u -> PointDisplace u-northwards = displaceV+disp_down :: Num u => u -> PointDisplace u+disp_down = displaceV . negate +disp_left :: Num u => u -> PointDisplace u+disp_left = displaceH . negate -southwards :: Num u => u -> PointDisplace u-southwards = displaceV . negate+disp_right :: Num u => u -> PointDisplace u+disp_right = displaceH -eastwards :: Num u => u -> PointDisplace u-eastwards = displaceH -westwards :: Num u => u -> PointDisplace u-westwards = displaceH . negate+-- diagonals - these are different to cardinals which have the+-- hypotenuese as the dist.+-- -northeastwards :: Floating u => u -> PointDisplace u-northeastwards = displaceVec . avec (0.25 * pi)+disp_up_left :: Num u => u -> PointDisplace u+disp_up_left u = displaceVec (V2 (-u) u) -northwestwards :: Floating u => u -> PointDisplace u-northwestwards = displaceVec . avec (0.75 * pi)+disp_up_right :: Num u => u -> PointDisplace u+disp_up_right u = displaceVec (V2 u u) -southeastwards :: Floating u => u -> PointDisplace u-southeastwards = displaceVec . avec (1.75 * pi)+disp_down_left :: Num u => u -> PointDisplace u+disp_down_left u = displaceVec (V2 (-u) (-u)) -southwestwards :: Floating u => u -> PointDisplace u-southwestwards = displaceVec . avec (1.25 * pi)+disp_down_right :: Num u => u -> PointDisplace u+disp_down_right u = displaceVec (V2 u (-u)) ++++++-- Cardinal displacement ++disp_north :: Num u => u -> PointDisplace u+disp_north = displaceV+++disp_south :: Num u => u -> PointDisplace u+disp_south = displaceV . negate++disp_east :: Num u => u -> PointDisplace u+disp_east = displaceH++disp_west :: Num u => u -> PointDisplace u+disp_west = displaceH . negate++disp_northeast :: Floating u => u -> PointDisplace u+disp_northeast = displaceVec . avec (0.25 * pi)++disp_northwest :: Floating u => u -> PointDisplace u+disp_northwest = displaceVec . avec (0.75 * pi)++disp_southeast :: Floating u => u -> PointDisplace u+disp_southeast = displaceVec . avec (1.75 * pi)++disp_southwest :: Floating u => u -> PointDisplace u+disp_southwest = displaceVec . avec (1.25 * pi)++ -------------------------------------------------------------------------------- -- ThetaPointDisplace functions @@ -241,37 +304,104 @@ displaceParallel x theta . displacePerpendicular y theta -thetaNorthwards :: Floating u => u -> ThetaPointDisplace u-thetaNorthwards = displacePerpendicular+adisp_north :: Floating u => u -> ThetaPointDisplace u+adisp_north = displacePerpendicular -thetaSouthwards :: Floating u => u -> ThetaPointDisplace u-thetaSouthwards = displacePerpendicular . negate+adisp_south :: Floating u => u -> ThetaPointDisplace u+adisp_south = displacePerpendicular . negate -thetaEastwards :: Floating u => u -> ThetaPointDisplace u-thetaEastwards = displaceParallel+adisp_east :: Floating u => u -> ThetaPointDisplace u+adisp_east = displaceParallel -thetaWestwards :: Floating u => u -> ThetaPointDisplace u-thetaWestwards = displaceParallel . negate+adisp_west :: Floating u => u -> ThetaPointDisplace u+adisp_west = displaceParallel . negate -thetaNortheastwards :: Floating u => u -> ThetaPointDisplace u-thetaNortheastwards d = - \theta pt -> pt .+^ avec (circularModulo $ theta + (0.25*pi)) d+adisp_northeast :: Floating u => u -> ThetaPointDisplace u+adisp_northeast d = \ang pt -> pt .+^ avec (ang + (0.25*pi)) d -thetaNorthwestwards :: Floating u => u -> ThetaPointDisplace u-thetaNorthwestwards d = - \theta pt -> pt .+^ avec (circularModulo $ theta + (0.75*pi)) d+adisp_northwest :: Floating u => u -> ThetaPointDisplace u+adisp_northwest d = \ang pt -> pt .+^ avec (ang + (0.75*pi)) d -thetaSoutheastwards :: Floating u => u -> ThetaPointDisplace u-thetaSoutheastwards d = - \theta pt -> pt .+^ avec (circularModulo $ theta + (1.75*pi)) d+adisp_southeast :: Floating u => u -> ThetaPointDisplace u+adisp_southeast d = \ang pt -> pt .+^ avec (ang + (1.75*pi)) d -thetaSouthwestwards :: Floating u => u -> ThetaPointDisplace u-thetaSouthwestwards d = - \theta pt -> pt .+^ avec (circularModulo $ theta + (1.25*pi)) d+adisp_southwest :: Floating u => u -> ThetaPointDisplace u+adisp_southwest d = \ang pt -> pt .+^ avec (ang + (1.25*pi)) d++++--------------------------------------------------------------------------------++-- | Absolute units.+-- +centerRelative :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) + => (Int,Int) -> a -> Query (Anchor u)+centerRelative coord a = snapmove coord >>= \v -> return $ center a .+^ v++-- TODO - These are really for Anchors.+--+-- Should the have a separate module or be rolled into the same+-- module as the classes?+--++-- | Value is 1 snap unit right.+--+-- This function should be considered obsolete, pending a +-- re-think.+-- +right_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) + => a -> Query (Anchor u)+right_of = centerRelative (1,0)++-- | Value is 1 snap move left.+--+-- This function should be considered obsolete, pending a +-- re-think.+-- +left_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) + => a -> Query (Anchor u)+left_of = centerRelative ((-1),0)++-- | Value is 1 snap move up, 1 snap move right.+--+-- This function should be considered obsolete, pending a +-- re-think.+-- +above_right_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) + => a -> Query (Anchor u)+above_right_of = centerRelative (1,1)++-- | Value is 1 snap move below, 1 snap move right.+--+-- This function should be considered obsolete, pending a +-- re-think.+-- +below_right_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) + => a -> Query (Anchor u)+below_right_of = centerRelative (1, (-1))++-- | Value is 1 snap move up, 1 snap move left.+--+-- This function should be considered obsolete, pending a +-- re-think.+-- +above_left_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) + => a -> Query (Anchor u)+above_left_of = centerRelative ((-1),1)++-- | Value is 1 snap move down, 1 snap move left.+--+-- This function should be considered obsolete, pending a +-- re-think.+-- +below_left_of :: (CenterAnchor a, Fractional u, InterpretUnit u, u ~ DUnit a) + => a -> Query (Anchor u)+below_left_of = centerRelative ((-1),(-1))+
src/Wumpus/Basic/Kernel/Objects/DrawingPrimitives.hs view
@@ -1,11 +1,9 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeSynonymInstances #-} {-# OPTIONS -Wall #-} -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Basic.Kernel.Objects.DrawingPrimitives--- Copyright : (c) Stephen Tetley 2010-2011+-- Copyright : (c) Stephen Tetley 2011 -- License : BSD3 -- -- Maintainer : stephen.tetley@gmail.com@@ -22,28 +20,34 @@ module Wumpus.Basic.Kernel.Objects.DrawingPrimitives ( - -- * Paths- locPath- , emptyLocPath + -- * Prim Paths+ locPP++ , emptyLocPP+ , vertexPP+ , curvePP+ , openStroke , closedStroke , filledPath , borderedPath -- * Text- , textline- , rtextline- , escapedline- , rescapedline+ , plainTextLine+ , rplainTextLine+ , escTextLine+ , rescTextLine - , hkernline- , vkernline+ , KernChar+ , hkernLine+ , vkernLine -- * Lines , straightLine- , straightLineGraphic- , curveGraphic+ , locStraightLine+ , curvedLine+ , straightConnector -- * Circles , strokedCircle@@ -55,7 +59,6 @@ , rstrokedEllipse , filledEllipse , rfilledEllipse- , borderedEllipse , rborderedEllipse @@ -75,55 +78,111 @@ ) where +import Wumpus.Basic.Kernel.Base.BaseDefs import Wumpus.Basic.Kernel.Base.ContextFun import Wumpus.Basic.Kernel.Base.QueryDC import Wumpus.Basic.Kernel.Base.WrappedPrimitive-import Wumpus.Basic.Kernel.Objects.Graphic+import Wumpus.Basic.Kernel.Objects.Basis+import Wumpus.Basic.Kernel.Objects.Connector+import Wumpus.Basic.Kernel.Objects.Image+import Wumpus.Basic.Kernel.Objects.LocImage+import Wumpus.Basic.Kernel.Objects.LocThetaImage import Wumpus.Core -- package: wumpus-core -import Data.AffineSpace -- package: vector-space- import Control.Applicative +-- Helpers --- Helper----graphicAns :: Primitive u -> (UNil u, PrimGraphic u)-graphicAns p = (uNil, primGraphic p) +norm2 :: InterpretUnit u => u -> u -> Query (Double,Double)+norm2 a b = (,) <$> normalizeCtx a <*> normalizeCtx b +makeGraphic :: Query a -> (a -> Primitive) -> Graphic u+makeGraphic qy fn = qy >>= \a -> return $ graphicAns $ prim1 $ fn a+++makeLocGraphic :: InterpretUnit u + => Query a -> (a -> DPoint2 -> Primitive) -> LocGraphic u+makeLocGraphic qy fn = promoteR1 $ \pt -> + normalizeCtxF pt >>= \dpt ->+ qy >>= \a -> return $ graphicAns $ prim1 $ fn a dpt++makeLocThetaGraphic :: InterpretUnit u + => Query a -> (a -> DPoint2 -> Radian -> Primitive) + -> LocThetaGraphic u+makeLocThetaGraphic qy fn = promoteR2 $ \pt ang -> + normalizeCtxF pt >>= \dpt ->+ qy >>= \a -> return $ graphicAns $ prim1 $ fn a dpt ang+++ -------------------------------------------------------------------------------- -- Paths --- | 'locPath' : @ [next_vector] -> (Point2 ~> PrimPath) @+-- Note - naming convention, the PP suffix is to avoid confusion +-- with the Path data type in Wumpus-Drawing. These paths are+-- considered more /internal/. ----- Create a path 'LocCF' - i.e. a functional type ++-- | 'locPP' : @ [next_vector] -> LocQuery PrimPath @+--+-- Create a path 'LocQuery' - i.e. a functional type -- /from Point to PrimPath/. -- -- This is the analogue to 'vectorPath' in @Wumpus-Core@, but the -- result is produced /within/ the 'DrawingContext'. ---locPath :: Num u => [Vec2 u] -> LocCF u (PrimPath u)-locPath vs = promoteR1 $ \pt -> pure $ vectorPath pt vs+locPP :: InterpretUnit u => [Vec2 u] -> LocQuery u PrimPath+locPP vs = promoteR1 $ \ pt ->+ vectorPrimPath <$> normalizeCtxF pt <*> mapM normalizeCtxF vs --- | 'emptyLocPath' : @ (Point ~> PrimPath) @+++-- | 'emptyLocPP' : @ (Point ~> PrimPath) @ ----- Create an empty path 'LocCF' - i.e. a functional type +-- Create an empty path 'LocQuery' - i.e. a functional type -- /from Point to PrimPath/. -- -- This is the analogue to 'emptyPath' in @Wumpus-Core@, but the -- result is produced /within/ the 'DrawingContext'. ---emptyLocPath :: Num u => LocCF u (PrimPath u)-emptyLocPath = locPath []+emptyLocPP :: InterpretUnit u => LocQuery u PrimPath+emptyLocPP = locPP [] +-- | 'vertexPP' : @ (Point ~> PrimPath) @ --+-- Create a PrimPath made of straight line segments joining the +-- supplied points.+--+-- This is the analogue to 'vertexPrimPath' in @Wumpus-Core@, but +-- it is polymorphic on unit.+--+vertexPP :: InterpretUnit u => [Point2 u] -> Query PrimPath+vertexPP xs = vertexPrimPath <$> mapM normalizeCtxF xs++++-- | 'curvePP' : @ (Point ~> PrimPath) @+--+-- Create a path made of curve segments joining the +-- supplied points.+--+-- This is the analogue to 'curvedPrimPath' in @Wumpus-Core@, but +-- it is polymorphic on unit.+--+curvePP :: InterpretUnit u => [Point2 u] -> Query PrimPath+curvePP xs = curvedPrimPath <$> mapM normalizeCtxF xs+++--------------------------------------------------------------------------------++-- -- Drawing paths (stroke, fill, bordered)... -- @@ -133,20 +192,20 @@ -- drawing properties (colour, line width, etc.) are taken from -- the implicit 'DrawingContext'. ---openStroke :: Num u => PrimPath u -> Graphic u-openStroke pp = - withStrokeAttr $ \rgb attr -> graphicAns $ ostroke rgb attr pp+openStroke :: PrimPath -> Graphic u+openStroke pp = makeGraphic strokeAttr (\(rgb,attr) -> ostroke rgb attr pp) + -- | 'closedStroke' : @ path -> Graphic @ -- -- This is the analogue to 'cstroke' in @Wumpus-core@, but the -- drawing properties (colour, line width, etc.) are taken from -- the implicit 'DrawingContext'. ---closedStroke :: Num u => PrimPath u -> Graphic u+closedStroke :: PrimPath -> Graphic u closedStroke pp = - withStrokeAttr $ \rgb attr -> graphicAns $ cstroke rgb attr pp+ makeGraphic strokeAttr (\(rgb,attr) -> cstroke rgb attr pp) -- | 'filledPath' : @ path -> Graphic @@@ -155,8 +214,8 @@ -- fill colour is taken from the implicit 'DrawingContext'. -- ---filledPath :: Num u => PrimPath u -> Graphic u-filledPath pp = withFillAttr $ \rgb -> graphicAns $ fill rgb pp+filledPath :: PrimPath -> Graphic u+filledPath pp = makeGraphic fillAttr (\rgb -> fill rgb pp) -- | 'borderedPath' : @ path -> Graphic @@@ -166,17 +225,17 @@ -- etc.) are taken from the implicit 'DrawingContext'. -- ---borderedPath :: Num u => PrimPath u -> Graphic u+borderedPath :: PrimPath -> Graphic u borderedPath pp =- withBorderedAttr $ \frgb attr srgb -> - graphicAns $ fillStroke frgb attr srgb pp+ makeGraphic borderedAttr + (\(frgb,attr,srgb) -> fillStroke frgb attr srgb pp) -------------------------------------------------------------------------------- -- Text --- | 'textline' : @ string -> LocGraphic @+-- | 'plainTextLine' : @ string -> LocGraphic @ -- -- Create a text 'LocGraphic' - i.e. a functional type -- /from Point to Graphic/.@@ -187,15 +246,16 @@ -- text properties (font family, font size, colour) are taken from -- the implicit 'DrawingContext'. ---textline :: Num u => String -> LocGraphic u-textline ss = - promoteR1 $ \pt -> - withTextAttr $ \rgb attr -> graphicAns (textlabel rgb attr ss pt)+plainTextLine :: InterpretUnit u => String -> LocGraphic u+plainTextLine ss = + makeLocGraphic textAttr + (\(rgb,attr) pt -> textlabel rgb attr ss pt) --- | 'rtextline' : @ string -> LocThetaGraphic @++-- | 'rplainTextLine' : @ string -> LocThetaGraphic @ -- -- Create a text 'LocThetaGraphic' - i.e. a functional type -- /from Point and Angle to Graphic/.@@ -208,14 +268,13 @@ -- -- This is the analogue to 'rtextlabel' in @Wumpus-core@. ---rtextline :: Num u => String -> LocThetaGraphic u-rtextline ss = - promoteR2 $ \pt theta -> - withTextAttr $ \rgb attr -> graphicAns (rtextlabel rgb attr ss theta pt)-+rplainTextLine :: InterpretUnit u => String -> LocThetaGraphic u+rplainTextLine ss =+ makeLocThetaGraphic textAttr+ (\(rgb,attr) pt ang -> rtextlabel rgb attr ss ang pt) --- | 'escapedline' : @ escaped_text -> LocGraphic @+-- | 'escTextline' : @ escaped_text -> LocGraphic @ -- -- Create a text 'LocGraphic' - i.e. a functional type -- /from Point to Graphic/.@@ -226,14 +285,14 @@ -- the text properties (font family, font size, colour) are taken -- from the implicit 'DrawingContext'. ---escapedline :: Num u => EscapedText -> LocGraphic u-escapedline ss = - promoteR1 $ \pt -> - withTextAttr $ \rgb attr -> graphicAns (escapedlabel rgb attr ss pt)+escTextLine :: InterpretUnit u => EscapedText -> LocGraphic u+escTextLine esc = + makeLocGraphic textAttr + (\(rgb,attr) pt -> escapedlabel rgb attr esc pt) --- | 'rescapedline' : @ escaped_text -> LocThetaGraphic @+-- | 'rescTextLine' : @ escaped_text -> LocThetaGraphic @ -- -- Create a text 'LocThetaGraphic' - i.e. a functional type -- /from Point and Angle to Graphic/.@@ -248,15 +307,25 @@ -- the text properties (font family, font size, colour) are taken -- from the implicit 'DrawingContext'. ---rescapedline :: Num u => EscapedText -> LocThetaGraphic u-rescapedline ss = - promoteR2 $ \pt theta -> - withTextAttr $ \rgb attr -> graphicAns (rescapedlabel rgb attr ss theta pt)+rescTextLine :: InterpretUnit u => EscapedText -> LocThetaGraphic u+rescTextLine esc = + makeLocThetaGraphic textAttr+ (\(rgb,attr) pt ang -> rescapedlabel rgb attr esc ang pt) +-- | Unit parametric version of KerningChar from Wumpus-Core.+--+type KernChar u = (u,EscapedChar) --- | 'hkernline' : @ [kern_char] -> LocGraphic @+uconvKernChar :: InterpretUnit u => [KernChar u] -> Query [KerningChar]+uconvKernChar = mapM mf+ where+ mf (u,ch) = (\u1 -> (u1,ch)) <$> normalizeCtx u++++-- | 'hkernLine' : @ [kern_char] -> LocGraphic @ -- -- Create a horizontally kerned text 'LocGraphic' - i.e. a -- functional type /from Point to Graphic/.@@ -267,13 +336,15 @@ -- the text properties (font family, font size, colour) are taken -- from the implicit 'DrawingContext'. ---hkernline :: Num u => [KerningChar u] -> LocGraphic u-hkernline xs = - promoteR1 $ \pt -> - withTextAttr $ \rgb attr -> graphicAns (hkernlabel rgb attr xs pt)+hkernLine :: InterpretUnit u => [KernChar u] -> LocGraphic u+hkernLine ks = uconvKernChar ks >>= body + where+ body ans = makeLocGraphic textAttr+ (\(rgb,attr) pt -> hkernlabel rgb attr ans pt) --- | 'vkernline' : @ [kern_char] -> LocGraphic @++-- | 'vkernLine' : @ [kern_char] -> LocGraphic @ -- -- Create a vertically kerned text 'LocGraphic' - i.e. a -- functional type /from Point to Graphic/.@@ -284,18 +355,28 @@ -- the text properties (font family, font size, colour) are taken -- from the implicit 'DrawingContext'. ---vkernline :: Num u => [KerningChar u] -> LocGraphic u-vkernline xs = - promoteR1 $ \pt -> - withTextAttr $ \rgb attr -> graphicAns (vkernlabel rgb attr xs pt)---+vkernLine :: InterpretUnit u => [KernChar u] -> LocGraphic u+vkernLine ks = uconvKernChar ks >>= body+ where+ body ans = makeLocGraphic textAttr+ (\(rgb,attr) pt -> vkernlabel rgb attr ans pt) -------------------------------------------------------------------------------- -- Lines --- | 'straightLine' : @ vec_to -> LocGraphic @ +-- | 'straightLine' : @ start_point * end_point -> LocGraphic @ +-- +-- Create a straight line 'Graphic', the start and end point +-- are supplied explicitly.+-- +-- The line properties (colour, pen thickness, etc.) are taken +-- from the implicit 'DrawingContext'.+-- +straightLine :: InterpretUnit u => Point2 u -> Point2 u -> Graphic u+straightLine p1 p2 = vertexPP [p1,p2] >>= openStroke+++-- | 'locStraightLine' : @ vec_to -> LocGraphic @ -- -- Create a stright line 'LocGraphic' - i.e. a functional type -- /from Point to Graphic/.@@ -307,42 +388,55 @@ -- The line properties (colour, pen thickness, etc.) are taken -- from the implicit 'DrawingContext'. -- -straightLine :: Fractional u => Vec2 u -> LocGraphic u-straightLine v = mf >>= (lift0R1 . openStroke)- where- mf = promoteR1 $ \pt -> pure $ primPath pt [lineTo $ pt .+^ v]+locStraightLine :: InterpretUnit u => Vec2 u -> LocGraphic u+locStraightLine v = promoteR1 $ \pt -> + apply1R1 (locPP [v]) pt >>= openStroke - --- | 'straightLineGraphic' : @ start_point * end_point -> LocGraphic @ +++-- | 'curveLine' : @ start_point * control_point1 * +-- control_point2 * end_point -> Graphic @ -- --- Create a straight line 'Graphic', the start and end point --- are supplied explicitly.+-- Create a Bezier curve 'Graphic', all control points are +-- supplied explicitly. -- -- The line properties (colour, pen thickness, etc.) are taken -- from the implicit 'DrawingContext'. -- -straightLineGraphic :: Fractional u => Point2 u -> Point2 u -> Graphic u-straightLineGraphic p1 p2 = openStroke $ primPath p1 [lineTo p2]+curvedLine :: InterpretUnit u+ => Point2 u -> Point2 u -> Point2 u -> Point2 u -> Graphic u+curvedLine p0 p1 p2 p3 = curvePP [p0,p1,p2,p3] >>= openStroke --- | 'curveGraphic' : @ start_point * control_point1 * --- control_point2 * end_point -> Graphic @ ++-- | 'straightConnector' : @ start_point * end_point -> Connector @ -- --- Create a Bezier curve 'Graphic', all control points are --- supplied explicitly.+-- Create a straight line 'Graphic', the start and end point +-- are supplied implicitly. -- -- The line properties (colour, pen thickness, etc.) are taken -- from the implicit 'DrawingContext'. -- -curveGraphic :: Fractional u - => Point2 u -> Point2 u -> Point2 u -> Point2 u -> Graphic u-curveGraphic sp cp1 cp2 ep = openStroke $ primPath sp [curveTo cp1 cp2 ep]+straightConnector :: InterpretUnit u => ConnectorGraphic u+straightConnector = promoteR2 $ \p0 p1 -> vertexPP [p0,p1] >>= openStroke + -------------------------------------------------------------------------------- -- Circles +-- | Helper for circle drawing.+--+circlePath :: InterpretUnit u + => u -> LocQuery u PrimPath+circlePath r = promoteR1 $ \pt ->+ (\dr dpt -> curvedPrimPath $ bezierCircle dr dpt) + <$> normalizeCtx r <*> normalizeCtxF pt++++ -- | 'strokedCircle' : @ radius -> LocGraphic @ -- -- Create a stroked circle 'LocGraphic' - the implicit point is @@ -351,11 +445,13 @@ -- The line properties (colour, pen thickness, etc.) are taken -- from the implicit 'DrawingContext'. -- -strokedCircle :: Floating u => u -> LocGraphic u-strokedCircle r = promoteR1 (closedStroke . curvedPath . bezierCircle r)+strokedCircle :: InterpretUnit u => u -> LocGraphic u+strokedCircle r = promoteR1 $ \pt -> + apply1R1 (circlePath r) pt >>= openStroke + -- | 'filledCircle' : @ radius -> LocGraphic @ -- -- Create a filled circle 'LocGraphic' - the implicit point is @@ -363,8 +459,9 @@ -- -- The fill colour is taken from the implicit 'DrawingContext'. -- -filledCircle :: Floating u => u -> LocGraphic u-filledCircle r = promoteR1 (filledPath . curvedPath . bezierCircle r)+filledCircle :: InterpretUnit u => u -> LocGraphic u+filledCircle r = promoteR1 $ \pt -> + apply1R1 (circlePath r) pt >>= filledPath @@ -376,15 +473,35 @@ -- The background fill colour and the outline stroke properties -- are taken from the implicit 'DrawingContext'. -- -borderedCircle :: Floating u => u -> LocGraphic u-borderedCircle r = promoteR1 (borderedPath . curvedPath . bezierCircle r)+borderedCircle :: InterpretUnit u => u -> LocGraphic u+borderedCircle r = promoteR1 $ \pt -> + apply1R1 (circlePath r) pt >>= borderedPath -------------------------------------------------------------------------------- -- Ellipses +-- | Helper for ellipse drawing.+--+ellipsePath :: InterpretUnit u + => u -> u -> LocQuery u PrimPath+ellipsePath rx ry = promoteR1 $ \pt ->+ (\drx dry dpt -> curvedPrimPath $ bezierEllipse drx dry dpt) + <$> normalizeCtx rx <*> normalizeCtx ry <*> normalizeCtxF pt ++-- | Helper for ellipse drawing.+--+rellipsePath :: InterpretUnit u + => u -> u -> LocThetaQuery u PrimPath+rellipsePath rx ry = promoteR2 $ \pt ang ->+ (\drx dry dpt -> curvedPrimPath $ rbezierEllipse drx dry ang dpt) + <$> normalizeCtx rx <*> normalizeCtx ry <*> normalizeCtxF pt++++ -- | 'strokedEllipse' : @ x_radius * y_radius -> LocGraphic @ -- -- Create a stroked ellipse 'LocGraphic' - the implicit point is @@ -393,9 +510,9 @@ -- The line properties (colour, pen thickness, etc.) are taken -- from the implicit 'DrawingContext'. -- -strokedEllipse :: Floating u => u -> u -> LocGraphic u-strokedEllipse rx ry =- promoteR1 (closedStroke . curvedPath . bezierEllipse rx ry)+strokedEllipse :: InterpretUnit u => u -> u -> LocGraphic u+strokedEllipse rx ry = promoteR1 $ \pt ->+ apply1R1 (ellipsePath rx ry) pt >>= closedStroke @@ -408,12 +525,14 @@ -- The line properties (colour, pen thickness, etc.) are taken -- from the implicit 'DrawingContext'. -- -rstrokedEllipse :: (Real u, Floating u) => u -> u -> LocThetaGraphic u-rstrokedEllipse hw hh = - promoteR2 $ \ pt theta -> - closedStroke $ curvedPath $ rbezierEllipse hw hh theta pt +rstrokedEllipse :: InterpretUnit u+ => u -> u -> LocThetaGraphic u+rstrokedEllipse rx ry = promoteR2 $ \pt ang -> + apply2R2 (rellipsePath rx ry) pt ang >>= closedStroke ++ -- | 'filledEllipse' : @ x_radius * y_radius -> LocGraphic @ -- -- Create a filled ellipse 'LocGraphic' - the implicit point is @@ -421,9 +540,9 @@ -- -- The fill colour is taken from the implicit 'DrawingContext'. -- -filledEllipse :: Floating u => u -> u -> LocGraphic u-filledEllipse hw hh = - promoteR1 (filledPath . curvedPath . bezierEllipse hw hh)+filledEllipse :: InterpretUnit u => u -> u -> LocGraphic u+filledEllipse rx ry = promoteR1 $ \pt -> + apply1R1 (ellipsePath rx ry) pt >>= filledPath -- | 'rfilledEllipse' : @ x_radius * y_radius -> LocGraphic @@@ -434,10 +553,9 @@ -- -- The fill colour is taken from the implicit 'DrawingContext'. -- -rfilledEllipse :: (Real u, Floating u) => u -> u -> LocThetaGraphic u-rfilledEllipse hw hh = - promoteR2 $ \ pt theta -> - filledPath $ curvedPath $ rbezierEllipse hw hh theta pt +rfilledEllipse :: InterpretUnit u => u -> u -> LocThetaGraphic u+rfilledEllipse rx ry = promoteR2 $ \pt ang ->+ apply2R2 (rellipsePath rx ry) pt ang >>= filledPath @@ -449,9 +567,9 @@ -- The background fill colour and the outline stroke properties -- are taken from the implicit 'DrawingContext'. -- -borderedEllipse :: Floating u => u -> u -> LocGraphic u-borderedEllipse hw hh =- promoteR1 (borderedPath . curvedPath . bezierEllipse hw hh)+borderedEllipse :: InterpretUnit u => u -> u -> LocGraphic u+borderedEllipse rx ry = promoteR1 $ \pt -> + apply1R1 (ellipsePath rx ry) pt >>= borderedPath @@ -464,29 +582,23 @@ -- The background fill colour and the outline stroke properties -- are taken from the implicit 'DrawingContext'. -- -rborderedEllipse :: (Real u, Floating u) => u -> u -> LocThetaGraphic u-rborderedEllipse hw hh = - promoteR2 $ \ pt theta -> - borderedPath $ curvedPath $ rbezierEllipse hw hh theta pt +rborderedEllipse :: InterpretUnit u+ => u -> u -> LocThetaGraphic u+rborderedEllipse rx ry = promoteR2 $ \pt ang -> + apply2R2 (rellipsePath rx ry) pt ang >>= borderedPath --- Note - clipping needs a picture as well as a path, so there is--- no analogous @clippedPath@ function.+-- Note - clipping to do... -------------------------------------------------------------------------------- -- Rectangles -- -- | Supplied point is /bottom-left/. ---rectanglePath :: Num u => u -> u -> Point2 u -> PrimPath u-rectanglePath w h bl = primPath bl [ lineTo br, lineTo tr, lineTo tl ]- where- br = bl .+^ hvec w- tr = br .+^ vvec h- tl = bl .+^ vvec h+rectanglePath :: InterpretUnit u + => u -> u -> LocQuery u PrimPath+rectanglePath w h = locPP [hvec w, vvec h, hvec (-w)] -- | 'strokedRectangle' : @ width * height -> LocGraphic @@@ -497,8 +609,9 @@ -- The line properties (colour, pen thickness, etc.) are taken -- from the implicit 'DrawingContext'. -- -strokedRectangle :: Fractional u => u -> u -> LocGraphic u-strokedRectangle w h = promoteR1 (closedStroke . rectanglePath w h)+strokedRectangle :: InterpretUnit u => u -> u -> LocGraphic u+strokedRectangle w h = promoteR1 $ \pt -> + apply1R1 (rectanglePath w h) pt >>= closedStroke -- | 'filledRectangle' : @ width * height -> LocGraphic @@@ -508,8 +621,9 @@ -- -- The fill colour is taken from the implicit 'DrawingContext'. -- -filledRectangle :: Fractional u => u -> u -> LocGraphic u-filledRectangle w h = promoteR1 (filledPath . rectanglePath w h)+filledRectangle :: InterpretUnit u => u -> u -> LocGraphic u+filledRectangle w h = promoteR1 $ \pt -> + apply1R1 (rectanglePath w h) pt >>= filledPath -- | 'borderedRectangle' : @ width * height -> LocGraphic @@@ -520,13 +634,12 @@ -- The background fill colour and the outline stroke properties -- are taken from the implicit 'DrawingContext'. -- -borderedRectangle :: Fractional u => u -> u -> LocGraphic u-borderedRectangle w h = promoteR1 (borderedPath . rectanglePath w h)-+borderedRectangle :: InterpretUnit u => u -> u -> LocGraphic u+borderedRectangle w h = promoteR1 $ \pt -> + apply1R1 (rectanglePath w h) pt >>= borderedPath --------------------------------------------------------------------------- - -- | 'strokedDisk' : @ radius -> LocGraphic @ -- -- Create a stroked circle 'LocGraphic' - the implicit point is @@ -544,10 +657,16 @@ -- The line properties (colour, pen thickness, etc.) are taken -- from the implicit 'DrawingContext'. -- -strokedDisk :: Num u => u -> LocGraphic u-strokedDisk r = strokedEllipseDisk r r+strokedDisk :: InterpretUnit u => u -> LocGraphic u+strokedDisk radius = + normalizeCtx radius >>= body+ where+ body r = makeLocGraphic strokeAttr+ (\(rgb,attr) pt -> strokeEllipse rgb attr r r pt) ++ -- | 'filledDisk' : @ radius -> LocGraphic @ -- -- Create a filled circle 'LocGraphic' - the implicit point is @@ -560,8 +679,11 @@ -- -- The fill colour is taken from the implicit 'DrawingContext'. -- -filledDisk :: Num u => u -> LocGraphic u-filledDisk r = filledEllipseDisk r r+filledDisk :: InterpretUnit u => u -> LocGraphic u+filledDisk radius = + normalizeCtx radius >>= body+ where+ body r = makeLocGraphic fillAttr (\rgb pt -> fillEllipse rgb r r pt) -- | 'borderedDisk' : @ radius -> LocGraphic @@@ -581,8 +703,12 @@ -- The background fill colour and the outline stroke properties -- are taken from the implicit 'DrawingContext'. -- -borderedDisk :: Num u => u -> LocGraphic u-borderedDisk r = borderedEllipseDisk r r+borderedDisk :: InterpretUnit u => u -> LocGraphic u+borderedDisk radius = + normalizeCtx radius >>= body+ where+ body r = makeLocGraphic borderedAttr+ (\(frgb,attr,srgb) pt -> fillStrokeEllipse frgb attr srgb r r pt) -- | 'strokedEllipseDisk' : @ x_radius * y_radius -> LocGraphic @@@ -602,13 +728,14 @@ -- The line properties (colour, pen thickness, etc.) are taken -- from the implicit 'DrawingContext'. -- -strokedEllipseDisk :: Num u => u -> u -> LocGraphic u-strokedEllipseDisk rx ry =- promoteR1 $ \ pt -> - withStrokeAttr $ \rgb attr -> - graphicAns (strokeEllipse rgb attr rx ry pt)+strokedEllipseDisk :: InterpretUnit u => u -> u -> LocGraphic u+strokedEllipseDisk rx ry = norm2 rx ry >>= body+ where+ body (drx,dry) = makeLocGraphic strokeAttr+ (\(rgb,attr) pt -> strokeEllipse rgb attr drx dry pt) + -- | 'filledEllipseDisk' : @ x_radius * y_radius -> LocGraphic @ -- -- Create a filled ellipse 'LocGraphic' - the implicit point is @@ -621,10 +748,11 @@ -- -- The fill colour is taken from the implicit 'DrawingContext'. -- -filledEllipseDisk :: Num u => u -> u -> LocGraphic u-filledEllipseDisk rx ry = - promoteR1 $ \pt -> - withFillAttr $ \rgb -> graphicAns (fillEllipse rgb rx ry pt)+filledEllipseDisk :: InterpretUnit u => u -> u -> LocGraphic u+filledEllipseDisk rx ry = norm2 rx ry >>= body+ where+ body (drx,dry) = makeLocGraphic fillAttr+ (\rgb pt -> fillEllipse rgb drx dry pt) -- | 'borderedEllipseDisk' : @ x_radius * y_radius -> LocGraphic @@@ -644,8 +772,10 @@ -- The background fill colour and the outline stroke properties -- are taken from the implicit 'DrawingContext'. -- -borderedEllipseDisk :: Num u => u -> u -> LocGraphic u-borderedEllipseDisk rx ry = - promoteR1 $ \pt -> - withBorderedAttr $ \frgb attr srgb -> - graphicAns (fillStrokeEllipse frgb attr srgb rx ry pt)+borderedEllipseDisk :: InterpretUnit u => u -> u -> LocGraphic u+borderedEllipseDisk rx ry = norm2 rx ry >>= body+ where+ body (drx,dry) = makeLocGraphic borderedAttr+ (\(frgb,attr,srgb) pt -> + fillStrokeEllipse frgb attr srgb drx dry pt)+
− src/Wumpus/Basic/Kernel/Objects/Graphic.hs
@@ -1,282 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.Kernel.Objects.Graphic--- Copyright : (c) Stephen Tetley 2010-2011--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : highly unstable--- Portability : GHC ------ Graphic type - this is largely equivalent to Primitive in--- Wumpus-Core, but drawing attributes are implicitly supplied --- by the DrawingContext.------ API in @Wumpus.Core@, but here they exploit the implicit --- @DrawingContext@.--------------------------------------------------------------------------------------module Wumpus.Basic.Kernel.Objects.Graphic- (-- Graphic- , DGraphic--- -- * LocGraphic - , LocGraphic- , DLocGraphic--- , LocThetaGraphic- , DLocThetaGraphic-- -- * Functions- , safeconcat- , ignoreAns- , replaceAns- , mapAns-- , intoImage- , intoLocImage- , intoLocThetaImage-- , emptyLocGraphic- , emptyLocThetaGraphic -- , decorate- , sdecorate- , adecorate- - , hyperlink-- ) where--import Wumpus.Basic.Kernel.Base.BaseDefs-import Wumpus.Basic.Kernel.Base.ContextFun-import Wumpus.Basic.Kernel.Base.WrappedPrimitive-import Wumpus.Basic.Kernel.Objects.BaseObjects--import Wumpus.Core -- package: wumpus-core---import Control.Applicative------------------------------------------------------------------------------------- Graphic---- | Simple drawing - produce a primitive, access the DrawingContext--- as required, e.g for fill colour, stroke colur, line width, etc.----type Graphic u = Image u (UNil u)---- | Alias of 'Graphic' where the unit type is specialized to --- Double. ----type DGraphic = Graphic Double----- | /Originated/ drawing - produce a primitive respective to the --- supplied start-point, access the DrawingContext as required.----type LocGraphic u = LocImage u (UNil u)---- | Alias of 'LocGraphic' where the unit type is specialized to --- Double. ----type DLocGraphic = LocGraphic Double------- | /Originated/ drawing - produce a primitive respective to the --- supplied start-point, access the DrawingContext as required.----type LocThetaGraphic u = LocThetaImage u (UNil u)----- | Alias of 'LocThetaGraphic' where the unit type is specialized --- to Double. ----type DLocThetaGraphic = LocThetaGraphic Double-------------------------------------------------------------------------------------- Functions----- | 'safeconcat' : @ alternative * [image] -> Image@--- --- 'safeconcat' produces a composite 'Image' from a list of --- @Image@\'s. If the list is empty the alternative @Image@ is --- used.------ This contrasts to 'oconcat' - when used for @Image@\'s, --- @oconcat@ has the same type signature as @safeconcat@ but --- @oconcat@ considers its arguments to be an already destructured --- list:--- --- > oconcat (head::Image) (rest::[Image])--- -safeconcat :: OPlus a => Image u a -> [Image u a] -> Image u a-safeconcat _ (x:xs) = oconcat x xs-safeconcat alt [] = alt----- | Ignore the answer produced by an 'Image', a 'LocImage' etc.------ Use this function to turn an 'Image' into a 'Graphic', a --- 'LocImage into a 'LocGraphic'.----ignoreAns :: Functor f => f (a,b) -> f (UNil u, b)-ignoreAns = fmap (replaceL uNil)----- | Replace the answer produced by an 'Image', a 'LocImage' etc.----replaceAns :: Functor f => z -> f (a,b) -> f (z, b)-replaceAns = fmap . replaceL----- | Apply the supplied function to the answer produced by an --- 'Image', a 'LocImage' etc.----mapAns :: Functor f => (a -> z) -> f (a,b) -> f (z,b)-mapAns f = fmap (\(a,b) -> (f a ,b))----- | 'intoImage' : @ context_function * graphic -> Image @------ Build an 'Image' from a context function ('CF') that generates --- the answer and a 'Graphic' that draws the 'Image'.----intoImage :: CF a -> Graphic u -> Image u a-intoImage = liftA2 (\a (_,b) -> (a,b))----- | 'intoLocImage' : @ loc_context_function * loc_graphic -> LocImage @------ /Loc/ version of 'intoImage'. --- --- The 'LocImage' is built as a function from an implicit start --- point to the answer.----intoLocImage :: LocCF u a -> LocGraphic u -> LocImage u a-intoLocImage = liftA2 (\a (_,b) -> (a,b))---- | 'intoLocThetaImage' : @ loc_theta_cf * loc_theta_graphic -> LocThetaImage @------ /LocTheta/ version of 'intoImage'. --- --- The 'LocThetaImage' is built as a function from an implicit --- start point and angle of inclination to the answer.----intoLocThetaImage :: LocThetaCF u a -> LocThetaGraphic u -> LocThetaImage u a-intoLocThetaImage = liftA2 (\a (_,b) -> (a,b))------ | 'emptyLocGraphic' : @ LocGraphic @------ Build an empty 'LocGraphic' (i.e. a function --- /from Point to Graphic/). This is a path with a start point --- but no path segments. --- --- The 'emptyLocGraphic' is treated as a /null primitive/ by --- @Wumpus-Core@ and is not drawn, although it does generate a --- minimum bounding box at the implicit start point.--- -emptyLocGraphic :: Num u => LocGraphic u-emptyLocGraphic = promoteR1 $ \pt -> - return $ (uNil, primGraphic $ zostroke $ emptyPath pt)------ | 'emptyLocThetaGraphic' : @ LocThetaGraphic @------ Build an empty 'LocThetaGraphic' (i.e. a function --- /from Point and Inclination to Graphic/). --- --- The 'emptyLocThetaGraphic' is treated as a /null primitive/ by --- @Wumpus-Core@ and is not drawn, although it does generate a --- minimum bounding box at the implicit start point.--- -emptyLocThetaGraphic :: Num u => LocThetaGraphic u-emptyLocThetaGraphic = lift1R2 emptyLocGraphic------- | Decorate an Image by superimposing a Graphic.------ Note - this function has a very general type signature and--- supports various graphic types:------ > decorate :: Image u a -> Graphic u -> Image u a--- > decorate :: LocImage u a -> LocGraphic u -> LocImage u a--- > decorate :: LocThetaImage u a -> LocThetaGraphic u -> LocTheteImage u a----decorate :: Monad m - => m (ImageAns u a) -> m (ImageAns u zz) -> m (ImageAns u a) -decorate img gf = - img >>= \(a,g1) -> gf >>= \(_,g2) -> return (a, g1 `oplus` g2)------ | /Anterior decorate/ - decorate an Image by superimposing it --- on a Graphic.------ Note - here the Graphic has access to the result produced by the --- the Image unlike 'decorate'.------ Again, this function has a very general type signature and--- supports various graphic types:------ > adecorate :: Image u a -> Graphic u -> Image u a--- > adecorate :: LocImage u a -> LocGraphic u -> LocImage u a--- > adecorate :: LocThetaImage u a -> LocThetaGraphic u -> LocTheteImage u a----adecorate :: Monad m - => m (ImageAns u a) -> (a -> m (ImageAns u zz)) -> m (ImageAns u a)-adecorate img f = - img >>= \(a,g1) -> f a >>= \(_,g0) -> return (a, g0 `oplus` g1)----- | /Superior decorate/ - decorate an image by superimposing a --- graphic on top of it.------ Note, here the Graphic has access to the result produced by the --- the Image unlike 'decorate'.------ Again, this function has a very general type signature and--- supports various graphic types:------ > sdecorate :: Image u a -> Graphic u -> Image u a--- > sdecorate :: LocImage u a -> LocGraphic u -> LocImage u a--- > sdecorate :: LocThetaImage u a -> LocThetaGraphic u -> LocTheteImage u a----sdecorate :: Monad m - => m (ImageAns u a) -> (a -> m (ImageAns u zz)) -> m (ImageAns u a)-sdecorate img f = - img >>= \(a,g1) -> f a >>= \(_,g2) -> return (a, g1 `oplus` g2)----- | Hyperlink a graphic object.--- --- This function has a very general type signature and supports --- various graphic types:------ > hyperlink :: XLink -> Graphic u -> Graphic u--- > hyperlink :: XLink -> Image u a -> Image u a--- > hyperlink :: XLink -> LocImage u a -> LocImage u a--- > hyperlink :: XLink -> LocThetaImage u a -> LocThetaImage u a----hyperlink :: Functor m => XLink -> m (ImageAns u a) -> m (ImageAns u a)-hyperlink hypl = - fmap (\(a,prim) -> (a, metamorphPrim (xlink hypl) prim))-
+ src/Wumpus/Basic/Kernel/Objects/Image.hs view
@@ -0,0 +1,105 @@+{-# OPTIONS -Wall #-}+++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.Kernel.Objects.Image+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- Image and Graphic types - these are functional types from the +-- DrawingContext to a graphic /primitive/.+--+--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Objects.Image+ (+ Graphic+ , Image++ , DImage+ , DGraphic++ , intoImage+ , graphic_++ , uconvImageF+ , uconvImageZ++ )++ where++import Wumpus.Basic.Kernel.Base.BaseDefs+import Wumpus.Basic.Kernel.Base.ContextFun+import Wumpus.Basic.Kernel.Objects.Basis++import Control.Applicative+++-- | Image - function from the DrawingContext to a polymorphic +-- /answer/ and a graphic /primitive/.+--+-- The answer is expected to be a Functor.+--+type Image u a = CF (ImageAns u a)++++-- | Graphic - function from the DrawingContext to a graphic +-- /primitive/.+--+type Graphic u = CF (GraphicAns u)++++-- | Type specialized version of 'Image'.+--+type DImage a = Image Double a +++-- | Type specialized version of 'Graphic'.+--+type DGraphic = Graphic Double +++-- | 'intoImage' : @ query * graphic -> Image @+--+-- Build an 'Image' from a context function ('CF') that generates +-- the answer and a 'Graphic' that draws the 'Image'.+--+intoImage :: Query a -> Graphic u -> Image u a+intoImage qf ma = replaceAns <$> qf <*> ma+++-- | /Downcast/ an 'Image' to a 'Graphic'.+-- +-- This means forgetting the answer of the Image, replacing it +-- with @()@.+--+graphic_ :: Image u a -> Graphic u+graphic_ = fmap ignoreAns++++++-- | Use this to convert 'Graphic' or 'Image' with Functor answer.+--+uconvImageF :: (Functor t, InterpretUnit u, InterpretUnit u1)+ => Image u (t u) -> Image u1 (t u1)+uconvImageF = uconvR0 szconvAnsF+++uconvImageZ :: (InterpretUnit u, InterpretUnit u1)+ => Image u a -> Image u1 a+uconvImageZ = uconvR0 szconvAnsZ++++--------------------------------------------------------------------------------+
+ src/Wumpus/Basic/Kernel/Objects/LocImage.hs view
@@ -0,0 +1,199 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.Kernel.Objects.LocImage+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- LocImage and LocGraphic types - these are functional types from the +-- DrawingContext and start point to a graphic /primitive/.+--+--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Objects.LocImage+ (+ LocGraphic+ , LocImage++ , DLocImage+ , DLocGraphic++ , intoLocImage+ , locGraphic_++ , emptyLocGraphic++ , uconvLocImageF+ , uconvLocImageZ++ -- * Composing LocImages+ , distrib+ , distribH + , distribV+ + , duplicate+ , duplicateH+ , duplicateV+++ )++ where++import Wumpus.Basic.Kernel.Base.BaseDefs+import Wumpus.Basic.Kernel.Base.ContextFun+import Wumpus.Basic.Kernel.Base.QueryDC+import Wumpus.Basic.Kernel.Base.WrappedPrimitive+import Wumpus.Basic.Kernel.Objects.Basis+import Wumpus.Basic.Kernel.Objects.Displacement+++import Wumpus.Core -- package: wumpus-core++import Data.AffineSpace -- package: vector-space+import Data.VectorSpace++import Control.Applicative+import Data.Monoid+++-- | Graphic - function from DrawingContext and start point to a +-- polymorphic /answer/ and a graphic /primitive/.+--+-- The answer is expected to be a Functor.+--+type LocImage u a = LocQuery u (ImageAns u a)+++++-- | LocGraphic - function from DrawingContext and start point to +-- a graphic /primitive/.+--+type LocGraphic u = LocQuery u (GraphicAns u)+++-- | Type specialized version of 'LocImage'.+--+type DLocImage a = LocImage Double a++-- | Type specialized version of 'LocGraphic'.+--+type DLocGraphic = LocGraphic Double +++++++-- | 'intoLocImage' : @ loc_query * loc_graphic -> LocImage @+--+-- /Loc/ version of 'intoImage'. +-- +-- The 'LocImage' is built as a function from an implicit start +-- point to the answer.+--+intoLocImage :: LocQuery u a -> LocGraphic u -> LocImage u a+intoLocImage ma gf = promoteR1 $ \pt -> + replaceAns <$> apply1R1 ma pt <*> apply1R1 gf pt+++-- | /Downcast/ an 'LocImage' to a 'LocGraphic'.+-- +-- This means forgetting the answer of the LocImage, replacing it +-- with @()@.+--+locGraphic_ :: LocImage u a -> LocGraphic u+locGraphic_ = (fmap . fmap) ignoreAns+++-- | 'emptyLocGraphic' : @ LocGraphic @+--+-- Build an empty 'LocGraphic' (i.e. a function +-- /from Point to Graphic/). This is a path with a start point +-- but no path segments. +-- +-- The 'emptyLocGraphic' is treated as a /null primitive/ by +-- @Wumpus-Core@ and is not drawn, although it does generate a +-- minimum bounding box at the implicit start point.+-- +emptyLocGraphic :: InterpretUnit u => LocGraphic u+emptyLocGraphic = promoteR1 $ \pt -> + uconvertCtxF pt >>= \dpt -> + return $ graphicAns $ prim1 $ zostroke $ emptyPrimPath dpt++++++-- | Use this to convert 'LocGraphic' or 'LocImage' with Functor +-- answer.+--+uconvLocImageF :: (InterpretUnit u, InterpretUnit u1, Functor t) + => LocImage u (t u) -> LocImage u1 (t u1)+uconvLocImageF = uconvR1 szconvAnsF++++-- | Use this to convert 'LocImage' with unit-less answer.+--+uconvLocImageZ :: (InterpretUnit u, InterpretUnit u1) + => LocImage u a -> LocImage u1 a+uconvLocImageZ = uconvR1 szconvAnsZ++++--------------------------------------------------------------------------------+-- Combining LocImages ++-- LocImages have no concept of /border/ or /next/, so they can +-- only be combined by manipulating the start point of successive+-- drawings.++-- 'oplus' gives super-imposition - Locimages are drawn at the same+-- start point.++++distrib :: (Monoid a, InterpretUnit u) + => Vec2 u -> [LocImage u a] -> LocImage u a+distrib _ [] = pushR1 (replaceAns mempty) $ emptyLocGraphic+distrib v1 (x:xs) = promoteR1 $ \pt -> + go (x `at` pt) (pt .+^ v1) xs+ where+ go acc _ [] = acc+ go acc pt (a:as) = go (acc `mappend` apply1R1 a pt) (pt .+^ v1) as++distribH :: (Monoid a, InterpretUnit u) + => u -> [LocImage u a] -> LocImage u a+distribH dx = distrib (hvec dx)++distribV :: (Monoid a, InterpretUnit u) + => u -> [LocImage u a] -> LocImage u a+distribV dy = distrib (hvec dy)++++-- | This is analogue to @replicate@ in the Prelude.+--+duplicate :: (Monoid a, InterpretUnit u) + => Int -> Vec2 u -> LocImage u a -> LocImage u a+duplicate n _ _ | n < 1 = pushR1 (replaceAns mempty) $ emptyLocGraphic+duplicate n v img = go img v (n-1)+ where+ go acc _ i | i < 1 = acc+ go acc va i = let img1 = moveStart (displaceVec va) img+ in go (acc `mappend` img1) (va ^+^ v) (i-1)++duplicateH :: (Monoid a, InterpretUnit u) + => Int -> u -> LocImage u a -> LocImage u a+duplicateH n dx = duplicate n (hvec dx)++duplicateV :: (Monoid a, InterpretUnit u) + => Int -> u -> LocImage u a -> LocImage u a+duplicateV n dy = duplicate n (vvec dy)
+ src/Wumpus/Basic/Kernel/Objects/LocThetaImage.hs view
@@ -0,0 +1,367 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.Kernel.Objects.LocThetaImage+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- LocThetaImage and LocThetaGraphic types - these are functional +-- types from the DrawingContext, start point and angle of +-- inclination to a graphic /primitive/.+--+--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Objects.LocThetaImage+ (+ LocThetaGraphic+ , LocThetaImage++ , DLocThetaGraphic+ , DLocThetaImage++ , intoLocThetaImage+ , locThetaGraphic_++ , emptyLocThetaGraphic++ , uconvLocThetaImageF+ , uconvLocThetaImageZ++ + )++ where++import Wumpus.Basic.Kernel.Base.BaseDefs+import Wumpus.Basic.Kernel.Base.ContextFun+import Wumpus.Basic.Kernel.Objects.Basis+-- import Wumpus.Basic.Kernel.Objects.Displacement+import Wumpus.Basic.Kernel.Objects.LocImage++-- import Wumpus.Core -- package: wumpus-core++import Control.Applicative+++-- | 'LocThetaImage' - function from DrawingContext, start point +-- and inclination to a polymorphic /answer/ and a graphic +-- /primitive/ (ImageAns).+--+-- The answer is expected to be a Functor.+--+type LocThetaImage u a = LocThetaQuery u (ImageAns u a)+++-- | LocThetaGraphic - function from DrawingContext, start point +-- and inclination to a graphic /primitive/ (GraphicAns).+--+type LocThetaGraphic u = LocThetaQuery u (GraphicAns u)+++-- | Type specialized version of 'LocThetaImage'.+--+type DLocThetaImage a = LocThetaImage Double a++-- | Type specialized version of 'LocThetaGraphic'.+--+type DLocThetaGraphic = LocThetaGraphic Double +++++-- | 'intoLocThetaImage' : @ loc_theta_query * loc_theta_graphic -> LocThetaImage @+--+-- /LocTheta/ version of 'intoImage'. +-- +-- The 'LocThetaImage' is built as a function from an implicit +-- start point and angle of inclination to the answer.+--+intoLocThetaImage :: LocThetaQuery u a + -> LocThetaGraphic u + -> LocThetaImage u a+intoLocThetaImage qf ma = + promoteR2 $ \a b -> replaceAns <$> apply2R2 qf a b <*> apply2R2 ma a b++++-- | /Downcast/ an 'LocThetaImage' to a 'LocThetaGraphic'.+-- +-- This means forgetting the answer of the Image, replacing it +-- with @()@.+--+locThetaGraphic_ :: LocThetaImage u a -> LocThetaGraphic u+locThetaGraphic_ = (fmap . fmap . fmap) ignoreAns+++-- | 'emptyLocThetaGraphic' : @ LocThetaGraphic @+--+-- Build an empty 'LocThetaGraphic' (i.e. a function +-- /from Point and Inclination to Graphic/). +-- +-- The 'emptyLocThetaGraphic' is treated as a /null primitive/ by +-- @Wumpus-Core@ and is not drawn, although it does generate a +-- minimum bounding box at the implicit start point.+-- +emptyLocThetaGraphic :: InterpretUnit u => LocThetaGraphic u+emptyLocThetaGraphic = lift1R2 emptyLocGraphic+++++-- | Use this to convert 'LocThetaGraphic' or 'LocThetaImage' +-- with Functor answer.+--+uconvLocThetaImageF :: (InterpretUnit u, InterpretUnit u1, Functor t) + => LocThetaImage u (t u) -> LocThetaImage u1 (t u1)+uconvLocThetaImageF = uconvR2a szconvAnsF++++-- | Use this to convert 'LocThetaImage' with unit-less answer.+--+uconvLocThetaImageZ :: (InterpretUnit u, InterpretUnit u1) + => LocThetaImage u a -> LocThetaImage u1 a+uconvLocThetaImageZ = uconvR2a szconvAnsZ+++++--------------------------------------------------------------------------------+-- Combining LocThetaImages++{-++infixr 6 `catLTI`+infixr 5 `sepLTI`++-- | Concatenate two LocThetaImages. The start point is /shared/.+--+-- This is just @oplus@.+--+catLTI :: OPlus (t u)+ => LocThetaImage t u -> LocThetaImage t u -> LocThetaImage t u+catLTI = oplus++++-- | Concatenate two LocThetaImages, the second LocThetaImage is +-- displaced /orthonormally/ from the the start point by the +-- supplied vector (separator). +--+-- Here, /orthonormally/ means that the x-component of the vector+-- displaces the second LocThetaImage in parallel to the angle+-- of inclination, the y-component of the vector displaces +-- perpendicular to the incliantion.+--+-- Note - the separator is exactly a displacement of the start+-- point, LocImages have no notion of border so this function+-- can only be used to concatenate to objects side by side if+-- there boundaries are known beforehand.+-- +-- Consider a PosThetaImage if you need more sophisticated arrangement.+-- +sepLTI :: (Floating u, OPlus (t u))+ => Vec2 u -> LocThetaImage t u -> LocThetaImage t u + -> LocThetaImage t u+sepLTI v g1 g2 = g1 `oplus` moveStartTheta (displaceOrtho v) g2++++-- | Concatenate two LocThetaImages, the second LocImage is +-- displaced parallel to the inclination by the supplied distance. +--+-- Note - this is exactly a start point displacement. See the +-- caveat for 'sepLTI'.+-- +paraSepLTI :: (Floating u, OPlus (t u))+ => u -> LocThetaImage t u -> LocThetaImage t u -> LocThetaImage t u+paraSepLTI u = sepLTI (hvec u)++++-- | Concatenate two LocThetaImages, the second LocThetaImage is +-- displaced perpendicular to the inclination by the supplied +-- distance.+--+-- Note - this is exactly a start point displacement. See the +-- caveat for 'sepLTI'.+-- +perpSepLTI :: (Floating u, OPlus (t u))+ => u -> LocThetaImage t u -> LocThetaImage t u -> LocThetaImage t u+perpSepLTI u = sepLTI (vvec u)+++-- | Repeatedly draw a LocThetaImage, moving the start point each time +-- /orthonormally/ by the supplied vector.+--+-- Note - the first LocThetaImage argument is the /empty/ alternative+-- this is drawn if the repeat count is less than 1.+--+repeatLTI :: (Floating u, OPlus (t u))+ => LocThetaImage t u -> Int -> Vec2 u -> LocThetaImage t u + -> LocThetaImage t u+repeatLTI alt i _ _ | i < 1 = alt+repeatLTI _ i v gf = promoteR2 $ \start ang -> body start ang+ where+ body start ang = go (i-1) (drawF start) (moveF start)+ where+ drawF pt = atIncline gf pt ang+ moveF pt = displaceOrtho v ang pt+ go n acc pt | n < 1 = acc+ | otherwise = go (n-1) (acc `oplus` drawF pt) (moveF pt)++++-- | Repeatedly draw a LocThetaImage, moving parallel to the +-- inclination each time by the supplied distance.+--+-- Note - this draws the alternative LocThetaImage if the repeat count +-- is less than 1.+--+paraRepeatLTI :: (Floating u, OPlus (t u))+ => LocThetaImage t u -> Int -> u -> LocThetaImage t u + -> LocThetaImage t u+paraRepeatLTI alt i u = repeatLTI alt i (hvec u) ++++-- | Repeatedly draw a LocThetaImage, moving perpendicular to the+-- inclination each time by the supplied distance.+--+-- Note - this draws the alternative LocThetaImage if the repeat count +-- is less than 1.+--+perpRepeatLTI :: (Floating u, OPlus (t u))+ => LocThetaImage t u -> Int -> u -> LocThetaImage t u -> LocThetaImage t u+perpRepeatLTI alt i u = repeatLTI alt i (vvec u) ++++-- | Concatenate a list of LocThetaImages, spacing them by moving +-- the start point /orthonormally/ each time by the supplied +-- vector.+--+-- Note - this draws the /empty/ alternative if the list is empty.+--+spaceLTI :: (Floating u, OPlus (t u))+ => LocThetaImage t u -> Vec2 u -> [LocThetaImage t u] + -> LocThetaImage t u+spaceLTI alt _ [] = alt+spaceLTI _ v (g:gs) = promoteR2 $ \start ang -> body start ang + where+ body start ang = go (drawF g start) (moveF start) gs+ where+ drawF gf pt = atIncline gf pt ang+ moveF pt = displaceOrtho v ang pt+ go acc _ [] = acc+ go acc pt (f:fs) = go (acc `oplus` drawF f pt) (moveF pt) fs++++-- | Concatenate a list of LocThetaImages, spacing them by moving +-- the start point parallel to the inclination each time by the +-- supplied distance.+--+-- Note - this draws the /empty/ alternative if the list is empty.+--+paraSpaceLTI :: (Floating u, OPlus (t u))+ => LocThetaImage t u -> u -> [LocThetaImage t u] + -> LocThetaImage t u+paraSpaceLTI alt u = spaceLTI alt (hvec u)+++-- | Concatenate a list of LocThetaImages, spacing them by moving +-- the start point perpendicular to the inclination each time by +-- the supplied distance.+--+-- Note - this draws the /empty/ alternative if the list is empty.+--+perpSpaceLTI :: (Floating u, OPlus (t u))+ => LocThetaImage t u -> u -> [LocThetaImage t u] + -> LocThetaImage t u+perpSpaceLTI alt u = spaceLTI alt (vvec u)+++-- | Enclose l r x+--+-- Note - the @left@ LocThetaImage is drawn at the start point, the +-- LocThetaImage @x@ is concatenated with 'sepLTI' then the right +-- LocThetaImage is concatenated with 'sepLi'.+--+encloseLTI :: (Floating u, OPlus (t u))+ => Vec2 u + -> LocThetaImage t u -> LocThetaImage t u -> LocThetaImage t u + -> LocThetaImage t u+encloseLTI v lft rht obj = lft `op` obj `op` rht+ where+ op = sepLTI v++++-- | Parallel version of 'encloseLTI'.+--+-- Note - the @left@ LocThetaImage is drawn at the start point, the +-- LocThetaImage @x@ is concatenated with 'sepLTI' then the right +-- LocThetaImage is concatenated with 'sepLTI'.+--+paraEncloseLTI :: (Floating u, OPlus (t u))+ => u + -> LocThetaImage t u -> LocThetaImage t u -> LocThetaImage t u + -> LocThetaImage t u+paraEncloseLTI u = encloseLTI (hvec u)++++-- | Perpendicular version of 'encloseLTI'.+--+-- Note - the @left@ LocThetaImage is drawn at the start point, the +-- LocThetaImage @x@ is concatenated with 'sepLTI' then the right +-- LocThetaImage is concatenated with 'sepLTI'.+--+perpEncloseLTI :: (Floating u, OPlus (t u))+ => u + -> LocThetaImage t u -> LocThetaImage t u -> LocThetaImage t u + -> LocThetaImage t u+perpEncloseLTI u = encloseLTI (vvec u)++++-- | Concatenate a list of LocThetaImages, punctuating with the +-- separator.+--+-- Note - this draws the /empty/ alternative if the list is empty.+--+punctuateLTI :: (Floating u, OPlus (t u))+ => LocThetaImage t u -> Vec2 u + -> LocThetaImage t u -> [LocThetaImage t u] + -> LocThetaImage t u+punctuateLTI alt _ _ [] = alt+punctuateLTI _ v sep (g:gs) = go g gs+ where + go acc [] = acc+ go acc (f:fs) = go (encloseLTI v acc f sep) fs+++-- | Parallel version of 'punctuateLTI'+--+paraPunctuateLTI :: (Floating u, OPlus (t u))+ => LocThetaImage t u -> u + -> LocThetaImage t u -> [LocThetaImage t u] + -> LocThetaImage t u+paraPunctuateLTI alt u = punctuateLTI alt (hvec u)+++-- | Perpendicular version of 'punctuateLTI'+--+perpPunctuateLTI :: (Floating u, OPlus (t u))+ => LocThetaImage t u -> u + -> LocThetaImage t u -> [LocThetaImage t u] + -> LocThetaImage t u+perpPunctuateLTI alt u = punctuateLTI alt (vvec u)++-}
+ src/Wumpus/Basic/Kernel/Objects/Orientation.hs view
@@ -0,0 +1,500 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.Kernel.Objects.Orientation+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- Graphic objects RectAddress and Orientation to model +-- rectangular positioning.+--+--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Objects.Orientation+ (+++ -- * Components+ RectAddress(..)+ , Orientation(..)++ , orientationStart+ , orientationBounds+ + , extendOrientation+ , extendOLeft+ , extendORight+ , extendODown+ , extendOUp++ , padHEven+ , padXMinor+ , padXMajor+ , padVEven+ , padYMajor+ , padYMinor++ , spineRight+ , spineBelow++ , halignBottomO+ , halignCenterO+ , halignTopO+ , valignLeftO+ , valignCenterO+ , valignRightO++ , spinemoveH+ , spinemoveV+ , binmoveHBottom+ , binmoveHCenter+ , binmoveHTop+ , binmoveVLeft+ , binmoveVCenter+ , binmoveVRight++ ) where+++import Wumpus.Basic.Kernel.Base.BaseDefs++import Wumpus.Core -- package: wumpus-core++import Data.Monoid++-- | Datatype enumerating the addressable positions of a rectangle +-- that can be derived for a 'PosObject'. +--+data RectAddress = CENTER + | NN | SS | EE | WW | NE | NW | SE | SW + | BLL | BLC | BLR+ deriving (Enum,Eq,Ord,Show)+++++-- | Utility datatype representing orientation within a +-- rectangular /frame/. RectPos is useful for graphics such as +-- text where the start point is not necessarily at the center +-- (or bottom left).+--+-- > x_minor is the horizontal distance from the left to the start point+-- >+-- > x_major is the horizontal distance from the start point to the right+-- >+-- > y_minor is the vertical distance from the bottom to the start point+-- >+-- > y_major is the vertical distance from the start point to the top+--+-- Values should be not be negative!+--+-- +data Orientation u = Orientation+ { or_x_minor :: !u+ , or_x_major :: !u+ , or_y_minor :: !u+ , or_y_major :: !u+ }+ deriving (Eq,Ord,Show)+++++--------------------------------------------------------------------------------++instance Functor Orientation where+ fmap f (Orientation xmin xmaj ymin ymaj) = + Orientation (f xmin) (f xmaj) (f ymin) (f ymaj)++instance (Fractional u, Ord u) => OPlus (Orientation u) where+ oplus = concatOrientation+++instance (Fractional u, Ord u) => Monoid (Orientation u) where+ mempty = Orientation 0 0 0 0+ mappend = concatOrientation++-- | Concatenation here essentially turns both Orientation objects+-- into /center-form/ then finds the maximum rectangle.+--+concatOrientation :: (Fractional u, Ord u) + => Orientation u -> Orientation u -> Orientation u+concatOrientation op0 op1 = Orientation hw hw hh hh+ where+ (hw0,hh0) = halfDists op0+ (hw1,hh1) = halfDists op1+ hw = max hw0 hw1+ hh = max hh0 hh1+++++-- | Find the half-width and half-height of an Orientation.+-- +-- Essentially this is /center-form/ of an Orientation, but +-- in /center-form/ there is duplication: +--+-- > xminor == xmajor+-- > yminor == ymajor+-- +-- So instead, the result type is just a pair.+--+halfDists :: Fractional u => Orientation u -> (u,u)+{-# INLINE halfDists #-}+halfDists (Orientation xmin xmaj ymin ymaj) = + (0.5 * (xmin+xmaj), 0.5 * (ymin+ymaj))++++++-- | The vector from a 'RectAddress' to the start point.+--+orientationStart :: Fractional u => RectAddress -> Orientation u -> Vec2 u+orientationStart rpos (Orientation xmin xmaj ymin ymaj) = go rpos+ where+ w = xmin + xmaj+ h = ymin + ymaj+ hw = 0.5 * w+ hh = 0.5 * h+ + -- CENTER, NN, SS, EE, WW all go to bottomleft then add back + -- the minors.++ go CENTER = V2 ((-hw) + xmin) ((-hh) + ymin)+ go NN = V2 ((-hw) + xmin) ((-h) + ymin)+ go SS = V2 ((-hw) + xmin) ymin+ go EE = V2 ((-w) + xmin) ((-hh) + ymin)+ go WW = V2 xmin ((-hh) + ymin)+ go NE = V2 (-xmaj) (-ymaj)+ go SE = V2 (-xmaj) ymin+ go SW = V2 xmin ymin+ go NW = V2 xmin (-ymaj)+ go BLL = V2 xmin 0+ go BLC = V2 ((-hw) + xmin) 0+ go BLR = V2 ((-w) + xmin) 0 +++-- | Calculate the bounding box formed by locating the 'Orientation'+-- at the supplied point.+-- +orientationBounds :: Num u + => Orientation u -> Point2 u -> BoundingBox u+orientationBounds (Orientation xmin xmaj ymin ymaj) (P2 x y) = BBox llc urc+ where+ llc = P2 (x-xmin) (y-ymin)+ urc = P2 (x+xmaj) (y+ymaj)+++--------------------------------------------------------------------------------+-- Extending an arm of the orientation++extendOrientation :: Num u + => u -> u -> u -> u -> Orientation u -> Orientation u+extendOrientation dxl dxr dyd dyu (Orientation xmin xmaj ymin ymaj) = + Orientation (xmin+dxl) (xmaj+dxr) (ymin+dyd) (ymaj+dyu)++extendOLeft :: Num u => u -> Orientation u -> Orientation u+extendOLeft u (Orientation xmin xmaj ymin ymaj) = + Orientation (u+xmin) xmaj ymin ymaj+++extendORight :: Num u => u -> Orientation u -> Orientation u+extendORight u (Orientation xmin xmaj ymin ymaj) = + Orientation xmin (u+xmaj) ymin ymaj++extendODown :: Num u => u -> Orientation u -> Orientation u+extendODown u (Orientation xmin xmaj ymin ymaj) = + Orientation xmin xmaj (u+ymin) ymaj++extendOUp :: Num u => u -> Orientation u -> Orientation u+extendOUp u (Orientation xmin xmaj ymin ymaj) = + Orientation xmin xmaj ymin (u+ymaj)+++--------------------------------------------------------------------------------++padHEven :: (Fractional u, Ord u) + => u -> Orientation u -> Orientation u+padHEven w ortt@(Orientation xmin xmaj _ _) = + if w > ow then ortt { or_x_minor = xmin + hdx+ , or_x_major = xmaj + hdx } + else ortt+ where+ ow = xmin + xmaj+ hdx = 0.5 * (w - ow)+++padXMinor :: (Num u, Ord u) + => u -> Orientation u -> Orientation u+padXMinor w ortt@(Orientation xmin xmaj _ _) = + if w > ow then ortt { or_x_minor = xmin + dx } else ortt+ where+ ow = xmin + xmaj+ dx = w - ow++padXMajor :: (Num u, Ord u)+ => u -> Orientation u -> Orientation u+padXMajor w ortt@(Orientation xmin xmaj _ _) = + if w > ow then ortt { or_x_major = xmaj + dx } else ortt+ where+ ow = xmin + xmaj+ dx = w - ow++padVEven :: (Fractional u, Ord u) + => u -> Orientation u -> Orientation u+padVEven h ortt@(Orientation _ _ ymin ymaj) = + if h > oh then ortt { or_y_minor = ymin + hdy+ , or_y_major = ymaj + hdy } + else ortt+ where+ oh = ymin + ymaj+ hdy = 0.5 * (h - oh)++padYMinor :: (Num u, Ord u) + => u -> Orientation u -> Orientation u+padYMinor h ortt@(Orientation _ _ ymin ymaj) = + if h > oh then ortt { or_y_minor = ymin + dy } else ortt+ where+ oh = ymin + ymaj+ dy = h - oh+++padYMajor :: (Num u, Ord u) + => u -> Orientation u -> Orientation u+padYMajor h ortt@(Orientation _ _ ymin ymaj) = + if h > oh then ortt { or_y_major = ymaj + dy } else ortt+ where+ oh = ymin + ymaj+ dy = h - oh+++--------------------------------------------------------------------------------+-- Combining Orientation++-- Note - there are lots of concatenations (due to alignment) +-- we need a consistent name scheme...+++-- | Second Orientation is moved /to the right/ of the first along+-- the /spine/ i.e the baseline.+--+spineRight :: (Num u, Ord u) + => Orientation u -> Orientation u -> Orientation u+spineRight (Orientation xmin0 xmaj0 ymin0 ymaj0) + (Orientation xmin1 xmaj1 ymin1 ymaj1) = + Orientation { or_x_minor = xmin0+ , or_x_major = xmaj0 + xmin1 + xmaj1 + , or_y_minor = max ymin0 ymin1+ , or_y_major = max ymaj0 ymaj1+ }+++-- | Second Orientation is moved /below/ the first along the spine+-- i.e. the vertical point between the left minor and right major+-- (not the same as the horizontal center).+--+spineBelow :: (Num u, Ord u) + => Orientation u -> Orientation u -> Orientation u+spineBelow (Orientation xmin0 xmaj0 ymin0 ymaj0) + (Orientation xmin1 xmaj1 ymin1 ymaj1) = + Orientation { or_x_minor = max xmin0 xmin1+ , or_x_major = max xmaj0 xmaj1+ , or_y_minor = ymin0 + ymaj1 + ymin1+ , or_y_major = ymaj0+ }+++-- | xmin and xmaj same as left.+--+halignBottomO :: (Num u, Ord u) + => Orientation u -> Orientation u -> Orientation u+halignBottomO (Orientation xmin0 xmaj0 ymin0 ymaj0) + (Orientation xmin1 xmaj1 ymin1 ymaj1) = + let hr = ymin1 + ymaj1+ in Orientation { or_x_minor = xmin0+ , or_x_major = xmaj0 + xmin1 + xmaj1+ , or_y_minor = ymin0+ , or_y_major = max ymaj0 (hr - ymin0)+ }++++++-- | xmin same as left.+--+halignCenterO :: (Fractional u, Ord u) + => Orientation u -> Orientation u -> Orientation u+halignCenterO (Orientation xmin0 xmaj0 ymin0 ymaj0) + (Orientation xmin1 xmaj1 ymin1 ymaj1) = + let hl = ymin0 + ymaj0+ hr = ymin1 + ymaj1+ half_diff = 0.5 * (hr - hl)+ in Orientation + { or_x_minor = xmin0+ , or_x_major = xmaj0 + xmin1 + xmaj1+ , or_y_minor = if hl >= hr then ymin0 else (ymin0 + half_diff)+ , or_y_major = if hl >= hr then ymaj0 else (ymaj0 + half_diff)+ }++++-- | xmin and ymaj same as left.+--+halignTopO :: (Num u, Ord u) + => Orientation u -> Orientation u -> Orientation u+halignTopO (Orientation xmin0 xmaj0 ymin0 ymaj0) + (Orientation xmin1 xmaj1 ymin1 ymaj1) = + let hr = ymin1 + ymaj1+ in Orientation { or_x_minor = xmin0+ , or_x_major = xmaj0 + xmin1 + xmaj1+ , or_y_minor = max ymin0 (hr - ymaj0)+ , or_y_major = ymaj0+ }++-- | Align second below - xmin and ymaj are same as left.+--+valignLeftO :: (Fractional u, Ord u) + => Orientation u -> Orientation u -> Orientation u+valignLeftO (Orientation xmin0 xmaj0 ymin0 ymaj0) + (Orientation xmin1 xmaj1 ymin1 ymaj1) = + let wr = xmin1 + xmaj1+ in Orientation { or_x_minor = xmin0+ , or_x_major = max xmaj0 (wr - xmin0)+ , or_y_minor = ymin0 + ymin1 + ymaj1+ , or_y_major = ymaj0+ }++++-- | Align second below - ymaj same as left.+--+valignCenterO :: (Fractional u, Ord u) + => Orientation u -> Orientation u -> Orientation u+valignCenterO (Orientation xmin0 xmaj0 ymin0 ymaj0) + (Orientation xmin1 xmaj1 ymin1 ymaj1) = + let wl = xmin0 + xmaj0+ wr = xmin1 + xmaj1+ half_diff = 0.5 * (wr - wl)+ in Orientation + { or_x_minor = if wl >= wr then xmin0 else (xmin0 + half_diff)+ , or_x_major = if wl >= wr then xmaj0 else (xmaj0 + half_diff)+ , or_y_minor = ymin0 + ymin1 + ymaj1+ , or_y_major = ymaj0 + }+++-- | Align second below - xmaj and ymaj are same as left.+--+valignRightO :: (Fractional u, Ord u) + => Orientation u -> Orientation u -> Orientation u+valignRightO (Orientation xmin0 xmaj0 ymin0 ymaj0) + (Orientation xmin1 xmaj1 ymin1 ymaj1) = + let wr = xmin1 + xmaj1+ in Orientation { or_x_minor = max xmin0 (wr - xmaj0)+ , or_x_major = xmaj0 + , or_y_minor = ymin0 + ymin1 + ymaj1+ , or_y_major = ymaj0 + }+++--------------------------------------------------------------------------------+-- Binary start pos displacement++upDown :: Num u => u -> u -> u+{-# INLINE upDown #-}+upDown u d = u - d++downUp :: Num u => u -> u -> u+{-# INLINE downUp #-}+downUp d u = negate d + u++-- | Move second right.+--+spinemoveH :: Num u => Orientation u -> Orientation u -> Vec2 u+spinemoveH op0 op1 = V2 hdist 0+ where+ hdist = or_x_major op0 + or_x_minor op1++-- | Move second below.+--+spinemoveV :: Num u => Orientation u -> Orientation u -> Vec2 u+spinemoveV op0 op1 = V2 0 (negate vdist)+ where+ vdist = or_y_minor op0 + or_y_major op1+ +++binmoveHBottom :: Num u => Orientation u -> Orientation u -> Vec2 u+binmoveHBottom op0 op1 = V2 hdist vdist+ where+ hdist = or_x_major op0 + or_x_minor op1+ vdist = downUp (or_y_minor op0) (or_y_minor op1)+ ++binmoveHCenter :: (Fractional u, Ord u) + => Orientation u -> Orientation u -> Vec2 u+binmoveHCenter (Orientation _ xmaj0 ymin0 ymaj0) + (Orientation xmin1 _ ymin1 ymaj1) = + V2 hdist vdist+ where+ h0 = ymin0 + ymaj0+ h1 = ymin1 + ymaj1+ half_diff = abs $ 0.5 * (h1 - h0)+ hdist = xmaj0 + xmin1+ vdist = if h0 >= h1 then downUp ymin0 (half_diff + ymin1)+ else upDown (ymaj0 + half_diff) ymaj1++++binmoveHTop :: Num u => Orientation u -> Orientation u -> Vec2 u+binmoveHTop op0 op1 = V2 hdist vdist+ where+ hdist = or_x_major op0 + or_x_minor op1+ vdist = upDown (or_y_major op0) (or_y_major op1)+++leftRight :: Num u => u -> u -> u+{-# INLINE leftRight #-}+leftRight l r = negate l + r+++rightLeft :: Num u => u -> u -> u+{-# INLINE rightLeft #-}+rightLeft r l = r - l+++binmoveVLeft :: Num u => Orientation u -> Orientation u -> Vec2 u+binmoveVLeft op0 op1 = V2 hdist vdist+ where+ hdist = leftRight (or_x_minor op0) (or_x_minor op1)+ vdist = negate $ or_y_minor op0 + or_y_major op1+++binmoveVCenter :: (Fractional u, Ord u) + => Orientation u -> Orientation u -> Vec2 u+binmoveVCenter (Orientation xmin0 xmaj0 ymin0 _) + (Orientation xmin1 xmaj1 _ ymaj1) = + V2 hdist vdist+ where+ w0 = xmin0 + xmaj0+ w1 = xmin1 + xmaj1+ half_diff = abs $ 0.5 * (w1 - w0)+ hdist = if w0 >= w1 then leftRight xmin0 (half_diff + xmin1)+ else rightLeft (xmaj0 + half_diff) xmaj1+ vdist = negate $ ymin0 + ymaj1++++binmoveVRight :: Num u => Orientation u -> Orientation u -> Vec2 u+binmoveVRight op0 op1 = V2 hdist vdist+ where+ hdist = rightLeft (or_x_major op0) (or_x_major op1)+ vdist = negate $ or_y_minor op0 + or_y_major op1+
− src/Wumpus/Basic/Kernel/Objects/PosImage.hs
@@ -1,237 +0,0 @@-{-# LANGUAGE TypeFamilies #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.Kernel.Objects.PosImage--- Copyright : (c) Stephen Tetley 2011--- License : BSD3------ Maintainer : stephen.tetley@gmail.com--- Stability : highly unstable--- Portability : GHC ------ Extended Graphic object - a rectangular /positionable/ Image.--- --- This graphic object has a more flexible API for positioning --- than other graphic objects. Rather than a LocGraphic which --- supports a single method of positioning at some start-point,--- a @PosGraphic@ can be drawn at its center or locations on its --- outer rectangle.--------------------------------------------------------------------------------------module Wumpus.Basic.Kernel.Objects.PosImage- (-- RectPosition(..)- , ObjectPos(..)-- -- * Positionable image-- , PosImage- , DPosImage -- , PosGraphic- , DPosGraphic-- , makePosImage-- , startPos- , atStartPos-- , objectPosBounds-- ) where---import Wumpus.Basic.Kernel.Base.BaseDefs-import Wumpus.Basic.Kernel.Base.ContextFun-import Wumpus.Basic.Kernel.Objects.BaseObjects-import Wumpus.Basic.Kernel.Objects.Displacement--import Wumpus.Core -- package: wumpus-core--import Data.AffineSpace -- package: vector-space---- | Datatype enumerating positions within a rectangle that can be--- derived for a 'PosGraphic'. ----data RectPosition = CENTER | NN | SS | EE | WW | NE | NW | SE | SW - deriving (Enum,Eq,Ord,Show)----- | Utility datatype representing orientation within a --- rectangular /frame/. ObjectPos is useful for graphics such as --- text where the start point is not necessarily at the center --- (or bottom left).------ > x_minor is the horizontal distance from the left to the start point--- >--- > x_major is the horizontal distance from the start point to the right--- >--- > y_minor is the vertical distance from the bottom to the start point--- >--- > y_major is the vertical distance from the start point to the top------ Values should be not be negative!------ -data ObjectPos u = ObjectPos - { op_x_minor :: !u- , op_x_major :: !u- , op_y_minor :: !u- , op_y_major :: !u- }- deriving (Eq,Ord,Show)----type instance DUnit (ObjectPos u) = u------ | A positionable Image.----type PosImage u a = CF2 (Point2 u) RectPosition (ImageAns u a)- --- | Version of PosImage specialized to Double for the unit type.----type DPosImage a = PosImage Double a------ | A positionable Graphic.----type PosGraphic u = PosImage u (UNil u) - --- | Version of PosGraphic specialized to Double for the unit type.----type DPosGraphic = PosGraphic Double------------------------------------------------------------------------------------------instance (Fractional u, Ord u) => OPlus (ObjectPos u) where- oplus = concatObjectPos----- | Concatenation here essentially turns both ObjectPos objects--- into /center-form/ then finds the maximum rectangle.----concatObjectPos :: (Fractional u, Ord u) - => ObjectPos u -> ObjectPos u -> ObjectPos u-concatObjectPos op0 op1 = ObjectPos hw hw hh hh- where- (hw0,hh0) = halfDists op0- (hw1,hh1) = halfDists op1- hw = max hw0 hw1- hh = max hh0 hh1----------------------------------------------------------------------------------------- | Find the half-width and half-height of an ObjectPos.--- --- Essentially this is /center-form/ of an ObjectPos, but --- in /center-form/ there is duplication: ------ > xminor == xmajor--- > yminor == ymajor--- --- So instead, the result type is just a pair.----halfDists :: Fractional u => ObjectPos u -> (u,u)-halfDists (ObjectPos xmin xmaj ymin ymaj) = - (0.5 * (xmin+xmaj), 0.5 * (ymin+ymaj))----- | 'makePosImage' : @ object_pos * loc_graphic -> PosGraphic @ ------ Create a 'PosImage' from an 'ObjectPos' describing how it--- is orientated within a border rectangle and a 'LocImage' that --- draws it.----makePosImage :: Fractional u - => ObjectPos u -> LocImage u a -> PosImage u a-makePosImage opos gf = promoteR2 $ \start rpos -> - let v1 = startVector rpos opos in gf `at` displaceVec v1 start----infixr 1 `startPos`---- | 'startPos' : @ pos_image * rect_pos -> LocImage @------ /Downcast/ a 'PosImage' to a 'LocImage' by supplying it --- with a 'RectPosition' (start position).--- -startPos :: Floating u - => PosImage u a -> RectPosition -> LocImage u a-startPos = apply1R2- --- | 'atStartPos' : @ pos_image * start_point * rect_pos -> LocImage @------ /Downcast/ a 'PosGraphic' to an 'Image' by supplying it --- with an initial point and a 'RectPosition' (start position).--- -atStartPos :: Floating u - => PosImage u a -> Point2 u -> RectPosition -> Image u a-atStartPos = apply2R2---- | The vector from some Rectangle position to the start point.----startVector :: Fractional u => RectPosition -> ObjectPos u -> Vec2 u-startVector rpos (ObjectPos xminor xmajor yminor ymajor) = go rpos- where- w = xminor + xmajor- h = yminor + ymajor- hw = 0.5 * w- hh = 0.5 * h- - -- CENTER, NN, SS, EE, WW all go to bottomleft then add back - -- the minors.-- go CENTER = V2 ((-hw) + xminor) ((-hh) + yminor)- go NN = V2 ((-hw) + xminor) ((-h) + yminor)- go SS = V2 ((-hw) + xminor) yminor- go EE = V2 ((-w) + xminor) ((-hh) + yminor)- go WW = V2 xminor ((-hh) + yminor)- go NE = V2 (-xmajor) (-ymajor)- go SE = V2 (-xmajor) yminor- go SW = V2 xminor yminor- go NW = V2 xminor (-ymajor)------ | Calculate the bounding box formed by locating the 'ObjectPos'--- at the supplied point.--- -objectPosBounds :: Fractional u - => Point2 u -> RectPosition -> ObjectPos u -> BoundingBox u-objectPosBounds (P2 x y) pos (ObjectPos xmin xmaj ymin ymaj) = go pos- where- w = xmin + xmaj- h = ymin + ymaj- hw = 0.5 * w- hh = 0.5 * h- bbox = \bl -> BBox bl (bl .+^ vec w h)-- go CENTER = bbox $ P2 (x-hw) (y-hh)- go NN = bbox $ P2 (x-hw) (y-h)- go SS = bbox $ P2 (x-hw) y- go EE = bbox $ P2 (x-w) (y-hh)- go WW = bbox $ P2 x (y-hh)- go NE = bbox $ P2 (x-w) (y-h)- go SE = bbox $ P2 (x-w) y- go SW = bbox $ P2 x y- go NW = bbox $ P2 x (y-h)--
+ src/Wumpus/Basic/Kernel/Objects/PosObject.hs view
@@ -0,0 +1,446 @@+{-# LANGUAGE TypeFamilies #-}+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.Kernel.Objects.PosObject+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- Extended Graphic object - a rectangular /positionable/ Image.+-- +-- This graphic object has a more flexible API for positioning +-- than other graphic objects. Rather than a LocGraphic which +-- supports a single method of positioning at some start-point,+-- a @PosGraphic@ can be drawn at its center or locations on its +-- outer rectangle.+--+--------------------------------------------------------------------------------++module Wumpus.Basic.Kernel.Objects.PosObject+ (++ -- * Positionable image++ PosObject+ , DPosObject++ , LocRectQuery+ , BoundedLocRectGraphic++ -- * Operations++ , makePosObject+ , makeBindPosObject+ , emptyPosObject+ , runPosObjectR0+ , runPosObjectR1+ , runPosObjectR2+++ , localizePO + , elaboratePO+ , aelaboratePO + + , startAddr+ , atStartAddr++ , extendPosObject++ , padHorizontalPO+ , padLeftPO+ , padRightPO+ , padVerticalPO+ , padUpPO+ , padDownPO++ , illustratePosObject+++ ) where+++import Wumpus.Basic.Kernel.Base.BaseDefs+import Wumpus.Basic.Kernel.Base.ContextFun+import Wumpus.Basic.Kernel.Base.DrawingContext+import Wumpus.Basic.Kernel.Base.QueryDC+import Wumpus.Basic.Kernel.Base.UpdateDC+import Wumpus.Basic.Kernel.Objects.Basis+import Wumpus.Basic.Kernel.Objects.Bounded+import Wumpus.Basic.Kernel.Objects.Concat+import Wumpus.Basic.Kernel.Objects.DrawingPrimitives+import Wumpus.Basic.Kernel.Objects.Displacement+import Wumpus.Basic.Kernel.Objects.LocImage+import Wumpus.Basic.Kernel.Objects.Orientation++import Wumpus.Core -- package: wumpus-core+import Wumpus.Core.Colour ( red, blue )++import Data.AffineSpace -- package: vector-space+import Data.VectorSpace++import Control.Applicative+import Data.Monoid+++-- | Helper for PosObject - a LocImage that is /pre-applied/ to +-- the DrawingContext.+--+-- This is somewhat contrived, but the orientation and the result+-- graphic from a PosImage have to be generated within the same +-- DrawingContext.+--+type PosDraw u = Point2 u -> GraphicAns u+++-- | A positionable \"Object\" that is drawn as a +-- 'BoundedLocGraphic'.+--+newtype PosObject u = PosObject + { getPosObject :: CF (Orientation u, PosDraw u) }++type instance DUnit (PosObject u) = u+ +-- | Version of PosObject specialized to Double for the unit type.+--+type DPosObject = PosObject Double+++++type LocRectQuery u a = CF (Point2 u -> RectAddress -> a)++type BoundedLocRectGraphic u = LocRectQuery u (ImageAns u (BoundingBox u))++--------------------------------------------------------------------------------+++instance (Fractional u, Ord u) => OPlus (PosObject u) where+ oplus = poconcat++instance (Fractional u, Ord u, InterpretUnit u) => Monoid (PosObject u) where+ mempty = pozero+ mappend = poconcat+++pozero :: InterpretUnit u => PosObject u+pozero = PosObject body+ where+ body = drawingCtx >>= \ctx -> + let pf = \pt -> runCF ctx (apply1R1 emptyLocGraphic pt)+ in return (Orientation 0 0 0 0, pf)++poconcat :: (Fractional u, Ord u) => PosObject u -> PosObject u -> PosObject u+poconcat a b = PosObject body+ where+ body = drawingCtx >>= \ctx -> + let (o0,pf0) = runCF ctx (getPosObject a)+ (o1,pf1) = runCF ctx (getPosObject b)+ pf = \pt -> pf0 pt `oplus` pf1 pt+ in return (o0 `oplus` o1, pf)+++-- | 'makePosObject' : @ object_pos * loc_image -> PosObject @ +--+-- Create a 'PosObject' from an 'Orientation' describing how it+-- is orientated within a border rectangle and a 'LocImage' that +-- draws it.+--+-- This is the /primary/ constructor for PosObjects. Because the+-- PosObject type is considered as a specialized object it does+-- not have the range of functions of LocImage or LocThetaImage.+-- +makePosObject :: Query (Orientation u) -> LocGraphic u -> PosObject u+makePosObject qortt gf = PosObject body+ where+ body = drawingCtx >>= \ctx -> + let ortt = runCF ctx qortt+ pf = runCF ctx gf+ in return (ortt,pf)+++-- | This is a bit of a hack to overcome that the newtype +-- wrapper around PosObject stops monadic bind operating +-- with the internal CF function.+--+makeBindPosObject :: Query a + -> (a -> Query (Orientation u)) -> (a -> LocGraphic u) + -> PosObject u +makeBindPosObject qy mkO mkG = PosObject body+ where+ body = drawingCtx >>= \ctx -> + let a = runCF ctx qy+ ortt = runCF ctx (mkO a)+ pf = runCF ctx (mkG a)+ in return (ortt,pf)++++-- | 'emptyPosObject' : @ PosObject @+--+-- Build an empty 'PosGraphicObject'.+--+emptyPosObject :: InterpretUnit u => PosObject u+emptyPosObject = + makePosObject (pure $ Orientation 0 0 0 0) emptyLocGraphic++ +-- | Run a PosObject forming an Image (an /arity zero/ answer).+--+runPosObjectR0 :: Fractional u + => Point2 u -> RectAddress -> PosObject u -> BoundedGraphic u+runPosObjectR0 pt addr (PosObject mf) = + mf >>= \(ortt,ptf) -> let sv = orientationStart addr ortt+ bb = orientationBounds ortt (displaceVec sv pt)+ in pure $ replaceAns bb $ ptf $ displaceVec sv pt++++-- | Version of 'runPosObject' that produces a +-- 'BoundedLocGraphic'. +-- +-- The 'PosObject' is run with only rect-address as an explicit +-- argument (start-point is implicit). The corresponding answer is +-- an /arity one/ Graphic that needs drawing with the start-point.+--+runPosObjectR1 :: Fractional u + => RectAddress -> PosObject u -> BoundedLocGraphic u+runPosObjectR1 addr obj = promoteR1 $ \start -> runPosObjectR0 start addr obj+++-- | Version of 'runPosObject' that produces a +-- 'BoundedLocRectGraphic'. +-- +-- The 'PosObject' is run with no explicit arguments (rect-address +-- or start-point) so the corresponding answer is an /arity two/ +-- Graphic that needs drawing with the start-point and +-- rect-address.+--+runPosObjectR2 :: Fractional u + => PosObject u -> BoundedLocRectGraphic u+runPosObjectR2 obj = promoteR2 $ \start addr -> runPosObjectR0 start addr obj++++-- | Run a DrawingContext update within a 'PosObject'.+--+localizePO :: DrawingContextF -> PosObject u -> PosObject u+localizePO upd = PosObject . localize upd . getPosObject+++-- | 'decorate' -like functionality.+--+elaboratePO :: (Orientation u -> LocGraphic u) -> PosObject u -> PosObject u+elaboratePO fn po = PosObject body+ where+ body = drawingCtx >>= \ctx -> + let (ortt,ptf) = runCF ctx (getPosObject po)+ deco = runCF ctx (fn ortt)+ in return (ortt, ptf `oplus` deco)++-- | ante-eloborate+--+aelaboratePO :: (Orientation u -> LocGraphic u) -> PosObject u -> PosObject u+aelaboratePO fn po = PosObject body+ where+ body = drawingCtx >>= \ctx -> + let (ortt,ptf) = runCF ctx (getPosObject po)+ deco = runCF ctx (fn ortt)+ in return (ortt, deco `oplus` ptf)++++++infixr 1 `startAddr`++-- | 'startAddr' : @ bounded_loc_rect * rect_pos -> BoundedlocGraphic @+--+-- /Downcast/ a 'BoundedLocRectGraphic' to a 'BoundedLocGraphic' +-- by supplying it with a 'RectAddress' (start address on the +-- rectangle frame).+-- +startAddr :: Floating u + => BoundedLocRectGraphic u -> RectAddress -> BoundedLocGraphic u+startAddr = apply1R2 ++++-- | 'atStartAddr' : @ bounded_loc_rect * start_point * rect_pos +-- -> BoundedGraphic @+--+-- /Downcast/ a 'BoundedLocRectGraphic' to a 'BoundedGraphic' by +-- supplying it with an initial point and a 'RectAddress' (start +-- address on the rectangle frame).+-- +atStartAddr :: Floating u + => BoundedLocRectGraphic u -> Point2 u -> RectAddress + -> BoundedGraphic u+atStartAddr = apply2R2++++-- | Extend the orientation.+--+extendPosObject :: Num u + => u -> u -> u -> u -> PosObject u -> PosObject u+extendPosObject x0 x1 y0 y1 po = PosObject body+ where+ body = drawingCtx >>= \ctx -> + let (o0,pf0) = runCF ctx (getPosObject po)+ ortt = extendOrientation x0 x1 y0 y1 o0+ in return (ortt,pf0)++ +--------------------------------------------------------------------------------+-- Padding++padHorizontalPO :: (Fractional u, Ord u) => u -> PosObject u -> PosObject u+padHorizontalPO w = genPad (padHEven w)++padLeftPO :: (Num u, Ord u) => u -> PosObject u -> PosObject u+padLeftPO w = genPad (padXMinor w)++padRightPO :: (Num u, Ord u) => u -> PosObject u -> PosObject u+padRightPO w = genPad (padXMajor w)+++padVerticalPO :: (Fractional u, Ord u) => u -> PosObject u -> PosObject u+padVerticalPO w = genPad (padVEven w)++padUpPO :: (Num u, Ord u) => u -> PosObject u -> PosObject u+padUpPO h = genPad (padYMajor h)++padDownPO :: (Num u, Ord u) => u -> PosObject u -> PosObject u+padDownPO h = genPad (padYMinor h)+++genPad :: (Orientation u -> Orientation u) -> PosObject u -> PosObject u+genPad fn po = PosObject body+ where+ body = drawingCtx >>= \ctx -> + let (o0,pf0) = runCF ctx (getPosObject po)+ ortt = fn o0+ in return (ortt,pf0)+++--------------------------------------------------------------------------------+++-- | Illustrate a 'PosObject' by super-imposing its 'Orientation'.+--+-- This turns the 'PosObject' into a 'LocImage' drawn at the locus+-- of the PosObject.+--+illustratePosObject :: InterpretUnit u + => PosObject u -> LocGraphic u+illustratePosObject (PosObject mf) = promoteR1 $ \pt -> + mf >>= \(ortt,ptf) -> + decorateR0 (pure $ ptf pt) (illustrateOrientation ortt `at` pt)+++illustrateOrientation :: InterpretUnit u + => Orientation u -> LocGraphic u+illustrateOrientation (Orientation xmin xmaj ymin ymaj) = promoteR1 $ \pt -> + dinterpCtx 3 >>= \radius -> + let upd = localize (fill_colour blue . dotted_line)+ bl = pt .-^ V2 xmin ymin+ dot = localize (fill_colour red) $ filledDisk radius `at` pt+ hln = upd $ locStraightLine (hvec $ xmin+xmaj) `at` pt .-^ hvec xmin+ vln = upd $ locStraightLine (vvec $ ymin+ymaj) `at` pt .-^ vvec ymin+ bdr = upd $ strokedRectangle (xmin+xmaj) (ymin+ymaj) `at` bl+ in bdr `oplus` hln `oplus` vln `oplus` dot+++--------------------------------------------------------------------------------+-- Combining PosObject+++instance (Fractional u, Ord u) => ZConcat (PosObject u) where+ superior = oplus+ anterior = flip oplus+++instance (Num u, Ord u) => Concat (PosObject u) where+ hconcat = genMoveAlign spinemoveH spineRight+ vconcat = genMoveAlign spinemoveV spineBelow++instance (Num u, Ord u) => CatSpace (PosObject u) where+ hspace = genMoveSepH spinemoveH spineRight+ vspace = genMoveSepV spinemoveV spineBelow++++instance (Fractional u, Ord u) => Align (PosObject u) where+ halign HTop = genMoveAlign binmoveHTop halignTopO+ halign HCenter = genMoveAlign binmoveHCenter halignCenterO+ halign HBottom = genMoveAlign binmoveHBottom halignBottomO++ valign VLeft = genMoveAlign binmoveVLeft valignLeftO+ valign VCenter = genMoveAlign binmoveVCenter valignCenterO+ valign VRight = genMoveAlign binmoveVRight valignRightO++++genMoveAlign :: (Num u) + => (Orientation u -> Orientation u -> Vec2 u) + -> (Orientation u -> Orientation u -> Orientation u) + -> PosObject u -> PosObject u -> PosObject u+genMoveAlign mkV mkO po0 po1 = PosObject body+ where+ body = drawingCtx >>= \ctx -> + let (ortt0,pf0) = runCF ctx (getPosObject po0)+ (ortt1,pf1) = runCF ctx (getPosObject po1)+ v1 = mkV ortt0 ortt1+ ortt = mkO ortt0 ortt1+ pf = \pt -> pf0 pt `oplus` (pf1 $ pt .+^ v1)+ in return (ortt,pf)+++--------------------------------------------------------------------------------+-- Sep++instance (Fractional u, Ord u) => AlignSpace (PosObject u) where+ halignSpace HTop = genMoveSepH binmoveHTop halignTopO+ halignSpace HCenter = genMoveSepH binmoveHCenter halignCenterO+ halignSpace HBottom = genMoveSepH binmoveHBottom halignBottomO++ valignSpace VLeft = genMoveSepV binmoveVLeft valignLeftO+ valignSpace VCenter = genMoveSepV binmoveVCenter valignCenterO+ valignSpace VRight = genMoveSepV binmoveVRight valignRightO+++genMoveSepH :: (Num u) + => (Orientation u -> Orientation u -> Vec2 u) + -> (Orientation u -> Orientation u -> Orientation u) + -> u+ -> PosObject u -> PosObject u -> PosObject u+genMoveSepH mkV mkO sep po0 po1 = PosObject body+ where+ body = drawingCtx >>= \ctx -> + let (ortt0,pf0) = runCF ctx (getPosObject po0)+ (ortt1,pf1) = runCF ctx (getPosObject po1)+ v1 = hvec sep ^+^ mkV ortt0 ortt1+ ortt = extendORight sep $ mkO ortt0 ortt1+ pf = \pt -> pf0 pt `oplus` (pf1 $ pt .+^ v1)+ in return (ortt,pf)+++genMoveSepV :: (Num u) + => (Orientation u -> Orientation u -> Vec2 u) + -> (Orientation u -> Orientation u -> Orientation u) + -> u+ -> PosObject u -> PosObject u -> PosObject u+genMoveSepV mkV mkO sep po0 po1 = PosObject body+ where+ body = drawingCtx >>= \ctx -> + let (ortt0,pf0) = runCF ctx (getPosObject po0)+ (ortt1,pf1) = runCF ctx (getPosObject po1)+ v1 = vvec (-sep) ^+^ mkV ortt0 ortt1+ ortt = extendODown sep $ mkO ortt0 ortt1+ pf = \pt -> pf0 pt `oplus` (pf1 $ pt .+^ v1)+ in return (ortt,pf)
src/Wumpus/Basic/Kernel/Objects/TraceDrawing.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}@@ -7,7 +6,7 @@ -------------------------------------------------------------------------------- -- | -- Module : Wumpus.Basic.Kernel.Objects.TraceDrawing--- Copyright : (c) Stephen Tetley 2010+-- Copyright : (c) Stephen Tetley 2010-2011 -- License : BSD3 -- -- Maintainer : stephen.tetley@gmail.com@@ -23,7 +22,10 @@ module Wumpus.Basic.Kernel.Objects.TraceDrawing ( - TraceDrawing+ -- * Collect primitives (writer monad) + TraceM(..)++ , TraceDrawing , DTraceDrawing , TraceDrawingT , DTraceDrawingT@@ -40,16 +42,20 @@ , mbPictureU - , query+ , evalQuery+ , draw- , xdraw , drawi- , drawi_- , xdrawi- , xdrawi_+ , drawl+ , drawli+ , drawc+ , drawci , node , nodei+ + , drawrc+ , drawrci ) where @@ -57,9 +63,13 @@ import Wumpus.Basic.Kernel.Base.BaseDefs import Wumpus.Basic.Kernel.Base.ContextFun import Wumpus.Basic.Kernel.Base.DrawingContext+import Wumpus.Basic.Kernel.Base.QueryDC import Wumpus.Basic.Kernel.Base.WrappedPrimitive-import Wumpus.Basic.Kernel.Objects.BaseObjects-import Wumpus.Basic.Kernel.Objects.Graphic+import Wumpus.Basic.Kernel.Objects.Anchors+import Wumpus.Basic.Kernel.Objects.Basis+import Wumpus.Basic.Kernel.Objects.Connector+import Wumpus.Basic.Kernel.Objects.Image+import Wumpus.Basic.Kernel.Objects.LocImage import Wumpus.Core -- package: wumpus-core @@ -68,7 +78,18 @@ import Data.Monoid +-------------------------------------------------------------------------------- +++-- | Collect elementary graphics as part of a larger drawing.+--+-- TraceM works much like a writer monad.+--+class TraceM (m :: * -> *) where+ trace :: MonUnit (m ()) ~ u => HPrim u -> m ()+ fontDelta :: m a -> m a+ -- Note - TraceDrawing run \once\ - it is supplied with the starting -- environment (DrawingContext) and returns a Picture. --@@ -84,17 +105,15 @@ newtype TraceDrawingT u m a = TraceDrawingT { getTraceDrawingT :: DrawingContext -> m (a, HPrim u) } +type instance MonUnit (TraceDrawing u a) = u+type instance MonUnit (TraceDrawingT u m a) = u + type DTraceDrawing a = TraceDrawing Double a type DTraceDrawingT m a = TraceDrawingT Double m a -type instance MonUnit (TraceDrawing u) = u-type instance MonUnit (TraceDrawingT u m) = u--- -- Functor instance Functor (TraceDrawing u) where@@ -157,25 +176,42 @@ -- the drawing model would be valuable. -- -instance TraceM (TraceDrawing u) where+instance TraceM (TraceDrawing u) where trace a = TraceDrawing $ \_ -> ((), a)+ fontDelta = fontDeltaMon +fontDeltaMon :: TraceDrawing u a -> TraceDrawing u a+fontDeltaMon mf = TraceDrawing $ \ctx -> + let (_,font_attrs) = runCF ctx textAttr+ (a,hf) = runTraceDrawing ctx mf+ prim = fontDeltaContext font_attrs $ primGroup $ hprimToList hf+ in (a, singleH $ prim1 $ prim) instance Monad m => TraceM (TraceDrawingT u m) where trace a = TraceDrawingT $ \_ -> return ((), a)+ fontDelta = fontDeltaTrans +fontDeltaTrans :: Monad m => TraceDrawingT u m a -> TraceDrawingT u m a+fontDeltaTrans mf = TraceDrawingT $ \ctx -> + let (_,font_props) = runCF ctx textAttr+ in runTraceDrawingT ctx mf >>= \(a,hf) ->+ let prim = fontDeltaContext font_props $ primGroup $ hprimToList hf+ in return (a, singleH $ prim1 $ prim) + -- DrawingCtxM instance DrawingCtxM (TraceDrawing u) where askDC = TraceDrawing $ \ctx -> (ctx, mempty)+ asksDC f = TraceDrawing $ \ctx -> (f ctx, mempty) localize upd ma = TraceDrawing $ \ctx -> getTraceDrawing ma (upd ctx) instance Monad m => DrawingCtxM (TraceDrawingT u m) where- askDC = TraceDrawingT $ \ctx -> return (ctx,mempty)+ askDC = TraceDrawingT $ \ctx -> return (ctx, mempty)+ asksDC f = TraceDrawingT $ \ctx -> return (f ctx, mempty) localize upd ma = TraceDrawingT $ \ctx -> getTraceDrawingT ma (upd ctx) @@ -231,7 +267,7 @@ -- -- If the HPrim is empty, a run-time error is thrown. -- -liftToPictureU :: (Real u, Floating u, FromPtSize u) => HPrim u -> Picture u+liftToPictureU :: HPrim u -> Picture liftToPictureU hf = let prims = hprimToList hf in if null prims then errK else frame prims where@@ -241,8 +277,7 @@ -- -- If the HPrim is empty, then @Nothing@ is returned. -- -liftToPictureMb :: (Real u, Floating u, FromPtSize u) - => HPrim u -> Maybe (Picture u)+liftToPictureMb :: HPrim u -> Maybe Picture liftToPictureMb hf = let prims = hprimToList hf in if null prims then Nothing else Just (frame prims) @@ -259,8 +294,7 @@ -- -- If the supplied value is @Nothing@ a run-time error is thrown. -- -mbPictureU :: (Real u, Floating u, FromPtSize u) - => Maybe (Picture u) -> Picture u+mbPictureU :: Maybe Picture -> Picture mbPictureU Nothing = error "mbPictureU - empty picture." mbPictureU (Just a) = a @@ -268,25 +302,29 @@ -- a very simple way to run graphics without concern for return -- type or initial drawing context. ++ -------------------------------------------------------------------------------- -query :: DrawingCtxM m => CF a -> m a-query df = askDC >>= \ctx -> return $ runCF ctx df +evalQuery :: DrawingCtxM m => Query a -> m a+evalQuery df = askDC >>= \ctx -> return $ runCF ctx df ++ -- | Draw a Graphic taking the drawing style from the -- /drawing context/. ----- This operation is analogeous to @tell@ in a Writer monad.+-- This function is the /forgetful/ version of 'drawi'. +-- Commonly, it is used to draw 'Graphic' objects which +-- have no /answer/. -- -draw :: (TraceM m, DrawingCtxM m, u ~ MonUnit m) => Graphic u -> m ()-draw gf = askDC >>= \ctx -> trace (collectH $ snd $ runCF ctx gf)+draw :: (TraceM m, DrawingCtxM m, u ~ MonUnit (m ()) ) + => Image u a -> m ()+draw gf = askDC >>= \ctx -> + let Ans o _ = runCF ctx gf+ in trace (singleH o) >> return () --- | Hyperlink version of 'draw'.----xdraw :: (TraceM m, DrawingCtxM m, u ~ MonUnit m) - => XLink -> Graphic u -> m ()-xdraw xl gf = draw (hyperlink xl gf) @@ -296,43 +334,142 @@ -- The graphic representation of the Image is drawn in the Trace -- monad, and the result is returned. -- -drawi :: (TraceM m, DrawingCtxM m, u ~ MonUnit m) => Image u a -> m a+drawi :: (TraceM m, DrawingCtxM m, u ~ MonUnit (m ()) ) + => Image u a -> m a drawi img = askDC >>= \ctx -> - let (a,o) = runCF ctx img in trace (collectH o) >> return a+ let Ans o a = runCF ctx img+ in trace (singleH o) >> return a --- | Forgetful 'drawi'.++-- | Draw a LocImage at the supplied Anchor taking the drawing +-- style from the /drawing context/. ---drawi_ :: (TraceM m, DrawingCtxM m, MonUnit m ~ u) => Image u a -> m ()-drawi_ img = drawi img >> return ()+-- This function is the /forgetful/ version of 'drawli'. +-- Commonly, it is used to draw 'LocGraphic' objects which +-- have no /answer/.+-- +drawl :: (TraceM m, DrawingCtxM m, u ~ MonUnit (m ()) ) + => Anchor u -> LocImage u a -> m ()+drawl ancr img = drawli ancr img >> return () --- | Hyperlink version of 'drawi'.++-- | Draw a LocImage at the supplied Point taking the drawing +-- style from the /drawing context/. ---xdrawi :: (TraceM m, DrawingCtxM m, MonUnit m ~ u) - => XLink -> Image u a -> m a-xdrawi xl img = drawi (hyperlink xl img)+-- The graphic representation of the Image is drawn in the Trace +-- monad, and the result is returned.+-- +drawli :: (TraceM m, DrawingCtxM m, u ~ MonUnit (m ()) ) + => Anchor u -> LocImage u a -> m a+drawli pt img = askDC >>= \ctx -> + let Ans o a = runCF ctx img pt + in trace (singleH o) >> return a --- | Forgetful 'xdrawi'.++-- Design note - having @drawlti@ for LocThetaImage does not seem +-- compelling (at the moment). The thinking is that LocTheta+-- objects should be downcast to Loc objects before drawing. ---xdrawi_ :: (TraceM m, DrawingCtxM m, MonUnit m ~ u)- => XLink -> Image u a -> m ()-xdrawi_ xl img = xdrawi xl img >> return ()+-- Connectors however are be different. +-- +-- PosImages would seem to be the same as LocThetaImages.+-- +-- | Draw a ConnectorGraphic with the supplied Anchors taking the +-- drawing style from the /drawing context/. +--+-- This function is the /forgetful/ version of 'drawci'. +-- Commonly, it is used to draw 'ConnectorGraphic' objects which +-- have no /answer/.+-- +drawc :: (TraceM m, DrawingCtxM m, u ~ MonUnit (m ()) ) + => Anchor u -> Anchor u -> ConnectorImage u a -> m ()+drawc an0 an1 img = drawci an0 an1 img >> return () -node :: (TraceM m, DrawingCtxM m, PointSupplyM m, MonUnit m ~ u) - => LocGraphic u -> m ()-node gf = askDC >>= \ctx -> - position >>= \pt -> - let (_,prim) = runCF1 ctx pt gf in trace (collectH prim) +-- | Draw a ConnectorImage with the supplied Points taking the +-- drawing style from the /drawing context/. +--+-- The graphic representation of the Image is drawn in the Trace +-- monad, and the result is returned.+-- +drawci :: (TraceM m, DrawingCtxM m, u ~ MonUnit (m ()) ) + => Anchor u -> Anchor u -> ConnectorImage u a -> m a+drawci p0 p1 img = drawi (connect img p0 p1) -nodei :: (TraceM m, DrawingCtxM m, PointSupplyM m, MonUnit m ~ u) - => LocImage u a -> m a-nodei imgL = askDC >>= \ctx -> - position >>= \pt -> - let (a,o) = runCF ctx (apply1R1 imgL pt)- in trace (collectH o) >> return a++++++++-- | Draw the object with the supplied grid coordinate. The +-- actual position is scaled according to the +-- @snap_grid_factors@ in the /drawing context/.+-- +-- This function is the /forgetful/ version of 'nodei'. +-- Commonly, it is used to draw 'LocGraphic' objects which +-- have no /answer/.+-- +node :: (Fractional u, TraceM m, DrawingCtxM m, u ~ MonUnit (m ()) ) + => (Int,Int) -> LocImage u a -> m ()+node coord gf = nodei coord gf >> return ()+++-- | Draw the object with the supplied grid coordinate. The +-- actual position is scaled according to the +-- @snap_grid_factors@ in the /drawing context/.+-- +nodei :: (Fractional u, TraceM m, DrawingCtxM m, u ~ MonUnit (m ()) ) + => (Int,Int) -> LocImage u a -> m a+nodei coord gf = askDC >>= \ctx -> + position coord >>= \pt ->+ let Ans o a = runCF ctx gf pt+ in trace (singleH o) >> return a++++ +++++-- | Draw a connector between two objects. The projection of the+-- connector line is drawn on the line from center to center of +-- the objects, the actual start and end points of the drawn line+-- are the radial points on the objects borders that cross the +-- projected line.+-- +-- This function is the /forgetful/ version of 'drawrci'. +-- Commonly, it is used to draw 'LocGraphic' objects which +-- have no /answer/.+-- +drawrc :: ( Real u, Floating u, DrawingCtxM m, TraceM m + , CenterAnchor a, RadialAnchor a+ , CenterAnchor b, RadialAnchor b+ , u ~ MonUnit (m ()), u ~ DUnit a, u ~ DUnit b + ) + => a -> b -> ConnectorImage u ans -> m ()+drawrc a b gf = drawrci a b gf >> return ()+++-- | Draw a connector between two objects. The projection of the+-- connector line is drawn on the line from center to center of +-- the objects, the actual start and end points of the drawn line+-- are the radial points on the objects borders that cross the +-- projected line.+-- +drawrci :: ( Real u, Floating u, DrawingCtxM m, TraceM m+ , CenterAnchor a, RadialAnchor a+ , CenterAnchor b, RadialAnchor b+ , u ~ MonUnit (m ()), u ~ DUnit a, u ~ DUnit b+ ) + => a -> b -> ConnectorImage u ans -> m ans+drawrci a b img = + let (p0,p1) = radialConnectorPoints a b in drawi (connect img p0 p1)
+ src/Wumpus/Basic/System/FontLoader.hs view
@@ -0,0 +1,141 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.System.FontLoader+-- Copyright : (c) Stephen Tetley 2011+-- License : BSD3+--+-- Maintainer : stephen.tetley@gmail.com+-- Stability : highly unstable+-- Portability : GHC +--+-- Top level module for font loading...+--+--------------------------------------------------------------------------------++module Wumpus.Basic.System.FontLoader+ (+ FontLoader+ , afmLoaderByEnv+ , gsLoaderByEnv+ , simpleFontLoader++ , default_font_loader_help++ ) where++import Wumpus.Basic.Kernel.Base.FontSupport +import Wumpus.Basic.System.FontLoader.AfmTopLevel+import Wumpus.Basic.System.FontLoader.GSTopLevel++import Control.Monad+import System.Environment+import System.IO.Error+++++-- | A FontLoader is an action from a list of fonts to a+-- 'FontLoadResult' returned in @IO@.+-- +-- Fonts are supplied in a list of @Either FontDef FontFamily@,+-- this is a little cumbersome but it allows the loader to load+-- individual fonts and \/ or a whole families with a single API+-- call.+--+type FontLoader = [Either FontDef FontFamily] -> IO FontLoadResult++++++-- | Environment variable pointing to the GhostScript font+-- directory.+-- +-- > WUMPUS_GS_FONT_DIR+--+wumpus_gs_font_dir :: String+wumpus_gs_font_dir = "WUMPUS_GS_FONT_DIR"+++-- | Environment variable pointing to the diretory containing +-- the Adobe Font Metrics files.+-- +-- > WUMPUS_AFM_FONT_DIR+--+wumpus_afm_font_dir :: String+wumpus_afm_font_dir = "WUMPUS_AFM_FONT_DIR"++++afmLoaderByEnv :: IO (Maybe FontLoader)+afmLoaderByEnv = do + mb <- envLookup wumpus_afm_font_dir+ case mb of + Nothing -> return Nothing+ Just path -> return $ Just (\xs -> loadAfmFontMetrics path $ fontList xs)+++gsLoaderByEnv :: IO (Maybe FontLoader)+gsLoaderByEnv = do+ mb <- envLookup wumpus_gs_font_dir+ case mb of+ Nothing -> return Nothing+ Just path -> return $ Just (\xs -> loadGSFontMetrics path $ fontList xs)+++-- | Tries to find the GhostScript metrics first...+--+-- Runs the IO action on the loader if it finds one.+--+-- Either of one of the environment variables +-- @WUMPUS_AFM_FONT_DIR@ or @WUMPUS_GS_FONT_DIR@ must be defined+-- and point to their respective directory. +-- +simpleFontLoader :: (FontLoader -> IO a) -> IO (Maybe a)+simpleFontLoader mf = + gsLoaderByEnv >>= maybe fk1 sk + where+ fk1 = afmLoaderByEnv >>= maybe fk2 sk+ fk2 = putStrLn default_font_loader_help >> return Nothing+ sk loader = mf loader >>= return . Just+++envLookup :: String -> IO (Maybe String)+envLookup name = liftM fn $ try $ getEnv name+ where+ fn (Left _) = Nothing+ fn (Right a) = Just a++ ++fontList :: [Either FontDef FontFamily] -> [FontDef]+fontList = foldr fn []+ where+ fn (Left a) acc = a:acc+ fn (Right b) acc = let f1 = maybe id (\a -> (a:)) $ ff_bold b+ f2 = maybe id (\a -> (a:)) $ ff_italic b+ f3 = maybe id (\a -> (a:)) $ ff_bold_italic b+ in ff_regular b : (f1 $ f2 $ f3 acc)+++default_font_loader_help :: String+default_font_loader_help = unlines $ + [ "This example uses glyph metrics loaded at runtime."+ , "It can use either the metrics files supplied with GhostScript,"+ , "or the AFM v4.1 metrics for the Core 14 fonts available from"+ , "Adobe's website."+ , "" + , "To use GhostScripts font metrics set the environemt variable"+ , wumpus_gs_font_dir ++ " to point to the GhostScript fonts"+ , "directory (e.g. /usr/share/ghostscript/fonts)."+ , ""+ , "To use the Adode Core 14 font metrics download the archive from"+ , "the Adobe website and set the environment variable "+ , wumpus_afm_font_dir ++ " to point to it."+ , ""+ , "If you have both environment variables set, the GhostScript loader"+ , "will be used."+ ]+
− src/Wumpus/Basic/System/FontLoader/Afm.hs
@@ -1,83 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.System.FontLoader.Afm--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Font loader / import shim for the Adobe \"Core 14\" glyph --- metrics.------ Use this loader if you have the Adode glyph metrics set--- (AFM v4.1). This metrics set is avaiable from the Adobe --- website.--------------------------------------------------------------------------------------module Wumpus.Basic.System.FontLoader.Afm- ( - loadAfmMetrics- - ) where--import Wumpus.Basic.Kernel-import Wumpus.Basic.System.FontLoader.Base.AfmV4Dot1Parser-import Wumpus.Basic.System.FontLoader.Base.Datatypes-import Wumpus.Basic.System.FontLoader.Base.FontLoadMonad---import Wumpus.Core -- package: wumpus-core--import Control.Monad-import Data.Monoid---- The file names of the Afm fonts match there PostScript names,--- the only difference is the addition of a @.afm@ extension.------- | 'loadAfmMetrics' : --- @ path_to_afm_fonts * [font_name] -> IO (metrics, messages) @ --- --- Load the supplied list of fonts. --- --- Note - if a font fails to load a message is written to the --- log and monospaced /fallback metrics/ are used.----loadAfmMetrics :: FilePath -> [FontName] -> IO (GlyphMetrics, [String])-loadAfmMetrics font_dir_path ns = - liftM post $ runFontLoadIO $ sequenceAll $ map mkFun ns- where- mkFun = afmLoadFontCalcs font_dir_path - - post (Left err,ss) = (mempty, ss ++ [err]) -- unreachable...- post (Right xs,ss) = (foldr insertFont mempty xs, ss)-----afmLoadFontCalcs :: FilePath -> FontName -> FontLoadIO FontMetricsOps-afmLoadFontCalcs font_dir_path name = do- logLoadMsg $ "Loading " ++ name- path <- checkFontPath font_dir_path (name ++ ".afm")- ans <- runParserFLIO path afmV4Dot1Parser- props <- buildAfmFontProps afm_mono_defaults_4_1 ans- return $ FontMetricsOps name (buildMetricsOps afmUnitScale props)------ | These are values extracted from Courier in the core 14 fonts.----afm_mono_defaults_4_1 :: MonospaceDefaults AfmUnit-afm_mono_defaults_4_1 = - MonospaceDefaults { default_letter_bbox = bbox- , default_cap_height = 562- , default_descender = (-157)- , default_char_width = V2 600 0- }- where- bbox = BBox (P2 (-23) (-250)) (P2 715 805)
+ src/Wumpus/Basic/System/FontLoader/AfmParserBase.hs view
@@ -0,0 +1,214 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.System.FontLoader.AfmParserBase+-- Copyright : (c) Stephen Tetley 2010-2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Common parsers for AFM files.+-- +--------------------------------------------------------------------------------++module Wumpus.Basic.System.FontLoader.AfmParserBase+ ( ++ afmFileParser+ , runQuery+ , textQuery++ , getFontBBox+ , getEncodingScheme+ , getCapHeight+ + , charBBox+ , metric+ , keyStringPair+ , versionNumber + , startCharMetrics++ , keyName+ , newlineOrEOF+ , name+ , name1+ , semi+ , uptoNewline+ , number+ , cint+ , hexInt+ , octInt++ , lexeme+ , symbol+ , integer+ , int+ , double++ ) where++import Wumpus.Basic.System.FontLoader.Datatypes++import Wumpus.Basic.Utils.ParserCombinators+import qualified Wumpus.Basic.Utils.TokenParsers as P++import Wumpus.Core -- package: wumpus-core++import Control.Applicative++import Data.Char+import qualified Data.Map as Map+++afmFileParser :: CharParser AfmGlyphMetrics -> CharParser AfmFile+afmFileParser pgm = do + info <- (versionNumber *> globalInfo) + cms <- (startCharMetrics *> many pgm)+ return $ AfmFile + { afm_encoding = getEncodingScheme info+ , afm_letter_bbox = getFontBBox info+ , afm_cap_height = getCapHeight info+ , afm_descender = getDescender info+ , afm_glyph_metrics = cms+ }++globalInfo :: CharParser GlobalInfo+globalInfo = (foldr (\(k,v) a -> Map.insert k v a) Map.empty) + <$> manyTill keyStringPair (peek startCharMetrics)+++ +runQuery :: String -> CharParser a -> GlobalInfo -> Maybe a+runQuery field_name p table = + Map.lookup field_name table >>= extr . runParser p+ where+ extr (Okay a _) = Just a+ extr _ = Nothing++textQuery :: String -> GlobalInfo -> Maybe String+textQuery = Map.lookup+++-- | Strictly speaking a fontBBox is measured in integer units.+--+getFontBBox :: GlobalInfo -> Maybe AfmBoundingBox+getFontBBox = runQuery "FontBBox" fontBBox++getEncodingScheme :: GlobalInfo -> Maybe String+getEncodingScheme = textQuery "EncodingScheme"++getCapHeight :: GlobalInfo -> Maybe AfmUnit+getCapHeight = runQuery "CapHeight" number++getDescender :: GlobalInfo -> Maybe AfmUnit+getDescender = runQuery "Descender" number+++charBBox :: CharParser AfmBoundingBox+charBBox = symbol "B" *> fontBBox <* semi++fontBBox :: CharParser AfmBoundingBox+fontBBox = (\llx lly urx ury -> boundingBox (P2 llx lly) (P2 urx ury))+ <$> number <*> number <*> number <*> number++++metric :: String -> a -> CharParser a -> CharParser a+metric iden dfault p = option dfault go+ where+ go = symbol iden *> p <* semi++++keyStringPair :: CharParser (AfmKey,String)+keyStringPair = (,) <$> keyName <*> uptoNewline <* newlineOrEOF + <?> "key-value line"++versionNumber :: CharParser String+versionNumber = + symbol "StartFontMetrics" *> many1 (digit <|> char '.') <* newlineOrEOF+ <?> "StartFontMetrics"+++startCharMetrics :: CharParser Int+startCharMetrics = symbol "StartCharMetrics" *> int <* newlineOrEOF+ <?> "StartCharMetrics failed"++++--------------------------------------------------------------------------------+++keyName :: CharParser AfmKey+keyName = lexeme (many1 $ satisfy isAlphaNum) +++newlineOrEOF :: CharParser ()+newlineOrEOF = skipOne (lexeme newline) <|> eof+++uptoNewline :: CharParser String+uptoNewline = many1 (noneOf ['\n'])+++name :: CharParser String+name = lexeme $ many (noneOf ";\n")++name1 :: CharParser String+name1 = lexeme $ many (noneOf "; \t\n")++++semi :: CharParser Char+semi = lexeme $ char ';'+++++number :: CharParser AfmUnit+number = liftA realToFrac double+++cint :: CharParser Int+cint = hexInt <|> octInt <|> int+++hexInt :: CharParser Int+hexInt = lexeme $ between (char '<') (char '>') P.hexBase+++octInt :: CharParser Int+octInt = lexeme $ char '\\' *> P.octBase++++--------------------------------------------------------------------------------++-- no newline in whitespace+++lp :: P.LexemeParser+lp = P.commentLineLexemeParser "Comment" [' ', '\t']+++lexeme :: CharParser a -> CharParser a+lexeme = P.lexeme lp++symbol :: String -> CharParser String+symbol = lexeme . string++-- whiteSpace :: CharParser ()+-- whiteSpace = P.whiteSpace lp+++integer :: CharParser Integer+integer = lexeme P.integer++int :: CharParser Int+int = fromIntegral <$> integer++double :: CharParser Double+double = lexeme P.double
+ src/Wumpus/Basic/System/FontLoader/AfmTopLevel.hs view
@@ -0,0 +1,111 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.System.FontLoader.AfmTopLevel+-- Copyright : (c) Stephen Tetley 2010-2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Top-level AFM V4.1 font loader. +--+-- Use this module to build a font loader if you want to work with +-- the Adobe metrics sets, but find the @simpleFontLoader@ in +-- @Wumpus.Basic.System.FontLoader@ too inflexible.+-- +--------------------------------------------------------------------------------++module Wumpus.Basic.System.FontLoader.AfmTopLevel+ ( ++ loadAfmFontMetrics++ , loadAfmFont1 ++ ) where++import Wumpus.Basic.Kernel+import Wumpus.Basic.System.FontLoader.AfmV4Dot1Parser+import Wumpus.Basic.System.FontLoader.Datatypes+import Wumpus.Basic.System.FontLoader.FontLoadMonad+++import Wumpus.Core -- package: wumpus-core++import Control.Monad+import Data.Monoid++-- The file names of the Afm fonts match there PostScript names,+-- the only difference is the addition of a @.afm@ extension.+--++-- | 'loadAfmFontMetrics' : +-- @ path_to_afm_fonts * [font_name] -> IO FontLoadResult @ +-- +-- Load the supplied list of fonts. +-- +-- Note - if a font fails to load a message is written to the +-- log and monospaced /fallback metrics/ are used.+--+loadAfmFontMetrics :: FilePath -> [FontDef] -> IO FontLoadResult+loadAfmFontMetrics font_dir_path ds = + liftM post $ runFontLoadIO $ sequenceAll $ map mkFun ds+ where+ mkFun = afmLoadFontMetrics font_dir_path + + post (Left err,msgs) = let errs = fontLoadMsg err `mappend` msgs+ in FontLoadResult mempty errs+ post (Right xs,msgs) = let body = foldr fn mempty xs+ in FontLoadResult body msgs+ + fn (name,metrics) table = insertFont name metrics table+++-- TODO - need a one font version...+++-- | 'loadAfmFont1' : +-- @ path_to_afm_fonts * font_def -> IO FontLoadResult @ +-- +-- Load a single AFM font. +-- +-- Note - if the font fails to load a message is written to the +-- log and monospaced /fallback metrics/ are used.+--+loadAfmFont1 :: FilePath -> FontDef -> IO FontLoadResult+loadAfmFont1 font_dir_path font_def =+ liftM post $ runFontLoadIO $ afmLoadFontMetrics font_dir_path font_def+ where+ post (Left err,msgs) = let errs = fontLoadMsg err `mappend` msgs+ in FontLoadResult mempty errs+ post (Right (a,b),msgs) = let body = insertFont a b mempty+ in FontLoadResult body msgs+ +++afmLoadFontMetrics :: FilePath -> FontDef -> FontLoadIO (FontName,FontMetrics)+afmLoadFontMetrics font_dir_path font_def = do+ tellLoadMsg $ "Loading " ++ afm_file+ path <- checkFontPath font_dir_path afm_file+ ans <- runParserFLIO path afmV4Dot1Parser+ props <- buildAfmFontProps afm_mono_defaults_4_1 ans+ return (name, buildMetricsOps afmValue props)+ where+ afm_file = afm_file_name font_def+ name = ps_font_name $ font_def_face font_def+++-- | These are values extracted from Courier in the core 14 fonts.+--+afm_mono_defaults_4_1 :: MonospaceDefaults AfmUnit+afm_mono_defaults_4_1 = + MonospaceDefaults { default_letter_bbox = bbox+ , default_cap_height = 562+ , default_descender = (-157)+ , default_char_width = V2 600 0+ }+ where+ bbox = BBox (P2 (-23) (-250)) (P2 715 805)
+ src/Wumpus/Basic/System/FontLoader/AfmV2Parser.hs view
@@ -0,0 +1,65 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.System.FontLoader.AfmV2Parser+-- Copyright : (c) Stephen Tetley 2010-2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- AFM file parser for Version 2.0.+--+-- Note - AFM Version 2.0 used by GhostScript and Version 3.0++-- have numerous differences. +-- +--------------------------------------------------------------------------------++module Wumpus.Basic.System.FontLoader.AfmV2Parser+ ( + afmV2Parser++ ) where++import Wumpus.Basic.System.FontLoader.AfmParserBase+import Wumpus.Basic.System.FontLoader.Datatypes+import Wumpus.Basic.Utils.ParserCombinators++import Wumpus.Core -- package: wumpus-core++import Control.Applicative+++++--------------------------------------------------------------------------------+-- parser+++afmV2Parser :: CharParser AfmFile+afmV2Parser = afmFileParser charMetricsV2+++charMetricsV2 :: CharParser AfmGlyphMetrics+charMetricsV2 = AfmGlyphMetrics <$>+ metric "C" (-1) cint+ <*> widthVector+ <*> metric "N" "" name1+ <* charBBox+ <* many (symbol "L" *> ligature_body <* semi)+ <* newlineOrEOF+ where+ ligature_body = ((,) <$> name <*> name)+ +widthVector :: CharParser (Vec2 AfmUnit)+widthVector = (symbol "WX" *> ((\w -> vec w 0) <$> number) <* semi)+ <|> (symbol "W" *> (vec <$> number <*> number) <* semi)+++--------------------------------------------------------------------------------++++
+ src/Wumpus/Basic/System/FontLoader/AfmV4Dot1Parser.hs view
@@ -0,0 +1,63 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.System.FontLoader.AfmV4Dot1Parser+-- Copyright : (c) Stephen Tetley 2010-2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- AFM file parser for Version 4.1.+--+-- Adobe distributes font metrics for the /Core 14/ fonts as+-- AFM Version 4.1 files. +--+--------------------------------------------------------------------------------++module Wumpus.Basic.System.FontLoader.AfmV4Dot1Parser+ ( + + afmV4Dot1Parser + ) where++import Wumpus.Basic.System.FontLoader.AfmParserBase+import Wumpus.Basic.System.FontLoader.Datatypes+import Wumpus.Basic.Utils.ParserCombinators++import Wumpus.Core -- package: wumpus-core++import Control.Applicative+++afmV4Dot1Parser :: CharParser AfmFile+afmV4Dot1Parser = afmFileParser charMetricsV4Dot1+++charMetricsV4Dot1 :: CharParser AfmGlyphMetrics+charMetricsV4Dot1 = AfmGlyphMetrics <$>+ characterCode+ <*> widthVector+ <*> metric "N" "" name1+ <* charBBox+ <* many (symbol "L" *> ligature_body <* semi)+ <* newlineOrEOF+ where+ ligature_body = ((,) <$> name <*> name)+++-- Note - there are many variants for width vectors in in 4.1.+-- Wumpus needs some thought about what to do for them, it also+-- needs some facility to tell how successful the parse has been.+ +widthVector :: CharParser (Vec2 AfmUnit)+widthVector = (symbol "WX" *> ((\w -> vec w 0) <$> number) <* semi)+ <|> (symbol "W" *> (vec <$> number <*> number) <* semi)+++-- V4.1 allows C int or CH \<hex\>+--+characterCode :: CharParser Int+characterCode = metric "CH" (-1) hexInt <|> metric "C" (-1) cint
− src/Wumpus/Basic/System/FontLoader/Base/AfmParserBase.hs
@@ -1,214 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.System.FontLoader.Base.AfmParserBase--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Common parsers for AFM files.--- -----------------------------------------------------------------------------------module Wumpus.Basic.System.FontLoader.Base.AfmParserBase- ( -- afmFileParser- , runQuery- , textQuery-- , getFontBBox- , getEncodingScheme- , getCapHeight- - , charBBox- , metric- , keyStringPair- , versionNumber - , startCharMetrics-- , keyName- , newlineOrEOF- , name- , name1- , semi- , uptoNewline- , number- , cint- , hexInt- , octInt-- , lexeme- , symbol- , integer- , int- , double-- ) where--import Wumpus.Basic.System.FontLoader.Base.Datatypes--import Wumpus.Basic.Utils.ParserCombinators-import qualified Wumpus.Basic.Utils.TokenParsers as P--import Wumpus.Core -- package: wumpus-core--import Control.Applicative--import Data.Char-import qualified Data.Map as Map---afmFileParser :: CharParser AfmGlyphMetrics -> CharParser AfmFile-afmFileParser pgm = do - info <- (versionNumber *> globalInfo) - cms <- (startCharMetrics *> many pgm)- return $ AfmFile - { afm_encoding = getEncodingScheme info- , afm_letter_bbox = getFontBBox info- , afm_cap_height = getCapHeight info- , afm_descender = getDescender info- , afm_glyph_metrics = cms- }--globalInfo :: CharParser GlobalInfo-globalInfo = (foldr (\(k,v) a -> Map.insert k v a) Map.empty) - <$> manyTill keyStringPair (peek startCharMetrics)--- -runQuery :: String -> CharParser a -> GlobalInfo -> Maybe a-runQuery field_name p table = - Map.lookup field_name table >>= extr . runParser p- where- extr (Okay a _) = Just a- extr _ = Nothing--textQuery :: String -> GlobalInfo -> Maybe String-textQuery = Map.lookup----- | Strictly speaking a fontBBox is measured in integer units.----getFontBBox :: GlobalInfo -> Maybe AfmBoundingBox-getFontBBox = runQuery "FontBBox" fontBBox--getEncodingScheme :: GlobalInfo -> Maybe String-getEncodingScheme = textQuery "EncodingScheme"--getCapHeight :: GlobalInfo -> Maybe AfmUnit-getCapHeight = runQuery "CapHeight" number--getDescender :: GlobalInfo -> Maybe AfmUnit-getDescender = runQuery "Descender" number---charBBox :: CharParser AfmBoundingBox-charBBox = symbol "B" *> fontBBox <* semi--fontBBox :: CharParser AfmBoundingBox-fontBBox = (\llx lly urx ury -> boundingBox (P2 llx lly) (P2 urx ury))- <$> number <*> number <*> number <*> number----metric :: String -> a -> CharParser a -> CharParser a-metric iden dfault p = option dfault go- where- go = symbol iden *> p <* semi----keyStringPair :: CharParser (AfmKey,String)-keyStringPair = (,) <$> keyName <*> uptoNewline <* newlineOrEOF - <?> "key-value line"--versionNumber :: CharParser String-versionNumber = - symbol "StartFontMetrics" *> many1 (digit <|> char '.') <* newlineOrEOF- <?> "StartFontMetrics"---startCharMetrics :: CharParser Int-startCharMetrics = symbol "StartCharMetrics" *> int <* newlineOrEOF- <?> "StartCharMetrics failed"---------------------------------------------------------------------------------------keyName :: CharParser AfmKey-keyName = lexeme (many1 $ satisfy isAlphaNum) ---newlineOrEOF :: CharParser ()-newlineOrEOF = skipOne (lexeme newline) <|> eof---uptoNewline :: CharParser String-uptoNewline = many1 (noneOf ['\n'])---name :: CharParser String-name = lexeme $ many (noneOf ";\n")--name1 :: CharParser String-name1 = lexeme $ many (noneOf "; \t\n")----semi :: CharParser Char-semi = lexeme $ char ';'-----number :: CharParser AfmUnit-number = liftA realToFrac double---cint :: CharParser Int-cint = hexInt <|> octInt <|> int---hexInt :: CharParser Int-hexInt = lexeme $ between (char '<') (char '>') P.hexBase---octInt :: CharParser Int-octInt = lexeme $ char '\\' *> P.octBase---------------------------------------------------------------------------------------- no newline in whitespace---lp :: P.LexemeParser-lp = P.commentLineLexemeParser "Comment" [' ', '\t']---lexeme :: CharParser a -> CharParser a-lexeme = P.lexeme lp--symbol :: String -> CharParser String-symbol = lexeme . string---- whiteSpace :: CharParser ()--- whiteSpace = P.whiteSpace lp---integer :: CharParser Integer-integer = lexeme P.integer--int :: CharParser Int-int = fromIntegral <$> integer--double :: CharParser Double-double = lexeme P.double
− src/Wumpus/Basic/System/FontLoader/Base/AfmV2Parser.hs
@@ -1,65 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.System.FontLoader.Internal.AfmV2Parser--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ AFM file parser for Version 2.0.------ Note - AFM Version 2.0 used by GhostScript and Version 3.0+--- have numerous differences. --- -----------------------------------------------------------------------------------module Wumpus.Basic.System.FontLoader.Base.AfmV2Parser- ( - afmV2Parser-- ) where--import Wumpus.Basic.System.FontLoader.Base.AfmParserBase-import Wumpus.Basic.System.FontLoader.Base.Datatypes-import Wumpus.Basic.Utils.ParserCombinators--import Wumpus.Core -- package: wumpus-core--import Control.Applicative---------------------------------------------------------------------------------------- parser---afmV2Parser :: CharParser AfmFile-afmV2Parser = afmFileParser charMetricsV2---charMetricsV2 :: CharParser AfmGlyphMetrics-charMetricsV2 = AfmGlyphMetrics <$>- metric "C" (-1) cint- <*> widthVector- <*> metric "N" "" name1- <* charBBox- <* many (symbol "L" *> ligature_body <* semi)- <* newlineOrEOF- where- ligature_body = ((,) <$> name <*> name)- -widthVector :: CharParser (Vec2 AfmUnit)-widthVector = (symbol "WX" *> ((\w -> vec w 0) <$> number) <* semi)- <|> (symbol "W" *> (vec <$> number <*> number) <* semi)---------------------------------------------------------------------------------------
− src/Wumpus/Basic/System/FontLoader/Base/AfmV4Dot1Parser.hs
@@ -1,63 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.System.FontLoader.Base.AfmV4Dot1Parser--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ AFM file parser for Version 4.1.------ Adobe distributes font metrics for the /Core 14/ fonts as--- AFM Version 4.1 files. --------------------------------------------------------------------------------------module Wumpus.Basic.System.FontLoader.Base.AfmV4Dot1Parser- ( - - afmV4Dot1Parser - ) where--import Wumpus.Basic.System.FontLoader.Base.AfmParserBase-import Wumpus.Basic.System.FontLoader.Base.Datatypes-import Wumpus.Basic.Utils.ParserCombinators--import Wumpus.Core -- package: wumpus-core--import Control.Applicative---afmV4Dot1Parser :: CharParser AfmFile-afmV4Dot1Parser = afmFileParser charMetricsV4Dot1---charMetricsV4Dot1 :: CharParser AfmGlyphMetrics-charMetricsV4Dot1 = AfmGlyphMetrics <$>- characterCode- <*> widthVector- <*> metric "N" "" name1- <* charBBox- <* many (symbol "L" *> ligature_body <* semi)- <* newlineOrEOF- where- ligature_body = ((,) <$> name <*> name)----- Note - there are many variants for width vectors in in 4.1.--- Wumpus needs some thought about what to do for them, it also--- needs some facility to tell how successful the parse has been.- -widthVector :: CharParser (Vec2 AfmUnit)-widthVector = (symbol "WX" *> ((\w -> vec w 0) <$> number) <* semi)- <|> (symbol "W" *> (vec <$> number <*> number) <* semi)----- V4.1 allows C int or CH \<hex\>----characterCode :: CharParser Int-characterCode = metric "CH" (-1) hexInt <|> metric "C" (-1) cint
− src/Wumpus/Basic/System/FontLoader/Base/Datatypes.hs
@@ -1,182 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.System.FontLoader.Base.Datatypes--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Datatypes--- -----------------------------------------------------------------------------------module Wumpus.Basic.System.FontLoader.Base.Datatypes- (-- -- * Afm Unit- AfmUnit- , afmValue- , afmUnitScale- - -- * Glyph metrics-- , PSCharCode- , PSEncodingScheme- , AfmBoundingBox-- , AfmKey- , GlobalInfo- , AfmFile(..)- , AfmGlyphMetrics(..)-- , MonospaceDefaults(..)-- , FontProps(..)- , buildMetricsOps- - ) where---import Wumpus.Basic.Kernel.Base.GlyphMetrics--import Wumpus.Core -- package: wumpus-core--import qualified Data.IntMap as IM-import qualified Data.Map as M------ | Wrapped Double representing 1\/1000 of the scale factor--- (Point size) of a font. AFM files encode all measurements --- as these units. --- -newtype AfmUnit = AfmUnit { getAfmUnit :: Double } - deriving (Eq,Ord,Num,Floating,Fractional,Real,RealFrac,RealFloat)--instance Show AfmUnit where- showsPrec p d = showsPrec p (getAfmUnit d)----- | Compute the size of a measurement in Afm units scaled by the--- point size of the font.----afmValue :: FromPtSize u => AfmUnit -> PtSize -> u-afmValue u pt = fromPtSize $ (realToFrac $ getAfmUnit u) * (pt / 1000)--afmUnitScale :: AfmUnit -> PtSize -afmUnitScale u = (realToFrac $ getAfmUnit u / 1000)--------------------------------------------------------------------------------------- | Afm files index glyphs by /PostScript character code/. This --- is not the same as Unicode, ASCII...------ It is expected to be determined by @EncodingScheme@ in the--- Global Font Information Section.----type PSCharCode = Int--type PSEncodingScheme = String--type AfmBoundingBox = BoundingBox AfmUnit--type AfmKey = String-type GlobalInfo = M.Map AfmKey String------ | Wumpus needs a very small subset of AFM files, common to both--- version 2.0 and version 4.1.------ Note - Bounding Box is mandatory for AFM versions 3.0 and 4.1--- --- Cap Height is optional in AFM versions 3.0 and 4.1. As Wumpus --- uses cap height in calculations, glyph metrics must be build --- with an arbitrary value if it is not present.------ Encoding Scheme is optional in AFM files.----data AfmFile = AfmFile - { afm_encoding :: Maybe String- , afm_letter_bbox :: Maybe AfmBoundingBox- , afm_cap_height :: Maybe AfmUnit- , afm_descender :: Maybe AfmUnit- , afm_glyph_metrics :: [AfmGlyphMetrics]- }- deriving (Show) - --- Note - for AfmFile BBox is a required field for version 4.1, --- but it appears to be optional for version 2.0.------data AfmGlyphMetrics = AfmGlyphMetrics- { afm_char_code :: !PSCharCode- , afm_width_vector :: !(Vec2 AfmUnit)- , afm_char_name :: !String- }- deriving (Eq,Show)----- | Monospace defaults are used if the font loader fails to --- extract the necessary fields.--- --- The values are taken from the font correpsonding to Courier --- in the distributed font files.----data MonospaceDefaults cu = MonospaceDefaults - { default_letter_bbox :: BoundingBox cu- , default_cap_height :: cu- , default_descender :: cu- , default_char_width :: Vec2 cu- }- deriving (Eq,Show)------ | The metrics read from a font file by a font loader. --- --- NOTE - FontProps is parametric on @cu@ - /Character Unit/ and --- not on the usual @u@. A typical character unit is 'AfmUnit', --- the unit of measurement for AFM files (1000th of a point).------ The is the initial representation used by Wumpus-Basic as an--- syntax tree when loading font files. ----data FontProps cu = FontProps- { fp_bounding_box :: BoundingBox cu - , fp_default_adv_vec :: Vec2 cu- , fp_adv_vecs :: IM.IntMap (Vec2 cu)- , fp_cap_height :: cu- , fp_descender :: cu- }----- | Build a MetricsOps function table, from a character unit--- scaling function and FontProps read from a file.----buildMetricsOps :: (cu -> PtSize) -> FontProps cu -> MetricsOps-buildMetricsOps fn font@(FontProps { fp_bounding_box = BBox ll ur- , fp_default_adv_vec = V2 vx vy }) = - MetricsOps- { get_bounding_box = \sz -> BBox (scalePt sz ll) (scalePt sz ur)- , get_cw_table = \sz i -> - maybe (defaultAV sz) (scaleVec sz) $ IM.lookup i (fp_adv_vecs font)- , get_cap_height = \sz -> upscale sz (fn $ fp_cap_height font)- , get_descender = \sz -> upscale sz (fn $ fp_descender font)- }- where- upscale sz d = fromPtSize $ sz * d - - defaultAV sz = V2 (upscale sz $ fn vx) (upscale sz $ fn vy) - scalePt sz (P2 cx cy) = P2 (upscale sz $ fn cx) (upscale sz $ fn cy) - scaleVec sz (V2 cx cy) = V2 (upscale sz $ fn cx) (upscale sz $ fn cy) ---
− src/Wumpus/Basic/System/FontLoader/Base/FontLoadMonad.hs
@@ -1,215 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.System.FontLoader.Base.FontLoadMonad--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Font load monad handling IO (file system access), failure and --- logging.--------------------------------------------------------------------------------------module Wumpus.Basic.System.FontLoader.Base.FontLoadMonad- (- FontLoadErr- , FontLoadIO- , runFontLoadIO- , evalFontLoadIO- , loadError- , logLoadMsg- , promoteIO- , promoteEither- , runParserFLIO-- , sequenceAll-- -- * Font loading-- , buildAfmFontProps- , checkFontPath- - ) where--import Wumpus.Basic.System.FontLoader.Base.Datatypes-import Wumpus.Basic.Utils.HList-import Wumpus.Basic.Utils.ParserCombinators---import Wumpus.Core -- package: wumpus-core-import Wumpus.Core.Text.GlyphIndices---import Control.Monad-import qualified Data.IntMap as IntMap-import qualified Data.Map as Map-import Data.Monoid-import System.Directory-import System.FilePath--------------------------------------------------------------------------------------- FontLoadIO monad - IO plus Error----type FontLoadErr = String--newtype FontLoadLog = FontLoadLog { getFontLoadLog :: H String }---instance Monoid FontLoadLog where- mempty = FontLoadLog $ emptyH- a `mappend` b = FontLoadLog $ getFontLoadLog a `appendH` getFontLoadLog b----newtype FontLoadIO a = FontLoadIO { - getFontLoadIO :: IO (Either FontLoadErr a, FontLoadLog ) }--instance Functor FontLoadIO where- fmap f ma = FontLoadIO $ getFontLoadIO ma >>= \(a,w) -> return (fmap f a, w)- -instance Monad FontLoadIO where- return a = FontLoadIO $ return (Right a, mempty)- m >>= k = FontLoadIO $ getFontLoadIO m >>= fn - where- fn (Left err, w) = return (Left err, w)- fn (Right a, w1) = getFontLoadIO (k a) >>= \(b,w2) -> - return (b, w1 `mappend` w2)--runFontLoadIO :: FontLoadIO a -> IO (Either FontLoadErr a,[String])-runFontLoadIO ma = liftM post $ getFontLoadIO ma - where- post (ans,w) = (ans, toListH $ getFontLoadLog w)---evalFontLoadIO :: FontLoadIO a -> IO (Either FontLoadErr a)-evalFontLoadIO ma = liftM post $ getFontLoadIO ma- where- post (ans,_) = ans---loadError :: FontLoadErr -> FontLoadIO a-loadError msg = FontLoadIO $ return (Left msg, mempty)--logLoadMsg :: String -> FontLoadIO ()-logLoadMsg msg = FontLoadIO $ return (Right (), message1 msg ) ---message1 :: String -> FontLoadLog -message1 = FontLoadLog . wrapH----- | aka liftIO-promoteIO :: IO a -> FontLoadIO a-promoteIO ma = FontLoadIO $ ma >>= \a -> return (Right a, mempty)--promoteEither :: Either FontLoadErr a -> FontLoadIO a-promoteEither = either loadError return --runParserFLIO :: FilePath -> Parser Char a -> FontLoadIO a-runParserFLIO filepath p = - promoteIO (readFile filepath) >>= promoteEither . runParserEither p----- | The standard monadic @sequence@ would finish on first fail--- for the FontLoadIO monad. As we want to be able to sequence--- the loading of a list of fonts, this is not really the --- behaviour we want for Wumpus. Instead we prefer to use fallback --- metrics and produce an inaccurate drawing on a font load error--- rather than fail and produce no drawing.----sequenceAll :: [FontLoadIO a] -> FontLoadIO [a]-sequenceAll = FontLoadIO . step- where- step [] = return (Right [], mempty)- step (m:ms) = liftM2 cons (getFontLoadIO m) (step ms) --cons :: (Either FontLoadErr a, FontLoadLog)- -> (Either FontLoadErr [a], FontLoadLog)- -> (Either FontLoadErr [a], FontLoadLog)-cons (Right a, w1) (Right as, w2) = - (Right $ a:as, w1 `mappend` w2)--cons (Right a, w1) (Left e2, w2) = - (Right [a], w1 `mappend` w2 `mappend` message1 e2)--cons (Left e1, w1) (Right as, w2) = - (Right as, w1 `mappend` message1 e1 `mappend` w2)--cons (Left e1, w1) (Left e2, w2) = - (Right [], w1 `mappend` message1 e1 `mappend` w2 `mappend` message1 e2)----------------------------------------------------------------------------------------- | Afm files do not have a default advance vec so use the --- monospace default.--- --- Afm files hopefully have @CapHeight@ and @FontBBox@ properties--- in the header. Use the monospace default only if they are --- missing.--- -buildAfmFontProps :: MonospaceDefaults AfmUnit - -> AfmFile - -> FontLoadIO (FontProps AfmUnit)-buildAfmFontProps defaults afm = do - cap_height <- extractCapHeight defaults afm- desc_depth <- extractDescender defaults afm- bbox <- extractFontBBox defaults afm - return $ FontProps - { fp_bounding_box = bbox- , fp_default_adv_vec = default_char_width defaults- , fp_adv_vecs = char_widths- , fp_cap_height = cap_height- , fp_descender = desc_depth- } - where- char_widths = foldr fn IntMap.empty $ afm_glyph_metrics afm- - fn (AfmGlyphMetrics _ v ss) table = case Map.lookup ss ps_glyph_indices of- Nothing -> table- Just i -> IntMap.insert i v table---extractCapHeight :: MonospaceDefaults AfmUnit -> AfmFile -> FontLoadIO AfmUnit-extractCapHeight defaults afm = maybe errk return $ afm_cap_height afm- where- errk = logLoadMsg "WARNING - Could not extract CapHeight" >> - return (default_cap_height defaults)----extractDescender :: MonospaceDefaults AfmUnit -> AfmFile -> FontLoadIO AfmUnit-extractDescender defaults afm = maybe errk return $ afm_descender afm- where- errk = logLoadMsg "WARNING - Could not extract Descender" >> - return (default_descender defaults)---extractFontBBox :: MonospaceDefaults AfmUnit -> AfmFile - -> FontLoadIO (BoundingBox AfmUnit)-extractFontBBox defaults afm = maybe errk return $ afm_letter_bbox afm- where- errk = logLoadMsg "WARNING - Could not extract CapHeight" >> - return (default_letter_bbox defaults)----checkFontPath :: FilePath -> FilePath -> FontLoadIO FilePath-checkFontPath path_root font_file_name = - let full_path = normalise (path_root </> font_file_name)- in do { check <- promoteIO (doesFileExist full_path)- ; if check then return full_path- else loadError $ "Could not resolve path: " ++ full_path- }
− src/Wumpus/Basic/System/FontLoader/Base/GSFontMap.hs
@@ -1,108 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.System.FontLoader.Base.GSFontMap--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ GhostScript Font map.------ GhostScript aliases the /Core 14/ PostScript fonts to fonts--- it can freely distribute. This module provides aliases to --- Wumpus so the font loader can find the equivalent GhostScript--- files to the Core 14 set.------ The data in this file matches GhostScript 8.63. Other versions--- of GhostScript may need different aliases.--- -----------------------------------------------------------------------------------module Wumpus.Basic.System.FontLoader.Base.GSFontMap- (- - GSFontMap(..)- , gsMetricsFile- , gsFontAlias- , gsVersionNumber- , ghostscript_fontmap_8_54-- ) where---import Data.Map ( Map )-import qualified Data.Map as Map----- | GhostScript version that the aliases were derived from.--- --- ghostscript_version :: String--- ghostscript_version = "gs8.54"----- | A map from standard /Adode PostScript/ font name to the--- equivalent GhostScript font and AFM file name.------ It is expected that all GhostScript AFM files will be located--- in the same directory.----data GSFontMap = GSFontMap- { ghostscript_version :: String- , ghostscript_fontmap :: Map String (String, FilePath)- }----- | Get the @.afm@ metrics file.------ Note this return only the file name and not the path to it.--- The full path must be resolved in client code.----gsMetricsFile :: GSFontMap -> String -> Maybe FilePath-gsMetricsFile mp name = fmap snd $ Map.lookup name (ghostscript_fontmap mp)---- | Get the GhostScript font name alias.----gsFontAlias :: GSFontMap -> String -> Maybe String-gsFontAlias mp name = fmap fst $ Map.lookup name (ghostscript_fontmap mp)----- | Get the GhostScript version number that the FontMap --- represents.----gsVersionNumber :: GSFontMap -> String-gsVersionNumber = ghostscript_version ----- | Map from PostScript font name to the corresponding --- GhostScript name and file.------ Naming is correct for GhostSCript version 8.54.--- -ghostscript_fontmap_8_54 :: GSFontMap-ghostscript_fontmap_8_54 = GSFontMap "8.54" body- where- body = Map.fromList $ - [ ("Courier", ("NimbusMonL-Regu", "n022003l.afm"))- , ("Courier-Oblique", ("NimbusMonL-ReguObli", "n022023l.afm"))- , ("Courier-Bold", ("NimbusMonL-Bold", "n022004l.afm"))- , ("Courier-BoldOblique", ("NimbusMonL-BoldObli", "n022024l.afm"))- - , ("Helvetica", ("NimbusSanL-Regu", "n019003l.afm"))- , ("Helvetica-Oblique", ("NimbusSanL-ReguItal", "n019023l.afm"))- , ("Helvetica-Bold", ("NimbusSanL-Bold", "n019004l.afm"))- , ("Helvetica-BoldOblique", ("NimbusSanL-BoldItal", "n019024l.afm"))-- , ("Times-Roman", ("NimbusRomNo9L-Regu", "n021003l.afm"))- , ("Times-Italic", ("NimbusRomNo9L-ReguItal", "n021023l.afm"))- , ("Times-Bold", ("NimbusRomNo9L-Medi", "n021004l.afm"))- , ("Times-BoldItalic", ("NimbusRomNo9L-MediItal", "n021024l.afm"))-- , ("Symbol", ("StandardSymL", "s050000l.afm"))-- , ("ZapfDingbats", ("Dingbats", "d050000l.afm"))- ]-
+ src/Wumpus/Basic/System/FontLoader/Datatypes.hs view
@@ -0,0 +1,158 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.System.FontLoader.Datatypes+-- Copyright : (c) Stephen Tetley 2010-2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Datatypes+-- +--------------------------------------------------------------------------------++module Wumpus.Basic.System.FontLoader.Datatypes+ (+ + -- * Glyph metrics++ PSCharCode+ , PSEncodingScheme+ , AfmBoundingBox++ , AfmKey+ , GlobalInfo+ , AfmFile(..)+ , AfmGlyphMetrics(..)++ , MonospaceDefaults(..)++ , FontProps(..)+ , buildMetricsOps+ + ) where+++import Wumpus.Basic.Kernel.Base.FontSupport++import Wumpus.Core -- package: wumpus-core++import qualified Data.IntMap as IM+import qualified Data.Map as M+++++++++--------------------------------------------------------------------------------++-- | Afm files index glyphs by /PostScript character code/. This +-- is not the same as Unicode, ASCII...+--+-- It is expected to be determined by @EncodingScheme@ in the+-- Global Font Information Section.+--+type PSCharCode = Int++type PSEncodingScheme = String++type AfmBoundingBox = BoundingBox AfmUnit++type AfmKey = String+type GlobalInfo = M.Map AfmKey String++++-- | Wumpus needs a very small subset of AFM files, common to both+-- version 2.0 and version 4.1.+--+-- Note - Bounding Box is mandatory for AFM versions 3.0 and 4.1+-- +-- Cap Height is optional in AFM versions 3.0 and 4.1. As Wumpus +-- uses cap height in calculations, glyph metrics must be build +-- with an arbitrary value if it is not present.+--+-- Encoding Scheme is optional in AFM files.+--+data AfmFile = AfmFile + { afm_encoding :: Maybe String+ , afm_letter_bbox :: Maybe AfmBoundingBox+ , afm_cap_height :: Maybe AfmUnit+ , afm_descender :: Maybe AfmUnit+ , afm_glyph_metrics :: [AfmGlyphMetrics]+ }+ deriving (Show) + +-- Note - for AfmFile BBox is a required field for version 4.1, +-- but it appears to be optional for version 2.0.+--+++data AfmGlyphMetrics = AfmGlyphMetrics+ { afm_char_code :: !PSCharCode+ , afm_width_vector :: !(Vec2 AfmUnit)+ , afm_char_name :: !String+ }+ deriving (Eq,Show)+++-- | Monospace defaults are used if the font loader fails to +-- extract the necessary fields.+-- +-- The values are taken from the font correpsonding to Courier +-- in the distributed font files.+--+data MonospaceDefaults cu = MonospaceDefaults + { default_letter_bbox :: BoundingBox cu+ , default_cap_height :: cu+ , default_descender :: cu+ , default_char_width :: Vec2 cu+ }+ deriving (Eq,Show)++++-- | The metrics read from a font file by a font loader. +-- +-- NOTE - FontProps is parametric on @cu@ - /Character Unit/ and +-- not on the usual @u@. A typical character unit is 'AfmUnit', +-- the unit of measurement for AFM files (1000th of a point).+--+-- The is the initial representation used by Wumpus-Basic as an+-- syntax tree when loading font files. +--+data FontProps cu = FontProps+ { fp_bounding_box :: BoundingBox cu + , fp_default_adv_vec :: Vec2 cu+ , fp_adv_vecs :: IM.IntMap (Vec2 cu)+ , fp_cap_height :: cu+ , fp_descender :: cu+ }+++-- | Build a MetricsOps function table, from a character unit+-- scaling function and FontProps read from a file.+--+buildMetricsOps :: (FontSize -> cu -> Double) -> FontProps cu -> FontMetrics+buildMetricsOps fn font@(FontProps { fp_bounding_box = BBox ll ur+ , fp_default_adv_vec = V2 vx vy }) = + FontMetrics+ { get_bounding_box = \sz -> BBox (scalePt sz ll) (scalePt sz ur)+ , get_cw_table = \sz i -> + maybe (defaultAV sz) (scaleVec sz) $ IM.lookup i (fp_adv_vecs font)+ , get_cap_height = \sz -> fn sz (fp_cap_height font)+ , get_descender = \sz -> fn sz (fp_descender font)+ }+ where+ defaultAV sz = V2 (fn sz vx) (fn sz vy) + scalePt sz (P2 cx cy) = P2 (fn sz cx) (fn sz cy) + scaleVec sz (V2 cx cy) = V2 (fn sz cx) (fn sz cy) +++
+ src/Wumpus/Basic/System/FontLoader/FontLoadMonad.hs view
@@ -0,0 +1,200 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.System.FontLoader.FontLoadMonad+-- Copyright : (c) Stephen Tetley 2010-2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Font load monad handling IO (file system access), failure and +-- logging.+--+--------------------------------------------------------------------------------++module Wumpus.Basic.System.FontLoader.FontLoadMonad+ (+ FontLoadIO+ , runFontLoadIO+ , evalFontLoadIO+ , loadError+ , tellLoadMsg+ , promoteIO+ , promoteEither+ , runParserFLIO++ , sequenceAll++ -- * Font loading++ , buildAfmFontProps+ , checkFontPath+ + ) where++import Wumpus.Basic.Kernel+import Wumpus.Basic.System.FontLoader.Datatypes+import Wumpus.Basic.Utils.ParserCombinators+++import Wumpus.Core -- package: wumpus-core+import Wumpus.Core.Text.GlyphIndices+++import Control.Monad+import qualified Data.IntMap as IntMap+import qualified Data.Map as Map+import Data.Monoid+import System.Directory+import System.FilePath++++--------------------------------------------------------------------------------+-- FontLoadIO monad - IO plus Error++++newtype FontLoadIO a = FontLoadIO { + getFontLoadIO :: IO (Either FontLoadMsg a, FontLoadLog ) }++instance Functor FontLoadIO where+ fmap f ma = FontLoadIO $ getFontLoadIO ma >>= \(a,w) -> return (fmap f a, w)+ +instance Monad FontLoadIO where+ return a = FontLoadIO $ return (Right a, mempty)+ m >>= k = FontLoadIO $ getFontLoadIO m >>= fn + where+ fn (Left err, w) = return (Left err, w)+ fn (Right a, w1) = getFontLoadIO (k a) >>= \(b,w2) -> + return (b, w1 `mappend` w2)++runFontLoadIO :: FontLoadIO a -> IO (Either FontLoadMsg a, FontLoadLog)+runFontLoadIO ma = getFontLoadIO ma +++evalFontLoadIO :: FontLoadIO a -> IO (Either FontLoadMsg a)+evalFontLoadIO ma = liftM post $ getFontLoadIO ma+ where+ post (ans,_) = ans+++loadError :: FontLoadMsg -> FontLoadIO a+loadError msg = FontLoadIO $ return (Left msg, mempty)++tellLoadMsg :: String -> FontLoadIO ()+tellLoadMsg msg = FontLoadIO $ return (Right (), fontLoadMsg msg ) ++++-- | Promote an @IO@ action into the the @FontLoadIO@ monad.+--+-- This function is equivalent to @liftIO@.+--+promoteIO :: IO a -> FontLoadIO a+promoteIO ma = FontLoadIO $ ma >>= \a -> return (Right a, mempty)++promoteEither :: Either FontLoadMsg a -> FontLoadIO a+promoteEither = either loadError return ++runParserFLIO :: FilePath -> Parser Char a -> FontLoadIO a+runParserFLIO filepath p = + promoteIO (readFile filepath) >>= promoteEither . runParserEither p+++-- | The standard monadic @sequence@ would finish on first fail+-- for the FontLoadIO monad. As we want to be able to sequence+-- the loading of a list of fonts, this is not really the +-- behaviour we want for Wumpus. Instead we prefer to use fallback +-- metrics and produce an inaccurate drawing on a font load error+-- rather than fail and produce no drawing.+--+sequenceAll :: [FontLoadIO a] -> FontLoadIO [a]+sequenceAll = FontLoadIO . step+ where+ step [] = return (Right [], mempty)+ step (m:ms) = liftM2 cons (getFontLoadIO m) (step ms) ++cons :: (Either FontLoadMsg a, FontLoadLog)+ -> (Either FontLoadMsg [a], FontLoadLog)+ -> (Either FontLoadMsg [a], FontLoadLog)+cons (Right a, w1) (Right as, w2) = + (Right $ a:as, w1 `mappend` w2)++cons (Right a, w1) (Left e2, w2) = + (Right [a], w1 `mappend` w2 `mappend` fontLoadMsg e2)++cons (Left e1, w1) (Right as, w2) = + (Right as, w1 `mappend` fontLoadMsg e1 `mappend` w2)++cons (Left e1, w1) (Left e2, w2) = + (Right [], w1 `mappend` fontLoadMsg e1 `mappend` w2 `mappend` fontLoadMsg e2)++++--------------------------------------------------------------------------------+++-- | Afm files do not have a default advance vec so use the +-- monospace default.+-- +-- Afm files hopefully have @CapHeight@ and @FontBBox@ properties+-- in the header. Use the monospace default only if they are +-- missing.+-- +buildAfmFontProps :: MonospaceDefaults AfmUnit + -> AfmFile + -> FontLoadIO (FontProps AfmUnit)+buildAfmFontProps defaults afm = do + cap_height <- extractCapHeight defaults afm+ desc_depth <- extractDescender defaults afm+ bbox <- extractFontBBox defaults afm + return $ FontProps + { fp_bounding_box = bbox+ , fp_default_adv_vec = default_char_width defaults+ , fp_adv_vecs = char_widths+ , fp_cap_height = cap_height+ , fp_descender = desc_depth+ } + where+ char_widths = foldr fn IntMap.empty $ afm_glyph_metrics afm+ + fn (AfmGlyphMetrics _ v ss) table = case Map.lookup ss ps_glyph_indices of+ Nothing -> table+ Just i -> IntMap.insert i v table+++extractCapHeight :: MonospaceDefaults AfmUnit -> AfmFile -> FontLoadIO AfmUnit+extractCapHeight defaults afm = maybe errk return $ afm_cap_height afm+ where+ errk = tellLoadMsg "WARNING - Could not extract CapHeight" >> + return (default_cap_height defaults)++++extractDescender :: MonospaceDefaults AfmUnit -> AfmFile -> FontLoadIO AfmUnit+extractDescender defaults afm = maybe errk return $ afm_descender afm+ where+ errk = tellLoadMsg "WARNING - Could not extract Descender" >> + return (default_descender defaults)+++extractFontBBox :: MonospaceDefaults AfmUnit -> AfmFile + -> FontLoadIO (BoundingBox AfmUnit)+extractFontBBox defaults afm = maybe errk return $ afm_letter_bbox afm+ where+ errk = tellLoadMsg "WARNING - Could not extract CapHeight" >> + return (default_letter_bbox defaults)++++checkFontPath :: FilePath -> FilePath -> FontLoadIO FilePath+checkFontPath path_root font_file_name = + let full_path = normalise (path_root </> font_file_name)+ in do { check <- promoteIO (doesFileExist full_path)+ ; if check then return full_path+ else loadError $ "Could not resolve path: " ++ full_path+ }
+ src/Wumpus/Basic/System/FontLoader/GSTopLevel.hs view
@@ -0,0 +1,108 @@+{-# OPTIONS -Wall #-}++--------------------------------------------------------------------------------+-- |+-- Module : Wumpus.Basic.System.FontLoader.GSTopLevel+-- Copyright : (c) Stephen Tetley 2010-2011+-- License : BSD3+--+-- Maintainer : Stephen Tetley <stephen.tetley@gmail.com>+-- Stability : highly unstable+-- Portability : GHC+--+-- Top-level GhostScript font loader. +--+-- Use this module to build a font loader if you want to work with +-- GhostScript, but find the @simpleFontLoader@ in +-- @Wumpus.Basic.System.FontLoader@ too inflexible.+-- +--------------------------------------------------------------------------------++module Wumpus.Basic.System.FontLoader.GSTopLevel+ ( ++ loadGSFontMetrics++ , loadGSFont1 + + ) where++import Wumpus.Basic.Kernel+import Wumpus.Basic.System.FontLoader.AfmV2Parser+import Wumpus.Basic.System.FontLoader.Datatypes+import Wumpus.Basic.System.FontLoader.FontLoadMonad++import Wumpus.Core -- package: wumpus-core++import Control.Monad+import Data.Monoid+++-- | 'loadGSFontMetrics' : +-- @ path_to_gs_fonts * [font_name] -> IO FontLoadResult @ +-- +-- Load the supplied list of fonts. +-- +-- Note - if a font fails to load a message is written to the +-- log and monospaced /fallback metrics/ are used.+--+loadGSFontMetrics :: FilePath -> [FontDef] -> IO FontLoadResult+loadGSFontMetrics font_dir_path ds = + liftM post $ runFontLoadIO $ sequenceAll $ map mkFun ds+ where+ mkFun = gsLoadFontMetrics font_dir_path ++ post (Left err,msgs) = let errs = fontLoadMsg err `mappend` msgs+ in FontLoadResult mempty errs + post (Right xs,msgs) = let body = foldr fn mempty xs+ in FontLoadResult body msgs++ fn (name,metrics) table = insertFont name metrics table+++-- | 'loadGSFont1' : +-- @ path_to_gs_fonts * font_name -> IO FontLoadResult @ +-- +-- Load a single GhostScript font. +-- +-- Note - if the font fails to load a message is written to the +-- log and monospaced /fallback metrics/ are used.+--+loadGSFont1 :: FilePath -> FontDef -> IO FontLoadResult+loadGSFont1 font_dir_path font_def = + liftM post $ runFontLoadIO $ gsLoadFontMetrics font_dir_path font_def+ where+ post (Left err,msgs) = let errs = fontLoadMsg err `mappend` msgs+ in FontLoadResult mempty errs + post (Right (a,b),msgs) = let body = insertFont a b mempty+ in FontLoadResult body msgs++++gsLoadFontMetrics :: FilePath -> FontDef+ -> FontLoadIO (FontName,FontMetrics)+gsLoadFontMetrics font_dir_path font_def = do+ tellLoadMsg $ "Loading " ++ gs_file+ path <- checkFontPath font_dir_path gs_file+ ans <- runParserFLIO path afmV2Parser+ props <- buildAfmFontProps ghostscript_mono_defaults_8_54 ans+ return (name, buildMetricsOps afmValue props)+ where+ gs_file = gs_file_name font_def+ name = ps_font_name $ font_def_face font_def++++-- | These are values extracted from the file @n022003l.afm@+-- which is the font @NimbusMonL-Regu@, GhostScript\'s eqivalent +-- font for the core 14 font Courier.+--+ghostscript_mono_defaults_8_54 :: MonospaceDefaults AfmUnit+ghostscript_mono_defaults_8_54 = + MonospaceDefaults { default_letter_bbox = bbox+ , default_cap_height = 563+ , default_descender = (-186)+ , default_char_width = V2 600 0+ }+ where+ bbox = BBox (P2 (-46) (-273)) (P2 650 820)
− src/Wumpus/Basic/System/FontLoader/GhostScript.hs
@@ -1,87 +0,0 @@-{-# OPTIONS -Wall #-}------------------------------------------------------------------------------------- |--- Module : Wumpus.Basic.System.FontLoader.GhostScript--- Copyright : (c) Stephen Tetley 2010--- License : BSD3------ Maintainer : Stephen Tetley <stephen.tetley@gmail.com>--- Stability : highly unstable--- Portability : GHC------ Font loader / import shim for GhostScript glyph metrics.------ Use this loader if you have GhostScript installed and you want --- to use the (AFM v2.0) metrics that are distributed with --- GhostScript.--- -----------------------------------------------------------------------------------module Wumpus.Basic.System.FontLoader.GhostScript- ( -- loadGSMetrics- - ) where--import Wumpus.Basic.Kernel-import Wumpus.Basic.System.FontLoader.Base.AfmV2Parser-import Wumpus.Basic.System.FontLoader.Base.Datatypes-import Wumpus.Basic.System.FontLoader.Base.FontLoadMonad-import Wumpus.Basic.System.FontLoader.Base.GSFontMap--import Wumpus.Core -- package: wumpus-core--import Control.Monad-import Data.Monoid----- | 'loadGSMetrics' : --- @ path_to_gs_fonts * [font_name] -> IO (metrics, messages) @ --- --- Load the supplied list of fonts. --- --- Note - if a font fails to load a message is written to the --- log and monospaced /fallback metrics/ are used.----loadGSMetrics :: FilePath -> [FontName] -> IO (GlyphMetrics, [String])-loadGSMetrics font_dir_path ns = - liftM post $ runFontLoadIO $ sequenceAll $ map mkFun ns- where- mkFun = gsLoadFontCalcs font_dir_path ghostscript_fontmap_8_54 - - post (Left err,ss) = (mempty, ss ++ [err]) -- unreachable...- post (Right xs,ss) = (foldr insertFont mempty xs, ss)---gsLoadFontCalcs :: FilePath -> GSFontMap -> FontName - -> FontLoadIO FontMetricsOps-gsLoadFontCalcs font_dir_path fm name = do- logLoadMsg $ "Loading " ++ name- font_file <- resolveFontFile fm name - path <- checkFontPath font_dir_path font_file- ans <- runParserFLIO path afmV2Parser- props <- buildAfmFontProps ghostscript_mono_defaults_8_54 ans- return $ FontMetricsOps name (buildMetricsOps afmUnitScale props)---resolveFontFile :: GSFontMap -> FontName -> FontLoadIO FilePath-resolveFontFile fm name = maybe errk return $ gsMetricsFile fm name- where- errk = loadError $ "Could note resolve GhostScript alias for " ++ name----- | These are values extracted from the file @n022003l.afm@--- which is the font @NimbusMonL-Regu@, GhostScript\'s eqivalent --- font for the core 14 font Courier.----ghostscript_mono_defaults_8_54 :: MonospaceDefaults AfmUnit-ghostscript_mono_defaults_8_54 = - MonospaceDefaults { default_letter_bbox = bbox- , default_cap_height = 563- , default_descender = (-186)- , default_char_width = V2 600 0- }- where- bbox = BBox (P2 (-46) (-273)) (P2 650 820)
src/Wumpus/Basic/Utils/HList.hs view
@@ -29,6 +29,7 @@ , concatH , toListH+ , prefixListH , fromListH @@ -79,6 +80,9 @@ toListH :: H a -> [a] toListH = ($ [])++prefixListH :: H a -> [a] -> [a]+prefixListH hf xs = hf $ xs fromListH :: [a] -> H a fromListH xs = (xs++)
src/Wumpus/Basic/Utils/JoinList.hs view
@@ -135,7 +135,7 @@ -- | Convert a join list to a regular list. -- toList :: JoinList a -> [a]-toList = joinfoldl (flip (:)) []+toList = joinfoldr (:) []
src/Wumpus/Basic/VersionNumber.hs view
@@ -23,7 +23,7 @@ -- | Version number ----- > (0,16,0)+-- > (0,17,0) -- wumpus_basic_version :: (Int,Int,Int)-wumpus_basic_version = (0,16,0)+wumpus_basic_version = (0,17,0)
wumpus-basic.cabal view
@@ -1,5 +1,5 @@ name: wumpus-basic-version: 0.16.0+version: 0.17.0 license: BSD3 license-file: LICENSE copyright: Stephen Tetley <stephen.tetley@gmail.com>@@ -29,7 +29,34 @@ . . Changelog:+ . + v0.16.0 to v0.17.0: .+ * Changed representation of ContextFuns - context funs are no + longer an arity family of newtypes. The new representation + is simpler, but some of the opportunities for overloading + have been lost.+ .+ * Substantial round of renaming for the @DrawingContext@ types+ an query and update functions.+ .+ * Re-worked the font metrics and font loader modules. The new+ names should be more systematic. Removed the need for the + GhostScript font modules to match PostScript names to + GhostScript font files. + .+ * Superceded the PointSupplyM class by adding snapping grid + scaling to the DrawingContext. + . + * Removed @ScalingContext@ module.+ .+ * Made text colour a distinct property in the DrawingContext. + Text is now drawn with the text colour rather than the stroke + colour.+ .+ * Added FontLoadLog to the DrawingContext - this allows access + to the errors recorded during font loading.+ . v0.15.0 to v0.16.0: . * Moved the Geometry modules from Wumpus-Drawing into @@ -43,6 +70,8 @@ * Added @PosImage@ object - this is a rectangle-framed object that can be drawn from any of its corners or its center. .+ * Added @CF3@, an arity three /ContextFunction/.+ . * Added @Displacement@ module. This defines the @PointDisplace@ type and provides a library of @PointDisplace@ functions. Note - some of the new functions have taken names previously @@ -85,9 +114,10 @@ extra-source-files: CHANGES, LICENSE,+ demo/AltUnits.hs, demo/FontDeltaPic.hs, demo/SimpleAdvGraphic.hs,- demo/SimplePosImage.hs+ demo/SimplePosObject.hs library hs-source-dirs: src@@ -96,42 +126,48 @@ directory >= 1.0 && < 2.0, filepath >= 1.1 && < 2.0, vector-space >= 0.6 && < 1.0,- wumpus-core >= 0.43.0 && < 0.44.0+ wumpus-core >= 0.50.0 && < 0.51.0 exposed-modules:+ Wumpus.Basic.Geometry, Wumpus.Basic.Geometry.Base, Wumpus.Basic.Geometry.Intersection, Wumpus.Basic.Geometry.Paths, Wumpus.Basic.Geometry.Quadrant, Wumpus.Basic.Kernel,- Wumpus.Basic.Kernel.Base.Anchors, Wumpus.Basic.Kernel.Base.BaseDefs, Wumpus.Basic.Kernel.Base.ContextFun, Wumpus.Basic.Kernel.Base.DrawingContext,- Wumpus.Basic.Kernel.Base.GlyphMetrics,+ Wumpus.Basic.Kernel.Base.FontSupport, Wumpus.Basic.Kernel.Base.QueryDC,- Wumpus.Basic.Kernel.Base.ScalingContext,+ Wumpus.Basic.Kernel.Base.Units, Wumpus.Basic.Kernel.Base.UpdateDC, Wumpus.Basic.Kernel.Base.WrappedPrimitive,- Wumpus.Basic.Kernel.Objects.AdvanceGraphic,- Wumpus.Basic.Kernel.Objects.BaseObjects,+ Wumpus.Basic.Kernel.Objects.AdvObject,+ Wumpus.Basic.Kernel.Objects.Anchors,+ Wumpus.Basic.Kernel.Objects.Basis, Wumpus.Basic.Kernel.Objects.Bounded,+ Wumpus.Basic.Kernel.Objects.Chain,+ Wumpus.Basic.Kernel.Objects.Concat, Wumpus.Basic.Kernel.Objects.Connector, Wumpus.Basic.Kernel.Objects.CtxPicture, Wumpus.Basic.Kernel.Objects.Displacement, Wumpus.Basic.Kernel.Objects.DrawingPrimitives,- Wumpus.Basic.Kernel.Objects.Graphic,- Wumpus.Basic.Kernel.Objects.PosImage,+ Wumpus.Basic.Kernel.Objects.Image,+ Wumpus.Basic.Kernel.Objects.LocImage,+ Wumpus.Basic.Kernel.Objects.LocThetaImage,+ Wumpus.Basic.Kernel.Objects.Orientation,+ Wumpus.Basic.Kernel.Objects.PosObject, Wumpus.Basic.Kernel.Objects.TraceDrawing,- Wumpus.Basic.System.FontLoader.Afm,- Wumpus.Basic.System.FontLoader.GhostScript,- Wumpus.Basic.System.FontLoader.Base.AfmParserBase,- Wumpus.Basic.System.FontLoader.Base.AfmV2Parser,- Wumpus.Basic.System.FontLoader.Base.AfmV4Dot1Parser,- Wumpus.Basic.System.FontLoader.Base.Datatypes,- Wumpus.Basic.System.FontLoader.Base.FontLoadMonad,- Wumpus.Basic.System.FontLoader.Base.GSFontMap,+ Wumpus.Basic.System.FontLoader,+ Wumpus.Basic.System.FontLoader.AfmParserBase,+ Wumpus.Basic.System.FontLoader.AfmTopLevel,+ Wumpus.Basic.System.FontLoader.AfmV2Parser,+ Wumpus.Basic.System.FontLoader.AfmV4Dot1Parser,+ Wumpus.Basic.System.FontLoader.Datatypes,+ Wumpus.Basic.System.FontLoader.FontLoadMonad,+ Wumpus.Basic.System.FontLoader.GSTopLevel, Wumpus.Basic.Utils.HList, Wumpus.Basic.Utils.FormatCombinators, Wumpus.Basic.Utils.JoinList,