{-# LANGUAGE QuasiQuotes #-}
--------------------------------------------------------------------------------
-- |
-- Module      :  Ipe.IpeToIpe
-- Copyright   :  (C) Frank Staals
-- License     :  see the LICENSE file
-- Maintainer  :  Frank Staals
--
-- Use 'ipetoipe' to generate pdf files.
--
-- Note that all functions in this module require that 'ipetoipe' is
-- installed (it is bundled with ipe) and available on the path.

--------------------------------------------------------------------------------
module Ipe.IpeToIpe where

import           HGeometry.Interval
import           Ipe.Types (IpeFile)
import           Ipe.Writer (writeIpeFile, IpeWriteText)
import           System.Directory.OsPath (getTemporaryDirectory, removeFile)
import           System.OsPath
import qualified System.Process.Typed as Process
import           System.Random

--------------------------------------------------------------------------------

-- | Call 'ipetoipe' to produce an image of the specified type.
ipeToIpeWith                          :: Options -- ^ the options to use
                                      -> FileType -- ^ output file type
                                      -> OsPath -- ^ input file path
                                      -> OsPath -- ^ output file path
                                      -> IO ()
ipeToIpeWith :: Options -> FileType -> OsPath -> OsPath -> IO ()
ipeToIpeWith Options
options FileType
fType OsPath
inFp OsPath
outFp =
    do
      inFp'  <- OsPath -> IO String
decodeFS OsPath
inFp
      outFp' <- decodeFS outFp
      Process.withProcessWait (Process.proc "ipetoipe" $ args inFp' outFp') $ \Process () () ()
_iperenderProc ->
        () -> IO ()
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
  where
    args :: String -> String -> [String]
args String
inFp' String
outFp' =
           [ String
"-" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> FileType -> String
forall a. Show a => a -> String
show FileType
fType ] [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<>
           [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ [ String
"-pages", ClosedInterval Int -> String
forall {a}. Show a => ClosedInterval a -> String
pageRange ClosedInterval Int
r ] | PageRange ClosedInterval Int
r <- [Options -> PageRange
pages Options
options] ] [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<>
           [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [ [ String
"-view", Int -> Int -> String
forall {a} {a}. (Show a, Show a) => a -> a -> String
pageView Int
p Int
v ] | Just (Int
p,Int
v) <- [Options -> Maybe (Int, Int)
singleView Options
options] ] [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<>
           [ String
"-export" | Export
Export Export -> Export -> Bool
forall a. Eq a => a -> a -> Bool
== Options -> Export
export Options
options ] [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<>
           [ String
"-runlatex" | Options -> Bool
runLatex Options
options] [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<>
           [ String
"-nozip"    | NoZip
NoZip NoZip -> NoZip -> Bool
forall a. Eq a => a -> a -> Bool
== Options -> NoZip
nozip Options
options ] [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<>
           [ String
inFp'
           , String
outFp'
           ]
    pageRange :: ClosedInterval a -> String
pageRange (ClosedInterval a
l a
u) = a -> String
forall a. Show a => a -> String
show a
l String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"-" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
u
    pageView :: a -> a -> String
pageView a
p a
v = a -> String
forall a. Show a => a -> String
show a
p String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"-" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> a -> String
forall a. Show a => a -> String
show a
v


-- | Call 'ipetoipe' with the default options.
ipeToIpe :: FileType -> OsPath -> OsPath -> IO ()
ipeToIpe :: FileType -> OsPath -> OsPath -> IO ()
ipeToIpe = Options -> FileType -> OsPath -> OsPath -> IO ()
ipeToIpeWith Options
defaultOptions

-- | Write an ipe file to disk as an ipe readable pdf file.
--
-- Note that like all other functions in this module, this requires
-- 'ipetoipe' to be installed (it is bundled with ipe) and available
-- on the path.
--
-- Note this will write soem intermediate file to your system temp dir.
writeIpeFileAsPdf      :: IpeWriteText r => OsPath -> IpeFile r -> IO ()
writeIpeFileAsPdf :: forall r. IpeWriteText r => OsPath -> IpeFile r -> IO ()
writeIpeFileAsPdf OsPath
fp IpeFile r
f = do num    <- forall a (m :: * -> *). (Random a, MonadIO m) => m a
randomIO @Int
                            tempDir <- getTemporaryDirectory
                            num' <- encodeUtf $ show num
                            let xmlFp = OsPath
tempDir OsPath -> OsPath -> OsPath
</> [osp|writeipepdf|] OsPath -> OsPath -> OsPath
forall a. Semigroup a => a -> a -> a
<> OsPath
num' OsPath -> OsPath -> OsPath
<.> [osp|ipe|]
                            writeIpeFile xmlFp f
                            ipeToIpe PDF xmlFp fp
                            removeFile xmlFp


data FileType = PDF | XML
  deriving (FileType -> FileType -> Bool
(FileType -> FileType -> Bool)
-> (FileType -> FileType -> Bool) -> Eq FileType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FileType -> FileType -> Bool
== :: FileType -> FileType -> Bool
$c/= :: FileType -> FileType -> Bool
/= :: FileType -> FileType -> Bool
Eq,Int -> FileType
FileType -> Int
FileType -> [FileType]
FileType -> FileType
FileType -> FileType -> [FileType]
FileType -> FileType -> FileType -> [FileType]
(FileType -> FileType)
-> (FileType -> FileType)
-> (Int -> FileType)
-> (FileType -> Int)
-> (FileType -> [FileType])
-> (FileType -> FileType -> [FileType])
-> (FileType -> FileType -> [FileType])
-> (FileType -> FileType -> FileType -> [FileType])
-> Enum FileType
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: FileType -> FileType
succ :: FileType -> FileType
$cpred :: FileType -> FileType
pred :: FileType -> FileType
$ctoEnum :: Int -> FileType
toEnum :: Int -> FileType
$cfromEnum :: FileType -> Int
fromEnum :: FileType -> Int
$cenumFrom :: FileType -> [FileType]
enumFrom :: FileType -> [FileType]
$cenumFromThen :: FileType -> FileType -> [FileType]
enumFromThen :: FileType -> FileType -> [FileType]
$cenumFromTo :: FileType -> FileType -> [FileType]
enumFromTo :: FileType -> FileType -> [FileType]
$cenumFromThenTo :: FileType -> FileType -> FileType -> [FileType]
enumFromThenTo :: FileType -> FileType -> FileType -> [FileType]
Enum)

instance Show FileType where
  show :: FileType -> String
show = \case
    FileType
PDF -> String
"pdf"
    FileType
XML -> String
"xml"

data Export = RetainIpeInfo | Export
  deriving (Int -> Export -> String -> String
[Export] -> String -> String
Export -> String
(Int -> Export -> String -> String)
-> (Export -> String)
-> ([Export] -> String -> String)
-> Show Export
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> Export -> String -> String
showsPrec :: Int -> Export -> String -> String
$cshow :: Export -> String
show :: Export -> String
$cshowList :: [Export] -> String -> String
showList :: [Export] -> String -> String
Show,Export -> Export -> Bool
(Export -> Export -> Bool)
-> (Export -> Export -> Bool) -> Eq Export
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Export -> Export -> Bool
== :: Export -> Export -> Bool
$c/= :: Export -> Export -> Bool
/= :: Export -> Export -> Bool
Eq,Int -> Export
Export -> Int
Export -> [Export]
Export -> Export
Export -> Export -> [Export]
Export -> Export -> Export -> [Export]
(Export -> Export)
-> (Export -> Export)
-> (Int -> Export)
-> (Export -> Int)
-> (Export -> [Export])
-> (Export -> Export -> [Export])
-> (Export -> Export -> [Export])
-> (Export -> Export -> Export -> [Export])
-> Enum Export
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Export -> Export
succ :: Export -> Export
$cpred :: Export -> Export
pred :: Export -> Export
$ctoEnum :: Int -> Export
toEnum :: Int -> Export
$cfromEnum :: Export -> Int
fromEnum :: Export -> Int
$cenumFrom :: Export -> [Export]
enumFrom :: Export -> [Export]
$cenumFromThen :: Export -> Export -> [Export]
enumFromThen :: Export -> Export -> [Export]
$cenumFromTo :: Export -> Export -> [Export]
enumFromTo :: Export -> Export -> [Export]
$cenumFromThenTo :: Export -> Export -> Export -> [Export]
enumFromThenTo :: Export -> Export -> Export -> [Export]
Enum)

type PageNumber = Int
type ViewNumber = Int

data MarkedView = All | OnlyMarkedViews
  deriving (Int -> MarkedView -> String -> String
[MarkedView] -> String -> String
MarkedView -> String
(Int -> MarkedView -> String -> String)
-> (MarkedView -> String)
-> ([MarkedView] -> String -> String)
-> Show MarkedView
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> MarkedView -> String -> String
showsPrec :: Int -> MarkedView -> String -> String
$cshow :: MarkedView -> String
show :: MarkedView -> String
$cshowList :: [MarkedView] -> String -> String
showList :: [MarkedView] -> String -> String
Show,MarkedView -> MarkedView -> Bool
(MarkedView -> MarkedView -> Bool)
-> (MarkedView -> MarkedView -> Bool) -> Eq MarkedView
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MarkedView -> MarkedView -> Bool
== :: MarkedView -> MarkedView -> Bool
$c/= :: MarkedView -> MarkedView -> Bool
/= :: MarkedView -> MarkedView -> Bool
Eq,Int -> MarkedView
MarkedView -> Int
MarkedView -> [MarkedView]
MarkedView -> MarkedView
MarkedView -> MarkedView -> [MarkedView]
MarkedView -> MarkedView -> MarkedView -> [MarkedView]
(MarkedView -> MarkedView)
-> (MarkedView -> MarkedView)
-> (Int -> MarkedView)
-> (MarkedView -> Int)
-> (MarkedView -> [MarkedView])
-> (MarkedView -> MarkedView -> [MarkedView])
-> (MarkedView -> MarkedView -> [MarkedView])
-> (MarkedView -> MarkedView -> MarkedView -> [MarkedView])
-> Enum MarkedView
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: MarkedView -> MarkedView
succ :: MarkedView -> MarkedView
$cpred :: MarkedView -> MarkedView
pred :: MarkedView -> MarkedView
$ctoEnum :: Int -> MarkedView
toEnum :: Int -> MarkedView
$cfromEnum :: MarkedView -> Int
fromEnum :: MarkedView -> Int
$cenumFrom :: MarkedView -> [MarkedView]
enumFrom :: MarkedView -> [MarkedView]
$cenumFromThen :: MarkedView -> MarkedView -> [MarkedView]
enumFromThen :: MarkedView -> MarkedView -> [MarkedView]
$cenumFromTo :: MarkedView -> MarkedView -> [MarkedView]
enumFromTo :: MarkedView -> MarkedView -> [MarkedView]
$cenumFromThenTo :: MarkedView -> MarkedView -> MarkedView -> [MarkedView]
enumFromThenTo :: MarkedView -> MarkedView -> MarkedView -> [MarkedView]
Enum)

data NoZip = NoZip | Zip
  deriving (Int -> NoZip -> String -> String
[NoZip] -> String -> String
NoZip -> String
(Int -> NoZip -> String -> String)
-> (NoZip -> String) -> ([NoZip] -> String -> String) -> Show NoZip
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> NoZip -> String -> String
showsPrec :: Int -> NoZip -> String -> String
$cshow :: NoZip -> String
show :: NoZip -> String
$cshowList :: [NoZip] -> String -> String
showList :: [NoZip] -> String -> String
Show,NoZip -> NoZip -> Bool
(NoZip -> NoZip -> Bool) -> (NoZip -> NoZip -> Bool) -> Eq NoZip
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: NoZip -> NoZip -> Bool
== :: NoZip -> NoZip -> Bool
$c/= :: NoZip -> NoZip -> Bool
/= :: NoZip -> NoZip -> Bool
Eq,Int -> NoZip
NoZip -> Int
NoZip -> [NoZip]
NoZip -> NoZip
NoZip -> NoZip -> [NoZip]
NoZip -> NoZip -> NoZip -> [NoZip]
(NoZip -> NoZip)
-> (NoZip -> NoZip)
-> (Int -> NoZip)
-> (NoZip -> Int)
-> (NoZip -> [NoZip])
-> (NoZip -> NoZip -> [NoZip])
-> (NoZip -> NoZip -> [NoZip])
-> (NoZip -> NoZip -> NoZip -> [NoZip])
-> Enum NoZip
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: NoZip -> NoZip
succ :: NoZip -> NoZip
$cpred :: NoZip -> NoZip
pred :: NoZip -> NoZip
$ctoEnum :: Int -> NoZip
toEnum :: Int -> NoZip
$cfromEnum :: NoZip -> Int
fromEnum :: NoZip -> Int
$cenumFrom :: NoZip -> [NoZip]
enumFrom :: NoZip -> [NoZip]
$cenumFromThen :: NoZip -> NoZip -> [NoZip]
enumFromThen :: NoZip -> NoZip -> [NoZip]
$cenumFromTo :: NoZip -> NoZip -> [NoZip]
enumFromTo :: NoZip -> NoZip -> [NoZip]
$cenumFromThenTo :: NoZip -> NoZip -> NoZip -> [NoZip]
enumFromThenTo :: NoZip -> NoZip -> NoZip -> [NoZip]
Enum)

data PageRange = EntireFile
               | PageRange (ClosedInterval PageNumber)
               deriving (Int -> PageRange -> String -> String
[PageRange] -> String -> String
PageRange -> String
(Int -> PageRange -> String -> String)
-> (PageRange -> String)
-> ([PageRange] -> String -> String)
-> Show PageRange
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> PageRange -> String -> String
showsPrec :: Int -> PageRange -> String -> String
$cshow :: PageRange -> String
show :: PageRange -> String
$cshowList :: [PageRange] -> String -> String
showList :: [PageRange] -> String -> String
Show,PageRange -> PageRange -> Bool
(PageRange -> PageRange -> Bool)
-> (PageRange -> PageRange -> Bool) -> Eq PageRange
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PageRange -> PageRange -> Bool
== :: PageRange -> PageRange -> Bool
$c/= :: PageRange -> PageRange -> Bool
/= :: PageRange -> PageRange -> Bool
Eq)

data Options = Options { Options -> Export
export     :: Export
                       , Options -> PageRange
pages      :: PageRange
                       , Options -> Maybe (Int, Int)
singleView :: Maybe (PageNumber,ViewNumber)
                       , Options -> MarkedView
markedView :: MarkedView
                       , Options -> Bool
runLatex   :: Bool
                       , Options -> NoZip
nozip      :: NoZip
                       } deriving (Int -> Options -> String -> String
[Options] -> String -> String
Options -> String
(Int -> Options -> String -> String)
-> (Options -> String)
-> ([Options] -> String -> String)
-> Show Options
forall a.
(Int -> a -> String -> String)
-> (a -> String) -> ([a] -> String -> String) -> Show a
$cshowsPrec :: Int -> Options -> String -> String
showsPrec :: Int -> Options -> String -> String
$cshow :: Options -> String
show :: Options -> String
$cshowList :: [Options] -> String -> String
showList :: [Options] -> String -> String
Show,Options -> Options -> Bool
(Options -> Options -> Bool)
-> (Options -> Options -> Bool) -> Eq Options
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Options -> Options -> Bool
== :: Options -> Options -> Bool
$c/= :: Options -> Options -> Bool
/= :: Options -> Options -> Bool
Eq)

defaultOptions :: Options
defaultOptions :: Options
defaultOptions = Export
-> PageRange
-> Maybe (Int, Int)
-> MarkedView
-> Bool
-> NoZip
-> Options
Options Export
RetainIpeInfo
                         PageRange
EntireFile
                         Maybe (Int, Int)
forall a. Maybe a
Nothing -- default : entire file
                         MarkedView
All
                         Bool
False
                         NoZip
Zip