curves-1.1.0: Graphics/Curves/Style.hs
{-# LANGUAGE MultiWayIf #-}
module Graphics.Curves.Style
( CurveAttribute(..)
, Style
, lineStyle, fillStyle, brushStyle
, gradient, dashedOpen, dashedClosed, dashed
) where
import Graphics.Curves.Math
import Graphics.Curves.Image
import Graphics.Curves.Colour
import Graphics.Curves.Curve
import Graphics.Curves.Attribute
import Debug.Trace
-- | A style is a list of attribute assignments.
type Style = [Assignment Image]
-- | Setting the line width, blur and colour.
lineStyle :: Scalar -> Scalar -> Colour -> Style
lineStyle w b c = [LineWidth := w, LineBlur := b, LineColour := c]
-- | Setting the fill blur and colour.
fillStyle :: Scalar -> Colour -> Style
fillStyle b c = [FillColour := c, FillBlur := b]
-- | Dynamic line width style that tapers off at the end points. First argument
-- is maximum width and the second the length of the tapering off part.
brushStyle :: Scalar -> Scalar -> Style
brushStyle w d =
[VarLineWidth := \x r _ ->
let total = x/r in
if | r == 0 -> 0
| x < d -> w * f (2 * x / d - 1)
| x > total - d -> w * f (2 * (total - x) / d - 1)
| otherwise -> w
]
where
f t = (1 + t + sin (pi * t) / pi) / 2
modDouble a b = a - b * fromIntegral (floor (a / b))
-- | Fade from the first to the second colour and then back. The third argument
-- in the distance in pixels it takes to reach the second colour.
gradient :: Colour -> Colour -> Scalar -> Style
gradient c1 c2 a =
[VarLineColour := \d _ _ ->
case modDouble d (2 * a) of
x | x <= a -> blend (setAlpha (x / a) c2) c1
| otherwise -> blend (setAlpha ((2 * a - x) / a) c2) c1
]
-- | A dashed line style. The first argument is the approximate length (in
-- pixels) of the dashes and the second argument of the gaps. The lengths are
-- adjusted to make the curve always end in a dash.
dashedOpen :: Scalar -> Scalar -> Style
dashedOpen a b =
dashed a b ++
[VarLineColour :~ \old d r p ->
if | r == 0 -> old d r p
| otherwise ->
let total = d/r
n = round (total / (a + b))
k = total / (fromIntegral n * (a + b) + a)
in old (d / k) r p
]
-- | A dashed line style. The first argument is the approximate length (in
-- pixels) of the dashes and the second argument of the gaps. The lengths are
-- adjusted to make the curve always end in a gap so closed curves have a
-- smooth transition where the end of the curve meets the start.
dashedClosed :: Scalar -> Scalar -> Style
dashedClosed a b =
dashed a b ++
[VarLineColour :~ \old d r p ->
if | r == 0 -> old d r p
| otherwise ->
let total = d/r
n = round (total / (a + b))
k = total / (fromIntegral n * (a + b))
in old (d / k) r p
]
-- | A dashed line style. The first argument is the lengths (in pixels) of the
-- dashes and the second argument of the gaps.
dashed :: Scalar -> Scalar -> Style
dashed a b =
[VarLineColour :~ \old d r p ->
case modDouble d (a + b) of
x | x <= a -> old d r p
| otherwise -> transparent
]