{-# LANGUAGE TemplateHaskell #-}
module Graphics.Rendering.Chart.Drawing
  ( 
    PointShape(..)
  , PointStyle(..)
  , drawPoint
  
  
  , alignPath
  , alignFillPath
  , alignStrokePath
  , alignFillPoints
  , alignStrokePoints
  
  , alignFillPoint
  , alignStrokePoint
  
  , strokePointPath
  , fillPointPath
  
  
  , withRotation
  , withTranslation
  , withScale
  , withScaleX, withScaleY
  , withPointStyle
  , withDefaultStyle
  
  
  , drawTextA
  , drawTextR
  , drawTextsR
  , textDrawRect
  , textDimension
  
  
  , defaultColorSeq
    
  , solidLine
  , dashedLine
  , filledCircles
  , hollowCircles
  , filledPolygon
  , hollowPolygon
  , plusses
  , exes
  , stars
  , arrows
    
  , solidFillStyle
  
  
  , module Graphics.Rendering.Chart.Backend
  
  
  , point_color
  , point_border_color
  , point_border_width
  , point_radius
  , point_shape
) where
import Data.Default.Class
import Control.Lens
import Data.Colour
import Data.Colour.Names
import Data.List (unfoldr)
import Data.Monoid
import Graphics.Rendering.Chart.Backend
import Graphics.Rendering.Chart.Geometry hiding (moveTo)
import qualified Graphics.Rendering.Chart.Geometry as G
withRotation :: Double -> BackendProgram a -> BackendProgram a
withRotation :: Double -> BackendProgram a -> BackendProgram a
withRotation Double
angle = Matrix -> BackendProgram a -> BackendProgram a
forall a. Matrix -> BackendProgram a -> BackendProgram a
withTransform (Double -> Matrix -> Matrix
rotate Double
angle Matrix
1)
withTranslation :: Point -> BackendProgram a -> BackendProgram a
withTranslation :: Point -> BackendProgram a -> BackendProgram a
withTranslation Point
p = Matrix -> BackendProgram a -> BackendProgram a
forall a. Matrix -> BackendProgram a -> BackendProgram a
withTransform (Vector -> Matrix -> Matrix
translate (Point -> Vector
pointToVec Point
p) Matrix
1)
withScale :: Vector -> BackendProgram a -> BackendProgram a
withScale :: Vector -> BackendProgram a -> BackendProgram a
withScale Vector
v = Matrix -> BackendProgram a -> BackendProgram a
forall a. Matrix -> BackendProgram a -> BackendProgram a
withTransform (Vector -> Matrix -> Matrix
scale Vector
v Matrix
1)
withScaleX :: Double -> BackendProgram a -> BackendProgram a
withScaleX :: Double -> BackendProgram a -> BackendProgram a
withScaleX Double
x = Vector -> BackendProgram a -> BackendProgram a
forall a. Vector -> BackendProgram a -> BackendProgram a
withScale (Double -> Double -> Vector
Vector Double
x Double
1)
withScaleY :: Double -> BackendProgram a -> BackendProgram a
withScaleY :: Double -> BackendProgram a -> BackendProgram a
withScaleY Double
y = Vector -> BackendProgram a -> BackendProgram a
forall a. Vector -> BackendProgram a -> BackendProgram a
withScale (Double -> Double -> Vector
Vector Double
1 Double
y)
withPointStyle :: PointStyle -> BackendProgram a -> BackendProgram a
withPointStyle :: PointStyle -> BackendProgram a -> BackendProgram a
withPointStyle (PointStyle AlphaColour Double
cl AlphaColour Double
bcl Double
bw Double
_ PointShape
_) BackendProgram a
m = 
  LineStyle -> BackendProgram a -> BackendProgram a
forall a. LineStyle -> BackendProgram a -> BackendProgram a
withLineStyle (LineStyle
forall a. Default a => a
def { _line_color :: AlphaColour Double
_line_color = AlphaColour Double
bcl, _line_width :: Double
_line_width = Double
bw, _line_join :: LineJoin
_line_join = LineJoin
LineJoinMiter }) (BackendProgram a -> BackendProgram a)
-> BackendProgram a -> BackendProgram a
forall a b. (a -> b) -> a -> b
$ 
    FillStyle -> BackendProgram a -> BackendProgram a
forall a. FillStyle -> BackendProgram a -> BackendProgram a
withFillStyle (AlphaColour Double -> FillStyle
solidFillStyle AlphaColour Double
cl) BackendProgram a
m
withDefaultStyle :: BackendProgram a -> BackendProgram a
withDefaultStyle :: BackendProgram a -> BackendProgram a
withDefaultStyle = LineStyle -> BackendProgram a -> BackendProgram a
forall a. LineStyle -> BackendProgram a -> BackendProgram a
withLineStyle LineStyle
forall a. Default a => a
def (BackendProgram a -> BackendProgram a)
-> (BackendProgram a -> BackendProgram a)
-> BackendProgram a
-> BackendProgram a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FillStyle -> BackendProgram a -> BackendProgram a
forall a. FillStyle -> BackendProgram a -> BackendProgram a
withFillStyle FillStyle
forall a. Default a => a
def (BackendProgram a -> BackendProgram a)
-> (BackendProgram a -> BackendProgram a)
-> BackendProgram a
-> BackendProgram a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FontStyle -> BackendProgram a -> BackendProgram a
forall a. FontStyle -> BackendProgram a -> BackendProgram a
withFontStyle FontStyle
forall a. Default a => a
def
alignPath :: (Point -> Point) -> Path -> Path
alignPath :: (Point -> Point) -> Path -> Path
alignPath Point -> Point
f = (Point -> Path)
-> (Point -> Path)
-> (Point -> Double -> Double -> Double -> Path)
-> (Point -> Double -> Double -> Double -> Path)
-> Path
-> Path
-> Path
forall m.
Monoid m =>
(Point -> m)
-> (Point -> m)
-> (Point -> Double -> Double -> Double -> m)
-> (Point -> Double -> Double -> Double -> m)
-> m
-> Path
-> m
foldPath (Point -> Path
G.moveTo (Point -> Path) -> (Point -> Point) -> Point -> Path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Point -> Point
f)
                       (Point -> Path
lineTo (Point -> Path) -> (Point -> Point) -> Point -> Path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Point -> Point
f)
                       (Point -> Double -> Double -> Double -> Path
arc (Point -> Double -> Double -> Double -> Path)
-> (Point -> Point) -> Point -> Double -> Double -> Double -> Path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Point -> Point
f)
                       (Point -> Double -> Double -> Double -> Path
arcNeg (Point -> Double -> Double -> Double -> Path)
-> (Point -> Point) -> Point -> Double -> Double -> Double -> Path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Point -> Point
f)
                       Path
close
alignStrokePath :: Path -> BackendProgram Path
alignStrokePath :: Path -> BackendProgram Path
alignStrokePath Path
p = do
  Point -> Point
f <- BackendProgram (Point -> Point)
getPointAlignFn
  Path -> BackendProgram Path
forall (m :: * -> *) a. Monad m => a -> m a
return (Path -> BackendProgram Path) -> Path -> BackendProgram Path
forall a b. (a -> b) -> a -> b
$ (Point -> Point) -> Path -> Path
alignPath Point -> Point
f Path
p
alignFillPath :: Path -> BackendProgram Path
alignFillPath :: Path -> BackendProgram Path
alignFillPath Path
p = do
  Point -> Point
f <- BackendProgram (Point -> Point)
getCoordAlignFn
  Path -> BackendProgram Path
forall (m :: * -> *) a. Monad m => a -> m a
return (Path -> BackendProgram Path) -> Path -> BackendProgram Path
forall a b. (a -> b) -> a -> b
$ (Point -> Point) -> Path -> Path
alignPath Point -> Point
f Path
p
alignStrokePoints :: [Point] -> BackendProgram [Point]
alignStrokePoints :: [Point] -> BackendProgram [Point]
alignStrokePoints [Point]
p = do
  Point -> Point
f <- BackendProgram (Point -> Point)
getPointAlignFn
  [Point] -> BackendProgram [Point]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Point] -> BackendProgram [Point])
-> [Point] -> BackendProgram [Point]
forall a b. (a -> b) -> a -> b
$ (Point -> Point) -> [Point] -> [Point]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Point -> Point
f [Point]
p
alignFillPoints :: [Point] -> BackendProgram [Point]
alignFillPoints :: [Point] -> BackendProgram [Point]
alignFillPoints [Point]
p = do
  Point -> Point
f <- BackendProgram (Point -> Point)
getCoordAlignFn
  [Point] -> BackendProgram [Point]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Point] -> BackendProgram [Point])
-> [Point] -> BackendProgram [Point]
forall a b. (a -> b) -> a -> b
$ (Point -> Point) -> [Point] -> [Point]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Point -> Point
f [Point]
p
alignStrokePoint :: Point -> BackendProgram Point
alignStrokePoint :: Point -> BackendProgram Point
alignStrokePoint Point
p = do 
    Point -> Point
alignfn <- BackendProgram (Point -> Point)
getPointAlignFn
    Point -> BackendProgram Point
forall (m :: * -> *) a. Monad m => a -> m a
return (Point -> Point
alignfn Point
p)
alignFillPoint :: Point -> BackendProgram Point
alignFillPoint :: Point -> BackendProgram Point
alignFillPoint Point
p = do 
    Point -> Point
alignfn <- BackendProgram (Point -> Point)
getCoordAlignFn
    Point -> BackendProgram Point
forall (m :: * -> *) a. Monad m => a -> m a
return (Point -> Point
alignfn Point
p)
stepPath :: [Point] -> Path
stepPath :: [Point] -> Path
stepPath (Point
p:[Point]
ps) = Point -> Path
G.moveTo Point
p
               Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> [Path] -> Path
forall a. Monoid a => [a] -> a
mconcat ((Point -> Path) -> [Point] -> [Path]
forall a b. (a -> b) -> [a] -> [b]
map Point -> Path
lineTo [Point]
ps)
stepPath [] = Path
forall a. Monoid a => a
mempty
strokePointPath :: [Point] -> BackendProgram ()
strokePointPath :: [Point] -> BackendProgram ()
strokePointPath [Point]
pts = Path -> BackendProgram ()
strokePath (Path -> BackendProgram ()) -> Path -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$ [Point] -> Path
stepPath [Point]
pts
fillPointPath :: [Point] -> BackendProgram ()
fillPointPath :: [Point] -> BackendProgram ()
fillPointPath [Point]
pts = Path -> BackendProgram ()
fillPath (Path -> BackendProgram ()) -> Path -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$ [Point] -> Path
stepPath [Point]
pts
drawTextA :: HTextAnchor -> VTextAnchor -> Point -> String -> BackendProgram ()
drawTextA :: HTextAnchor -> VTextAnchor -> Point -> String -> BackendProgram ()
drawTextA HTextAnchor
hta VTextAnchor
vta = HTextAnchor
-> VTextAnchor -> Double -> Point -> String -> BackendProgram ()
drawTextR HTextAnchor
hta VTextAnchor
vta Double
0
  
drawTextR :: HTextAnchor -> VTextAnchor -> Double -> Point -> String -> BackendProgram ()
drawTextR :: HTextAnchor
-> VTextAnchor -> Double -> Point -> String -> BackendProgram ()
drawTextR HTextAnchor
hta VTextAnchor
vta Double
angle Point
p String
s =
  Point -> BackendProgram () -> BackendProgram ()
forall a. Point -> BackendProgram a -> BackendProgram a
withTranslation Point
p (BackendProgram () -> BackendProgram ())
-> BackendProgram () -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$
    Double -> BackendProgram () -> BackendProgram ()
forall a. Double -> BackendProgram a -> BackendProgram a
withRotation Double
theta (BackendProgram () -> BackendProgram ())
-> BackendProgram () -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$ do
      TextSize
ts <- String -> BackendProgram TextSize
textSize String
s
      Point -> String -> BackendProgram ()
drawText (HTextAnchor -> VTextAnchor -> TextSize -> Point
adjustText HTextAnchor
hta VTextAnchor
vta TextSize
ts) String
s
  where
    theta :: Double
theta = Double
angleDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
180.0
drawTextsR :: HTextAnchor -> VTextAnchor -> Double -> Point -> String -> BackendProgram ()
drawTextsR :: HTextAnchor
-> VTextAnchor -> Double -> Point -> String -> BackendProgram ()
drawTextsR HTextAnchor
hta VTextAnchor
vta Double
angle Point
p String
s = case Int
num of
      Int
0 -> () -> BackendProgram ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
      Int
1 -> HTextAnchor
-> VTextAnchor -> Double -> Point -> String -> BackendProgram ()
drawTextR HTextAnchor
hta VTextAnchor
vta Double
angle Point
p String
s
      Int
_ -> 
        Point -> BackendProgram () -> BackendProgram ()
forall a. Point -> BackendProgram a -> BackendProgram a
withTranslation Point
p (BackendProgram () -> BackendProgram ())
-> BackendProgram () -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$
          Double -> BackendProgram () -> BackendProgram ()
forall a. Double -> BackendProgram a -> BackendProgram a
withRotation Double
theta (BackendProgram () -> BackendProgram ())
-> BackendProgram () -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$ do
            [TextSize]
tss <- (String -> BackendProgram TextSize)
-> [String] -> ProgramT ChartBackendInstr Identity [TextSize]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM String -> BackendProgram TextSize
textSize [String]
ss
            let ts :: TextSize
ts = [TextSize] -> TextSize
forall a. [a] -> a
head [TextSize]
tss
            let 
                
                maxh :: Double
maxh   = [Double] -> Double
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ((TextSize -> Double) -> [TextSize] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map TextSize -> Double
textSizeYBearing [TextSize]
tss)
                gap :: Double
gap    = Double
maxh Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2 
                totalHeight :: Double
totalHeight = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
numDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
maxh Double -> Double -> Double
forall a. Num a => a -> a -> a
+
                              (Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
numDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
1)Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
gap
                ys :: [Double]
ys = Int -> [Double] -> [Double]
forall a. Int -> [a] -> [a]
take Int
num ((Double -> Maybe (Double, Double)) -> Double -> [Double]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr (\Double
y-> (Double, Double) -> Maybe (Double, Double)
forall a. a -> Maybe a
Just (Double
y, Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
gapDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
maxh))
                                       (VTextAnchor -> TextSize -> Double -> Double
yinit VTextAnchor
vta TextSize
ts Double
totalHeight))
                xs :: [Double]
xs = (TextSize -> Double) -> [TextSize] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map (HTextAnchor -> TextSize -> Double
adjustTextX HTextAnchor
hta) [TextSize]
tss
            [BackendProgram ()] -> BackendProgram ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
t (m a) -> m ()
sequence_ ((Double -> Double -> String -> BackendProgram ())
-> [Double] -> [Double] -> [String] -> [BackendProgram ()]
forall a b c d. (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
zipWith3 Double -> Double -> String -> BackendProgram ()
drawT [Double]
xs [Double]
ys [String]
ss)
    where
      ss :: [String]
ss   = String -> [String]
lines String
s
      num :: Int
num  = [String] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [String]
ss
      drawT :: Double -> Double -> String -> BackendProgram ()
drawT Double
x Double
y = Point -> String -> BackendProgram ()
drawText (Double -> Double -> Point
Point Double
x Double
y)
      theta :: Double
theta = Double
angleDouble -> Double -> Double
forall a. Num a => a -> a -> a
*Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
180.0
      yinit :: VTextAnchor -> TextSize -> Double -> Double
yinit VTextAnchor
VTA_Top      TextSize
ts Double
_      = TextSize -> Double
textSizeAscent TextSize
ts
      yinit VTextAnchor
VTA_BaseLine TextSize
_  Double
_      = Double
0
      yinit VTextAnchor
VTA_Centre   TextSize
ts Double
height = Double
height Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ TextSize -> Double
textSizeAscent TextSize
ts
      yinit VTextAnchor
VTA_Bottom   TextSize
ts Double
height = Double
height Double -> Double -> Double
forall a. Num a => a -> a -> a
+ TextSize -> Double
textSizeAscent TextSize
ts
adjustText :: HTextAnchor -> VTextAnchor -> TextSize -> Point
adjustText :: HTextAnchor -> VTextAnchor -> TextSize -> Point
adjustText HTextAnchor
hta VTextAnchor
vta TextSize
ts = Double -> Double -> Point
Point (HTextAnchor -> TextSize -> Double
adjustTextX HTextAnchor
hta TextSize
ts) (VTextAnchor -> TextSize -> Double
adjustTextY VTextAnchor
vta TextSize
ts)
adjustTextX :: HTextAnchor -> TextSize -> Double
adjustTextX :: HTextAnchor -> TextSize -> Double
adjustTextX HTextAnchor
HTA_Left   TextSize
_  = Double
0
adjustTextX HTextAnchor
HTA_Centre TextSize
ts = - (TextSize -> Double
textSizeWidth TextSize
ts Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2)
adjustTextX HTextAnchor
HTA_Right  TextSize
ts = - TextSize -> Double
textSizeWidth TextSize
ts
adjustTextY :: VTextAnchor -> TextSize -> Double
adjustTextY :: VTextAnchor -> TextSize -> Double
adjustTextY VTextAnchor
VTA_Top      TextSize
ts = TextSize -> Double
textSizeAscent TextSize
ts
adjustTextY VTextAnchor
VTA_Centre   TextSize
ts = - TextSize -> Double
textSizeYBearing TextSize
ts Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2
adjustTextY VTextAnchor
VTA_BaseLine TextSize
_  = Double
0
adjustTextY VTextAnchor
VTA_Bottom   TextSize
ts = - TextSize -> Double
textSizeDescent TextSize
ts
textDrawRect :: HTextAnchor -> VTextAnchor -> Point -> String -> BackendProgram Rect
textDrawRect :: HTextAnchor
-> VTextAnchor -> Point -> String -> BackendProgram Rect
textDrawRect HTextAnchor
hta VTextAnchor
vta (Point Double
x Double
y) String
s = do
  TextSize
ts <- String -> BackendProgram TextSize
textSize String
s
  
  
  
  
  
  let (Double
w,Double
h,Double
dh) = (TextSize -> Double
textSizeWidth TextSize
ts, TextSize -> Double
textSizeHeight TextSize
ts, TextSize -> Double
textSizeDescent TextSize
ts)
      lx :: Double
lx = HTextAnchor -> TextSize -> Double
adjustTextX HTextAnchor
hta TextSize
ts
      ly :: Double
ly = VTextAnchor -> TextSize -> Double
adjustTextY VTextAnchor
vta TextSize
ts
      (Double
x',Double
y') = (Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
lx, Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
ly Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
dh)
      p1 :: Point
p1 = Double -> Double -> Point
Point Double
x' (Double
y' Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
h)
      p2 :: Point
p2 = Double -> Double -> Point
Point (Double
x' Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
w) Double
y'
  Rect -> BackendProgram Rect
forall (m :: * -> *) a. Monad m => a -> m a
return (Rect -> BackendProgram Rect) -> Rect -> BackendProgram Rect
forall a b. (a -> b) -> a -> b
$ Point -> Point -> Rect
Rect Point
p1 Point
p2
textDimension :: String -> BackendProgram RectSize
textDimension :: String -> BackendProgram (Double, Double)
textDimension String
s = do
  TextSize
ts <- String -> BackendProgram TextSize
textSize String
s
  (Double, Double) -> BackendProgram (Double, Double)
forall (m :: * -> *) a. Monad m => a -> m a
return (TextSize -> Double
textSizeWidth TextSize
ts, TextSize -> Double
textSizeHeight TextSize
ts)
  
data PointShape = PointShapeCircle           
                | PointShapePolygon Int Bool 
                | PointShapePlus  
                | PointShapeCross 
                | PointShapeStar  
                | PointShapeArrowHead Double
                | PointShapeEllipse Double Double 
data PointStyle = PointStyle
  { PointStyle -> AlphaColour Double
_point_color :: AlphaColour Double
  
  , PointStyle -> AlphaColour Double
_point_border_color :: AlphaColour Double
  
  , PointStyle -> Double
_point_border_width :: Double
  
  , PointStyle -> Double
_point_radius :: Double
  
  , PointStyle -> PointShape
_point_shape :: PointShape
  
  }
instance Default PointStyle where
  def :: PointStyle
def = PointStyle :: AlphaColour Double
-> AlphaColour Double
-> Double
-> Double
-> PointShape
-> PointStyle
PointStyle 
    { _point_color :: AlphaColour Double
_point_color        = Colour Double -> AlphaColour Double
forall a. Num a => Colour a -> AlphaColour a
opaque Colour Double
forall a. Num a => Colour a
black
    , _point_border_color :: AlphaColour Double
_point_border_color = AlphaColour Double
forall a. Num a => AlphaColour a
transparent
    , _point_border_width :: Double
_point_border_width = Double
0
    , _point_radius :: Double
_point_radius       = Double
1
    , _point_shape :: PointShape
_point_shape        = PointShape
PointShapeCircle
    }
drawPoint :: PointStyle  
          -> Point       
          -> BackendProgram ()
drawPoint :: PointStyle -> Point -> BackendProgram ()
drawPoint ps :: PointStyle
ps@(PointStyle AlphaColour Double
cl AlphaColour Double
_ Double
_ Double
r PointShape
shape) Point
p = PointStyle -> BackendProgram () -> BackendProgram ()
forall a. PointStyle -> BackendProgram a -> BackendProgram a
withPointStyle PointStyle
ps (BackendProgram () -> BackendProgram ())
-> BackendProgram () -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$ do
  p' :: Point
p'@(Point Double
x Double
y) <- Point -> BackendProgram Point
alignStrokePoint Point
p
  case PointShape
shape of
    PointShape
PointShapeCircle -> do
      let path :: Path
path = Point -> Double -> Double -> Double -> Path
arc Point
p' Double
r Double
0 (Double
2Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
forall a. Floating a => a
pi)
      Path -> BackendProgram ()
fillPath Path
path
      Path -> BackendProgram ()
strokePath Path
path
    PointShapePolygon Int
sides Bool
isrot -> do
      let intToAngle :: a -> p
intToAngle a
n =
            if Bool
isrot
            then       a -> p
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n p -> p -> p
forall a. Num a => a -> a -> a
* p
2p -> p -> p
forall a. Num a => a -> a -> a
*p
forall a. Floating a => a
pip -> p -> p
forall a. Fractional a => a -> a -> a
/Int -> p
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
sides
            else (p
0.5 p -> p -> p
forall a. Num a => a -> a -> a
+ a -> p
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n)p -> p -> p
forall a. Num a => a -> a -> a
*p
2p -> p -> p
forall a. Num a => a -> a -> a
*p
forall a. Floating a => a
pip -> p -> p
forall a. Fractional a => a -> a -> a
/Int -> p
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
sides
          angles :: [Double]
angles = (Int -> Double) -> [Int] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map Int -> Double
forall p a. (Integral a, Floating p) => a -> p
intToAngle [Int
0 .. Int
sidesInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1]
          (Point
p1:Point
p1':[Point]
p1s) = (Double -> Point) -> [Double] -> [Point]
forall a b. (a -> b) -> [a] -> [b]
map (\Double
a -> Double -> Double -> Point
Point (Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
r Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
sin Double
a)
                                      (Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
r Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos Double
a)) [Double]
angles
      let path :: Path
path = Point -> Path
G.moveTo Point
p1 Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> [Path] -> Path
forall a. Monoid a => [a] -> a
mconcat ((Point -> Path) -> [Point] -> [Path]
forall a b. (a -> b) -> [a] -> [b]
map Point -> Path
lineTo ([Point] -> [Path]) -> [Point] -> [Path]
forall a b. (a -> b) -> a -> b
$ Point
p1'Point -> [Point] -> [Point]
forall a. a -> [a] -> [a]
:[Point]
p1s) Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Point -> Path
lineTo Point
p1 Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Point -> Path
lineTo Point
p1'
      Path -> BackendProgram ()
fillPath Path
path
      Path -> BackendProgram ()
strokePath Path
path
    PointShapeArrowHead Double
theta ->
      Point -> BackendProgram () -> BackendProgram ()
forall a. Point -> BackendProgram a -> BackendProgram a
withTranslation Point
p (BackendProgram () -> BackendProgram ())
-> BackendProgram () -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$ Double -> BackendProgram () -> BackendProgram ()
forall a. Double -> BackendProgram a -> BackendProgram a
withRotation (Double
theta Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
forall a. Floating a => a
piDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2) (BackendProgram () -> BackendProgram ())
-> BackendProgram () -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$
          PointStyle -> Point -> BackendProgram ()
drawPoint (Double -> Int -> Bool -> AlphaColour Double -> PointStyle
filledPolygon Double
r Int
3 Bool
True AlphaColour Double
cl) (Double -> Double -> Point
Point Double
0 Double
0)
    PointShape
PointShapePlus -> 
      Path -> BackendProgram ()
strokePath (Path -> BackendProgram ()) -> Path -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Path
moveTo' (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
r) Double
y
                Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
lineTo' (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
r) Double
y
                Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
moveTo' Double
x (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
r)
                Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
lineTo' Double
x (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
r)
    PointShape
PointShapeCross -> do
      let rad :: Double
rad = Double
r Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double -> Double
forall a. Floating a => a -> a
sqrt Double
2
      Path -> BackendProgram ()
strokePath (Path -> BackendProgram ()) -> Path -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Path
moveTo' (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
rad) (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
rad)
                Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
lineTo' (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
rad) (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
rad)
                Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
moveTo' (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
rad) (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
rad)
                Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
lineTo' (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
rad) (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
rad)
    PointShape
PointShapeStar -> do
      let rad :: Double
rad = Double
r Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double -> Double
forall a. Floating a => a -> a
sqrt Double
2
      Path -> BackendProgram ()
strokePath (Path -> BackendProgram ()) -> Path -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Path
moveTo' (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
r) Double
y
                Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
lineTo' (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
r) Double
y
                Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
moveTo' Double
x (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
r)
                Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
lineTo' Double
x (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
r)
                Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
moveTo' (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
rad) (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
rad)
                Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
lineTo' (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
rad) (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
rad)
                Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
moveTo' (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
rad) (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
rad)
                Path -> Path -> Path
forall a. Semigroup a => a -> a -> a
<> Double -> Double -> Path
lineTo' (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
rad) (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
rad)
    PointShapeEllipse Double
b Double
theta ->
      Point -> BackendProgram () -> BackendProgram ()
forall a. Point -> BackendProgram a -> BackendProgram a
withTranslation Point
p (BackendProgram () -> BackendProgram ())
-> BackendProgram () -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$ Double -> BackendProgram () -> BackendProgram ()
forall a. Double -> BackendProgram a -> BackendProgram a
withRotation Double
theta (BackendProgram () -> BackendProgram ())
-> BackendProgram () -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$ Double -> BackendProgram () -> BackendProgram ()
forall a. Double -> BackendProgram a -> BackendProgram a
withScaleX Double
b (BackendProgram () -> BackendProgram ())
-> BackendProgram () -> BackendProgram ()
forall a b. (a -> b) -> a -> b
$ do
        let path :: Path
path = Point -> Double -> Double -> Double -> Path
arc (Double -> Double -> Point
Point Double
0 Double
0) Double
r Double
0 (Double
2Double -> Double -> Double
forall a. Num a => a -> a -> a
*Double
forall a. Floating a => a
pi)
        Path -> BackendProgram ()
fillPath Path
path
        Path -> BackendProgram ()
strokePath Path
path
defaultColorSeq :: [AlphaColour Double]
defaultColorSeq :: [AlphaColour Double]
defaultColorSeq = [AlphaColour Double] -> [AlphaColour Double]
forall a. [a] -> [a]
cycle ([AlphaColour Double] -> [AlphaColour Double])
-> [AlphaColour Double] -> [AlphaColour Double]
forall a b. (a -> b) -> a -> b
$ (Colour Double -> AlphaColour Double)
-> [Colour Double] -> [AlphaColour Double]
forall a b. (a -> b) -> [a] -> [b]
map Colour Double -> AlphaColour Double
forall a. Num a => Colour a -> AlphaColour a
opaque [Colour Double
forall a. (Ord a, Floating a) => Colour a
blue, Colour Double
forall a. (Ord a, Floating a) => Colour a
red, Colour Double
forall a. (Ord a, Floating a) => Colour a
green, Colour Double
forall a. (Ord a, Floating a) => Colour a
yellow, Colour Double
forall a. (Ord a, Floating a) => Colour a
cyan, Colour Double
forall a. (Ord a, Floating a) => Colour a
magenta]
solidLine :: Double             
          -> AlphaColour Double 
          -> LineStyle
solidLine :: Double -> AlphaColour Double -> LineStyle
solidLine Double
w AlphaColour Double
cl = Double
-> AlphaColour Double
-> [Double]
-> LineCap
-> LineJoin
-> LineStyle
LineStyle Double
w AlphaColour Double
cl [] LineCap
LineCapButt LineJoin
LineJoinMiter
dashedLine :: Double   
           -> [Double] 
           -> AlphaColour Double 
           -> LineStyle
dashedLine :: Double -> [Double] -> AlphaColour Double -> LineStyle
dashedLine Double
w [Double]
ds AlphaColour Double
cl = Double
-> AlphaColour Double
-> [Double]
-> LineCap
-> LineJoin
-> LineStyle
LineStyle Double
w AlphaColour Double
cl [Double]
ds LineCap
LineCapButt LineJoin
LineJoinMiter
filledCircles :: Double             
              -> AlphaColour Double 
              -> PointStyle
filledCircles :: Double -> AlphaColour Double -> PointStyle
filledCircles Double
radius AlphaColour Double
cl = 
  AlphaColour Double
-> AlphaColour Double
-> Double
-> Double
-> PointShape
-> PointStyle
PointStyle AlphaColour Double
cl AlphaColour Double
forall a. Num a => AlphaColour a
transparent Double
0 Double
radius PointShape
PointShapeCircle
hollowCircles :: Double 
              -> Double 
              -> AlphaColour Double 
              -> PointStyle
hollowCircles :: Double -> Double -> AlphaColour Double -> PointStyle
hollowCircles Double
radius Double
w AlphaColour Double
cl = 
  AlphaColour Double
-> AlphaColour Double
-> Double
-> Double
-> PointShape
-> PointStyle
PointStyle AlphaColour Double
forall a. Num a => AlphaColour a
transparent AlphaColour Double
cl Double
w Double
radius PointShape
PointShapeCircle
hollowPolygon :: Double 
              -> Double 
              -> Int    
              -> Bool   
              -> AlphaColour Double 
              -> PointStyle
hollowPolygon :: Double -> Double -> Int -> Bool -> AlphaColour Double -> PointStyle
hollowPolygon Double
radius Double
w Int
sides Bool
isrot AlphaColour Double
cl = 
  AlphaColour Double
-> AlphaColour Double
-> Double
-> Double
-> PointShape
-> PointStyle
PointStyle AlphaColour Double
forall a. Num a => AlphaColour a
transparent AlphaColour Double
cl Double
w Double
radius (Int -> Bool -> PointShape
PointShapePolygon Int
sides Bool
isrot)
filledPolygon :: Double 
              -> Int    
              -> Bool   
              -> AlphaColour Double 
              -> PointStyle
filledPolygon :: Double -> Int -> Bool -> AlphaColour Double -> PointStyle
filledPolygon Double
radius Int
sides Bool
isrot AlphaColour Double
cl = 
  AlphaColour Double
-> AlphaColour Double
-> Double
-> Double
-> PointShape
-> PointStyle
PointStyle AlphaColour Double
cl AlphaColour Double
forall a. Num a => AlphaColour a
transparent Double
0 Double
radius (Int -> Bool -> PointShape
PointShapePolygon Int
sides Bool
isrot)
plusses :: Double 
        -> Double 
        -> AlphaColour Double 
        -> PointStyle
plusses :: Double -> Double -> AlphaColour Double -> PointStyle
plusses Double
radius Double
w AlphaColour Double
cl = 
  AlphaColour Double
-> AlphaColour Double
-> Double
-> Double
-> PointShape
-> PointStyle
PointStyle AlphaColour Double
forall a. Num a => AlphaColour a
transparent AlphaColour Double
cl Double
w Double
radius PointShape
PointShapePlus
exes :: Double 
     -> Double 
     -> AlphaColour Double 
     -> PointStyle
exes :: Double -> Double -> AlphaColour Double -> PointStyle
exes Double
radius Double
w AlphaColour Double
cl =
  AlphaColour Double
-> AlphaColour Double
-> Double
-> Double
-> PointShape
-> PointStyle
PointStyle AlphaColour Double
forall a. Num a => AlphaColour a
transparent AlphaColour Double
cl Double
w Double
radius PointShape
PointShapeCross
stars :: Double 
      -> Double 
      -> AlphaColour Double 
      -> PointStyle
stars :: Double -> Double -> AlphaColour Double -> PointStyle
stars Double
radius Double
w AlphaColour Double
cl =
  AlphaColour Double
-> AlphaColour Double
-> Double
-> Double
-> PointShape
-> PointStyle
PointStyle AlphaColour Double
forall a. Num a => AlphaColour a
transparent AlphaColour Double
cl Double
w Double
radius PointShape
PointShapeStar
arrows :: Double 
       -> Double 
       -> Double 
       -> AlphaColour Double 
       -> PointStyle
arrows :: Double -> Double -> Double -> AlphaColour Double -> PointStyle
arrows Double
radius Double
angle Double
w AlphaColour Double
cl =
  AlphaColour Double
-> AlphaColour Double
-> Double
-> Double
-> PointShape
-> PointStyle
PointStyle AlphaColour Double
forall a. Num a => AlphaColour a
transparent AlphaColour Double
cl Double
w Double
radius (Double -> PointShape
PointShapeArrowHead Double
angle)
solidFillStyle :: AlphaColour Double -> FillStyle
solidFillStyle :: AlphaColour Double -> FillStyle
solidFillStyle = AlphaColour Double -> FillStyle
FillStyleSolid
$( makeLenses ''PointStyle )