{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
module Diagrams.Core.Compile
(
RNode(..)
, RTree
, toRTree
, renderDia
, renderDiaT
, toDTree
, fromDTree
)
where
import qualified Data.List.NonEmpty as NEL
import Data.Maybe (fromMaybe)
import Data.Monoid.Coproduct
import Data.Monoid.MList
import Data.Monoid.WithSemigroup (Monoid')
import Data.Semigroup
import Data.Tree
import Data.Tree.DUAL
import Data.Typeable
import Diagrams.Core.Envelope (OrderedField, diameter)
import Diagrams.Core.Style
import Diagrams.Core.Transform
import Diagrams.Core.Types
import Linear.Metric hiding (qd)
#if __GLASGOW_HASKELL__ >= 707
#define Typeable1 Typeable
#endif
emptyDTree :: Tree (DNode b v n a)
emptyDTree = Node DEmpty []
uncurry3 :: (a -> b -> c -> r) -> (a, b, c) -> r
uncurry3 f (x, y, z) = f x y z
toDTree :: (HasLinearMap v, Floating n, Typeable n)
=> n -> n -> QDiagram b v n m -> Maybe (DTree b v n Annotation)
toDTree g n (QD qd)
= foldDUAL
(\d -> withQDiaLeaf
(\p -> Node (DPrim p) [])
(Node DDelay . (:[]) . fromMaybe emptyDTree . toDTree g n . ($ (d, g, n)) . uncurry3)
)
emptyDTree
(\ts -> case NEL.toList ts of
[t] -> t
ts' -> Node DEmpty ts'
)
(\d t -> case get d of
Option Nothing -> t
Option (Just d') ->
let (tr,sty) = untangle d'
in Node (DStyle sty) [Node (DTransform tr) [t]]
)
(\a t -> Node (DAnnot a) [t])
qd
fromDTree :: forall b v n. (Floating n, HasLinearMap v)
=> DTree b v n Annotation -> RTree b v n Annotation
fromDTree = fromDTree' mempty
where
fromDTree' :: Transformation v n -> DTree b v n Annotation -> RTree b v n Annotation
fromDTree' accTr (Node (DPrim p) _)
= Node (RPrim (transform accTr p)) []
fromDTree' accTr (Node (DStyle s) ts)
= Node (RStyle (transform accTr s)) (fmap (fromDTree' accTr) ts)
fromDTree' accTr (Node (DTransform tr) ts)
= Node REmpty (fmap (fromDTree' (accTr <> tr)) ts)
fromDTree' accTr (Node (DAnnot a) ts)
= Node (RAnnot a) (fmap (fromDTree' accTr) ts)
fromDTree' _ (Node DDelay ts)
= Node REmpty (fmap (fromDTree' mempty) ts)
fromDTree' accTr (Node _ ts)
= Node REmpty (fmap (fromDTree' accTr) ts)
toRTree
:: (HasLinearMap v, Metric v, Typeable n,
OrderedField n, Monoid m, Semigroup m)
=> Transformation v n -> QDiagram b v n m -> RTree b v n Annotation
toRTree globalToOutput d
= (fmap . onRStyle) (unmeasureAttrs gToO nToO)
. fromDTree
. fromMaybe (Node DEmpty [])
. toDTree gToO nToO
$ d
where
gToO = avgScale globalToOutput
nToO = product (map (`diameter` d) basis) ** (1 / fromIntegral (dimension d))
onRStyle :: (Style v n -> Style v n) -> RNode b v n a -> RNode b v n a
onRStyle f (RStyle s) = RStyle (f s)
onRStyle _ n = n
renderDiaT
:: (Backend b v n , HasLinearMap v, Metric v,
Typeable n, OrderedField n, Monoid' m)
=> b -> Options b v n -> QDiagram b v n m -> (Transformation v n, Result b v n)
renderDiaT b opts d = (g2o, renderRTree b opts' . toRTree g2o $ d')
where (opts', g2o, d') = adjustDia b opts d
renderDia
:: (Backend b v n , HasLinearMap v, Metric v,
Typeable n, OrderedField n, Monoid' m)
=> b -> Options b v n -> QDiagram b v n m -> Result b v n
renderDia b opts d = snd (renderDiaT b opts d)