never executed always true always false
    1 {-# LANGUAGE BangPatterns   #-}
    2 {-|
    3   2D transformation matrices capable of translating, scaling,
    4   rotating, and skewing.
    5 -}
    6 module Reanimate.Transform
    7   ( identity
    8   , transformPoint
    9   , mkMatrix
   10   , toTransformation
   11   ) where
   12 
   13 -- XXX: Use Linear.Matrix instead of Data.Matrix to drop the 'matrix' dependency.
   14 import           Data.List
   15 import           Data.Matrix (Matrix)
   16 import qualified Data.Matrix as M
   17 import           Data.Maybe
   18 import           Graphics.SvgTree
   19 import           Linear.V2
   20 
   21 type TMatrix = Matrix Coord
   22 
   23 -- | Identity matrix.
   24 --
   25 --   @transformPoints identity x = x@
   26 identity :: TMatrix
   27 identity = M.identity 3
   28 
   29 fromList :: [Coord] -> TMatrix
   30 fromList [a,b,c,d,e,f] = M.fromList 3 3 [a,c,e,b,d,f,0,0,1]
   31 fromList _             = error "Reanimate.Transform.fromList: bad input"
   32 
   33 -- | Apply a transformation matrix to a 2D point.
   34 transformPoint :: TMatrix -> RPoint -> RPoint
   35 transformPoint m (V2 x y) = V2 (a*x +c*y + e) (b*x + d*y +f)
   36   where
   37     !a = M.unsafeGet 1 1 m
   38     !c = M.unsafeGet 1 2 m
   39     !e = M.unsafeGet 1 3 m
   40     !b = M.unsafeGet 2 1 m
   41     !d = M.unsafeGet 2 2 m
   42     !f = M.unsafeGet 2 3 m
   43     -- (a:c:e:b:d:f:_) = M.toList m
   44 
   45 -- | Convert multiple SVG transformations into a single transformation matrix.
   46 mkMatrix :: Maybe [Transformation] -> TMatrix
   47 mkMatrix Nothing   = identity
   48 mkMatrix (Just ts) = foldl' (*) identity (map transformationMatrix ts)
   49 
   50 -- | Convert an SVG transformation into a transformation matrix.
   51 transformationMatrix :: Transformation -> TMatrix
   52 transformationMatrix transformation =
   53   case transformation of
   54     TransformMatrix a b c d e f -> fromList [a,b,c,d,e,f]
   55     Translate x y               -> translate x y
   56     Scale sx mbSy               -> fromList [sx,0,0,fromMaybe sx mbSy,0,0]
   57     Rotate a Nothing            -> rotate a
   58     Rotate a (Just (x,y))       -> translate x y * rotate a * translate (-x) (-y)
   59     SkewX a                     -> fromList [1,0,tan (a*pi/180),1,0,0]
   60     SkewY a                     -> fromList [1,tan (a*pi/180),0,1,0,0]
   61     TransformUnknown            -> identity
   62   where
   63     translate x y = fromList [1,0,0,1,x,y]
   64     rotate a = fromList [cos r,sin r,-sin r,cos r,0,0]
   65       where r = a * pi / 180
   66 
   67 -- | Convert a transformation matrix back into an SVG transformation.
   68 toTransformation :: TMatrix -> Transformation
   69 toTransformation m = TransformMatrix a b c d e f
   70   where
   71     [a,c,e,b,d,f,_,_,_] = M.toList m