{-# LANGUAGE FlexibleContexts  #-}
{-# LANGUAGE OverloadedStrings #-}

-------------------------------------------------------------------------------
-- |
-- Module      :  Graphics.Svg.Path
-- Copyright   :  (c) 2015 Jeffrey Rosenbluth
-- License     :  BSD-style (see LICENSE)
-- Maintainer  :  jeffrey.rosenbluth@gmail.com
--
-- Utility functions to help create SVG path attributes,
-- and transforms.
--
-------------------------------------------------------------------------------

module Graphics.Svg.Path where

import           Data.Text                        (Text)
import qualified Data.Text                        as T
import           Data.Text.Lazy                   (toStrict)
import           Data.Text.Lazy.Builder           (toLazyText)
import           Data.Text.Lazy.Builder.RealFloat

-- | Convert a number to Text.
toText :: RealFloat a => a -> Text
toText :: a -> Text
toText = Text -> Text
toStrict (Text -> Text) -> (a -> Text) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
toLazyText (Builder -> Text) -> (a -> Builder) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FPFormat -> Maybe Int -> a -> Builder
forall a. RealFloat a => FPFormat -> Maybe Int -> a -> Builder
formatRealFloat FPFormat
Fixed (Int -> Maybe Int
forall a. a -> Maybe a
Just 4)

-- | moveto (absolute)
mA :: RealFloat a =>  a -> a -> Text
mA :: a -> a -> Text
mA x :: a
x y :: a
y = [Text] -> Text
T.concat ["M " ,a -> Text
forall a. RealFloat a => a -> Text
toText a
x, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
y, " "]

-- | moveto (relative)
mR :: RealFloat a =>  a -> a -> Text
mR :: a -> a -> Text
mR dx :: a
dx dy :: a
dy = [Text] -> Text
T.concat ["m ", a -> Text
forall a. RealFloat a => a -> Text
toText a
dx, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
dy, " "]

-- | lineto (absolute)
lA :: RealFloat a =>  a -> a -> Text
lA :: a -> a -> Text
lA x :: a
x y :: a
y = [Text] -> Text
T.concat ["L ", a -> Text
forall a. RealFloat a => a -> Text
toText a
x, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
y, " "]

-- | lineto (relative)
lR :: RealFloat a =>  a -> a -> Text
lR :: a -> a -> Text
lR dx :: a
dx dy :: a
dy = [Text] -> Text
T.concat ["l ", a -> Text
forall a. RealFloat a => a -> Text
toText a
dx, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
dy, " "]

-- | horizontal lineto (absolute)
hA :: RealFloat a =>  a -> Text
hA :: a -> Text
hA x :: a
x = [Text] -> Text
T.concat ["H ", a -> Text
forall a. RealFloat a => a -> Text
toText a
x, " "]

-- | horizontal lineto (relative)
hR :: RealFloat a =>  a -> Text
hR :: a -> Text
hR dx :: a
dx = [Text] -> Text
T.concat ["h ", a -> Text
forall a. RealFloat a => a -> Text
toText a
dx, " "]

-- | vertical lineto (absolute)
vA :: RealFloat a =>  a -> Text
vA :: a -> Text
vA y :: a
y = [Text] -> Text
T.concat ["V ", a -> Text
forall a. RealFloat a => a -> Text
toText a
y, " "]

-- | vertical lineto (relative)
vR :: RealFloat a =>  a -> Text
vR :: a -> Text
vR dy :: a
dy = [Text] -> Text
T.concat ["v ", a -> Text
forall a. RealFloat a => a -> Text
toText a
dy, " "]

-- | Cubic Bezier curve (absolute)
cA :: RealFloat a =>  a -> a -> a -> a -> a -> a -> Text
cA :: a -> a -> a -> a -> a -> a -> Text
cA c1x :: a
c1x c1y :: a
c1y c2x :: a
c2x c2y :: a
c2y x :: a
x y :: a
y = [Text] -> Text
T.concat
  [ "C ", a -> Text
forall a. RealFloat a => a -> Text
toText a
c1x, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
c1y, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
c2x, ","
  , a -> Text
forall a. RealFloat a => a -> Text
toText a
c2y, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
x, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
y]

-- | Cubic Bezier curve (relative)
cR :: RealFloat a =>  a -> a -> a -> a -> a -> a -> Text
cR :: a -> a -> a -> a -> a -> a -> Text
cR dc1x :: a
dc1x dc1y :: a
dc1y dc2x :: a
dc2x dc2y :: a
dc2y dx :: a
dx dy :: a
dy = [Text] -> Text
T.concat
  [ "c ", a -> Text
forall a. RealFloat a => a -> Text
toText a
dc1x, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
dc1y, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
dc2x
  , ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
dc2y, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
dx, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
dy]

-- | Smooth Cubic Bezier curve (absolute)
sA :: RealFloat a =>  a -> a -> a -> a -> Text
sA :: a -> a -> a -> a -> Text
sA c2x :: a
c2x c2y :: a
c2y x :: a
x y :: a
y = [Text] -> Text
T.concat
  ["S ", a -> Text
forall a. RealFloat a => a -> Text
toText a
c2x, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
c2y, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
x, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
y, " "]

-- | Smooth Cubic Bezier curve (relative)
sR :: RealFloat a =>  a -> a -> a -> a -> Text
sR :: a -> a -> a -> a -> Text
sR dc2x :: a
dc2x dc2y :: a
dc2y dx :: a
dx dy :: a
dy = [Text] -> Text
T.concat
  ["s ", a -> Text
forall a. RealFloat a => a -> Text
toText a
dc2x, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
dc2y, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
dx, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
dy, " "]

-- | Quadratic Bezier curve (absolute)
qA :: RealFloat a =>  a -> a -> a -> a -> Text
qA :: a -> a -> a -> a -> Text
qA cx :: a
cx cy :: a
cy x :: a
x y :: a
y = [Text] -> Text
T.concat
  ["Q ", a -> Text
forall a. RealFloat a => a -> Text
toText a
cx, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
cy, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
x, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
y, " "]

-- | Quadratic Bezier curve (relative)
qR :: RealFloat a =>  a -> a -> a -> a -> Text
qR :: a -> a -> a -> a -> Text
qR dcx :: a
dcx dcy :: a
dcy dx :: a
dx dy :: a
dy = [Text] -> Text
T.concat
  ["q ", a -> Text
forall a. RealFloat a => a -> Text
toText a
dcx, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
dcy, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
dx, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
dy, " " ]

-- | Smooth Quadratic Bezier curve (absolute)
tA  :: RealFloat a =>  a -> a -> Text
tA :: a -> a -> Text
tA x :: a
x y :: a
y = [Text] -> Text
T.concat ["T ", " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
x, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
y, " "]

-- | Smooth Quadratic Bezier curve (relative)
tR :: RealFloat a =>  a -> a -> Text
tR :: a -> a -> Text
tR x :: a
x y :: a
y = [Text] -> Text
T.concat [ "t ", a -> Text
forall a. RealFloat a => a -> Text
toText a
x, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
y, " "]

-- | Arc (absolute)
aA :: RealFloat a =>  a -> a -> a -> a -> a -> a -> a -> Text
aA :: a -> a -> a -> a -> a -> a -> a -> Text
aA rx :: a
rx ry :: a
ry xrot :: a
xrot largeFlag :: a
largeFlag sweepFlag :: a
sweepFlag x :: a
x y :: a
y = [Text] -> Text
T.concat
  [ "A ", a -> Text
forall a. RealFloat a => a -> Text
toText a
rx, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
ry, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
xrot, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
largeFlag
  , " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
sweepFlag, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
x, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
y, " "]

-- | Arc (relative)
aR :: RealFloat a =>  a -> a -> a -> a -> a -> a -> a -> Text
aR :: a -> a -> a -> a -> a -> a -> a -> Text
aR rx :: a
rx ry :: a
ry xrot :: a
xrot largeFlag :: a
largeFlag sweepFlag :: a
sweepFlag x :: a
x y :: a
y = [Text] -> Text
T.concat
  [ "a ", a -> Text
forall a. RealFloat a => a -> Text
toText a
rx, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
ry, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
xrot, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
largeFlag
  , " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
sweepFlag, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
x, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
y, " "]

-- | closepath
z :: Text
z :: Text
z = "Z"

-- | SVG Transform components
-- | Specifies a translation by @x@ and @y@
translate :: RealFloat a =>  a -> a -> Text
translate :: a -> a -> Text
translate x :: a
x y :: a
y = [Text] -> Text
T.concat ["translate(", a -> Text
forall a. RealFloat a => a -> Text
toText a
x, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
y, ")"]

-- | Specifies a scale operation by @x@ and @y@
scale :: RealFloat a =>  a -> a -> Text
scale :: a -> a -> Text
scale x :: a
x y :: a
y = [Text] -> Text
T.concat ["scale(", a -> Text
forall a. RealFloat a => a -> Text
toText a
x, " ", a -> Text
forall a. RealFloat a => a -> Text
toText a
y, ")"]

-- | Specifies a rotation by @rotate-angle@ degrees
rotate :: RealFloat a =>  a -> Text
rotate :: a -> Text
rotate angle :: a
angle = [Text] -> Text
T.concat ["rotate(", a -> Text
forall a. RealFloat a => a -> Text
toText a
angle, ")"]

-- | Specifies a rotation by @rotate-angle@ degrees about the given time @rx,ry@
rotateAround :: RealFloat a =>  a -> a -> a -> Text
rotateAround :: a -> a -> a -> Text
rotateAround angle :: a
angle rx :: a
rx ry :: a
ry = [Text] -> Text
T.concat
  ["rotate(", a -> Text
forall a. RealFloat a => a -> Text
toText a
angle, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
rx, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
ry, ")"]

-- | Skew tansformation along x-axis
skewX :: RealFloat a =>  a -> Text
skewX :: a -> Text
skewX angle :: a
angle = [Text] -> Text
T.concat ["skewX(", a -> Text
forall a. RealFloat a => a -> Text
toText a
angle, ")"]

-- | Skew tansformation along y-axis
skewY :: RealFloat a =>  a -> Text
skewY :: a -> Text
skewY angle :: a
angle = [Text] -> Text
T.concat ["skewY(", a -> Text
forall a. RealFloat a => a -> Text
toText a
angle, ")"]

-- | Specifies a transform in the form of a transformation matrix
matrix :: RealFloat a =>  a -> a -> a -> a -> a -> a -> Text
matrix :: a -> a -> a -> a -> a -> a -> Text
matrix a :: a
a b :: a
b c :: a
c d :: a
d e :: a
e f :: a
f =  [Text] -> Text
T.concat
  [ "matrix(", a -> Text
forall a. RealFloat a => a -> Text
toText a
a, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
b, ",",  a -> Text
forall a. RealFloat a => a -> Text
toText a
c
  , ",",  a -> Text
forall a. RealFloat a => a -> Text
toText a
d, ",", a -> Text
forall a. RealFloat a => a -> Text
toText a
e, ",",  a -> Text
forall a. RealFloat a => a -> Text
toText a
f, ")"]