Switch back to stylish-haskell and enumerate imports.

This commit is contained in:
David Himmelstrup 2020-10-10 18:17:01 +08:00
commit e7bce27d12
39 changed files with 405 additions and 449 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Before After
Before After

BIN
docs/gifs/doc_svgLogo2.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

14
examples/doc_svgLogo.hs Executable file → Normal file
View file

@ -1,16 +1,10 @@
#!/usr/bin/env stack
-- stack runghc --package reanimate
module Main (main) where
import Codec.Picture.Types
import Reanimate
import Reanimate.Builtin.Documentation
import Reanimate.External
import Reanimate
import Reanimate.Builtin.Documentation
import Reanimate.Builtin.Images
main :: IO ()
main =
reanimate $
docEnv $
staticFrame 1 $
withFillOpacity 1 $ svgLogo "cassandra"
main = reanimate $ docEnv $ animate $ const svgLogo

15
examples/doc_svgLogo2.hs Executable file
View file

@ -0,0 +1,15 @@
#!/usr/bin/env stack
-- stack runghc --package reanimate
module Main (main) where
import Reanimate
import Reanimate.Builtin.Documentation
import Reanimate.External
main :: IO ()
main =
reanimate $
docEnv $
staticFrame 1 $
withFillOpacity 1 $ svgLogo "cassandra"

View file

@ -53,14 +53,13 @@ module Reanimate.Animation
, renderSvg
) where
import Control.Arrow ()
import Data.Fixed (mod')
import Graphics.SvgTree
import Graphics.SvgTree.Printer
import Reanimate.Constants
import Reanimate.Ease
import Reanimate.Svg.Constructors
import Text.XML.Light.Output
import Graphics.SvgTree.Printer (ppDocument)
import Reanimate.Constants (defaultStrokeWidth)
import Reanimate.Ease (Signal, reverseS)
import Reanimate.Svg.Constructors (mkGroup, scaleXY, withStrokeWidth)
import Text.XML.Light.Output (ppElement)
-- | Duration of an animation or effect. Usually measured in seconds.
type Duration = Double

View file

@ -36,17 +36,17 @@ module Reanimate.Blender
, blender'
) where
import Data.Hashable
import Data.Hashable (Hashable (hash))
import Data.Text (Text)
import qualified Data.Text.IO as T
import Graphics.SvgTree (Tree)
import Reanimate.Animation
import Reanimate.Cache
import Reanimate.Constants
import Reanimate.Misc
import Reanimate.Parameters
import Reanimate.Raster
import Reanimate.Svg.Constructors
import Reanimate.Animation (SVG)
import Reanimate.Cache (cacheFile, encodeInt)
import Reanimate.Constants (screenHeight, screenWidth)
import Reanimate.Misc (requireExecutable, runCmd)
import Reanimate.Parameters (pNoExternals)
import Reanimate.Raster (mkImage)
import Reanimate.Svg.Constructors (mkText)
import System.FilePath (replaceExtension, (<.>))
import System.IO.Unsafe (unsafePerformIO)

View file

@ -9,13 +9,15 @@ Portability : POSIX
Convenience module for rendering circle plots.
-}
module Reanimate.Builtin.CirclePlot where
module Reanimate.Builtin.CirclePlot
( circlePlot
) where
import Codec.Picture
import Graphics.SvgTree (Tree)
import Reanimate.Raster
import Reanimate.Svg
import Reanimate.Constants
import Codec.Picture (PixelRGBA8 (..), generateImage)
import Graphics.SvgTree (Tree)
import Reanimate.Constants (screenHeight)
import Reanimate.Raster (embedImage)
import Reanimate.Svg (flipYAxis, scaleToHeight)
-- | Circle plots are scaled to 'screenHeight'.
--

View file

@ -12,11 +12,11 @@ GIFs for a consistent look and feel.
-}
module Reanimate.Builtin.Documentation where
import Reanimate.Animation
import Reanimate.Svg
import Reanimate.Raster
import Reanimate.Constants
import Codec.Picture
import Codec.Picture (PixelRGB8, PixelRGBA8 (..), generateImage)
import Reanimate.Animation (Animation, SVG, mapA, mkAnimation)
import Reanimate.Constants (screenHeight, screenWidth)
import Reanimate.Raster (embedImage)
import Reanimate.Svg
-- | Default environment for API documentation GIFs.
docEnv :: Animation -> Animation

View file

@ -16,21 +16,21 @@ module Reanimate.Builtin.Images
)
where
import Codec.Picture
import qualified Data.ByteString as B
import qualified Data.Text.IO as T
import Graphics.SvgTree (parseSvgFile)
import Paths_reanimate
import Reanimate.Animation
import Reanimate.Svg
import System.IO.Unsafe
import Codec.Picture
import qualified Data.ByteString as B
import qualified Data.Text.IO as T
import Graphics.SvgTree (parseSvgFile)
import Paths_reanimate
import Reanimate.Animation
import Reanimate.Svg
import System.IO.Unsafe
embedImage :: FilePath -> IO SVG
embedImage key = do
svg_file <- getDataFileName key
svg_data <- T.readFile svg_file
case parseSvgFile svg_file svg_data of
Nothing -> error "Malformed svg"
Nothing -> error "Malformed svg"
Just svg -> return $ embedDocument svg
loadJPG :: FilePath -> Image PixelRGBA8
@ -38,7 +38,7 @@ loadJPG key = unsafePerformIO $ do
jpg_file <- getDataFileName key
dat <- B.readFile jpg_file
case decodeJpeg dat of
Left err -> error err
Left err -> error err
Right img -> return $ convertRGBA8 img
{- HLINT ignore svgLogo -}

View file

@ -7,10 +7,10 @@ Portability : POSIX
-}
module Reanimate.Builtin.Slide where
import Reanimate.Transition
import Reanimate.Constants
import Reanimate.Svg
import Reanimate.Effect
import Reanimate.Constants (screenHeight, screenWidth)
import Reanimate.Effect (constE, translateE)
import Reanimate.Svg (translate)
import Reanimate.Transition (Transition, effectT)
-- | <<docs/gifs/doc_slideLeftT.gif>>
slideLeftT :: Transition

View file

@ -21,10 +21,10 @@ module Reanimate.Builtin.TernaryPlot
, fromCartesianCoords
) where
import Codec.Picture
import Codec.Picture (PixelRGBA8 (..), generateImage)
import Graphics.SvgTree (Tree)
import Reanimate.Raster
import Reanimate.Svg
import Reanimate.Raster (embedImage)
import Reanimate.Svg (flipYAxis, scaleToWidth, translate)
-- a+b+c=1
-- | Left-most coordinate.

View file

@ -8,24 +8,24 @@ module Reanimate.Cache
, encodeInt
) where
import Control.Exception
import Control.Exception (evaluate)
import Control.Monad (unless)
import Data.Bits
import Data.Hashable
import Data.IORef
import Data.Bits (Bits (shiftR))
import Data.Hashable (Hashable (hash))
import Data.IORef (IORef, atomicModifyIORef, newIORef, readIORef)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Graphics.SvgTree (Tree, unparse, pattern None)
import Graphics.SvgTree (Tree, pattern None, unparse)
import Reanimate.Animation (renderTree)
import Reanimate.Misc (renameOrCopyFile,getReanimateCacheDirectory)
import System.Directory
import System.FilePath
import System.IO
import System.IO.Temp
import System.IO.Unsafe
import Reanimate.Misc (getReanimateCacheDirectory, renameOrCopyFile)
import System.Directory (doesFileExist)
import System.FilePath ((<.>), (</>))
import System.IO (hClose)
import System.IO.Temp (openTempFile, withSystemTempFile)
import System.IO.Unsafe (unsafePerformIO)
import Text.XML.Light (Content (..), parseXML)
-- Memory cache and disk cache

View file

@ -22,16 +22,16 @@ module Reanimate.ColorComponents
, fromRGB8
) where
import Codec.Picture
import Codec.Picture.Types
import Data.Colour
import Data.Colour.CIE
import Codec.Picture (Pixel (pixelOpacity), PixelRGB8 (..), PixelRGBA8 (..))
import Codec.Picture.Types (TransparentPixel (dropTransparency))
import Data.Colour (Colour)
import Data.Colour.CIE (cieLAB, cieLABView, cieXYZ, cieXYZView)
import Data.Colour.CIE.Illuminant (d65)
import Data.Colour.RGBSpace
import Data.Colour.RGBSpace.HSV
import Data.Colour.SRGB
import Data.Fixed
import Reanimate.Ease
import Data.Colour.RGBSpace (RGB (RGB), uncurryRGB)
import Data.Colour.RGBSpace.HSV (hsv, hsvView)
import Data.Colour.SRGB (sRGB, sRGB24, toSRGB, toSRGBBounded)
import Data.Fixed (mod')
import Reanimate.Ease (fromToS)
-- | Constructor and destructor for color's three components.
data ColorComponents = ColorComponents

View file

@ -19,15 +19,15 @@ module Reanimate.ColorMap
, greyscale
) where
import Data.Text (Text)
import Data.Vector (Vector)
import qualified Data.Text as T
import qualified Data.Vector as V
import Codec.Picture
import Data.Char
import Data.Bits
import Codec.Picture (Pixel8, PixelRGB8 (..))
import Data.Bits (Bits (shiftL))
import Data.Char (digitToInt)
import Data.Colour.RGBSpace (RGB (RGB))
import qualified Data.Colour.RGBSpace.HSV as HSV
import Data.Colour.RGBSpace
import Data.Text (Text)
import qualified Data.Text as T
import Data.Vector (Vector)
import qualified Data.Vector as V
-- | Given a number t in the range [0,1], returns the corresponding color from
-- the “turbo” color scheme by Anton Mikhailov.

View file

@ -14,7 +14,7 @@ module Reanimate.Constants
, defaultStrokeWidth
) where
import Graphics.SvgTree
import Graphics.SvgTree (Dpi)
-- | Number of units from the left-most point to the right-most point on the screen.
screenWidth :: Fractional a => a

View file

@ -12,15 +12,16 @@ module Reanimate.Debug
)
where
import Data.IORef
import System.IO.Unsafe
import Control.Exception
import Reanimate.Animation
import Reanimate.Svg
import Reanimate.LaTeX
import Reanimate.Constants
import Text.Printf
import qualified Data.Text as T
import Control.Exception (evaluate)
import Data.IORef (IORef, atomicModifyIORef', modifyIORef', newIORef)
import qualified Data.Text as T
import Reanimate.Animation (Animation, SVG, duration, parA, pause, seqA, staticFrame)
import Reanimate.Constants (defaultStrokeWidth)
import Reanimate.LaTeX (latex)
import Reanimate.Svg (center, mkGroup, translate, withFillColor, withStrokeColor,
withStrokeWidth)
import System.IO.Unsafe (unsafePerformIO)
import Text.Printf (printf)
{-# NOINLINE traceBuffer #-}
traceBuffer :: IORef [Animation]

View file

@ -9,12 +9,10 @@ module Reanimate.Driver.CLI
, showRaster
) where
import Data.Char
import Data.Monoid
import Data.Char (toLower)
import Options.Applicative
import Prelude
import Reanimate.Render (FPS, Format (..), Height, Raster (..),
Width)
import Reanimate.Render (FPS, Format (..), Height, Raster (..), Width)
newtype Options = Options
{ optsCommand :: Command
@ -29,10 +27,10 @@ data Command
| Test
| Check
| View
{ viewVerbose :: Bool
, viewGHCPath :: Maybe FilePath
, viewGHCOpts :: [String]
, viewOrigin :: Maybe FilePath
{ viewVerbose :: Bool
, viewGHCPath :: Maybe FilePath
, viewGHCOpts :: [String]
, viewOrigin :: Maybe FilePath
}
| Render
{ renderTarget :: Maybe String
@ -54,12 +52,12 @@ data Preset = Youtube | ExampleGif | Quick | MediumQ | HighQ | LowFPS
readRaster :: String -> Maybe Raster
readRaster raster =
case map toLower raster of
"none" -> Just RasterNone
"auto" -> Just RasterAuto
"inkscape" -> Just RasterInkscape
"rsvg" -> Just RasterRSvg
"imagemagick" -> Just RasterMagick
_ -> Nothing
"none" -> Just RasterNone
"auto" -> Just RasterAuto
"inkscape" -> Just RasterInkscape
"rsvg" -> Just RasterRSvg
"imagemagick" -> Just RasterMagick
_ -> Nothing
showRaster :: Raster -> String
showRaster RasterNone = "none"

View file

@ -8,17 +8,17 @@ module Reanimate.Driver.Check
) where
import Control.Exception (SomeException, handle)
import Control.Monad
import Data.Maybe
import Data.Version
import Reanimate.Misc (runCmd_)
import Control.Monad (forM_)
import Data.Maybe (fromMaybe, listToMaybe)
import Data.Version (Version (Version), parseVersion, showVersion)
import Reanimate.Driver.Magick (magickCmd)
import Reanimate.Misc (runCmd_)
import System.Console.ANSI.Codes
import System.Directory (findExecutable)
import System.IO
import System.IO.Temp
import Text.ParserCombinators.ReadP
import Text.Printf
import System.IO (hClose, hPutStr)
import System.IO.Temp (withSystemTempDirectory, withTempFile)
import Text.ParserCombinators.ReadP (readP_to_S)
import Text.Printf (printf)
--------------------------------------------------------------------------
-- Check environment

View file

@ -13,26 +13,27 @@ module Reanimate.External
)
where
import Codec.Picture (PixelRGB8 (..))
import Control.Monad (unless)
import Crypto.Hash.SHA256 (hash)
import Data.Aeson (decodeFileStrict)
import qualified Data.ByteString as B (readFile)
import Data.ByteString.Base64 (encode)
import qualified Data.ByteString.Char8 as B8 (unpack)
import Data.Char (isSpace, toLower)
import Data.List (sort)
import Data.Map (Map)
import qualified Data.Map as M
import Numeric (readHex)
import Reanimate.Animation (SVG)
import Reanimate.Constants (screenHeight, screenWidth)
import Reanimate.Misc (getReanimateCacheDirectory, withTempFile)
import Reanimate.Raster (mkImage)
import System.Directory (doesDirectoryExist, doesFileExist, findExecutable, getDirectoryContents)
import System.FilePath (splitExtension, (<.>), (</>))
import System.IO.Unsafe (unsafePerformIO)
import System.Process (callProcess)
import Codec.Picture (PixelRGB8 (..))
import Control.Monad (unless)
import Crypto.Hash.SHA256 (hash)
import Data.Aeson (decodeFileStrict)
import qualified Data.ByteString as B (readFile)
import Data.ByteString.Base64 (encode)
import qualified Data.ByteString.Char8 as B8 (unpack)
import Data.Char (isSpace, toLower)
import Data.List (sort)
import Data.Map (Map)
import qualified Data.Map as M
import Numeric (readHex)
import Reanimate.Animation (SVG)
import Reanimate.Constants (screenHeight, screenWidth)
import Reanimate.Misc (getReanimateCacheDirectory, withTempFile)
import Reanimate.Raster (mkImage)
import System.Directory (doesDirectoryExist, doesFileExist, findExecutable,
getDirectoryContents)
import System.FilePath (splitExtension, (<.>), (</>))
import System.IO.Unsafe (unsafePerformIO)
import System.Process (callProcess)
-- | Resource address
type URL = String
@ -83,8 +84,8 @@ downloadFile url action = do
mbCurl <- findExecutable "curl"
mbWget <- findExecutable "wget"
case (mbCurl, mbWget) of
(Just curl, _) -> downloadFileCurl curl url action
(_, Just wget) -> downloadFileWget wget url action
(Just curl, _) -> downloadFileCurl curl url action
(_, Just wget) -> downloadFileWget wget url action
(Nothing, Nothing) -> error "curl/wget required to download files"
downloadFileCurl :: FilePath -> URL -> (FilePath -> IO a) -> IO a
@ -151,7 +152,7 @@ simpleIcon = mkImage screenWidth screenHeight . simpleIconPath
simpleIconColor :: String -> PixelRGB8
simpleIconColor key =
case M.lookup key simpleIconColors of
Nothing -> error $ "Key not found in simple-icons dataset: " ++ show key
Nothing -> error $ "Key not found in simple-icons dataset: " ++ show key
Just pixel -> pixel
-- | Complete list of all Simple Icons.
@ -168,7 +169,7 @@ simpleIconColors = unsafePerformIO $ do
]
case parsed of
Nothing -> error "Invalid json in simpleIcons"
Just v -> pure v
Just v -> pure v
where
fromTitle :: String -> String
fromTitle = replaceChars . map toLower
@ -194,7 +195,7 @@ simpleIconColors = unsafePerformIO $ do
where
p offset = case readHex (take 2 $ drop offset hex) of
[(num, "")] -> num
_ -> error $ "Invalid hex: " ++ (take 2 $ drop offset hex)
_ -> error $ "Invalid hex: " ++ (take 2 $ drop offset hex)
{-# NOINLINE simpleIcons #-}
simpleIcons :: [String]
@ -227,7 +228,7 @@ svgLogoPath key = unsafePerformIO $ do
-- `svgLogo` "cassandra"
-- @
--
-- <<docs/gifs/doc_svgLogo.gif>>
-- <<docs/gifs/doc_svgLogo2.gif>>
svgLogo :: String -> SVG
svgLogo = mkImage screenWidth screenHeight . svgLogoPath
@ -238,4 +239,4 @@ svgLogos = unsafePerformIO $ do
files <- getDirectoryContents svgLogosFolder
return $
sort
[key | file <- files, let (key, ext) = splitExtension file, ext == ".svg"]
[key | file <- files, let (key, ext) = splitExtension file, ext == ".svg"]

View file

@ -1,9 +1,8 @@
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ScopedTypeVariables #-}
-- |
-- Copyright : Written by David Himmelstrup
-- License : Unlicense
@ -35,37 +34,25 @@ module Reanimate.LaTeX
)
where
import Control.Lens
import qualified Data.ByteString as B
import Data.Hashable
import Data.Monoid
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import qualified Data.Text.Encoding as T
import GHC.Generics (Generic)
import Graphics.SvgTree
( Tree,
clipPathRef,
clipRule,
mapTree,
parseSvgFile,
strokeColor,
pattern ClipPathTree,
pattern None,
)
import Reanimate.Animation (SVG)
import Reanimate.Cache
import Reanimate.External
import Reanimate.Misc
import Reanimate.Parameters
import Reanimate.Svg
import System.FilePath
( replaceExtension,
takeFileName,
(</>),
)
import System.IO.Unsafe (unsafePerformIO)
import Control.Lens ((&), (.~))
import qualified Data.ByteString as B
import Data.Hashable (Hashable)
import Data.Monoid (Last (Last))
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Text.IO as T
import GHC.Generics (Generic)
import Graphics.SvgTree (Tree, clipPathRef, clipRule, mapTree, parseSvgFile,
pattern ClipPathTree, pattern None, strokeColor)
import Reanimate.Animation (SVG)
import Reanimate.Cache (cacheDiskSvg, cacheMem)
import Reanimate.External (zipArchive)
import Reanimate.Misc (requireExecutable, runCmd, withTempDir, withTempFile)
import Reanimate.Parameters (pNoExternals)
import Reanimate.Svg
import System.FilePath (replaceExtension, takeFileName, (</>))
import System.IO.Unsafe (unsafePerformIO)
-- | TeX backends. They have different features and capabilities.
data TexEngine = LaTeX | XeLaTeX | LuaLaTeX
@ -73,8 +60,8 @@ data TexEngine = LaTeX | XeLaTeX | LuaLaTeX
-- | TeX configurations can load packages and set up environments for tex scripts.
data TexConfig = TexConfig
{ texConfigEngine :: TexEngine,
texConfigHeaders :: [T.Text],
{ texConfigEngine :: TexEngine,
texConfigHeaders :: [T.Text],
texConfigPostScript :: [T.Text]
}
deriving (Generic, Hashable, Read, Show, Eq, Ord)
@ -86,8 +73,8 @@ latexCfg (TexConfig engine headers postscript) =
where
gen =
case engine of
LaTeX -> someTexWithHeaders engine "latex" "dvi" []
XeLaTeX -> someTexWithHeaders engine "xelatex" "xdv" ["-no-pdf"]
LaTeX -> someTexWithHeaders engine "latex" "dvi" []
XeLaTeX -> someTexWithHeaders engine "xelatex" "xdv" ["-no-pdf"]
LuaLaTeX -> someTexWithHeaders engine "lualatex" "pdf" []
-- | Invoke latex and import the result as an SVG object. SVG objects are
@ -184,13 +171,13 @@ postprocess =
enginePostprocess :: TexEngine -> Tree -> Tree
enginePostprocess LuaLaTeX svg = translate 0 (svgHeight svg) svg
enginePostprocess _ svg = svg
enginePostprocess _ svg = svg
removeClipPaths :: SVG -> SVG
removeClipPaths = mapTree worker
where
worker ClipPathTree {} = None
worker t = t & clipRule .~ Last Nothing & clipPathRef .~ Last Nothing
worker t = t & clipRule .~ Last Nothing & clipPathRef .~ Last Nothing
-- executable, arguments, header, tex
latexToSVG :: TexEngine -> String -> String -> [String] -> Text -> IO Tree

View file

@ -23,13 +23,13 @@ module Reanimate.Memo
, memo
) where
import Data.Dynamic
import Data.IORef
import qualified Data.Map as Map
import Data.Maybe
import Data.Typeable
import System.IO.Unsafe
import System.Mem.StableName
import Data.Dynamic (Dynamic, fromDynamic, toDyn)
import Data.IORef (IORef, atomicModifyIORef', newIORef)
import qualified Data.Map as Map
import Data.Maybe (fromMaybe)
import Data.Typeable (Typeable, cast, typeOf)
import System.IO.Unsafe (unsafePerformIO)
import System.Mem.StableName (StableName, eqStableName, hashStableName, makeStableName)
data DynamicName = forall a. DynamicName !(StableName a) | forall a. (Eq a, Ord a, Typeable a) => DynamicKey a
instance Eq DynamicName where

View file

@ -10,46 +10,25 @@ module Reanimate.Misc
)
where
import Control.Concurrent
import Control.Exception (catch, evaluate, finally, throw)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Foreign.C.Error
import GHC.IO.Exception
import System.Directory
( XdgDirectory (XdgCache),
copyFile,
createDirectoryIfMissing,
findExecutable,
getXdgDirectory,
removeFile,
renameFile,
)
import System.FilePath ((<.>), (</>))
import System.IO
( hClose,
hGetContents,
hIsEOF,
hPutStr,
stderr,
)
import System.IO.Temp
( withSystemTempDirectory,
withSystemTempFile,
)
import System.Process
( readProcessWithExitCode,
runInteractiveProcess,
showCommandForUser,
terminateProcess,
waitForProcess,
)
import Control.Concurrent (forkIO)
import Control.Exception (catch, evaluate, finally, throw)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Foreign.C.Error (Errno (Errno), eXDEV)
import GHC.IO.Exception (ExitCode (ExitFailure, ExitSuccess), IOException (ioe_errno))
import System.Directory (XdgDirectory (XdgCache), copyFile, createDirectoryIfMissing,
findExecutable, getXdgDirectory, removeFile, renameFile)
import System.FilePath ((<.>), (</>))
import System.IO (hClose, hGetContents, hIsEOF, hPutStr, stderr)
import System.IO.Temp (withSystemTempDirectory, withSystemTempFile)
import System.Process (readProcessWithExitCode, runInteractiveProcess,
showCommandForUser, terminateProcess, waitForProcess)
requireExecutable :: String -> IO FilePath
requireExecutable exec = do
mbPath <- findExecutable exec
case mbPath of
Nothing -> error $ "Couldn't find executable: " ++ exec
Nothing -> error $ "Couldn't find executable: " ++ exec
Just path -> return path
runCmd :: FilePath -> [String] -> IO ()
@ -96,7 +75,7 @@ runCmdLazy exec args handler = do
_ <- evaluate (length errOutput)
ret <- waitForProcess pid
case ret of
ExitSuccess -> return (Left "")
ExitSuccess -> return (Left "")
ExitFailure {} -> return (Left errOutput)
else {-ExitFailure errMsg -> do
return $ Left $

View file

@ -21,8 +21,8 @@ module Reanimate.Parameters
, setRootDirectory
) where
import System.IO.Unsafe
import Data.IORef
import Data.IORef (IORef, newIORef, readIORef, writeIORef)
import System.IO.Unsafe (unsafePerformIO)
-- | Width of animation in pixels.
type Width = Int

View file

@ -48,7 +48,7 @@ import qualified Data.Geometry.Point as Geo
import qualified Data.Geometry.Polygon as Geo
import Data.List (nub, partition, sortOn)
import qualified Data.PlaneGraph as Geo
import Data.Proxy
import Data.Proxy (Proxy (Proxy))
import qualified Data.Vector as V
import Geom2D.CubicBezier.Linear (ClosedPath (..),
CubicBezier (..),

View file

@ -14,17 +14,17 @@ module Reanimate.Povray
, povrayExtreme'
) where
import Data.Hashable
import Data.Hashable (Hashable (hash))
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Graphics.SvgTree (Tree)
import Reanimate.Cache
import Reanimate.Constants
import Reanimate.Misc
import Reanimate.Parameters
import Reanimate.Raster
import Reanimate.Svg.Constructors
import Reanimate.Cache (cacheFile, encodeInt)
import Reanimate.Constants (screenHeight, screenWidth)
import Reanimate.Misc (requireExecutable, runCmd)
import Reanimate.Parameters (pNoExternals)
import Reanimate.Raster (mkImage)
import Reanimate.Svg.Constructors (mkText)
import System.FilePath (replaceExtension, (<.>))
import System.IO.Unsafe (unsafePerformIO)

View file

@ -26,36 +26,35 @@ module Reanimate.Raster
)
where
import Codec.Picture
import Control.Lens ( (&)
, (.~)
)
import Control.Monad
import qualified Data.ByteString as B
import qualified Data.ByteString.Base64.Lazy as Base64
import qualified Data.ByteString.Lazy.Char8 as LBS
import Data.Hashable
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Graphics.SvgTree ( Number(..)
, defaultSvg
, parseSvgFile
)
import qualified Graphics.SvgTree as Svg
import Reanimate.Animation
import Reanimate.Cache
import Reanimate.Driver.Magick
import Reanimate.Misc
import Reanimate.Render
import Reanimate.Parameters
import Reanimate.Constants
import Reanimate.Svg.Constructors
import Reanimate.Svg.Unuse
import System.Directory
import System.FilePath
import System.IO
import System.IO.Temp
import System.IO.Unsafe
import Codec.Picture (DynamicImage, Image (imageHeight, imageWidth),
PngSavable (encodePng), decodePng, dynamicMap,
encodeDynamicPng, writePng)
import Control.Lens ((&), (.~))
import Control.Monad (unless)
import qualified Data.ByteString as B
import qualified Data.ByteString.Base64.Lazy as Base64
import qualified Data.ByteString.Lazy.Char8 as LBS
import Data.Hashable (Hashable (hash))
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Graphics.SvgTree (Number (..), defaultSvg, parseSvgFile)
import qualified Graphics.SvgTree as Svg
import Reanimate.Animation (SVG, renderSvg)
import Reanimate.Cache (cacheFile, encodeInt)
import Reanimate.Constants (screenHeight, screenWidth)
import Reanimate.Driver.Magick (magickCmd)
import Reanimate.Misc (getReanimateCacheDirectory, renameOrCopyFile,
requireExecutable, runCmd)
import Reanimate.Parameters (Height, Raster (RasterNone), Width, pHeight,
pNoExternals, pRaster, pRootDirectory, pWidth)
import Reanimate.Render (applyRaster, requireRaster)
import Reanimate.Svg.Constructors (flipYAxis, mkText, scaleXY)
import Reanimate.Svg.Unuse (replaceUses, unbox, unboxFit)
import System.Directory (copyFile, doesFileExist, removeFile)
import System.FilePath (replaceExtension, takeExtension, (<.>), (</>))
import System.IO (hClose)
import System.IO.Temp (withSystemTempFile)
import System.IO.Unsafe (unsafePerformIO)
-- | Load an external image. Width and height must be specified,
-- ignoring the image's aspect ratio. The center of the image is

View file

@ -26,22 +26,22 @@ module Reanimate.Render
import Control.Concurrent
import Control.Exception
import Control.Monad (forM_, forever, unless, void, when)
import Data.Either
import Data.Function
import Data.Either (isRight)
import Data.Function (fix)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Data.Time
import Graphics.SvgTree (Number (..))
import Numeric
import Reanimate.Animation
import Reanimate.Driver.Check
import Reanimate.Driver.Magick
import Numeric (showFFloat)
import Reanimate.Animation (Animation, duration, frameAt, renderSvg)
import Reanimate.Driver.Check (hasInkscape, hasMagick, hasRSvg)
import Reanimate.Driver.Magick (magickCmd)
import Reanimate.Misc
import Reanimate.Parameters
import System.Console.ANSI.Codes
import System.Exit
import System.FileLock (withTryFileLock, SharedExclusive(..), unlockFile)
import System.Directory
import System.Console.ANSI.Codes (clearFromCursorToLineEndCode)
import System.Directory (doesFileExist, removeFile)
import System.Exit (ExitCode (ExitFailure), exitWith)
import System.FileLock (SharedExclusive (..), unlockFile, withTryFileLock)
import System.FilePath (replaceExtension, (<.>), (</>))
import System.IO
import Text.Printf (printf)

View file

@ -2,11 +2,11 @@
module Reanimate.Scene.Core where
import Control.Monad.Fix (MonadFix (..))
import Control.Monad.ST
import Data.List
import Reanimate.Animation
import Reanimate.Svg.Constructors
import Control.Monad.Fix (MonadFix (..))
import Control.Monad.ST (ST, runST)
import Data.List (sortOn)
import Reanimate.Animation (Animation, Duration, SVG, Time, mkAnimation)
import Reanimate.Svg.Constructors (mkGroup)
-- | The ZIndex property specifies the stack order of sprites and animations. Elements
-- with a higher ZIndex will be drawn on top of elements with a lower index.

View file

@ -1,32 +1,26 @@
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE RecordWildCards #-}
module Reanimate.Scene.Object where
import Linear.V2
import Linear.Vector
import Control.Lens
import Control.Monad (forM_, void)
import Control.Monad.State (State, execState)
import Data.Monoid ( Last(getLast) )
import Graphics.SvgTree
( Number (..),
Tree,
strokeWidth,
toUserUnit,
pattern None,
)
import Reanimate.Animation
import Reanimate.Constants (defaultDPI, defaultStrokeWidth)
import Reanimate.Ease (Signal, curveS, fromToS)
import Reanimate.Effect ( applyE, fadeLineOutE, overEnding )
import Reanimate.Math.Balloon ( balloon )
import Reanimate.Morph.Common (morph)
import Reanimate.Morph.Linear (linear)
import Reanimate.Svg
import Control.Lens
import Control.Monad (forM_, void)
import Control.Monad.State (State, execState)
import Data.Monoid (Last (getLast))
import Graphics.SvgTree (Number (..), Tree, pattern None, strokeWidth, toUserUnit)
import Linear.V2 (R1 (_x), R2 (_y), V2 (..))
import Linear.Vector (Additive (lerp), (^*))
import Reanimate.Animation
import Reanimate.Constants (defaultDPI, defaultStrokeWidth)
import Reanimate.Ease (Signal, curveS, fromToS)
import Reanimate.Effect (applyE, fadeLineOutE, overEnding)
import Reanimate.Math.Balloon (balloon)
import Reanimate.Morph.Common (morph)
import Reanimate.Morph.Linear (linear)
import Reanimate.Svg
import Reanimate.Scene.Core
import Reanimate.Scene.Sprite
import Reanimate.Scene.Var
import Reanimate.Scene.Core (Scene, fork, scene, wait)
import Reanimate.Scene.Sprite (Sprite, newSprite, newSpriteA', play, spriteModify, unVar)
import Reanimate.Scene.Var (Var, modifyVar, newVar, readVar, tweenVar)
-------------------------------------------------------
-- Objects
@ -43,23 +37,23 @@ instance Renderable Tree where
-- change over time.
data Object s a = Object
{ objectSprite :: Sprite s,
objectData :: Var s (ObjectData a)
objectData :: Var s (ObjectData a)
}
-- | Container for object properties.
data ObjectData a = ObjectData
{ _oTranslate :: V2 Double,
_oValueRef :: a,
_oSVG :: SVG,
_oContext :: SVG -> SVG,
{ _oTranslate :: V2 Double,
_oValueRef :: a,
_oSVG :: SVG,
_oContext :: SVG -> SVG,
-- | Top, right, bottom, left
_oMargin :: (Double, Double, Double, Double),
_oBB :: (Double, Double, Double, Double),
_oOpacity :: Double,
_oShown :: Bool,
_oZIndex :: Int,
_oEasing :: Signal,
_oScale :: Double,
_oMargin :: (Double, Double, Double, Double),
_oBB :: (Double, Double, Double, Double),
_oOpacity :: Double,
_oShown :: Bool,
_oZIndex :: Int,
_oEasing :: Signal,
_oScale :: Double,
_oScaleOrigin :: V2 Double
}
@ -508,7 +502,7 @@ oDraw = oStagger $ \svg -> scene $
let sWidth =
case toUserUnit defaultDPI <$> getLast (attr ^. strokeWidth) of
Just (Num d) -> max defaultStrokeWidth d
_ -> defaultStrokeWidth
_ -> defaultStrokeWidth
-- wait 1
play $
mapA ctx $

View file

@ -1,39 +1,21 @@
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RankNTypes #-}
module Reanimate.Scene.Sprite where
import Control.Monad (void)
import Control.Monad.ST (ST)
import Data.Bifunctor (Bifunctor (first))
import Data.STRef (STRef, modifySTRef, newSTRef, readSTRef)
import Graphics.SvgTree
( pattern None,
)
import Reanimate.Animation
( Animation,
Duration,
SVG,
Sync (SyncStretch),
Time,
dropA,
duration,
getAnimationFrame,
)
import Reanimate.Effect (Effect, delayE)
import Reanimate.Scene.Core
( Scene (M),
ZIndex,
addGen,
fork,
liftST,
queryNow,
scene,
wait,
)
import Reanimate.Scene.Var (unpackVar, Var (..), newVar, readVar)
import Reanimate.Transition (Transition, overlapT)
import Control.Monad (void)
import Control.Monad.ST (ST)
import Data.Bifunctor (Bifunctor (first))
import Data.STRef (STRef, modifySTRef, newSTRef, readSTRef)
import Graphics.SvgTree (pattern None)
import Reanimate.Animation (Animation, Duration, SVG, Sync (SyncStretch), Time, dropA,
duration, getAnimationFrame)
import Reanimate.Effect (Effect, delayE)
import Reanimate.Scene.Core (Scene (M), ZIndex, addGen, fork, liftST, queryNow, scene,
wait)
import Reanimate.Scene.Var (Var (..), newVar, readVar, unpackVar)
import Reanimate.Transition (Transition, overlapT)
-- | Create and render a variable. The rendering will be born at the current timestamp
-- and will persist until the end of the scene.

View file

@ -1,13 +1,13 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RecordWildCards #-}
module Reanimate.Scene.Var where
import Control.Monad.ST (ST)
import qualified Data.Map as M
import Data.STRef
import Reanimate.Animation (Duration, Time)
import Reanimate.Scene.Core (Scene, liftST, queryNow, wait)
import Control.Monad.ST (ST)
import qualified Data.Map as M
import Data.STRef (STRef, modifySTRef, newSTRef, readSTRef)
import Reanimate.Animation (Duration, Time)
import Reanimate.Scene.Core (Scene, liftST, queryNow, wait)
-- | Time dependent variable.
newtype Var s a = Var (STRef s (VarData a))
@ -18,9 +18,9 @@ newtype Var s a = Var (STRef s (VarData a))
-- it shouldn't be Nothing again.
-- 3. isNothing (evarLastTime var) => M.null (evarTimeline var)
data VarData a = VarData
{ evarDefault :: a,
evarTimeline :: Timeline a,
evarLastTime :: Maybe Time,
{ evarDefault :: a,
evarTimeline :: Timeline a,
evarLastTime :: Maybe Time,
evarLastValue :: a
}
@ -103,7 +103,7 @@ modifyVarData now fn var =
let before = keepBefore now var
after = keepFrom now var
timeline = flip M.map (evarTimeline after) $ \case
StaticValue s -> StaticValue $ fn s
StaticValue s -> StaticValue $ fn s
TweenValue dur f -> TweenValue dur $ \a t -> fn (f a t)
in after {evarTimeline = timeline, evarLastValue = fn $ evarLastValue after} `elseVar` before
@ -165,5 +165,5 @@ keepBefore nd var@VarData {..} =
_ -> timeline'
lastTime = case lastModifier of
Just (t, TweenValue dur _) -> Just $ min nd (t + dur)
_ -> min nd <$> evarLastTime
_ -> min nd <$> evarLastTime
in VarData evarDefault timeline'' lastTime (maybe evarDefault (readVarData var) lastTime)

View file

@ -14,17 +14,17 @@ module Reanimate.Svg
, module Reanimate.Svg.Unuse
) where
import Control.Lens ((%~), (&), (.~), (^.), (?~))
import Control.Lens ((%~), (&), (.~), (?~), (^.))
import Control.Monad.State
import Graphics.SvgTree
import Linear.V2 hiding (angle)
import Reanimate.Constants
import Reanimate.Animation (SVG)
import Linear.V2 (V2 (V2))
import Reanimate.Animation (SVG)
import Reanimate.Constants (defaultDPI)
import Reanimate.Svg.BoundingBox (boundingBox, svgHeight, svgWidth)
import Reanimate.Svg.Constructors
import Reanimate.Svg.LineCommand
import Reanimate.Svg.BoundingBox
import Reanimate.Svg.Unuse
import qualified Reanimate.Transform as Transform
import Reanimate.Svg.Unuse (embedDocument, replaceUses, unbox, unboxFit)
import qualified Reanimate.Transform as Transform
-- | Remove transformations (such as translations, rotations, scaling)
-- and apply them directly to the SVG nodes. Note, this function
@ -343,9 +343,9 @@ mapSvgLines fn = mapSvgPaths (lineToPath . fn . toLineCommands)
mapSvgPoints :: (RPoint -> RPoint) -> SVG -> SVG
mapSvgPoints fn = mapSvgLines (map worker)
where
worker (LineMove p) = LineMove (fn p)
worker (LineMove p) = LineMove (fn p)
worker (LineBezier ps) = LineBezier (map fn ps)
worker (LineEnd p) = LineEnd (fn p)
worker (LineEnd p) = LineEnd (fn p)
-- | Convert coordinate system from degrees to radians.
svgPointsToRadians :: SVG -> SVG

View file

@ -11,18 +11,18 @@ module Reanimate.Svg.BoundingBox
, svgWidth
) where
import Control.Arrow ((***))
import Control.Lens ((^.))
import Data.List
import Data.Maybe (mapMaybe)
import qualified Data.Vector.Unboxed as V
import Control.Arrow ((***))
import Control.Lens ((^.))
import Data.List (foldl')
import Data.Maybe (mapMaybe)
import qualified Data.Vector.Unboxed as V
import qualified Geom2D.CubicBezier.Linear as Bezier
import Graphics.SvgTree
import Linear.V2 hiding (angle)
import Linear.Vector
import Reanimate.Constants
import Reanimate.Svg.LineCommand
import qualified Reanimate.Transform as Transform
import Linear.V2 (V2 (V2))
import Linear.Vector (Additive (zero))
import Reanimate.Constants (defaultDPI)
import Reanimate.Svg.LineCommand (LineCommand (..), toLineCommands)
import qualified Reanimate.Transform as Transform
-- | Return bounding box of SVG tree.
-- The four numbers returned are (minimal X-coordinate, minimal Y-coordinate, width, height)
@ -114,7 +114,7 @@ svgBoundingPoints t = map (Transform.transformPoint m) $
rnum = circ ^. circleRadius
in case mapMaybe unpackNumber [xnum, ynum, rnum] of
[x, y, r] -> [ V2 (x + r * cos angle) (y + r * sin angle) | angle <- [0, pi/10 .. 2 * pi]]
_ -> []
_ -> []
ellipseBoundingPoints e =
let (xnum,ynum) = e ^. ellipseCenter

View file

@ -63,11 +63,11 @@ import Data.Attoparsec.Text (parseOnly)
import qualified Data.Map as Map
import qualified Data.Text as T
import Graphics.SvgTree
import Graphics.SvgTree.NamedColors
import Graphics.SvgTree.PathParser
import Linear.V2 hiding (angle)
import Reanimate.Constants
import Reanimate.Svg.BoundingBox
import Graphics.SvgTree.NamedColors (svgNamedColors)
import Graphics.SvgTree.PathParser (pathParser)
import Linear.V2 (V2 (V2))
import Reanimate.Constants (screenHeight, screenWidth)
import Reanimate.Svg.BoundingBox (boundingBox)
-- | Apply list of transformations to given image.
withTransformations :: [Transformation] -> Tree -> Tree

View file

@ -15,17 +15,20 @@ module Reanimate.Svg.LineCommand
)
where
import Control.Lens ((%~), (&), (.~))
import Control.Monad.Fix
import Control.Monad.State
import Data.Functor
import Data.Maybe
import qualified Data.Vector.Unboxed as V
import Control.Lens ((%~), (&), (.~))
import Control.Monad.Fix (MonadFix (mfix))
import Control.Monad.State (MonadState (get, put), State, evalState, forM, gets,
modify)
import Data.Functor (($>))
import Data.Maybe (mapMaybe)
import qualified Data.Vector.Unboxed as V
import qualified Geom2D.CubicBezier.Linear as Bezier
import Graphics.SvgTree
import Linear.Metric
import Linear.V2 hiding (angle)
import Linear.Vector
import Graphics.SvgTree (Coord, Origin (OriginAbsolute, OriginRelative),
PathCommand (..), RPoint, Tree, mapTree, pathDefinition,
pattern PathTree)
import Linear.Metric (Metric (distance))
import Linear.V2 (R1 (_x), R2 (_y), V2 (V2))
import Linear.Vector (Additive (lerp, zero))
-- | Line command monad used for keeping track of the current location.
type CmdM a = State RPoint a
@ -42,13 +45,13 @@ data LineCommand
lineToPath :: [LineCommand] -> [PathCommand]
lineToPath = map worker
where
worker (LineMove p) = MoveTo OriginAbsolute [p]
worker (LineMove p) = MoveTo OriginAbsolute [p]
-- worker (LineDraw p) = LineTo OriginAbsolute [p]
worker (LineBezier [a, b, c]) = CurveTo OriginAbsolute [(a, b, c)]
worker (LineBezier [a, b]) = QuadraticBezier OriginAbsolute [(a, b)]
worker (LineBezier [a]) = LineTo OriginAbsolute [a]
worker LineBezier {} = error "Reanimate.Svg.lineToPath: invalid bezier curve"
worker LineEnd {} = EndPath
worker (LineBezier [a, b]) = QuadraticBezier OriginAbsolute [(a, b)]
worker (LineBezier [a]) = LineTo OriginAbsolute [a]
worker LineBezier {} = error "Reanimate.Svg.lineToPath: invalid bezier curve"
worker LineEnd {} = EndPath
-- | Using @n@ control points, approximate the path of the curves.
lineToPoints :: Int -> [LineCommand] -> [RPoint]
@ -56,9 +59,9 @@ lineToPoints nPoints cmds =
mapMaybe lineEnd lineSegments
where
lineSegments = [partialLine (fromIntegral n / fromIntegral nPoints) cmds | n <- [0 .. nPoints -1]]
lineEnd [] = Nothing
lineEnd [] = Nothing
lineEnd [LineBezier pts] = Just (last pts)
lineEnd (_ : xs) = lineEnd xs
lineEnd (_ : xs) = lineEnd xs
partialLine :: Double -> [LineCommand] -> [LineCommand]
partialLine alpha cmds = evalState (worker 0 cmds) zero
@ -78,9 +81,9 @@ adjustLineLength :: Double -> RPoint -> LineCommand -> LineCommand
adjustLineLength alpha from cmd =
case cmd of
LineBezier points -> LineBezier $ drop 1 $ partialBezierPoints (from : points) 0 alpha
LineMove p -> LineMove p
LineMove p -> LineMove p
-- LineDraw t -> LineDraw (lerp alpha t from)
LineEnd p -> LineBezier [lerp alpha p from]
LineEnd p -> LineBezier [lerp alpha p from]
-- | Estimated length of all segments in a line.
lineLength :: LineCommand -> CmdM Double
@ -101,10 +104,10 @@ lineLength cmd =
rpointsToBezier :: [RPoint] -> Bezier.CubicBezier Double
rpointsToBezier lst =
case lst of
[a, b] -> Bezier.CubicBezier a a b b
[a, b, c] -> Bezier.quadToCubic (Bezier.QuadBezier a b c)
[a, b] -> Bezier.CubicBezier a a b b
[a, b, c] -> Bezier.quadToCubic (Bezier.QuadBezier a b c)
[a, b, c, d] -> Bezier.CubicBezier a b c d
_ -> error $ "rpointsToBezier: Invalid list of points: " ++ show lst
_ -> error $ "rpointsToBezier: Invalid list of points: " ++ show lst
-- | Convert from path commands to line commands.
toLineCommands :: [PathCommand] -> [LineCommand]
@ -116,12 +119,12 @@ toLineCommands ps = evalState (worker zero Nothing ps) zero
let startPos' =
case lcmds of
[LineMove pos] -> pos
_ -> startPos
_ -> startPos
(lcmds ++) <$> worker startPos' (cmdToControlPoint $ last lcmds) cmds
cmdToControlPoint :: LineCommand -> Maybe RPoint
cmdToControlPoint (LineBezier points) = Just (last (init points))
cmdToControlPoint _ = Nothing
cmdToControlPoint _ = Nothing
mkStraightLine :: RPoint -> LineCommand
mkStraightLine p = LineBezier [p]
@ -180,7 +183,7 @@ toLineCommand startPos mbPrevControlPt cmd =
adjustPosition OriginRelative p = modify (+ p)
adjustPosition OriginAbsolute p = put p
makeAbsolute OriginAbsolute _from p = p
makeAbsolute OriginRelative from p = from + p
makeAbsolute OriginRelative from p = from + p
calculateVectorAngle :: Double -> Double -> Double -> Double -> Double
calculateVectorAngle ux uy vx vy

View file

@ -14,18 +14,19 @@ module Reanimate.Svg.Unuse
import Control.Lens ((%~), (&), (.~), (?~), (^.))
import qualified Data.Map as Map
import Data.Maybe
import Data.Maybe (fromMaybe)
import Graphics.SvgTree
import Reanimate.Constants
import Reanimate.Svg.Constructors
import Reanimate.Constants (defaultDPI, screenHeight, screenWidth)
import Reanimate.Svg.Constructors (flipYAxis, mkGroup, scaleXY, translate,
withFillOpacity, withStrokeWidth)
-- | Replace all @<use>@ nodes with their definition.
replaceUses :: Document -> Document
replaceUses doc = doc & documentElements %~ map (mapTree replace)
where
replaceDefinition PathTree{} = None
replaceDefinition PathTree{} = None
replaceDefinition SymbolTree{} = None
replaceDefinition t = t
replaceDefinition t = t
replace t@DefinitionTree{} = mapTree replaceDefinition t
replace (UseTree _ Just{}) = error "replaceUses: subtree in use?"

View file

@ -1,4 +1,4 @@
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE BangPatterns #-}
{-|
2D transformation matrices capable of translating, scaling,
rotating, and skewing.
@ -11,12 +11,12 @@ module Reanimate.Transform
) where
-- XXX: Use Linear.Matrix instead of Data.Matrix to drop the 'matrix' dependency.
import Data.List
import Data.Matrix (Matrix)
import qualified Data.Matrix as M
import Data.Maybe
import Graphics.SvgTree
import Linear.V2
import Data.List (foldl')
import Data.Matrix (Matrix)
import qualified Data.Matrix as M
import Data.Maybe (fromMaybe)
import Graphics.SvgTree (Coord, RPoint, Transformation (..))
import Linear.V2 (V2 (V2))
-- | Identity matrix.
--

View file

@ -15,9 +15,10 @@ module Reanimate.Transition
, fadeT
) where
import Reanimate.Animation
import Reanimate.Ease
import Reanimate.Effect
import Reanimate.Animation (Animation, dropA, duration, lastA, parA, pause, seqA, signalA,
takeA)
import Reanimate.Ease (Signal)
import Reanimate.Effect (Effect, applyE, fadeInE, fadeOutE)
-- | A transition transforms one animation into another.
type Transition = Animation -> Animation -> Animation
@ -66,7 +67,7 @@ effectT eA eB a b = applyE eA a `parA` applyE eB b
--
-- <<docs/gifs/doc_chainT.gif>>
chainT :: Transition -> [Animation] -> Animation
chainT _ [] = pause 0
chainT _ [] = pause 0
chainT t (x:xs) = foldl t x xs
-- | Fade out left-hand-side animation while fading in right-hand-side animation.

View file

@ -1,6 +1,6 @@
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE RecordWildCards #-}
{-|
Reanimate can automatically synchronize animations to your voice if you have
a transcript and an audio recording. This works with the help of Gentle
@ -20,27 +20,27 @@ module Reanimate.Voice
)
where
import Control.Monad (forM_)
import Data.Aeson
import Data.Char
import System.IO.Unsafe ( unsafePerformIO )
import System.Directory
import System.FilePath
import System.Process
import System.Exit
import Control.Monad
import Data.List
import Data.Maybe
import qualified Data.Map as Map
import Data.Map ( Map )
import Data.Text ( Text )
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Reanimate.Misc
import Reanimate.LaTeX
import Reanimate.Scene
import Reanimate.Animation
import Reanimate.Svg
import Reanimate.Constants
import Data.Char (isAlphaNum, isSpace)
import Data.List (sortOn)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Maybe (listToMaybe)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Reanimate.Animation (SVG, staticFrame)
import Reanimate.Constants (defaultStrokeWidth, screenHeight, screenWidth)
import Reanimate.LaTeX (latex, latexChunks)
import Reanimate.Misc (withTempFile)
import Reanimate.Scene (Scene, play, waitUntil)
import Reanimate.Svg (mkGroup, scale, translate, withStrokeColor, withStrokeWidth)
import System.Directory (doesFileExist)
import System.Exit (ExitCode (ExitFailure, ExitSuccess))
import System.FilePath (replaceExtension)
import System.IO.Unsafe (unsafePerformIO)
import System.Process (rawSystem, showCommandForUser)
-- | Aligned transcript. Contains the transcript text as well as
-- timing data for each word.